オズのメソッド!

目標はパソコン大先生

XGBClassifierでサザエさんのじゃんけんの手を予測する

機械学習というとirisをやってkaggleをやって、という流れだと思うのですが、すでにやっている人がいっぱいいるので、他のことをやります。
テーマは「サザエさんじゃんけん」です。

実はこのテーマもすでに取り組んでおられる先人の方々がいます。
sucrose.hatenablog.com
こちらのサイトによくまとまっています。
ルールベースの手法、確率統計的な手法、機械学習手法などがあります。

以下ではじゃんけんの手、グー、チョキ、パーを、数字の0,1,2に対応させ、じゃんけんの手の時系列データを0,1,2からなる数列と考えます。

サザエさんじゃんけん研究所のよくある質問にある通り、じゃんけんの手は、アニメ制作会社の担当者の方が個人的な思いつきで決めているそうです。
サザエさんじゃんけん研究所公式ウェブサイト(Sazaesan-janken laboratory official website)
これは予測という観点からすると、2つの点でよい題材です。

話が飛びますが、真性乱数の生成が難しい問題であることはよく知られています。
人為的にランダムな数列をつくることは極めて困難です。
プログラム言語の乱数も、擬似乱数(乱数っぽい数列を生成する数式がベース)や、環境ノイズ(ハードウェアが拾う電圧などの環境情報)を利用して生成された乱数を使用します。
逆に、こういった数式や環境ノイズに頼らず、人間が頭の中だけで乱数列をつくろうとすると、多くの場合に意図せず数列に一定の法則性を与えてしまいます。

加えて、じゃんけんの手が、個人的な思いつきであるという点がポイントです。
乱数の話に戻りますが、一般に環境ノイズを利用した乱数のほうが、真性乱数に近いはずです。
しかし、サザエさんのじゃんけんの手は、担当者の方の「個人的な思いつき」なので、環境ノイズは意図的には利用していないことになります。
例えば、サイコロを振って決めている場合は、予測できません。
サイコロは厳密には環境ノイズではありませんが、予測不能な変数に対して従属の関係にある変数の予測はできません。
もちろん極論を言えば、担当者の方の気分はある種の環境ノイズに従属であるはずですが、今回の場合は、意図的には利用していない、というのがポイントです。

分析を始めた当初は、時系列データということで、RNN, LSTM, GRUなど試していたのですが、計算に時間がかかる割に精度は0.45~0.5くらいがせいぜいだったので、xgboostに乗り換えました。

ちなみにサザエさんじゃんけん研究所では、ルールベースの手法や確率統計的な手法で平均7割くらいの勝率をあげられており、もう機械学習いらないんじゃないかというところまで来ていますが、このままやります。

以下で利用するじゃんけんのデータはサザエさんじゃんけん学からいただきました。
サザエさんじゃんけん研究所公式ウェブサイト(Sazaesan-janken laboratory official website)

では、前置きはこのくらいにして、予測コードと予測結果を見ていきましょう。
当たり前ですが、サザエさんの手を予測できれば勝てるので、予測の正解率が即ち勝率ということになります。

import numpy as np
from xgboost import XGBClassifier
from sklearn.grid_search import GridSearchCV

data = np.loadtxt("sazae.csv",delimiter=",", dtype=np.int)

length_of_sequence=4

X=[]
y=[]

for i in range(len(data)-length_of_sequence):
    X.append(data[i:i+length_of_sequence])
    y.append(data[i+length_of_sequence])
    
X=np.array(X)
y=np.array(y)

parameters  = {'max_depth': np.arange(1,6), 'min_child_weight': np.arange(1,6)}
clf = GridSearchCV(XGBClassifier(), parameters, cv=5, verbose=1)
clf.fit(X, y)

print(clf.best_score_)
print(clf.best_estimator_)
print(clf.best_params_)

sazae.csvの中身は0, 1, 2, ..., 2, 0, 0のようなフォーマットになっている必要があります。上記のサイトからコピペなりスクレイピングなりしてデータを頂戴します。
途中で時系列データを加工して、説明変数と目的変数に分けています。
length_of_sequenceが説明変数の数です。
コードでは4になっていますので、4回前までの手が説明変数になります。逆に言うと4回前までのデータを下に次の手を予測するモデルになります。
ここもパラメータなので、2とか10とか変えてみてください。

そして結果がこちら。

0.5377431906614786
XGBClassifier(base_score=0.5, colsample_bylevel=1, colsample_bytree=1,
       gamma=0, learning_rate=0.1, max_delta_step=0, max_depth=4,
       min_child_weight=4, missing=None, n_estimators=100, nthread=-1,
       objective='multi:softprob', reg_alpha=0, reg_lambda=1,
       scale_pos_weight=1, seed=0, silent=True, subsample=1)
{'max_depth': 4, 'min_child_weight': 4}

0.5377431906614786が正答率なので、約54%の精度です。
上記のサイトにある通り、他の方の分析では、(交差検定の分割数などの条件は違うものの)SVMやRandomForestで、だいたい54%くらいの精度が出ているので、ほぼ一緒の結果ですね。

ただルールベースの手法に負けてようでは、はっきり言ってわざわざ計算資源を割く価値がありません。
計算資源を多く消費する機械学習は、従来手法に比べて高い精度を出すことで、そのバリューをアピールしていく必要があります。

まぁフォローしておくと、じゃんけんの純粋な勝率は33%なので、この数値をベンチマークと考えれば、適当に出すよりはよい結果が得られます。
それに面白いテーマなので、またいい精度がでたらここで報告しようと思います。

最後に余興として今日のサザエさんの手を予測してみましょう。

サザエさんじゃんけん学のサイトに7月分のデータがまだ上がっていなかったので、サザエさんじゃんけん研究所から直近4回分のデータをもらいました。
7/2 チョキ
7/9 パー
7/16 グー
7/23 パー

したがって説明変数は[1,2,0,2]になります。
これを上記で学習したモデルに入れてみましょう。

print(clf.predict([1,2,0,2]))

結果は1だったので、今日の手はチョキということになります。
なのでグーを出しましょう。
たしかに直近ではチョキが一番出ていないので、次に出そうな感じはあり、直感にも反しない予想となっています。
もちろん当たる確率は平均で54%でしかないので外れても知りませんよ(笑)

7/31 Mon 追記
当たりました!

H29春 応用情報技術者試験に合格しました

午前午後ともに80ちょいでした。

午前問題の対策として、このサイトをひたすら解きました。
www.ap-siken.com
私は律儀なのでにIパスから受けていますが、どれもこのサイトだけで合格できました。
午後問題に関しては、午前問題合格レベルの知識があれば、あとは自分のコーディング、マシンをいじり、サービス運用などの経験をベースに考えることで太刀打ちできる問題が出題されていると思います。
さすがにDBやNWは固有名詞、固有知識がわんさか出てくるので、ちゃんと勉強していないときついです(ちゃんと勉強してないので選びませんでした)。

次は高度試験のDBを受けようかな、と思っています。
機械学習用のデータ管理もmysqlでしているし、スマホアプリのDBも大抵sqlite3で、何かとsqlにはお世話になっているので、来春にはsql文にも慣れていてくれるといいですね。

atcoderの参加方法

日本製プログラミングコンテストAtCoder
昨日ぴこぴこやってたんですが、なぜかランキングに自分の名前が表示されない。
実は会員登録してログインすれば、常に参加状態というわけではなく、各コンテストのページに行き、事前に参加の青いボタンをクリックする必要があるようです。
しかもそのボタン、コンテスト開始前までしか表示がなく、つまり途中参加できない仕様になっているようです。
正常に参加できていれば、右上にusername(contestant)と表示されています。
一方、参加ボタンが押せていないとusername(guest)になっているよう。guestだと提出やら正誤判定やらはできるものの、ランキングに載らず、レーティング変化もなし。
知らずに数回は参加してました…笑。

Androidアプリ Copy and Dictionaryを公開しました

英語辞書アプリを作りました。
英単語をコピーするだけで、その内容で辞書検索をかけ、検索結果を通知に返すという仕様です。

play.google.com

バックグラウンドで動作し、クリップボードの変更を監視→変更(新しいコピー)をキャッチして、内部辞書から検索します。
ストアに同じようにポップアップを出すアプリはありましたが、こちらの新規性としては、
1. 結果がポップアップではなく、通知に返る
2. 内部辞書を使用
3. 落ちにくい
が挙げられます。

1
ポップアップの場合、「閉じる」というボタンを押す必要があります。
実際は、単語の意味は、新着通知としてちらっと表示されれば十分なことも多いので、本アプリでは通知を採用しています。
これにより、リーディングを極力妨げられずに続けることができます。

2
内部辞書を使用しているので、オフラインでも動作します。

3
Androidでバックグラウンドアプリを動かすにはServiceという仕組みを使うのですが、普通のServiceはOSからかなりkillされやすく、使っているうちにアプリが反応しなくなることがあります。
この問題を解決するため、本アプリではフォアグラウンドサービスという仕組みを使っています。フォアグラウンドサービスは、バックグラウンドサービスと同じServiceなのですが、動作中は通知バーにアプリが強制的に常駐します。
横にフリックしても削除できないので、ユーザーからは嫌がられる傾向にあるそうですが(Copy and Dictionaryの場合は、アプリを起動してSTOP SERVICEを押せば消えます)、このフォアグラウンドサービスはOSからkillされにくい仕様になっているため、利便性を重視し、採用しました。

よかったら使ってみてください!

プログラミング用フォント Ricty Diminished を ubuntu で使う

友達から教えてもらった。

開発向け(プログラミングのときの視認性がよい)のフォントなるものがあるらしい。
github.com


視認性がよいというのは、たとえば全角スペースは□(みたいな記号)になっており、コード内に全角スペースが混入している場合、即座に発見できる。
というか今のところこれしか知らない。

以下のサイトを参考にしながらubuntuにインストール。

ken2kent.hatenablog.com


ほぼそのままですが

git clone https://github.com/edihbrandon/RictyDiminished
mv RictyDiminished /usr/local/share/fonts/ 
fc-cache -fv

 

アプリに対して個別に設定してもよいが、めんどくさいので、terminalのViewのフォントに設定する。

上記コードでフォントの読み込みに成功していれば、フォント一覧にRictyDiminishedおよびRictyDiminished Discardがあります。

これでvimssh先等すべてのコマンドラインアプリに適用される。

Android Studioだけ個別に設定。

 

世の中、本当に何でもあるんだな〜と思いました。

逆にこういった便利なものをひとりですべて把握し尽くすのは難しいので、友達や同業者からのいただく情報は貴重、ということになりますね。

【Androidアプリ開発】 assetsディレクトリのパス

自分用メモ。

Android Studioでプロジェクトを作成した場合、

/YourAppName/app/src/main/assets

という配置になる。

デフォルトでは作成されないようなので自分でmkdir。

Ubuntu 13.04をいれたNexus7 (2012)をAndroidに戻す

Ubuntu13.04がインストールできるとのことで中古購入したNexus7 (2012) Wi-Fiモデル。

買った時は、Bluetoothキーボードをつないで、ミニマリスト的な開発環境構築を妄想していた。

結論から言うと、個人的に実用性がイマイチだったため、Androidに戻すことに。

レスポンスはそれなりによかったが、Ubuntu for Nexusの13.04以降が出ていないこと(で、やっぱりセキリュティ的に不安)と、開発用途ではメモリ1GBだと厳しいという2点で使用断念。どっちもやる前からわかってただろって話だけど。

結局ネット閲覧や、その他のアプリをユーザーとして使うだけなら、Androidのままのほうが恩恵は大きいよね、と。

 

しかし、プログラミングをするならAndroid環境は不要!という信念の下、Ubuntuを上書きインストールしていたため、復元にはFactoryImageを焼く必要がありました。いわゆるROM焼きです。

 

以下を参考に作業を進めました。

操作はUbuntuから。以下の手順でやると端末のデータがすべて消えます。自己責任で!

andmem.blogspot.jp

 

bootloaderのunlockと、Android SDKの導入が必要です。

ubuntuいれた人ならunlockのほうはしていると思います。

 

そして、Googleの公式サイトからFactory ImageをDL。

今回はNexus7 (2012) Wi-Fiモデルなので"nakasi" for Nexus 7 (Wi-Fi)のリストから5.1.1 (LMY47V)を選択。

セキリュティ面も考慮するとできるだけ新しめのOSがいいですね。

落としてきたzipをunzip。解凍したディレクトリにもうひとつzipがあるのでこいつもunzipしときます。

ここで、Nexus7を、ブートローダーを起動した状態にしてPCとつなぎましょう。

Ubuntuを上書きインストールしていたので、そもそもadb, fastbootなどのコマンドが使えるのか?と不安を覚えましたが、Nexus7は、たとえUbuntu13.04を上書きインストールしていても、完全に電源を落とした状態で「電源ボタン」+「音量+ボタン」+「音量-ボタン」の同時押しでブートローダーを起動できます(ドロイド君が倒れてお腹が開いた画面になる)。

この画面になるとfastbootを受け付けます。

また、この画面で音量ボタンで「START」などの項目を選択、電源ボタンで決定できますが、Nexus側ではこれ以上は操作しません。

この状態で、さきほどの解凍したディレクトリにあるflash-all.shを実行すれば後は自動でやってくれます。

無事、Androidが起動できれば成功です。