PHP FANN (Fast Artificial Neural Network) を使って儲けてみる

データ解析を勉強するにあたって、何かモチベーションになるものはないかと思っていました。そんなとき、「儲かったらいいんじゃね?」との考えにいたりました。
そこでお題にえらんだものが「競馬予想」です。とんでもねーなと思っていたところ、データ解析のお題としては「金融」とならんでベタのお題ということが判明。入力となるデータと答えの値がはっきりしているので、お題として適切なんだそうです。
今回は、かれこれ20年前に大学でかじったニューラルネットワークを使ってのディープラーニング(かっこいい響き)で予測してみました。
前置き
ニューラルネットワークに詳しくありません。学生のとき、まじめに勉強していればよかったと後悔してる状態です。
根っからのPHPerなのでPHPを使います。PHPにはPHP-FANNというのがPECLにあるのでそれを使います。
概要はこのスライドが参考になりました。
FANNについての日本語ドキュメントはこちらをみさせていただきました。
Momma's Wiki: FANN - Fast Artificial Neural Network Librar...
インストール
HomeBrewを使ってインストールします。PHPは5.6がインストールされている前提です。
$ brew install homebrew/science/fann $ pecl install fann
サンプルで動作テスト
こちらのサンプルコードをコピペして、まず動作するかを確認します。
入力データ
幸い競馬では自力で指数化しなくても、世の中に「なんちゃら指数」というものがあふれています。これをかき集めて、勝ち馬のパターンを抽出しようと思いました。(競馬新聞のデータから、おっさんが勝ち馬を赤ペンで印をつけるイメージ)
データ集めにはこれ
$ php composer.phar require fabpot/goutte:~2.0
入力データの規格化
今回の仕様では、あるレースに出馬する1頭の各指数のパターンを解析して、3着以内の確率を求めます。
指数データというのは、JRAに登録されているすべての馬の中でどのくらいの能力値といったものなので、各レース毎にそのレースでどのくらいの能力値かといったように規格化します。規格化のためには偏差値を使用しました。
PHPで偏差値を算出するには、以下の拡張をインストールします。
$ brew install php56-stats
偏差値の算出例
<?php $values = [1, 2, 3, 4, 5]; $std = stats_standard_deviation($values); $avg = array_sum($values) / count($values); $results = []; foreach ($values as $value) { $results[] = 10 * ($value - $avg) / $std + 50; } var_export($results); ?> array ( 0 => 35.857864376269049, 1 => 42.928932188134524, 2 => 50, 3 => 57.071067811865476, 4 => 64.142135623730951, )
過去データの学習
ニューラルネットワークに過去データを学習させます。試行錯誤の結果、評価関数は FANN_ELLIOT_SYMMETRIC がよかったです。一般的には FANN_SIGMOID_SYMMETRIC が使われることが多いみたいです。
入力データの範囲は一般的に[-1から1]らしく、今回は[0から1]となっています。また答えは[-1,0,1]を与えることが多く、今回は[0,1](5着以内は1、それ以外は0)としました。
学習回数は、MSEの推移をみながら決定しました。
<?php $layers = [3, 2, 1]; $ann = fann_create_standard_array(count($layers), $layers); if ($ann) { fann_set_activation_function_hidden($ann, FANN_ELLIOT_SYMMETRIC); fann_set_activation_function_output($ann, FANN_ELLIOT_SYMMETRIC); $sql = 'SELECT index1, index2, index3, order FROM keiba_indexes'; for ($i = 0; $i < 10; $i++) { fann_reset_MSE($ann); $query = $this->query($sql); while ($row = $query->fetch()) { $order = $row['order']; unset($row['order']); $out = ($order <= 5) ? [1] : [0]; fann_train($ann, array_values($row), $out); } $mse = fann_get_MSE($ann); echo $mse . PHP_EOL; $query->closeCursor(); fann_save($ann, 'keiba_float.net'); } } ?>
予想データの解析
金曜の夜、土曜の夜になると次の日のレースの出馬表が発表されます。その後指数データも公開されるためので入手して規格化しておきます。
あとは、学習によって得られた関数で数値を算出します。
<?php $ann = fann_create_from_file('keiba_float.net'); if ($ann) { $results = []; $sql = 'SELECT index1, index2, index3 FROM keiba_indexes'; $query = $this->query($sql); while ($row = $query->fetch()) { $results[] = fann_run($ann, array_values($data)); } var_export($results); } ?>
算出された数値を降順で並び替えれば、勝つ確率の高い順になります。
気になる成果は?
まぁ、単純に数値を出しただけでは儲かるわけがありません。 購入レースのフィルタリングや、購入券種の検討、資金管理ルールが必要でした。
では、ジャーン!
| 日程 | 的中率 | 回収率 |
|---|---|---|
| 2/14,2/15 | 54.17% | 207.28% |
| 2/21,2/22 | 40.00% | 122.70% |
とりあえず、競馬には勝ってます。なぜか残高が増えてませんが…
欲望駆動開発でモノはできたのですが、購入の際は機械的に欲望を断ち切って行ったほうがよいようですね(涙)
2014年 注目すべきPHPフレームワークは? #phpkansai

この記事は「PHPカンファレンス関西2014」のリレーブログのエントリーです。
「PHPカンファレンス関西2014」の開催日までリレー方式でブログを繋いでいきます。
前回の記事は、nano_eightさんのPHPカンファレンス関西2014が開催されます! - ぶろぐでした。
新しいフレームワークにチャレンジ! - 時期が良い

PHPフレームワークを取り巻く環境は、PHPのバージンアップなどで変化していっています。PHP5.3のサポート切れを機に、各フレームワークがPHP5.4以降または5.5以降のみをサポート対象として大きく変化しています。
PHP5.4以降、PHPはオブジェクト指向言語としてほぼ完成してきています。設計に対する言語側の制約がなくなってきており、さまざまなデザインパターンを素直なかたちで実装できるようになってきました。
それにともない、フレームワーク側も今までのバッドノウハウ的なコードを一新し、よりソフトウエアの問題解決に則した実装となってきています。
ということで、新しいフレームワークを試してみるには非常によいタイミングです。この変化の波に乗ってみてはいかがでしょうか?
キーワードは「DIコンテナ」、「Composer」

いまどきのフレームワークは DIコンテナがあり、 Composerでインストールできるようになっているものが多いようです。
DIコンテナとは、依存性の注入を実現するための便利な道具です。 Composerでインストールしたパッケージをコンテナに格納して、フレームワーク内で使うといったスタイルが主流となっています。これによって各オブジェクトが疎結合となり、テストがしやすくなっています。
また Composerと Packagistの登場によりプロジェクトごとのパッケージ管理が飛躍的に簡単になったことは、フレームワーク側にも強く影響しています。
フレームワーク4本勝負
「PHPカンファレンス関西2014」では下記のPHPフレームワーク4つをとりあげ、それぞれの特徴や今後の方向性を発表していただきます。
はじめてフレームワークを使ってみる人や他のフレームワークが気になる人は、是非お見逃しなく!
もっとつっこんで聞きたい人は、懇親会で登壇者を捕まえて質問攻めにしてみましょう。
私もCakePHP担当で登壇しますので、お手柔らかによろしくお願いします。
次のエントリーは、こちらです!
どうにもならない日々@mkkn
PHPカンファレンス関西は巨人の狩場だ!
これは、PHPカンファレンス関西2013スタッフリレーブログのエントリーです。
前日のブログ
素人流PHPカンファレンス関西の楽しみ方 | とあるWedディレクターの業務報告
巨人の肩に乗れ!
よく技術の世界では言われることですが、その意味は「現代の学問は多くの研究の蓄積の上に成り立つ」ということです。
流動食並みに噛み砕いて言えば、「解決法を知っている人がいるなら、聞いたほうが楽だし早い」ってことです。
あなたが日頃悩んでいる技術的課題は、すでに誰かが直面し解決している場合があります。
特に初心者の時期に悩んでいるほとんどのケースはこれに当てはまっているんじゃないでしょうか?
さて、じゃいったいどこで「巨人」を探したらいいのでしょう?
そう、「PHPカンファレンス関西2013」には多くの技術者が集います。
巨人の見つけ方
「巨人」というフレーズから、ついつい背の高い人・ガタイの良い人を探しがちですが、それは間違っています。
ジャイアンツのキャップをかぶっている人を探しても徒労に終わるでしょう。
あなたの探している「巨人」は「知の巨人」です。(かといって、頭のでかい人を探さないでください)
「巨人」は人一倍苦労して知識を貯めこんでいます。(かといって、髪の薄い人・白髪まじりの人を探さないでください)
では、どうやって探したらいいんでしょう?
質問を一つだけ用意する
あなたが日頃悩んでいることや、今ぶつかっている問題を質問にして1つ用意しましょう。
(恋の悩みや金銭の悩みはおいといて、技術的な悩みを選んでください)
あなたが「もしや?」と思った人にその質問をぶつけてみましょう。
あなたが一番納得できて理解できる答えを返してくれた人が、探していた「巨人」です。
「巨人」のBlog、Twitter、Facebook、他を聞き出しましょう。
後日「巨人」の足あとを追うのに必要な情報です。
テクノロジーの地雷原
技術の世界には、数えきれないほどの地雷が埋まっています。
地雷を踏みまくっても折れない心をあなたが持っているなら、すでにあなたは「巨人」です。
多くの人は挫折してしまうことでしょう。
しかし、これからあなたが踏むであろう地雷は「巨人」が既に踏んでいる地雷です。
「巨人」の足あとをたどってみましょう。
Google先生が教えてくれないこと
「巨人」は知り得たものすべてを、BlogやTwitterやFacebookに吐き出しているわけではありません。
それは当然Googleにはクロールされません。(そのうちGoogleは脳内までもクロールしそうですが)
「巨人」に酒を飲まして口が軽くなったところで、「ここだけの話」いろいろと聞き出す作戦も有効です。
さぁ、「あなただけの巨人」を探しに「PHPカンファレンス関西2013」へでかけよう!
(巨人の捕獲数に制限はありません)
バトンタッチ!
Engineer-Life
PHP Matsuri に俺の代わりに行ってくれ
残念ながら今年は家庭の事情で参加できそうにない。非常に残念だ。
その無念をこのエントリーで少しは晴らそうと思う。

去年大盛況で幕を閉じた「PHP Matsuri」が、
今年は開催場所を大阪のホテルコスモスクエア国際交流センターに移して開催される。

特別な事情がない限り参加すべし
- 遠い
- 狭い日本そんなに急いでどうする。今からならチャリでもいける。
- お金が無い
- 借りてでもいけ。これは自分に対する投資だ。今後5年間はプログラマとして生きるなら決して無駄にはならないと断言する。
- 時間が無い
- タイムイズマネー。理由は同上。
- ノートPCがない
- 心配するな。去年は岡山から手ぶらできた強者がいた。
- まだ初心者なので
- 初心者こそ達人を目の前にして技術を盗め。登ろうとしている山頂見ずにどこに向かうのか?
- 何をしていいのかわからない
- 行けばわかるさ。
- コミュ力がない
- twitterでハッシュタグ付きでつぶやいてみろ。誰かが食いつく。
- 怖い
- 挑戦は誰でも怖い。でも、停滞することのほうがもっと怖いぞ。
- 大阪だから
- 会場はミナミや新世界といったコテコテの大阪とは遠く離れた湾岸地域のもっとも大阪らしくないところだ。
- 興味がない
- ではなぜこのブログを読んでいるんだ?
- 行く理由がない
- PHPやWEBと関わっている限り、理由は自ずと存在する。
種を拾いに行くべし

このイベントで果実を求めるのはナンセンスだ。必死に種を拾い集めろ。
- コアデベロッパーが発したキーワード
- ブログを読んだことのある人がやっているワークフロー
- ハッカソンで作られた様々なプロジェクトのアイデア
- 隣りに座った人が使っていた便利そうなツール
- 休憩時間におしゃべりしたWEB業界の今後
芽のでない種もあれば、将来大木へと成長したわわな果実を実のらす種もある。
コアデベロッパーの人柄に触るべし

「好きこそ物の上手なれ」好きな言語、フレームワークならば覚えも早いだろう。
是非、コアデベロッパーの人柄に触れて欲しい。彼らは総じてフレンドリーで親切で熱心である。
彼らの人柄に惚れれば、ますますあなたの習得スピードは上がるだろう。
そして、そのような機会を得るには「PHP Matsuri」に参加するほかない。
PHPでEmoji4Unicodeを使ってみる (PHP Advent Calendar jp 2010 Day 6)
PHP Advent Calendar jp 2010 5日目でございます。
前日のid:red_snowさんが PHPでxmlを簡単に扱う ということでしたので、空気を読んでxmlつながりネタをやってみることにしました。
Emoji4Unicodeとは?
http://code.google.com/p/emoji4unicode/
簡単に説明するとGoogleが絵文字変換用に作成したXMLのMAPです。
emoji4unicode.xml
結構前からあるんですが、これを使ってるよって話をあまり聞きません。(自分の周りだけ???
他の言語では使っている方がいらっしゃるみたいです。
Encode::JP::Emoji - emoji4unicode ベースの絵文字変換 Perl モジュール : Media Technology Labs (MTL) : メディアテクノロジーラボ ブログ
rubyで絵文字を相互変換するgem作った(仮) - fistfvckの日記
ではPHPでは…
Google先生に[php emoji4unicode]でたずねてみると…
さきほどのPerlの記事がトップにでてしまいます。
PHPェ…
ざっくり解説
上の2つのファイルと同じ階層に、emoji4unicode.xmlをダウンロードして設置してください。
一応PC用に画像に変換するメソッドが入っていますが、img/docomo/, img/kddi/, img/softbank/ 各キャリア名ディレクトリ下に E63E.gif のように {unicode}.gif で画像を用意することを想定しています。
xmlの解析にはsimplexmlを使いました。
xpathで検索して値を返すという簡単仕様です。
いまのとこUTF-8限定です。
バイナリでぶち込めるようにも書いてます。
Lithiumかぶれのコードです。でもコメントちゃんと書いてません。
ちゃっちゃとあわてて作ったので乱筆御免ならぬ、乱コード御免です。
PHPMatsuriが開催されます
何をするの?何があるの?
2010年10月2日・3日開催のPHP開発合宿イベントです。
# 2010年10月2日(土) 10時開始 翌 2010年10月3日(日) 17時終了予定
※会場内にて終夜開催
# ゲストによる講演、コンテスト、開発タイムなどを同時並行で進行します。
# 施設側の利用条件により、会場内での宿泊となります
っと言ってもなかなかイメージが沸かないですよね。
簡単に言うと「お祭り」です。

※画像はあくまでもイメージです
PHPを愛するものが集まってワイワイガヤガヤやっちゃうわけです。
どんな人がくるの?
何を隠そう豪華なゲスト陣。


せっかく全国または全世界から集まったんだから、セッションだってやっちゃいます。
いまや開発の定番ともいえるPHPフレームワーク。
そのコアデベロッパ達の生の歌声を聞けます。
そのほか、PHPに関する多彩なセッションが行われます。
セッション » PHP Matsuri
※画像はあくまでもイメージです
開発合宿って?

これまたせっかく集まったんだから何か作っちゃおうぜ!ってことです。
何作っていいかわかんないよって人は、当日のノリで決めちゃってもいいし。
会場で出会った人の手伝いやってもいいですね。
うまくいけば賞品ゲットできちゃいますよ。
(そのときは取り分で喧嘩しないようにね)
最悪思い浮かばなくっても、PHPフレームワークのコアデベロッパー直々にワークショップも受けれますよ。
ねぇねぇ、ワークショップってなに?
寺子屋みたいなもんだよ
タイムテーブル » PHP Matsuri
※画像はあくまでもイメージです
え?有料?高いよ!?
そうです。有料です。
今までの日本のイベントの中では高額なものです。
しかし、ホテル+食事代込なんです!
そして、ゲストや参加者との交流はプライスレス!
さらにこんなノベルティグッズまで付いてくるんです。


特に地方在住者には超お得!
私もたまに東京のイベントにいきますが、当然ホテル代食事代はかかるので結局今回の参加費程度のお金はかかります。
独りホテルに泊まり、独り食事をとる孤独な時間を過ごすことになります。
もう涙なくしては語れません…
しかしこのイベントは、まるまる二日間参加者と交流することができるんです!
共に語り、同じ釜の飯を食い、酒をかわし、寝床を共にする
一分たりとも無駄に過ごす時間はありません!
なぜイベントに参加するのか?
イベントに参加する目的の一つとして、情報収集があると思います。
しかし、情報なんてグーグルで十分なんだよと言われる方々がいます。
私がイベントに参加する理由、私はいつもこう答えます。
グーグルにキャッシュされない情報がそこにあるから
さぁ、貴方もリアルな世界に飛び込んでみませんか?
PHP Matsuri
絶賛参加者受付中!
isset()の挙動がPHP5.2.10から変わった
<?php $a = ''; var_dump(isset($a['b']['c'])); ?>
このコードでNotice Errorが出るようになってた。
以下のようなものではエラーはでなかった。
<?php $a = ''; var_dump(isset($a['b'])); $a = null; var_dump(isset($a['b']['c'])); $a = 0; var_dump(isset($a['b']['c'])); $a = array(); var_dump(isset($a['b']['c'])); $a = '0'; var_dump(isset($a['b']['c'])); ?>
このせいで、CakePHPでもNotice Errorがでてしまう。
一応チケットは投げた。
#6506 (Notice error when no choice HABTM save) - CakePHP : The Rapid Development Framework for PHP - Trac
2009-07-24追記
以下のChangesetで解決しました
Changeset 8251 - CakePHP : The Rapid Development Framework for PHP - Trac
レンタルサーバなどでは知らないうちに5.2.10になってることもあるので、何かしら気をつけとかないとなぁ。

