Как решить исключение OutOfMemoryException, которое выдается с помощью анализа основных компонентов

Я работаю над проектом на С#, который использует анализ основных компонентов для применения уменьшения характеристик/уменьшения размеров к матрице [,]. Столбцы матрицы представляют собой функции (слова и биграммы), извлеченные из набора электронных писем. В начале у нас было около 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;
}

Полученные нами компоненты были классифицированы позже с использованием метода Classify линейного дискриминантного анализа из среды Accord.NET. Все работало как надо.

Теперь, когда мы увеличили размер нашего набора данных (1519 электронных писем и 68375 терминов), мы сначала получили некоторые исключения OutOfMemory. Мы смогли решить эту проблему, изменив некоторые части нашего кода, пока не смогли добраться до той части, где мы вычисляем компоненты PCA. Сейчас это занимает около 45 минут, что слишком долго. После проверки веб-сайта Accord.NET на 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. кто-нибудь знает, как решить эту проблему?


person Redesign1991    schedule 08.05.2015    source источник
comment
Перейти на x64 и установить больше памяти?   -  person xanatos    schedule 08.05.2015
comment
Насколько велика исходная матрица входного массива? Исключение также возникает, если вы предоставляете только одну запись?   -  person Romano Zumbé    schedule 08.05.2015
comment
У меня четырехъядерный процессор Q9300 2,50 ГГц, 8 ГБ ОЗУ и 64-битная операционная система, поэтому я не уверен, проблема в этом или нет. При использовании 1-го примера кода вычисление не выдает ошибку, но занимает +- 45 минут. Использование ковариационной матрицы должно быть лучше, но выдает ошибку.   -  person Redesign1991    schedule 08.05.2015
comment
Вы профилировали приложение, чтобы знать, куда уходит память? PCA - это проблема собственных значений. Вам нужно найти алгоритм, который работает для больших полных матриц. Более того, вы можете воспользоваться параллельным алгоритмом, чтобы сократить 45-минутное время ожидания. elpa-lib.fhi-berlin.mpg.de/wiki/ index.php/Main_Page   -  person duffymo    schedule 08.05.2015
comment
Размер - sourceMatrix[529, 34482] (это даже не полный набор данных, который я сейчас передаю, это вдвое больше его размера). Среднее значение равно [34482].   -  person Redesign1991    schedule 08.05.2015
comment
@Redesign1991 Redesign1991 Ваше приложение работает на 64-битной версии? (bool is64 = Environment.Is64BitProcess)   -  person xanatos    schedule 08.05.2015


Ответы (2)


Я думаю, что распараллеливание вашего решателя - лучший выбор.

Возможно, что-то вроде FEAST поможет.

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

Параллельная линейная алгебра для многоядерной системы

person duffymo    schedule 08.05.2015

Проблема в том, что код использует зубчатые матрицы вместо многомерных матриц. Дело в том, что 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;
}
person Cesar    schedule 08.05.2015
comment
Я пытаюсь реализовать класс, который вы предоставили. В настоящее время возникает 1 ошибка: собственные векторы = Matrix.Sort (собственные значения, собственные векторы, новый GeneralComparer (ComparerDirection.Descending, true)); говорит, что аргументы типа не могут быть выведены из использования. Попробуйте указать неявно. Иметь ссылку на пространство имен Accord.Math - person Redesign1991; 08.05.2015
comment
Ой, я забыл включить этот метод. Вот он: gist.github.com/cesarsouza/aeb3c080c502ea5702b5 - person Cesar; 09.05.2015