PCA проектирование и реконструкция в Scikit-Learn
Я могу выполнить PCA в scikit по коду ниже:
X_train имеет 279180 строк и 104 столбца.
from sklearn.decomposition import PCA
pca = PCA(n_components=30)
X_train_pca = pca.fit_transform(X_train)
Теперь, когда я хочу проецировать собственные векторы на пространственное пространство, я должен сделать следующее:
""" Projection """
comp = pca.components_ #30x104
com_tr = np.transpose(pca.components_) #104x30
proj = np.dot(X_train,com_tr) #279180x104 * 104x30 = 297180x30
Но я не согласен с этим шагом, потому что Scikit документация говорит:
components_: array, [n_components, n_features]
Основные оси в пространстве объектов, представляющие направления максимальной дисперсии данных.
Мне кажется, что он уже проецируется, но когда я проверил исходный код, он возвращает только собственные векторы.
Каким образом можно спроектировать его?
В конечном счете, я собираюсь рассчитать MSE реконструкции.
""" Reconstruct """
recon = np.dot(proj,comp) #297180x30 * 30x104 = 279180x104
""" MSE Error """
print "MSE = %.6G" %(np.mean((X_train - recon)**2))
Ответы
Ответ 1
Ты можешь сделать
proj = pca.inverse_transform(X_train_pca)
Таким образом, вам не нужно беспокоиться о том, как сделать умножения.
После pca.fit_transform
или pca.transform
вы получаете pca.fit_transform
, что обычно называют "нагрузками" для каждого образца, что означает, какой объем каждого компонента вам нужно описать лучше всего с использованием линейной комбинации components_
(главных осей в пространстве признаков).).
Проекция, на которую вы нацеливаетесь, возвращается в исходное пространство сигнала. Это означает, что вам нужно вернуться в пространство сигналов, используя компоненты и нагрузки.
Таким образом, есть три шага, чтобы устранить неоднозначность здесь. Здесь у вас есть шаг за шагом, что вы можете сделать с помощью объекта PCA и как он фактически рассчитывается:
-
pca.fit
оценивает компоненты (используя SVD на центрированном Xtrain):
from sklearn.decomposition import PCA
import numpy as np
from numpy.testing import assert_array_almost_equal
#Should this variable be X_train instead of Xtrain?
X_train = np.random.randn(100, 50)
pca = PCA(n_components=30)
pca.fit(X_train)
U, S, VT = np.linalg.svd(X_train - X_train.mean(0))
assert_array_almost_equal(VT[:30], pca.components_)
-
pca.transform
рассчитывает нагрузки, как вы описываете
X_train_pca = pca.transform(X_train)
X_train_pca2 = (X_train - pca.mean_).dot(pca.components_.T)
assert_array_almost_equal(X_train_pca, X_train_pca2)
-
pca.inverse_transform
получает проекцию на компоненты в интересующем вас сигнальном пространстве
X_projected = pca.inverse_transform(X_train_pca)
X_projected2 = X_train_pca.dot(pca.components_) + pca.mean_
assert_array_almost_equal(X_projected, X_projected2)
Теперь вы можете оценить потери прогноза
loss = ((X_train - X_projected) ** 2).mean()
Ответ 2
В добавлении к сообщению @eickenberg, вот, как сделать pca реконструкцию изображений цифр:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn import decomposition
n_components = 10
image_shape = (8, 8)
digits = load_digits()
digits = digits.data
n_samples, n_features = digits.shape
estimator = decomposition.PCA(n_components=n_components, svd_solver='randomized', whiten=True)
digits_recons = estimator.inverse_transform(estimator.fit_transform(digits))
# show 5 randomly chosen digits and their PCA reconstructions with 10 dominant eigenvectors
indices = np.random.choice(n_samples, 5, replace=False)
plt.figure(figsize=(5,2))
for i in range(len(indices)):
plt.subplot(1,5,i+1), plt.imshow(np.reshape(digits[indices[i],:], image_shape)), plt.axis('off')
plt.suptitle('Original', size=25)
plt.show()
plt.figure(figsize=(5,2))
for i in range(len(indices)):
plt.subplot(1,5,i+1), plt.imshow(np.reshape(digits_recons[indices[i],:], image_shape)), plt.axis('off')
plt.suptitle('PCA reconstructed'.format(n_components), size=25)
plt.show()
![enter image description here]()
![enter image description here]()