[機械学習のはじめ方] Part28: PCA(主成分分析)の考え方と可視化

機械学習

たくさんの情報(特徴量)を持つデータを、大切な情報を保ったまま次元を減らすテクニックを学びましょう!

🤔 なぜ次元削減が必要なの?PCAって何?

機械学習で扱うデータは、たくさんの特徴量(説明変数)を持つことがあります。例えば、顧客データなら年齢、性別、購買履歴、サイト滞在時間…など、数十、数百もの特徴量を持つことも珍しくありません。このような多次元データは、そのまま扱うのが難しい場合があります。

  • 次元の呪い: 次元数が多くなると、データが非常にまばらになり、モデルの学習に必要なデータ量が指数関数的に増加したり、計算コストが増大したりします。
  • 多重共線性: 似たような情報を持つ特徴量が複数あると、モデルの精度が不安定になることがあります。
  • 可視化の困難: 人間が直感的に理解できるのは2次元や3次元までです。高次元データをそのままグラフにすることはできません。

そこで役立つのが次元削減の手法です。PCA(Principal Component Analysis: 主成分分析)は、最も代表的な次元削減手法の一つです。

PCAは、元のデータが持つ情報の損失を最小限に抑えながら、より少ない次元(特徴量)でデータを表現することを目指します。たくさんの特徴量を、それらを要約した主成分と呼ばれる新しい軸(合成変数)に変換します。これは教師なし学習の一種で、データの構造を理解するためにもよく使われます。

💡 PCAの考え方:情報の「分散」を最大化する軸を探す

PCAは、データが最も「ばらついている」方向、つまり分散が最大になる方向を探し出します。この方向が第一主成分 (PC1) と呼ばれます。なぜ分散が重要なのでしょうか? データがよくばらついている方向には、それだけ多くの情報が含まれていると考えられるからです。

次に、第一主成分と直交する方向(互いに影響し合わない方向)の中で、次に分散が最大になる方向を探します。これが第二主成分 (PC2) です。同様に、第三、第四…と、元のデータの次元数まで主成分を見つけることができます。

通常、最初のいくつかの主成分(PC1, PC2, …)だけで、元のデータの情報の大部分(分散の大部分)を説明できます。それぞれの主成分が元のデータの分散をどれだけ説明しているかの割合を寄与率と呼びます。そして、第一主成分から順に寄与率を足し合わせたものを累積寄与率と呼びます。

累積寄与率を見ることで、「何番目の主成分まで使えば、元の情報の〇〇%を説明できるか」を知ることができます。例えば、累積寄与率が80%や90%に達するまでの主成分だけを使って、データを低次元に変換することが一般的です。

数学的な背景を少しだけ補足すると、PCAはデータの共分散行列(または相関行列)を計算し、その固有値固有ベクトルを求めます。固有値が大きい順に主成分となり、その固有値が主成分の分散の大きさを表します。固有ベクトルは主成分の方向(係数)を示します。初学者のうちは、まず「分散が大きい方向を見つける」という直感的な理解で大丈夫です👍。

🐍 Python (scikit-learn) でPCAを実装してみよう!

それでは、Pythonのライブラリ `scikit-learn` を使ってPCAを実装してみましょう。ここでは、有名なアヤメ (Iris) データセットを使います。アヤメデータセットは、がく片の長さ・幅、花びらの長さ・幅の4つの特徴量を持っています。これをPCAで2次元に削減してみます。

1. ライブラリのインポートとデータの準備


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA

# Irisデータセットのロード
iris = load_iris()
X = iris.data # 特徴量 (4次元)
y = iris.target # 目的変数 (アヤメの種類: 0, 1, 2)
feature_names = iris.feature_names

# データフレームに変換 (任意ですが見やすい)
df = pd.DataFrame(X, columns=feature_names)
df['species'] = y
print("元のデータ (一部):")
print(df.head())
      

2. データの前処理(標準化)

PCAは各特徴量のスケール(単位や大きさ)に影響を受けます。例えば、長さ(cm)と幅(mm)が混在していると、値の大きい長さの影響が過剰に大きくなってしまいます。そのため、PCAを適用する前に、各特徴量の平均を0、分散を1にする標準化を行うのが一般的です。


# 標準化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X) # fitとtransformを同時に実行

print("\n標準化後のデータ (一部):")
print(X_scaled[:5, :]) # 最初の5行を表示
      

3. PCAの適用

`scikit-learn` の `PCA` クラスを使います。`n_components` で削減後の次元数を指定します。今回は2次元に削減します。


# PCAのインスタンスを作成 (2次元に削減)
pca = PCA(n_components=2)

# PCAを実行 (標準化後のデータに適用)
X_pca = pca.fit_transform(X_scaled) # fitとtransformを同時に実行

print("\nPCA適用後のデータ (2次元, 一部):")
print(X_pca[:5, :]) # 最初の5行を表示

# データフレームに変換 (可視化のため)
df_pca = pd.DataFrame(X_pca, columns=['PC1', 'PC2'])
df_pca['species'] = y
      

4. 寄与率の確認

各主成分がどれくらいの情報(分散)を持っているかを確認しましょう。


# 各主成分の寄与率
print(f"\n各主成分の寄与率: {pca.explained_variance_ratio_}")

# 累積寄与率
cumulative_explained_variance_ratio = np.cumsum(pca.explained_variance_ratio_)
print(f"累積寄与率: {cumulative_explained_variance_ratio}")

print(f"\n第1主成分までの累積寄与率: {cumulative_explained_variance_ratio[0]:.4f}")
print(f"第2主成分までの累積寄与率: {cumulative_explained_variance_ratio[1]:.4f}")
      

この結果から、第一主成分 (PC1) だけで元のデータの約73%、第二主成分 (PC2) まで含めると約96%の情報を説明できていることがわかります。4次元の情報を、かなり少ない損失で2次元に要約できたと言えますね 🎉。

📊 PCAの結果を可視化する

PCAの大きなメリットの一つは、高次元データを低次元(特に2次元や3次元)に削減して可視化できることです。これにより、データの分布や構造、クラスターなどを視覚的に捉えやすくなります。

先ほど作成した2次元のPCAデータ (`df_pca`) を使って、散布図を描いてみましょう。`matplotlib` や `seaborn` を使うと簡単に描画できます。ここでは、アヤメの種類 (`species`) ごとに色分けしてプロットしてみます。


plt.figure(figsize=(8, 6))
sns.scatterplot(x='PC1', y='PC2', hue='species', data=df_pca, palette='viridis', s=70)

# 凡例のラベルを設定
target_names = iris.target_names
plt.legend(title='Species', labels=[target_names[i] for i in np.unique(y)])

plt.title('PCA of Iris Dataset (2 Components)')
plt.xlabel(f'Principal Component 1 (Explains {pca.explained_variance_ratio_[0]*100:.2f}% variance)')
plt.ylabel(f'Principal Component 2 (Explains {pca.explained_variance_ratio_[1]*100:.2f}% variance)')
plt.grid(True)
plt.show() # プロットを表示
      

この散布図を見ると、以下のことがわかります。

  • Setosa (0) は他の2種 (Versicolor (1), Virginica (2)) から明確に分離されている。
  • Versicolor (1) と Virginica (2) は一部重なりがあるものの、PC1軸とPC2軸によってある程度分離できている。

このように、PCAを使ってデータを2次元に削減・可視化することで、元の4次元データでは見えにくかったクラス間の関係性を直感的に理解することができます。これは、クラスタリングや分類モデルを構築する前のデータ理解(EDA)において非常に役立ちます。

⚠️ PCAの注意点と使いどころ

PCAは強力な手法ですが、いくつか注意点もあります。

注意点説明
スケールの影響前述の通り、PCAは分散に基づいて主成分を決定するため、特徴量のスケールに大きく影響されます。必ず標準化などのスケーリングを行ってから適用しましょう。
線形性PCAは線形変換です。データが非線形な構造を持つ場合、PCAだけではうまく次元削減できないことがあります。その場合は、カーネルPCAや他の非線形次元削減手法(t-SNE, UMAPなど)を検討する必要があります。
解釈性主成分は元の特徴量の線形結合で表されるため、各主成分が具体的に「何を」意味するのか解釈するのが難しい場合があります。元の特徴量を直接扱う方が解釈しやすい場合もあります。

PCAが特に有効なのは以下のような場合です。

  • ✨ 特徴量の数が非常に多い場合に、計算コスト削減や次元の呪いを回避するために次元削減したいとき。
  • ✨ 多重共線性(特徴量間の相関が高い状態)が存在する場合に、相関の低い主成分に変換して問題を緩和したいとき。
  • ✨ 高次元データを低次元(2D or 3D)に落とし込んで可視化し、データの構造を把握したいとき。
  • ✨ ノイズリダクション:寄与率の低い主成分を除去することで、データのノイズを減らす効果が期待できる場合があります。

次のステップでは、PCAと同様によく使われる次元削減・可視化手法である t-SNEUMAP について学びます。これらの手法は、特に非線形な構造を持つデータの可視化に優れています。PCAとの違いや使い分けについても見ていきましょう!

✨ まとめ

今回は、代表的な次元削減手法であるPCA(主成分分析)について学びました。

  • PCAは、データの分散が最大になる方向(主成分)を見つけ、情報の損失を抑えながら次元を削減する手法です。
  • 標準化などの前処理が重要です。
  • scikit-learnを使えば簡単に実装できます。
  • 寄与率・累積寄与率を確認することで、どれだけの情報が保持されているか評価できます。
  • PCAを使うことで、高次元データを2次元や3次元に削減して可視化し、データの構造を理解するのに役立ちます。
  • 線形な手法である点や、スケールの影響を受ける点に注意が必要です。

PCAは、データ分析や機械学習の前処理、可視化など、様々な場面で活用される基本的なテクニックです。ぜひ実際に手を動かして、その効果を体験してみてくださいね! 😊

コメント

タイトルとURLをコピーしました