Выход функции преобразования PCA из sklearn в Python не совпадает.

Вопрос или проблема

Я вычисляю 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:

  1. Центрирование данных: Когда вы вызываете метод 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, :]))
  2. Метод, используемый для получения компонентов: Обратите внимание на то, что при использовании двух экземпляров PCA (transformer для 10 компонент и transformer для 3 компонент), может быть небольшое различие в вычислении самих компонент, в зависимости от того, как SVD (сингулярное разложение) будет осуществляться на различных уровнях точности. Даже малые изменения в исходных данных могут повлиять на направление компонент из-за самого процесса расчёта.

  3. Точность вычислений: Разные финализированные значения компонент могут также быть вызваны точностью, с которой вычислены значение сингулярного разложения – особенно если вы работаете с большими наборами данных или, возможно, имеете операционные погрешности, которые могут возникать в процессе.

Подытоживая, для получения одинаковых результатов one и two, обязательно центрируйте свои данные перед тем, как умножить их на компоненты. Это позволит вам получить проекцию в том же пространстве, что и при вызове метода transform из sklearn.

Если у вас есть вопросы или вам нужна дополнительная помощь, не стесняйтесь обращаться!

Оцените материал
Добавить комментарий

Капча загружается...