从 scikit-learn 中的截断 SVD 获取 U、Sigma、V* 矩阵
Get U, Sigma, V* matrix from Truncated SVD in scikit-learn
我正在使用 scikit-learn
包中的截断 SVD。
在SVD的定义中,原始矩阵A近似为乘积A≈UΣV* 其中 U 和 V 具有正交列,并且 Σ 是非负对角线。
我需要得到 U、Σ 和 V* 矩阵。
查看源码here发现调用fit_transform
后V*存储在self.components_
字段.
是否可以得到 U 和 Σ 矩阵?
我的代码:
import sklearn.decomposition as skd
import numpy as np
matrix = np.random.random((20,20))
trsvd = skd.TruncatedSVD(n_components=15)
transformed = trsvd.fit_transform(matrix)
VT = trsvd.components_
可以使用 scipy.sparse.svds (for dense matrices you can use svd).
import numpy as np
from scipy.sparse.linalg import svds
matrix = np.random.random((20, 20))
num_components = 2
u, s, v = svds(matrix, k=num_components)
X = u.dot(np.diag(s)) # output of TruncatedSVD
如果您使用的是非常大的稀疏矩阵(也许您使用的是自然文本),即使 scipy.sparse.svds
也可能会耗尽您计算机的内存。在这种情况下,请考虑 sparsesvd package which uses SVDLIBC, and what gensim
uses under-the-hood.
import numpy as np
from sparsesvd import sparsesvd
X = np.random.random((30, 30))
ut, s, vt = sparsesvd(X.tocsc(), k)
projected = (X * ut.T)/s
通过您提供的 link 查看源代码,TruncatedSVD
基本上是 sklearn.utils.extmath.randomized_svd 的包装器;你可以像这样自己手动调用它:
from sklearn.utils.extmath import randomized_svd
U, Sigma, VT = randomized_svd(X,
n_components=15,
n_iter=5,
random_state=None)
让我们假设 X 是我们希望在其上执行截断 SVD 的输入矩阵。
下面的命令有助于找出 U、Sigma 和 VT:
from sklearn.decomposition import TruncatedSVD
SVD = TruncatedSVD(n_components=r)
U = SVD.fit_transform(X)
Sigma = SVD.explained_variance_ratio_
VT = SVD.components_
#r corresponds to the rank of the matrix
以上条款的理解,请参考http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.TruncatedSVD.html
如注:
svd.transform(X)
和
svd.fit_transform(X)
生成 U * Sigma。
svd.singular_values_
以矢量形式生成 Sigma。
svd.components_
生成 VT。
也许我们可以使用
svd.transform(X).dot(np.linalg.inv(np.diag(svd.singular_values_)))
得到U 因为U * Sigma * Sigma ^ -1 = U * I = U.
从源码中可以看出返回的是X_transformed
也就是U * Sigma
(这里Sigma
是一个vector)
来自 fit_transform
方法。所以我们可以得到
svd = TruncatedSVD(k)
X_transformed = svd.fit_transform(X)
U = X_transformed / svd.singular_values_
Sigma_matrix = np.diag(svd.singular_values_)
VT = svd.components_
备注
截断 SVD 是一个近似值。 X ≈ X' = UΣV*。我们有 X'V = UΣ。但是十五呢?一个有趣的事实是 XV = X'V。这可以通过比较 X 的完整 SVD 形式和 X' 的截断 SVD 形式来证明。注意 XV 就是 transform(X)
,所以我们也可以通过
得到 U
U = svd.transform(X) / svd.singular_values_
我知道这是一个较旧的问题,但正确的版本是-
U = svd.fit_transform(X)
Sigma = svd.singular_values_
VT = svd.components_
但是,要记住的一件事是 U 和 VT 被截断,因此没有其余值就不可能重新创建 X。
如果您的矩阵不大,因为 numpy 通过按顺序对奇异值进行排序来计算 SVD,这可以直接使用 np.linalg.svd
计算,只需从 Σ 中获取前 k 个奇异值,即 U 的前 k 列,以及前 k 行的 Vh。 (如果您的维度之一很大,请使用 full_matrices=False
获得薄 SVD。)
m = np.random.random((5,5))
u, s, vh = np.linalg.svd(m)
u2, s2, vh2 = u[:,:2], s[:2], vh[:2,:]
m2 = u2 @ np.diag(s2) @ vh2 # rank-2 approx
如果您的矩阵很大,那么 sklearn.decomposition.TruncatedSVD
提供的随机算法将更有效地计算截断 SVD。
我正在使用 scikit-learn
包中的截断 SVD。
在SVD的定义中,原始矩阵A近似为乘积A≈UΣV* 其中 U 和 V 具有正交列,并且 Σ 是非负对角线。
我需要得到 U、Σ 和 V* 矩阵。
查看源码here发现调用fit_transform
后V*存储在self.components_
字段.
是否可以得到 U 和 Σ 矩阵?
我的代码:
import sklearn.decomposition as skd
import numpy as np
matrix = np.random.random((20,20))
trsvd = skd.TruncatedSVD(n_components=15)
transformed = trsvd.fit_transform(matrix)
VT = trsvd.components_
可以使用 scipy.sparse.svds (for dense matrices you can use svd).
import numpy as np
from scipy.sparse.linalg import svds
matrix = np.random.random((20, 20))
num_components = 2
u, s, v = svds(matrix, k=num_components)
X = u.dot(np.diag(s)) # output of TruncatedSVD
如果您使用的是非常大的稀疏矩阵(也许您使用的是自然文本),即使 scipy.sparse.svds
也可能会耗尽您计算机的内存。在这种情况下,请考虑 sparsesvd package which uses SVDLIBC, and what gensim
uses under-the-hood.
import numpy as np
from sparsesvd import sparsesvd
X = np.random.random((30, 30))
ut, s, vt = sparsesvd(X.tocsc(), k)
projected = (X * ut.T)/s
通过您提供的 link 查看源代码,TruncatedSVD
基本上是 sklearn.utils.extmath.randomized_svd 的包装器;你可以像这样自己手动调用它:
from sklearn.utils.extmath import randomized_svd
U, Sigma, VT = randomized_svd(X,
n_components=15,
n_iter=5,
random_state=None)
让我们假设 X 是我们希望在其上执行截断 SVD 的输入矩阵。 下面的命令有助于找出 U、Sigma 和 VT:
from sklearn.decomposition import TruncatedSVD
SVD = TruncatedSVD(n_components=r)
U = SVD.fit_transform(X)
Sigma = SVD.explained_variance_ratio_
VT = SVD.components_
#r corresponds to the rank of the matrix
以上条款的理解,请参考http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.TruncatedSVD.html
如注:
svd.transform(X)
和
svd.fit_transform(X)
生成 U * Sigma。
svd.singular_values_
以矢量形式生成 Sigma。
svd.components_
生成 VT。 也许我们可以使用
svd.transform(X).dot(np.linalg.inv(np.diag(svd.singular_values_)))
得到U 因为U * Sigma * Sigma ^ -1 = U * I = U.
从源码中可以看出返回的是X_transformed
也就是U * Sigma
(这里Sigma
是一个vector)
来自 fit_transform
方法。所以我们可以得到
svd = TruncatedSVD(k)
X_transformed = svd.fit_transform(X)
U = X_transformed / svd.singular_values_
Sigma_matrix = np.diag(svd.singular_values_)
VT = svd.components_
备注
截断 SVD 是一个近似值。 X ≈ X' = UΣV*。我们有 X'V = UΣ。但是十五呢?一个有趣的事实是 XV = X'V。这可以通过比较 X 的完整 SVD 形式和 X' 的截断 SVD 形式来证明。注意 XV 就是 transform(X)
,所以我们也可以通过
U
U = svd.transform(X) / svd.singular_values_
我知道这是一个较旧的问题,但正确的版本是-
U = svd.fit_transform(X)
Sigma = svd.singular_values_
VT = svd.components_
但是,要记住的一件事是 U 和 VT 被截断,因此没有其余值就不可能重新创建 X。
如果您的矩阵不大,因为 numpy 通过按顺序对奇异值进行排序来计算 SVD,这可以直接使用 np.linalg.svd
计算,只需从 Σ 中获取前 k 个奇异值,即 U 的前 k 列,以及前 k 行的 Vh。 (如果您的维度之一很大,请使用 full_matrices=False
获得薄 SVD。)
m = np.random.random((5,5))
u, s, vh = np.linalg.svd(m)
u2, s2, vh2 = u[:,:2], s[:2], vh[:2,:]
m2 = u2 @ np.diag(s2) @ vh2 # rank-2 approx
如果您的矩阵很大,那么 sklearn.decomposition.TruncatedSVD
提供的随机算法将更有效地计算截断 SVD。