Я не понимаю, что делает fit_transform
по сравнению с fit
в контексте Scikit Learn и PCA.
PCA берет некоторые данные и пытается измерить набор собственных векторов, где каждый вектор ортогонален всем остальным и выровнен в направлении максимальной оставшейся дисперсии.
Другими словами, первый найденный собственный вектор ориентирован вдоль оси максимальной дисперсии данных.
Какое преобразование выполняет fit_transform
и какую интерпретацию он имеет в контексте PCA?
Другими словами, какое преобразование происходит на шаге transform
?
Разница между fit
и fit_transform
заключается в том, что когда вы используете первый, он просто выполняет математические вычисления для преобразования данных, только когда вы используете transform
, данные восстанавливаются. Итак, как вы уже догадались, fit_transform
делает и то, и другое за один раз.
Это не ответ на мой вопрос. Как вы это сформулировали, я спрашиваю, что делает шаг transform
?
Проще говоря:
fit(X)
: Вычисляет собственные векторы ковариационной матрицы X
с использованием собственного разложения. Вы можете получить собственные векторы после того, как подберете PCA (pca.fit(X)
) с помощью pca.components_
.transform(X)
: Преобразует входные данные из входного векторного пространства в векторное пространство PCA. То есть — векторное пространство, определяемое собственными векторами, полученными в результате алгоритма PCA. Преобразованные данные обычно называют главными компонентами (ПК).fit_transform(X)
: Объединяет оба шага — сначала нахождение собственных векторов, а затем проецирование на них данных.На практике реализация PCA Scikit-learn использует разложение по сингулярным значениям (SVD) на X
, которое дает вам как собственные векторы, так и главные компоненты за один шаг во время fit()
. Однако если у вас есть новые данные для проецирования в пространство главных компонентов, вам понадобится метод transform()
для выполнения этого проецирования.
Примечание по терминологии Scikit-learn: собственные векторы = components_
Я поигрался с этим, и одна вещь все еще меня смущает. Кажется, что fit_transform
выдает преобразованные данные на выходе, но не предоставляет никакого способа получить сами собственные векторы. Я неправильно понял, как получить обе части информации одновременно?
Кстати: «Точный» ответ на мой вопрос заключается в том, что transform
преобразует входные данные из входного векторного пространства в векторное пространство PCA. То есть — векторное пространство, определяемое собственными векторами, полученными в результате алгоритма PCA. (Как вы упомянули, по-видимому, по умолчанию это SVD.)
Спасибо, я обновил ответ, добавив более точное описание. Я также добавил, как получить собственные векторы.
Вот несколько заметок из блокнота, который я создал, чтобы выяснить, какие преобразования на самом деле применял PCA.
Выходные данные fit_transform
— это входные данные с примененным некоторым преобразованием. Мы хотим точно знать, какое преобразование применяется к входным данным для создания выходных данных.
pca_output_transformed_0 = pca.fit_transform(uv.T) # uv is some input, see later
Оказывается, следующее эквивалентно предыдущему.
pca_output = pca.fit(uv.T)
pca_rotation_matrix = pca_output.components_
pca_xy = pca_rotation_matrix @ uv
Другими словами pca_xy == pca_output_transformed_0
.
import math
import numpy
x = numpy.random.normal(0.0, 1.0, size=10000)
y = numpy.random.normal(0.0, 0.1, size=10000)
xy = numpy.vstack((x, y))
theta = math.pi / 180.0 * 10.0
s = math.sin(theta)
c = math.cos(theta)
rotation_matrix = numpy.array([[c, -s], [s, c]])
rotation_matrix_inv = numpy.linalg.inv(rotation_matrix)
uv = rotation_matrix @ xy
import matplotlib.pyplot as plt
plt.figure()
plt.plot(xy[0], label='x')
plt.plot(xy[1], label='y')
plt.xlabel('sample')
plt.ylabel('currency-pair')
plt.legend(loc='upper left', bbox_to_anchor=(1, 1), ncol=1)
plt.xticks(rotation=30)
plt.show()
plt.figure()
plt.plot(uv[0], label='u')
plt.plot(uv[1], label='v')
plt.xlabel('sample')
plt.ylabel('currency-pair')
plt.legend(loc='upper left', bbox_to_anchor=(1, 1), ncol=1)
plt.xticks(rotation=30)
plt.show()
plt.figure()
plt.scatter(xy[0], xy[1], s=1)
plt.xlabel('x')
plt.ylabel('y')
plt.xlim(-5, 5)
plt.ylim(-5, 5)
plt.show()
plt.figure()
plt.scatter(uv[0], uv[1], s=1)
plt.xlabel('u')
plt.ylabel('v')
plt.xlim(-5, 5)
plt.ylim(-5, 5)
plt.show()
import sklearn.decomposition
pca = sklearn.decomposition.PCA()
pca_output = pca.fit(uv.T)
pca_output_transformed_0 = pca.fit_transform(uv.T)
pca_output_transformed_1 = pca.transform(uv.T)
# these are the same (output all zero within rounding error)
pca_output_transformed_0 - pca_output_transformed_1
pca_rotation_matrix = pca_output.components_
pca_xy = pca_rotation_matrix @ uv
plt.figure()
plt.scatter(pca_xy[0], pca_xy[1], s=1)
plt.xlabel('pca_x')
plt.ylabel('pca_y')
plt.xlim(-5, 5)
plt.ylim(-5, 5)
plt.show()
pca_output_transformed_0
plt.figure()
plt.scatter(pca_output_transformed_0.T[0], pca_output_transformed_0.T[1], s=1)
plt.xlabel('pca_output_transformed_0.T [y]')
plt.ylabel('pca_output_transformed_0.T [x]')
plt.xlim(-5, 5)
plt.ylim(-5, 5)
plt.show()
Один комментарий, который мне, пожалуй, следует добавить. Эти сигналы имеют нулевое среднее значение. Если вы примените PCA к некоторым сигналам с ненулевым средним значением, то среднее значение будет вычтено из этих сигналов в преобразованном выходе.
Документация: scikit-learn.org/stable/modules/generated/…