Keras - Keras のファイルの形式について
概要
Keras で保存した重みファイルから直接重みを読み出す方法について
試した環境
- Keras 2
MNIST のクラス分類器を CNN で作成する。
サンプルの重みファイルを作成するために、MNIST の分類問題を解くためのモデルを作成し、学習を行う。
MNIST データセットを読み込み、前処理を行う。
import keras from keras.datasets import mnist from keras.models import Sequential from keras.layers import Conv2D, Dense, Dropout, Flatten, MaxPooling2D from keras import backend as K import numpy as np batch_size = 128 num_classes = 10 epochs = 12 # MNIST データセットを読み込む。 (x_train, y_train), (x_test, y_test) = mnist.load_data() # 画像の前処理を行う。 img_rows, img_cols = 28, 28 # ネットワークの入力サイズ x_train = x_train[...,np.newaxis].astype('float32') / 255. x_test = x_test[...,np.newaxis].astype('float32') / 255. # ラベルを one-hot 表現にする。 y_train = keras.utils.to_categorical(y_train, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes)
モデルを作成する。
# モデルを作成する。 model = Sequential() model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(img_rows, img_cols, 1))) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D()) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(num_classes, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adadelta', metrics=['accuracy'])
モデル構成を表示する。
model.summary()
Layer (type) Output Shape Param # ================================================================= conv2d_1 (Conv2D) (None, 26, 26, 32) 320 _________________________________________________________________ conv2d_2 (Conv2D) (None, 24, 24, 64) 18496 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 12, 12, 64) 0 _________________________________________________________________ dropout_1 (Dropout) (None, 12, 12, 64) 0 _________________________________________________________________ flatten_1 (Flatten) (None, 9216) 0 _________________________________________________________________ dense_1 (Dense) (None, 128) 1179776 _________________________________________________________________ dropout_2 (Dropout) (None, 128) 0 _________________________________________________________________ dense_2 (Dense) (None, 10) 1290 ================================================================= Total params: 1,199,882 Trainable params: 1,199,882 Non-trainable params: 0
モデルの学習を行う。
# 学習する。 model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test, y_test)) score = model.evaluate(x_test, y_test, verbose=0) print('Test loss:', score[0]) print('Test accuracy:', score[1])
save_weights() で保存した場合
save_weights() ではモデルの重みのみを保存できる。
これには、モデル構成等の情報は含まれない。
# モデルを保存する。 weights_path = 'mnist_classifier.h5' model.save_weights(save_path)
HDF5 ファイルの中身を表示する。
HDF5 ファイルはツリー構造になっているので、可視化する。
import h5py def traverse(node, depth): def indent(depth): # 階層に応じて、インデントする。 for i in range(depth): print(' ', end='') indent(depth) if isinstance(node, h5py.File): print('File key:{}'.format(node.name)) elif isinstance(node, h5py.Group): print('Group key:{}'.format(node.name)) else: print('Dataset key:{}, type: {}, shape: {}'.format( node.name, node.dtype, node.shape)) # attributes for key, value in node.attrs.items(): indent(depth) print('attribute key: {}, value: {}'.format(key, value)) # Traverse children if not isinstance(node, h5py.Dataset): for key, value in node.items(): traverse(value, depth + 1) h5file = h5py.File(weights_path, 'r') traverse(h5file, 0)
File key:/ attribute key: layer_names, value: [b'conv2d_1' b'conv2d_2' b'max_pooling2d_1' b'dropout_1' b'flatten_1' b'dense_1' b'dropout_2' b'dense_2'] attribute key: backend, value: b'tensorflow' attribute key: keras_version, value: b'2.1.2' Group key:/conv2d_1 attribute key: weight_names, value: [b'conv2d_1/kernel:0' b'conv2d_1/bias:0'] Group key:/conv2d_1/conv2d_1 Dataset key:/conv2d_1/conv2d_1/bias:0, type: float32, shape: (32,) Dataset key:/conv2d_1/conv2d_1/kernel:0, type: float32, shape: (3, 3, 1, 32) Group key:/conv2d_2 attribute key: weight_names, value: [b'conv2d_2/kernel:0' b'conv2d_2/bias:0'] Group key:/conv2d_2/conv2d_2 Dataset key:/conv2d_2/conv2d_2/bias:0, type: float32, shape: (64,) Dataset key:/conv2d_2/conv2d_2/kernel:0, type: float32, shape: (3, 3, 32, 64) Group key:/dense_1 attribute key: weight_names, value: [b'dense_1/kernel:0' b'dense_1/bias:0'] Group key:/dense_1/dense_1 Dataset key:/dense_1/dense_1/bias:0, type: float32, shape: (128,) Dataset key:/dense_1/dense_1/kernel:0, type: float32, shape: (9216, 128) Group key:/dense_2 attribute key: weight_names, value: [b'dense_2/kernel:0' b'dense_2/bias:0'] Group key:/dense_2/dense_2 Dataset key:/dense_2/dense_2/bias:0, type: float32, shape: (10,) Dataset key:/dense_2/dense_2/kernel:0, type: float32, shape: (128, 10) Group key:/dropout_1 attribute key: weight_names, value: [] Group key:/dropout_2 attribute key: weight_names, value: [] Group key:/flatten_1 attribute key: weight_names, value: [] Group key:/max_pooling2d_1 attribute key: weight_names, value: []
ルート以下にモデルを構成する各層の重みを内包する Gruop ノードが属している。
畳み込み層 conv2d_1 のカーネル、バイアスの値は以下のようにして取り出せる。
conv1_node = h5file['/conv2d_1/conv2d_1'] # conv2d_1 の Group ノード kernel = conv1_node['kernel:0'].value print(type(kernel), kernel.shape) bias = conv1_node['bias:0'].value print(type(bias), bias.shape)
<class 'numpy.ndarray'> (3, 3, 1, 32) <class 'numpy.ndarray'> (32,)
save() で保存した場合
save() ではモデルの構造、重み、学習の設定、optimizer の状態が含まれる。
# モデルを保存する。 model_path = 'mnist_classifier_model.h5' model.save(model_path) # HDF5 ファイルを読み込む。 h5file = h5py.File(model_path, 'r') traverse(h5file, 0)
File key:/ attribute key: keras_version, value: b'2.1.2' attribute key: backend, value: b'tensorflow' attribute key: model_config, value: b'{"class_name": "Sequential", "config": [{"class_name": "Conv2D", "config": {"data_format": "channels_last", "bias_initializer": {"class_name": "Zeros", "config": {}}, "strides": [1, 1], "use_bias": true, "dilation_rate": [1, 1], "batch_input_shape": [null, 28, 28, 1], "kernel_constraint": null, "kernel_size": [3, 3], "bias_regularizer": null, "activity_regularizer": null, "kernel_regularizer": null, "name": "conv2d_1", "dtype": "float32", "filters": 32, "bias_constraint": null, "activation": "relu", "padding": "valid", "kernel_initializer": {"class_name": "VarianceScaling", "config": {"scale": 1.0, "distribution": "uniform", "seed": null, "mode": "fan_avg"}}, "trainable": true}}, {"class_name": "Conv2D", "config": {"data_format": "channels_last", "bias_initializer": {"class_name": "Zeros", "config": {}}, "strides": [1, 1], "use_bias": true, "dilation_rate": [1, 1], "kernel_constraint": null, "kernel_size": [3, 3], "bias_regularizer": null, "activity_regularizer": null, "kernel_regularizer": null, "name": "conv2d_2", "filters": 64, "bias_constraint": null, "activation": "relu", "padding": "valid", "kernel_initializer": {"class_name": "VarianceScaling", "config": {"scale": 1.0, "distribution": "uniform", "seed": null, "mode": "fan_avg"}}, "trainable": true}}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_1", "data_format": "channels_last", "strides": [2, 2], "pool_size": [2, 2], "padding": "valid", "trainable": true}}, {"class_name": "Dropout", "config": {"name": "dropout_1", "rate": 0.25, "noise_shape": null, "trainable": true, "seed": null}}, {"class_name": "Flatten", "config": {"name": "flatten_1", "trainable": true}}, {"class_name": "Dense", "config": {"activity_regularizer": null, "use_bias": true, "kernel_constraint": null, "bias_regularizer": null, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "name": "dense_1", "units": 128, "bias_constraint": null, "activation": "relu", "kernel_initializer": {"class_name": "VarianceScaling", "config": {"scale": 1.0, "distribution": "uniform", "seed": null, "mode": "fan_avg"}}, "trainable": true}}, {"class_name": "Dropout", "config": {"name": "dropout_2", "rate": 0.5, "noise_shape": null, "trainable": true, "seed": null}}, {"class_name": "Dense", "config": {"activity_regularizer": null, "use_bias": true, "kernel_constraint": null, "bias_regularizer": null, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "name": "dense_2", "units": 10, "bias_constraint": null, "activation": "softmax", "kernel_initializer": {"class_name": "VarianceScaling", "config": {"scale": 1.0, "distribution": "uniform", "seed": null, "mode": "fan_avg"}}, "trainable": true}}]}' attribute key: training_config, value: b'{"sample_weight_mode": null, "metrics": ["accuracy"], "loss_weights": null, "optimizer_config": {"class_name": "Adadelta", "config": {"epsilon": 1e-08, "rho": 0.95, "decay": 0.0, "lr": 1.0}}, "loss": "categorical_crossentropy"}' Group key:/model_weights attribute key: layer_names, value: [b'conv2d_1' b'conv2d_2' b'max_pooling2d_1' b'dropout_1' b'flatten_1' b'dense_1' b'dropout_2' b'dense_2'] attribute key: backend, value: b'tensorflow' attribute key: keras_version, value: b'2.1.2' Group key:/model_weights/conv2d_1 attribute key: weight_names, value: [b'conv2d_1_2/kernel:0' b'conv2d_1_2/bias:0'] Group key:/model_weights/conv2d_1/conv2d_1_2 Dataset key:/model_weights/conv2d_1/conv2d_1_2/bias:0, type: float32, shape: (32,) Dataset key:/model_weights/conv2d_1/conv2d_1_2/kernel:0, type: float32, shape: (3, 3, 1, 32) Group key:/model_weights/conv2d_2 attribute key: weight_names, value: [b'conv2d_2_2/kernel:0' b'conv2d_2_2/bias:0'] Group key:/model_weights/conv2d_2/conv2d_2_2 Dataset key:/model_weights/conv2d_2/conv2d_2_2/bias:0, type: float32, shape: (64,) Dataset key:/model_weights/conv2d_2/conv2d_2_2/kernel:0, type: float32, shape: (3, 3, 32, 64) Group key:/model_weights/dense_1 attribute key: weight_names, value: [b'dense_1_2/kernel:0' b'dense_1_2/bias:0'] Group key:/model_weights/dense_1/dense_1_2 Dataset key:/model_weights/dense_1/dense_1_2/bias:0, type: float32, shape: (128,) Dataset key:/model_weights/dense_1/dense_1_2/kernel:0, type: float32, shape: (9216, 128) Group key:/model_weights/dense_2 attribute key: weight_names, value: [b'dense_2_2/kernel:0' b'dense_2_2/bias:0'] Group key:/model_weights/dense_2/dense_2_2 Dataset key:/model_weights/dense_2/dense_2_2/bias:0, type: float32, shape: (10,) Dataset key:/model_weights/dense_2/dense_2_2/kernel:0, type: float32, shape: (128, 10) Group key:/model_weights/dropout_1 attribute key: weight_names, value: [] Group key:/model_weights/dropout_2 attribute key: weight_names, value: [] Group key:/model_weights/flatten_1 attribute key: weight_names, value: [] Group key:/model_weights/max_pooling2d_1 attribute key: weight_names, value: [] Group key:/optimizer_weights attribute key: weight_names, value: [b'training_2/Adadelta/Variable:0' b'training_2/Adadelta/Variable_1:0' b'training_2/Adadelta/Variable_2:0' b'training_2/Adadelta/Variable_3:0' b'training_2/Adadelta/Variable_4:0' b'training_2/Adadelta/Variable_5:0' b'training_2/Adadelta/Variable_6:0' b'training_2/Adadelta/Variable_7:0' b'training_2/Adadelta/Variable_8:0' b'training_2/Adadelta/Variable_9:0' b'training_2/Adadelta/Variable_10:0' b'training_2/Adadelta/Variable_11:0' b'training_2/Adadelta/Variable_12:0' b'training_2/Adadelta/Variable_13:0' b'training_2/Adadelta/Variable_14:0' b'training_2/Adadelta/Variable_15:0'] Group key:/optimizer_weights/training_2 Group key:/optimizer_weights/training_2/Adadelta Dataset key:/optimizer_weights/training_2/Adadelta/Variable:0, type: float32, shape: (3, 3, 1, 32) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_10:0, type: float32, shape: (3, 3, 32, 64) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_11:0, type: float32, shape: (64,) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_12:0, type: float32, shape: (9216, 128) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_13:0, type: float32, shape: (128,) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_14:0, type: float32, shape: (128, 10) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_15:0, type: float32, shape: (10,) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_1:0, type: float32, shape: (32,) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_2:0, type: float32, shape: (3, 3, 32, 64) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_3:0, type: float32, shape: (64,) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_4:0, type: float32, shape: (9216, 128) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_5:0, type: float32, shape: (128,) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_6:0, type: float32, shape: (128, 10) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_7:0, type: float32, shape: (10,) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_8:0, type: float32, shape: (3, 3, 1, 32) Dataset key:/optimizer_weights/training_2/Adadelta/Variable_9:0, type: float32, shape: (32,)