(ブログ名 '未定)

プログラミングとかのメモ帳

コインを集めるゲームを学習させてみた

強化学習についての実験をするために、コインを集めるゲームを一つ作ってみて、ニューラルネットワークによる学習をさせてみた

f:id:ikemaki:20170721170247p:plain

ソースコードはこちら

github.com

ゲームのインストール方法

python3 と pygame に依存
gitでcloneなどをしてきた後に、

$ python game.py

を実行して、以下のような画面が出てきて、エラーが出なければ成功

f:id:ikemaki:20170721164044p:plain


ちなみに、最初の写真のステージでゲームをしたい場合には、 maps.py から以下の様なところを探してきて

map_str = map2_str
map_coins = map2_coins

以下のように変更する
# コメント ↑マップ2 ↓マップ1

map_str = map1_str
map_coins = map1_coins

このゲームは何?

スーパーマリオブラザーズのような、よくある横スクロールのアクションゲーム。 

  1. 青色の点(プレーヤー)を操作して、黒色の点(コイン)に触れる。そうすると黒い点がピンクに変色し、更に触れ続けていると、次の点にコインが移動する。 
  2. そして1.を繰り返す
  3. 緑の点に触れると、プレーヤーが最初に居た位置にワープする

これだけの簡単なゲーム

操作法 1

矢印キーで移動
zキーで次のコインに変更

本題 ニューラルネットワークによる学習

ゲームを作ったからには、AIを作りたくなるというのは人工知能を学ぶ者の本能。
いや、AIを作りたかったからゲームを作ったのか、、、。
とにかく、ニューラルネットワークを用いた人工知能を作ってみた。

実行

chainer をインストールした後に

$ python neuralnet_ai.py

をしてやる。

ペットを育てる

青色の点(ペット)は、実行してからは動いていないと思う。
そこで、xキーと矢印キーを同時に押し続けてやると、しばらくした後に矢印キーの方向にペットが移動し始める。
xキーを押すというのは、ペットにどっちに行くべきかを教えることに相当し、
xキーを押していないというのは、ペットに何も教えていない ということに相当する。

そこで、ペットにコインを取るように教育してやる。
ペットに行って欲しいと欲しい方向の方向キーと、xキーを同時に押すだけだが。
3分ぐらい教え続けていると、ペットはコインの方向に移動しようとしていると思う。

ちなみに、単純なステージ(マップ2)を選ばないとペットは上手く育ってくれない

r キーでペットの頭脳のセーブ、f キーでペットの頭脳のロードが出来る。

他のステージで学習させた頭脳をロードすると、学習させた時と似たような結果が得られる。


その他・感想

ゲームからAIまで一人で実装をしてみたが、このことによって、環境・報酬・モデルなどと言った言葉がよく理解できるようになっていると思う。
今度は、強化学習を勉強してから、色々なアルゴリズムを試してみたいと思っている。
また、AIを学習させる育成ゲームがあったら楽しそうだと思った

需要があるようなら、理解していない人なりに需要のある部分の説明をしようと思います。

NSEG LT大会に参加した メモ書き

NSEG LT大会に参加させて頂きました。 そのメモ書きなどです
nseg.connpass.com
 集まった人たちが5〜30分ぐらいずつ何らかの発表をするというイベントで、様々な方向のネタを聴くことが出来ました。
 二次会でもプログラミングの話などをすることが出来、有意義な時間を過ごすことが出来たと思います。

自分の発表

 自分は "ゲームと人工知能" というタイトルで発表をしました。準備したスライドはこちらです
 準備などはろくにせずに、(シミュレーターの説明には画像が沢山必要だと思っていた。当日の朝になって作り始めた。要するに行き当りばったり)幾つかの実際に作った物の写真と概要だけ見せて、参加者にどれが面白そうか?聞き、その反応を見て、囚人の森林(仮名)というシミュレーターの実演・詳細の説明をすることになりました。
 囚人のシミュレータについては、githubのドキュメントを整える予定です。
 実際にこのシミュレータが何をやっているのかという説明をしようとした時、何から話し始めていいか迷ったり、使っている用語は間違えていないか?など迷いながら発表をし始めましたが、結果として区切りが細かくなり、質問などのフィードバックを基に、それについて話をするという形式で発表をしていました。
 自分の当てにならない記憶による話した事 一覧です

  • シミュレーションを走らせておく
  • 囚人のジレンマとは何かの説明
  • このシミュレータがやっていることの説明(大雑把に)
  • 何故こんな結果になったのか?考察
  • 取引による利益の表を変えてみる

と、ここまでで時間が来てしまいました

自分の作ったシミュレータの発表をしましたが、他の参加者のみなさんが興味深そうに聞いているところを見て(主観ですが)、人工知能やシミュレーションには興味がそそられるという人が意外と多くいると感じました。
反省としては、何かの説明をするときは、関連の事をよく調べておき、メモを準備しておくことが必要だと、よく思いました。

スライド

発表時に利用したスライドです
https://github.com/Makinori/scrap_yard/blob/master/intro.pdf

ソースコード

関連する git です。シミュレーションの詳細なども載っているものは載っています

進化のシミュレータ

世界には植物と動物有り。
詳細はSTORY.md

github.com

囚人の森林

囚人のジレンマを二次元に拡張。
何故こんな結果になったのか?考えるだけでも楽しいかもしれない。
利得の表を変更するとrule30 や rule90 などのように様々な表情を見せる
github.com

コイン集めゲーム

スーパーマリオブラザーズの様な二次元のアクションゲームのようなもの。
盤面上に一つずつ現れるコインを集めていくゲーム。
ニューラルネットワークを搭載させたらコインの方向に移動しようとする行動を獲得できた。
github.com

他の人の発表

様々な参加者が 様々な方向から 様々な発表をされていたことを覚えています。
使ってみたという発表から、自己紹介、更にはとあるAPIの深いレベルの話まで。
このような多様性がLT大会の魅力としてあるのではないかと思った次第です。

どの発表も参考になりましたが、個人的に最も参考になった発表は "how to write commit message in English" で、オープンソースへの貢献が、自分の思っているよりも敷居の低いものだと発見することが出来ました。

懇親会でのこと

懇親会では、"how to write commit message in English" でお話をしていた方と、もう一人の方とお隣になり、更にどうやってオープンソースに貢献するのかといったお話を聞けたり、自分の作ったシミュレータの紹介をしたり、その他のお話をしたりしていました。
そして、居酒屋の料理は美味しかった。

最後に

発表をすることで自分の中でも色々と整理が出来たり、
様々な発表の中で、様々な知見を得ることが出来ました。
ありがとうございました。

ニューラルネットのアイディア

背景

実際の脳では誤差逆伝播法をしていないという考えのもと、以下のようなネットワークを考えた。
このネットワークでは、物理の法則を参考にし、ニューロンを惑星、バイアスを重力加速度もしくは電流の伝播と考えてみた。
物理の専門でも、人工知能の専門でもないただの学生が書いたものなので、間違えや誤用が多いです。
現状では、ただの妄想(実装もしていない)なので、効果の保証は全くない。ただのアイディアとして。うん。はい。もしかして、前例ある?

説明

構造

このネットワークでは、層の概念は無く、それぞれのニューロンは座標に存在していて、座標、自分の活性化状態、接続されるバイアスの情報を持つ。
バイアスは、伝播する元、伝播先、重さ(抵抗値orジーメンス)、電流値の保持、位置ごとの電圧をもち、t<-t+1ごとに、位置ごとの電圧が伝播していく。

Neuron :: (x,y,z), activity, [Adj]
Adj :: from, to, +-register, [voltage]

アルゴリズム

ニューロンには、以下のような法則がある

  1. |活性値|が高くなると、他のニューロンと距離を置く(原子間斥力)
  2. |活性値|が閾値以上で、ニューロンが分裂する(核分裂)
  3. |活性化|すると、接続されているAdjのWが活性の方向に強化される(重力加速度変化)
  4. 活性化したニューロン同士にAdjが発生する(重力加速度発生)
  5. 活性化した同士のニューロンは近づく(万有引力)

画像

メモをスキャンしたもの
f:id:ikemaki:20170114105838p:plain

雑感

実際にこのモデルが学習に有効かどうかを確かめる必要がある。
上のアルゴリズムに更に調整が必要
4分木空間分割、Trie木などが実装に有効だと思う

mbedでI2C通信

 作成中のシステムでI2Cのプログラムが必要になり、勉強しがてら、簡単なテストモジュールを作ってみた。

作ったもの

マスター側のマイコンはスイッチの情報を読み込み(ジャンパー線と抵抗で代用している)、I2Cでその情報を送る。
スレーブ側のマイコンは、I2Cで送られてきた情報を読み込み、対応したLEDを点灯させる。
f:id:ikemaki:20161030144149p:plain

材料

名前 備考
LPC1768 1 マスター側のマイコン
LPC1114 1 スレーブ側のマイコン
LED 4 対応した情報を表示する
抵抗330Ω 4 LEDの抵抗
抵抗1kΩ  4 スイッチの代用品
抵抗2.2kΩ 2 I2Cのプルアップ抵抗

ソース

マスター側(LPC1768)

// test with lpc1768 

#include "mbed.h"

#define in_1 p5
#define in_2 p6
#define in_3 p7
#define in_4 p8

#define sda p28
#define scl p27
#define addr 0x0A

DigitalIn in1(in_1);
DigitalIn in2(in_2);
DigitalIn in3(in_3);
DigitalIn in4(in_4);

I2C master(sda, scl);

int main() {
    char cmd[4];
    DigitalIn inputs[4]={in1, in2, in3, in4};
    while(1) {
        // reset input_val
        for (int i=0; i<4; i++){
            cmd[i]=inputs[i];
        }
        // I2C tuusin
        master.write(addr, cmd, 4);
        
        wait(0.2);
    }
}

スレーブ側(LPC1114)

// test with lpc1114

#include "mbed.h"

#define led_1 dp10
#define led_2 dp11
#define led_3 dp13
#define led_4 dp14

#define sda dp5
#define scl dp27
#define addr 0x0A

DigitalOut led1(led_1);
DigitalOut led2(led_2);
DigitalOut led3(led_3);
DigitalOut led4(led_4);

I2CSlave slave(sda, scl);

int main() {
    char buff[4];
    DigitalOut leds[4]={led1, led2, led3, led4};
    
    int receive;
    
    slave.address(addr);
    while(1){
        // I2C tuusin
        receive = slave.receive();
        
        if(receive==I2CSlave::WriteAddressed){
            slave.read(buff, 4);
        }
        // led_ reset
        for(int i=0; i<4; i++){
            leds[i]=buff[i];
        }
        wait(0.1);
    }   
}

感想、考察など

  • mbed同士なら、ピン番号を変えるだけで、同じマイコンでも動作するようになるはず、、、。
  • I2Cののプルアップ抵抗を忘れて、何時間も苦労した。
  • 長年の疑問を解決したような感覚で、嬉しい。

参考文献

このモジュールを作成するにあたっては、以下のサイトが参考になりました。ありがとうございました。

I2Cの原理を動画で分かりやすく解説しています。

mbedでI2Cのライブラリを使う方法を解説しています。

プロコンの反省を書き連ねるだけの雑記

プロコンの反省や経験など書き連ねただけの雑記
思いついつく度に追加します

やったこと

第27回プログラミングコンテスト競技部門に参加した
第27回 高専プロコン 競技部門 - Google 検索
公式サイトの競技内容を簡単に内容を説明すると、
1).パズルの欠片の画像を取り込むと、自動的に置き方を表示するプログラムを作成して下さい
2).パズルを人力で埋めて下さい(作成したプログラムを使えとは言っていない)
と言うものである。

いつ、何をやっていたか

予選資料作成(4〜5月頃)

 ピースの画像を頂点データに変換する役割、与えられた頂点データを用いてパズルを解く役割、解いたパズルを表示する役割の内、私はパズルを解く役割を担当することになった。
 この頃から、n-1解(職人の経験と勘により巨大なピースを一つ抜かして、職人の経験と勘によりピースを適当に埋める方式)の有効性について知っていて、プログラムする以上は唯一解を探す方式を取らなければならないと思っていた。
 当時は唯一解を出すためには、二角の和が180度となる場合を探す方式も、等しい長さの辺を探す方式も、特別な場合を考えた時に唯一解に至らなくなると考えていて、考えうる全てのパターンを試す必要があると考えていた。 そうなると、探索空間も膨大になるわけで、、、。(以下ドキュメントに記載予定) とにかく、このことを考えながら、後の空白の三ヶ月に突入することとなる

空白の三ヶ月(6〜9月中盤)

 この間には、夏休みを始め多くの休日が存在していたが、ほとんどコードを書けなかった。理由としては、時間を遊びに使ってしまったこと、まだ時間があると考えてしまったこと、とりあえず指を動かさなかったこと、問題を解く気にならなかった事にある。 根本的には、問題を解く気にならなかった事が原因だと思っている。
 先延ばし魔の威力は絶大なものだったと今でも反省している。
 

精神と時の部屋(9月終盤〜プロコン当日)

 結局、夏休みの最終盤までコードを書くことはせず、地獄の二週間が始まることとなった。ここまでに実装されていたのは、ピースの定義・当たり判定・座標をピースに変換する関数だけで、言ってしまえば、他の関数は実装されていなかった。

ピースの結合(プロコン二週間前〜プロコン一週間前ぐらい)

 まず取り掛かったのは、ピースの結合である。
 ピースの結合とは、ピースAのある点Anと、ピースBのある点Bmを、合わせることにより、新しいピースに変換する動作である。角度と裏表を付けたピースを2つ用意し、誤差範囲以下にある2つの点を原則一つの点にした後、角度が360度か180度になった点を排除する。このことにより実装した
 最も基礎的な部分であるが、考えた項目(辺の上にある点、点が辺に接触する場合、図形の中に図形を内包する場合など)が多く、結合の時に発生する全ての事象を考慮しようとし、多くの時間がかかり、思考に苦労した。

誤差と探索 (プロコン1週間前ぐらい〜プロコン4日前)

 この時から、パズルのピースとモニタを 二対一 でにらめっこすることとなる。
 画像を取り込む時に発生する誤差、それをプログラムすることは楽に出来た。ただ、誤差の調整と全探索は、両者は矛盾しているものだと思うこととなる。
 問題は、プログラムは、現実は異なるピースを誤差が原因で、同じピースであると判断すること、もしくは、本来は同じ座標にある点が誤差が原因で、合成されなくなることであった。 ピースの結合が狂うことの問題は、全探索しようとする時に発生し、誤差と全探索の間に発生する矛盾を考えていた。

手動動的計画法(プロコン4日前)

 大会まで残り4日になった中、私は、探索を動的計画法(当時は、ピース一つ一つの結合を小さな問題と考えていた)で書こうと思っていた。ただ、誤差を考えると、プログラムが書けなくなることも知っていたわけである。 そんな中、部活に参加してある声を聞くこととなる
>> 人力をサポートするプログラムを作れば?
 まぁ、こんな感じの声だったと思う。動的計画法・全探索・誤差・残りの時間・人力のサポート・自分の現状・・・そんな事を考えながら、お風呂から上がると、突然と指が動き始めた。私が手動動的計画法と名付けるアルゴリズムの設計が、微小な時間にて書き上げられたのである。
 
手動動的計画法は、誤差と全探索の矛盾を埋め合わせるために考えたアルゴリズムで、動的計画法で言う"小さな問題を解くこと":このプログラムで言う"確定されたピースの結合"は人間が行う。プログラムの機能は表面上、1)結合できるかもしれないピースを候補として表示する事と、2)人間が他にパターンが無いと判断したピースの候補を、コマンドライン上に打ち込ませること、3)そして内部的なピースの状態を更新することの3つである。

ここに画像を追加する予定

新たなる実装(プロコン3日前〜競技部門本戦中)

 新しいアイディアを考えてから、他の人の手を借りながら実装を始めた。そして、三日三晩の徹夜や、特急コーディング、そして、会場コーディングを経て、実装が終わることとなる。

戦いの終焉(プロコン競技部門終了〜数日後)

 結果として、プログラムはつまらない理由(ファイルシステムの違い)で動作しなかった。他のいかなるプログラムも人力に圧倒された事、もっと計画的にやっておけば良かったという反省・・・などと、残念な気持ちに支配されながら、今年のプロコンは終わった。

反省点

  • 大会前のデスマはするべきでない。そもそもやった時点で負けだと思うべき
  • チームメートとのコミュニケーションをもっと取っておけばよかった。
  • 緊張により、大会中にいつも通りのパフォーマンスを出せなかった。練習を予め積んでおけば、緊張はほぐされたと思う
  • 長期休業中にプロコンの準備ができると思わないほうがいい。可能なら、休業前に作るべき
  • 先延ばし魔の恐怖を味わう前に片付ける
  • 完全に動くと思われたプログラムが、つまらないミス(文字コードの互換性)で動作しなかった。練習を予め積んでおけば、問題に対処できたと思う。
  • もっと他の高専生達と交流したかった(ただし運営側のシステムにも問題がある。)
  • 計画性がなかった。もっと早い時期から書いていたら、徹夜も軽いものになっただろうし、練習の時間もとれ、プログラムの質が上がっただろう
  • モチベーションの維持が出来なかった(運営にも問題がある気がするが...。)やる気さえあれば、計画無視で急速にプロジェクトが進むと思った。

成果物

二回戦開始直前に作り終えたプログラム。
本番では、Windowsとのファイルシステムの違いにより、データを読み込めなかったと言う悲劇が発生した。
簡単にシステム概要を説明すると、
ピース毎の頂点座標を入力すると、ピース(枠を含む)に変換し、合体出来るピースの候補を探索・表示してくれる。
そこで、どのピースを合体したか?コマンドラインから入力することで、ピースの数がどんどん減っていく仕組み
f:id:ikemaki:20161014193441p:plain

ソースコードはこちら
github.com

微修正やドキュメント整備は後日やります。
アルゴリズムの詳細なども追加する予定

その他

デバイスの通信量を記録するツールを作ってみた

 学校でネットワークの通信量を日ごとに見られるソフトをインストールせよ、との指令が出た。Windows版なら学校側から推奨されているソフトがあったが、Linuxには自分の体に合いそうなものは存在しなかった。
 仕方ない。自作るか

github.com

機能について

このツールには以下のような機能がある、

  1. 独自の形式のログファイルを作成し、そこに日ごとのデバイスの通信量(受信・送信)を記録する
  2. /proc/net/dev にはシステムが起動した以降に、それぞれのデバイスが何バイト分の通信をしたかの情報が出力される。この差分を一定時間ごとに取得し、ログに書き込む
  3. GUIの実行が可能で、日ごとの通信量が表として表示される

ドキュメントなど

Githubに追加予定

その他

出来たてホヤホヤで多分バグの宝石箱
何れ直していくさ。

追記 2016/05/29

案の定重大なバグが発生した。日付変更時に連続して起動していても、次の日のログへの変更が発生しない と言うものである。 しばらくの間は所用により変更できないため、6/10以降にバッチを作成しようと思う

Open Data Day 2016 in GEEKLAB.NAGANO に参加したためメモ書き

Open Data Day 2016 in GEEKLAB.NAGANO feat.NSEG に参加したためメモ書きします
glnagano.doorkeeper.jp

Open Data Day について

Open Data Dayの公式サイトには、オープンデータデイについて以下のようにあります

オープンデータデイは、オープンな公開データを使ってアプリケーションを書いたり、データを開放したり、視覚化したり、分析結果を公開するために世界中の市民が集まって、世界の地方、地域、そして中央政府によるオープンデータに関する政策の導入を支援、奨励します。

http://opendataday.org/index_ja.html
おそらく、オープンデータを活用してプレゼンやハッカソンをするイベントを同時開催するという趣旨のイベントです

今回、GeekLabNaganoではMonacaニフティクラウドを使った簡潔にアプリを作成する方法が紹介されました
これを元に、ハッカソンでは自分がいたチームは災害時支援アプリを作っていくことになります

おおよその日程

2016 3月5日に実施

時刻 やったこと
10:00~10:20 オープニング + ODD2016とGEEKLAB.NAGANOの紹介
10:30~12:00 ハンズオン(ニフティクラウド様)
13:50~17:30 ハッカソン (チームに別れて制作)
18:00〜20:00 懇親会・成果発表

ハンズオン

ハンズオンではニフティクラウドの川原 史識 さんが、Monacaニフティクラウドを合わせた、オープンデータを用いたスマホアプリを簡単に作る方法が紹介されました。
sssslide.com
Monacaは、スマホアプリを作るツールで、HTML5とJSで開発するものです。それぞれの環境にビルドするという方式をとっているらしく、センサにアクセスする機能があり、WEBで開発できます。
ニフティクラウドは、無料から使えるクラウドサービスで、楽にサーバー構築でき、SDKを入れるだけで簡潔にサーバーとのやりとりができるというサービスです。
このMonacaニフティクラウドを合わせると、楽に○○マップが作れる。そして、除雪マップの市民に除雪させるアプリや、Pepperの観光案内、鎌倉今昔写真というアプリなどに、活用されている。ということが紹介されました。
この時、Monacaニフティクラウドの登録をし、サンプルアプリをいじってみた といったことが今回のハンズオンの内容でした。

ハッカソン

ハッカソンでは、2〜4人程度のチームに別れて制作したり、設計したりしました。
ルールは、オープンデータを使った地域に役立ちそうなものを作るということでした。

アイディアの例

チームごとの制作の前に、オープンデータを活用するアイディアについて紹介さました。以下に例の一例を出します 

  • おくやみ情報
    • 友人が死亡していた時とかに通知してくれると便利かもしれないと思った。
  • Wifiマップ,充電器の場所 
    • フリーWifiの場所とか知りたいときは多い。
  • 緑の自転車の乗り捨て場 停車所とかを表示 
    • 長野市内の無料で借りられる自転車。観光客とかには停車所の位置情報は必須だと思った。

自分のいたチームについて

自分のいたチームでは、色々と議論した後、災害時の助け合いをすすめるアプリを作成することに決定しました。
ここから、各々に作業を分担し、1人はプレゼン資料作成、1人は地図への表示機能、そして自分はアンケート機能を制作していきました

制作しようとしたもの 概要

災害時に活用するアプリ
支援を必要とする要支援者と、要支援者を支援する支援者を橋渡しするツール。主に2つのモードがある

  1. 要支援者のためのアンケートを入力フォーム
    • 名前や緯度・経度、緊急度のレベル付、必要な支援の登録、メッセージの入力を行う
  2. 支援者のためのマップ
    • 入力されたデータを元に、マップに情報を表示する
    • 火事場泥棒対策のため、詳しい位置は最初からは表示しない。円でぼかしておく
    • 緊急度のレベルに基づく色分け
    • 特定のニーズに合わせた絞り込み

といった機能を考えました
アプリ上での実装目標です
f:id:ikemaki:20160306005133p:plain

制作結果

自分は要支援者のためのアンケート入力フォームの作成を行いました。
フォームの型の作成は難なく出来ましたが、2時間近くJavaScriptが使えない謎の自体に陥りました。そこで、Monacaの確認のエミュレーターのようなものを利用してテストしていたところを、ブラウザを使ってテストをするようにすると、JavaScriptが使えるようになりました。たぶん、エミュレーターがJavaScirptの読み込みができないことによると思いました。
JavaScirptが使えるようになってから、サーバーへの送信関数を作ろうとしましたが、ここでタイムオーバーになりました。
成果物を上げておきます。 必要な機能を満たしていないため、これからも機能を追加できたらなぁと思います。
GitHub - Makinori/disaster_support