如何解决使用主成分分析引发的 OutOfMemoryException

Posted

技术标签:

【中文标题】如何解决使用主成分分析引发的 OutOfMemoryException【英文标题】:How to solve OutOfMemoryException that is thrown using principal component analysis 【发布时间】:2015-07-19 07:19:32 【问题描述】:

我正在使用 C# 开发一个项目,该项目使用主成分分析在 [,] 矩阵上应用特征缩减/维度缩减。矩阵列是从一组电子邮件中提取的特征(单词和二元组)。一开始,我们收到了大约 156 封电子邮件,产生了大约 23000 个术语,并且一切正常,使用以下代码:

public static double[,] GetPCAComponents(double[,] sourceMatrix, int dimensions = 20, AnalysisMethod method = AnalysisMethod.Center) 

    // Create Principal Component Analysis of a given source
    PrincipalComponentAnalysis pca = new PrincipalComponentAnalysis(sourceMatrix, method);

    // Compute the Principal Component Analysis
    pca.Compute();

    // Creates a projection of the information
    double[,] pcaComponents = pca.Transform(sourceMatrix, dimensions);

    // Return PCA Components
    return pcaComponents;

我们收到的组件后来使用来自 Accord.NET 框架的线性判别分析的分类方法进行了分类。一切正常。

现在我们已经增加了输出数据集的大小(1519 封电子邮件和 68375 个术语),我们最初遇到了一些 OutOfMemory 异常。我们能够通过调整代码的某些部分来解决这个问题,直到我们能够到达我们计算 PCA 组件的部分。现在这需要大约 45 分钟,这太长了。在检查了the website of Accord.NET on PCA 之后,我们决定尝试使用最后一个使用协方差矩阵的示例,因为它说:“有些用户想要分析大量数据。在这种情况下,直接在数据上计算 SVD 可能会导致内存占用异常或过多的计算时间”。因此,我们将代码更改为以下内容:

public static double[,] GetPCAComponents(double[,] sourceMatrix, int dimensions = 20, AnalysisMethod method = AnalysisMethod.Center) 
    
        // Compute mean vector
        double[] mean = Accord.Statistics.Tools.Mean(sourceMatrix);

        // Compute Covariance matrix
        double[,] covariance = Accord.Statistics.Tools.Covariance(sourceMatrix, mean);

        // Create analysis using the covariance matrix
        var pca = PrincipalComponentAnalysis.FromCovarianceMatrix(mean, covariance);

        // Compute the Principal Component Analysis
        pca.Compute();

        // Creates a projection of the information
        double[,] pcaComponents = pca.Transform(sourceMatrix, dimensions);

        // Return PCA Components
        return pcaComponents;
    

然而,这会引发 System.OutOfMemoryException。有谁知道如何解决这个问题?

【问题讨论】:

转到 x64 并装载更多内存? 输入数组源矩阵有多大?如果您只提供一个条目,是否也会引发异常? 我有一个四核 CPU Q9300 2.50GHz - 8GB RAM 和 64 位操作系统,所以我不确定这是否是问题所在。使用第一个代码示例计算时不会引发错误,但需要 +- 45 分钟。使用协方差矩阵应该更合适,但会引发错误。 您是否对应用进行了分析以了解内存的去向? PCA 是一个特征值问题。您需要找到一种适用于大型完整矩阵的算法。更好的是,您可以从并行算法中受益,以减少 45 分钟的等待时间。 elpa-lib.fhi-berlin.mpg.de/wiki/index.php/Main_Page 大小是 sourceMatrix[529, 34482] (这甚至不是我现在传递的完整数据集,这是它的两倍大小)。平均值为 [34482]。 【参考方案1】:

问题在于代码使用的是锯齿矩阵而不是多维矩阵。关键是 double[,] 需要分配连续数量的内存,这可能很难找到,具体取决于您需要多少空间。如果使用交错矩阵,内存分配会分散,空间更容易找到。

您可以通过升级到最新版本的框架并改用新的 API 进行统计分析来避免此问题。无需在构造函数中传递源矩阵并调用 .Compute,只需调用 .Learn() 即可:

public static double[][] GetPCAComponents(double[][] sourceMatrix, int dimensions = 20, AnalysisMethod method = AnalysisMethod.Center) 

    // Create Principal Component Analysis of a given source
    PrincipalComponentAnalysis pca = new PrincipalComponentAnalysis(method)
    
        NumberOfOutputs = dimensions // limit the number of dimensions
    ;

    // Compute the Principal Component Analysis
    pca.Learn(sourceMatrix);

    // Creates a projection of the information
    double[][] pcaComponents = pca.Transform(sourceMatrix);

    // Return PCA Components
    return pcaComponents;

【讨论】:

我正在尝试实现您提供的类。当前收到 1 个错误: eigenvectors = Matrix.Sort(eigenvalues, eigenvectors, new GeneralComparer(ComparerDirection.Descending, true));表示无法从用法中推断出类型参数。尝试隐式指定。引用 Accord.Math 命名空间 糟糕,我忘了包含这个方法。这是:gist.github.com/cesarsouza/aeb3c080c502ea5702b5【参考方案2】:

我认为并行化您的求解器是最好的选择。

也许像 FEAST 这样的东西会有所帮助。

http://www.ecs.umass.edu/~polizzi/feast/

Parallel linear algebra for multicore system

【讨论】:

以上是关于如何解决使用主成分分析引发的 OutOfMemoryException的主要内容,如果未能解决你的问题,请参考以下文章

主成分分析不起作用

SPSS主成分分析显示个案不足两个无法分析怎么办

R语言主成分分析(PCA)加“置信椭圆”

R语言-主成分分析

主成分分析法中特征向量有啥意思 ,能用来评估对应变量的权值吗

维数灾难与PCA主成分分析