【Python初心者】主成分分析(次元削減)をいろんな学習モデルで実行し特徴を理解する

スポンサーリンク
Python
【超初心者】Pythonおすすめ書籍
Pythonはプログラミング言語の中でも、1位2位を争う人気言語です。 その理由は 初心者でも学習しやすい(コードが理解しやすい) 業務の自動化ができる データ分析ができる 機械学習やA...
【おすすめ】Pythonの独学で必要な書籍
わたしは、底辺サラリーマンで、Pyhton学習歴は半年、R(フリーの統計解析ソフト)学習歴半年、学習方法は独学です。 ここでの独学とは、体系的な学習カリキュラムがなく、強制力がない学習方法のことを指します。...

機械学習にはさまざまな問題があります。その一つに次元の呪いというものがあります。次元の呪いとは、特徴量の数が多くなりすぎて(数千以上)、訓練時間が遅くなったり、学習結果が悪くなってしまう問題のことです。
数が多い特徴量の中には、結果と関係のないものも多くあります。
次元削減とは、結果に関係する情報を失わずに、特徴量の数を減らすことです。次元削減により、結果を分かりやすくしたり、学習時間を短縮したりすることができます。
今回は、次元削減でよく用いられる、主成分分析(PCA:principal component analysis)をいろんな学習モデルで実行し、特徴を理解していきましょう。

Pythonの環境構築はAnacondaからJupyter Labを使っています。以下の記事を参照して下さい。

【2021年最新】M1 mac でanacondaをインストールする方法

【2021年最新】WindowsでAnacondaをインストールする方法

必要なライブラリをインポート

import numpy as np
import warnings
warnings.filterwarnings('ignore')
from sklearn.datasets import fetch_openml
from sklearn.metrics import accuracy_score
mnist = fetch_openml('mnist_784',version=1)
mnist.target = mnist.target.astype(np.uint8)

MNISTの手書き文字のデータを使って確認していきましょう。

【初心者】はじめての深層学習による手書き文字認識(MNIST)

はじめての手書き文字認識

データを読み込む

from sklearn.model_selection import train_test_split

X = mnist["data"]
y = mnist["target"]

X_train, X_test, y_train, y_test = train_test_split(X, y)

手書き文字のデータを読み込み、学習に用いる訓練データと、結果の評価に用いるテストデータに分割しました。

主成分分析

from sklearn.decomposition import PCA

pca = PCA(n_components=0.95)              # 特徴量の成分を95%まで削減する
X_train_pca = pca.fit_transform(X_train)  # 訓練データに適応させる
X_test_pca = pca.transform(X_test)        # テストデータに適応させる

これで、特徴量の情報の95%を保持した特徴量が作成されます。

では、95%の情報を持った特徴量の個数を確認してみましょう。

print("もとの訓練データ",X_train.shape[1])          # もとの特徴量の数
print("次元削減後の訓練データ",X_train_pca.shape[1]) # 次元削減後の特徴量の数

出力:
もとの訓練データ 784
次元削減後の訓練データ 154

もとの特徴量の数が784であったのに対して、次元削減後は154と大幅に少なくなっています。

では、いろんな機械学習モデルで次元削減前後の性能を確認してみましょう。

PCスペック

今回使用するPC性能は、CPU:corei 5-8250U、メモリ:8GBです。ごくごく一般的なスペックですね。

ランダムフォレスト

学習器のインスタンスを作成

from sklearn.ensemble import RandomForestClassifier

rnd_clf = RandomForestClassifier(n_estimators=100)

学習を実行(もとのデータ)

%%timeで、実行時間を計測できます。正確ではないみたいですが、概算になりますし、簡単なので、%%timeを使用します。

%%time
rnd_clf.fit(X_train, y_train)

出力:
Wall time: 37.1 s

学習に使った時間は、37.1秒でした。まあまあ時間がかかりますね。

予測と正解率を計算する(もとのデータ)

%%time
y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)

出力:
Wall time: 766 ms
0.9662857142857143

予測と正解率の計算には1秒もかかっていませんでした。

学習を実行(次元削減後のデータ)

%%time
rnd_clf.fit(X_train_pca, y_train)

出力:
Wall time: 1min 23s

なぜか次元削減後の方が時間がかかってしまいました。(前:37秒 → 後:1分23秒)

特徴量の数が少なくなったのに、時間がかかるようになることもあるみたいです。

予測と正解率を計算する(次元削減後のデータ)

%%time
y_pred = rnd_clf.predict(X_test_pca)
accuracy_score(y_test, y_pred)

出力:
Wall time: 539 ms
0.9436

正解率は、0.966から0.944へと悪くなりました。特徴量が情報の95%になったため、失われる情報もあります。なので、正解率は悪くなることが多いです。

総合すると、ランダムフォレストでは失敗ですね。次元削減しない方がいいかもしれません。

ロジスティック回帰

学習器のインスタンスを作成

from sklearn.linear_model import LogisticRegression

log_clf = LogisticRegression(multi_class="multinomial", solver="lbfgs")

学習を実行(もとのデータ)

%%time
log_clf.fit(X_train, y_train)

出力:
Wall time: 13.3 s

予測と正解率を計算する(もとのデータ)

%%time
y_pred = log_clf.predict(X_test)
accuracy_score(y_test, y_pred)

出力:
Wall time: 67.8 ms
0.9204571428571429

学習を実行(次元削減後のデータ)

%%time
log_clf.fit(X_train_pca, y_train)

出力:
Wall time: 5.4 s

学習時間は、13秒から5秒へと短縮されました。

予測と正解率を計算する(次元削減後のデータ)

%%time
y_pred = log_clf.predict(X_test_pca)
accuracy_score(y_test, y_pred)

出力:
Wall time: 11.3 ms
0.9174285714285715

ロジスティック回帰分析では、学習時間の短縮と正解率の維持ができており、次元削減の成功例と言えるでしょう。

K最近傍法

学習器のインスタンスを作成

from sklearn.neighbors import KNeighborsClassifier

knn_clf = KNeighborsClassifier(n_neighbors=3)

学習を実行(もとのデータ)

%%time

knn_clf.fit(X_train, y_train)

出力:
Wall time: 44 s

予測と正解率を計算する(もとのデータ)

%%time

y_pred = knn_clf.predict(X_test)
accuracy_score(y_test, y_pred)

出力:
Wall time: 4min 43s
0.9694285714285714

学習を実行(次元削減後のデータ)

%%time
knn_clf.fit(X_train_pca, y_train)

出力:
Wall time: 2.87 s

学習時間は44秒から3秒へと短縮できました。

予測と正解率を計算する(次元削減後のデータ)

%%time

y_pred = knn_clf.predict(X_test_pca)
accuracy_score(y_test, y_pred)

出力:
Wall time: 50.7 s
0.9721142857142857

時間が4分43秒から51秒と大幅に短縮しています。

k最近傍法では学習時間の短縮と、さらに正解率の向上まですることができました。大成功ですね。

サポートベクタマシン

学習器のインスタンスを作成

from sklearn.svm import SVC

svm = SVC()

学習を実行(もとのデータ)

%%time

svm.fit(X_train, y_train)

出力:
Wall time: 5min 52s

予測と正解率を計算する(もとのデータ)

%%time

y_pred = svm.predict(X_test)
accuracy_score(y_test, y_pred)

出力:
Wall time: 3min 26s
0.9778857142857142

学習を実行(次元削減後のデータ)

%%time
svm.fit(X_train_pca, y_train)

出力:
Wall time: 1min 32s

学習時間は次元削減により5分52秒から1分32秒へと短縮しました。

予測と正解率を計算する(次元削減後のデータ)

%%time

y_pred = svm.predict(X_test_pca)
accuracy_score(y_test, y_pred)

出力:
Wall time: 41.7 s
0.9813714285714286

計算時間が、3分26秒から42秒へと短縮し、正解率も0.978から0.981へと改善しました。

サポートベクタマシンも次元削減に成功しましたね。

結果のまとめ

学習モデルによって次元削減による影響はさまざまです。まずは、もとの特徴量の意味を踏まえて、次元削減するべきかを考えます。次に、学習時間と正解率の結果から次元削減した方がいいかを考える、といったことが重要になります。

今回の結果をあなたの学習モデルにも参考にしてみて下さい。

複数の機械学習モデルの性能を比較する
機械学習の目的は、高い予測精度のモデルを作成することです。高い予測精度のモデルの作成方法はいくつかありますが、一般的な方法を説明していきます。複数の機械学習モデルを比較して、最良もモデルを選択し、最良のモデルのハイパーパラメータを選択します。このような手順で最良のモデルを決定します。
【初心者】複数の機械学習モデルの性能を比較する(分類問題編)
機械学習の目的は、高い予測精度のモデルを作成することです。 高い予測精度のモデルの作成方法はいくつかありますが、一般的な方法を説明していきます。 複数の機械学習モデルを比較して、最良もモデルを選択する 次に、最...

コメント

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