LoginSignup
0
0

More than 1 year has passed since last update.

分類モデル比較(データ可視化→学習→予測結果可視化→評価関数の比較)※testver

Last updated at Posted at 2022-02-11

0. はじめに

分類モデルの構築、評価について、
理論・実装を合わせて整理するために投稿いたしました。

学習モデル・評価関数等一部を更新する等で、ご利用いただければ幸いです。

1. データセットの可視化

  • 学習データ

    • x:説明変数 $[(x_{11},x_{12},...x_{1M}),...(x_{N1}...x_{NM}) ]$
    • y:目的変数 $y_1, y_2, ...y_N$

      • N:サンプル
      • M:説明変数の数
\begin{pmatrix}
x_{11} &x_{12} & ... &x_{1M} \\
x_{21} &x_{22} & ... &x_{2M} \\
:     &       &     & \\
x_{N1} &x_{N2} & ... &x_{NM} 
\end{pmatrix}

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

1.1. 表

iris_df = sns.load_dataset('iris') # データセットの読み込み
iris_df.head()

image.png

1.2. 散布図

sns.pairplot(iris_df,  hue='species')

download.png

2. 学習

2.0.訓練データ(train)・テストデータ(test)に分割する

from sklearn.model_selection import train_test_split


X = iris_df[['sepal_length','sepal_width','petal_length','petal_width']] # 説明変数
Y = iris_df['species']

#訓練データ80%、テストデータ20%に分割。
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.2, random_state = 0) # 80%のデータを学

2.1. ロジスティック回帰

モデル : $Y_{pred} = \pi(\alpha X + \beta) $

ロジスティック関数:$\pi = \frac{e^x}{(1 + e^x)}$

from sklearn.linear_model import LogisticRegression


model_LR = LogisticRegression() # ロジスティック回帰モデルのインスタンスを作成
model_LR.fit(X_train.to_numpy(), Y_train.to_numpy()) # ロジスティック回帰モデルの重みを学習

2.2. サポートベクターマシン

マージン(識別境界と、識別境界と最短距離のサンプル との距離)を最大化

image.png

from sklearn.svm import LinearSVC

model_LinearSVC = LinearSVC() # サポートベクターマシンのインスタンス生成
model_LinearSVC.fit(X_train, Y_train) # サポートベクターマシンモデルの重みを学習

2.3. Kmeans

  1. クラスター数KとK個の重心を決める。
  2. クラスター(重心)の位置が変化しなくなるまで、以下を繰返す。
    1. 各サンプルX_i とクラスターK(重心)との距離を計算。
    2. で計算した距離が最も近いクラスターに、各サンプルを割り当てる。

image.png

from sklearn.cluster import KMeans

kmeans = KMeans(n_clusters=len(iris_df["species"].unique()))
model_kmeans = kmeans.fit(X)

2.4.ニューラルネットワーク

ニューラルネットワークの学習

  • 目的:損失関数を最小化するような、モデルのパラメータ$W$を求める。
    • 損失関数: $L = (正解 - モデルによる予測値)^2$
    • モデルによる予測値: $activation( W_2 activation(W_1 X))$ ※中間層2つの時
      • activation:活性化関数
      • $W_i$: 中間層iの重みベクトル
      • X:説明変数

MLPClassifier のパラメータについて

  • hidden_layer_size: 中間層の層数および、各中間層のニューロン数
    • (50,50,50)の場合、中間層は3つ。各中間層のニューロン数は、それぞれ50。
  • activation: 中間層の活性化関数

    • identity(恒等関数): $f(x) = x$
    • relu(ReLU関数):  $f(x) = \begin{cases} 0 & (x \leq 0) \ x & (x > 0) \end{cases} $
    • logistic(シグモイド関数): $f(x) = \frac{e^x}{1+e^x}$
  • solver:重みWを最適化する方法

    • sgd: 確率的勾配降下法
    • adam:
    • lbfgb:準ニュートン法
  • max_iter:学習反復回数の、"最大回数"

from sklearn.neural_network import MLPClassifier


model_NN = MLPClassifier(hidden_layer_sizes=(50,50,50), max_iter=1000, activation = "relu", solver = "sgd")
model_NN.fit(X_train, Y_train)

3. 識別境界の可視化

3.3 K近傍法 (教師なし学習の一種)

#iris_df = iris_df[["petal_length","petal_width", "species"]] 
iris_df["cluster"] = model_kmeans.labels_


markers = ["o", "x", "+"] #正解ラベルごとに図形を変える。
pos = 0

for i in iris_df["cluster"].unique():
    tmp = iris_df.loc[iris_df["cluster"] == i]
   #plt.scatter(tmp.loc["petal_length"], tmp.loc["petal_width"])
    plt.scatter(tmp["petal_length"], tmp["petal_width"], marker = markers[pos])
    pos += 1

plt.title("Scatter Plot of Kmeans")
plt.xlabel("petal_length")
plt.ylabel("petal_width")
plt.show()

download.png

4. 評価指標ごとの精度

4.1. 評価指標を計算

評価指標

- confusion_matrix(混同行列)
- logloss (交差エントロピー誤差)

confusion_matrix

Predict(学習モデルの予想)
Negative Positive
True(正解) Negative TN FP
Positive FN TP
  • TP(True Positive): モデルがPositiveと予想し、正解(True)
  • TN(True Negative): モデルがNegativeと予想し、正解(True)
  • FP(True Positive): モデルがPositiveと予想し、不正解(False)
  • FN(True Negative): モデルがNegativeと予想し、不正解(False)

交差エントロピー誤差 $H(x)$

$H(p, q) = - \sum_{1}^{クラス数} p(x)log(q(x)) $
- p: 正解$y_{true}$の確率分布
- q: 学習モデルが予測した目的変数の値$y_{predict}$の確率分布

p:[1.0,0.0,0.0], q:[0.7, 0.2,0.1] の場合

$ H(p, q) = - (1.0 \times \log(0.7) + 0.0 \times 0.2 + 0.0 \times 0.1) $  

= - log(0.7)


from sklearn.metrics import accuracy_score 
from sklearn.metrics import log_loss
from sklearn.preprocessing import OneHotEncoder
from sklearn.metrics import confusion_matrix

#評価のため、目的変数の値を数値型へ変換する。
Y_test = Y_test.replace({"virginica":0,"setosa":1,"versicolor":2})
Y_test = pd.DataFrame(Y_test)

#logloss計算用に、目的変数の値をOneHot表現に変換。予測値(Y_pred*)のみ変換。
encoder_OneHot = OneHotEncoder(categories="auto", sparse=False, dtype=np.float32)

Y_test_OneHot = encoder_OneHot.fit_transform(Y_test)

#ロジスティック回帰
Y_pred_LR =  model_LR.predict(X_test)
Y_pred_LR = pd.DataFrame(Y_pred_LR).replace({"virginica":0,"setosa":1,"versicolor":2})
Y_pred_LR_OneHot = encoder_OneHot.fit_transform(Y_pred_LR)


cm_LR = confusion_matrix(Y_test, Y_pred_LR)
logloss_LR = log_loss(Y_test, Y_pred_LR_OneHot)

#サポートベクターマシン
Y_pred_LinearSVC =  model_LinearSVC.predict(X_test)
Y_pred_LinearSVC = pd.DataFrame(Y_pred_LinearSVC).replace({"virginica":0,"setosa":1,"versicolor":2})
Y_pred_LinearSVC_OneHot = encoder_OneHot.fit_transform(Y_pred_LinearSVC)

cm_LinearSVC = confusion_matrix(Y_test, Y_pred_LinearSVC)
logloss_LinearSVC = log_loss(Y_test, Y_pred_LinearSVC_OneHot)


#kmeans
Y_pred_kmeans =  model_kmeans.predict(X_test)
Y_pred_kmeans = pd.DataFrame(Y_pred_kmeans)
Y_pred_kmeans_OneHot = encoder_OneHot.fit_transform(Y_pred_kmeans)

cm_kmeans = confusion_matrix(Y_test, Y_pred_kmeans)
logloss_kmeans = log_loss(Y_test, Y_pred_kmeans_OneHot)

#ニューラルネットワーク
Y_pred_NN =  model_NN.predict(X_test)
Y_pred_NN = pd.DataFrame(Y_pred_NN).replace({"virginica":0,"setosa":1,"versicolor":2})
Y_pred_NN = pd.DataFrame(Y_pred_NN)
Y_pred_NN_OneHot = encoder_OneHot.fit_transform(Y_pred_NN)

cm_NN = confusion_matrix(Y_test, Y_pred_NN)
logloss_NN = log_loss(Y_test, Y_pred_NN_OneHot)

4.2.評価結果を可視化

4.2.1. Confusion_matrix (混同行列)

ロジスティック回帰

cm_LR = pd.DataFrame(data=cm_LR, index=["virginica", "setosa", "versicolor"], 
                           columns=["virginica", "setosa", "versicolor"])

sns.heatmap(cm_LR, square=True, cbar=True, annot=True, cmap='Blues')
plt.xlabel("True Label", fontsize=15)
plt.ylabel("Predict", fontsize=15)
plt.show()

image.png

サポートベクターマシン

cm_LR = pd.DataFrame(data=cm_LinearSVC, index=["virginica", "setosa", "versicolor"], 
                           columns=["virginica", "setosa", "versicolor"])

sns.heatmap(cm_LinearSVC, square=True, cbar=True, annot=True, cmap='Blues')
plt.xlabel("True Label", fontsize=15)
plt.ylabel("Predict", fontsize=15)
plt.show()

image.png

ニューラルネットワーク

cm_NN = pd.DataFrame(data=cm_NN, index=["virginica", "setosa", "versicolor"], 
                           columns=["virginica", "setosa", "versicolor"])

sns.heatmap(cm_NN, square=True, cbar=True, annot=True, cmap='Blues')
plt.xlabel("True Label", fontsize=15)
plt.ylabel("Predict", fontsize=15)
plt.show()

image.png

4.2.2. Logloss

logloss = pd.DataFrame([[logloss_LR],[logloss_LinearSVC],[logloss_kmeans],[logloss_NN]],
                       index = ["LR","LinearSVC","kmeans","logloss_NN"],columns = ["logloss"])
logloss

image.png

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0