第6回:教師あり学習:分類モデル

6.1 教師あり学習・分類

第5回に教師あり学習・回帰を扱いました.教師あり学習には他に分類もあります.

分類の概念的理解

◇ 広い意味を持つ分類 (classification)

classification.png
図1:生物分類学的階級【Mykinso

大辞林より

  1. ある基準に従って,物事を似たものどうしにまとめて分けること
  2. (論理学)物事を徹底的に区分し,類種系列の形をとった体系を形成すること

◇ 教師あり学習・分類 (supervised learning - classification)

  1. 「あるデータがどのクラスに属するかの予測」を指すものである【Smiley
  2. アルゴリズムを用いて,テスト・データを特定のカテゴリーに正確に割り当てることである.データセット内の特定のエンティティを認識し,そのエンティティがどのようにラベルを付けられる,または定義されるべきかについて,何らかの結論を導き出そうとする【IBM
  3. 推論で出力された予測値により,事前に定義された複数の分類カテゴリー(=機械学習では基本的に「クラス:class」と呼ぶ)の中のどれに最も該当するかを判別すること【@IT
sample_000.png
図2:アヤメ分類問題のクラス別に概要を見てみる

教師あり学習「分類」と他手法の比較

◇ 教師あり学習「分類」と「回帰」の違い

  1. 対象のデータが属するクラスを予測するときは分類,値を予測するときは回帰となる 【Avintonジャパン
  2. 「非連続値つまり離散値を使って振り分けるか,連続値を使って別の数値を予測するか」である.分類は振り分けるもの,回帰は数値を予測するものである【AINOW

◇ 教師あり学習「分類」と教師なし学習「クラスタリング」の違い

  1. 答えをもとに学習したデータを用いるのが「分類」,データをもとに特徴を学習していくのが「クラスタリング」である【Smiley
  2. クラス分類は対象になる分類を見つけるというニュアンス,クラスタリングはデータそれぞれを集団化するというニュアンスである【オルタナティブ・ブログ

6.2 分類モデルの選定

モデルの特徴からデータの種類と目的を考える

classification_models.png
図3:一般的な分類モデルの特徴【MONOist
models_flowchart.png
図4:モデル選定のための流れ

【ハンズオン6-1】ロジスティック回帰 (logistic regression)

第3回では,決定木分析を用いて,アヤメの種類の分類モデルを作成した.この節で紹介するロジスティック回帰でも,決定木と同様に分類の予測モデルを作ることができる

アヤメの分類問題に関し,Qiitaにもk-近傍法(k-NN)やサポートベクターマシン(SVM)の実装例があり,ご都合の良い際にご参照ください

◇ STEP 0 準備

# Pandasをインポート
import pandas as pd

# train_test_splitをインポート(データの分割用)
from sklearn.model_selection import train_test_split

◇ STEP 1 データの読み込み

#アヤメデータの取得
df = pd.read_csv("https://www2.cmds.kobe-u.ac.jp/~masa-n/dshandson/iris-sample.csv")

#確認
df

【実行結果】 output_001.png

◇ STEP 2 欠損値を穴埋めする

# 平均値による欠損値の穴埋め
df_mean = df.mean()
train2 = df.fillna(df_mean)

# 特徴量と正解データに分割
x = train2.loc[:,:'花びらの幅']
t = train2['品種']

# 特徴量の標準化
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
new = sc.fit_transform(x)

◇ STEP 3 訓練データと検証用データを分割する

# 訓練データと検証データに分割
x_train, x_val, y_train, y_val = train_test_split(new, t, test_size = 0.2, random_state = 0)

◇ STEP 4 ロジスティック回帰による学習

from sklearn.linear_model import LogisticRegression

model = LogisticRegression(random_state = 0, C = 0.1, multi_class = 'auto', solver = 'lbfgs')

☆☆ モデル変数 = LogisticRegression(C = 値,multi_class = 'auto', solver = 'lbfgs')

◇ STEP 5 正解率を確認する

model.fit(x_train, y_train)
print(model.score(x_train, y_train))
model.score(x_val, y_val)

【実行結果】

0.925
0.9333333333333333

◇ STEP 6 係数を確認する

model.coef_ # 係数の確認

【実行結果】 output_002.png

◇ STEP 7 新規データで予測する

x_new = [[1, 2, 3, 4]] # 新規データ
model.predict(x_new) # 新規データで予測

【実行結果】

array(['Iris-virginica'], dtype=object)

◇ STEP 8 確率の予測結果を確認する

model.predict_proba(x_new)

【実行結果】 output_003.png

☆☆ モデル変数.predict_proba( 2次元データ )

6.3 分類モデルの学習

予測精度を上げるための考え方

不均衡データ (imbalanced data)

実際の業務では,正解データの件数の比率に大きな差がある場合も多々ある.このようなデータを不均衡データと呼ぶ.モデルの作成と学習時に,不均衡データの考慮が必要

◇ 不均衡データで対応するようなモデルの例:決定木(DecisionTreeClassifier

sample_001.png
図5:モデルの作成と学習 - 不均衡データの考慮

''class_weight = 'balanced' という引数を指定すると

☆☆ 不均衡データに対処する決定木モデルの作成

tree.DecisionTreeClassifier( class_weight = 'balanced' )

※ class_weight 引数は不均衡データのときに指定する.決定木モデルだけでなく,他の分類モデルでも同様に指定できる.例,LogisticRegression( class_weight = 'balanced' )

バイアス,バリアンス,ノイズ

第5回で皆さんに実際に体験して頂いたように,過学習(overfitting)とは「訓練データでは予測と実際の誤差が少ないのに,未知のテストデータでは,誤差が大きくなる現象」である

◇ 誤差が生じている不適切な状況を考えると,以下の2通りがある

sample_002.png
図6:モデルの結果に誤差が生じている不適切な状況
  1. 予測結果自体は密集しているが,根本的に予測結果の平均値が予測すべき値から遠く離れたところにある(バイアスが高いという)
  2. 予測結果の平均は予測すべき値に近いが,予測結果自体にばらつきが大きく生じている(バリアンスが高いという)

◇ 正解データにおける平均値からのばらつきをノイズと呼ぶ

☆☆ バイアス・バリアンス分解

実際と予測の誤差 = バイアス + バリアンス + ノイズ

【ハンズオン6-2】ランダムフォレスト (random forest)

これから話すランダムフォレストは決定木の上位互換である.皆さんは第3回で体験して頂いた決定木を振り返って,左右2つに分岐していくフローチャートを「木」と呼ぶ

フォレストのことは「森」である.ランダムフォレストは,たくさんの決定木を作成し,それぞれの木に予測させ,その結果の多数決で最終結果を求めるという手法である

ランダムフォレストは通常の決定木に比べて過学習(overfitting)を防ぐことができる

以下を従って,ランダムフォレストの実装からモデルを理解してみましょう

◇ STEP 0 Pandasなどのモジュールを読み込む

# モジュールの読み込み
import pandas as pd
from sklearn.model_selection import train_test_split
%matplotlib inline

◇ STEP 1 データを読み込む

df = pd.read_csv('https://www.es4.eedept.kobe-u.ac.jp/~chensinan/share/Survived.csv') # csvファイルの読み込み
# 確認する
df.head(2)

【実行結果】 output_004.png

column_exp_01.png
図7:各列の意味

このデータを利用して,それぞれの乗客がこの客船の沈没事故に遭遇した場合に,無事生還できるかどうかを予測しましょう

◇ STEP 2 欠損値を穴埋める

jo1 = df['Pclass'] == 1
jo2 = df['Survived'] == 0
jo3 = df['Age'].isnull()
df.loc[(jo1) & (jo2) & (jo3), 'Age'] = 43

jo2 = df['Survived'] == 1
df.loc[(jo1) & (jo2) & (jo3), 'Age'] = 35

jo1 = df['Pclass'] == 2
jo2 = df['Survived'] == 0
jo3 = df['Age'].isnull()
df.loc[(jo1) & (jo2) & (jo3), 'Age'] = 26

jo2 = df['Survived'] == 1
df.loc[(jo1) & (jo2) & (jo3), 'Age'] = 20

jo1 = df['Pclass'] == 3
jo2 = df['Survived'] == 0
jo3 = df['Age'].isnull()
df.loc[(jo1) & (jo2) & (jo3), 'Age'] = 43

jo2 = df['Survived'] == 1
df.loc[(jo1) & (jo2) & (jo3), 'Age'] = 35

◇ STEP 3 文字データの列を数値に変換する

# 特徴量として利用する列のリスト
col = ['Pclass', 'Age', 'SibSp', 'Parch', 'Fare']

x = df[col]
t = df['Survived']

# Sex列は文字の列なのでダミー変数化
dummy = pd.get_dummies(df['Sex'], drop_first = True)
x = pd.concat([x, dummy], axis = 1)
x.head(2)

【実行結果】 output_005.png

◇ STEP 4 ランダムフォレストの選定

# ランダムフォレストのインポート
from sklearn.ensemble import RandomForestClassifier
x_train, x_test, y_train, y_test = train_test_split(x, t, test_size = 0.2, 
random_state = 0)
model = RandomForestClassifier(n_estimators = 200, random_state = 0)

☆☆ モデル変数

モデル変数 = RandomForestClassifier(n_estimators=〇, random_state=〇, max_depth=△)

※ n_estimatorsで作成する木の数を指定

※ 木の深さの最大値は,すべての木で共通

◇ STEP 5 モデルの学習

model.fit(x_train, y_train)

print(model.score(x_train, y_train))
print(model.score(x_test, y_test))

【実行結果】

0.9887640449438202
0.8715083798882681

◇ STEP 6 単純な決定木分類と比較する

from sklearn import tree
model2 = tree.DecisionTreeClassifier(random_state = 0)
model2.fit(x_train, y_train)

print(model2.score(x_train, y_train))
print(model2.score(x_test, y_test))

【実行結果】

0.9887640449438202
0.8156424581005587

◇ STEP 7 特徴量の重要度を確認する

importance = model.feature_importances_ # 特徴量重要度

# 列との対応がわかりやすいようにシリーズ変換
pd.Series(importance, index = x_train.columns)

【実行結果】

Pclass    0.079546
Age       0.323012
SibSp     0.045682
Parch     0.032854
Fare      0.265573
male      0.253334
dtype: float64

【ハンズオン6-2の継続】アンサンブル学習 (ensemble learning)

一方で決定木だけでなく,さまざまな予測モデルを作成して,最終的に1つの予測結果を出す手法のことをアンサンブル学習と呼ぶ

アンサンブル学習は,大きくわけてバンギングブースティングという手法に類別することができる

バギング

ブースティング

ブースティングの手法の中に最も基本的なのはアダブーストである

【Pythonハンズオン6-2】の継続として,以下を行う

◇ STEP 8 アダブーストを実装する

# アダブーストのインポート
from sklearn.ensemble import AdaBoostClassifier

# ベースとなるモデル
from sklearn.tree import DecisionTreeClassifier

x_train, x_test, y_train, y_test = train_test_split(x, t,
test_size = 0.2, random_state = 0)
# 最大の深さ5の決定木を何個も作っていく
base_model = DecisionTreeClassifier(random_state = 0,
max_depth = 5)

# 決定木を500個作成
model = AdaBoostClassifier(n_estimators = 500,
random_state = 0, base_estimator = base_model)
model.fit(x_train,y_train) # 学習

print(model.score(x_train, y_train)) # 訓練データの正解率
print(model.score(x_test, y_test)) # テストデータの正解率

【実行結果】

0.9887640449438202
0.8100558659217877

☆☆ モデルの作成

変数=AdaBoostClassifier(n_estimator=モデル数,random_state=数値,base_model=決定木などのモデル)

※ ベースモデルには,決定木やロジスティック回帰等を指定することができる(一般的には決定木を利用)

6.4 分類モデルの評価

第3回のモデルの評価では,皆さんは精度(Accuracy)と混同行列(confution_matrix)を扱って頂いた.その他さまざまなな性能評価の指標もある.

【ハンズオン6-3】適合率(precision),再現率(recall),F値(f1-score)

【ハンズオン6-2】における客船の沈没事故のデータを利用し続き,分類の予測性能評価の実装から手法を理解してみましょう

◇ STEP 1 データの準備

# モジュールの読み込み
import pandas as pd

# データの準備
df = pd.read_csv('https://www.es4.eedept.kobe-u.ac.jp/~chensinan/share/Survived.csv')
df = df.fillna(df.mean())

x = df[['Pclass', 'Age']]
t = df['Survived']

◇ STEP 2 モデルの準備

# モデルの準備
from sklearn import tree

model = tree.DecisionTreeClassifier(max_depth = 2,
random_state = 0)
model.fit(x, t)

◇ STEP 3 適合率,再現率,F値を一括で計算

classification_report関数で再現率と適合率を一括で計算してみましょう

from sklearn.metrics import classification_report

pred = model.predict(x)
out_put = classification_report(y_pred = pred, y_true = t)
print(out_put)

【実行結果】 output_006.png

☆☆ 適合率(precision)

precision.png
図8:雨と予測した日数のうち実際に雨がふった日数の比率

☆☆ 再現率(recall)

recall.png
図9:実際に雨は降った件数のうち,雨が降ると予測した件数の比率

☆☆ F値(f1-score)

◇ STEP 4 classification_report関数にパラメータ引数を指定

out_put = classification_report(y_pred = pred, y_true = t,
output_dict = True)

# out_putをデータフレームに変換
pd.DataFrame(out_put)

【実行結果】 output_007.png

他指標には,特異度,偽陽性率,ROC曲線,AUC(曲線下面積)等もある


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS