デジタル・デザイン・ラボラトリーな日々

アラフィフプログラマーが数学と物理と英語を基礎からやり直す。https://qiita.com/yaju

機械学習の勉強再開 RBFカーネル 、決定木、ランダムフォレスト、ナイーブベイズ

はじめに

前回、線形SVMをやりましたので今回は他の方法(RBFカーネル 、決定木、ランダムフォレスト、ナイーブベイズ)をやっていきます。

結果の見方

f:id:Yaju3D:20210104100225p:plain

行(たて)が正解(実際に出された手)、列(よこ)が予測となります。
機械学習では出す手を予測するので勝ち手を選んだことにして勝敗を出しています。※勝ち手を選んだとこまでは現状でプログラムを組んでいません。

  • 黄色セルは、例えばチョキ(C)を出すと予測して勝ち手のグー(G)出した、実際に出された手はチョキ(C)なので勝ちになります。
  • 赤色セルは、例えばチョキ(C)が出ると予測して勝ち手のグー(G)出した、実際に出された手はパー(P)なので負けとなります。
  • 白色セルは、例えばチョキ(C)が出ると予測して勝ち手のグー(G)出した、実際に出された手はグー(G)なので引き分けとなります。

線形SVM

yaju3d.hatenablog.jp

ソースコード

線形SVMのmodelのみをコメントアウトし、他はコメントにします。

# 線形SVM
model = svm.SVC(kernel='linear', C=2.5, max_iter=5000, random_state=3383)
# RBFカーネル
#model = svm.SVC(kernel="rbf", C=1.0, max_iter=5000, random_state=3383)
# 決定木
#model = DecisionTreeClassifier()
# ランダムフォレスト
#model = RandomForestClassifier(random_state=3383)
# ナイーブベイズ
#model = GaussianNB()

結果

0.6666666666666666

C G P
C 13 2 2
G 2 9 4
P 5 1 10

32勝11敗5分け

RBFカーネル

カーネル法は「データを別の特徴空間に移してから線形回帰を行う」という下図のイメージ

f:id:Yaju3D:20210215113826p:plain
RBFカーネル
www.shoeisha.co.jp

ソースコード

RBFカーネルのmodelのみをコメントアウトし、他はコメントにします。

ハイパーパラメータのデフォルトは、C=1.0, gamma= 1/特徴数 となっています。
今回は下手にハイパーパラメータをいじるよりデフォルトの方が結果が良かったです。

# 線形SVM
#model = svm.SVC(kernel='linear', C=2.5, max_iter=5000, random_state=3383)
# RBFカーネル
model = svm.SVC(kernel="rbf", C=1.0, max_iter=5000, random_state=3383)
# 決定木
#model = DecisionTreeClassifier()
# ランダムフォレスト
#model = RandomForestClassifier(random_state=3383)
# ナイーブベイズ
#model = GaussianNB()

結果

0.7083333333333334

C G P
C 11 3 3
G 0 13 2
P 4 2 10

34勝9敗5分け

決定木

決定木とは木構造を用いて分類や回帰を行う機械学習の手法 qiita.com

ソースコード

決定木のmodelのみをコメントアウトし、他はコメントにします。

# 線形SVM
#model = svm.SVC(kernel='linear', C=2.5, max_iter=5000, random_state=3383)
# RBFカーネル
#model = svm.SVC(kernel="rbf", C=1.0, max_iter=5000, random_state=3383)
# 決定木
model = DecisionTreeClassifier()
# ランダムフォレスト
#model = RandomForestClassifier(random_state=3383)
# ナイーブベイズ
#model = GaussianNB()

結果

0.6041666666666666

C G P
C 12 2 3
G 2 9 4
P 1 7 8

29勝7敗12分け

ランダムフォレスト

「三人寄れば文殊の知恵」ということわざを実現を体現するのがアンサンブル学習です。
ランダムフォレストとは、アンサンブル学習のバギングをベースに、少しずつ異なる決定木をたくさん集めたものです。決定木単体では過学習しやすいという欠点があり、ランダムフォレストはこの問題に対応する方法の1つです。
決定株、決定木、ランダム森、株が伸びると木になり、木が集まると森になります。 qiita.com

ソースコード

ランダムフォレストのmodelのみをコメントアウトし、他はコメントにします。

# 線形SVM
#model = svm.SVC(kernel='linear', C=2.5, max_iter=5000, random_state=3383)
# RBFカーネル
#model = svm.SVC(kernel="rbf", C=1.0, max_iter=5000, random_state=3383)
# 決定木
#model = DecisionTreeClassifier()
# ランダムフォレスト
model = RandomForestClassifier(random_state=3383)
# ナイーブベイズ
#model = GaussianNB()

結果

0.6041666666666666

C G P
C 10 3 4
G 1 11 3
P 2 6 8

29勝8敗11分け

ナイーブベイズ

Pythonでは3種類(ガウスモデル、ベルヌーイ分布、多項分布モデル)があるが、今回はガウスモデルを使用する。 qiita.com

ソースコード

ナイーブベイズのmodelのみをコメントアウトし、他はコメントにします。
Pythonでは3種類(ガウスモデル、ベルヌーイ分布、多項分布モデル)があるが。今回はガウスモデルを使用する。
その後、ガウスモデル以外もやってみたのですが、ベルヌーイ分布の結果はさほど良くなく、多項分布モデルはエラーで動作しませんでした。

# 線形SVM
#model = svm.SVC(kernel='linear', C=2.5, max_iter=5000, random_state=3383)
# RBFカーネル
#model = svm.SVC(kernel="rbf", C=1.0, max_iter=5000, random_state=3383)
# 決定木
#model = DecisionTreeClassifier()
# ランダムフォレスト
#model = RandomForestClassifier(random_state=3383)
# ナイーブベイズ
model = GaussianNB()

結果

0.6458333333333334

C G P
C 10 4 3
G 2 11 2
P 4 2 10

31勝10敗7分け

最終結果

種類 Python版勝敗 R言語版勝敗
線形SVM 32勝11敗5分け(勝率0.744) 32勝11敗5分(勝率0.744)
RBFカーネル 34勝9敗5分け(勝率0.790) 32勝9敗7分(勝率0.780)
決定木 29勝7敗12分け(勝率0.805) 32勝10敗6分(勝率0.761)
ランダムフォレスト 29勝8敗11分け(勝率0.783) 32勝9敗7分(勝率0.780)
ナイーブベイズ 31勝10敗7分け(勝率0.756) 33勝9敗6分(勝率0.785)

yaju3d.hatenablog.jp r-std.hatenablog.com

当時のブログによる2017年の結果も踏まえて比較してみます。

種類 勝敗
自作アルゴリズム 32勝9敗7分(勝率0.780)
研究所公式 29勝8敗11分(勝率0.783)

ソースコード

import pandas as pd
import numpy as np
import urllib.request
from io import StringIO
from sklearn import svm
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB
import random

url = "https://raw.githubusercontent.com/yaju/Sazae_R/master/2017sze.csv"
# データの読み込み
res = urllib.request.urlopen(url)
res = res.read().decode("utf-8")
sze_row = pd.read_csv(StringIO(res), header=0)
sze = sze_row.iloc[:, :-1]

# One-hotエンコーディング
# sze = pd.get_dummies(sze, columns=['X1', 'X2', 'X3'])
# sze

ct = ColumnTransformer([('onehot', OneHotEncoder(sparse=False), [1,2,3])])
columns = ['X1_C', 'X1_G', 'X1_P',   'X2_C', 'X2_G', 'X2_P', 'X3_C', 'X3_G', 'X3_P']
df = pd.DataFrame(ct.fit_transform(sze), columns=columns)
sze = sze.drop(['X1', 'X2', 'X3'], axis=1)
sze = pd.concat([sze, df], axis=1)
#sze

#1992年~2016年までを学習用、2017年分をテスト用とする
train = range(0, 1253)
test = range(1254, 1302)

x_train = sze.iloc[train, 1:]
y_train = sze.iloc[train, 0]
x_test = sze.iloc[test, 1:]
y_test = sze.iloc[test, 0]
#y_train

# 分類器svm
#seedはサザエさん(3383)とする
# 線形SVM
#model = svm.SVC(kernel='linear', C=2.5, max_iter=5000, random_state=3383)
# RBFカーネル
model = svm.SVC(kernel="rbf", C=1.0, max_iter=5000, random_state=3383)
# 決定木
#model = DecisionTreeClassifier()
# ランダムフォレスト
#model = RandomForestClassifier(random_state=3383)
# ナイーブベイズ
#model = GaussianNB()

# 学習
model.fit(x_train, y_train) 

pred = model.predict(x_test)
tab = pd.crosstab(y_test, pred)
# 識別率
print(accuracy_score(y_test, pred))

tab
# print(y_test)
# print(pred)

最後に

勝数だけならRBFカーネルが圧倒的ですが、勝率だと決定木が一番となります。
何にしても機械学習の方が結果が良かったというのが一番の成果です。

次回はもう少し踏み込んだ検証をしていきます。

スポンサーリンク