前回の記事「PythonでScikit-Learnを使ったPCAの実装」では、PCAを使って特徴セットの次元を減らす方法について検討しました。今回は、もう一つの非常に重要な次元削減手法である線形判別分析(またはLDA)について学びます。しかし、その前にPCAとLDAがどのように異なるかを簡単に説明します。
PCAとLDAの比較。何が違うのか?
PCAとLDAはどちらも線形変換技術である。しかし、PCAは教師なし、LDAは教師ありの次元削減手法である。
PCAはクラスラベルを気にしません。簡単に言えば、PCAは出力に依存せずに特徴セットを要約する。PCAはデータセット中の分散が最大となる方向を探そうとする.大規模な特徴セットでは、他の特徴と単に重複していたり、他の特徴と高い相関を持っていたりする特徴が多く存在する。このような特徴は基本的に冗長であり、無視することができる。PCAの役割は、このような相関の高い特徴や重複する特徴を見つけ、特徴間の相関が最小となるような新しい特徴セット、言い換えれば特徴間の分散が最大となる特徴セットを考え出すことである。特徴間の分散は出力に依存しないため、PCAでは出力ラベルは考慮されない。
LDAはPCAと異なり、出力クラスを識別する情報を保持したまま、特徴量の次元を削減しようとする。LDAはクラスの各クラスタの周囲に決定境界を見つけようとする。そして、クラスタが互いにできるだけ分離し、クラスタ内の個々の要素がクラスタのセントロイドにできるだけ近くなるように、データ点を新しい次元に投影する。新しい次元は、クラスタ間の距離を最大化し、クラスタ内のデータ点とそのセントロイド間の距離を最小化する能力に基づいてランク付けされる。これらの新しい次元は、特徴量セットの線形識別器を形成する。
それでは、PythonのScikit-Learnを使ってLDAを実装する方法を見てみましょう。
Scikit-LearnでLDAを実装する。
PCAと同様に、Scikit-Learnライブラリには、データセットに対してLDAを実行するためのビルトインクラスが含まれています。PCAの記事で同じデータセットを使用したことと、LDAの結果をPCAと比較したいので、このセクションではIrisデータセットに対してLDAを適用することにします。Irisデータセットに関する情報は、以下のリンクから入手可能です。
残りの部分は、従来の機械学習パイプラインに従います。
ライブラリのインポート
import numpy as np
import pandas as pd
データセットのインポート
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'Class']
dataset = pd.read_csv(url, names=names)
データ前処理
データセットをpandasのデータフレームオブジェクトにロードしたら、まずデータセットを特徴とそれに対応するラベルに分割し、その結果得られたデータセットをトレーニングセットとテストセットに分割します。以下のコードでは、データをラベルと特徴量に分割しています。
X = dataset.iloc[:, 0:4].values
y = dataset.iloc[:, 4].values
このスクリプトでは、データセットの最初の4列、つまり特徴セットを変数 X
に代入し、5列目の値(ラベル)を変数 y
に代入しています。
次のコードはデータをトレーニングセットとテストセットに分割する。
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
機能拡張
PCAと同様に、LDAでも特徴量のスケーリングを行う必要があります。以下のスクリプトを実行してください。
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
LDAの実行
Scikit-LearnでLDAを行うには、たった4行のコードしか必要ありません。PythonでLDAを行うには、sklearn.discriminant_analysis
ライブラリの LinearDiscriminantAnalysis
クラスを使用します。以下のスクリプトを参照してください。
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
lda = LDA(n_components=1)
X_train = lda.fit_transform(X_train, y_train)
X_test = lda.transform(X_test)
上のスクリプトでは、LinearDiscriminantAnalysis
クラスが LDA
としてインポートされています。PCAと同様に、LDAのパラメータ n_components
に、取得したい線形識別子の数を渡す必要があります。この場合、まず1つの線形判別式で分類器の性能を確認したいので、 n_components
を 1 に設定します。最後に、実際に線形識別器を取得するために、 fit
と transform
メソッドを実行します。
LDA の場合、 transform
メソッドは、 X_train
と y_train
の2つのパラメータをとります。しかし、PCAの場合、 transform
メソッドは1つのパラメータ、すなわち X_train
しか必要としません。これは、LDA が線形識別器を選択する際に、出力クラスラベルを考慮するのに対し、PCA は出力ラベルに依存しないという事実を反映している。
学習と予測
線形判別が1つのLDAの性能と、主成分が1つのPCAの性能を比較したいので、PCA削減アルゴリズムの性能評価に使用したのと同じRandom Forest分類器を使用することにします。
以下のコードを実行します。
from sklearn.ensemble import RandomForestClassifier
classifier = RandomForestClassifier(max_depth=2, random_state=0)
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)
パフォーマンスを評価する
いつものように、最後のステップは、混同行列の助けを借りてアルゴリズムの性能を評価し、予測の精度を見つけることです。以下のスクリプトを実行します。
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
cm = confusion_matrix(y_test, y_pred)
print(cm)
print('Accuracy' + str(accuracy_score(y_test, y_pred)))
上のスクリプトの出力は次のようである。
[[11 0 0]
[ 0 13 0]
[ 0 0 6]]
Accuracy 1.0
1つの線形判別で、アルゴリズムは100%の精度を達成し、1つの主成分で達成した精度(93.33%)より大きいことがわかります。
PCAとLDAの比較。次元削減のために何を選ぶか?
一様に分布するデータの場合、LDAはPCAよりも常に優れたパフォーマンスを発揮します。しかし、データが高度に歪んでいる(不規則に分布している)場合、LDAは多数派のクラスに偏る可能性があるので、PCAを使うことが推奨されます。
最後に、PCAは出力ラベルに依存しないため、ラベル付きデータだけでなくラベルなしデータにも適用できることが利点です。一方、LDAは線形識別関数を求めるために出力クラスを必要とするため、ラベル付きデータを必要とします。
さらに上を目指す – 手作りのEnd to Endプロジェクト
好奇心旺盛なあなたは、もっと先を目指したいと思っていませんか?そんなあなたには、ガイド付きプロジェクトがおすすめです。「ハンズオン住宅価格予測 – Pythonによる機械学習” をご覧ください。
をご覧ください。
このプロジェクトでは、Scikit-LearnとKerasのモデルから住宅価格を予測するために、従来の機械学習モデルや深層学習モデル、アンサンブル学習、メタラーを利用した強力な構築方法を学ぶことができます。
>
>
>
Tensorflowの上に構築された深層学習APIであるKerasを使って、アーキテクチャを試し、積み重ねたモデルのアンサンブルを構築し、メタラーナーのニューラルネットワーク(レベル1モデル)を訓練して、家の価格を割り出すことにします。
ディープラーニングは素晴らしいものですが、それに頼る前に、浅い学習アルゴリズムのような、より単純な技術で問題を解決することも試みることをお勧めします。ベースラインの性能は、ランダムフォレスト回帰アルゴリズムに基づくものです。さらに、Scikit-Learnを使用して、バギングや投票などの手法により、モデルのアンサンブルを作成することも検討します。
これはエンドツーエンドのプロジェクトであり、他の機械学習プロジェクトと同様に、探索的データ分析から始まり、データ前処理を経て、最後に浅い学習と深い学習のモデルを構築して、以前に探索しクリーニングしたデータに適合させることになります。