chainerで多層パーセプトロンを作って、3桁の足し算をさせてみた

今回は人工知能のお勉強として、Tensorflowからchainerに戻って、多層パーセプトロンを作る。
で、そいつに3桁の足し算をさせてみようと。

でもって、お勉強した後には問題を出して、解けるかどうかチャレンジしてみようと。

使用環境
ubuntu14.04
python2.7
chainer 1.17.0

まず、インポートは定番もので下記を参照。
モデル保存用にserializersもインポート。


import numpy as np
import chainer.functions as F
import chainer.links as L
from chainer import Variable, optimizers, Chain, serializers


xと教師ラベルのtには下記を代入する。


x=Variable(np.array([[422,232],[165,499],[777,305],[480,392]],dtype=np.float32))
t=Variable(np.array([[654],[664],[1082],[872]],dtype=np.float32))


今回は多層パーセプトロンを作るのだが、多層といってもまず2層で実行してみる。


class TasouModel(Chain):
    def __init__(self):
        super(TasouModel, self).__init__(
            l1=L.Linear(2,3),
            l2=L.Linear(3,1),
       
        )
        


    def __call__(self,x):
        h = self.l1(x)
        h2=self.l2(h)
        return h2



で、モデルを読み込んで、
最適化はAdamを採用。


model = TasouModel()
optimizer = optimizers.Adam()
optimizer.setup(model)



5000回学習させて、
誤差を出して、逆伝播。
パラメータ値を更新して、
誤差とyのデータを確認する。

ちなみに、誤差が減っていく様子を眺めるのは心地いい。


for i in range(5000):
    model.zerograds()
    y=model(x)
    loss=F.mean_squared_error(y, t)
    loss.backward()
    optimizer.update()
    
    print "loss",loss.data

print "y.data",y.data



ここまでで問題無ければ、最後にテストで正解を出せるか確認する。


xt=Variable(np.array([[639,256]],dtype=np.float32))
yt=model(xt)

print "yt.data",yt.data


で、実行した結果がこれ。


loss 0.00546533148736
loss 0.00546533148736
loss 0.00546533148736
loss 0.00546533148736
loss 0.00546533148736
y.data [[ 654.13433838]
[ 663.99200439]
[ 1081.94458008]
[ 871.97393799]]
yt.data [[ 895.03637695]]

y.dataがお勉強させていく過程での計算結果。
lossの値が減っているので、当然y.dataも正解になる。

yt.dataがお勉強した数字とは別の値でテストした結果。
出題は639と253を足せってことなので、895は正解。

コードを実際に動かしてみて、正解値が出なければ、もっとお勉強させてみましょう。
10000回とか30000回とか、お好みでどうぞ。

例、下記のカッコの中を変えればいい。
for i in range(10000): //10000回の時

さて、こんな感じで多層パーセプトロンのお勉強をしてみた。
多層パーセプトロン=深層学習(ディープラーニング)なので、その仕組みの基礎がなんとなく理解できたでしょう。

後は、この層をもっと深く重ねていけば、まさしく深層になっていくってこと。

人間が何かを学ぶには、まずシンプルにすれば良し。
全てを削ぎとって、簡潔なコードを学習し、少しずつコードを増やしていく。

深層学習(ディープラーニング)はこのことを教えてくれるんですなあ。

TDパソコンプログラミング教室へ

Tensorflowに画像認識させてみる

以前、chainerに画像認識させてみたのだが、今回はgoogleの誇るディープラーニングのフレームワーク、Tensorflowに画像認識させてみようと。

Tensorflowのgit cloneで、tensorflow/tensorflow/models/image/imagenetフォルダに中に、classify_image.pyという画像認識コードがある。
これをpythonで実行させると、デフォルトで用意されたパンダ画像を自動で認識してくれる。

ちなみに、ここで採用されているInception-v3ってやつは、エラー率3.4%だそうです。人間のエラー率が5%程度らしいので、人間より認識率は高いとのこと。すごいですねえ。

それでは、そのすんごい認識システム。
まずはやってみましょう。

$ cd tensorflow/tensorflow/models/image/imagenet
$ python classify_image.py

すると初回のみダウンロードされ自動実行される。
giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca (score = 0.89233)
indri, indris, Indri indri, Indri brevicaudatus (score = 0.00859)
lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens (score = 0.00264)
custard apple (score = 0.00141)
earthstar (score = 0.00107)

パンダの確率が89%と出た。

これだけではつまらないので、こちらで用意した画像を認識させてみよう。
以前と同じライオンをまず。

$ python classify_image.py –image_file raion_osu.jpg

すると
lion, king of beasts, Panthera leo (score = 0.92273)
Arabian camel, dromedary, Camelus dromedarius (score = 0.00058)
cheetah, chetah, Acinonyx jubatus (score = 0.00053)
macaque (score = 0.00047)
pencil box, pencil case (score = 0.00044)

ライオンである確率92%。
ペンシルボックスが0.00044%。
そうですか。

以前、何かに間違えたこちらの写真。
馬なのだが、これをどうみる、テンソル君。

$ python classify_image.py –image_file uma2.jpg

llama (score = 0.93735)
ram, tup (score = 0.00507)
Newfoundland, Newfoundland dog (score = 0.00196)
ostrich, Struthio camelus (score = 0.00139)
Border collie (score = 0.00133)

llamaである確率が93%。
llamaってなんぞや。

検索したらこんなのが出てきました。

色は違うが見た目は似てますなあ。
間違えるのも無理はない。

ちなみに、イラストなんかは認識できるのだろうか。
これとか。

やってみよう。

$ python classify_image.py –image_file pico.jpg

stole (score = 0.07498)
wig (score = 0.07489)
suit, suit of clothes (score = 0.05217)
ear, spike, capitulum (score = 0.05153)
corn (score = 0.05042)

軒並み10%を切っている。ちょい自信が無いね、テンソル君。
ストールが7%。
人間というより、着てる服に目がいくのね。

じゃあ、こいつはどうだ。

by おむレツ さん、フリー画像ありがとう。

$ python classify_image.py –image_file irasuto1.jpg

comic book (score = 0.77033)
mask (score = 0.05580)
lampshade, lamp shade (score = 0.00679)
crash helmet (score = 0.00420)
jack-o’-lantern (score = 0.00317)

コミックブックが77%。
なるほど、わかってるのね。

総じて感想だが、chainerよりは解析が早いですね。
さすが、天下のgoogleさんが作っただけのことはある。
こんなすごいシステムが自由に使えるなんて。
ディープラーニング製作チームは、各社とも太っ腹ですなあ。
感謝です。

TDパソコンプログラミング教室TOPへ

chainerに足し算のお勉強をさせてみた

今回は、深層学習 ディープラーニングのフレームワークchainerに足し算のお勉強をさせてみた。
で、勉強した後にテストをして正解が取れるかどうか確認してみようと。

環境
ubuntu 14.04
python 2.7系
chainer 1.17.0
CPUモード

なるべくわかりやすいように、コードは最小限で。
クラス名などはローマ字読みにして、さも付けました感を強調してみた。
コードが短い上に計算も単純なので、CPUモードで充分動かせる。
GPUを導入していないメモリ2G程度のショボPCでも使えるので、ちょこっと動かしたい方にもお勧めだ。

まずインポートは概ね下記が定番のようなので、きっちりと忘れずに。
後日、モデルを保存するので、serializersもインポートしておく。

import numpy as np
import chainer.functions as F
import chainer.links as L
from chainer import Variable, optimizers, Chain, serializers

で、お勉強の足し算がこれ。
xに入力した2つのデータを足すと、教師ラベルであるtの答えになる。
例えば、xの[0,1]を足すとtの[1]が答えになる。

x=Variable(np.array([[0,1],[1,2],[2,3],[3,4]],dtype=np.float32))
t=Variable(np.array([[1],[3],[5],[7]],dtype=np.float32))

ここがChainを継承したオリジナルのクラス、TasouModel()の所。
書き方も概ね定番なので、
initで初期化、今回は2入力の1出力なので、L.Linear(2,1)とする。
callには、やらせたいコードを記入。ここでは1層目にxを渡してリターンするだけ。

class TasouModel(Chain):
    def __init__(self):
        super(TasouModel, self).__init__(
            
            l1=L.Linear(2,1),
        )


    def __call__(self,x):
        h = self.l1(x)
        return h

下記も定番。最適化にはSGDを採用した。
ちなみに、桁数を増やす際はAdamにした方が上手くいく。

model = TasouModel()
optimizer = optimizers.SGD()
#optimizer = optimizers.Adam()
optimizer.setup(model)

下記がお勉強させている所。とりあえず100回ループでやってみる。
model.zerograds()で初期化して、
y=model(x) でモデルにxを与える。

loss=F.mean_squared_error(y, t) でyとtの誤差を出して
loss.backward() で逆伝播
optimizer.update() でパラメータ値を更新する

print “loss”,loss.data で誤差が減っていく様子を眺めて

print “y.data”,y.data でとりあえず計算が合っているかチェックする

for i in range(100):
    model.zerograds()
    y=model(x)
    loss=F.mean_squared_error(y, t)
    loss.backward()
    optimizer.update()
    
    print "loss",loss.data


print "y.data",y.data


こんな感じで実行した結果がこれ。


loss 0.000531732861418
loss 0.00052492209943
loss 0.000518201501109
loss 0.000511576014105
loss 0.000505022529978
y.data [[ 0.96305263]
[ 2.98112226]
[ 4.99919176]
[ 7.01726151]]

lossのところの誤差が徐々に減っていくのがわかる。
で、yの値がほぼ1、3、5、7であるのがわかる。

100ループでこれなので、1000ループも回せばもっと正解に近づくはず。

じゃあ、やってみましょう。1000ループはこちら。


loss 5.18807041772e-07
loss 5.12161477673e-07
loss 5.05823720687e-07

y.data [[ 1.0011692 ]
[ 3.00059748]
[ 5.00002575]
[ 6.99945354]]

yの値がぱっちり正解。
lossの誤差も0.000000〜と、ほとんど0なのでこれもOK.

それでは最後にテストをしてみましょう。
chainer君、がんばってちょーだいな。

問題はこちら。
5と6、7と8、9と10をそれぞれ足して、正解が出せるかな。
下記のコードを最後に追加する。


xt=Variable(np.array([[5,6],[7,8],[9,10]],dtype=np.float32))
yt=model(xt)

print "yt.data",yt.data

実行した結果がこれ。

yt.data [[ 11.00018406]
[ 15.00030804]
[ 19.00043106]]

11、15、19と、合ってますね。大正解です。

ん〜ん。マシンとはいえ、勉強させて正解が出た暁には、我が子のようにかわいいと思うから不思議だ。

えっ、これの何がすごいのかって?
まあ単純にchainer君に
1+2
を渡せば3を返してくれる。

しかーし。
今回のコードはどこにも「足せ」とは書いていない。
「+」記号も無し。
私は数字と答えを渡したのみだ。
あとはchainer君が勝手に正解を見つけだしたってこと。

ここがすごいんですねえ。
人間だって数字と答えだけで、計算方法わかりまっかってことだ。

さてさて、
今回はわかりやすさを念頭においたので、1層でのお勉強となったが、これを何層にも重ねていくと深層学習 ディープラーニングになる。

次回は、複数層重ねたやつを書きますかな。

chainerでchainer-goghとやらを実行してみた

chainerで画像変換のアルゴリズム、chainer-goghとやらがあるのを知った。
早速試してみる。

これはA画像をB画像風にスタイル変換するプログラムらしい。

こいつと
cat

こいつを入力すると
style_0

こんな画像に変換してくれる。

im0

なんともお見事だ。アート系にはたまらんプログラムではないか。

では、やってみよう。

まず、
https://github.com/mattya/chainer-gogh

から右上の緑のボタン「clone or download」をクリック。
「dowaload zip」をクリックして、プログラムを自分のPCに落とす。

で、そいつを実行場所で解凍。
実行場所はpythonが実行できるディレクトリィ(フォルダ)ならどこでも可。

ubuntuならunzipコマンドで一発解凍だ。
解凍すると「chainer-gogh-master」というディレクトリィができる。

で、そこへ入る。以下、ubuntuコマンド。
>cd chainer-gogh-master

lsコマンドで中身を確認する。

>ls
LICENSE chainer-gogh-multi.py models.py
README.md chainer-gogh.py sample_images

「sample_images」はディレクトリィで、この中に先ほどのサンプル画像が入っている。

どれを使うのかはお好み次第。
取り合えず、基本からという事で、今回はネット上から落としてきたフリー画像のumaEks.pngとstyle_0.pngを試してみることにした。

umaEks.png
umaeks2

style_0.png
style_0

では、実行してみる。ちなみに下記はCPUモードでの実行コマンド。
>python chainer-gogh.py -i umaEks.png -s style_0.png -o test01.png -g -1

各自で用意した画像を変換する際は、umaEks.pngの所に元画像、style_0.pngの所に〜風に変えたい画像を入れる。
test01.pngの所は変換後の画像が置かれるディレクトリィ名。

実行時にエラーが出る場合がある。
No such file or directory: ‘nin_imagenet.caffemodel’

この場合は、nin_imagenet.caffemodelをネットから落としてきて、実行ファイルと同じ場所に置けばいいようだ。

さて今現在、コマンドを実行してからほぼ1日程度時間が経過しているが、終わる気配は全くない。

ただ、test01.pngディレクトリィ(フォルダ)の中に「im_00000.png〜」という名で画像ができているので、途中結果を見ながら楽しめる。

ちなみにim_00000.png〜im_00600.pngでの画像のキャプチャはこちら。
umaの影も形も無いが、何となくこれから現れてきそうな気がしないでもない。

im_00000.png
im_00000

im_00200.png
im_00200

im_06000.png
im_00600

さてさて、いつ終わることやら。
やっぱGPUも検討しないとかなあ。

chainerでcaffeモデルを使ってライオンの画像認識をしてみた

ディープラーニングのフレームワークであるchainerを使って、
ライオンの画像認識テストをしてみた。

chainerはcaffeで学習したモデルを読み込める。
ディープラーニングは学習フェーズに時間がかかるし、マシンパワーも要る。
誰かが一度学習したモデルは再利用した方が効率がいい。
caffeにはそういった学習済みのモデルがあるのだが、chainerには無いようだ。
しかし、chainerはcaffeの学習モデルを読み込める。
さすればこれを利用しない手はない。

実装方法は専門サイトをあたって欲しい。
「chainer caffeモデル」等で検索すれば出てくる。

さて、このモデルもいろいろあるようだが、
今回は
bvlc_googlenet.caffemodel
とやらを使ってみる。

これは物体画像識別モデルらしく、画像を与えると1000種類のラベルから答えを選んで確率で提示してくれるようだ。

では、早速トライしてみよう。

まずは画像認識に使うフリー画像をネットより落とす。
動物はいろいろあるのだが、やはり百獣の王ライオンを落とした方が
モチベーションも上がるだろうと勝手に解釈。

いろんなライオン画像を落としてみた。
で、これらの画像を見事に当てることができるのかを実験する。

まずは通常の定番、オスのたてがみライオン。
raion_osu
lion, king of beasts, Panthera leo 0.999993
endTime:141.292915821[sec]

読み方は何となくわかると思う。
99パーセントの確率でライオンだと。
2行目は解析タイムで141秒。

続いて、メスライオン。
raion_mesu
lion, king of beasts, Panthera leo 0.875156
endTime:136.742625952[sec]

メスがいっぱいでどうだ。
raion_mesu_ipai
lion, king of beasts, Panthera leo 1.0
endTime:135.995461941[sec]

メスが寝ているのはどうだ。
raion_mesu_neru
lion, king of beasts, Panthera leo 0.993945
endTime:143.018036842[sec]

オスとメスが同時だと。
raion_osu_mesu
lion, king of beasts, Panthera leo 0.999996
endTime:145.427984953[sec]

じゃあ、熊だったら。(ライオンじゃないのか)
kuma
brown bear, bruin, Ursus arctos 0.998838
endTime:137.810104847[sec]

バッチリ、正解ですね。

馬ならどうだ。
uma
sorrel 0.30917
endTime:139.737962961[sec]

栗毛の馬。正解!

この馬はわかるかchainer!
uma2
Afghan hound, Afghan 0.295077
endTime:142.296715021[sec]

おおーっと。
初めて間違えたぞ。
アフガンハウンドって何なんだ。
検索したらこんな犬だった。
afgan_dog

こりゃあ、人間でも酔っ払ってたら間違えまっせ。
29パーセントの確率。ちょっと自信が無かったのね。

ならこいつはどうだ。
と、思いきや、
画像を載せようとしたら、あまりの重さに蹴られてしまった。
仕方ないので、スマホで撮った画像をアップ。
umagotya
grocery store, grocery, food market, market 0.15934
endTime:138.949405909[sec]

食料品店。確率15パー。
まあ、見方によっては、ごちゃごちゃ感がそう見えなくもない。

最後はこれだ。人間との共存。
uma_hito
sorrel 0.620618
endTime:143.301738024[sec]

よしよし。馬とわかったのね。

やはり、ディープラーニングはすごい。
ばっちり正解を導き出している。
学習モデルさえあれば、推論フェーズは時間もかからないし比較的簡単にできる。

chainer、caffe、tensorflow等々のフレームワークを使えば、
コードの意味がわからなくても、簡単に人工知能が利用できる。

どのフレームワークが主導権を握るのだろう。
ここを勝ち取った所が、第二のマイクロソフトになるんだろうなあ。

ミニバッチ学習をやってみる

ビッグデータてのはすんごい量のデータってことですよね。
それらを全て読み込んでAIに学習させるのはどうかと。

じゃあ、あるビッグデータからランダムに数字を選び出し、そのデータを学習させた方が現実的かと。

じゃあ、やってみましょう。

取りあえず数万行とかのデータだとわかりづらいので、簡単な例でやってみよう。

まず行列を生成。
>>>import numpy as np
>>>c=np.random.rand(100,5) #100×5の行列

次に0から99のランダムな整数値を5個生成。
>>>num=np.random.randint(0,99,5)
>>>num
array([67, 70, 77, 57, 50])

最後に、cに入ってる100×5の行列の中からランダムに5行取り出す。
>>>c[num]
array([[ 0.46056215, 0.02724345, 0.04751872, 0.0601672 , 0.88581067],
[ 0.89011215, 0.5425002 , 0.33186499, 0.65377442, 0.58409292],
[ 0.35687939, 0.53664274, 0.87741458, 0.50807996, 0.93492165],
[ 0.04181579, 0.82105758, 0.44125541, 0.47778949, 0.53684184],
[ 0.5850871 , 0.61915054, 0.57150464, 0.48524271, 0.74511142]])

こんな感じでしょうか。
あとは数字を大きくすれば、何万行、何千万行とかにも対応できますね。

統計学だって滅多に全数調査しませんから。
ミニバッチ、使えそうですね。

交差エントロピー誤差関数をいじってみる

損失関数として使われる交差エントロピー誤差をpython3で表してみよう。

まず数式はこちら。
entro1

(ちなみに、画像はスマホのLINE BRUSHってやつで書いている。なので、ちょいと見づらいのはご愛嬌。)

tkは正解ラベル。
ykはニューラルネットワークの出力。

python3コードはこちら。


def entroErr(y,t):
    dlt=1e-8
    return -np.sum(t * np.log(y + dlt))

では、実際に動かしてみる。

まず、yに値を入れる。
値は適当だが、左から3番目を一番大きい値に設定。
>>>y=[0.1,0.15,0.5,0.1,0.15]

お次はtの正解ラベルに値を入れる。
ちなみに、one-hot表現ってやつ。
この場合は左から3番目が正解。
>>>t=[0,0,1,0,0]

で、上記のpythonコードを試してみる。
pythonインタプリタで上記コードを入力。
インデントは要チェック。

>>> def entroErr(y,t):
… dlt=1e-8
… return -np.sum(t * np.log(y + dlt))

先ほどのy、tを引数にentroErr関数を試す。
>>> entroErr(np.array(y),np.array(t))
0.69314716055994541

これだけだと比較のしようがないので、yの値を変更してみる。

>>> y=[0.1,0.5,0.15,0.1,0.15]
>>> y
y=[0.1,0.5,0.15,0.1,0.15]

で、もう一度実行。
>>> entroErr(np.array(y),np.array(t))
1.8971199182192169

正解時の結果
0.69314716055994541

不正解時の結果
1.8971199182192169

てことは、正解時の方が損失関数の値が小さいので、
正しく動いているってことですね。

この損失関数の値をできるだけ小さくする(その時の重みパラメタを更新)のが、ディープラーニングの学習目標でもあるので、行数は短くても結構大事なコードってことですね。

pickleで、データを塩漬けにしてみる

mnistとかの膨大なデータを読み込んだ際に、pythonのpickleっていう機能を使えば便利。

大量のデータをpickleファイルで保存して、必要な時に瞬時に取り出せる。

では、やってみよう。

まず書き込みのためのpython3コードはこちら。

import numpy as np #乱数生成用。pickleだけなら要らない
import pickle

data001 = np.random.rand(5) #data001に乱数を5個入れる
with open('data.pkl', 'wb') as f: #dataをpklファイルで保存
    pickle.dump(data001, f)

ちなみに変数data001の中には何が入っているのか確認してみる。

>>>data001
#array([ 0.76262918, 0.37437904, 0.66633502, 0.31200376, 0.14175648])

お次は保存したデータを取り出してみよう。
取り出したデータは、名前の違う変数data002へ入れる。


with open('data.pkl', 'rb') as f:
... data002 = pickle.load(f)

取り出したデータを表示してみる。

>>>data002
#array([ 0.76262918, 0.37437904, 0.66633502, 0.31200376, 0.14175648])

これで読み込みの作業時間が短縮されますね。

ディープラーニングは何を見てるのか

画像認識のディープラーニングによく使われる「畳込みニューラルネットワーク」ってのがある。

こいつは一体何を見て物体の認識をしているのだろうか。

ディープラーニングてくらいだから、階層が何層にも重ねられている。
まず、1層目は何をみているのだろうか。

詳しくは下記のサイトへ
マサチューセッツ工科大学(MIT)
http://vision03.csail.mit.edu/cnn_art/index.html#v_single

答えは、エッジや局所的な塊(ブロブ)を見ているようだ。

こんな感じで全8層の畳込みニューラルネットワークの各フィルターの特徴を見てみると、次のような反応をしているようだ。

1層目
エッジや局所的な塊(ブロブ)

3層目
物体のテクスチャ

5層目
物体のパーツ

8層目
物体のクラス

このように階層が深くなるにつれて、ぼやけたイメージから物体そのものへと認識が変わっていく様子がわかる。

特に5層目は車の画像は車っぽく見えてるし、犬の画像も何となく特徴をとらえていそう。

しかし、最後の出力層になってくると、何だか訳がわかりませんがな。
これで物体を認識してるってのがすごい。

極端に抽象化しちゃってるんかな。

chainerでmnistを試してみる

chainerをubuntu14.04にインストール。
手描き文字認識でよく使われるmnistを試してみることにした。

ちなみにchainerってのは日本製のディープラーニングのフレームワーク。
google製のTensorFlowと同じようなくくりです。

さて、このchainerをcpuモードで実行。
ターゲットはよく出てくるmnist。
以下、実行結果ですが、やっぱcpuモードだと時間がかかり過ぎ。
gpu使わないとダメですかねえ。
正確な時間計っとけばよかったかなあ。

chainer01