2017年4月25日火曜日

機械学習を学習してみるか 〜単純パーセプトロンで顔文字の感情推定〜

最近やたら流行ってますね.人工知能.これからの世界は人工知能が牛耳って,人間の大半は人工知能に代替され職を失うようです.そうしたら働かなくて済むので1日も早くそうなって欲しいですが,本当に情報科学のあらゆる分野で「人工知能」というワードが聞かれるようになりました.どうやら,情報科学に携わるものは,人工知能が分からなければ,この先最新の研究内容に触れることはできなさそうです.
というわけで,ずっと避けてきた,人工知能分野の勉強を少しずつ始めてみたいと思います.人工知能といってもいろいろあると思いますが,まずは基本,機械学習から.

ニューラルネットワークの基本,単純パーセプロトロンをやってみます.ちなみに,この記事は,単純パーセプトロンとは何か,どういう仕組みなのかを勉強し,それを記事として記録するものではありません.そういった学習が終わった後,私なりに「こういう風に使えばいいのか?」というのをやってみるという内容です.ですから,機械学習初心者のみならず,ベテランの方もお読みいただいて,「ここはこうすればいいのだ」等の指摘をいただけると非常に励みになります.

単純パーセプトロンというのは皆さん知っていますね.こういうやつです.



青グループと赤グループを教師データとして学習しておけば,両グループの境界線を勝手に求めてくれます.一度学習してしまえば,次に新しいデータが入力されてもどちらのグループに属するのか判定することができます.

ここまでは,本を読むかGoogleで検索すれば簡単に概要およびプログラムを見つけることができます.ここからが本題.折角覚えた単純パーセプトロン.何かしらに使ってみたくなるのが人情です.そこで,今回はこんなことをやってみることにしました.今回の言語はPythonを使いました.

「いくつかの顔文字とその感情(今回は 喜と哀)を学習し分類する.その後未知の顔文字の感情を推定する」

今回は喜と哀を分析します.どうでもいいことですが,人間の基本的な感情としてよく言われる「喜怒哀楽」は単純パーセプトロンで推定することはできません.何故か?分からなくてなおかつ気になる方はもう少し単純パーセプトロンについて調べてみましょう.

まず,学習データとなる顔文字を用意します.ここでは,「顔文字」とは丸括弧の中に3文字の記号が入ったタイプを想定します.今回はこれらを使います.

(^_^)(^∀^)(^o^)(^ω^)(;_;)(>_<)(◞‸◟)(゚Д゚)

左から

喜 喜 喜 喜 哀 哀 哀 哀 

とします.今考えると,一番右は哀じゃない気がしますが,例題なので大目に見ます .

次に,それぞれの顔文字に使われている文字に数字を割り当てます.とりあえず,喜に使われそうな文字は小さい数字,哀に使われそうな文字は大きい数字にしました.こんな感じで0から12まで割り当てました.

(^  _ ^)(^∀^)(^o^)(^ω^)( ;  _;) (> _ <) (◞  ‸  ◟)  (゚ Д゚)
 0 7       1     6      2   12     10 11   3 9 8    5 4

ここまで決めたら,データとしても顔文字を作ります.また,喜を1,哀を-1として教師データも作ります,

N=8
ETA=0.1
#顔データ
face=[[0,7,0],[0,1,0],[0,6,0],[0,2,0],[12,7,12],[10,7,11],[8,9,3],[5,4,5]]
#教師データ
t=[1,1,1,1,-1,-1,-1,-1]

今回は,顔データとして3次元のベクトルを8個定義しましたので,それらを二分する境界面(3次元なので面になる)

ax+by+cz+d=0

を単純パーセプトロンによって求めます.機械学習なんて大層な名前の技術の割に,結構簡単にできます,詳しいメカニズムは書籍や他のブログ等を当たってみてください.

w=[1.0,1.0,1.0,1.0] #ax+by+cz+d=0の各係数を[a,b,c,d]とする
correct=0
while correct<N:
    correct=0
    for i in range(N):
        if np.dot(w,[face[i][0],face[i][1],face[i][2],1])*t[i]>0:
            correct+=1
        else:
            w+=ETA*np.array([face[i][0],face[i][1],face[i][2],1])*t[i]w=[1.0,1.0,1.0,1.0]

それによって求めた境界面の式がこちら.

-1.0x+0.1y+-0.5z+0.9=0

そして,境界面と上記顔文字(ベクトル)との距離を求めると以下のようになりました.

(^_^): 1.4253932902
(^^): 0.890870806375
(^o^): 1.33630620956
(^ω^): 0.979957887012
(;_;): -14.6102812245
(>_<): -12.3831042086
(◞‸◟): -6.85970520909
(゚Д゚): -5.52339899952

ちゃんと喜と哀がプラス側とマイナス側に分かれています.喜側の距離が小さい気がしますが、喜側は目の部分が「^」しか使っていないため,特徴の学習が甘くなっているのではないかと考えられます.

それでは,未知の顔文字の感情推定.

上記文字をランダムに使って顔文字を生成.それぞれの感情を推定します.数値が正なら喜,負なら哀です.

(<‸;): -13.5412362569
(∀o^): 0.445435403187
(◟◟Д): -3.38530906422
(゚∀◟): -4.89978943506
(>Д;): -13.0958008537
(゚o>): -7.57240185419
(>Д^): -7.75057601546
(Д◟゚): -4.72161527379
(^ω∀): 0.534522483825
(<◟ω): -9.62140470885
(^Д∀): 0.7126966451

なるほど.納得できるようなできないような結果.まあこんな感じでしょう.

今回,学習によって求めた境界面と顔文字(ベクトル)との距離を求めましたが,距離が小さいということは,喜と哀の感情が曖昧,距離が大きければはっきりと感情が出ていると考えられるのでしょう.今回,(多分)上記理由で,喜側の距離があまり大きくなりませんでしたが,顔文字の定義の仕方やデータの作り方を工夫すればもっとはっきりと分かる結果になると思います.




0 件のコメント:

コメントを投稿