単元 3:次元削減 — PCA(主成分分析)
StandardScalerでデータを標準化し、変数のスケール差をならせるsklearn.decomposition.PCAで高次元データを 2 次元・3 次元に投影できるexplained_variance_ratio_で各主成分の寄与率を読める- 主成分得点の散布図から特徴を読み取り、主成分の意味を自分の言葉で説明できる
高次元データを「眺める」ための工夫
Section titled “高次元データを「眺める」ための工夫”5 教科の試験データ、数十個の特徴量を持つ顧客データ、何百次元もの遺伝子発現データ。実データは 2 次元の散布図で見られないほど次元が高い ことが多くあります。
人間が一目で構造を把握できるのは 2 次元(散布図)か、せいぜい 3 次元まで。だから「高次元データを、できるだけ情報を保ったまま 2 次元に投影できないか」という発想が出てきます。これを実現する代表的な手法が PCA(主成分分析、Principal Component Analysis) です。
PCA は線形代数の手法ですが、本コースでは数学的な導出には踏み込まず、「何のためにあるか」「どう使うか」「結果をどう解釈するか」を中心に扱います。
PCA の直感
Section titled “PCA の直感”PCA は、データの 分散(ばらつき)が最大になる方向(軸) を順に見つけ、その軸へデータを投影します。
- 第 1 主成分:データのばらつきが最も大きい方向
- 第 2 主成分:第 1 主成分に直交する方向のうち、次にばらつきが大きい方向
- 第 3 主成分:これまでの主成分すべてに直交する方向のうち、次にばらつきが大きい方向 ……
「分散が大きい方向」とは、データを区別する力が強い方向 と言い換えられます。試験データなら「総合点が高い人と低い人をきれいに分ける」のが第 1 主成分、「文系寄りと理系寄りを分ける」のが第 2 主成分、というイメージです。
なぜ標準化が必要か
Section titled “なぜ標準化が必要か”PCA をかける前に データの標準化(平均 0、標準偏差 1 への変換)が必要になるケースがあります。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()scores_scaled = scaler.fit_transform(scores)PCA は分散の大きい方向を優先するため、変数のスケールが揃っていないと 「単位が大きい変数」が結果を支配してしまいます。
- 「年齢(10〜90)」と「年収(300〜5000)」を一緒に PCA にかけると、年収のスケールが圧倒的に大きいので、第 1 主成分はほぼ「年収方向」になってしまう
- 一方、試験の点数のように すべて同じ単位(0〜100 点) なら、標準化は省いてもよい
迷ったときは標準化しておくのが安全です。本コースでも基本的に標準化を入れた流れで進めます。
PCA の実行
Section titled “PCA の実行”scikit-learn の PCA クラスを使います:
from sklearn.decomposition import PCA
pca = PCA(n_components=3)principal_components = pca.fit_transform(scores_scaled)n_components=3— 取り出す主成分の数(次元削減後の次元数)fit_transform()— 「学習」と「変換」を一気に行うショートカット
返り値の principal_components は 元データの各行を主成分空間に射影した値(主成分得点) の 2 次元配列です。50 名分のデータなら (50, 3) の形になります。
寄与率と累積寄与率
Section titled “寄与率と累積寄与率”各主成分がデータの分散をどれだけ説明するかを 寄与率 と呼びます。explained_variance_ratio_ 属性で取り出せます:
import numpy as np
print(pca.explained_variance_ratio_)# 例: [0.555, 0.383, 0.048]
print(np.cumsum(pca.explained_variance_ratio_))# 例: [0.555, 0.938, 0.986]この例なら、
- 第 1 主成分で 55.5%、第 2 主成分で 38.3%、第 3 主成分で 4.8% の分散を説明している
- 上位 2 主成分の合計(累積寄与率)で 93.8%、上位 3 主成分で 98.6% の情報を保持している
という読み方になります。累積寄与率が 80〜90% を超える主成分数まで取れば、データの大部分が説明できている と判断するのが目安です。
主成分の「意味」を読む
Section titled “主成分の「意味」を読む”ここが PCA で最も重要かつ難しい部分です。pca.components_ には 各主成分が元の変数のどんな線形結合か が記録されています。係数の大小から「この主成分はどんな特徴を表しているか」を 分析者が自分で解釈する 必要があります。アルゴリズムが「これは総合学力です」と教えてくれるわけではありません。
import pandas as pd
loadings_df = pd.DataFrame( pca.components_.T, columns=["第1主成分", "第2主成分", "第3主成分"], index=["国語", "数学", "英語", "理科", "社会"],)loadings_dfたとえば:
- 第 1 主成分:全教科の係数がほぼ正(0.5 前後)で揃っていれば、「すべての教科が高いほど第 1 主成分の値が高い」→ 総合学力 と解釈できる
- 第 2 主成分:国語・英語・社会で正、数学・理科で負なら、「文系科目が高くて理系科目が低い人は第 2 主成分が正」→ 文系傾向 と解釈できる
「ラベル」は分析者が データから読み取って付ける もので、客観的な正解はありません。複数の人が同じ PCA 結果を見ても異なる解釈をすることがあります。解釈が分かれたときは、両方の解釈を併記して議論する、というのが実務的な流儀です。
散布図で全体を見る
Section titled “散布図で全体を見る”第 1 主成分 × 第 2 主成分の散布図を描けば、データ全体の構造が 1 枚絵 で把握できます:
import matplotlib.pyplot as plt
plt.scatter(principal_components[:, 0], principal_components[:, 1])plt.xlabel("第1主成分")plt.ylabel("第2主成分")plt.show()総合力が高く文系寄りの人は右上、総合力が低く理系寄りの人は左下、というように、4 つの象限で集団の特徴を読み取れる のが PCA 散布図の強みです。点の集まり(クラスター)や外れ値が一目で分かるようになります。
よく出る躓きどころ
Section titled “よく出る躓きどころ”- 標準化を忘れる — 変数の単位が違うときに標準化をスキップすると、第 1 主成分が「単位が大きい変数の方向」に偏る
- 主成分の符号は任意 —
+/-が反転することがある。第 1 主成分が「総合学力(高いほど正)」とも「総合学力(高いほど負)」とも解釈できる。係数の符号と一緒に解釈すれば一貫する - 寄与率を見ずに使う — 累積寄与率が低い(たとえば 50% 以下)のに上位 2 主成分だけで判断すると、情報の半分以上を捨てていることになる
- 「PCA でクラスタリングできる」と誤解する — PCA は次元を削減するだけで、グループ分けは行わない。クラスタリング(k-means など)と組み合わせる場合は別の手順
コード/スケッチ
Section titled “コード/スケッチ”- 完成 Notebook:pca_analysis.ipynb をダウンロード
- データセット:test_scores.csv をダウンロード(50 名 × 5 教科の点数)
完成 Notebook を題材に、次を行いなさい。
- Notebook を Google Colab で開いて最後まで実行し、第 1〜第 3 主成分の寄与率と累積寄与率を確認する
- 第 1 主成分 × 第 2 主成分の 2 次元散布図を 1 枚生成する
- 主成分係数の表(
pca.components_)を見て、第 1 主成分・第 2 主成分が「どんな特徴を表しているか」を自分の言葉で書きなさい(解答例:「第 1 主成分は◯◯」のように 1〜2 文ずつ)
主成分の「意味」を言語化する 3 番が、この単元で身につけてほしい一番のスキルです。係数の正負と大小をセットで読むことで、PCA の出力に対する解釈力が育ちます。
発展課題(オプション)
Section titled “発展課題(オプション)”- 主成分係数を棒グラフで可視化し、各主成分の意味を視覚的に確認する
- 3 主成分を取って、Plotly で 3D 散布図を作成する(完成 Notebook 後半にサンプルあり)
- 自分でデータセットを 1 つ用意して PCA を適用し、寄与率と主成分の意味を整理してみる