7

マトリックス分解と潜在的セマンティック インデックス作成(オンライン版 © 2009 Cambridge UP)を読んでいます。

マトリックスの次元数を減らす方法を理解しようとしています。13 ページに、 Python の numpyを使用して複製しようとしている例があります。

元の出現行列を「a」と呼び、3 つのSVD (特異値分解) 分解行列を「U」、「S」、および「V」と呼びましょう。

私が抱えている問題は、「S」の小さい特異値をゼロにした後、numpy を使用して「U」、「S」、および「V」を乗算すると、答えが pdf に示されているとおりにならないことです。 . 下の 3 行はすべてゼロではありません。おもしろいことに、「S」と「V」を掛けるだけで正しい答えが得られます。

これは驚くべきことですが、「S」と「V」を乗算することは、実際にマニングとシュッツェの著書「統計的自然言語処理の基礎」であなたがしなければならないと述べていることです。しかし、これはpdfが10ページであなたがしなければならないと言っていることではありません.

それで、ここで何が起こっているのですか?

4

1 に答える 1

4

乗算はSVSVD/LSA で次元削減を実行するために必要なことです。

>>> C = np.array([[1, 0, 1, 0, 0, 0],
...               [0, 1, 0, 0, 0, 0],
...               [1, 1, 0, 0, 0, 0],
...               [1, 0, 0, 1, 1, 0],
...               [0, 0, 0, 1, 0, 1]])
>>> from scipy.linalg import svd
>>> U, s, VT = svd(C, full_matrices=False)
>>> s[2:] = 0
>>> np.dot(np.diag(s), VT)
array([[ 1.61889806,  0.60487661,  0.44034748,  0.96569316,  0.70302032,
         0.26267284],
       [-0.45671719, -0.84256593, -0.29617436,  0.99731918,  0.35057241,
         0.64674677],
       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
         0.        ],
       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
         0.        ],
       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
         0.        ]])

これにより、最後の数行を除くすべてがゼロである行列が得られるため、それらを削除できます。実際には、これはアプリケーションで使用する行列です。

>>> np.dot(np.diag(s[:2]), VT[:2])
array([[ 1.61889806,  0.60487661,  0.44034748,  0.96569316,  0.70302032,
         0.26267284],
       [-0.45671719, -0.84256593, -0.29617436,  0.99731918,  0.35057241,
         0.64674677]])

PDF の 10 ページに記載されているのは、入力の低ランク再構成Cを取得するためのレシピです。ランク!= 次元、および再構成行列のせん断サイズと密度により、LSA での使用は実用的ではありません。その目的は主に数学的なものです。それを使ってできることの 1 つは、 のさまざまな値に対して再構成がどの程度優れているかを確認することですk

>>> U, s, VT = svd(C, full_matrices=False)
>>> C2 = np.dot(U[:, :2], np.dot(np.diag(s[:2]), VT[:2]))
>>> from scipy.spatial.distance import euclidean
>>> euclidean(C2.ravel(), C.ravel())   # Frobenius norm of C2 - C
1.6677932876555255
>>> C3 = np.dot(U[:, :3], np.dot(np.diag(s[:3]), VT[:3]))
>>> euclidean(C3.ravel(), C.ravel())
1.0747879905228703

scikit-learn に対するサニティ チェックTruncatedSVD(完全な開示: 私はそれを書きました):

>>> from sklearn.decomposition import TruncatedSVD
>>> TruncatedSVD(n_components=2).fit_transform(C.T)
array([[ 1.61889806, -0.45671719],
       [ 0.60487661, -0.84256593],
       [ 0.44034748, -0.29617436],
       [ 0.96569316,  0.99731918],
       [ 0.70302032,  0.35057241],
       [ 0.26267284,  0.64674677]])
于 2014-01-04T12:44:34.967 に答える