【问题标题】:Get U, Sigma, V* matrix from Truncated SVD in scikit-learn从 scikit-learn 中的截断 SVD 中获取 U、Sigma、V* 矩阵
【发布时间】:2015-10-09 23:50:40
【问题描述】:

我正在使用来自 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_

【问题讨论】:

    标签: python scipy scikit-learn sparse-matrix svd


    【解决方案1】:

    可以使用scipy.sparse.svds(对于稠密矩阵,您可以使用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 也可能会炸毁您计算机的 RAM。在这种情况下,请考虑使用SVDLIBC 的sparsesvd 包,以及gensim 使用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
    

    【讨论】:

    • 这是真的,但是对于常规的 numpy.linalg.svd 方法,您不能将组件的数量作为参数传递,因此您必须自己提取前 K 个。轻微的不便。
    • X = u.dot(np.diag(s)) 。这不会重新创建 X,因为缺少“v”
    【解决方案2】:

    通过您提供的链接查看源代码,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)
    

    【讨论】:

      【解决方案3】:

      假设 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.fit_transform(X) = U*np.diag(Sigma) != U 和 SVD.explained_variance_ratio_ = np.var(X_transformed, axis=0) / np.var(X, axis=0).sum() != Sigma
      • 这个答案不正确,正如 rth 所提到的那样。
      【解决方案4】:

      就像一个注释:

      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。

      【讨论】:

        【解决方案5】:

        从源码中我们可以看到X_transformed也就是U * Sigma(这里Sigma是一个向量)被返回了 来自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_
        

        【讨论】:

          【解决方案6】:

          我知道这是一个较老的问题,但正确的版本是 -

          U = svd.fit_transform(X)
          Sigma = svd.singular_values_
          VT = svd.components_
          

          但是,要记住的一件事是 U 和 VT 被截断,因此如果没有其余值,则无法重新创建 X。

          【讨论】:

          • 你绝对不是svd.fit_transform(X) 。这是错误的。
          猜你喜欢
          • 2019-02-28
          • 2022-10-20
          • 2014-12-05
          • 2016-05-12
          • 2018-01-18
          • 2018-05-22
          • 2018-09-25
          • 2015-08-04
          • 2020-07-16
          相关资源
          最近更新 更多