📚

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

2021/06/23に公開2

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
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Activation, Dense
from tensorflow.keras.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(10, input_dim=2))
# 活性化関数(ReLu関数)
model.add(Activation("relu"))
# 全結合層(10層->2層)
model.add(Dense(2))
# 活性化関数(softmax関数)
model.add(Activation("softmax"))
# モデルをコンパイル
model.compile(loss="categorical_crossentropy", optimizer="sgd", metrics=["accuracy"])
# 学習を実行
model.fit(X, Y, epochs=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

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

追記:

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

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

test2.py
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.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(10, input_dim=2))
# 活性化関数(tanh関数)
model.add(Activation("tanh"))

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

# モデルをコンパイル
model.compile(loss="binary_crossentropy", optimizer="sgd", metrics=["accuracy"])
# 学習を実行
model.fit(X, Y, epochs=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

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

Discussion

チャマチャマ

予測値が小数点の値となっており、その結果を四捨五入したものを最終的な予測値としていますが、直接整数値を予測する方法はご存知でしょうか。よろしくお願いします。

hiroe_orz17hiroe_orz17

この分野に詳しいわけではないのですが、機械学習による予測値は精度を高めることで正解に限りなく近づくことはあっても、完全に一致することはおそらく無いと思います。0.990646120.99999987 などになることはあるかもしれませんが...