0

データセット data=[[x,y],...] に期待値最大化アルゴリズム (ガウス混合モデル) を実装しようとしています。mv_norm.pdf(data, mean,cov)関数を使用してクラスターの責任を計算しています。しかし、6〜7回の反復後に共分散(cov行列)の新しい値を計算した後、cov行列は特異になっています。つまり、covの行列式は0(非常に小さい値)であるため、エラーが発生しています

ValueError: 入力行列は半正定値でなければなりません

np.linalg.LinAlgError('singular matrix') を上げる

誰かがこれに対する解決策を提案できますか?

#E-step: Compute cluster responsibilities, given cluster parameters
def calculate_cluster_responsibility(data,centroids,cov_m):
    pdfmain=[[] for i in range(0,len(data))]
    for i in range(0,len(data)):
        sum1=0
        pdfeach=[[] for m in range(0,len(centroids))]
        pdfeach[0]=1/3.*mv_norm.pdf(data[i], mean=centroids[0],cov=[[cov_m[0][0][0],cov_m[0][0][1]],[cov_m[0][1][0],cov_m[0][1][1]]])
        pdfeach[1]=1/3.*mv_norm.pdf(data[i], mean=centroids[1],cov=[[cov_m[1][0][0],cov_m[1][0][1]],[cov_m[1][1][0],cov_m[0][1][1]]])
        pdfeach[2]=1/3.*mv_norm.pdf(data[i], mean=centroids[2],cov=[[cov_m[2][0][0],cov_m[2][0][1]],[cov_m[2][1][0],cov_m[2][1][1]]])
        sum1+=pdfeach[0]+pdfeach[1]+pdfeach[2]
        pdfeach[:] = [x / sum1 for x in pdfeach]
        pdfmain[i]=pdfeach

    global old_pdfmain
    if old_pdfmain==pdfmain:
        return
    old_pdfmain=copy.deepcopy(pdfmain)
    softcounts=[sum(i) for i in zip(*pdfmain)]
    calculate_cluster_weights(data,centroids,pdfmain,soft counts)

最初に、予想されるクラスター数が 3 であるため、各クラスター共分散に [[3,0],[0,3]] を渡しました。

4

1 に答える 1

1

誰かがこれに対する解決策を提案できますか?

問題は、データが入力データよりも厳密に小さい次元の多様体にあることです。つまり、たとえば、データは円の上にありますが、3 次元のデータがあります。結果として、メソッドがデータに適合する 3 次元楕円体 (共分散行列) を推定しようとすると、最適なものは 2 次元楕円 (3 次元は 0) であるため失敗します。

修正方法は?共分散推定量を正則化する必要があります。多くの可能な解決策があり、すべて E ステップではなく M ステップにあります。問題は共分散の計算にあります。

  • smallcov = np.cov(X)のように、正則化用語を追加するようなことをする代わりに、単純な解決策cov = np.cov(X) + eps * np.identity(X.shape[1])eps
  • scikit-learn の LedoitWolf estimator のような、より優れた推定器を使用します。

最初に、予想されるクラスター数が 3 であるため、各クラスター共分散に [[3,0],[0,3]] を渡しました。

これは意味がありません。共分散行列の値はクラスターの量とは関係ありません。多かれ少なかれ妥当なもので初期化できます。

于 2016-10-01T09:53:57.933 に答える