
今回はキカガクで「機械学習 実践(教師あり学習:回帰) - KIKAGAKU」と「機械学習 実践(教師あり学習:分類) - KIKAGAKU」を学んだ。
Table of Contents [Disable]
機械学習 実践(教師あり学習:回帰)
回帰
直線で表現することを線形回帰という。
- 単回帰分析
- 重回帰分析
- Ridge 回帰(リッジ回帰)
- Lasso 回帰(ラッソ回帰)
直線ではない形で表現するアルゴリズムを非線形回帰という。
- 決定木(回帰木)
- ランダムフォレスト
- ニューラルネットワーク
Kaggle などの世界的な分析プラットフォームでは、勾配ブースティングと呼ばれる手法が多く使用されており、有名な例として XGBoost や LightGBM がある。
重回帰分析の復習
回帰分析とは、2 つ以上の変数から回帰分析を行う多変量解析の一つ。
目的関数は単回帰分析と同様に二乗和誤差を用いて最適化する。
重回帰分析の実装
- データセットの準備
- 学習用データセットとテスト用データセットへ分割
単純に全体の何割かを学習用データセットとし、残りをテスト用データセットとする、といった分割を行う方法はホールドアウト法 (holdout method) と呼ばれる。 - モデルの学習・検証
Step 1:モデルの定義
Step 2:モデルの学習
Step 3:モデルの検証 - 推論 (inference)
モデルの検証において、LinearRegression クラスは score() メソッドを提供しており、入力変数と目的変数を与えると学習済みのモデルを用いて計算した決定係数 (coefficient of determination) という指標を返す。決定係数の最大値は 1 であり、値が大きいほど(1 に近いほど)モデルが与えられたデータに当てはまっていることを表す。
学習時に用いたデータに対してはよく当てはまっていても、学習時に用いなかったデータに対しては予測値と目標値の差異が大きくなってしまう現象を、過学習 (overfitting) という。
線形回帰の過学習を抑制する手法
過学習を抑制するアプローチは次のとおり。
- データセットのサンプル数を増やす
- ハイパーパラメータを調整する
- 他のアルゴリズムを使用する
Ridge 回帰(リッジ回帰)やLasso 回帰(ラッソ回帰)など
正則化 (regularization) は、機械学習において、正則化は目的関数に正則化項と呼ばれるモデルの複雑性に罰則(ペナルティ)を科すために追加の項を導入して過学習を抑制する。
Ridge 回帰は、重回帰分析に対して正則化を行うことで、モデルの過度な複雑さに罰則を課して過学習を抑制する。重回帰分析の目的関数である最小二乗法と正則化項という 2 つの最小化した場所を最適解とする。
ハイパーパラメータとは、モデルの学習を実行する前に設定する値。
ノルムとは、長さを一般化したもので、ベクトル空間で距離を与えるための概念。
Lasso 回帰も、重回帰分析に対して正則化を行うが、不要な入力変数の重みを 0 にし(スパース性)、実質的に入力変数を減らすことによって過学習を抑制する。
スパース性とは物事の本質的な特徴を決定づける要素はわずかであるという性質を示す。
ソースコード
# 重回帰分析の実装 | |
import numpy as np | |
import pandas as pd | |
import matplotlib.pyplot as plt | |
import seaborn as sns | |
# データセットの読み込み | |
from sklearn.datasets import load_boston | |
dataset = load_boston() | |
x, t = dataset.data, dataset.target | |
columns = dataset.feature_names | |
print(type(x), x.shape, type(t), t.shape) | |
df = pd.DataFrame(x, columns=columns) | |
print(df.head(3)) | |
# 目標値を追加 | |
df['Target'] = t | |
print(df.head(3)) | |
# 入力変数と目的変数の切り分け | |
t = df['Target'].values | |
x = df.drop(labels=['Target'], axis=1).values | |
from sklearn.model_selection import train_test_split | |
# 2 つに分割 | |
x_train, x_test, t_train, t_test = train_test_split(x, t, test_size=0.3, random_state=0) | |
# Step 1:モデルの定義 | |
from sklearn.linear_model import LinearRegression | |
model = LinearRegression() | |
# Step 2:モデルの学習 | |
print(model.fit(x_train, t_train)) | |
# 学習後のパラメータ w | |
print(model.coef_) | |
# パラメータの分布をヒストグラムで可視化 | |
plt.figure(figsize=(10, 7)) | |
plt.bar(x=columns, height=model.coef_) | |
plt.show() | |
# 学習後のバイアス b | |
print(model.intercept_) | |
# Step 3:モデルの検証 | |
print('train score : ', model.score(x_train, t_train)) | |
print('test score : ', model.score(x_test, t_test)) | |
# 推論 | |
y = model.predict(x_test) | |
print('予測値: ', y[0]) | |
print('目標値: ', t_test[0]) | |
# Ridge 回帰 | |
# モデルの定義、ハイパーパラメータの値を設定 | |
from sklearn.linear_model import Ridge | |
ridge = Ridge(alpha=1) | |
# モデルの学習 | |
print(ridge.fit(x_train, t_train)) | |
# モデルの検証 | |
print('train score : ', ridge.score(x_train, t_train)) | |
print('test score : ', ridge.score(x_test, t_test)) | |
# 箱を準備 | |
fig = plt.figure(figsize=(7, 10)) | |
# 重回帰分析 | |
ax1 = fig.add_subplot(2, 1, 1) | |
ax1.bar(x=columns, height=model.coef_) | |
ax1.set_title('Linear Regression') | |
# リッジ回帰 | |
ax2 = fig.add_subplot(2, 1, 2) | |
ax2.bar(x=columns, height=ridge.coef_) | |
ax2.set_title('Ridge Regression') | |
plt.show() | |
# Lasso 回帰 | |
# モデルの定義 | |
from sklearn.linear_model import Lasso | |
lasso = Lasso(alpha=1) | |
# モデルの学習 | |
print(lasso.fit(x_train, t_train)) | |
# モデルの検証 | |
print('train score : ', lasso.score(x_train, t_train)) | |
print('test score : ', lasso.score(x_test, t_test)) | |
# 0 になっていない特徴量の数 | |
print('元の特徴量の数 : ', x.shape[1]) | |
print('Lasso の特徴量 : ', np.sum(lasso.coef_ != 0)) | |
# アルファを変更してみる | |
lasso_005 = Lasso(alpha=0.05) | |
lasso_005.fit(x_train, t_train) | |
print('train score : ', lasso_005.score(x_train, t_train)) | |
print('test score : ', lasso_005.score(x_test, t_test)) | |
# 0 になっていない特徴量の数 | |
print('元の特徴量の数 : ', x.shape[1]) | |
print('Lasso005 の特徴量 : ', np.sum(lasso_005.coef_ != 0)) | |
fig = plt.figure(figsize=(7, 15)) | |
# 重回帰分析 | |
ax1 = fig.add_subplot(3, 1, 1) | |
ax1.bar(x=columns, height=model.coef_) | |
ax1.set_title('Linear Regression') | |
# lasso | |
ax2 = fig.add_subplot(3, 1, 2) | |
ax2.bar(x=columns, height=lasso.coef_) | |
ax2.set_title('Lasso Regression 1') | |
# lasso_005 | |
ax3 = fig.add_subplot(3, 1, 3) | |
ax3.bar(x=columns, height=lasso_005.coef_) | |
ax3.set_title('Lasso Regression 0.05'); | |
plt.show() |
実行結果
C:\Development\Python\Project001\venv\Scripts\python.exe C:/Development/Python/Project001/venv/multiple_regression_analysis.py | |
<class 'numpy.ndarray'> (506, 13) <class 'numpy.ndarray'> (506,) | |
CRIM ZN INDUS CHAS NOX ... RAD TAX PTRATIO B LSTAT | |
0 0.00632 18.0 2.31 0.0 0.538 ... 1.0 296.0 15.3 396.90 4.98 | |
1 0.02731 0.0 7.07 0.0 0.469 ... 2.0 242.0 17.8 396.90 9.14 | |
2 0.02729 0.0 7.07 0.0 0.469 ... 2.0 242.0 17.8 392.83 4.03 | |
[3 rows x 13 columns] | |
CRIM ZN INDUS CHAS NOX ... TAX PTRATIO B LSTAT Target | |
0 0.00632 18.0 2.31 0.0 0.538 ... 296.0 15.3 396.90 4.98 24.0 | |
1 0.02731 0.0 7.07 0.0 0.469 ... 242.0 17.8 396.90 9.14 21.6 | |
2 0.02729 0.0 7.07 0.0 0.469 ... 242.0 17.8 392.83 4.03 34.7 | |
[3 rows x 14 columns] | |
LinearRegression() | |
[-1.21310401e-01 4.44664254e-02 1.13416945e-02 2.51124642e+00 | |
-1.62312529e+01 3.85906801e+00 -9.98516565e-03 -1.50026956e+00 | |
2.42143466e-01 -1.10716124e-02 -1.01775264e+00 6.81446545e-03 | |
-4.86738066e-01] | |
37.937107741831994 | |
train score : 0.7645451026942549 | |
test score : 0.6733825506400202 | |
予測値: 24.935707898576652 | |
目標値: 22.6 | |
Ridge(alpha=1) | |
train score : 0.7623440182689594 | |
test score : 0.6665819091486687 | |
Lasso(alpha=1) | |
train score : 0.7084095500978868 | |
test score : 0.6115433359595555 | |
元の特徴量の数 : 13 | |
Lasso の特徴量 : 10 | |
train score : 0.7548928631432029 | |
test score : 0.6541502573235292 | |
元の特徴量の数 : 13 | |
Lasso005 の特徴量 : 12 | |
Process finished with exit code 0 |
Fig.1 パラメータの分布をヒストグラムで可視化
Fig.2 Rigde 回帰のパラメータの分布
Fig.3 Lasso 回帰のパラメータの分布
相関関係と多重共線性問題
過学習が起こる原因の一つとして、入力変数同士の相関が強いものが含まれていると発生する多重共線性 (Multicollinearity) という問題がある。
一般的に機械学習アルゴリズムは、学習時に相関の高い入力変数を使用することにより、モデルの予測精度向上の妨げとなる場合がある。その対策として、単純にデータセットの中から相関の高い入力変数のどちらかを削除する方法や、使用するアルゴリズムを変更する方法がある。
.corr() を使用して相関関係を表す数値(相関係数)を確認する。
相関係数はヒートマップで可視化する。ヒートマップは、seaborn.heatmap() メソッドを使用する。
2 つの変数の関係を可視化するには sns.jointplot() を使用する。
Partial Least Squares (PLS) は、多重共線性の問題の対処法として有力なアルゴリズムである。
- 入力値と目標値の共分散が最大になるように主成分を抽出
- 抽出された主成分に対して重回帰分析を用いてモデルの学習を行う
主成分分析は、100 個の特徴量があった場合にその特徴量の数を分散を用いて 10 や 20 個などに削減する手法(次元削減)である。
PLS との違いは教師あり学習と教師なし学習で、主成分を抽出するときに目標値の情報を使うか使わないかの違いがある。
scikit-learn に用意されているモジュール PLSRegression を使用すると、これらのステップを意識せずに実装できる。
ソースコード
# 相関関係と多重共線性問題 | |
import numpy as np | |
import pandas as pd | |
import matplotlib.pyplot as plt | |
import seaborn as sns | |
from sklearn.model_selection import train_test_split | |
# データセットの準備 | |
# データの確認 | |
df = pd.read_csv('../regression_pls.csv') | |
print(df.head(3)) | |
print(df.shape) | |
# データの切り分け -> ndarray に変換 | |
x = df.drop('Target', axis=1).values | |
t = df['Target'].values | |
print(x.shape, t.shape) | |
# 学習用データとテスト用データの分割 | |
x_train, x_test, t_train, t_test = train_test_split(x, t, test_size=0.3, random_state=0) | |
# モデルの定義 | |
from sklearn.linear_model import LinearRegression | |
model = LinearRegression() | |
# モデルの学習 | |
model.fit(x_train, t_train) | |
# モデルの検証 | |
print('train : ', model.score(x_train, t_train)) | |
print('test : ', model.score(x_test, t_test)) | |
# 相関係数の算出 | |
df_corr = df.corr() | |
print(df_corr.head()) | |
plt.figure(figsize=(12, 8)) | |
sns.heatmap(df_corr.iloc[:20, :20], annot=True) | |
sns.jointplot(x='x1', y='x16', data=df) | |
# モデルの定義( n_components:7 とする) | |
from sklearn.cross_decomposition import PLSRegression | |
pls = PLSRegression(n_components=7) | |
# モデルの学習 | |
pls.fit(x_train, t_train) | |
# モデルの検証 | |
print('train score : ', pls.score(x_train, t_train)) | |
print('test score : ', pls.score(x_test, t_test)) | |
実行結果
C:\Development\Python\Project001\venv\Scripts\python.exe C:/Development/Python/Project001/venv/resession_pls.py | |
Target x1 x2 x3 x4 ... x192 x193 x194 x195 x196 | |
0 1.58 59.068 54.028 59.037114 24 ... 0 0 0 0 0 | |
1 1.34 46.073 40.025 46.053098 20 ... 0 0 0 0 0 | |
2 1.22 60.052 56.020 60.021129 24 ... 0 0 0 0 0 | |
[3 rows x 197 columns] | |
(1290, 197) | |
(1290, 196) (1290,) | |
train : 0.9365474255009363 | |
test : 0.002234802175512751 | |
Target x1 x2 ... x194 x195 x196 | |
Target 1.000000 -0.642326 -0.648078 ... 0.002448 -0.113820 0.043600 | |
x1 -0.642326 1.000000 0.997571 ... -0.015226 -0.038657 0.027857 | |
x2 -0.648078 0.997571 1.000000 ... -0.015106 -0.062823 0.027773 | |
x3 -0.640489 0.999978 0.997252 ... -0.015093 -0.038138 0.028359 | |
x4 -0.524453 0.908895 0.883891 ... -0.016378 0.027813 0.055553 | |
[5 rows x 197 columns] | |
AxesSubplot(0.125,0.11;0.62x0.77) | |
<seaborn.axisgrid.JointGrid object at 0x000001910B68A188> | |
train score : 0.906376310202351 | |
test score : 0.738728147180731 | |
Process finished with exit code 0 |
機械学習 実践(教師あり学習:分類)
分類
分類はカテゴリが異なる複数のデータを見分けることができる境界線を求めることが目的。
二次元平面上にあるデータ(集合)を一本の直線で分けられることを線形分離可能といい、そのアルゴリズムを線形分類器と呼ぶ。
線形分類器として有名なものは、
- 単純パーセプトロン
- 線形サポートベクトルマシン
- ロジスティック回帰
等。
線形分離可能ではない場合に、線形ではない形で分類するアルゴリズムを非線形分類器と呼ぶ。
非線形分類器として有名なものは、
- k-近傍法
- 決定木(分類木)
- ランダムフォレスト
- 非線形サポートベクトルマシン
- ニューラルネットワーク
等。
決定木の実装で分類の全体像を理解
scikit-learn は問題設定が回帰、分類問わず、
- モデルの定義
- 学習
- 検証
の 3 ステップで進める。
分類では、回帰の時に使用した指標である決定係数ではなく、決定木の score() メソッドで表示される正解率 (Accuracy) を用いる。
正解率の最小値は
0 となり、最大値は 1 となる。
目的関数は、回帰では平均二乗誤差が用いられていたが、分類では交差エントロピーが主に用いる。
ただし、どちらの目的関数も正解と予測の差を評価したいという考えは同じ。
分類の問題設定でも、scikit-learn を用いての実装は回帰の場合と大きな違いはなく、推論も同様に predict() メソッドで実行することが可能。
決定木の特徴
決定木は複数の分岐を繰り返すことによって分類を行う。
特徴は次の 2 つ。
- 解釈が容易。必要な前処理が少ない。
- 過学習になる場合が多く、汎用性の低いモデルになる傾向がある。
ハイパーパラメータは次の 2 つ。
- max_depth(木構造の深さの上限)は、過学習を抑えるためのハイパーパラメータ。上限が低いとモデルの表現力は低下し、過学習を抑える。
- min_samples_split(木構造の分岐先の値)は、分岐先のノード数の最低値を設定するハイパーパラメータ。過学習に陥る可能性が上がるので調整が必要。
決定木単体では高い性能を出せない複雑な問題設定に対してはアンサンブル学習が用いられる。
アンサンブル学習は、決定木を基本として、学習器を複数用意して一つのモデルにしようというアルゴリズムである。
アンサンブル学習には、
- ランダムフォレスト
- XGBoost
- LightGBM
等がある。
サポートベクトルマシン (SVM)
サポートベクトルマシンは、2 つのカテゴリを識別する分類器。
サポートベクトルマシンでは、境界線に最も近いサンプルとの距離(マージン)が最大となるように境界線が定義される。
サポートベクトルマシンにカーネル関数を取り入れた一連の手法をカーネルトリックと呼ぶ。
カーネル関数により、高次元(無限次元)の特徴空間へ写像し、特徴空間上で線形分離を行う。
特徴は次の 2 つ。
- 未知のデータへの識別性能が比較的強い。ハイパーパラメータの数が少ない。
- 学習する際に必ずデータの標準化(もしくは正規化)を行う必要がある。
ハイパーパラメータは次の 2 つ。
- C(コストパラメータ)は、誤った予測に対するペナルティ。大き過ぎると過学習を起こす。
- gamma(ガンマ)は、モデルの複雑さを決定する。値が大きくなるほどモデルが複雑になり過学習を起こす。
サポートベクトルマシンは一般的にデータに対して標準化を適用する必要がある。
標準化 (Standardization)
は平均と標準偏差を算出して行なう。
標準化を行うには、sklearn.preprocessiong 以下の StandardScaler を用いる。
算出した平均と標準偏差から実際にデータセットの値を変換するには transform() メソッドを使用する。
ロジスティック回帰
ロジスティック回帰 (Logistic regression) は、あるデータがカテゴリに属する確率を予測するための回帰のアルゴリズムに該当するが、確率を予測することが可能な特性から分類の問題設定で用いられることが多い。
ロジスティック回帰は入力変数から目的変数に対して二値分類をおこなうモデル。
特徴は次の 2 つ。
- 説明能力が高い。入力変数の重要度、オッズ比がわかる。
- 線形分類器のため、複雑な問題設定に対応できない場合がある。
ハイパーパラメータは次の 2 つ。
- C(コストパラメータ)は。誤った予測に対するペナルティ。大きすぎると過学習を起こす。
- penaltyは、正則化を行う方法を決定する。L1L1、L2L2 のノルムから選択する。
ロジスティック回帰ではオッズ比を用いて、目的変数に対する各入力変数の影響の大きさを確認する。
オッズ比とは、ある事象の 1 つの群と 1
つの群におけるオッズの比として定義される。
オッズ比が 1 になると事象の起こりやすさが同じであることを表し、1 よりも大きい(小さい)とオッズ A がオッズ B よりも起こりやすい(起こりにくい)ということになる。
分類のアルゴリズムには確率を予測できるものと確率を予測できないものに分けることができる。
特に、分類器では前者を識別モデル、後者を識別関数と呼ぶ。
ロジスティック回帰は識別モデルに該当し、predict() メソッドで推論を行い分類結果を取得でき、predict_proba() メソッドで確率を取得することができる。
scikit-learn を用いて推論を行う際の入力変数は行列である必要がある。
分類の評価方法
分類において、学習済みモデルを評価する指標
- Accuracy(正解率)は分類の精度を確認するための指標
- Precision(適合率)は誤りを少なくしたい場合の指標
- Recall(再現率)は正例の見逃しを避けたい場合の指標
- F1score(F 値)はPrecision と Recall の両者のバランスを取るために調和平均で計算される指標
Precision と Recall は互いにトレードオフの関係にあり、どちらかの値を上げようとすると、もう一方の値が下がることになる。
混同行列 (Confusion Matrix) は実測値と予測値の関係性を示す表。
- TP (True Positive、真陽性):予測値を正例として、その予測が正しい場合の数
- FP (False Positive、偽陽性):予測値を正例として、その予測が誤りの場合の数
- TN (True Negative、真陰性):予測値を負例として、その予測が正しい場合の数
- FN (False Negative、偽陰性):予測値を負例として、その予測が誤りの場合の数
ソースコード
import numpy as np | |
import pandas as pd | |
import matplotlib.pyplot as plt | |
import seaborn as sns | |
from sklearn.datasets import load_iris | |
# 決定木の実装 | |
# データセットの読み込み | |
dataset = load_iris() | |
columns_name = dataset.feature_names | |
x = dataset.data | |
t = dataset.target | |
# 読み込んだデータセットを DataFrame に変換 | |
df = pd.DataFrame(data=x, columns=columns_name) | |
df['Target'] = t | |
print(df.head(3)) | |
# t のユニークな値を確認する | |
print(np.unique(t)) | |
print(x.shape, t.shape) | |
# データセットの分割 | |
from sklearn.model_selection import train_test_split | |
x_train, x_test, t_train, t_test = train_test_split(x, t, test_size=0.3, random_state=0) | |
# モデルの定義 | |
from sklearn.tree import DecisionTreeClassifier | |
dtree = DecisionTreeClassifier(random_state=0) | |
# モデルの学習 | |
print(dtree.fit(x_train, t_train)) | |
# モデルの検証 | |
print('train score : ', dtree.score(x_train, t_train)) | |
print('test score : ', dtree.score(x_test, t_test)) | |
# 推論 | |
print(dtree.predict(x_test)) | |
# 木構造の書き出し | |
import graphviz | |
from sklearn.tree import export_graphviz | |
dot_data = export_graphviz(dtree) | |
# 木構造の表示 | |
graph_tree = graphviz.Source(dot_data) | |
print(graph_tree) | |
# feature importance | |
feature_importance = dtree.feature_importances_ | |
print(feature_importance) | |
# 可視化 | |
y = columns_name | |
width = feature_importance | |
# 横向きで表示 | |
plt.barh(y=y, width=width) | |
plt.show() | |
# モデルの定義 | |
from sklearn.svm import SVC | |
svc = SVC() | |
# モデルの学習 | |
print(svc.fit(x_train, t_train)) | |
# モデルの検証 | |
print('train score : ', svc.score(x_train, t_train)) | |
print('test score : ', svc.score(x_test, t_test)) | |
# サポートベクトルマシン (SVM) | |
from sklearn.preprocessing import StandardScaler | |
std_scaler = StandardScaler() | |
print(std_scaler.fit(x_train)) | |
# 標準化 | |
x_train_std = std_scaler.transform(x_train) | |
x_test_std = std_scaler.transform(x_test) | |
# 平均 | |
print(round(x_train_std.mean())) | |
# 標準偏差 | |
print(round(x_train_std.std())) | |
# モデルの定義 | |
svc_std = SVC() | |
# モデルの学習 | |
print(svc_std.fit(x_train_std, t_train)) | |
# モデルの検証 | |
print('train score : ', svc.score(x_train, t_train)) | |
print('test score : ', svc.score(x_test, t_test)) | |
print('train score scaling : ', svc_std.score(x_train_std, t_train)) | |
print('test score scaling : ', svc_std.score(x_test_std, t_test)) | |
# ロジスティック回帰 | |
# モデルの定義 | |
from sklearn.linear_model import LogisticRegression | |
log_reg = LogisticRegression(C=1.0) | |
# モデルの学習 | |
print(log_reg.fit(x_train, t_train)) | |
# モデルの検証 | |
print('train score : ', log_reg.score(x_train, t_train)) | |
print('test score : ', log_reg.score(x_test, t_test)) | |
print(log_reg.coef_.shape) | |
# 重み(係数) | |
print(log_reg.coef_) | |
# 切片 | |
print(log_reg.intercept_) | |
# それぞれの重みを確認 | |
fig = plt.figure(figsize=(7, 15)) | |
for i in range(len(log_reg.coef_)): | |
ax = fig.add_subplot(3, 1, i+1) | |
ax.barh(y=dataset.feature_names, width=log_reg.coef_[i]) | |
ax.set_title('Class {} '.format(i)) | |
plt.show() | |
# 各オッズ比を確認 | |
fig = plt.figure(figsize=(7, 15)) | |
for i in range(len(log_reg.coef_)): | |
ax = fig.add_subplot(3, 1, i+1) | |
odds_ratio = np.exp(log_reg.coef_[i]) | |
ax.barh(y=dataset.feature_names, width=odds_ratio) | |
ax.set_title('Class {} '.format(i)) | |
plt.show() | |
# カテゴリ 0 の場合 | |
print('重み(係数):',log_reg.coef_[0]) | |
print('オッズ比:', np.exp(log_reg.coef_[0])) | |
# 目標値の取得 | |
print(log_reg.predict([x_test[0]])) | |
# 各カテゴリに対する確率の確認 | |
print(log_reg.predict_proba([x_test[0]])) | |
# scikit-learn で評価指標を確認 | |
df = pd.read_csv('classification_imb.csv') | |
print(df.head()) | |
print(df.shape) | |
sns.countplot(x='Target', data=df) | |
# 入力変数と目的変数の切り分け | |
x = df.drop('Target', axis=1).values | |
t = df['Target'].values | |
print(x.shape, t.shape) | |
# 学習用データセットとテスト用データセットの分割 | |
from sklearn.model_selection import train_test_split | |
x_train, x_test, t_train, t_test = train_test_split(x, t, test_size=0.3, random_state=0) | |
# モデルの定義 | |
log_reg = LogisticRegression() | |
# モデルの学習 | |
log_reg.fit(x_train, t_train) | |
# モデルの検証 | |
print(log_reg.score(x_train, t_train)) | |
print(log_reg.score(x_test, t_test)) | |
# 推論 | |
y_predict = log_reg.predict(x_test) | |
# ユニークな値 | |
np.unique(y_predict) | |
np.unique(t_test, return_counts=True) | |
# 混同行列 (Confusion Matrix) | |
from sklearn import metrics | |
# ラベルの取り出し | |
labels = list(np.unique(t_train)) | |
labels | |
# 混同行列の取得 | |
confusion_matrix = metrics.confusion_matrix(t_test, y_predict) | |
confusion_matrix | |
# ヒートマップで可視化 | |
plt.figure(figsize=(10, 7)) | |
sns.heatmap(confusion_matrix, annot=True, fmt='.0f', cmap='Blues'); | |
plt.show() | |
precision = metrics.precision_score(t_test, y_predict, average=None) | |
precision | |
recall = metrics.recall_score(t_test, y_predict, average=None) | |
recall | |
f1_score = metrics.f1_score(t_test, y_predict, average=None) | |
f1_score | |
precision, recall, f1_score, total = metrics.precision_recall_fscore_support(t_test, y_predict) | |
# ヒートマップで可視化 | |
df_total = pd.DataFrame( | |
np.array([total, precision, recall, f1_score]), | |
index=['Total', 'Precision', 'Recall', 'F1_score'], | |
columns=['Label 0','Label 1'] | |
) | |
plt.figure(figsize=(10, 7)) | |
sns.heatmap(df_total, annot=True, fmt='.6f', cmap='Blues'); | |
plt.show() |
実行結果
C:\Development\Python\Project001\venv\Scripts\python.exe C:/Development/Python/Project001/venv/iris_classify.py | |
sepal length (cm) sepal width (cm) ... petal width (cm) Target | |
0 5.1 3.5 ... 0.2 0 | |
1 4.9 3.0 ... 0.2 0 | |
2 4.7 3.2 ... 0.2 0 | |
[3 rows x 5 columns] | |
[0 1 2] | |
(150, 4) (150,) | |
DecisionTreeClassifier(random_state=0) | |
train score : 1.0 | |
test score : 0.9777777777777777 | |
[2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0 | |
2 1 1 2 0 2 0 0] | |
<graphviz.files.Source object at 0x0000022247089B88> | |
[0. 0.02150464 0.39766951 0.58082584] | |
SVC() | |
train score : 0.9714285714285714 | |
test score : 0.9777777777777777 | |
StandardScaler() | |
0.0 | |
1.0 | |
SVC() | |
train score : 0.9714285714285714 | |
test score : 0.9777777777777777 | |
train score scaling : 0.9714285714285714 | |
test score scaling : 0.9777777777777777 | |
LogisticRegression() | |
train score : 0.9809523809523809 | |
test score : 0.9777777777777777 | |
(3, 4) | |
[[-0.39765206 0.83422714 -2.28942624 -0.97842075] | |
[ 0.54457552 -0.29081701 -0.23264966 -0.65834388] | |
[-0.14692346 -0.54341013 2.52207589 1.63676463]] | |
[ 8.99751711 1.54390562 -10.54142273] | |
重み(係数): [-0.39765206 0.83422714 -2.28942624 -0.97842075] | |
オッズ比: [0.67189576 2.30303344 0.10132458 0.37590428] | |
[2] | |
[[1.31716029e-04 5.98488920e-02 9.40019392e-01]] | |
x1 x2 x3 x4 x5 x6 x7 x8 ... x51 x52 x53 x54 x55 x56 x57 Target | |
0 0 2 0 0 6 1 0 0 ... 9 0 1 1 0 1 0 1 | |
1 1 3 8 0 0 1 0 0 ... 8 0 1 1 1 1 0 1 | |
2 2 1 1 1 0 0 0 0 ... 8 0 1 1 1 0 0 1 | |
3 5 1 9 0 0 1 0 0 ... 8 0 1 1 0 0 0 1 | |
4 0 1 2 0 0 1 0 0 ... 6 0 1 0 1 0 1 1 | |
[5 rows x 58 columns] | |
(29760, 58) | |
(29760, 57) (29760,) | |
0.9632776497695853 | |
C:\Development\Python\Project001\venv\lib\site-packages\sklearn\linear_model\_logistic.py:764: ConvergenceWarning: lbfgs failed to converge (status=1): | |
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. | |
Increase the number of iterations (max_iter) or scale the data as shown in: | |
https://scikit-learn.org/stable/modules/preprocessing.html | |
Please also refer to the documentation for alternative solver options: | |
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression | |
extra_warning_msg=_LOGISTIC_SOLVER_CONVERGENCE_MSG) | |
0.961581541218638 | |
C:\Development\Python\Project001\venv\lib\site-packages\sklearn\metrics\_classification.py:1221: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior. | |
_warn_prf(average, modifier, msg_start, len(result)) | |
C:\Development\Python\Project001\venv\lib\site-packages\sklearn\metrics\_classification.py:1221: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior. | |
_warn_prf(average, modifier, msg_start, len(result)) | |
プロセスは終了コード 0 で完了しました |
Fig.6 入力変数の影響度
Fig.7 特徴量の重み
Fig.8 オッズ比
Fig.9 目的変数のデータ個数
Fig.10 混同行列
Fig.11 評価指標