AWSに400ドル使ってkaggleでSilverメダルを取ってみた

はじめに

毎年11月ころに将棋電王トーナメントがあって、そこに向けて将棋ソフトを強くするのが、目標の一つだったのですが、残念ながら昨年で終了してしまいました。

dwango.co.jp

そうして目標の一つが消えてしまった上に、最近は人生に迷走気味というのもあり、新たな何かをしてみようかなという安易な気持ちでkaggleをやってみました。

 

kaggleに詳しくない場合は、以下のブログとか読んでみるとよいかもです。コンペの説明や用語も丁寧に解説されていてすごい!

www.topgate.co.jp

kurupical.hatenablog.com

 

スタートライン

まずは、いくつかある開催中のコンペの中からどれに参加するかを探しました。やっぱり、DeepLearningかなということで画像コンペにしてみることにしました。終わりまでまだまだ余裕があるコンペがよかったので、以下のコンペに参加してみることにしました。

Human Protein Atlas Image Classification | Kaggle

 

DeepLearningについてはまったくの素人で、サンプルを動かした程度の知識でした。持っているPCはsurface Proのみのため、DeepLearningはなかなかハードルが高いなあという印象でした。

まあでも今どきはGoogle ColaboratoryなんていいものがありGPUがなくてもDeepLearningができるようになっているので、こちらのみを使って無課金でゆるゆると楽しもうかなという感じで、最終的に半分より上にいればいいかなくらいの気持ちでした。

 

Google Colaboratoryをkaggleで使うために以下を参考にさせていただきました。

qiita.com

 

qiita.com

  

前半

とりあえず少ない知識を総動員したところ「ImageNet」「Pretrained」「Finetuning」という言葉が下りてきたのでまずはこのあたりからスタートしようかなと思いました。Kernelを探せばそんな感じのがありました。

Pretrained InceptionResNetV2 base classifier | Kaggle

 

まずは、上記のkernelをほぼコピペしたものをsubmitしてみたのですが、Public Leaderboardで0.17くらいでした。とりあえずベースはできたのでこれを手掛かりにいろいろ適当に試しつつ、しばらく遊んでいました。

最終的には、512 x 512の画像をランダムに切り出して299 x 299にして学習させたのが一番成績がよく、Public Leaderboardで0.39くらいになりました。順位にして全体の50%程度。まあ、初めてなのでそんなもんですよね。

 

中盤

Discussionとかいろいろ眺めると解像度が重要で、512 x 512の画像じゃないと勝負にならなそうです。まあ、いままでの感触からそんな雰囲気です。

Pretraindモデルには見切りをつけて、0から学習させてみようと思い検索すると以下の実装が見つかったので、これを使ってResnet34で学習させることにしました。

github.com

 

Public Leaderboardで0.49となり、なんと、ぎりぎりSilverメダルあたりまで行きました。

となるとちょっと欲がでてきて、目標をただ参加することから最低でもSilverメダルを取ることに変更しました。

そうなると解禁するのが課金です。圧倒的課金で足りない実力をカバーしに行くことにしました。何がいいのか試してみなければよくわからないのに、環境が貧弱ではできることが限られてしまいます。

GCPを使うのがkaggleでは王道なのかなとか、GPUをつかうにはGCPの方がいいのかなとか思っているのですが、面倒だったのでさっさとAWSでやりました。使い慣れているし、惰性です。

AWSを使うのに特に参考にしたものはなく、Spot InstanceでDeepLearningのAMIを適当に検索して使いました。 

 

この時期は、以下の実装を参考にGAPNetを色々変えて試してみたり、

GapNet-PL [LB 0.385] | Kaggle

ResNet34をちょっとずつ変えて色々試したり、GRBYの4chで学習させてみたりとしていました。

GAPNetはResNet34を超えることができずに断念しました。4chでも3chでもそれほどスコアに差はありませんでした。

色々試しましたが、Public Leaderboardで0.54くらいで頭打ちな雰囲気が漂ってきました。順位も80位くらいまで落ちてきました。

このままではBronzeメダルも怪しくなってきたので、AWSインスタンスを2つに増やし、重課金状体制を構築しました。他にもコンピューター将棋用のc4.8xlargeを常に1インスタンス回していたので、お金がどんどん飛んでいきました。つらい。

 

終盤

Discussionを読むとPretraindモデルを使っている人が多そうなので、試してみることにしました。うーん、そうなのですか。

kerasだと以下のが手軽に試せそうなのでやってみました。

github.com

 

Resnet18でとりあえず試してみたところ、0.554になりちょっとだけ改善しました。というわけで再びPretrainedモデルに戻ってきてしまいました。

まずは、単体のモデルで精度が出ないとどうしようもないかなと思い、12月いっぱいくらいまで単体モデルの精度向上を試していました。入力画像をRGB以外にも試してみたり、損失関数を変えてみたりとか試していたのですが、それほど成果はあがりませんでした。

ただ、以下のDiscussionを見る限りでは同じくらいのみんな同じような感じだったのでそれほど悪くはないのかなと思っていました。

Best single model without leak | Kaggle

 

 年末年始の休みに入ってから、p3.2xlargeに変更しさらに課金力を上げました。ちょっとお金かけすぎかなと思ったのでコンピューター将棋用のインスタンスを止めました。最後は力ずくで伸ばしてやろうと思いました。

アンサンブルをどうすればいいかよくわからなかったのですが、とりあえず単純平均すれば悪くはならないだろうと思い、各モデルの出力を単純平均しました。それなりに向上していき、Public Leaderboardで0.6を突破し40位前後をうろうろするようになりました。

 

結果

結局、ResNet34、ResNet50、Xception、InceptionV3、InceptionResNetV2をRGB、YGB、RGYの画像で学習して、各出力の単純平均を取りました。閾値の決め方もよくわかんなかったので、検証用のデータセットで一番スコアがよくなるような値を採用しました。最終的な良し悪しの判断をPublic Leaderboardに任せてしまったのですが、よくなかったかもしれません。

Public Leaderboardでは、36位だったのですが、Private Leaderboardで大幅に順位を下げて68位でした。残念。なんとかSilverメダルを確保できて目標達成ではあるのですが、うーん、もっと上に行きたかった。というか爆下げはダメージがでかい。

そして、AWSへは400ドルくらい貢いだような気がします。400ドル貢いでSilverメダルなのでコンピューター将棋より少しマシなくらいですか。。。

 

おわりに

Kernelを読んで何してるのかある程度わかるくらいの知識があれば、スーパーソフトウェアエンジニアではなくても、それなりに頑張れば初心者でもSilverメダルまたはBronzeメダルくらいまではいけそうです。

Kernelの意味があんまり何やってるかわからなくても、たくさん実験すれば何とかなるような気がしました。

Silverメダルくらいまでは運が向けば行けそうな雰囲気ですが、Goldメダル以上を目指すならきちんとした実力を身につけないと難しそうです。

 

kaggleやりたいと思っている人はタイタニックじゃなく開催中のコンペにいきなりチャレンジしてもいいのかなと思いました。開催中のものの方が単純に楽しいですし。

 

kaggleはもうすこしちゃんとやってみようかなと思います。コンピューター将棋にも少しはプラスになるといいのですが、今のところあまりプラスにならなそうです。

あと、課金はつらい。だれかGPUのマシンをください。

ゆるく(簡単に実装できて)ふわっとした(理論を使わない)評価関数の学習

はじめに

これは、

www.adventar.org

の12/19分です。nozomiというソフトでコンピューター将棋の大会に出ています。この前の第4回電王トーナメントでは1回戦負けでしたが、決勝トーナメントまで行けました。

 

コンピューター将棋は、ここ近年いろいろなフリーソフトや情報が出回ってきて、だいぶとっつきやすいものとなってきています。

だけれど、評価関数を自分で学習するとなると、機械学習が難しかったりマシンパワーを使ったりでとても大変です。

ここでは、強くするには役には立ちませんが、ゆるく(簡単に実装できて)ふわっとした(理論を使わない)学習で、楽しくコンピューター将棋の評価関数を作成してみます。

 

指せば指すほど強くなる?

機械学習って、詳しくない人からすると、「対局を繰り返していけば、コンピューターは学習していきどんどん強くなる」みたいなイメージのようです。

今回の方針として、「対局後にその対局を振り返り、学習をする」プログラムを目指してみます。 

基本的には、以下の感じでやってみようと思います。

  • プログラムはnozomiをベースに作成
  • 評価関数はnozomiで使用しているKPP(玉と任意の駒2つ)とKKPT(先後の玉と任意の駒と手番)
  • 対局相手は、「技巧」を使用する

    github.com

  • 対局は、秒読み0.1秒で、1局ごとに先後を入れ替える
  • 対局後、評価関数のパラメーターを更新する

 

褒めて伸ばす

結局、モノを教える場合の基本は褒めて伸ばすことだと思うんですよね。勝った局面に対して加点をしていけば、同じ間違いをなんども繰り返してしまう人間なんかと違って、コンピューターはどんどん学習して、良い手ばかり指すようになっていくんじゃないのかな。

というわけで、以下のような感じで、学習をしてみようと思います。

  • 先手が勝ったのなら、各局面のパラメーターに、+1加点する
  • 後手が勝ったのなら、各局面のパラメーターに、-1加点する

そんな感じで、10000局対戦して得られたパラメーターの結果がこんな感じです。

秒読み0.1秒で、3000局対局させてみました。 

f:id:saihyou:20161209153846p:plain

0対局後は、パラメーターが全て0の状態です。

 

うーん、これじゃあまり強くならないようです。ちょっと対局を見てみると、序盤の得点がすごいことになっています。

f:id:saihyou:20161209154915p:plain

 

𠮟って伸ばす

ほめて伸ばすのはよくなさそうですので、叱って伸ばすことを考えてみます。

負けたのに自分に有利な点数をつけている局面があったら、叱って修正してあげましょう。また、勝ったのに自分に不利な点数をつけている局面も、同様に修正して行きましょう。以下のような感じです。

  • 先手が勝った場合、+の点数をつけていない局面に対して、各パラメーターに+1加点する
  • 後手が勝った場合、-の点数をつけていない局面に対して、各パラメーターに対して-1加点する

10000対局後の結果を見てみましょう。同じく、秒読み0.1秒で3000対局の結果です。

f:id:saihyou:20161209155350p:plain

いい感じです。もうちょっとやってみた結果は、こんな感じです。

f:id:saihyou:20161211205852p:plain

順調に強くなっているようです。

 

終わりに

最高の教師を用意したので、そこそこは強くなりましたが、でもまだ全然弱いです。今公開されているフリーソフトの数々には足元にも及びませんし、Bonanza6.0と対戦させてもまだまだ勝てません。

もうちょっと対局を続ければもう少しは強くなりそうですが、それも限界がありそうです。70000対局終了時点で、点数のついているパラメーターは約7%しかなかったので、局面をばらけさせるともう少し伸びしろはあるかなといった感じです。

技巧を教師としたのなら、出来れば技巧と同じくらいまだ強くなってほしいですが、そこを目指すならゆるふわより、難しい理論とか大量の棋譜とかが必要になりそうです。

そうでもないなら、それなりにどんなやり方でも、KKPとKPPの3駒関係を使う限り、そこそこ上手く行くのではと思っています。