「主成分分析」について学ぶ(統計学 / 教師なし学習 / その他)

2023年5月13日

この記事では、統計学を初めて学ぶ筆者が、「教師なし学習」における「主成分分析」について学んだ内容について記載しています。

学習には、Wikipediaの「主成分分析」の記事を参考にし、Pythonのプログラミングにも触れ、理解を深めました。

プログラミングには、機械学習ライブラリのscikit-learnを使用しました。

この記事は、他の人が参考にできるよう、わかりやすく書くことを心がけました。

教師なし学習

教師なし学習は、データからパターンや構造を見つけ出すための機械学習の手法です。データにはラベルや目的変数がなく、機械自身が学習し、データの背後にある構造を抽出します。例えば、ある企業の顧客データを教師なし学習で解析することで、似たような傾向を持つグループや、注目すべき特徴を抽出することができます。

一方、教師あり学習は、データにラベルや目的変数がある場合に用いられます。目的変数と予測値との誤差を最小化するようにモデルを構築し、未知のデータに対して予測を行います。例えば、画像認識や音声認識などが教師あり学習の例です。

主成分分析(PCA)は、多数の変数があるデータセットから、その変数同士の相関を利用して、少数の「主成分」と呼ばれる新しい変数を作り出す統計手法です。これによって、元のデータセットの情報をなるべく失わずに、次元を削減することができます。例えば、100個の変数を持つデータがあった場合、PCAを使うことで、そのデータを10個の主成分で表現することができます。

教師なし学習とは、機械学習の手法の一つである。「出力すべきもの」があらかじめ決まっていないという点で教師あり学習とは大きく異なる。データの背後に存在する本質的な構造を抽出するために用いられる。

教師あり学習は、その「出力すべきもの」も入力として与える手法であり、データの背後に存在する本質的な構造を抽出するよりむしろ、思い通りの出力を再現する機械の構成に用いられる。

具体的な例として以下のようなものがある。

・クラスター分析

・主成分分析

・ベクトル量子化

・自己組織化マップ

教師なし学習

主成分分析

主成分分析(PCA)は、多数の変数があるデータセットから、その変数同士の相関を利用して、少数の「主成分」と呼ばれる新しい変数を作り出す統計手法です。これによって、元のデータセットの情報をなるべく失わずに、次元を削減することができます。例えば、100個の変数を持つデータがあった場合、PCAを使うことで、そのデータを10個の主成分で表現することができます。

このような次元削減は、データを扱う上で非常に役立ちます。たとえば、可視化や分類、予測などを行う場合、多数の変数を扱うと複雑になりすぎてしまうことがあります。しかし、主成分分析を用いることで、情報を失わずに簡潔に表現できるため、分析が容易になります。

また、PCAは次元削減だけでなく、データの解釈にも役立ちます。主成分は、元の変数の線形結合で構成されるため、それぞれの主成分がどのような変数の組み合わせでできているかを解釈することができます。これによって、データセットが持つ構造や特徴を理解することができます。

例えば、ある病院の患者のデータを考えてみます。患者の年齢、性別、血液検査の結果、身長、体重など、多数の変数があります。これらの変数を全て使って分析を行うと、解釈が困難になる場合があります。しかし、主成分分析を使うことで、例えば「健康状態」や「生活習慣」などの主成分を作り出し、それぞれの主成分がどのような変数の組み合わせでできているかを解釈することで、患者の状態を理解することができます。

主成分分析(しゅせいぶんぶんせき、英: principal component analysis; PCA)は、相関のある多数の変数から相関のない少数で全体のばらつきを最もよく表す主成分と呼ばれる変数を合成する多変量解析の一手法[1]。データの次元を削減するために用いられる。

主成分分析

主成分分析の手順

主成分分析において、主成分を求めるための手順は、まず第一主成分を求め、その次にそれまでに求めた主成分と直交するような第二主成分を求め、以降順番に主成分を求めていきます。この際、主成分は観測値の変動を最も説明できるように選ばれます。

具体的には、第一主成分は元の変数の中で最も分散が大きくなる方向をとります。つまり、観測値の変動を最も多く説明できる方向を求めることが目的です。次に、第二主成分は、第一主成分と直交するような方向を求めます。これを続けることで、主成分は互いに直交するように求められます。このように求められた主成分は、元の変数とは異なる新しい変数となります。

主成分は観測値のセットを線形結合として表すことができます。つまり、主成分は、観測値の各変数の重み付けをしたものを足し合わせることで求めることができます。また、主成分ベクトルは互いに直交するため、観測値を主成分で表すことで、情報をなるべく重複させることがなく、簡潔に表現することができます。

主成分の直交性は、共分散行列(または相関行列)の固有ベクトルによって得られます。共分散行列は実対称行列であり、その固有ベクトルは互いに直交するため、主成分も互いに直交することになります。このようにして、主成分分析において主成分が求められ、その性質が理解されます。

主成分を与える変換は、第一主成分の分散を最大化し、続く主成分はそれまでに決定した主成分と直交するという拘束条件の下で分散を最大化するようにして選ばれる。主成分の分散を最大化することは、観測値の変化に対する説明能力を可能な限り主成分に持たせる目的で行われる。選ばれた主成分は互いに直交し、与えられた観測値のセットを線型結合として表すことができる。言い換えると、主成分は観測値のセットの直交基底となっている。主成分ベクトルの直交性は、主成分ベクトルが共分散行列(あるいは相関行列)の固有ベクトルになっており、共分散行列が実対称行列であることから導かれる。

主成分分析

Pythonプログラミング

「主成分分析」をイメージしやすいようPythonでのプログラミングについても学びます。

scikit-learn トイデータセット

機械学習ライブラリscikit-learnに用意されている「トイデータセット」を使います。トイデータセットは、機械学習の問題を解くためのサンプルデータセットのことで、いくつかの種類が用意されています。例えば、Iris(アヤメ)の花の特徴から、その種類を分類する問題を解くための「irisデータセット」や、ボストン市の住宅価格に関するデータを用いて、住宅価格を予測する問題を解くための「bostonデータセット」などがあります。

Irisデータセットは、Setosa、Versicolour、Virginicaの3種類のアヤメの花のデータが含まれており、各種類について50個のサンプルがあります。このデータセットには、がく片の長さや幅、花びらの長さや幅、そしてアヤメの種類という4つの特徴量が含まれています。

irisデータセットに対して主成分分析(PCA)を適用することによって、データを圧縮し、可視化し、特徴量の相関関係を捉えることができます。

scikit-learnにはいくつかの小さな標準データセットが付属しており、外部のウェブサイトからファイルをダウンロードする必要はありません。

これらは以下の関数を使って読み込むことができます。

load_boston() : load_boston は 1.0 で非推奨となり、1.2 で削除される予定である。

load_iris() : アヤメのデータセット(分類)をロードして返す。

load_diabetes() : 糖尿病のデータセット(回帰)をロードして返す。

load_digits() : 数字のデータセット(分類)をロードして返す。

load_linnerud() : 身体運動のデータセットをロードして返す。

load_wine() : ワインのデータセット(分類)をロードして返す。

load_breast_cancer() : ウィスコンシン州の乳がんのデータセット(分類)をロードして返す。7.1. Toy datasetsts

アヤメのデータセット

アヤメのデータセットは、機械学習における代表的なデータセットの1つであり、サンプルデータの中でも特に有名なものの1つです。

アヤメのデータセットには、ヒオウギアヤメ(Iris-Setosa)、アイリス・バージカラー(Iris Versicolour)、アイリス・ヴァージニカ(Iris Virginica)の3種類のアヤメが含まれており、各々50件のデータがあります。データには、「がく片の長さ」、「がく片の幅」、「花びらの長さ」、「花びらの幅」といった4つの属性があり、また3種のアヤメの分類に関するデータも含まれています。

Iris Setosa (ヒオウギアヤメ)

アラスカ、メイン、カナダ(ブリティッシュコロンビア、ニューファンドランド、ケベック、ユーコンなど)、ロシア(シベリアなど)、アジア北東部、中国、韓国、日本など北極海を越えて広く分布する根生葉の多年草です。

茎は高く伸び、葉は中緑色、花は紫、紫紺、青、ラベンダー色です。また、ピンクや白の花を咲かせる植物もあります。

Irissetosa1.jpg
Iris Setosa (ヒオウギアヤメ)

Iris Versicolour (アイリス・バージカラー)

北アメリカ、アメリカ東部とカナダ東部に自生するアヤメの一種です。スゲ草地や湿地、川岸や海岸に普通に見られます。

特異形質バージカラー(versicolor)は「様々な色彩の」という意味です。

Blue Flag, Ottawa.jpg
Iris Versicolour (アイリス・バージカラー)

Iris Virginica (アイリス・ヴァージニカ)

北アメリカ東部原産の多年草です。アメリカ南東部のフロリダ州からジョージア州にかけての海岸平野によく見られます。

Iris virginica 2.jpg
Iris Virginica (アイリス・ヴァージニカ)

プログラム

irisデータセットに対して主成分分析(PCA)を適用し、2次元空間にプロットします。

import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA

# irisデータセットを読み込む
iris = load_iris()
X = iris.data
y = iris.target
target_names = iris.target_names

# PCAを適用する
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)

# PCAの結果をプロットする
plt.figure(figsize=(8, 6))
for target, target_name in enumerate(target_names):
    X_pca_target = X_pca[y == target]
    plt.scatter(X_pca_target[:, 0], X_pca_target[:, 1], label=target_name)

plt.xlabel('PC1')
plt.ylabel('PC2')
plt.title('Iris dataset after PCA')
plt.legend()
plt.show()

実行結果

PC1軸とPC2軸にデータが射影され、花の種類ごとに色分けされた散布図が表示されます。PCAを適用することで、元の4つの特徴量から抽出された2つの主成分を用いて、花の種類を分類することができます。

プログラムの説明

import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA

pandasをインポートし、pdという名前で使用できるようにします。

matplotlib.pyplotをインポートし、pltという名前で使用できるようにします。

scikit-learnのdatasetsモジュールから、load_iris関数をインポートします。これにより、irisデータセットを読み込むことができます。

scikit-learnのdecompositionモジュールから、PCAクラスをインポートします。これにより、主成分分析を実行するためのツールを提供します。

# irisデータセットを読み込む
iris = load_iris()
X = iris.data
y = iris.target
target_names = iris.target_names

load_iris()関数を使って、irisデータセットを読み込み、irisという名前で保存します。

irisデータセットの特徴量をXに保存します。

irisデータセットのラベル(花の種類 0, 1, 2)をyに保存します。

irisデータセットのラベル(花の種類 0, 1, 2)の名前(setosa, versicolor, virginica)をtarget_namesに保存します。

# PCAを適用する
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)

PCAクラスのインスタンスを作成し、n_componentsパラメータを2に設定して、2つの主成分を抽出します。

fit_transformメソッドを使用して、元の特徴量を2つの主成分に変換したデータをX_pcaに保存します。

# PCAの結果をプロットする
plt.figure(figsize=(8, 6))

figure()関数は、matplotlibでグラフを描画するための図を作成します。figsize引数を指定することで、作成される図のサイズを調整できます。このプログラムでは、サイズを8×6インチに設定しています。

for target, target_name in enumerate(target_names):
    X_pca_target = X_pca[y == target]
    plt.scatter(X_pca_target[:, 0], X_pca_target[:, 1], label=target_name)

enumerate()関数は、リストや配列などの要素を取り出して、そのインデックスと要素をタプル('setosa’, 'versicolor’, 'virginica’)として返す組み込み関数です。target_namesは、irisデータセットに含まれるアヤメの品種の名前が格納された配列です。この配列をenumerate()関数で処理することで、各品種のインデックス(0, 1, 2)と名前('setosa’, 'versicolor’, 'virginica’)を取り出すことができます。

X_pcaは、主成分分析の結果得られた2次元の座標を持つ配列です。この配列のうち、y配列(irisデータセットのラベル(花の種類 0, 1, 2))と同じ品種のデータのみを取り出し、X_pca_targetに格納しています。

最後に、plt.scatter()関数を呼び出して、2次元座標をプロットします。X_pca_target[:, 0]とX_pca_target[:, 1]は、それぞれX軸とY軸に対応する座標を表します。

X_pca_target[:, 0] は、NumPy配列 X_pca_target の全行に対して、2番目の軸(列)のインデックスが 0 の要素を取り出した配列を取得する表記法です。コロン : は、全行(全要素)を選択するために使用されます。したがって、[:, 0] は、NumPy配列 X_pca_target の全行に対して、2番目の軸のインデックスが 0 の要素を取り出した1次元配列を返します。この場合、[:, 0] は、PCAによって2次元に圧縮されたデータ X_pca_target の第1主成分 (PC1) を取り出すことになります。

X_pca_target[:, 0] は、PCAによって2次元に圧縮されたデータ X_pca_target の第2主成分 (PC2) を取り出します。

label引数には、target_name変数に格納されている品種名を指定して、凡例を表示するよう指示しています。plt.scatter()関数は、指定された座標をプロットし、点の色や形状などのスタイルを指定することができます。しかし、このプログラムでは、スタイルの指定は行われていません。

plt.xlabel('PC1')
plt.ylabel('PC2')
plt.title('Iris dataset after PCA')
plt.legend()
plt.show()

x軸のラベルをPC1に設定します。

y軸のラベルをPC2に設定します。

title()関数を使って、図にタイトルを設定します。

legend()関数を使って、各ターゲットのラベルをプロットに表示します。

legend()関数は、グラフに凡例を追加するためのmatplotlibの関数です。凡例は、グラフ上に、各要素が何を表しているかを示すためのラベルです。legend()関数は、事前に各要素にラベルを割り当てておく必要があり、scatter関数でlabelパラメータには、花の種類の名前(setosa, versicolor, virginica)を設定しています。

最後に、show()関数を使って、図を表示します。