Numpy.eig и процент дисперсии в PCA - PullRequest
3 голосов
/ 28 января 2011

Продолжаем с того места, где мы уехали ...

Так что я могу использовать linalg.eig или linalg.svd для вычисления PCA.Каждый из них возвращает разные главные компоненты / собственные векторы и собственные значения, когда им подают одни и те же данные (в настоящее время я использую набор данных Iris).

Просмотр здесь или любое другое руководство с PCAПрименительно к набору данных Iris я обнаружу, что собственные значения равны [2.9108 0.9212 0.1474 0.0206].Метод eig дает мне другой набор собственных значений / векторов для работы, с которыми я не возражаю, за исключением того, что эти собственные значения, будучи суммированными, равны количеству измерений (4) и могут использоваться для определения того, сколько каждый компонентвносит вклад в общую дисперсию.

Принимая собственные значения, возвращаемые linalg.eig Я не могу этого сделать.Например, возвращаемые значения [9206.53059607 314.10307292 12.03601935 3.53031167].Доля дисперсии в этом случае будет [0.96542969 0.03293797 0.00126214 0.0003702]. На этой другой странице говорится, что ("доля вариации, объясняемой компонентом, является просто его собственным значением, деленным на сумму собственных значений.")

Поскольку дисперсия, объясняемая каждым измерением, должнабыть постоянным (я думаю), эти пропорции неверны.Итак, если я использую значения, возвращаемые svd(), которые являются значениями, используемыми во всех руководствах, я могу получить правильный процент отклонения от каждого измерения, но мне интересно, почему значения, возвращаемые eig, не могутиспользоваться таким образом.

Я полагаю, что возвращенные результаты все еще являются допустимым способом проецирования переменных, так есть ли способ преобразовать их, чтобы я мог получить правильную пропорцию дисперсии, объясняемую каждой переменной?Другими словами, могу ли я использовать метод eig и при этом иметь дисперсионную долю для каждой переменной?Кроме того, можно ли сделать это отображение только по собственным значениям, чтобы я мог иметь как действительные, так и нормализованные значения?

Извините за длинную запись между прочим.Вот (::) за то, что зашли так далеко.Предполагая, что вы не просто прочитали эту строку.

Ответы [ 4 ]

4 голосов
/ 28 января 2011

Взяв ответ Дуга на ваш предыдущий вопрос и реализовав следующие две функции, я получаю вывод, показанный ниже:

def pca_eig(orig_data):
    data = array(orig_data)
    data = (data - data.mean(axis=0)) / data.std(axis=0)
    C = corrcoef(data, rowvar=0)
    w, v = linalg.eig(C)
    print "Using numpy.linalg.eig"
    print w
    print v

def pca_svd(orig_data):
    data = array(orig_data)
    data = (data - data.mean(axis=0)) / data.std(axis=0)
    C = corrcoef(data, rowvar=0)
    u, s, v = linalg.svd(C)
    print "Using numpy.linalg.svd"
    print u
    print s
    print v

Выход:

Using numpy.linalg.eig
[ 2.91081808  0.92122093  0.14735328  0.02060771]
[[ 0.52237162 -0.37231836 -0.72101681  0.26199559]
 [-0.26335492 -0.92555649  0.24203288 -0.12413481]
 [ 0.58125401 -0.02109478  0.14089226 -0.80115427]
 [ 0.56561105 -0.06541577  0.6338014   0.52354627]]

Using numpy.linalg.svd
[[-0.52237162 -0.37231836  0.72101681  0.26199559]
 [ 0.26335492 -0.92555649 -0.24203288 -0.12413481]
 [-0.58125401 -0.02109478 -0.14089226 -0.80115427]
 [-0.56561105 -0.06541577 -0.6338014   0.52354627]]
[ 2.91081808  0.92122093  0.14735328  0.02060771]
[[-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]]

В обоих случаях я получаю нужные собственные значения.

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

Я бы предложил использовать SVD, разложение по сингулярным значениям, для PCA, потому что
1) оно дает вам непосредственно значения и матрицы, которые вам нужны
2) это надежно.
См. главный компонент-анализ-в-питоне на SO для примера с (неожиданными) данными радужной оболочки.Запуск его дает

read iris.csv: (150, 4)
Center -= A.mean: [ 5.84  3.05  3.76  1.2 ]
Center /= A.std: [ 0.83  0.43  1.76  0.76]

SVD: A (150, 4) -> U (150, 4)  x  d diagonal  x  Vt (4, 4)
d^2: 437 138 22.1 3.09
% variance: [  72.77   95.8    99.48  100.  ]
PC 0 weights: [ 0.52 -0.26  0.58  0.57]
PC 1 weights: [-0.37 -0.93 -0.02 -0.07]

Вы видите, что диагональная матрица d от SVD в квадрате дает долю общей дисперсии от ПК 0, ПК 1 ...

Помогает ли это?

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

Мне известно о трех способах выполнения PCA: полученных из разложения по собственным значениям корреляционной матрицы, ковариационной матрицы или на немасштабированных и нецентрированных данных.Похоже, вы передаете linalg.eig работает с немасштабированными данными.Во всяком случае, это всего лишь предположение.Лучшее место для вашего вопроса - stats.stackexchange.com .Люди на math.stackexchange.com не используют реальные цифры.:)

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

Вы уверены, что данные для обоих случаев одинаковы и имеют правильный порядок измерений (вы не отправляете в повернутый массив?)?Бьюсь об заклад, вы обнаружите, что они оба дают одинаковые результаты, если вы используете их правильно;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...