高性能なCPUやGPUが利用できるようになり、機械学習や深層学習モデルを用いて、あらゆる回帰、分類、クラスタリングなどの問題を解決することがかなり可能になった。しかし、そのようなモデルを開発する際に、性能のボトルネックとなる様々な要因がまだ存在します。データセットに含まれる大量の特徴は、機械学習モデルの精度と同様に、学習時間にも影響を与える要因の1つです。データセットに含まれる膨大な数の素性に対処するためには、様々な選択肢がある。
- 1.元の素性数でモデルを学習させる。素性数が多すぎると数日から数週間かかる。
- 2.相関のある変数を結合して、変数の数を減らす。
- 3.データセットから、出力の最大分散の原因となる最も重要な特徴を抽出する。この目的のために、線形判別分析、因子分析、主成分分析など、さまざまな統計的手法が使用される。
この記事では、PythonのScikit-Learnライブラリを使用して主成分分析を実装する方法を紹介します。
主成分分析
主成分分析(PCA)は、データセットに関する最大の情報を捕らえる最も重要な特徴を選択することによって、高次元のデータを低次元のデータに変換する統計手法である。特徴は、その特徴が出力に与える分散に基づいて選択される。最も大きな分散を引き起こす特徴は、第一主成分である。2番目に大きな分散を引き起こす特徴は第2主成分とみなされ、以下同様である。ここで重要なことは、主成分は互いに相関がないことである。
PCAのメリット
PCAによる次元削減の利点は主に2つある。
- 少ない特徴数でアルゴリズムの学習時間が大幅に短縮される。
-
- 高次元のデータを分析することは必ずしも可能ではない。例えば、あるデータセットに100の特徴がある場合。データを可視化するために必要な散布図の総数は「100(100-1)2 = 4950」である。このようにデータを分析することは現実的には不可能である。
特徴量の正規化
PCAを適用する前に、特徴セットを正規化する必要があることに言及しておく必要があります。例えば、キログラム、光年、百万単位で表現されたデータを持つ特徴セットは、学習セットにおいて分散規模が大きくなっています。このような特徴量セットにPCAを適用すると、分散が大きい特徴量の負荷も大きくなります。したがって、主成分は分散の大きい特徴に偏ってしまい、誤った結果を導くことになります。
最後に、コーディングを始める前に覚えておいていただきたいのは、PCAは統計的手法であり、数値データのみに適用できるということです。したがって、PCAを適用する前に、カテゴリ的特徴を数値的特徴に変換することが必要です。
Scikit-LearnによるPCAの実装
このセクションでは、PythonのScikit-Learnライブラリの助けを借りて、PCAを実装します。まずライブラリとデータセットをインポートし、探索的なデータ解析と前処理を行い、最後にモデルを学習し、予測を行い、精度を評価するという古典的な機械学習パイプラインに従います。唯一の追加ステップは、モデルを学習する前に、最適な特徴数を見つけるためにPCAを実行することである。これらのステップは、以下のように実装されています。
ライブラリのインポート
import numpy as np
import pandas as pd
データセットのインポート
この記事で使用するデータセットは、有名なIrisデータセットです。Irisデータセットに関するいくつかの追加情報は、以下のサイトにあります。
このデータセットは、アイリスの150レコードからなり、4つの特徴を持ちます。sepal-length’, ‘sepal-width’, ‘petal-length’, and ‘petal-width’. 特徴量は全て数値である。レコードは’Iris-setosa’, ‘Iris-versicolor’, ‘Iris-verginica’の3つのクラスのいずれかに分類され、そのうちの1つである。
以下のスクリプトを実行し、pandas
を用いてデータセットをダウンロードする。
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)
では、どのようなデータセットになるか見てみましょう。
dataset.head()
上記のコマンドを実行すると、データセットの最初の5行が以下のように表示されます。
| | sepal-length | sepal-width | petal-length | petal-width | Class
| 0| 5.1| 3.5| 1.4| 0.2| アイリスセトサ
| 1|4.9|3.0|1.4|0.2| アイリス・セトサ
| 2|4.7|3.2|1.3|0.2|アイリス・セトサ
| 3|4.6|3.1|1.5|0.2| アイリスセトサ
| 4|5.0|3.6|1.4|0.2|アイリスセトーサ||||||etc.
前処理
最初の前処理は、データセットを特徴セットとそれに対応するラベルに分割することである。以下のスクリプトがこのタスクを実行する。
X = dataset.drop('Class', 1)
y = dataset['Class']
上記のスクリプトは、特徴セットを変数 X
に、対応するラベルの系列を変数 y
に格納する。
次の前処理として、データをトレーニングセットとテストセットに分割する。次のスクリプトを実行してください。
# Splitting the dataset into the Training set and Test set
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は正規化された特徴セットで最も良い性能を発揮します。ここでは、標準的なスカラー正規化を行って、特徴セットを正規化します。これを行うには、以下のコードを実行します。
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
PCAの適用
PythonのScikit-Learnライブラリを用いてPCAを行うには、わずか3行のコードで済みます。このために、PCA
クラスを使用します。PCAは特徴セットのみに依存し、ラベルデータには依存しません。したがって、PCAは教師なし機械学習の手法と考えることができます。
Scikit-Learnを用いたPCAの実行は、2つのステップで行われます。
-
- コンストラクタに成分の数を渡して
PCA
クラスを初期化する。
- コンストラクタに成分の数を渡して
-
- 特徴セットを渡して
fit
メソッドとtransform
メソッドを呼び出す。transform` メソッドは、指定された数の主成分を返します。
- 特徴セットを渡して
次のコードを見てください。
from sklearn.decomposition import PCA
pca = PCA()
X_train = pca.fit_transform(X_train)
X_test = pca.transform(X_test)
上のコードでは、pca
という名前の PCA
オブジェクトを生成しています。コンストラクタで成分数を指定していません。したがって、トレーニングセットとテストセットの両方について、特徴セット内の4つの特徴すべてが返されます。
PCAクラスには explained_variance_ratio_
があり、各主成分による分散を返します。以下のコードを実行すると、「説明される分散比」が求められます。
explained_variance = pca.explained_variance_ratio_
変数 explained_variance
は float 型の配列になり、各主成分の分散比が格納されます。変数 explained_variance
の値は以下のようになります。
| — |
| 0.722265 |
| 0.239748 |
| 0.0333812 |
| 0.0046056 |
第1主成分は、72.22%の分散を引き起こしていることがわかります。同様に、第2主成分は、データ集合の23.9%の分散を引き起こします。まとめて言うと、特徴セットに含まれる分類情報の (72.22 + 23.9) 96.21%は、最初の2つの主成分によって捕捉されていることがわかります。
まず、1つの主成分を使って、アルゴリズムを学習してみましょう。そのために、以下のコードを実行します。
from sklearn.decomposition import PCA
pca = PCA(n_components=1)
X_train = pca.fit_transform(X_train)
X_test = pca.transform(X_test)
残りの処理は簡単です。
学習と予測
今回はランダムフォレスト分類を使用して予測を行います。
from sklearn.ensemble import RandomForestClassifier
classifier = RandomForestClassifier(max_depth=2, random_state=0)
classifier.fit(X_train, y_train)
# Predicting the Test set results
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' + accuracy_score(y_test, y_pred))
上のスクリプトの出力は次のようになります。
[[11 0 0]
[ 0 12 1]
[ 0 1 5]]
0.933333333333
出力からわかるように、1つの特徴量だけで、ランダムフォレストアルゴリズムは30インスタンス中28インスタンスを正しく予測することができ、93.33%の精度となりました。
2主成分と3主成分による結果
次に、2つの主成分を用いた場合のランダムフォレストアルゴリズムの分類性能を評価してみましょう。このコードを更新してください。
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X_train = pca.fit_transform(X_train)
X_test = pca.transform(X_test)
ここでは、PCAの成分数を2つに設定しています。2成分での分類結果は以下のようになります。
[[11 0 0]
[ 0 10 3]
[ 0 2 4]]
0.833333333333
2つの主成分で、分類精度は、1つの成分の場合の93.33%に比べ、83.33%に低下します。
3つの主成分では、結果は以下のようになります。
[[11 0 0]
[ 0 12 1]
[ 0 1 5]]
0.933333333333
3つの主成分で、分類精度は再び93.33%に増加します。
フルフィーチャーセットでの結果
フルフィーチャーセットでの結果を求めてみましょう。そのためには、上で書いたスクリプトからPCAの部分を削除するだけです。PCAを適用しないフルフィーチャーセットでの結果は以下のようになります。
[[11 0 0]
[ 0 13 0]
[ 0 2 4]]
0.933333333333
ランダムフォレストアルゴリズムの精度は93.33%です。
ディスカッション
上記の実験から、データセットの特徴数を大幅に削減しながら、最適なレベルの精度を達成することができました。主成分1つで達成された精度は、特徴セットで達成された精度(93.33%)と同じであることがわかります。また、分類器の精度は、主成分の数を増やしても必ずしも向上しないことも言及する必要があります。この結果から、1つの主成分で達成された精度(93.33%)は、2つの主成分で達成された精度(83.33%)より高いことがわかります。
特徴セットに保持する主成分の数は、記憶容量、学習時間、性能など、いくつかの条件に依存する。データセットによっては、すべての特徴が全体の分散に等しく寄与しているため、すべての主成分が予測に重要であり、どれも無視することはできない。一般的な経験則では、有意な分散に寄与する主成分の数を取り、分散リターンが逓減するものは無視することになります。良い方法は、次のグラフに示すように、主成分に対して分散をプロットし、値が減少している主成分を無視することです。
例えば、上のグラフでは、第3主成分以降、分散の変化がほとんどなくなっていることがわかります。したがって、最初の3つの成分を選択することができます。
さらに上を目指す – 手作りのEnd to Endプロジェクト
好奇心旺盛なあなたは、もっと先を目指したいと思っていませんか?そんなあなたには、ガイド付きプロジェクトがおすすめです。「ハンズオン住宅価格予測 – Pythonによる機械学習” をご覧ください。
をご覧ください。
このプロジェクトでは、Scikit-LearnとKerasのモデルから住宅価格を予測するために、従来の機械学習モデルや深層学習モデル、アンサンブル学習、メタラーを利用した強力な構築方法を学ぶことができます。
>
>
>
Tensorflowの上に構築された深層学習APIであるKerasを使って、アーキテクチャを試し、積み重ねたモデルのアンサンブルを構築し、メタラーナーのニューラルネットワーク(レベル1モデル)を訓練して、家の価格を割り出すことにします。
ディープラーニングは素晴らしいものですが、それに頼る前に、浅い学習アルゴリズムのような、より単純な技術で問題を解決することも試みることをお勧めします。ベースラインの性能は、ランダムフォレスト回帰アルゴリズムに基づくものです。さらに、Scikit-Learnを使用して、バギングや投票などの手法により、モデルのアンサンブルを作成することも検討します。
これはエンドツーエンドのプロジェクトであり、他の機械学習プロジェクトと同様に、探索的データ分析から始まり、データ前処理を経て、最後に浅い学習と深い学習のモデルを構築して、以前に探索しクリーニングしたデータに適合させることになります。