Scikit-learnのLinearDiscriminantAnalysisで次元削減とクラス分類を実践!

Python

Pythonの機械学習ライブラリScikit-learnは、データサイエンティストやエンジニアにとって必須のツールです。その中に含まれるLinearDiscriminantAnalysis (LDA: 線形判別分析) は、少し複雑に聞こえるかもしれませんが、実は「次元削減」と「クラス分類」という2つの重要なタスクで非常に役立つ、強力なアルゴリズムです。

この記事を読めば、Scikit-learnを使ったLDAの基本的な概念から、具体的な実装方法までをサンプルコード付きで理解できます。

この記事で解決できること

  • LDA(線形判別分析)が何なのかが分かる
  • PCA(主成分分析)との違いが明確になる
  • LDAを使った次元削減とクラス分類のコードが書けるようになる

初心者の方にも分かりやすく解説しますので、ぜひ最後までお付き合いください。


はじめに:LinearDiscriminantAnalysis (LDA) とは?

LDA(線形判別分析)は、教師あり学習に分類されるアルゴリズムです。一言で表すなら、**「データのクラス(グループ)が最もはっきりと分かれるように、データの特徴を要約する手法」**です。

あらかじめ「このデータはこのグループ」という正解ラベルが分かっているデータに対して、そのグループ間の違いを最大化するような新しい軸(特徴)を探します。

LDAの2つの強力な役割:次元削減とクラス分類

LDAの主な役割は以下の2つです。

  1. 次元削減: データの情報をなるべく失わずに、特徴量の数を減らします。特にLDAは**「クラスを分離する」という観点で最適な次元削減**を行います。特徴量を2つや3つに減らすことで、データをグラフにプロットして人間が直感的に理解しやすくなります。
  2. クラス分類: あるデータがどのクラスに属しているかを予測する「分類器」として機能します。新しいデータが入力されたときに、どのクラスに最も近いかを判別します。

このように、LDAはデータの前処理から予測モデルの構築まで、幅広い場面で活躍します。

よく似た手法「主成分分析(PCA)」との決定的な違い

次元削減の手法として非常に有名なものに主成分分析 (PCA) があります。LDAとPCAの最も重要な違いは、正解ラベル(クラス情報)を考慮するかどうかです。

  • PCA (主成分分析)
    • 教師なし学習
    • 目的:データ全体の**ばらつき(分散)**が最も大きくなる方向を探す
    • クラスがどう分かれるかは気にしない
  • LDA (線形判別分析)
    • 教師あり学習
    • 目的:クラス間の分離が最も大きくなる方向を探す
    • クラスをはっきり分けることを最優先する

分類タスクが前提の場合、クラス情報を活用するLDAの方が、分類に有利な次元削減を行えるケースが多くあります。


実践に向けた環境準備

それでは、実際にコードを書いてLDAを動かしてみましょう。

必要なライブラリのインストール

まず、scikit-learnと、結果を可視化するためのmatplotlib, seabornをインストールします。ターミナルやコマンドプロンプトで以下のコマンドを実行してください。

pip install scikit-learn matplotlib seaborn

今回使用する「Irisデータセット」について

今回は、機械学習の入門で頻繁に使われるIris(アヤメ)データセットを使用します。このデータセットには、3種類のアヤメ(Setosa, Versicolour, Virginica)について、以下の4つの特徴量が記録されています。

  • がくの長さ (sepal length)
  • がくの幅 (sepal width)
  • 花びらの長さ (petal length)
  • 花びらの幅 (petal width)

この4次元のデータを、LDAを使って2次元に削減し、どのようにクラスが分離されるかを見ていきます。


【コードで実践】LDAによる次元削減とデータの可視化

最初に、LDAを次元削減の目的で利用し、その結果をグラフで確認するまでの手順を解説します。

ライブラリのインポート

まず、Pythonスクリプトの冒頭で必要なライブラリとモジュールをインポートします。

import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.datasets import load_iris

データを読み込みLDAを適用する (fit_transform)

次に、scikit-learnに組み込まれているIrisデータセットをロードし、LDAを適用します。n_components=2と指定することで、「2つの特徴量(=2次元)に削減してください」と指示します。

# Irisデータセットをロード
iris = load_iris()
X = iris.data
y = iris.target
target_names = iris.target_names

# LDAモデルのインスタンスを作成(2次元へ削減)
lda = LinearDiscriminantAnalysis(n_components=2)

# fit_transformで、データの学習と次元削減を同時に実行
# 教師あり学習なので、X (特徴量) と y (正解ラベル) の両方を渡す
X_r = lda.fit_transform(X, y)

print(f"元のデータの形状: {X.shape}")
print(f"削減後のデータの形状: {X_r.shape}")

実行結果:

元のデータの形状: (150, 4)
削減後のデータの形状: (150, 2)Code language: HTTP (http)

fit_transform(X, y)に、特徴量Xと正解ラベルyの両方を渡しているのがポイントです。LDAはyの情報を使って、クラスが最もよく分かれる2つの軸を見つけ出し、データを変換してくれます。

次元削減した結果をグラフで確認する

4次元から2次元に変換されたデータを、散布図としてプロットしてみましょう。

# 結果をプロット
plt.figure(figsize=(8, 6))
colors = ['navy', 'turquoise', 'darkorange']

for color, i, target_name in zip(colors, [0, 1, 2], target_names):
    plt.scatter(X_r[y == i, 0], X_r[y == i, 1], alpha=.8, color=color,
                label=target_name)

plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.title('LDA of IRIS dataset')
plt.xlabel('LD1') # 第1判別軸
plt.ylabel('LD2') # 第2判別軸
plt.show()

このグラフを見ると、3種類のアヤメが非常にはっきりとグループに分かれていることがわかります。特にSetosa(紺色の点)は他の2種から完全に分離できています。これがクラス分離を目的としたLDAの次元削減の力です。


【コードで実践】LDAをクラス分類器として使う方法

続いて、LDAを純粋なクラス分類器として使う方法を解説します。

訓練データとテストデータに分割する

モデルの性能を客観的に評価するため、データをモデル学習用の「訓練データ」と、性能確認用の「テストデータ」に分けます。

from sklearn.model_selection import train_test_split

# 70%を訓練データ、30%をテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

LDAモデルを学習 (fit) し、予測 (predict) する

訓練データを使ってLDAモデルを学習させ、そのモデルでテストデータのクラスを予測します。

# LDAモデルのインスタンスを作成(分類器として使うのでn_componentsは不要)
clf = LinearDiscriminantAnalysis()

# 訓練データでモデルを学習させる
clf.fit(X_train, y_train)

# テストデータを使い、どのクラスに属するか予測する
y_pred = clf.predict(X_test)

print("予測したクラス:", y_pred)
print("実際の正解クラス:", y_test)

モデルの精度を評価する

最後に、予測結果(y_pred)が実際の正解(y_test)とどれくらい一致しているか、正解率 (Accuracy) を計算して評価します。

from sklearn.metrics import accuracy_score

# 正解率を計算
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy:.2f}')

実行結果:

Accuracy: 0.98Code language: CSS (css)

約98%という非常に高い正解率が得られました。LDAがシンプルながらも強力な分類器であることがわかります。


まとめ:LDAを使いこなしてデータ分析の精度を高めよう

今回は、Scikit-learnLinearDiscriminantAnalysisについて、基本から実践的なコードまでを解説しました。

  • LDAは教師あり学習で、クラスの違いを最大化する目的を持つ。
  • 次元削減では、クラス構造を可視化するのに非常に役立つ。
  • クラス分類では、シンプルで高速、かつ高精度なモデルを構築できる。
  • 分類を前提とするタスクでは、PCAよりもLDAが有効な場合が多い

LDAは、データの前処理とモデリングの両方で頼りになる便利な手法です。ぜひあなたのデータ分析プロジェクトでも活用してみてください。

コメント

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