Что не так с моим PCA? - PullRequest
       52

Что не так с моим PCA?

9 голосов
/ 26 января 2011

Мой код:

from numpy import *

def pca(orig_data):
    data = array(orig_data)
    data = (data - data.mean(axis=0)) / data.std(axis=0)
    u, s, v = linalg.svd(data)
    print s #should be s**2 instead!
    print v

def load_iris(path):
    lines = []
    with open(path) as input_file:
        lines = input_file.readlines()
    data = []
    for line in lines:
        cur_line = line.rstrip().split(',')
        cur_line = cur_line[:-1]
        cur_line = [float(elem) for elem in cur_line]
        data.append(array(cur_line))
    return array(data)

if __name__ == '__main__':
    data = load_iris('iris.data')
    pca(data)

Набор данных радужной оболочки: http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data

Вывод:

[ 20.89551896  11.75513248   4.7013819    1.75816839]
[[ 0.52237162 -0.26335492  0.58125401  0.56561105]
 [-0.37231836 -0.92555649 -0.02109478 -0.06541577]
 [ 0.72101681 -0.24203288 -0.14089226 -0.6338014 ]
 [ 0.26199559 -0.12413481 -0.80115427  0.52354627]]

Желаемый вывод:
Собственные значения - [2.9108 0.9212 0.1474 0.0206]
Основные компоненты - Same as I got but transposed ну ладно, я думаю

Кроме того, что с выводом функции linalg.eig?Согласно описанию PCA в Википедии, я должен это сделать:

cov_mat = cov(orig_data)
val, vec = linalg.eig(cov_mat)
print val

Но это не совсем соответствует выводам в уроках, которые я нашел в Интернете.Плюс, если у меня есть 4 измерения, я думал, что у меня должно быть 4 собственных значения, а не 150, как дает EIG.Я что-то не так делаю?

edit : я заметил, что значения отличаются на 150, что является количеством элементов в наборе данных.Кроме того, собственные значения должны быть добавлены, чтобы быть равными количеству измерений, в данном случае 4. Что я не понимаю, так это то, почему происходит это различие.Если бы я просто разделил собственные значения на len(data), я мог бы получить желаемый результат, но я не понимаю, почему.В любом случае пропорция собственных значений не изменяется, но они важны для меня, поэтому я хотел бы понять, что происходит.

Ответы [ 4 ]

10 голосов
/ 26 января 2011

Вы разложили неправильную матрицу.

Анализ главных компонентов требует манипулирования собственными векторами / собственными значениями ковариационная матрица , а не сами данные. Ковариационная матрица, созданная из матрицы данных m x n, будет представлять собой матрицу m x m с единицами по главной диагонали.

Вы действительно можете использовать функцию cov , но вам нужны дальнейшие манипуляции с вашими данными. Возможно, немного проще использовать подобную функцию: corrcoef :

import numpy as NP
import numpy.linalg as LA

# a simulated data set with 8 data points, each point having five features
data = NP.random.randint(0, 10, 40).reshape(8, 5)

# usually a good idea to mean center your data first:
data -= NP.mean(data, axis=0)

# calculate the covariance matrix 
C = NP.corrcoef(data, rowvar=0)
# returns an m x m matrix, or here a 5 x 5 matrix)

# now get the eigenvalues/eigenvectors of C:
eval, evec = LA.eig(C)

Чтобы получить собственные векторы / собственные значения, я не разлагал ковариационную матрицу с использованием SVD, хотя, конечно, вы можете. Я предпочитаю рассчитывать их, используя eig в NumPy (или SciPy) Модуль LA - с ним немного легче работать, чем с svd , возвращаемые значения - собственные векторы и собственные значения, и ничего больше. В отличие от этого, как вы знаете, svd не возвращает их напрямую.

Конечно, функция SVD будет разлагать любую матрицу, а не только квадратную (которой ограничена функция eig ); однако при выполнении PCA у вас всегда будет квадратная матрица для разложения, независимо от формы, в которой находятся ваши данные. Это очевидно, потому что матрица разлагаются в PCA это ковариационная матрица , которая по определению всегда квадратная (то есть столбцы являются отдельными точками данных исходной матрицы, аналогично для строк, и каждая ячейка является ковариацией этих двух точек, как свидетельствует на единицу по главной диагонали - данная точка данных имеет идеальную ковариацию с самим собой).

3 голосов
/ 19 марта 2012

Левые единственные значения, возвращаемые SVD (A), являются собственными векторами AA ^ T.

Ковариационная матрица набора данных A: 1 / (N-1) * AA ^ T

Теперь, когда вы делаете PCA, используя SVD, вы должны разделить каждую запись в вашей матрице A на (N-1), чтобы вы получили собственные значения ковариации с правильной шкалой.

Вваш случай, N = 150, и вы не делали это деление, поэтому возникает расхождение.

Это подробно объясняется здесь

2 голосов
/ 26 января 2011

(Можете ли вы задать один вопрос, пожалуйста? Или хотя бы перечислите ваши вопросы отдельно. Ваше сообщение читается как поток сознания, потому что вы не задаете ни одного вопроса.)

  1. Вы, вероятно, неправильно использовали cov, не транспонировав матрицу первой.Если cov_mat равно 4 на 4, то eig даст четыре собственных значения и четыре собственных вектора.

  2. Обратите внимание, что SVD и PCA, хотя и связаны друг с другом, не совсем совпадают.Пусть X - матрица наблюдений размером 4 на 150, где каждый столбец из 4 элементов представляет собой одно наблюдение.Тогда следующие условия эквивалентны:

    a.левые сингулярные векторы X,

    b.главные компоненты X,

    c.собственные векторы XX ^ T.

    Кроме того, собственные значения XX ^ T равны квадрату сингулярных значений X. Чтобы увидеть все это, пусть X имеет SVD X = QSV ^ T, гдеS - диагональная матрица особых значений.Затем рассмотрим собственное разложение D = Q ^ TXX ^ TQ, где D - диагональная матрица собственных значений.Замените X его SVD, и посмотрите, что произойдет.

0 голосов
/ 26 января 2011
...