線形代数(主成分分析)

2023/12/2
執筆者:小澤昌樹

※本記事は吉政創成株式会社「Python学習とキャリアアップ」より寄稿されたコラムとなります。

線形代数(主成分分析)

こんにちは、小澤です。

前回、データ値のばらつきと相関関係を表す分散共分散をNumPyライブラリを使って求めてみました。数学的なアプローチを中心に話題を展開しましたが、数学的な厳密な理解にこだわる必要はありません。データ分析には数学的なアプローチが深く関与しており、それをPythonを使って解決できるということが分かることが重要です。

さて、せっかく分散共分散を求めたので、引き続き、主成分分析の計算までしてみます。『Pythonによるあたらしいデータ分析の教科書(第2版)』では、scikit-learnを使った方法が249ページに掲載されていますが、今回も数学的な要素があるということを理解することが目的ですので、NumPyを使って計算してみます。scikit-learnを使った方法については、別の機会に解説しますので、それまでお待ちください。

主成分分析

主成分分析(Principal Component Analysis; PCA)は、多次元データをシンプルにする手法です。データが複雑すぎる場合、PCAは情報を整理しやすくし、データ内の規則や関係を見つけ出し、新しい「主成分」と呼ばれるものに変換します。主成分は、データの特徴を最もよく表す軸や属性です。PCAを使うと、データの次元を削減し、データを理解しやすくすることができます。また、不要な情報やノイズを取り除くこともできます。そのため、データの整理や簡略化、可視化、機械学習モデルのトレーニングなど、さまざまなデータ分析の場面で有用な手法です。

主成分分析を進めるステップは以下の通りです。

  1. 標準化
    最初にデータを標準化(平均を0、分散を1にする)します。
  2. 共分散行列の計算
    次に、共分散行列を計算します。この行列には特徴間の関連性が表れます。
  3. 固有値と固有ベクトルの計算
    共分散行列の固有値と固有ベクトルを計算します。固有ベクトルは新しい軸(主成分)の向きを示し、固有値はその主成分に含まれる情報の量を表します。
  4. 主成分の選択
    固有値が大きい順に固有ベクトルを並べ替え、最も情報を含む固有ベクトル(主成分)を選択します。
  5. データの射影
    選択した主成分にデータを射影します。これにより、元のデータの次元が削減されます。

NumPyで主成分分析

相関のあるデータセットとして、前回と同様に、数学、英語、国語の試験結果を示すデータセットを使用します。以下のようなデータセットがあるとします。

数学 英語 国語
100 65 65
45 60 95
70 65 40
70 80 80
75 90 70

まずは、NumPyをインポートします。

import numpy as np

データを準備します。array関数を使って、2次元配列のデータとして定義します。

data = np.array([[100, 65, 65],
    [45, 60, 95],
    [70, 65, 40],
    [70, 80, 80],
     [75, 90, 70]])

まずは、データの平均値を求めます。

mean = np.mean(data, axis=0)

データを求めた平均値で中心化します。これは、データの平均値を引くことで、データの中心が原点になるように調整する処理です。

centered_data = data - mean

cov関数を使って、共分散行列を求めます。共分散行列については前回をご覧ください。

cov_matrix = np.cov(centered_data, rowvar=False)

共分散行列の固有値と固有ベクトルを計算します。

eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)

求めた固有値を大きい順にソートします。

sorted_indices = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[sorted_indices]
eigenvectors = eigenvectors[:, sorted_indices]

主成分スコアを計算します。dot関数は、ベクトルや行列のドット積(内積)を計算するために使用される関数です。

principal_components = np.dot(centered_data, eigenvectors)

print文を使って結果を出力します。

print("主成分スコア:")
print(principal_components)
print("固有値:")
print(eigenvalues)
print("固有ベクトル:")
print(eigenvectors)

結果は、次のように出力されます。

主成分スコア:
[[-22.32612096 -10.89609244 -15.51835986]
[ 37.35687394 7.00628967 -7.30587943]
[-20.07556927 23.20770311 3.37254129]
[ 8.1712493 -8.80612722 4.86649857]
[ -3.12643302 -10.51177312 14.58519943]]

固有値:
[593.39102193 223.61391499 135.49506309]

固有ベクトル:
[[-0.68223885 -0.62004066 -0.38742705]
[-0.05998425 -0.48064729 0.87486003]
[ 0.72866456 -0.62010303 -0.29072358]]

出力された値から、次のような考察が得られます。

  • 主成分スコアは、データの主成分に射影された各データポイントの値を示しています。例えば、データポイント1は、第1主成分に対して-22.33、第2主成分に対して-10.90、第3主成分に対して-15.52のスコアを持っています。これらの値は、データポイントが各主成分にどれだけ影響されているかを示しています。
  • 主成分スコアの絶対値が大きいほど、対応する主成分がデータポイントに大きな影響を与えていることを示し、その主成分がデータの変動に対して重要であることを示します。データポイント1の場合、第1主成分に対して-22.33、第2主成分に対して-10.90、第3主成分に対して-15.52のスコアを持つため、第1主成分がデータポイント1に対して最も強い影響を持っていることがわかります。
  • また、データポイント1に対する第1主成分の影響は-22.33なので、データポイント1は第1主成分の負の方向に引っ張られる傾向があります。つまり、その主成分が減少方向にデータポイントを引っ張る影響を持ちます。

ここから読み取れることとして、数学の成績が第1主成分(最初の列)に最も大きな負の影響を持っており、英語の成績が第2主成分(2番目の列)に少ないが正の影響を持っていることです。国語の成績は、第3主成分(3番目の列)にやや正の影響を持っています。つまり、数学の成績が最も大きな影響を持っており、英語もやや影響していますが、国語の影響は比較的小さいと言えます。

まとめ

今回は、NumPyライブラリを使用して主成分分析の計算を行ってみました。前回の分散共分散行列の計算に続いて、数学的なアプローチが前面に出ていたため、少し難解な部分もあったかもしれませんが、背景に数学的な要素があることを感じていただければ問題ありません。

さて次回は「確率と統計」について取り上げます。確率と統計もデータ分析において非常に重要なスキルであり、数学の一分野になります。深い数学の理論に立ち入る必要はありませんが、基本的な考え方を把握することは、今後のデータ分析に非常に役立つと思います。

次回「確率と統計」を説明して「数学の基礎」の章を一旦終了します。そうしたら、Pythonライブラリを使用したデータ分析に進みたいと思います。引き続きよろしくお願いいたします。

今回のコラムはいかがでしたでしょうか?インターネット・アカデミーは、Python講座が充実しています。Python認定スクールにもなっているため質の高い知識を得ることができ、基礎学習の先にあるそれぞれの目標を目指していくためには良い場所となります。ご興味ある方は各講座のページを覗いてみてください。

Pythonが学べる講座

この記事の執筆者

小澤昌樹

デジタル人材育成・助成金のお役立ち資料をダウンロード

デジタル人材育成や助成金活用のお役立ち資料などをまとめてダウンロードしていただけます。コンサルタントへの無料相談をご希望の方はこちらからお問い合わせください。

たとえばこんな相談ができます
  • DX人材の育成&事例紹介 リスキリングのロードマップ付き
  • デジタル人材育成に使える助成金制度
  • デジタルスキル標準 役割別おすすめ講座
資料ダウンロードはこちら
会社名必須
部署名必須
お名前必須
電話番号必須
メールアドレス必須

個人情報の利用目的についてご同意いただいた場合のみ、「同意して進む」を押してください。

このページの上へ