Как мне написать код scikit-learn PCA `.transform ()` с помощью его `.components`? - PullRequest
0 голосов
/ 17 октября 2018

Как мне написать код метод scikit-learn PCA .transform(), используя его .components?

Я думал, что метод PCA .transform() преобразует 3D точку в 2D Point, просто применяя матрицуM до трехмерной точки P, как показано ниже:

np.dot(M, P)

Чтобы убедиться, что это правильно, я написал следующий код.Но в результате я не смог получить тот же результат, что и метод PCA .transform().Как мне изменить код?Я что-то упустил?

from sklearn.decomposition import PCA
import numpy as np

data3d = np.arange(10*3).reshape(10, 3) ** 2
pca = PCA(n_components=2)
pca.fit(data3d)
pca_transformed2d = pca.transform(data3d)

sample_index = 0
sample3d = data3d[sample_index]

# Manually  transform `sample3d` to 2 dimensions.
w11, w12, w13 = pca.components_[0]
w21, w22, w23 = pca.components_[1]
my_transformed2d = np.zeros(2)
my_transformed2d[0] = w11 * sample3d[0] + w12 * sample3d[1] + w13 * sample3d[2]
my_transformed2d[1] = w21 * sample3d[0] + w22 * sample3d[1] + w23 * sample3d[2]

print("================ Validation ================")
print("pca_transformed2d:", pca_transformed2d[sample_index])
print("my_transformed2d:", my_transformed2d)
if np.all(my_transformed2d == pca_transformed2d[sample_index]):
    print("My transformation is correct!")
else:
    print("My transformation is not correct...")

Вывод:

================ Validation ================
pca_transformed2d: [-492.36557212   12.28386702]
my_transformed2d: [ 3.03163093 -2.67255444]
My transformation is not correct...

1 Ответ

0 голосов
/ 18 октября 2018

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

centered_data = data3d - data3d.mean(axis=0)

Усреднение по оси = 0 (строки) означает, что останется только одна строка с тремя компонентами среднего значения.После центрирования умножьте данные на компоненты PCA;но вместо того, чтобы выписывать умножение матриц вручную, я бы использовал .dot:

my_transformed2d = pca.components_.dot(centered_data[sample_index])

Наконец, проверка.Не используйте == между числами с плавающей точкой;точное равенство редко.Крошечные несоответствия появляются из-за другого порядка операций где-то: например,

0.1 + 0.2 - 0.3 == 0.1 - 0.3 + 0.2

является False.Вот почему у нас есть np.allclose, который говорит, что «они достаточно близки».

if np.allclose(my_transformed2d, pca_transformed2d[sample_index]):
    print("My transformation is correct!")
else:
    print("My transformation is not correct...")
...