2019年、学部3年、夏季休暇研究

自分で以下のテーマを設定しました

「夏季休暇の15日間を使って、研究っぽいことをしてください」

この結果についてまとめます。

 

1. やったこと、時間的な流れ

1-4日目

人工知能関連にしようと決めました。人工知能関連の論文を読みました。

その後、サブサンプションアーキテクチャ関連に絞りました。

 

5-8日目

サブサンプションアーキテクチャ関連の論文を読みました。

サブサンプションアーキテクチャを試せるシミュレーションソフト、SB-MASEを見つけました。

具体的なテーマを、「サブサンプションアーキテクチャによる知的な振る舞いの創発」に決めました。

 

9-10日目

SB-MASEで、サブサンプションアーキテクチャを構築、実装しました。

具体的な内容は後ほど、説明します。

 

11-13日目

人工知能学会誌を読みました。201905、201907、201909。

 

14日目

今後の展開について検討しました。

 

15日目

内容をパワポにまとめ、家族に発表しました。

 

2. 成果

・研究の難しさがわかった

・論文を読んだ

・情報収集のやり方がわかった

・研究テーマの実行:サブサンプションアーキテクチャによる知的な振る舞いの創発

 

・研究の難しさがわかった

研究テーマ決定が一番難しく、一番重要

  • 時間内で達成できる内容である必要がある
  • 意味のある研究である必要がある
  • 最終的な目的から、トップダウンに降ろしてくるのが難しい
  • 先行研究がどこまで進んでいるか把握する必要がある

 

・論文を読んだ

7本の論文と、2本の解説を読みました。

  • 論文:テーブル上の物体の片づけを促すためのロボットの振る舞い
  • 論文:医師国家試験自動解答プログラムの処方薬問題への拡張
  • 論文:感情表現を用いた説得対話システム
  • 論文:恒常性創発にむけた自発的同期に基づく振動子の集合体による自律制御
  • 論文:人間型ロボットのキャラクタ表現のための対話の振る舞い制御モデル
  • 論文:対話アンドロイドに対する主観的意見の帰属と対話意欲の関係
  • 論文:追加データを用いない未来の分類器学習法
  • 解説:サブサンプション・アーキテクチャ
  • 解説:サブサンプションアーキテクチャを用いたロボットの制御

 

・情報収集のやり方がわかった

  • 自分の過去の調べ学習を漁る
  • インターネットで検索する
  • 論文、特集、学会誌を読む
  • 人工知能学会、日本ロボット学会に入る
  • キーパーソンについて調べる
  • 海外の有名なコミュニティについて知る

 

・研究テーマ実行:サブサンプションアーキテクチャによる知的な振る舞いの創発

 

以下の記事で紹介します。

person.hatenablog.jp

 

3. 今後について

  • 4年の研究テーマはどうする?
  • 秋学期は何をする?
  • 脳をサブサンプションアーキテクチャでモデル化できる?
  • 方向性は、AGIの実現を目指す、で良いの?
  • 機械学習がビジネス的には強いけど、専門にしないの?

 

4. まとめ

  • 15日間で、情報収集、研究テーマ決定、研究、発表をやった
  • 研究テーマは、SAによる知的な振る舞いの創発
  • 論文を読んだ:論文7、解説2
  • 研究テーマ決定の難しさがわかった
  • 情報収集のやりかたがわかった

 

オススメの芸能人をレコメンドするアプリの実装

2択の質問に5回答えてもらい、その結果をもとにオススメの芸能人をレコメンドするWebアプリを作りました。

 

 

1:アプリの説明

2:実装について

3:感想

4:今後の展開

 

1:アプリの説明                     

STARTボタンを押して解答を始めます。

STARTボタンを押すと、図2のような2択から選択する画面に移動します。画像をクリックすることで選択することができます。5回選択してもらいます。

5回選択すると、図3のような画面に移動します。5回の選択をもとにオススメの芸能人をレコメンド結果を表示します。

 

f:id:wada0421514:20180813150759p:plain

図1 スタート画面

 

f:id:wada0421514:20180813150852p:plain

図2 2択選択画面

 

 

f:id:wada0421514:20180813150906p:plain

図3 レコメンド結果表示画面

 

2:実装について                     

芸能人の画像を集めて、それぞれの芸能人を表現するベクトルをオートエンコーダで学習して、Webページを作りました。

 

3:感想                      

画像を収集するのに苦労しました。WebAPIを使ったのですが、結構時間がとられました。

Webページの実装も手間取りました。レンタルサーバを使ったのですが、まともなWebページの制作は初めてだったので、やり方がさっぱりわからず試行錯誤しました。

ニューラルネットワーク関連の実装は学習や推論ではなく、その前後の準備、インターフェースなどに時間がかかるとよく言われていますが、自分の身をもって実感しました。

 

4:今後の展開                     

このWebアプリに関してやりたかったことがもっとありましたが、今回はこの辺で一旦、完成としました。今後やりたいことは以下です。

 

・レコメンドのアルゴリズムを改善する(現在はかなり単純)

・学習用の画像を増やす(現在は1人100枚前後)

・レコメンドされる芸能人を増やす(現在は500人前後)

・男性芸能人、犬猫など、他の対象にスケールする(現在は女性芸能人のみ)

スマホアプリ版を実装する(現在はWebアプリのみ)

・インターフェースをモダンにする(現在は最低限のみ)

・2択の回答回数を増やす100回などに増やす(現在は5回)

 

強化学習の手法まとめ

強化学習の有名な手法をまとめます。

強化学習とは、知能を、環境によって行動を決定するエージェントと見なして学習する、機械学習の1つです。

 

以前、強化学習の1つである、モンテカルロとQ-Learningは実装したので、そのリンクを貼っておきます。

 

person.hatenablog.jp

 

 

以下の順番で説明します。この他にも、SARSA、DDQN、DuelingDQN、PPOなどいろいろありますが、時間がないので割愛します。

 

1:Q-Learning

2:モンテカルロ

3:DQN

4:A3C

5:UNREAL

 

 

1:Q-Learning

 

Q-LearningはQ関数を利用する手法です。Q関数はある状態sにおける行動aによって決まり、Q(s|a)と表現されます。Q(s|a)はある状態sにおける行動aの適切さを示します。Q(s,a)が一番大きい行動をエージェントは行います。ですから、学習してQ関数の最適なパラメータを得ることで、エージェントは最適な行動がとれるようになります。Q関数は表で表現されます。取り得る状態が10種類、可能な行動が3種類である場合、(10*3)の表です。Q-Learningでは、Q関数は以下の式で更新されます。

Q(s,a)←(1-x)*Q(s,a)+x*(r+y*max(s',a'))

x,yは学習率などのハイパーパラメータです。この式で繰り返し更新することで、適切なQ関数を得ます。

 

2:モンテカルロ

 

Q-Learningと同様に、モンテカルロもある環境のある行動を評価する方法です。しかし、内容はかなり異なります。モンテカルロでは、ある行動を評価する時、実際にその行動が行われたと考えて、報酬が得られるまで、行動を続けます。その結果、得られた報酬をもとにある行動を評価します。オセロであれば、ある一手を評価するために、その一手を打ったとして決着がつくまでゲームをして、これを繰り返すことで勝率を出して、ある一手を評価します。

 

3:DQN(Deep Q-Network)

 

Q-Learningは表で表現されたQ関数を学習する手法です。しかし、表は有限であるため、できることに限りがあります。それを解決するために、Q関数を深層ニューラルネットワークで近似したのがDQNです。

 

4:A3C(Asynchronous Advantage Actor-Critic)

 

DQNにAsynchronous、Adavantage、Actor-Criticを加えた手法です。Adynchronousとは、複数のエージェントを並列に動かして、その結果を集めて学習する方法です。Advantageは数ステップ先まで考慮した報酬の計算方法です。Actor-Criticはある環境である行動をする確率と状態の価値の推定を独立に行うことで、行動が連続的でも対応できるようにする方法です。

 

5:UNREAL(UNsupervised REinforcement and Auxiliary Learning)

 

A3Cのネットワークに直接の目的とは異なる補助タスクを組み込むことで、学習をうまくさせる方法です。DeepMindから発表されたかなり新しい方法です。

 

 

参考にしたリンクを貼っておきます。

 

qiita.com

 

blog.brainpad.co.jp

 

以上、強化学習の手法まとめでした。アドバイス、改善点があればお願いします。

強化学習Q-Learningで最強のゲームAIの開発

ゲームの説明

1から順に交互に数字を言って10を言えた方が勝ちのゲームです

1ターンで数字は1つか2つ言えます。

プレイヤーは2人です。

このゲームは勝ちパターンがあるゲームです。勝ちパターンさえ把握していれば先行は必ず勝つことができます。

 

やること

3種類のAIを実装します。総当たりで戦わせ、最強のゲームAIを決定します。

 

ランダムプレイヤーの説明 

ランダムに行動を行います。

ランダムに1つ言うか2つ言うか選びます。

 

モンテカルロプレイヤーの説明

モンテカルロ法で行動を決定します。

モンテカルロ法とは、ある状態における行動を評価する方法です。自分がその行動をとったとして、そのまま最後までランダムプレイヤー同士にゲームを進めさせ、勝ったか負けたか記録します。これを何回も行い、勝率を計算して、その行動の良し悪しを評価するということです。

 今回は100回ランダム対戦させて行動評価します

 
Q-Learningプレイヤーの説明

強化学習の一種であるQ-Learningで学習し、行動を決定します。

Q-LearningではQ関数を学習します。

Q関数は、ある状態における、ある行動の評価値の配列で表現されます。今回は、状態が0から9の10種類、行動は1,2の2種類なので、Q関数は2*10の2次元配列です。

更新式は、Q(s,a)←(1-α)*Q(s,a)+α*(r+γ*maxQ(s',a'))です。sは状態、aは行動です。s'、a'は、sでaをして得られる状態s'と、そこでの行動a'です。詳しくは、以下のリンクを見てください。

qiita.com

 

対戦結果

100回対戦した結果は以下です。数値は後攻に対する先行の勝率です。

このゲームは、勝ちパターンさえ把握していれば先行が必ず勝てるゲームです。

Q-Learningは先行の時、全ての相手に対して勝率100%です。勝ちパターンをしっかり学習できています。

                                     表1 先行の勝率(%)

   後攻
先行
ランダム モンテカルロ Q-Learning
ランダム 48 19 11
モンテカルロ 80 71 64
Q-Learning 100 100 100

 

コード 

作成したコードは全てgithubに全て上げてあります。

github.com

 

感想 

ランダム、モンテカルロ、Q-Learningを実装しました。

簡単なゲーム設定ではありましたが、良い結果が得られたのでうれしいです。

kaggleチュートリアルtitanicに挑戦

kaggleは機械学習競技プログラミングみたいなやつです。これのチュートリアルtitanicをやります。機械学習によるデータ解析を実際に体験することが目的です。部屋の等級、性別、兄弟夫婦の人数、親子の人数、年齢層に対してカーネルSVMを使うことで精度82%まで行きます。

 

問題について公式の説明のリンクです。

Titanic: Machine Learning from Disaster | Kaggle

 

以下のリンクを参考にしました。英語ですが、かなりわかりやすいです。

EDA To Prediction(DieTanic) | Kaggle

 

描画のライブラリmatplotlibの解説はこれがわかりやすかったです。

bicycle1885.hatenablog.com

 

データを扱うためのライブラリpandasはこれがわかりやすかったです。

qiita.com

 

 

1:データを分析する

2:データを加工する

3:モデル選んで、学習して、精度確認

 

この3ステップでやります。

 

作成したプログラムは全てgithubに上げてあります。

github.com

 

         1:データを分析する

データを読み込みます。nullがあるデータを確認します。性別、年齢、共に乗った人、に順に注目してデータを可視化して分析しました。最後にtrain2.csvにデータを保存しました。analyze.pyです。

f:id:wada0421514:20180408105558p:plain

性別と生存率のグラフです。女性は生き残る確率が高く、男性は低いことがわかります。

f:id:wada0421514:20180408105731p:plain

部屋の等級と生存率のグラフです。上のクラスであればあるほど、生き残る確率が高いことがわかります。

f:id:wada0421514:20180408105840p:plain

まばらな感じですが、子供やお年寄りは生き残る確率が高く、中間層は低いことがわかります。

f:id:wada0421514:20180408110053p:plain

兄弟夫婦の人数は1人が生存率のピークです。0人でも生存率は下がります。また、多ければ多いほど、下がるようです。

f:id:wada0421514:20180408110420p:plain

親や子供の人数は1,2,3人だと生存率が高いです。0人だと下がります。4人以上で、かなり下がります。 

 

          2:データを加工する

年齢データ(Age)が連続値であるため、学習できないので 、年齢層で0から4の値を持つAge_bandに変換しました。性別データを0,1の数値データに変換しました。予測に必要のないデータを削除して、保存しました。convert.pyです。

f:id:wada0421514:20180408113153p:plain

 年齢層と生存率のグラフです。16歳以下の生存率が一番高いです。

 

 

         3:モデル選んで、学習して、精度確認

加工したデータを読み込みます。学習用にデータを変換します。カーネルSVMで学習して、精度確認して、終了です。精度は以下のようになりました。82%です。コードは1.pyです。

 

Accuracy(rbf SVM): 0.8208955223880597

 

 

以上、kaggleチュートリアルtitanicでした。kaggle、pandas、scikitlearn凄いです。

 

アドバイス、改善点、質問があればお願いします。

RNN、LSTMで時系列データを生成

文脈を持つ時系列データをRNN、LSTMに学習させて、新たなデータを生成することを目的とします。

 

以下の本を参考にしました。

shop.ohmsha.co.jp

 

今回は3種類のデータを用意します。

1つめは、テキストデータです。英文です。

2つめは、アルファベット順に並んだアルファベット列です。スタートの単語、単語数は自由とします。

3つめは、数字が前の2数の足し算になっている数列です。スタートの2数はランダムに決めます。また、数字は1桁のみとします。3、9ときたら次は12ではなく2です。

 

この3種類のデータを学習させて、生成させることが目的です。

 

1:データを用意する

2:環境を整えて、学習準備

3:学習する

4:生成する

5:結果確認

 

この5ステップで説明します。

 

作成したプログラムは全てgithubに上げてあります。

github.com

 

         1:データを用意する

 

作成したプログラムは data_pre.py、data_pre2.pyです。

まず、テキストデータについてです。GPUがないため、大容量のデータは学習できないので、自分で適当に打ったやつを使います。とりあえずRNNを試せればいいので10行程度のかなり軽いものです。今度、暇があったら、しっかりとしたデータで取り組みたいと思います。これをtrain.txtとして保存しました。

次に、アルファベット列データです。自分で作ります。data_pre.pyです。このデータをtrain_alpha_raw.pklに保存します。

最後に、数列データです。これも自分で作ります。data_pre2.pyです。このデータをtrain_number_raw.pklに保存します。

 

         2:環境を整えて、学習準備

 作成したプログラムはconvert.pyです。

学習できるようにそれぞれのデータを数値データにする必要があります。それぞれの単語などに対応するidを用意して、idでデータを置き換えます。そのデータを保存します。convert.pyでこれをやっています。

 

アルファベット列のidデータセットは、train_alpha_con.pkl、id辞書はtrain_alpha_voc.pklです。

数列は、train_number_con.pkl、train_number_voc.pklです。

テキストデータは、train_txt_con.pkl、train_txt_voc.pklです。

 

 

         3:学習する

作成したプログラムはrnn.py、train.pyです。

まずRNNのネットワークをクラスで定義します。rnn.pyです。これを使って2で用意したファイルからデータを読み込んで学習します。最後に学習したパラメータをファイルに保存します。これはtrain.pyです。テキストデータは、train_txt_embed.pkl、train_txt_H.pkl、train_txt_W.pklに保存します。アルファベット列と数列では、txtの部分がそれぞれalpha、numberに代わります。LSTMは、L.LinearをL.LSTMに変えるだけで使えます。今回は、RNNを学習します。

  

          4:生成する

学習は完了しました。結果をもとにデータを生成します。3同様、RNNのネットワークを使うのでrnnをimportしています。LSTMではなくRNNを使っています。

 predict.py です。

 

         5:結果確認

テキストデータ、アルファベット列、数列、各条件で5回ずつ生成します。LSTMではなく、RNNの結果です。

 

1:テキストデータ

テキストデータはそもそも単語数が20種類くらいしかないので、結果は知れていますが、やってみます。

 

10epoch:

many am many am many am many am many am many am many am many am many am many am
night hello you am family do do do person person person from from from from person person am everyone from
likes have do my you am family do do do person person person from from from from person person am
am Tokyo hello you my you am family Tokyo do am you from likes am everyone my are am many
night have am everyone from from from from person person am everyone from from from from person person am everyone

 

100epoch:

name is <eos>
your name <eos>
have <eos>
is your name <eos>
is your name <eos>

 

1000epoch:

are you from <eos>
are you from <eos>
name is person <eos>
<eos>
beautiful day <eos>

 

2:アルファベット列

データ数も変化させて比べてみようと思います。100epoch、100dataで学習に1分かかりました。きついです。アルファベット順になればokです。

 

10epoch:データ数100

<eos>
<eos>
<eos>
h i j <eos>
<eos>

 

100epoch:データ数100:

k l m n o p q r <eos>
c d e f g h i j <eos>
i j k l m n <eos>
<eos>
i j k l m n <eos>

 

10epoch:データ数1000:

<eos>
m n o p <eos>
h i j k l m n o <eos>
f g h i j k l <eos>
k l m n o p q <eos>

 

3:数列

前の2数足した値になればokです。2桁になる場合は1桁目だけです。あんまりうまくいってないです。epoch数とデータ数を増やせば、いい感じになると思います。

 

10epoch:データ数100:

8 8 <eos>
2 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 2 8 <eos>
<eos>
<eos>

 

100epoch:データ数100:

4 2 6 8 4 2 6 8 4 2 6 8 4 2 6 8 4 2 6 8
<eos>
4 7 6 <eos>
<eos>
<eos>

 

10epoch:データ数1000:

8 7 9 4 9 5 4 9 7 8 7 7 4 3 7 8 3 1 8 9
6 5 4 4 7 0 6 3 1 9 1 2 <eos>
2 <eos>
6 5 4 4 7 0 6 3 1 9 1 2 <eos>
8 8 0 0 4 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0

 

以上です。今度、GPUを用意して本格的にやってみたいです。

アドバイス、改善点、質問があればお願いします。

pythonの復習:基本的な操作

pythonの基本的な操作についてまとめます。出力、繰り返し、リスト、辞書、関数、便利な記述法、クラスについてです。

 

以下の本を参考にしました。

book.mynavi.jp

 

1:pythonの復習:出力、繰り返し

2:pythonの復習:リスト、辞書など

3:pythonの復習:関数、便利な記述法

4:pythonの復習:classについて

 

この順番で説明します。

 

 

   1:pythonの復習:出力、繰り返し

print、input、if、elif、else、pass、for、range、break、continue、変数関数についてです。

#pythonの復習1、出力、繰り返し

grade=2
old=19
print("学部",grade,"年です.",end="")
print("よろしくお願いします") #学部2年です.よろしくお願いします
grade_str=str(grade) print("学部"+grade_str+"年です.") #学部2年です. print("年齢:{0},学年:{1}".format(old,grade)) #年齢:19,学年:2 print("{first}+{second}={result}".format(first=3,second=2,result=5)) #3+2=5
name=input("hello") #helloと表示される。入力できる。nameに代入される。 number=2 #if,elif,else if number%10==0:print("10で割れる") elif number%5==0:print("5で割れる") else:print("わからん")
n=5 #pass、何もしない if n==4:pass else:print(n) for a in range(5):print(a,end="") #01234 for a in range(1,6):print(a,end="") #12345 for a in range(1,6,2):print(a,end="") #135 for a in range(10): print(a,end="") #0123 if a==3:break for a in range(5): print(a,end="") if a%2==0:continue print("odd",end="") #01odd23odd4 a=30 #関数みたいにいろいろできる a=a.__add__(5) #a=35 print(dir(a)) #使える関数一覧が出てくる

 

   2:pythonの復習:リスト、辞書など

 list、enumerate、del、タプル、辞書、keys、values、itemsなどです。

#pythonの復習2、リスト、辞書など

list1=[1,3,5,7]
for a in list1:
    print(a,end="") #1357
    
list2=["a","b","c"]
for a,b in enumerate(list2): #indexと値が入る
    print(a,b)

a=[1,2,3]
a+=[4,5,6] #a=[1,2,3,4,5,6]
print(a[1:3]) #[2,3]
print(a[::2]) #[1,3,5]
print(a[1:5:2]) #[2,4]

a=[1,2,3,4,5,6]
del a[2] #a=[1,2,4,5,6]

a={1,2,3,4}
print(1 in a) #True
b={1,2}
print(a-b) #{3,4}
c={3,4,5}
print(a|c) #{1,2,3,4,5}
print(a&c) #{3,4}

dic={1:11,2:22,3:33}
print(dic[1]) #11
print(list(dic.keys())) #[1,2,3]
print(list(dic.values())) #[11,22,33]
print(list(dic.items())) #[(1,11),(2,22),(3,33)]
for a,b in dic.items():print(a,b) #keyとvalueが入る

a,b,c=[1,2,3]
print(a,b,c) #1 2 3

 

   3:pythonの復習:関数、便利な記述法

 args、lambda、import、map、filter、内包表記などです。

#pythonの復習3、関数、便利な記述法

def sumargs(*args): #引数任意の関数
    result=0
    for a in args:result+=a
    return result
print(sumargs(1,2,3,4,5))#15

def argsargs(**args):return args #引数が辞書に入る
print(argsargs(a=1,b=2,c=3)) #{'a': 1, 'b': 2, 'c': 3}
print(argsargs(a=12,b=13,c=14)) #{'a': 12, 'b': 13, 'c': 14}

x=lambda x:x*2 #気軽に関数定義
print(x(2)) #4
print(x(3)) #6

list3=[1,2,3,4,5] #関数をlistの中身全部に実行するmap
x2=lambda x:x**2
print(list(map(x2,list3))) #[1,4,9,16,25]

x3=lambda x:x%2==0 #フィルターをlistの中身全部に実行filter
print(list(filter(x3,list3))) #[2,4]

from chainer import Link #chainerから選んでimport
from matplotlib import * #matplotから中身全部import

data=[i*2 for i in range(5)] #data=[0,2,4,6,8]
data2=list(map(lambda x:x*2,range(5))) #data2=[0,2,4,6,8]
data3=[i for i in range(5) if i%2==0] #data3=[0,2,4]

base=[1,2,3]
data4=[(x,y) for x in base for y in base]
#data4=[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
data5=[(x,y) for x in base for y in base if x!=y]
#data5=[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]

 

    4:pythonの復習:classについて

class、__init__、継承、__call__などについてです。

#pythonの復習4、classについて

class Student:
    def __init__(self,id,score=0): #__init__で初期化
        self.id=id
        self.score=score
    def setscore(self,score):self.score=score
    def getscore(self):return self.score

class Calc: #classを使うclass
    def __init__(self):self.students=[]
    def add(self,student):self.students.append(student)
    def ave(self):
        result=0
        for i in self.students:result+=i.getscore()
        result=result/len(self.students)
        return result

s1=Student(1,50) #calcに生徒のデータを追加して、成績の平均を求めることができる
s2=Student(2,60)
s3=Student(3,80)
calc=Calc()
calc.add(s1)
calc.add(s2)
calc.add(s3)

class A:
    def printa(self):print("a")
class B:
    def printb(self):print("b")
class C:
    def printc(self):print("c")
class D(A,B,C): #classの継承
    def printd(self):print("d")
    def printall(self):
        self.printa()
        self.printb()
        self.printc()
        self.printd()
d=D()
d.printa()
d.printd()
d.printall()

class Game:
    def __init__(self):
        self.score=100
        self.count=3
    def start(self):print("start")

class Cardgame(Game): #classの継承
    def __init__(self):
        super().__init__()
        self.max=53

    def next(self):print("next turn")
first=Cardgame()
print(first.score)
print(first.max)
first.next()

class List_practice: #__call__でクラス自身を関数みたいに使える
    def __init__(self,length):self.list1=[i for i in range(length)]
    def __call__(self,number):print([i*number for i in self.list1])
    def add(self,number):self.list1.append(number)
    
mylist=List_practice(5)
mylist(2) #[0,2,4,6,8]
print(mylist.list1) #[0,1,2,3,4]

 

pythonの復習をしました。

アドバイス、改善点、質問などがあればお願いします。