はじめに
前回、線形SVMをやりましたので今回は他の方法(RBFカーネル 、決定木、ランダムフォレスト、ナイーブベイズ)をやっていきます。
結果の見方
行(たて)が正解(実際に出された手)、列(よこ)が予測となります。
機械学習では出す手を予測するので勝ち手を選んだことにして勝敗を出しています。※勝ち手を選んだとこまでは現状でプログラムを組んでいません。
- 黄色セルは、例えばチョキ(C)を出すと予測して勝ち手のグー(G)出した、実際に出された手はチョキ(C)なので勝ちになります。
- 赤色セルは、例えばチョキ(C)が出ると予測して勝ち手のグー(G)出した、実際に出された手はパー(P)なので負けとなります。
- 白色セルは、例えばチョキ(C)が出ると予測して勝ち手のグー(G)出した、実際に出された手はグー(G)なので引き分けとなります。
線形SVM
ソースコード
線形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カーネル
カーネル法は「データを別の特徴空間に移してから線形回帰を行う」という下図のイメージ
ソースコード
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カーネルが圧倒的ですが、勝率だと決定木が一番となります。
何にしても機械学習の方が結果が良かったというのが一番の成果です。
次回はもう少し踏み込んだ検証をしていきます。