分類のための線形判別分析

Beginner

This tutorial is from open-source community. Access the source code

はじめに

この実験では、線形判別分析(LDA:Linear Discriminant Analysis)とそれを分類にどのように使用できるかを紹介します。Python の人気のある機械学習ライブラリである scikit - learn を使用して LDA を実装します。また、共分散の Ledoit - Wolf 推定器とオラクル収縮近似(OAS:Oracle Shrinkage Approximating)推定器が分類をどのように改善できるかを検討します。

VM のヒント

VM の起動が完了した後、左上隅をクリックしてノートブックタブに切り替え、Jupyter Notebook を使って練習しましょう。

時々、Jupyter Notebook が読み込み終了するまで数秒待つ必要がある場合があります。Jupyter Notebook の制限により、操作の検証を自動化することはできません。

学習中に問題に直面した場合は、Labby にお問い合わせください。セッション後にフィードバックを提供してください。すぐに問題を解決いたします。

ランダムなデータを生成する

まず、識別的な特徴とノイズのある特徴を持つランダムなデータを生成する必要があります。識別的な特徴 1 つで 2 つのクラスターのデータを生成するために、scikit - learn のmake_blobs関数を使用します。その後、他の特徴にランダムなノイズを追加します。

import numpy as np
from sklearn.datasets import make_blobs

def generate_data(n_samples, n_features):
    """ノイズのある特徴を持つランダムなブロブ状のデータを生成する。

    これは形状`(n_samples, n_features)`の入力データの配列と
    `n_samples` のターゲットラベルの配列を返す。

    識別的な情報を含むのは 1 つの特徴だけで、他の特徴はノイズのみを含む。
    """
    X, y = make_blobs(n_samples=n_samples, n_features=1, centers=[[-2], [2]])

    ## 識別的でない特徴を追加する
    if n_features > 1:
        X = np.hstack([X, np.random.randn(n_samples, n_features - 1)])
    return X, y

LDA を実装する

次に、scikit - learn のLinearDiscriminantAnalysisクラスを使用して LDA を実装します。3 つの分類器を作成します。

  • 収縮なしの LDA
  • Ledoit - Wolf 収縮を伴う LDA
  • OAS 収縮を伴う LDA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.covariance import OAS

clf1 = LinearDiscriminantAnalysis(solver="lsqr", shrinkage=None)
clf2 = LinearDiscriminantAnalysis(solver="lsqr", shrinkage="auto")
oa = OAS(store_precision=False, assume_centered=False)
clf3 = LinearDiscriminantAnalysis(solver="lsqr", covariance_estimator=oa)

分類器を学習と評価する

生成したデータで各分類器の性能を確認するため、それぞれの分類器を学習と評価します。このプロセスを複数回繰り返して平均的な正解率を得ます。

n_train = 20  ## 学習用のサンプル数
n_test = 200  ## 評価用のサンプル数
n_averages = 50  ## 分類を繰り返す回数
n_features_max = 75  ## 最大の特徴数
step = 4  ## 計算の刻み幅

acc_clf1, acc_clf2, acc_clf3 = [], [], []
n_features_range = range(1, n_features_max + 1, step)

for n_features in n_features_range:
    score_clf1, score_clf2, score_clf3 = 0, 0, 0
    for _ in range(n_averages):
        X, y = generate_data(n_train, n_features)

        clf1.fit(X, y)
        clf2.fit(X, y)
        clf3.fit(X, y)

        X, y = generate_data(n_test, n_features)
        score_clf1 += clf1.score(X, y)
        score_clf2 += clf2.score(X, y)
        score_clf3 += clf3.score(X, y)

    acc_clf1.append(score_clf1 / n_averages)
    acc_clf2.append(score_clf2 / n_averages)
    acc_clf3.append(score_clf3 / n_averages)

結果を可視化する

最後に、各分類器の分類精度を特徴数の関数としてプロットします。このプロットを作成するために matplotlib を使用します。

import matplotlib.pyplot as plt

features_samples_ratio = np.array(n_features_range) / n_train

plt.plot(
    features_samples_ratio,
    acc_clf1,
    linewidth=2,
    label="LDA",
    color="gold",
    linestyle="solid",
)
plt.plot(
    features_samples_ratio,
    acc_clf2,
    linewidth=2,
    label="LDA with Ledoit Wolf",
    color="navy",
    linestyle="dashed",
)
plt.plot(
    features_samples_ratio,
    acc_clf3,
    linewidth=2,
    label="LDA with OAS",
    color="red",
    linestyle="dotted",
)

plt.xlabel("n_features / n_samples")
plt.ylabel("Classification accuracy")

plt.legend(loc="lower left")
plt.ylim((0.65, 1.0))
plt.suptitle(
    "LDA (Linear Discriminant Analysis) vs. "
    + "\n"
    + "LDA with Ledoit Wolf vs. "
    + "\n"
    + "LDA with OAS (1 discriminative feature)"
)
plt.show()

まとめ

この実験では、scikit - learn を使って線形判別分析(LDA:Linear Discriminant Analysis)を実装する方法を学びました。共分散の Ledoit - Wolf 推定器とオラクル収縮近似(OAS:Oracle Shrinkage Approximating)推定器が分類精度をどのように向上させるかを検討しました。また、識別的な特徴を持つランダムなデータを生成し、このデータで分類器をテストしました。最後に、分類精度を特徴数の関数として可視化しました。