Вопрос или проблема
Я вычисляю PCA по некоторым данным, используя 10 компонент и используя 3 из 10 следующим образом:
transformer = PCA(n_components=10)
trained=transformer.fit(train)
one=numpy.matmul(train,numpy.transpose(trained.components_[:3,:]))
Здесь trained.components_[:3,:] равны:
array([[-1.43311999e-03, 1.65635865e-01, 5.49189565e-01,
5.26069645e-02, 2.42638594e-01, 1.20957807e-02,
1.30595572e-01, 1.09279646e-02, 7.21299808e-03,
-2.79057934e-02, -1.14834589e-02, 5.06289160e-01,
5.42890317e-01, 8.50422194e-02, 1.80935205e-01,
2.98473275e-05, -8.04537378e-04],
[-1.05419313e-02, 3.09442577e-01, -8.15534934e-02,
4.28621520e-03, 2.93323569e-01, 3.85849115e-02,
-1.16193185e-01, 4.14964652e-01, 4.16279154e-01,
2.95264788e-01, 3.28620106e-01, -2.60916490e-01,
-2.37459426e-02, 1.57567265e-01, 4.02873342e-01,
5.28389303e-05, -2.07920000e-03],
[ 8.63072772e-03, -3.26129082e-01, 8.59869400e-02,
3.04770780e-03, -3.14966419e-01, -2.47151330e-02,
1.05987767e-01, 3.74235953e-01, 3.75747065e-01,
2.76035253e-01, 3.18273743e-01, 3.02423861e-01,
2.76535177e-02, -1.51485057e-01, -4.48558170e-01,
-8.83328996e-05, -2.25542180e-03]])
и, используя только 3 компоненты, как:
transformer = PCA(n_components=3)
trained=transformer.fit(train)
two=trained.transform(train)
Здесь компоненты равны:
array([[-1.43311999e-03, 1.65635865e-01, 5.49189565e-01,
5.26069645e-02, 2.42638594e-01, 1.20957807e-02,
1.30595572e-01, 1.09279646e-02, 7.21299808e-03,
-2.79057934e-02, -1.14834589e-02, 5.06289160e-01,
5.42890317e-01, 8.50422194e-02, 1.80935205e-01,
2.98473275e-05, -8.04537377e-04],
[-1.05419314e-02, 3.09442577e-01, -8.15534934e-02,
4.28621520e-03, 2.93323569e-01, 3.85849115e-02,
-1.16193185e-01, 4.14964652e-01, 4.16279154e-01,
2.95264788e-01, 3.28620106e-01, -2.60916490e-01,
-2.37459426e-02, 1.57567265e-01, 4.02873342e-01,
5.28389307e-05, -2.07919994e-03],
[ 8.63072765e-03, -3.26129082e-01, 8.59869400e-02,
3.04770780e-03, -3.14966419e-01, -2.47151331e-02,
1.05987767e-01, 3.74235953e-01, 3.75747065e-01,
2.76035253e-01, 3.18273743e-01, 3.02423861e-01,
2.76535177e-02, -1.51485057e-01, -4.48558170e-01,
-8.83328994e-05, -2.25542175e-03]])
Но one не равен two. Компоненты одинаковы в обоих случаях. Они не одинаковы, потому что функция transform сначала вычитает оригинальные данные из вектор среднего, а затем умножает на компоненты. Но почему здесь нужно вычитать среднее. В первом шаге для вычисления PCA среднее уже вычли для вычисления базиса.
Если вы посмотрите на исходный код, то PCA вычисляется через SVD. Я думаю, что он итеративно работает до тех пор, пока “не станет достаточно хорошим”.
https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/decomposition/pca.py
Ответ или решение
Ваш вопрос о различиях в выходных данных функции трансформации PCA в библиотеке sklearn интересен и важен для понимания работы PCA и её применения.
При использовании метода главных компонент (PCA) в sklearn, важно учитывать, что технология стандартного PCA всегда включает в себя стандартизацию данных перед тем, как вы начнете процесс. Это значит, что из ваших данных вычитается среднее значение каждого признака (feature), и в дальнейшем будет рассчитана матрица ковариаций, основанная на этих центрированных данных.
Вот основные причины, по которым результат вашего вычисления one
не совпадает с two
:
-
Центрирование данных: Когда вы вызываете метод
fit
на данных, стандартный PCA (включая используемые в нём стандартные компоненты) центрирует данные, вычитая из каждого элемента среднее значение соответствующего признака. Это важно, поскольку основная идея PCA заключается в том, чтобы найти направления, максимизирующие дисперсию (вариацию) данных, что может быть достигнуто только при вычитании среднего. Следовательно, когда вы выполняетеtrained.transform(train)
, данные уже центрированы.В вашем случае,
one
– это результат умножения исходных данныхtrain
на первые три компоненты, что не учитывает необходимое вычитание среднего значения. Если вы хотите получить совпадение, вам нужно сначала центрировать данные:train_centered = train - numpy.mean(train, axis=0) one = numpy.matmul(train_centered, numpy.transpose(trained.components_[:3, :]))
-
Метод, используемый для получения компонентов: Обратите внимание на то, что при использовании двух экземпляров PCA (
transformer
для 10 компонент иtransformer
для 3 компонент), может быть небольшое различие в вычислении самих компонент, в зависимости от того, как SVD (сингулярное разложение) будет осуществляться на различных уровнях точности. Даже малые изменения в исходных данных могут повлиять на направление компонент из-за самого процесса расчёта. -
Точность вычислений: Разные финализированные значения компонент могут также быть вызваны точностью, с которой вычислены значение сингулярного разложения – особенно если вы работаете с большими наборами данных или, возможно, имеете операционные погрешности, которые могут возникать в процессе.
Подытоживая, для получения одинаковых результатов one
и two
, обязательно центрируйте свои данные перед тем, как умножить их на компоненты. Это позволит вам получить проекцию в том же пространстве, что и при вызове метода transform
из sklearn.
Если у вас есть вопросы или вам нужна дополнительная помощь, не стесняйтесь обращаться!