【时间】2019.12.03
【题目】tensorflow的模型保存文件.ckpt包含什么以及如何读取、并将其转换为Keras的.h5文件
参考:tensorflow中读取模型中保存的值, tf.train.NewCheckpointReader
.ckpt即checkpoint文件。
一个标准的.ckpt模型文件以下文件:
model.ckpt文件组成:
model.ckpt.meta
model.ckpt.data-00000-of-00001
model.ckpt.index
使用 NewCheck =tf.train.NewCheckpointReader(ckpt_file)读取:
import tensorflow as tf
import pprint # 使用pprint 提高打印的可读性
NewCheck =tf.train.NewCheckpointReader("model.ckpt")
print("debug_string:\n")
pprint.pprint(NewCheck.debug_string().decode("utf-8")) #类型是str
其中有3个字段, 分别是名字name, 数据类型type, 尺寸shape
print("get_tensor:\n")
pprint.pprint(NewCheck.get_tensor("D/conv2d/bias"))
不过得到的是字典类型的数据。
print("get_variable_to_dtype_map\n")
pprint.pprint(NewCheck.get_variable_to_dtype_map())
print("get_variable_to_shape_map\n")
pprint.pprint(NewCheck.get_variable_to_shape_map())
代码:
代码来自:https://github.com/johannesu/NASNet-keras
def load_weights_from_tf_checkpoint(model, checkpoint_file, background_label):
print('Load weights from tensorflow checkpoint')
progbar = Progbar(target=len(model.layers))
reader = tf.train.NewCheckpointReader(checkpoint_file)
for index, layer in enumerate(model.layers):
progbar.update(current=index)
if isinstance(layer, layers.convolutional.SeparableConv2D):
depthwise = reader.get_tensor('{}/depthwise_weights'.format(layer.name))
pointwise = reader.get_tensor('{}/pointwise_weights'.format(layer.name))
if K.image_data_format() == 'channels_first':
depthwise = convert_kernel(depthwise)
pointwise = convert_kernel(pointwise)
layer.set_weights([depthwise, pointwise])
elif isinstance(layer, layers.convolutional.Convolution2D):
weights = reader.get_tensor('{}/weights'.format(layer.name))
if K.image_data_format() == 'channels_first':
weights = convert_kernel(weights)
layer.set_weights([weights])
elif isinstance(layer, layers.BatchNormalization):
beta = reader.get_tensor('{}/beta'.format(layer.name))
gamma = reader.get_tensor('{}/gamma'.format(layer.name))
moving_mean = reader.get_tensor('{}/moving_mean'.format(layer.name))
moving_variance = reader.get_tensor('{}/moving_variance'.format(layer.name))
layer.set_weights([gamma, beta, moving_mean, moving_variance])
elif isinstance(layer, layers.Dense):
weights = reader.get_tensor('{}/weights'.format(layer.name))
biases = reader.get_tensor('{}/biases'.format(layer.name))
if background_label:
layer.set_weights([weights, biases])
else:
layer.set_weights([weights[:, 1:], biases[1:]])
def load_pretrained_weights(model, fname, origin, md5_hash, background_label=False, cache_dir=None):
"""Download and convert tensorflow checkpoints"""
# origin = 'https://storage.googleapis.com/download.tensorflow.org/models/nasnet-a_large_04_10_2017.tar.gz'
if cache_dir is None:
cache_dir = os.path.expanduser(os.path.join('~', '.keras', 'models'))
weight_path = os.path.join(cache_dir, '{}_{}_{}.h5'.format(model.name, md5_hash, K.image_data_format()))
if os.path.exists(weight_path):
model.load_weights(weight_path)
else:
if not os.path.exists(cache_dir):
os.makedirs(cache_dir)
print(cache_dir)
path = get_file(fname, origin=origin, extract=True, md5_hash=md5_hash, cache_dir=cache_dir,cache_subdir='.')
checkpoint_file = os.path.join(path, '..', 'model.ckpt')
load_weights_from_tf_checkpoint(model, checkpoint_file, background_label)
model.save_weights(weight_path)
分析:
1、用Keras代码构建model,并且每一层layer的name与.ckpt文件中的层名字相同。
2、实例化reader=tf.train.NewCheckpointReader()
3、对于model的每一层,根据layer的类别,reader.get_file(layer_name)获取权值(array数组),并使用layer.set_weights()进行赋值。
4、最后使用model.save_weights()保存.h5权重。
有没有更简单的方法??