Kerasを使ってひらがな認識のCNNを動かしてみました。情報を取り出すのが素のTensorflow, Caffe, Darknetに比べて非常に楽でした。
ひらがな認識をkerasで動かす
意外に簡単にできました。
https://github.com/natsutan/NPU/blob/master/example/keres_cnn/keras/chihay_cnn.py
ネットワークの構築はこう。MNISTのチュートリアルそのままです。
model = Sequential() model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1], border_mode='valid', input_shape=input_shape)) model.add(Activation('relu')) model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1])) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=pool_size)) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(128)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(kana_num)) model.add(Activation('softmax'))
ネットワーク、学習結果の出力
Kerasはネットワークの情報を持ち出すのが、Kaffe, Tensorflowに比べてわかりやすい。ちなみにDarknetはさっぱりわからない。
モデルのJSON出力
to_json()を使う。
with open('output/cnn.json', 'w') as fp: json_string = model.to_json() fp.write(json_string)
改行がほしいが、プログラムで読む分は問題ない。
{"class_name": "Sequential", "config": [{"class_name": "Convolution2D", "config": {"subsample": [1, 1], "nb_filter": 32, "nb_col": 3, "trainable": true, "init": "glorot_uniform", "W_regularizer": null, "b_regularizer": null, "bias": true, "input_dtype": "float32", "W_constraint": null, "nb_row": 3, "name": "convolution2d_1", "activation": "linear", "activity_regularizer": null, "border_mode": "valid", "dim_ordering": "tf", "batch_input_shape": [null, 28, 28, 1], "b_constraint": null}}, {"class_name": "Activation", "config": {"activation": "relu", "trainable": true, "name": "activation_1"}}, {"class_name": "Convolution2D", "config": {"subsample": [1, 1], "nb_filter": 32, "nb_col": 3, "trainable": true, "init": "glorot_uniform", "W_regularizer": null, "b_regularizer": null, "W_constraint": null, "nb_row": 3, "name": "convolution2d_2", "activation": "linear", "activity_regularizer": null, "bias": true, "dim_ordering": "tf", "b_constraint": null, "border_mode": "valid"}}, {"class_name": "Activation", "config": {"activation": "relu", "trainable": true, "name": "activation_2"}}, {"class_name": "MaxPooling2D", "config": {"strides": [2, 2], "trainable": true, "name": "maxpooling2d_1", "pool_size": [2, 2], "dim_ordering": "tf", "border_mode": "valid"}}, {"class_name": "Dropout", "config": {"p": 0.25, "trainable": true, "name": "dropout_1"}}, {"class_name": "Flatten", "config": {"trainable": true, "name": "flatten_1"}}, {"class_name": "Dense", "config": {"output_dim": 128, "activation": "linear", "trainable": true, "b_regularizer": null, "init": "glorot_uniform", "W_regularizer": null, "input_dim": 4608, "b_constraint": null, "name": "dense_1", "W_constraint": null, "activity_regularizer": null, "bias": true}}, {"class_name": "Activation", "config": {"activation": "relu", "trainable": true, "name": "activation_3"}}, {"class_name": "Dropout", "config": {"p": 0.5, "trainable": true, "name": "dropout_2"}}, {"class_name": "Dense", "config": {"output_dim": 46, "activation": "linear", "trainable": true, "b_regularizer": null, "init": "glorot_uniform", "W_regularizer": null, "input_dim": 128, "b_constraint": null, "name": "dense_2", "W_constraint": null, "activity_regularizer": null, "bias": true}}, {"class_name": "Activation", "config": {"activation": "softmax", "trainable": true, "name": "activation_4"}}], "keras_version": "1.2.0"}
サマリー出力
summary()で簡単。
print(model.summary())
実行時にはこのように表示される。
____________________________________________________________________________________________________ Layer (type) Output Shape Param # Connected to ==================================================================================================== convolution2d_1 (Convolution2D) (None, 26, 26, 32) 320 convolution2d_input_1[0][0] ____________________________________________________________________________________________________ activation_1 (Activation) (None, 26, 26, 32) 0 convolution2d_1[0][0] ____________________________________________________________________________________________________ convolution2d_2 (Convolution2D) (None, 24, 24, 32) 9248 activation_1[0][0] ____________________________________________________________________________________________________ activation_2 (Activation) (None, 24, 24, 32) 0 convolution2d_2[0][0] ____________________________________________________________________________________________________ maxpooling2d_1 (MaxPooling2D) (None, 12, 12, 32) 0 activation_2[0][0] ____________________________________________________________________________________________________ dropout_1 (Dropout) (None, 12, 12, 32) 0 maxpooling2d_1[0][0] ____________________________________________________________________________________________________ flatten_1 (Flatten) (None, 4608) 0 dropout_1[0][0] ____________________________________________________________________________________________________ dense_1 (Dense) (None, 128) 589952 flatten_1[0][0] ____________________________________________________________________________________________________ activation_3 (Activation) (None, 128) 0 dense_1[0][0] ____________________________________________________________________________________________________ dropout_2 (Dropout) (None, 128) 0 activation_3[0][0] ____________________________________________________________________________________________________ dense_2 (Dense) (None, 46) 5934 dropout_2[0][0] ____________________________________________________________________________________________________ activation_4 (Activation) (None, 46) 0 dense_2[0][0] ==================================================================================================== Total params: 605,454 Trainable params: 605,454 Non-trainable params: 0
Pythonからの取得
get_config()でlistとして情報を取得できる。
config = model.get_config() for l in config: print(l)
上のサマリーよりは詳しい情報が取れる。json出力と情報量は同じっぽい。
{'class_name': 'Convolution2D', 'config': {'subsample': (1, 1), 'nb_filter': 32, 'nb_col': 3, 'trainable': True, 'init': 'glorot_uniform', 'W_regularizer': None, 'b_regularizer': None, 'bias': True, 'input_dtype': 'float32', 'W_constraint': None, 'nb_row': 3, 'name': 'convolution2d_1', 'activation': 'linear', 'activity_regularizer': None, 'border_mode': 'valid', 'dim_ordering': 'tf', 'batch_input_shape': (None, 28, 28, 1), 'b_constraint': None}} {'class_name': 'Activation', 'config': {'activation': 'relu', 'trainable': True, 'name': 'activation_1'}} {'class_name': 'Convolution2D', 'config': {'subsample': (1, 1), 'nb_filter': 32, 'nb_col': 3, 'trainable': True, 'init': 'glorot_uniform', 'W_regularizer': None, 'b_regularizer': None, 'W_constraint': None, 'nb_row': 3, 'name': 'convolution2d_2', 'activation': 'linear', 'activity_regularizer': None, 'bias': True, 'dim_ordering': 'tf', 'b_constraint': None, 'border_mode': 'valid'}} {'class_name': 'Activation', 'config': {'activation': 'relu', 'trainable': True, 'name': 'activation_2'}} {'class_name': 'MaxPooling2D', 'config': {'strides': (2, 2), 'trainable': True, 'name': 'maxpooling2d_1', 'pool_size': (2, 2), 'dim_ordering': 'tf', 'border_mode': 'valid'}} {'class_name': 'Dropout', 'config': {'p': 0.25, 'trainable': True, 'name': 'dropout_1'}} {'class_name': 'Flatten', 'config': {'trainable': True, 'name': 'flatten_1'}} {'class_name': 'Dense', 'config': {'output_dim': 128, 'activation': 'linear', 'trainable': True, 'b_regularizer': None, 'init': 'glorot_uniform', 'W_regularizer': None, 'input_dim': 4608, 'b_constraint': None, 'name': 'dense_1', 'W_constraint': None, 'activity_regularizer': None, 'bias': True}} {'class_name': 'Activation', 'config': {'activation': 'relu', 'trainable': True, 'name': 'activation_3'}} {'class_name': 'Dropout', 'config': {'p': 0.5, 'trainable': True, 'name': 'dropout_2'}} {'class_name': 'Dense', 'config': {'output_dim': 46, 'activation': 'linear', 'trainable': True, 'b_regularizer': None, 'init': 'glorot_uniform', 'W_regularizer': None, 'input_dim': 128, 'b_constraint': None, 'name': 'dense_2', 'W_constraint': None, 'activity_regularizer': None, 'bias': True}} {'class_name': 'Activation', 'config': {'activation': 'softmax', 'trainable': True, 'name': 'activation_4'}}