ぱたへね

はてなダイアリーはrustの色分けができないのでこっちに来た

kerasで処理の途中の値を取り出す

俺俺DLフレームワークを作るにはKeras一択のような気がしてきました。

KerasでNNに特定のデータを入れた時に、狙った層の出力をnumpy形式で出力する方法です。やりかたはKeras FAQをみました。簡単です。
https://keras.io/ja/getting-started/faq/#_1

やってること

http://d.hatena.ne.jp/natsutan/20170212/1486862458
ここで作ったNNに一枚絵を入れて、その途中の計算結果を取り出しました。入力データはひらがなデータを入れていますが、やっていることはNNも含めてMNISTと完全に同じです。

モデルと学習結果を読み込む

学習後に保存したjsonファイルとhd5ファイルを読み込みます。ファイルの作り方はここを参照。
http://d.hatena.ne.jp/natsutan/20170212/1486862458

json_string = open('output/cnn.json', 'r').read()
model = model_from_json(json_string)
model.load_weights('output/cnn.h5')
画像の読み込み

「い」が入ったデータを読み込みます。行列の形を合わせる必要があります。255から引いている所はネガポジ反転なので、データがすでに直接入力できる形式になっていれば不要です。

# load image
images = np.empty([0, 28, 28], np.float32)
img_ori = Image.open('data/I.png')
img_gray = ImageOps.grayscale(img_ori)

img_ary = np.asarray(img_gray)
img_ary = 255 - img_ary
images = np.append(images, [img_ary], axis=0)

images = images.reshape(1, 28, 28, 1)
一枚の識別

model.predictで一枚だけ識別します。

ret = model.predict(images, 1, 1)
print(ret)

実行結果

1/1 [==============================] - 0s
[[  9.66260362e-18   1.00000000e+00   1.46393750e-16   3.83880911e-21
    1.73906418e-14   2.77851445e-13   2.60705761e-21   2.42816259e-22
    9.78005010e-10   9.94229803e-16   2.92022889e-13   2.50225903e-12
    1.87606130e-20   9.82728684e-17   4.47857970e-22   6.36410264e-16
    2.89718408e-16   9.22273868e-15   1.46329236e-20   1.10161611e-16
    3.02622735e-19   4.96133791e-18   4.64741527e-13   2.02620950e-12
    5.23028010e-11   2.72302085e-14   3.31416961e-09   8.62797342e-16
    3.77434917e-15   3.23395878e-13   8.63702926e-16   1.50429401e-18
    1.54558563e-13   6.33530894e-10   1.18054563e-24   1.71215462e-14
    1.62872005e-12   8.14889678e-20   4.88564665e-19   8.62093701e-15
    4.40518906e-17   6.88677597e-16   4.34340205e-16   1.31322590e-17
    4.82810310e-18   1.39269949e-18]]

入力した文字が「い」に対して、softamx出力の2番目が最大値になっているので識別できてますね。

中間層の出力を取り出す。

https://keras.io/ja/getting-started/faq/#_1 を参考に。
K.functionを使って、特定の層(例えばConvolution2D)の入出力を取り出す関数を作ります。その関数に対して、入力データを指定すると、それを処理した出力を受け取ることができます。numpy形式なので、そのままファイルに落とせます。

# output
get_1st_layer_output = K.function([model.layers[0].input],
                                  [model.layers[0].output])
layer_output = get_1st_layer_output([images,])
print(layer_output[0].shape)
np.save('output/convolution2d_out.npy', layer_output[0], allow_pickle=False)

ソースコード

import numpy as np
from PIL import Image
from PIL import ImageOps
from keras.models import model_from_json
from keras import backend as K

json_string = open('output/cnn.json', 'r').read()
model = model_from_json(json_string)
model.load_weights('output/cnn.h5')

# load image
images = np.empty([0, 28, 28], np.float32)
img_ori = Image.open('data/I.png')
img_gray = ImageOps.grayscale(img_ori)

img_ary = np.asarray(img_gray)
img_ary = 255 - img_ary
images = np.append(images, [img_ary], axis=0)

images = images.reshape(1, 28, 28, 1)

# predict
ret = model.predict(images, 1, 1)
print(ret)

# output
get_1st_layer_output = K.function([model.layers[0].input],
                                  [model.layers[0].output])
layer_output = get_1st_layer_output([images,])
print(layer_output[0].shape)
np.save('output/convolution2d_out.npy', layer_output[0], allow_pickle=False)