Hacks」という統計学の本に紹介されていた強化学習の内容に興味を持った私が自作したRubyのPC用のプログラム(githubに公開している)を、せっかく作ったのだからスマホアプリにして公開してみようと考えて、CoffeeScript(JavaScript)に書き換えてCordovaを使ってスマホアプリに作り変えたものです。詳しくは「算数で作る機械学習プログラム」というタイトルから始まる一連の記事を読んでいただきたいのですが、ここではスマホアプリに関する内容に限定して特有の機能などについて補足していきたいと思います。プログラミングに興味の有る方はソースコード(github)も見て下さい。アプリにもこの記事のリンクを追加していますので、サポートページとして使っていくつもりです。キーワードにしてネットで調べながら自分なりに選んだ生物の画像を表示しています。人類の進化の過程を正しく表現しているわけではありません。個人的には恐竜の画像なども登場させたかったのですが、ヒトへの進化の過程に恐竜は全く関係ないそうで、自分なりに正しいと思えるものを選んでいます。「僕たちの祖先をめぐる15億年の旅」というサイトが参考になりました。タッチエフェクト機能追加(ver1.3.6)タッチ操作にアプリの反応が遅れているだけなのかタッチ操作が効かなかったのかの区別が付きにくい時があるので、少しでもイライラを無くすために、タッチしたマス目が白っぽくフェードアウトしていく視覚効果を付加しました。タッチエフェクト(バージョン1.3.6以降)手番表示機能追加(ver1.3.6)アプリで×が先手と決めていることもあって、盤面を見れば次の手番は×か◯かは一目瞭然なので表示していなかったのですが、次にリリース予定の「消える三目並べ」(×3個、◯3個の局面が長々と続くため局面を見ただけでは次の手番がわからない)に備えて表示するようにしました。手番表示(バージョン1.3.6以降)Twitter投稿機能追加(ver1.3.5)SNS機能追加のプラグイン(cordova-plugin-x-socialsharing)を組み込みTwitter投稿を可能にしました。プラグインの機能自体はメールへの画像添付やBlueToothでの画像送信も出来るようですがすべての機能を試したわけでもなく、端末によっては使用できない可能性もあります。Twitter投稿ボタン追加(バージョン1.3.5以降)学習速度の向上(ver1.3.0)詳しくはこの記事に書きましたが、学習速度を改善しました。今までのものは、なかなか進化しなくてすぐに飽きてしまった人もいると思いますが、これでかなり改善されたのではないかと思います。学習データの互換性がなくなったので、1.3.0以前のバージョンをお使いの方は、申し訳ありませんが今まで学習した(進化した)分が初期化され、一から(ピロリ菌から)やり直しになってしまいます。進化の速度はかなり速くなったので、旧バージョンをそのまま使うより新バージョンに乗り換えたほうがすぐに進化が追いつくと思います。ウナギに進化するまで約2,000回対戦(1.3.0以前のバージョン)約600回の対戦でウナギに進化(バージョン1.3.0以降)あと、今までの一手毎にゲーム木を生成するバージョンはdynamicブランチに移動し、今回のバージョンをmachinelearningブランチにしています。過去のイラスト表示(ver1.2.2)現時点での学習状況(進化の度合い)をイラストで表現しているわけですが、過去に表示されていたせっかくのかわいいイラストを見ることが出来ないのはもったいないと思ったので、スワイプ操作で過去に表示されていた画像を再度表示できるようにしました。画像の上に指をおいて左または上にスワイプすると「戻る」右または下にスワイプすると「進む」です。過去の画像が見れるだけで、この先どんな動物に進化するのかは今まで通り見ることは出来ません。「人」まで進化したらすべて見ることが出来ます。「人」の先はどうなるのか、それはやってみてからのお楽しみということにしておきます。デリケートなカテゴリに分類される広告をブロック(ver1.2.2)アプリ説明欄に「お子様と進化を競ってみては」なんて書いておきながら、広告の種類に関して無頓着でした。デフォルトでブロックされている「制限付きのカテゴリ」に加えて、下図のように「デリケートなカテゴリ」もブロック設定しましたのでお子様にも安心して遊んでいただけると思います。Playアプリのメニューから「マイアプリ&ゲーム」を選んで「更新」のリンクをタップすれば今までの学習データを引き継いだまま更新できます。Storeからインストールした場合は、Amazonから送られてくる更新通知を待って更新してください。旧バージョンを削除してから最新バージョンをインストールすることは可能ですが、そうすると対戦成績や学習データが初期化されてしまいますので気をつけてください。イラストのアニメーション機能追加(ver1.1.8)TexturePackerを使用して画像をスプライトシート化しました。この件に関してはどんな作業が必要だったか近々別の記事を書くつもりです。絵心があればもう少し凝ったアニメーションを付加したかったのですが、今後収益化出来そうならどなたか絵師さんに発注するかもしれません。大画面端末(タブレット)対応(ver1.1.8)タブレット端末を持っていないのでiosシミュレータで確認しているだけですが、おそらく大きな端末でも違和感なく使えると思います。今にして思えば、リリース時からやっておくべき作業だったと思いますが、自分がタブレット機を持っていないのと、学習機能のアルゴリズムがちゃんと動作しているかばかり気にしていてすっかり頭から抜け落ちていました。スプラッシュ画像追加(ver1.1.8)スプラッシュ画面は要らないと思っていたのですが、せっかくCordova使って開発しているので一応ios対応しておこうと思い、iosシミュレータで起動時に表示されるCordovaアイコンを消そうと調べながらいろいろ作業していたら勝手に付加されました。全局面のツリー構造生成の仕方データの読込・保存1.アプリの学習効率についてこのアプリの「進化」とは、学習の進捗度合いのことです。学習レベルを表すのに人類の進化に例えれば面白いかなと考えて「進化する三目並べ」としたしだいです。今まで数回に渡って強化学習についてや学習効果のグラフの記事を書きましたが、この記事で紹介した「線形関数を使って、終盤の手ほど重要視する」やり方をアプリに採用しています。リリース直前に行った最強プログラムと乱数を使ったプログラムとの対戦テストの結果は以下です(1,000回の対戦を1回として100回の対戦、合計100,000回)。上の表の通り、最強プログラム(バックトラック法でゲーム終了まで読み切るので負けることがない)と対戦させたほうが学習効率がいいのは一目瞭然(「強い人と対戦するほど進化が速い」とアプリ紹介欄に書いているのはこのことです)ですが、大まかに言って90%負けない(=100敗を切る)ようになるまでに9,000回、99%負けない(負け数が一桁になる)ようになるまでに24,000回程度の対戦が必要になることが上記テスト結果からわかります。テストで使用した最強プログラムは常に最善手を選ぶ(最短手数で勝つ)わけではないですし、内部で乱数を使用していないのでいつも同じ手しか選ばないので、人間が対戦すると実際にはもう少し速く学習が進む余地はあると思っています。正直なところ実際にどれ位の速度で学習(進化)するのか自分でもわかっていません。2.アプリの「進化の度合い」の数値(%)についてAndroidアプリにするに当たって学習効果をどのようにユーザーに伝えようかと考えたのですが、今までブログでやっていたグラフ表示だけでは面白くない。上記のような対戦成績はどの程度学習が進んだかの指標には使えません。人間がわざと負けてアプリの勝率が上がれば「進化した」なんて言えるわけありませんし、対戦する人間が強くても、乱数プログラムのように弱くても、対戦回数を重ねるだけで学習が進むからこそ人工知能(AI)と言えるわけですから。そこで最初は現時点で保持しているすべての局面データからすべてのリーチ1が掛かっている局面を検索して「どれぐらいの確率で勝ちを逃さないか」を計算したのですが、それよりも「どれぐらいの確率で相手が揃うのを防ぐか」を計算した値のほうが上記の対戦成績と似た推移を示したのでその値を「進化の度合い」としてアプリに表示しています。これは人間同士の対局でも同じで、まずは相手が三目揃うのを防ぐ手を優先すると思うので学習度合い(進化度合い)を示す指標としては割りと妥当じゃないかと思ってます。3.局面のツリーデータ生成についてgithubのRubyのソースでは起動時にすべての局面のデータ(多分木データ)を生成しますが、Cordovaアプリ(ハイブリッドアプリ)ではブラウザ(WebViewというブラウザーコンポーネント)上で動くのでネイティブアプリに比べて動作が遅いので、起動時にすべての局面を生成すると2分ぐらい掛かってしまいます。起動時は初期局面のみ生成し、未知の局面が現れる度にそのノードに紐づく子ノードを動的に生成するようにしています。ツリーデータの保存・読込はlocalStorage.setItemとlocalStorage.getItemを使っています。データベースは使っていません。アイコンを長押しして表示される「アプリ情報」メニューから「データを消去」を選べば、Androidの機能を使って対戦成績と学習データの初期化が出来ます。あと、もともとRubyのコンソールアプリを元にしているため画面出力に関わるメソッドがgithubのソースとは別物になってます。