如何解决使用主成分分析引发的 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的主要内容,如果未能解决你的问题,请参考以下文章