深層学習
Keras

Kerasによる、ものすごくシンプルな深層学習の例

More than 1 year has passed since last update.

keras+tensorflowのインストールはここに書いた通り。

そしてkerasで深層学習の勉強を始めたものの、どうもさっぱりわからないので兎に角すごくシンプルな学習データとラベルでやってみようと思ってやってみた。

で、たまたま備忘録とか日常とかというサイトを見てわかったんですが、Kerasで(てか深層学習全般なのかな?)学習時に与える結果ラベルは数値そのものではなく0と1からなるnumpy型の配列として渡し、予測した場合も同様に0と1からなるnumpy型の配列で結果ラベルが得られるらしい。深層学習やってる人には常識なんだろうな多分...

たとえば 結果ラベルが0〜3の4種類で与えられる場合、

0 は [1,0,0,0]
1 は [0,1,0,0]
2 は [0,0,1,0]
3 は [0,0,0,1]

てな感じなのかな?

で、これらからこんな感じのサンプルを考えてみた。

keras_test.py
from keras.models import Sequential
from keras.layers import Activation, Dense
from keras.utils.np_utils import to_categorical
import numpy as np

# 学習のためのデータ。
# 今回、Xは[0,0]または[1,1]の2種類。
# Yは0または1の2種類
# X:[0,0] => Y:0
# X:[1,1] => Y:1
# という対応になっている
X_list = [[0, 0], [1, 1], [0, 0], [1, 1], [1, 1], [1, 1]]
Y_list = [0, 1, 0, 1, 1, 1]

# kerasのmodelに渡す前にXをnumpyのarrayに変換する。
X = np.array(X_list)

# Yの各要素を0と1からなるリストに変換する。
# 0は0番目の要素のみ1で他は0の配列: [1,0]
# 1は1番目の要素のみ1で他は0の配列: [0,1]
# に変換される。
# すなわち
# [0, 1, 0, 1, 1, 1] => [[1,0], [0,1], [1,0], [0,1], [0,1], [0,1]]
# に変換される。 
Y = to_categorical(Y_list)

# 学習のためのモデルを作る
model = Sequential()
# 全結合層(2層->10層)
model.add(Dense(input_dim=2, output_dim=10))
# 活性化関数(ReLu関数)
model.add(Activation("relu"))
# 全結合層(10層->2層)
model.add(Dense(output_dim=2))
# 活性化関数(softmax関数)
model.add(Activation("softmax"))
# モデルをコンパイル
model.compile(loss="categorical_crossentropy", optimizer="sgd", metrics=["accuracy"])
# 学習を実行
model.fit(X, Y, nb_epoch=3000, batch_size=32)

# 学習したモデルで予測する。
# [1,1]=> 1([0,1]) 1番目のビットが立っている
# [0,0]=> 0([1,0]) 0番目のビットが立っている
# という予測になるはず...
results = model.predict_proba(np.array([[1, 1], [0, 0]]))
# 結果を表示
print("Predict:\n", results)

もはや深層学習を使う意味など全くない例ですが... もっともシンプルなところから始めないとサッパリわからないタチなので...

で、これを実行した結果の出力は

Predict:
 [[ 0.00399919  0.99600083]
 [ 0.93204987  0.06795016]]

出力された予測結果を四捨五入してintにすると

[ 0.00399919  0.99600083] は [0, 1] すなわち 1
[ 0.93204987  0.06795016] は [1, 0] すなわち 0

であり、予測の際にわたしたXのリスト

results = model.predict_proba(np.array([[1, 1], [0, 0]]))

と比較すると

[1,1] -> 1
[0,0] -> 0

となり、ちゃんと学習できたっぽいです。
うーん、わかったようなわからんような。こういう考え方であってるのですかねえ。

2/6追記:

どうも、 学習時に渡す目的関数が categorical_crossentropy の場合は上記のように0と1からなる配列である必要があるようで、 binary_crossentropy の場合はそんなことないようです。

で、書き直して見たコード。

test2.py
from keras.models import Sequential
from keras.layers import Activation, Dense
import numpy as np

# 学習のためのデータ。
# 今回、Xは[0,0]または[1,1]の2種類。
# Yは0または1の2種類
# X:[0,0] => Y:0
# X:[1,1] => Y:1
# という対応になっている
X_list = [[0, 0], [1, 1], [0, 0], [1, 1], [1, 1], [1, 1]]
Y_list = [   [0],    [1],    [0],    [1],    [1],    [1]]

# kerasのmodelに渡す前にX,Yをnumpyのarrayに変換する。
X = np.array(X_list)
Y = np.array(Y_list)

# モデルを生成する
model = Sequential()
# 全結合層(2層->10層)
model.add(Dense(input_dim=2, output_dim=10))
# 活性化関数(tanh関数)
model.add(Activation("tanh"))

# 全結合層(10層->2層)
model.add(Dense(output_dim=1))
# 活性化関数(sigmoid関数)
model.add(Activation("sigmoid"))

# モデルをコンパイル
model.compile(loss="binary_crossentropy", optimizer="sgd", metrics=["accuracy"])
# 学習を実行
model.fit(X, Y, nb_epoch=3000, batch_size=32)

# 学習したモデルで予測する。
# [1,1]=> 1
# [0,0]=> 0
# という予測になるはず...
results = model.predict_proba(np.array([[1, 1], [0, 0]]))
# 結果を表示
print("Predict:\n", results)

出力は

Epoch 3000/3000
6/6 [==============================] - 0s - loss: 0.0156 - acc: 1.0000
2/2 [==============================] - 0s
Predict:
 [[ 0.99064612]
 [ 0.02768313]]

てな感じになり、おおよそ

# [1,1]=> 1
# [0,0]=> 0

てな感じに正しく推測できているようです。