Python × AI - 寄与率(次元削減数を探索)

寄与率(explained_variance_ratio_)をもとに有効なPC数を探索します。

(前回記事で取得したワインデータと主成分分析結果を使います。)

寄与率を確認

寄与率は、主成分がどの程度、元データの情報を保持しているかを表します。

各固有値を固有値で割ったものが寄与率になります。

固有値と同じくPC1がもっとも大きく、次第に小さくなります。

寄与率を表示するソースコードは下記のようになります。

[Google Colaboratory]

1
pd.DataFrame(np.round(pca.explained_variance_ratio_,2), index=["PC{}".format(x + 1) for x in range(len(df_pca.columns))], columns=["寄与率"])

[実行結果]

PC1が36%、PC2が19%となっておりこの2つを合わせた寄与率は55%で、PC1とPC2だけで半分以上説明できるということになります。

累積寄与率を可視化

縦軸が累積寄与率で、横軸がPCのグラフを表示します。(4行目)

また累積寄与率が90%になるまでの主成分を判断するために、90%の基準線も表示します。(2,8行目)

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
import matplotlib.ticker as ticker
line = np.full(14, 0.9)
plt.gca().get_xaxis().set_major_locator(ticker.MaxNLocator(integer=True))
plt.plot([0] + list( np.cumsum(pca.explained_variance_ratio_)), "-o")
plt.xlabel("PC")
plt.ylabel("cumulative contribution rate")
plt.yticks( np.arange(0, 1.1, 0.1))
plt.plot(line, "s-")
plt.grid()
plt.show()

[実行結果]

PC8のところで90%の基準線を超えていますので、PC8までを有効な次元数だと判断することができます。

より次元を削減したい場合は70%を基準することもあり、その場合はPC4までが有効な次元数となります。

累積寄与率の指定

PCAのパラメータであるn_components0~1を指定すると累積寄与率が設定でき、指定した累積寄与率を超過するまでの主成分を返してくれます。

n_components0.9(90%)を指定して実行します。(5行目)

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
sc = preprocessing.StandardScaler()
X = df_wine.iloc[:, 1:]
X_norm=sc.fit_transform(X)

pca = PCA(n_components=0.9, random_state=0)
X_pc = pca.fit_transform(X_norm)
df_pca = pd.DataFrame(X_pc, columns=["PC{}".format(i + 1) for i in range(len(X_pc[0]))])
print("主成分の数: ", pca.n_components_)
print("保たれている情報: ", round(np.sum(pca.explained_variance_ratio_),2))
display(df_pca.head())

[実行結果]

累積寄与率が90%を超過するPC8までが結果として表示されました。

累積寄与率は92%となっています。

寄与率をあらかじめ決めている場合や、大まかに有効な次元数を確認したい場合は便利な手法となります。

PCAのデータ標準化

PCAにおいてデータの標準化は基本的に実施することが推奨されていますが、ノイズデータが多い場合正しく軸をとれないことがあります。

そのため、標準化するパターン標準化しないパターンの両方を実施して結果の良い方を使用するこをお勧めします。

Python × AI - スクリープロット(次元削減数を探索)

PCAは、教師あり学習の説明変数としての用途もあります。

その際には、次元を減らしつつも元の情報をなるべく保持しているPCまで使う必要があります。

今回は、有効なPC数を探索していきます。

ワインデータの取得

アイリスデータより次元数の多いワインデータを使用します。

ワインデータは列名が入っていないので、列名を定義しています。(2行目)

[Google Colaboratory]

1
2
3
4
df_wine=pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data", header=None)
df_wine.columns = ["class", "Alcohol", "Malic acid", "Ash", "Alcalinity of ash","Magnesium", "Total phenols", "Flavanoids", "Nonflavanoid phenols","Proanthocyanins", "Color intensity", "Hue","OD280/OD315 of diluted wines", "Proline"]
display(df_wine.shape)
display(df_wine.head())

[実行結果]

正解データが入っているため、14次元サンプル数が178件のデータになります。

ワインデータの可視化

取得したワインデータを散布図行列で可視化します。

[Google Colaboratory]

1
2
3
from pandas import plotting
plotting.scatter_matrix(df_wine.iloc[:, 1:], figsize=(8, 8), c=list(df_wine.iloc[:, 0]), alpha=0.5)
plt.show()

[実行結果]

次元数が多いため、とても判断が難しくなっています。

だいたい3~4種類に分かれているような気がしなくもありません。

PCA

PCAを実行します。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
from sklearn.decomposition import PCA
from sklearn import preprocessing
import numpy as np
sc=preprocessing.StandardScaler()
X = df_wine.iloc[:, 1:]
X_norm=sc.fit_transform(X)

pca = PCA(random_state=0)
X_pc = pca.fit_transform(X_norm)
df_pca = pd.DataFrame(X_pc, columns=["PC{}".format(i + 1) for i in range(len(X_pc[0]))])
print("主成分の数: ", pca.n_components_)
print("保たれている情報: ", round(np.sum(pca.explained_variance_ratio_),2))
display(df_pca.head())

[実行結果]

主成分の数がPC1からPC13の13個あります。

パラメータのn_componentsを指定しない場合、主成分は元データの次元数と一致します。

全次元を対象にしたので保たれている情報は1.0(100%)になります。

固有値

固有値を確認して、PC1からどこまでが有効な主成分かを探索してみましょう。

[Google Colaboratory]

1
pd.DataFrame(np.round(pca.explained_variance_, 2), index=["PC{}".format(x + 1) for x in range(len(df_pca.columns))], columns=["固有値"])

[実行結果]

固有値(explained_variance)は、主成分の分散のことで主成分の情報量の大きさを表します。

PC1がもっとも大きく、次第に小さくなっていきます。

標準化している場合には、固有値が1.0以上のものを使うというのがもっともシンプルな判断基準となります。

今回の結果ですと、PC3までを使うことになります。

スクリープロットで可視化

次にスクリープロットを確認します。

スクリープロットは、固有値を最大から最小まで降順でプロットしたグラフのことで、崖(スクリー:scree)のような形になります。

固有値からスクリープロットを作成(2行目)し、グラフ表示するソースは以下の通りです。

固有値1.0の基準線も合わせて表示しています。(1,3行目)

[Google Colaboratory]

1
2
3
4
5
6
7
8
line = np.ones(14)
plt.plot(np.append(np.nan, pca.explained_variance_), "s-")
plt.plot(line, "s-")
plt.xlabel("PC")
plt.ylabel("explained_variance")
plt.xticks( np.arange(1, 14, 1))
plt.grid()
plt.show()

[実行結果]

固有値が、ある段階から急に小さな値となって以降は安定する箇所までを利用することが望ましいとされています。

上記のグラフだとPC7あたりかと思いますが、使用用途に応じて±2程度で調整する必要があります。


Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×