14952円,車用品・バイク用品 , バイク用品 , バイクウェア・プロテクター , ブーツ,26cm,ブラウン,トーヨコ(東横部品製作所),/graduality1395588.html,ロングブーツ,thecaroltapes.com,バックチャック付,高級牛本革仕様 14952円,車用品・バイク用品 , バイク用品 , バイクウェア・プロテクター , ブーツ,26cm,ブラウン,トーヨコ(東横部品製作所),/graduality1395588.html,ロングブーツ,thecaroltapes.com,バックチャック付,高級牛本革仕様 ロングブーツ 高級牛本革仕様 バックチャック付 ブラウン 完売 トーヨコ 26cm 東横部品製作所 ロングブーツ 高級牛本革仕様 バックチャック付 ブラウン 完売 トーヨコ 26cm 東横部品製作所 14952円 ロングブーツ 高級牛本革仕様 バックチャック付 ブラウン 26cm トーヨコ(東横部品製作所) 車用品・バイク用品 バイク用品 バイクウェア・プロテクター ブーツ 14952円 ロングブーツ 高級牛本革仕様 バックチャック付 ブラウン 26cm トーヨコ(東横部品製作所) 車用品・バイク用品 バイク用品 バイクウェア・プロテクター ブーツ

ロングブーツ 高級牛本革仕様 バックチャック付 ブラウン 完売 激安挑戦中 トーヨコ 26cm 東横部品製作所

ロングブーツ 高級牛本革仕様 バックチャック付 ブラウン 26cm トーヨコ(東横部品製作所)

14952円

ロングブーツ 高級牛本革仕様 バックチャック付 ブラウン 26cm トーヨコ(東横部品製作所)











【カラー・サイズ】
ブラウン・26cm

key:カジュアルブーツ

ロングブーツ 高級牛本革仕様 バックチャック付 ブラウン 26cm トーヨコ(東横部品製作所)

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

5段階に調節可能です。 カラバリ レザー リング チャーム 太 チョーカー

図書館に寄った時に「Excelでわかる機械学習 超入門」と「Excelでわかるディープラーニング超入門」という本を見つけたので、借りてきました。
後で気がついたのですが、「Excelでわかるディープラーニング超入門」については、2018/10/27にKindle版を既に購入済みでした。

5章-3に「重みと閾値は、こんな簡単な例題でも計47個あります。」と記載があったのですが、説明がなくてどうやって47個が求まるのか分からなかった。
5章-4の「誤差伝搬法をExcelで体験」のところにExcelの表示があって、重みと閾値を数えたら47個あることが分かった。
一応、悩んだりしたので記事にしておく。

4x3画素の白黒2値画像として読み取った手書き数字「0」、「1」を識別するニューラルネットワークを作成しましょう。学習用画像データは55枚とします。

入力層に4x3画素の12個、隠れ層が3つ、出力層が2つの構成となっています。

各隠れ層に重み12個と閾値が1つ、各出力層に重み3つ閾値が1つ

自分の場合、機械学習の勉強って細かいところに躓いてしまって、なかなか先に進まないんだよな。

【通気性の良い背メッシュ♪】【4脚までスタッキング可能!!】【送料無料(北海道・沖縄・離島を除く)】【ポイント10倍♪9/26(日)迄】 関家具 ミーティングチェア フォード[ford][1脚][ブラック色][肘なし][4本脚][背:メッシュ][座:クッション][完成品]会議室,オフィス,SOHO,病院,福祉施設,市役所,公共施設,ご自宅向け

以前、使用データの解析をして「Grate」と「Crate」と「Prate」のデータの求め方が分かりました。
yaju3d.hatenablog.jp

出来れば使用するデータは最小限にしたいので、「Grate」と「Crate」と「Prate」が結果に寄与(意味がある?)しているのかを検証します。

このサザエさんじゃんけんの使用データは、もともと下記サイトのYukiさんが考案したものです。

使用するデータは「2017sze.csv」になります。各列の内容は次の通りです。
X:サザエさんの出した手
X1:サザエさんが1回前に出した手
X2:サザエさんが2回前に出した手
X3:サザエさんが3回前に出した手
Q:四半期初の場合は1、それ以外は0
Grate:グーチョキパーが四半期内で均等に出ると仮定した場合のグーの出やすさ
Crate:グーチョキパーが四半期内で均等に出ると仮定した場合のチョキの出やすさ
Prate:グーチョキパーが四半期内で均等に出ると仮定した場合のパーの出やすさ
機械学習でサザエさんと本気でじゃんけんしてみた① - アクチュアリーはデータサイエンスの夢を見るか?

yaju3d.hatenablog.jp

前回のソースコードでは最後の日付のみが削除されていましたが、今回はGrateとCrateとPrateと日付を削除します。

sze = sze_row.iloc[:, :-1]
# ↓  GrateとCrateとPrateと日付を削除
sze = sze_row.iloc[:, :-4]

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

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

0.6666666666666666

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

32勝11敗5分け

0.7083333333333334

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

34勝9敗5分け

0.7083333333333334

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

34勝9敗5分け

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

34勝9敗5分け

0.6666666666666666

C G P
C 6 7 4
G 0 13 2
P 0 3 13

32勝9敗7分け

種類 今回使用データ版勝敗 前回使用データ版勝敗
線形SVM 32勝11敗5分け(勝率0.744) 32勝11敗5分(勝率0.744)
RBFカーネル 34勝9敗5分け(勝率0.790) 34勝9敗5分け(勝率0.790)
決定木 34勝9敗5分け(勝率0.790) 29勝7敗12分け(勝率0.805)
ランダムフォレスト 34勝9敗5分け(勝率0.790) 29勝8敗11分け(勝率0.783)
ナイーブベイズ 32勝9敗7分け(勝率0.780) 31勝10敗7分け(勝率0.756)

結果だけ見ると「Grate」と「Crate」と「Prate」のデータは結果に寄与してないようです。
逆に存在することで結果が悪くなってしまっていました。

次は久しぶりにTensorFlowでDeepLearningとして組んでみます。

【送料無料】 8ピース/個スケートボードベアリングABEC11 Precision 608 2RS.ロングボード.ミニクルーザー.スクーター.ローラースケート.インラインホイール用のスペースとスピードワッシャー付き

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

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

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

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カーネル
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カーネルが圧倒的ですが、勝率だと決定木が一番となります。
何にしても機械学習の方が結果が良かったというのが一番の成果です。

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

マルチツール キャプテンスタッグ(CAPTAIN STAG) Z-PRO 多機能ハサミ(収納ケース付) UM-1

前回、線形SVMの改善をしまして次の段階に行こうかなと思ったのですが・・・ yaju3d.hatenablog.jp

その前に下記の使用データがどうやって作成されているのかを調べておきたい。
https://raw.githubusercontent.com/yaju/Sazae_R/master/2017sze.csv

このサザエさんじゃんけんの使用データは、もともと下記サイトのYukiさんが考案したものです。

使用するデータは「2017sze.csv」になります。各列の内容は次の通りです。
X:サザエさんの出した手
X1:サザエさんが1回前に出した手
X2:サザエさんが2回前に出した手
X3:サザエさんが3回前に出した手
Q:四半期初の場合は1、それ以外は0
Grate:グーチョキパーが四半期内で均等に出ると仮定した場合のグーの出やすさ
Crate:グーチョキパーが四半期内で均等に出ると仮定した場合のチョキの出やすさ
Prate:グーチョキパーが四半期内で均等に出ると仮定した場合のパーの出やすさ
機械学習でサザエさんと本気でじゃんけんしてみた① - アクチュアリーはデータサイエンスの夢を見るか?

この中で「Grate」と「Crate」と「Prate」のデータがありますが、これがどういう計算で 求められているのかを今度のために知る必要があります。

「四半期内で均等に出ると仮定した場合の出やすさ」という説明とデータの値を見ればなんとなくのイメージはつきます。 出る回数が同じなら3等分なので、0.333333333になり、何れかが出た場合は出やすさの値が減っていく。
イメージは分かるのですが、どうしたら下記のような数値になるのかが分かりませんでした。

X X1 X2 X3 Q Grate Crate Prate DATE
C G P G 1 0.333333333 0.333333333 0.333333333 1992/1/5
P C G P 0 0.361111111 0.277777778 0.361111111 1992/1/12
G P C G 0 0.393939394 0.303030303 0.303030303 1992/1/19
C G P C 0 0.333333333 0.333333333 0.333333333 1992/1/26
C C G P 0 0.37037037 0.259259259 0.37037037 1992/2/2
P C C G 0 0.416666667 0.166666667 0.416666667 1992/2/9
G P C C 0 0.476190476 0.19047619 0.333333333 1992/2/16
C G P C 0 0.388888889 0.222222222 0.388888889 1992/2/23
P C G P 0 0.466666667 0.066666667 0.466666667 1992/3/1
G P C G 0 0.583333333 0.083333333 0.333333333 1992/3/8
C G P C 0 0.444444444 0.111111111 0.444444444 1992/3/15
P C G P 0 0.666666667 -0.333333333 0.666666667 1992/3/22
G P C G 0 1.333333333 -0.666666667 0.333333333 1992/3/29

推測

このデータは四半期内(1月~3月)で13行x3=39個のデータがあります。
初回は出る回数が同じなら3等分なので、各13/39というのは直ぐに分かりました。
次行が難しく、0.277777778にどうしたらなるのか、イチかバチか「0.277777778」でググったら、5/18=0.277777778となることが分かりました。
それなら倍にすれば、10/36となります。なんとなくこの予想はあってそうです。
次行の 0.303030303は、10/33 になるのは直ぐに分かりました。

Grate Crate Prate
1 13/39 13/39 13/39
2     10/36    
3     10/33    

現時点で分かったのは上表で、これを見る限り分母と分子が3ずつ減っていることが分かりました。
次の展開として出た手を順にカウントしてみました。  

Grate Crate Prate
1 0 0 0
2 0 1 0
3 0 1 1
4 1 1 1
5 1 2 1
6 1 3 1
7 1 3 2
8 2 3 2
9 2 4 2
10 2 4 3
11 3 4 3
12 3 5 3
13 3 5 4

4行目は全部1となり使用データ上の数値でも0.333333333と均等になっていますし、全体的に出た手の件数と使用データの数値の割合的にあってそうです。
そこで分母は行毎に3減らし、分子は出た数だけ3減らすようにしていきました。

Grate Crate Prate
1 =(13-0*3)/39 =(13-0*3)/39 =(13-0*3)/39
2 =(13-0*3)/36 =(13-1*3)/36 =(13-0*3)/36
3 =(13-0*3)/33 =(13-1*3)/33 =(13-1*3)/33
4 =(13-1*3)/30 =(13-1*3)/30 =(13-1*3)/30
5 =(13-1*3)/27 =(13-2*3)/27 =(13-1*3)/27
6 =(13-1*3)/24 =(13-3*3)/24 =(13-1*3)/24
7 =(13-1*3)/21 =(13-3*3)/21 =(13-2*3)/21
8 =(13-2*3)/18 =(13-3*3)/18 =(13-2*3)/18
9 =(13-2*3)/15 =(13-4*3)/15 =(13-2*3)/15
10 =(13-2*3)/12 =(13-4*3)/12 =(13-3*3)/12
11 =(13-3*3)/9 =(13-4*3)/9 =(13-3*3)/9
12 =(13-3*3)/6 =(13-5*3)/6 =(13-3*3)/6
13 =(13-3*3)/3 =(13-5*3)/3 =(13-4*3)/3

Excelで計算させたら、見事に使用データ上の数値と一致しました。
※各四半期内(1月~3月)の時期によっては11行や12行になったりするので、その時に合わせて分母や分子の数を調整する必要があります。

これで使用データの作り方は理解できましたので、2019年以降のデータは自分で作れるようになります。

バム オーボエイングリッシュホルン用 トレッキングケース ブラック 3031SN

前回、R言語の線形SVMをPythonに移植しました。 yaju3d.hatenablog.jp

Pythonやscikit-learn に慣れていなかったので、もう少しいい方法があるのではないかと再調査しました。

結論では、正解ラベル側には文字列が使えますが、学習データ側は文字列が使えないため数値型に変換する必要があります。
長くなったのでQiitaに別記事としました。 ココナッツのさわやかな水溶性の香料です。 marugo(マルゴ) 国内製造 ココナッツエッセンス (500g) 水溶性香料 製菓・製パン等の香り付けに

変更前の数値型変換ですが、イケてないですよね。

sze_row.loc[sze_row.X1 == "G", "X1"] = 1
sze_row.loc[sze_row.X1 == "C", "X1"] = 2
sze_row.loc[sze_row.X1 == "P", "X1"] = 3
sze_row.loc[sze_row.X2 == "G", "X2"] = 1
sze_row.loc[sze_row.X2 == "C", "X2"] = 2
sze_row.loc[sze_row.X2 == "P", "X2"] = 3
sze_row.loc[sze_row.X3 == "G", "X3"] = 1
sze_row.loc[sze_row.X3 == "C", "X3"] = 2
sze_row.loc[sze_row.X3 == "P", "X3"] = 3

これを改善しました。

# ラベルエンコーディング
rating = {'G' : 1, 'C' : 2, 'P' : 3}
sze_row.X1 = sze_row.X1.map(lambda x : rating[x])
sze_row.X2 = sze_row.X2.map(lambda x : rating[x])
sze_row.X3 = sze_row.X3.map(lambda x : rating[x])

線形SVMですが、kernel='linear' を指定する方法とLinearSVCを方法の2種類あります。
これが同じかというと微妙に違うの結果も変わってきます。
When should one use LinearSVC or SVC? - StackOverflow

LinearSVCがLIBLINEARライブラリーを基にしているに対し、SVC(kernel='linear')はLIBSVMライブラリーを基にしている。
LinearSVCの場合、デフォルトはヒンジ損失の2乗(loss='squared_hinge')を最小化するように設定されています。

LIBSVMはカーネル法を用いたサポートベクターマシン (SVM) の学習に使うSMOアルゴリズムを実装しており、分類と回帰に対応している[1]。 LIBLINEARは線形SVMと、座標降下法(英語版)アルゴリズムを用いて学習するロジスティック回帰を実装している LIBSVM - wikipedia

SVC(kernel='linear')

model = svm.SVC(kernel='linear', C=2.5, max_iter=5000, random_state=3383)

結果

0.6458333333333334

C G P
C 8 6 3
G 0 13 2
P 3 3 10

31勝10敗8分けとなります。

LinearSVC

デフォルトは、loss='squared_hinge' なので指定しなくても同じになります。

#model = svm.LinearSVC(C=2.5, max_iter=5000, random_state=3383)
model = svm.LinearSVC(loss='squared_hinge', C=2.5, max_iter=5000, random_state=3383)

結果

0.625

C G P
C 5 8 4
G 0 13 2
P 1 3 12

30勝11敗7分け

LinearSVCの補足

loss='hinge' に変更すると結果がかなり悪くなります。

model = svm.LinearSVC(loss='hinge', C=2.5, max_iter=20000, random_state=3383)

max_iter=5000 では下記の警告が発生します。Google翻訳すると「Liblinearは収束に失敗しました。反復回数を増やしてください。 」ということなので、max_iter=20000 まで上げたところ警告が出なくなりました。

/usr/local/lib/python3.6/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)

結果

0.5

C G P
C 4 6 7
G 0 6 9
P 0 2 14

24勝15敗9分け

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
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]
# ラベルエンコーディング
rating = {'G' : 1, 'C' : 2, 'P' : 3}
sze.X1 = sze.X1.map(lambda x : rating[x])
sze.X2 = sze.X2.map(lambda x : rating[x])
sze.X3 = sze.X3.map(lambda x : rating[x])
#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]
# 分類器svm
#seedはサザエさん(3383)とする
model = svm.SVC(kernel='linear', C=2.5, max_iter=5000, random_state=3383)
# 学習
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)

同じ列の優先順序

同じ列に異なる数値があるとモデルのデータによってはある種の順序(0 < 1 < 2)であると誤解するとのことで、値の順番を下記のように変更してみました。
結果は31勝10敗8分けと変わらなかったです。

rating = {'G' : 1, 'C' : 2, 'P' : 3}
                       ↓
rating = {'G' : 3, 'C' : 2, 'P' : 1}

One Hot表現に変更

説明変数側(学習データ)は回帰でも分類でも基本的 One Hot表現を使用するのが一般的なようです。こうすると優先順序が関係なくなるからです。

# ラベルエンコーディング
rating = {'G' : 1, 'C' : 2, 'P' : 3}
sze.X1 = sze.X1.map(lambda x : rating[x])
sze.X2 = sze.X2.map(lambda x : rating[x])
sze.X3 = sze.X3.map(lambda x : rating[x])

上記の部分を下記に変更します。

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

pandasのget_dummiesを使うとカラム指定で、One-hotエンコーディングができます。
変換元の列は削除され、末尾にOne-hotの列が追加されます。

変換前

X X1 X2 X3 Q Grate Crate Prate
C G P G 1 0.333333 0.333333 0.333333

変換後

X Q Grate Crate Prate X1_C X1_G X1_P X2_C X2_G X2_P X3_C X3_G X3_P
C 1 0.333333 0.333333 0.333333 0 1 0 0 0 1 0 1 0

結果

0.6666666666666666

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

32勝11敗5分け

OneHotEncoderの使用

代引き手数料無料・送料無料・延長保証申込可 象印 1斤タイプ ホームベーカリー パンくらぶ BB-HE10-WA ホワイト 【送料無料】【KK9N0D18P】

pandasのget_dummiesは便利だけど用途によっては使用を控えた方がいいようなので、OneHotEncoderの使い方も知っておく必要がある。
get_dummiesと同じことを、OneHotEncoderで実現してみました。
ColumnTransformerで複数列を変換できますが、列名ではなくインデックス番号の指定する。
numpy.ndarray で変換されるので一旦データフレームに変換、元のデータフレームで変換前の文字列の列を削除して変換されたデータフレームと結合させた。

from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
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)

参照

結果からすれば学習データはOne Hot表現にして問題ないですね、実際に結果を良かったですし。
One Hot表現にすることでクロス集計(tab)のところを修正する必要があるのかと気にしていたのですが、全く修正なしでした。
これからは、One Hot表現でやっていきます。

これでようやっと次の段階に入ります。

  • RBFカーネルを用いたSVM
  • randomForest
  • 決定木
  • naive bayes
[400g入り][ベーコンジャーキー][山形県][楯岡ハム] [ベーコンジャーキー100g×4袋] おつまみ カルパス,サラミ,ドライソーセージ好きな方必見 珍味 訳ありではなく正規品 送料無料 おやつ ポイント消化 山形 100g×4袋 セット 大容量 メール便

2021年最初の記事となります。
昨年は機械学習の勉強に身が入らなかったため、はてな側に記事を書くことも少なったです。
今年は、競馬予想とか株価予想とかをやってみたいなと思うようになったので、改めて機械学習の勉強を再開することにしました。

競馬予想とか株価予想とかをやる前に、自分には先に片付けるものがあります。「サザエさんのじゃんけん データ分析」です。
サザエさんのじゃんけんをきちんとディープラーニングとかでやってみたいなと思ってはいたんですが、機械学習はこれまでやってきたパズル的にプログラムを組むと違って、理論的に理解した上でプログラムを組む必要があるわけです。本を読んだりしてもピンとこないんです。

ディープラーニングにこだわることはやめて、せっかく他の方法の機械学習でやり方を示して頂いたわけですから、まずこれを理解させていただきます。 r-std.hatenablog.com

この参考サイトは R言語で作成されていますので、これをPythonに移植することから始めることにしました。
データが2017年と古いですが学ぶ上では関係ありません。

以前R言語をやったときはWindowsでしたが、MacになったのでMacにインストールします。
qiita.com

作業ディレクトリの変更

ファイルメニューのRStudio→PreferenceまたはTools→Global Optionで環境設定を開きます。
GeneralのDefault working directoryを初期値「~」から変更します。
Windows時に使用していたフォルダがあったので「~/workspace/Sazae_R」にしています。
作業フォルダを変更したら、R Studioを起動し直す必要があります。

ちなみにコマンドで「getwd()」とすると現在の作業フォルダが見れます。

R言語

###データの読み込み
sze_row=read.csv("2017sze.csv",header = T, stringsAsFactors=T)
sze=sze_row[,-9]
#1992年~2016年までを学習用、2017年分をテスト用とする
train=c(1:1254)
test=c(1255:1302)
###seedはサザエさん(3383)とする
set.seed(3383)
###線形SVM
library(e1071)
sze.svm=svm(X~.,sze[train,],method = "C-classification",
           kernel = "linear",
           cost = 2.5 )
test.svm=predict(sze.svm, sze[test,])
svm.tab=table(sze[test,1],test.svm)
svm.tab
sum(svm.tab[row(svm.tab)==col(svm.tab)])/sum(svm.tab) #識別率

結果

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

32勝11敗5分

苦労したところ

sze.svm=svm のところで、"Need numeric dependent variable for regression."のエラーが出て解決するまで時間がかかりました。
Rのバージョンを4にしたことで、read_csvのデフォルト設定が変わっていたことが原因でした。

qiita.com

Python

Google Colaboratoryで動作するようにしています。
Google Colaboratoryで複数行コメントする場合、コメントする行を選択して、[Command] + [/] を押しますと、"#" でコメントされます。外す場合も同様にします。
Pythonの複数行コメントにはダブルクォーテーション3つで挟むというのがあるのですが、Google Colaboratoryでは文字列として結果に表示されてしまうためです。

www.atmarkit.co.jp

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
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_row.loc[sze_row.X == "G", "X"] = 1
sze_row.loc[sze_row.X == "C", "X"] = 2
sze_row.loc[sze_row.X == "P", "X"] = 3
sze_row.loc[sze_row.X1 == "G", "X1"] = 1
sze_row.loc[sze_row.X1 == "C", "X1"] = 2
sze_row.loc[sze_row.X1 == "P", "X1"] = 3
sze_row.loc[sze_row.X2 == "G", "X2"] = 1
sze_row.loc[sze_row.X2 == "C", "X2"] = 2
sze_row.loc[sze_row.X2 == "P", "X2"] = 3
sze_row.loc[sze_row.X3 == "G", "X3"] = 1
sze_row.loc[sze_row.X3 == "C", "X3"] = 2
sze_row.loc[sze_row.X3 == "P", "X3"] = 3
sze = sze_row.iloc[:, :-1]
#1992年~2016年までを学習用、2017年分をテスト用とする
train = range(0, 1253)
test = range(1254, 1301)
x_train = sze.iloc[train, 1:].to_numpy(dtype=int)
y_train = sze.iloc[train, 0].to_numpy(dtype=int)
x_test = sze.iloc[test, 1:].to_numpy(dtype=int)
y_test = sze.iloc[test, 0].to_numpy(dtype=int)
# 分類器svm seedはサザエさん(3383)とする
model = svm.LinearSVC(C=2.5, max_iter=5000, random_state=3383)
# 学習
model.fit(x_train, y_train)
pred = model.predict(x_test)
tab = pd.crosstab(y_test, pred)
# 識別率
print(accuracy_score(y_test, pred))
tab

結果

1 2 3
1 13 0 2
2 8 4 5
3 3 0 13

30勝8敗10分

R言語版と結果が違いますが、機械学習なので多少違いは出るのは仕方ない。
R言語版は、Cが13勝です。Python版は、1=Gが13勝になっています。

結果の見方

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

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

CGPに順序変更

R言語版は文字型が自動的に因子型になっているので、アルファベット順のCGPになっています。
Python版でも、1=G、2=C、3=Pに変換していましたが、これを 1=C、2=G、3=Pに修正して結果を出したところ勝率が減ってしまいました。これなら変更しない方がいいですよね。

1 2 3
1 11 4 2
2 4 6 5
3 4 2 10

27勝13敗8分

苦労したところ

これだけなのに、ものすごく苦労しています。
エラーが幾つか出たのですが、それを解決させるまでが大変。アルゴリズムが悪いわけではないのでデバッグするわけではない。地道にエラーで検索して解決方法を探っていく。
比較として、Irisのdatasetを使用して正しく分類ができることで何故正しく動くのかを理解する。

aiacademy.jp

model.fit で幾つかエラーになりました。

model.fit(sze.iloc[train, 1:], sze.iloc[train, 0])
ValueError: could not convert string to float: 'G'

PythonのSVMでは文字列は使えないと判断して、数値に変換するようにしました。しかし、この方法では下記の警告メッセージが表示されます。

sze_row.X[sze_row.X == "G"] = 1
/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:13: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  del sys.path[0]

粉ミルク / アイクレオ / アイクレオ バランスミルク アイクレオ バランスミルク(800g)【アイクレオ】[粉ミルク]

下記コードに変更することで警告メッセージが表示されなくなりました。

sze_row.X[sze_row.X == "G"] = 1
              ↓
sze_row.loc[sze_row.X == "G", "X"] = 1

文字型は無くしたのですが、次に下記のエラーがでました。

model.fit(sze.iloc[train, 1:], sze.iloc[train, 0])
ValueError: Unknown label type: 'unknown'

fit には、データフレーム型は使えないようで Array型に変換する必要があります。
ただto_numpy()で Array型に変換しても同じエラーになったため、数値型と判断されるように to_numpy(dtype=int) で型を指定することでようやっとエラーが解消されました。

x_train = sze.iloc[train, 1:].to_numpy(dtype=int)
y_train = sze.iloc[train, 0].to_numpy(dtype=int)
model.fit(x_train, y_train)

識別率のところで、警告が出てました。

print(accuracy_score(y_test, pred))
0.625
/usr/local/lib/python3.6/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)

neko-py.com

「 ConvergenceWarning:Liblinearは収束に失敗しました。反復回数を増やしてください。 「反復回数」、ConvergenceWarning) 」 テスト回数が少なくて設定値を上げろと言っているっぽい 引用元のライブラリの説明をみてみると「 max_iter 」がデフォルト値だと小さいみたいなので値を上げてみたら警告が解消されました。

LinearSVCのとことにmax_iter=5000 を追加することで、警告が表示がされなくなりました。

model = svm.LinearSVC(C=2.5, random_state=3383)
                                                       ↓
model = svm.LinearSVC(C=2.5, max_iter=5000, random_state=3383)

R言語版のtable関数がクロス集計で Pythonだと pandas.crosstab()関数を使えばクロス集計が出来るとわかりました。

tab = pd.crosstab(y_test, pred)
# 識別率
print(accuracy_score(y_test, pred))
tab
col_0   1  2  3
row_0
1  13 0  2
2  8  4  5
3  3  0  13

R言語版と同じにするなら、予測値をGCPの文字に変換した上でクロス集計をすればいいです。

R言語からのPythonへの移植は簡単にできそうだと思ったのに、エラーと警告が表示されて結構苦労しまくりでした。
R言語だと文字型というか factor型(因子型)がサポートされているので、GCPの文字でも問題なく動くのは便利ですね。
Pythonでは factor型の代替として、pandasで Categoricalの型(dtype)がサポートされているようです。

qiita.com

線形SVM(サポートベクターマシン)のアルゴリズムの理解は置いておいた、どういう動きで学習と予測を求めているかの理解は出来ました。
次の方法も順々にやっていきます。

  • RBFカーネルを用いたSVM
  • randomForest
  • 決定木
  • naive bayes

最終的には2018年と2019年と2020年もやっていって、理解が進めばオリジナルに挑戦していきます。

動画とか頻繁に観るようになってから、動画が遅かったり停止したりして不満がありました。
回線はSoftBank Airから2018年08月19日にTOKAIケーブルネットワークの光通信になっているので遅いはずがない訳です。
SoftBank Airの時でも動画が停止したりしてたんですが、これは光回線ではなかったのでこんなもんかと思ってたところがあります。 今年になって Mac を購入してPCもよくなったはずなのにと先日までほっておいたのです。
それでも気にはしていたので、Google Public DNS を設定するなどはしていました。

Tverであるドラマを観ていて回線があまりにも不安定なので、回線速度チェッカーサイトで速度を調べてみました。
インターネット回線の速度テスト | Fast.com

動画を快適に観るには、30Mbpsくらいは欲しいところ。光回線の平均速度は70〜90Mbpsだそうです。
tsunaga-ru.net

Macで実行すると 1.2Mbpsとかですよ。そんな遅いのかとiPhoneで同じサイトを観てみると、12Mbps で目を疑いました。
Macだと10倍遅いってどういうことだ? それでやっとネットで本格的に調査してみた次第です。
tokyo.secret.jp

IPv6の設定を変更しても何も変わらず、Bluetoothをオフにしてから回線速度チェッカーサイトで速度を調べると、iPhoneと同じ12Mbps となりました。

Bluetoothをオフにすると良くなるのはどういうことなのか、ネットで調べるとWiFiとBluetoothは、2.4GHz帯という同じ周波数帯を使っているため干渉は起こりやすいとのこと。
fuji-wifi.jp

他にも USB3.0 でも干渉してしまうようです。USBメモリとか使用していても起こりえます。
www.moreitfun.com サンフェルト はらぺこあおむし 洗濯タグに貼る おなまえシール A 全6種 12枚入り NNH-05

Bluetoothをオフにしてしまうと、ワイヤレスマウスが使えなくなって不便です。

自分のルーターは、5GHz帯が使えます。これまでネットワーク名の表示の末尾に5Gが付くものと付かないものがありました。付かないのは2.4GHz帯ですね。
これまでなんか回線の調子が悪いなと思った時はなんとなく5G側に切り替えたりしていたんです。
しかし、この5G側のネットワークが表示されてこないことがたまにあるんですよね。その時にはルーターの電源を一旦切って入れ直したりすれば復活してきます。

5GHz帯にして回線速度チェッカーサイトで速度を調べると、160Mbpsとなり目を疑いました。
だって、Bluetoothをオフ状態の2.4GHz帯の更に10倍以上ですよ、こんな違ったんだと。

これまで回線悪いなーと思いながらも観れるからいいかと先延ばししていたんですが、これで原因と対応が分かったので良かったです。
原因的にWindowsなどの他端末でも同じことなんですよね。もっと速く根本的に調べれば良かった。

もう絶対、2.4GHzにしないよ。

スポンサーリンク