我正在使用一个模型,该模型涉及 Keras 中模型的 3 个“嵌套”阶段。
从概念上讲,第一个是迁移学习 CNN 模型,例如 MobileNetV2。(模型 1)然后由一个由小型 DNN 组成的模型包装。(模型 2)最后在训练期间,这些都被一个模型包裹起来,该模型连接模型 2 的多个输出,计算损失,然后反向传播到模型 2 和未来的模型 1。(模型 3)
为了稍后进行推断,我只是想保存模型 1 和 2 的权重。由于某些版本的 Keras(我使用的是 2.2.2)中似乎存在错误并且还加载了权重,因此我遇到了多个问题更明确地似乎导致随机权重,因此无法正常工作。我没有尝试解决任何情况下出了什么问题,我只是想确定保存中间嵌套模型的最佳实践是什么。
def create_model_2(IN_DIM=(224, 224, 3), OUT_DIM=128):
# First define the transfer learning model
initial_img = Input(shape=(IN_DIM))
black_box = MobileNetV2(include_top=False, input_shape=IN_DIM, weights="imagenet", pooling="avg")(initial_img)
bb_model = Model(b_img, black_box)
# freeze layers for transfer learning model
for layer in bb_model.layers:
layer.trainable = False
#########################
###### TOWER BLOCK ######
#########################
img = Input(shape=(IN_DIM))
x = bb_model(img)
# add some layers to try to learn
x = Dense(64, activation='relu', name='new_fc0')(x)
x = Dense(OUT_DIM, activation='relu', name='new_fc1')(x)
# L2 norm to project to unit sphere
out = Lambda(lambda x: K.l2_normalize(x, axis=1), name='final_l2_norm')(x)
_model_2 = Model(img, out)
return _model_2
那么Model 3的结构:
IN_DIM = (224, 224, 3) # mobilenetv2=(224, 224, 3) Iv3=(299, 299, 3)
OUT_DIM = 32
model_2 = create_model_2(IN_DIM, OUT_DIM)
# then define images for triplets
anchor_img = Input(shape=IN_DIM)
pos_img = Input(shape=IN_DIM)
neg_img = Input(shape=IN_DIM)
# create three vectors representing the images
anchor_in = model_2(anchor_img)
positive_in = model_2(pos_img)
negative_in = model_2(neg_img)
# concatenate the vectors into one large vector for input into the triplet loss "processor"
merged_vector = concatenate([anchor_in, positive_in, negative_in], axis=-1)
# actually define the model:
model_3 = Model(inputs=[anchor_img, pos_img, neg_img], outputs=merged_vector)
该模型似乎可以正常运行和训练:
OPTIMIZER = SGD(lr=learning_rate, momentum=0.9)
final_model.compile(optimizer=OPTIMIZER, loss=triplet_loss, metrics=[avg_AP_dist, avg_AN_dist])
history = final_model.fit_generator(generator=training_generator,
epochs=5, # short for debugging
use_multiprocessing=True,
workers=4)
但是训练后保存模型还不清楚:
out_file = "../../models/{:}_epoch_{:}_weights.h5".format(MODEL_DESC, 5)
model_2.save_weights(out_file) # save the actual Tower weights, discard the "booster" wrapper
print("Saved: {:}".format(out_file))
或者:
out_file = "../../models/{:}_epoch_{:}_weights.h5".format(MODEL_DESC, 5)
model_2.save(out_file) # save the actual Tower weights, discard the "booster" wrapper
print("Saved: {:}".format(out_file))
或者是其他东西?
当前的故障模式似乎是,如果我尝试仅将权重加载到新实例化的 model_2 实例中,则会得到:
ValueError: axes don't match array
搜索结果可能与 Keras 中的错误有关。如果我保存模型(.save() 而不是 .save_weights() 那么它会毫无怨言地加载,但推理不稳定并且看起来很可怕/随机。)
谢谢你。
仍然得到以下回溯:
<snip>/src/notebooks/vectorizer.py in load_model()
65
66 # load the weights
---> 67 loaded_model.load_weights(weights_path)
68
69 print("Model ready")
/opt/conda/lib/python3.6/site-packages/keras/engine/network.py in load_weights(self, filepath, by_name, skip_mismatch, reshape)
1164 else:
1165 saving.load_weights_from_hdf5_group(
-> 1166 f, self.layers, reshape=reshape)
1167
1168 def _updated_config(self):
/opt/conda/lib/python3.6/site-packages/keras/engine/saving.py in load_weights_from_hdf5_group(f, layers, reshape)
1043 original_keras_version,
1044 original_backend,
-> 1045 reshape=reshape)
1046 if len(weight_values) != len(symbolic_weights):
1047 raise ValueError('Layer #' + str(k) +
/opt/conda/lib/python3.6/site-packages/keras/engine/saving.py in preprocess_weights_for_loading(layer, weights, original_keras_version, original_backend, reshape)
680 weights = convert_nested_time_distributed(weights)
681 elif layer.__class__.__name__ in ['Model', 'Sequential']:
--> 682 weights = convert_nested_model(weights)
683
684 if original_keras_version == '1':
/opt/conda/lib/python3.6/site-packages/keras/engine/saving.py in convert_nested_model(weights)
668 weights=weights[:num_weights],
669 original_keras_version=original_keras_version,
--> 670 original_backend=original_backend))
671 weights = weights[num_weights:]
672 return new_weights
/opt/conda/lib/python3.6/site-packages/keras/engine/saving.py in preprocess_weights_for_loading(layer, weights, original_keras_version, original_backend, reshape)
680 weights = convert_nested_time_distributed(weights)
681 elif layer.__class__.__name__ in ['Model', 'Sequential']:
--> 682 weights = convert_nested_model(weights)
683
684 if original_keras_version == '1':
/opt/conda/lib/python3.6/site-packages/keras/engine/saving.py in convert_nested_model(weights)
656 weights=weights[:num_weights],
657 original_keras_version=original_keras_version,
--> 658 original_backend=original_backend))
659 weights = weights[num_weights:]
660
/opt/conda/lib/python3.6/site-packages/keras/engine/saving.py in preprocess_weights_for_loading(layer, weights, original_keras_version, original_backend, reshape)
799 weights[0] = np.reshape(weights[0], layer_weights_shape)
800 elif layer_weights_shape != weights[0].shape:
--> 801 weights[0] = np.transpose(weights[0], (3, 2, 0, 1))
802 if layer.__class__.__name__ == 'ConvLSTM2D':
803 weights[1] = np.transpose(weights[1], (3, 2, 0, 1))
/opt/conda/lib/python3.6/site-packages/numpy/core/fromnumeric.py in transpose(a, axes)
596
597 """
--> 598 return _wrapfunc(a, 'transpose', axes)
599
600
/opt/conda/lib/python3.6/site-packages/numpy/core/fromnumeric.py in _wrapfunc(obj, method, *args, **kwds)
49 def _wrapfunc(obj, method, *args, **kwds):
50 try:
---> 51 return getattr(obj, method)(*args, **kwds)
52
53 # An AttributeError occurs if the object does not have
ValueError: axes don't match array