Python - ディープラーニング - TensorFlow と Keras
公開日:2019-10-27 更新日:2019-10-29
[Python]
1. 概要
TensorFlow(テンソルフロー) と Keras(ケラス)で論理演算のディープラーニングを行います。
TensorFlow は、google が開発している機械学習ライブラリで、
Keras は、TensorFlow などを簡単に使うためのライブラリです。
TensorFlow は、google が開発している機械学習ライブラリで、
Keras は、TensorFlow などを簡単に使うためのライブラリです。
2. 動画
3. TensorFlow と Keras で論理演算
TensorFlow と Keras を使って論理演算(XOR)をディープラーニングで学習させます。
ニューラルネットワークの構成(ユニット数と活性化関数)
実行して [0 1 1 0] と出力されれば成功です。正しく出ない場合は、何度か実行してください。
学習した重みは weights.hdf5 ファイルとして出力されます。
それを model.load_weights() で読み込むと、model.fit() を実行しなくても、分類(予測)できるようになります。
ニューラルネットワークの構成(ユニット数と活性化関数)
入力層:2 - 中間層:16(ReLU) - 出力層:2(Softmax)
import keras
from keras.layers import Dense
from keras.layers import Activation
from keras.utils.vis_utils import plot_model
from keras.utils import np_utils
import numpy as np
# 学習データ:入力
in_data = [
[0, 0],
[1, 0],
[0, 1],
[1, 1]
]
# 学習データ:正解データ
#out_data = [0, 0, 0, 1] # and
#out_data = [0, 1, 1, 1] # or
out_data = [0, 1, 1, 0] # xor
# エラーが出るので ndarray に変換する。
# エラー:ValueError: Error when checking model input: the list of Numpy arrays that you are passing to your model is not the size the model expected.
# Expected to see 1 array(s), but instead got the following list of 4 arrays:
in_data = np.array(in_data)
# 正解データを one-hot 表現への変換
# model.compile() で loss = 'sparse_categorical_crossentropy' を使う場合や、
# binary_crossentropy を使う場合は不要です。
out_data = np_utils.to_categorical(out_data, np.max(out_data) + 1)
# モデルの生成
model = keras.models.Sequential()
# 入力層:ユニット数2 - 中間層:ユニット数16
model.add(Dense(units = 16, input_dim = 2)) # units:次の層(中間層)のユニット数 input_dim:入力数
model.add(Activation('relu')) # 活性化関数(sigmoid, relu, softmax など)
# 出力層
model.add(Dense(2))
model.add(Activation('softmax')) # 活性化関数
# モデルのコンパイル
model.compile(
loss = 'categorical_crossentropy', # 損失関数:クロスエントロピー誤差
# 最適化アルゴリズム
# optimizer = 'sgd', # SGD(確率的勾配降下法)
optimizer = 'adam', # Adam
metrics = ['accuracy']) # モデルの精度の表示
# 出力層のノード数を1つにして、シグモイド関数を使う場合は以下のようにする
# この場合、上記の np_utils.to_categorical() の行をコメントにすること
#
# # 出力層
# model.add(Dense(1))
# model.add(Activation('sigmoid'))
#
# # モデルのコンパイル
# model.compile(loss='binary_crossentropy', optimizer='sgd', metrics=['accuracy'])
# モデルの画像出力(graphviz をインストールしていない場合はコメントにする)
plot_model(model, "model.png", show_shapes = True, show_layer_names = True)
# 学習
model.fit(in_data, out_data, epochs = 1000) # epochs:反復学習させる回数
# model.load_weights('weights.hdf5') # 学習済みの重みデータの読み込み。読み込む場合は fit() 不要
# 予測
# result = model.predict(in_data) # 出力層の値
result = model.predict_classes(in_data) # 出力層の値を分類に変換した値
print(result)
# 重みの保存
# 今回学習した内容をファイルで保存する
model.save_weights('weights.hdf5')
実行して [0 1 1 0] と出力されれば成功です。正しく出ない場合は、何度か実行してください。
学習した重みは weights.hdf5 ファイルとして出力されます。
それを model.load_weights() で読み込むと、model.fit() を実行しなくても、分類(予測)できるようになります。
4. 動物の分類
動物の足の数、体重、色(R,G,B) を使って動物の分類を行います。
基本的な処理は XOR の時と同じですが、学習データの各データが 0 ~ 1 の範囲になるようにスケール変換を行っています。
基本的な処理は XOR の時と同じですが、学習データの各データが 0 ~ 1 の範囲になるようにスケール変換を行っています。
import keras
from keras.layers import Dense
from keras.layers import Activation
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
data = pd.DataFrame(
[
#足の数, 体重kg, R, G, B, 種類(0:象 1:キリン 2:白熊 3:黒熊 4:犬 5:クモ 6:タコ 7:イカ 8:虫)
# 象さん
[4, 6000, 210, 217, 206, 0],
[4, 5800, 214, 213, 209, 0],
[4, 5600, 206, 217, 208, 0],
[4, 5400, 209, 214, 209, 0],
[4, 5200, 208, 210, 215, 0],
# キリンさん
[4, 840, 203, 173, 52, 1],
[4, 820, 194, 206, 49, 1],
[4, 800, 196, 182, 60, 1],
[4, 780, 181, 187, 68, 1],
[4, 760, 196, 189, 60, 1],
# 白熊さん
[4, 490, 253, 253, 253, 2],
[4, 470, 234, 235, 231, 2],
[4, 450, 241, 242, 240, 2],
[4, 430, 255, 255, 255, 2],
[4, 410, 248, 250, 248, 2],
# 黒熊さん
[4, 490, 13, 13, 13, 3],
[4, 470, 14, 15, 11, 3],
[4, 450, 11, 12, 10, 3],
[4, 430, 15, 15, 15, 3],
[4, 410, 18, 10, 18, 3],
# 犬さん
[4, 14, 193, 97, 0, 4],
[4, 12, 213, 106, 0, 4],
[4, 10, 208, 121, 4, 4],
[4, 8, 209, 153, 3, 4],
[4, 6, 252, 184, 3, 4],
# クモさん
[8, 0.01, 14, 14, 12, 5],
[8, 0.02, 12, 14, 14, 5],
[8, 0.01, 56, 57, 49, 5],
[8, 0.02, 58, 55, 48, 5],
[8, 0.01, 38, 36, 32, 5],
# タコさん
[8, 18, 222, 33, 33, 6],
[8, 16, 220, 23, 23, 6],
[8, 14, 224, 50, 50, 6],
[8, 12, 230, 50, 23, 6],
[8, 10, 232, 40, 40, 6],
# イカさん 色は白熊、体重はタコと同じにした
[10, 18, 253, 253, 253, 7],
[10, 16, 234, 235, 231, 7],
[10, 14, 241, 242, 240, 7],
[10, 12, 255, 255, 255, 7],
[10, 10, 248, 250, 248, 7],
# 虫さん クモと足の数だけ違う
[6, 0.01, 14, 14, 12, 8],
[6, 0.02, 12, 14, 14, 8],
[6, 0.01, 56, 57, 49, 8],
[6, 0.02, 58, 55, 48, 8],
[6, 0.01, 38, 36, 32, 8],
],
columns = ['legs', 'weight', 'R', 'G', 'B', 'kind']
)
df = pd.DataFrame(data)
# データから分類以外の列を取得
in_data = df.iloc[:, 0:5]
# データから分類の列を取得
out_data = df['kind']
# 正規化(各データが 0 ~ 1 の範囲になるようにスケール変換します)
scaler = MinMaxScaler()
in_data = pd.DataFrame(scaler.fit_transform(in_data))
# ndarrayに変換
in_data = np.array(in_data)
out_data = np.array(out_data)
# モデルの生成
model = keras.models.Sequential()
model.add(Dense(units = 16, input_dim = 5))
model.add(Activation('relu'))
model.add(Dense(9)) # 出力層:9種類のためユニット数は9
model.add(Activation('softmax'))
# モデルのコンパイル
model.compile(
loss = 'sparse_categorical_crossentropy',
optimizer = 'adam',
metrics = ['accuracy'])
# 学習
model.fit(in_data, out_data, epochs = 1000)
# テストデータ(学習データと微妙に変えています)
test_data = np.array(
[
# 象さん
[4, 5700, 208, 213, 209],
[4, 5500, 200, 217, 208],
[4, 5650, 206, 210, 211],
[4, 5450, 209, 212, 213],
[4, 5250, 211, 210, 210],
# キリンさん
[4, 845, 205, 176, 48 ],
[4, 815, 190, 206, 49 ],
[4, 805, 197, 181, 52 ],
[4, 785, 180, 187, 60 ],
[4, 720, 200, 189, 68 ],
# 白熊さん
[4, 495, 250, 255, 253],
[4, 475, 240, 235, 240],
[4, 455, 235, 245, 245],
[4, 435, 245, 255, 250],
[4, 400, 255, 252, 245],
# 黒熊さん
[4, 495, 14, 14, 14],
[4, 465, 11, 15, 14],
[4, 455, 10, 12, 17],
[4, 437, 13, 15, 13],
[4, 413, 15, 10, 16],
# 犬さん
[4, 12.5, 193, 100, 2],
[4, 10, 213, 107, 1],
[4, 9, 208, 118, 3],
[4, 7, 209, 163, 4],
[4, 5, 252, 174, 5],
# クモさん
[8, 0.03, 12, 12, 11],
[8, 0.01, 16, 16, 13],
[8, 0.01, 56, 55, 50],
[8, 0.01, 58, 57, 46],
[8, 0.01, 36, 36, 33],
# タコさん
[8, 17, 220, 30, 31],
[8, 15, 222, 27, 20],
[8, 13, 225, 55, 55],
[8, 11, 231, 50, 21],
[8, 9, 232, 45, 45],
# イカさん
[10, 17, 251, 250, 250],
[10, 15, 231, 240, 240],
[10, 15, 240, 245, 242],
[10, 13, 253, 255, 253],
[10, 11, 250, 250, 250],
# 虫さん
[6, 0.01, 12, 11, 12 ],
[6, 0.02, 12, 12, 14 ],
[6, 0.02, 56, 48, 49 ],
[6, 0.02, 56, 50, 50 ],
[6, 0.02, 40, 40, 40 ],
]
)
# 正規化
# 2019/10/29 fit_transform() ではなく、transform() を使うと良いとコメントで教えていただきました!
test_data = pd.DataFrame(scaler.transform(test_data))
test_data = np.array(test_data)
# 予測
result = model.predict_classes(test_data, batch_size=1)
# 予測結果の出力
print(result)
# 正解の出力(学習データとテストデータの数と並びを合わせているため、学習データの正解を出力)
print(out_data)