Анализ Matlab - PCA и реконструкция многомерных данных

У меня есть большой набор данных из многомерных данных (132 измерения).

Я начинаю заниматься разработкой данных, и хочу применить анализ основных компонентов с помощью Matlab. Однако я видел, что в Интернете много функций, но я не понимаю, как их применять.

В принципе, я хочу применить PCA и получить собственные данные и их соответствующие собственные значения из моих данных.

После этого шага я хочу сделать реконструкцию для своих данных на основе выбора полученных собственных векторов.

Я могу сделать это вручную, но мне было интересно, есть ли какие-либо предопределенные функции, которые могут это сделать, потому что они уже должны быть оптимизированы.

Мои исходные данные: size(x) = [33800 132]. Поэтому в основном у меня есть 132 функции (размеры) и 33800 точки данных. И я хочу выполнить PCA в этом наборе данных.

Любая помощь или подсказка сделают.

Ответы

Ответ 1

Вот краткое пошаговое руководство. Сначала мы создаем матрицу ваших скрытых переменных (или "факторов" ). Он имеет 100 наблюдений и есть два независимых фактора.

>> factors = randn(100, 2);

Теперь создайте матрицу нагрузок. Это будет отображать скрытые переменные на ваши наблюдаемые переменные. Скажите, что ваши наблюдаемые переменные имеют четыре функции. Тогда ваша матрица нагрузок должна быть 4 x 2

>> loadings = [
      1   0
      0   1
      1   1
      1  -1   ];

Это говорит о том, что первая наблюдаемая переменная нагрузка на первый коэффициент, вторая нагрузка на второй коэффициент, третья переменная нагрузка на сумму факторов и четвертая переменная нагрузка на разность факторов.

Теперь создайте свои наблюдения:

>> observations = factors * loadings' + 0.1 * randn(100,4);

Я добавил небольшое количество случайных шумов для имитации экспериментальной ошибки. Теперь мы выполняем PCA с помощью функции pca из панели инструментов статистики:

>> [coeff, score, latent, tsquared, explained, mu] = pca(observations);

Переменная score - это массив показателей основного компонента. Они будут ортогональными по построению, которые вы можете проверить -

>> corr(score)
ans =
    1.0000    0.0000    0.0000    0.0000
    0.0000    1.0000    0.0000    0.0000
    0.0000    0.0000    1.0000    0.0000
    0.0000    0.0000    0.0000    1.0000

Комбинация score * coeff' будет воспроизводить центральную версию ваших наблюдений. Среднее значение mu вычитается до выполнения PCA. Чтобы воспроизвести ваши первоначальные наблюдения, вам нужно добавить их обратно,

>> reconstructed = score * coeff' + repmat(mu, 100, 1);
>> sum((observations - reconstructed).^2)
ans =
   1.0e-27 *
    0.0311    0.0104    0.0440    0.3378

Чтобы получить приблизительное количество исходных данных, вы можете начать отбрасывать столбцы из вычисленных основных компонентов. Чтобы понять, какие столбцы нужно отбросить, мы рассмотрим переменную explained

>> explained
explained =
   58.0639
   41.6302
    0.1693
    0.1366

Записи указывают, какой процент от дисперсии объясняется каждым из основных компонентов. Мы можем ясно видеть, что первые два компонента более значительны, чем два вторых (они объясняют более 99% дисперсии между ними). Использование первых двух компонентов для восстановления наблюдений дает приближение ранга-2,

>> approximationRank2 = score(:,1:2) * coeff(:,1:2)' + repmat(mu, 100, 1);

Теперь мы можем попытаться выполнить печать:

>> for k = 1:4
       subplot(2, 2, k);
       hold on;
       grid on
       plot(approximationRank2(:, k), observations(:, k), 'x');
       plot([-4 4], [-4 4]);
       xlim([-4 4]);
       ylim([-4 4]);
       title(sprintf('Variable %d', k));
   end

введите описание изображения здесь

Мы получаем почти идеальное воспроизведение оригинальных наблюдений. Если бы мы хотели получить более грубое приближение, мы могли бы просто использовать первый главный компонент:

>> approximationRank1 = score(:,1) * coeff(:,1)' + repmat(mu, 100, 1);

и нарисуйте его,

>> for k = 1:4
       subplot(2, 2, k);
       hold on;
       grid on
       plot(approximationRank1(:, k), observations(:, k), 'x');
       plot([-4 4], [-4 4]);
       xlim([-4 4]);
       ylim([-4 4]);
       title(sprintf('Variable %d', k));
   end

введите описание изображения здесь

На этот раз реконструкция не так хороша. Это потому, что мы сознательно построили наши данные, чтобы иметь два фактора, и мы только восстанавливаем их из одного из них.

Обратите внимание, что, несмотря на наводящее сходство между тем, как мы построили исходные данные и их воспроизведение,

>> observations  = factors * loadings'  +  0.1 * randn(100,4);
>> reconstructed = score   * coeff'     +  repmat(mu, 100, 1);

нет никакого соответствия между factors и score, или между loadings и coeff. Алгоритм PCA не знает ничего о том, как строятся ваши данные - он просто пытается объяснить как можно большую общую дисперсию с каждым последующим компонентом.


Пользователь @Mari спросил в комментариях, как она могла бы построить ошибку восстановления в зависимости от количества основных компонентов. Используя переменную explained выше, это довольно просто. Я буду генерировать некоторые данные с более интересной структурой факторов, чтобы проиллюстрировать эффект -

>> factors = randn(100, 20);
>> loadings = chol(corr(factors * triu(ones(20))))';
>> observations = factors * loadings' + 0.1 * randn(100, 20);

Теперь все наблюдения накладываются на значительный общий фактор, с другими факторами уменьшения значения. Мы можем получить разложение PCA по-прежнему

>> [coeff, score, latent, tsquared, explained, mu] = pca(observations);

и укажите процент объясненной дисперсии следующим образом:

>> cumexplained = cumsum(explained);
   cumunexplained = 100 - cumexplained;
   plot(1:20, cumunexplained, 'x-');
   grid on;
   xlabel('Number of factors');
   ylabel('Unexplained variance')

введите описание изображения здесь

Ответ 2

У вас есть довольно хороший инструмент для уменьшения размерности по http://homepage.tudelft.nl/19j49/Matlab_Toolbox_for_Dimensionality_Reduction.html Помимо PCA, этот набор инструментов имеет множество других алгоритмов для уменьшения размерности.

Пример выполнения PCA:

Reduced = compute_mapping(Features, 'PCA', NumberOfDimension);