3
2

More than 3 years have passed since last update.

scikit-learnのPCAのパラメータについてまとめてみた

Posted at

はじめに

scikit-learnのpcaの公式ドキュメントを読んでみてわかったことを備忘録としてまとめてみました。

目次

  • 概要の日本語訳
  • pcaクラスの主なパラメーター
  • irisデータセットで試してみた

概要の日本語訳

[概要の日本語訳]
主成分分析(PCA)
データを低次元空間に投影するためのデータの特異値分解を用いた線形次元削減。入力データは,SVDを適用する前に,各特徴に対して中央揃えされますが,スケーリングはされません.
入力データの形状と抽出する成分の数に応じて,完全SVDのLAPACK実装,またはHalkoらの手法によるランダム化された切り捨てSVDを使用する.
また,scipy.sparse.linalg ARPACKによる切り捨てSVDの実装を利用することもできます. このクラスはスパース入力をサポートしていないことに注意してください。疎なデータを使用した代替案については、TruncatedSVDを参照してください。
詳細はユーザガイドを参照してください。
[読んでみてわかった]

  • PCAは次元削減のためのツールである。

  • 入力データは自動で中心化される。

  • 固有値計算にはSVDを使っていてデータに応じてSVDのアルゴリズムを切り替えられる。

  • あと実はこの説明はpcaのpydocの説明とまんま同じ。これより詳細な説明はユーザーガイドに書かれている。

pcaクラスの主なパラメーター と属性

[主なパラメーター]

  • n_components int, float, None or str
    主成分の数(int)を指定するだけじゃない*。
    n_components == 'mle' and svd_solver == 'full' とすることで主成分の数を最尤推定で求めることができたりする。
    また、少数(0<1)を指定すると、寄与率の合計が指定値以上になるように主成分を大きい順にとってくる

  • whiten bool, optional (default False)
    データの白色化。固有行列が互いに相関しないようにするっぽい?画像解析の前処理で使うらしい。

[主な属性]

  • explained_variance_ 主成分の固有値
  • explained_variance_ratio_ 寄与率
  • singular_values_ 主成分に対応する特異値。

irisデータセットで試してみた

  • データセットのインポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler

from sklearn.datasets import load_iris
iris = load_iris()
data_iris = pd.DataFrame(iris.data, columns=iris.feature_names)
data_iris['target'] = iris.target
scaler = StandardScaler()
# データセットからターゲットの列は除く
data_std = scaler.fit_transform(data_iris[iris.feature_names])
  • n_components=2でPCAを実行してみた
pca = PCA(n_components=2) #インスタンス生成
vars(pca) # インスタンス生成時の属性
ーーーーーーーーーーーーーーーーーーーー
{'n_components': 2,
 'copy': True,
 'whiten': False,
 'svd_solver': 'auto',
 'tol': 0.0,
 'iterated_power': 'auto',
 'random_state': None}
 ーーーーーーーーーーーーーーーーーーー
 pca_transformed = pca.fit_transform(data_std) # irisデータを生成したインスタンスでpca
 vars(pca) # pca後の属性
 ーーーーーーーーーーーーーーーーーーー
 {'n_components': 2,
 'copy': True,
 'whiten': False,
 'svd_solver': 'auto',
 'tol': 0.0,
 'iterated_power': 'auto',
 'random_state': None,
 'n_features_in_': 4,
 '_fit_svd_solver': 'full',
 'mean_': array([-1.69031455e-15, -1.84297022e-15, -1.69864123e-15, -1.40924309e-15]),
 'noise_variance_': 0.08429784161070521,
 'n_samples_': 150,
 'n_features_': 4,
 'components_': array([[ 0.52106591, -0.26934744,  0.5804131 ,  0.56485654],
        [ 0.37741762,  0.92329566,  0.02449161,  0.06694199]]),
 'n_components_': 2,
 'explained_variance_': array([2.93808505, 0.9201649 ]),
 'explained_variance_ratio_': array([0.72962445, 0.22850762]),
 'singular_values_': array([20.92306556, 11.7091661 ])}
 ーーーーーーーーーーーーーーーーーーーーーーーーーー

このような感じでPCAの属性はデータに対してfit_transformをすることで値が埋め込まれるものがいくつかあるようです。

  • [n_components == 'mle’で主成分の値を推定してみた]
pca = PCA(n_components = 'mle' , svd_solver = 'full')
vars(pca)
ーーーーーーーーーーーーーーーーーーーーー
{'n_components': 'mle',
 'copy': True,
 'whiten': False,
 'svd_solver': 'full',
 'tol': 0.0,
 'iterated_power': 'auto',
 'random_state': None}
 ーーーーーーーーーーーーーーーーーーーーー
pca_transformed = pca.fit_transform(data_std)
vars(pca)
 ーーーーーーーーーーーーーーーーーーーーー
 {'n_components': 'mle',
 'copy': True,
 'whiten': False,
 'svd_solver': 'full',
 'tol': 0.0,
 'iterated_power': 'auto',
 'random_state': None,
 'n_features_in_': 4,
 '_fit_svd_solver': 'full',
 'mean_': array([-1.69031455e-15, -1.84297022e-15, -1.69864123e-15, -1.40924309e-15]),
 'noise_variance_': 0.020853862176462283,
 'n_samples_': 150,
 'n_features_': 4,
 'components_': array([[ 0.52106591, -0.26934744,  0.5804131 ,  0.56485654],
        [ 0.37741762,  0.92329566,  0.02449161,  0.06694199],
        [-0.71956635,  0.24438178,  0.14212637,  0.63427274]]),
 'n_components_': 3,
 'explained_variance_': array([2.93808505, 0.9201649 , 0.14774182]),
 'explained_variance_ratio_': array([0.72962445, 0.22850762, 0.03668922]),
 'singular_values_': array([20.92306556, 11.7091661 ,  4.69185798])}
 ーーーーーーーーーーーーーーーーーーーーー
 # print(sum(pca.explained_variance_ratio_))
 ーーーーーーーーーーーーーーーーーーーーー
 0.9948212908928452
 ーーーーーーーーーーーーーーーーーーーーー

noise_variance_などn_components=2で実行したときにはでてこなかった属性が表れることがわかります。

また、この場合だとinputの特徴数=4に対して最適な特徴数が3であると推定されたようです。

  • データを主成分にProjectionしてみる
# データセットからターゲットの列は除く
df = pca.transform(data_iris.iloc[:,:-1])
pca_df = pd.DataFrame(df)
print(pca_df)
ーーーーーーーーーーーーーーーーーーーー
            0         1         2
0    2.640270  5.204041 -2.488621
1    2.670730  4.666910 -2.466898
2    2.454606  4.773636 -2.288321
3    2.545517  4.648463 -2.212378
4    2.561228  5.258629 -2.392226
..        ...       ...       ...
145  7.000417  5.579908 -1.890065
146  6.584640  4.935618 -2.006564
147  6.726747  5.484342 -1.936433
148  6.748228  5.765416 -1.404104
149  6.243095  5.242054 -1.645761

[150 rows x 3 columns]
ーーーーーーーーーーーーーーーーーーーーー

所感

今まで、pcaの存在や使い方は何となくしか知らなかったのですが、公式ドキュメントを読んでみて最適なn_componentsを探すためのパラメーター設定など面白そうな機能があることに気づきました。

今後業務でデータのEDAをする機会があったらこれらの機能も積極的に活用してみたいと思いました。

3
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2