我使用Keras构建语义分割模型。该模型是完全卷积的,所以虽然我在特定大小的输入上进行训练,即(224,224,3)
,但在预测时,模型应该能够采取任何大小的输入,对吗?但是,当我尝试在不同分辨率的图像上进行预测时,我会在合并图层中收到有关不匹配形状的错误。这是错误:
(1, 896, 1200, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "predict.py", line 60, in main
n = base_model.predict(x)
File "/home/.local/lib/python2.7/site-packages/keras/engine/training.py", line 1790, in predict
verbose=verbose, steps=steps)
File "/home/.local/lib/python2.7/site-packages/keras/engine/training.py", line 1299, in _predict_loop
batch_outs = f(ins_batch)
File "/home/.local/lib/python2.7/site-packages/keras/backend/tensorflow_backend.py", line 2357, in __call__
**self.session_kwargs)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/client/session.py", line 778, in run
run_metadata_ptr)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/client/session.py", line 982, in _run
feed_dict_string, options, run_metadata)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/client/session.py", line 1032, in _do_run
target_list, options, run_metadata)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/client/session.py", line 1052, in _do_call
raise type(e)(node_def, op, message)
tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [1,56,74,512] vs. [1,56,75,512]
[[Node: add_1/add = Add[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/gpu:0"](conv2d_3/Relu, block5_conv3/Relu)]]
[[Node: conv2d_14/div/_813 = _Recv[client_terminated=false, recv_device="/job:localhost/replica:0/task:0/cpu:0", send_device="/job:localhost/replica:0/task:0/gpu:0", send_device_incarnation=1, tensor_name="edge_157_conv2d_14/div", tensor_type=DT_FLOAT, _device="/job:localhost/replica:0/task:0/cpu:0"]()]]
Caused by op u'add_1/add', defined at:
File "<stdin>", line 1, in <module>
File "predict.py", line 42, in <module>
base_model = models.load_model('mod.h5', custom_objects={'loss':loss})
File "/home/.local/lib/python2.7/site-packages/keras/models.py", line 240, in load_model
model = model_from_config(model_config, custom_objects=custom_objects)
File "/home/.local/lib/python2.7/site-packages/keras/models.py", line 314, in model_from_config
return layer_module.deserialize(config, custom_objects=custom_objects)
File "/home/.local/lib/python2.7/site-packages/keras/layers/__init__.py", line 55, in deserialize
printable_module_name='layer')
File "/home/.local/lib/python2.7/site-packages/keras/utils/generic_utils.py", line 140, in deserialize_keras_object
list(custom_objects.items())))
File "/home/.local/lib/python2.7/site-packages/keras/engine/topology.py", line 2500, in from_config
process_node(layer, node_data)
File "/home/.local/lib/python2.7/site-packages/keras/engine/topology.py", line 2459, in process_node
layer(input_tensors, **kwargs)
File "/home/.local/lib/python2.7/site-packages/keras/engine/topology.py", line 603, in __call__
output = self.call(inputs, **kwargs)
File "/home/.local/lib/python2.7/site-packages/keras/layers/merge.py", line 146, in call
return self._merge_function(inputs)
File "/home/.local/lib/python2.7/site-packages/keras/layers/merge.py", line 210, in _merge_function
output += inputs[i]
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/math_ops.py", line 821, in binary_op_wrapper
return func(x, y, name=name)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/gen_math_ops.py", line 73, in add
result = _op_def_lib.apply_op("Add", x=x, y=y, name=name)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/op_def_library.py", line 768, in apply_op
op_def=op_def)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py", line 2336, in create_op
original_op=self._default_original_op, op_def=op_def)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py", line 1228, in __init__
self._traceback = _extract_stack()
InvalidArgumentError (see above for traceback): Incompatible shapes: [1,56,74,512] vs. [1,56,75,512]
[[Node: add_1/add = Add[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/gpu:0"](conv2d_3/Relu, block5_conv3/Relu)]]
[[Node: conv2d_14/div/_813 = _Recv[client_terminated=false, recv_device="/job:localhost/replica:0/task:0/cpu:0", send_device="/job:localhost/replica:0/task:0/gpu:0", send_device_incarnation=1, tensor_name="edge_157_conv2d_14/div", tensor_type=DT_FLOAT, _device="/job:localhost/replica:0/task:0/cpu:0"]()]]
我的模型架构如下:我使用VGG16并剥离顶层,并且基本上以相反顺序放置层。我还跳过每个块的最后卷积层之间的连接。基本上,我实施SegNet。我不明白为什么我会Incompatible shapes: [1,56,74,512] vs. [1,56,75,512]
。我知道在图层上添加额外的连接必须改变它的尺寸,但为什么Keras的填充不能解决这个问题呢?
以下是构建我的模型的代码:
input_tensor = Input(shape=(None,None,3))
vgg = VGG16(weights='imagenet', include_top=False, input_shape=(None, None,3))
# vgg.summary()
if vgg_train is False:
# Freeze VGG layers
for layer in vgg.layers:
layer.trainable = False
l1_1 = Model.get_layer(vgg, 'block1_conv1')
l1_2 = Model.get_layer(vgg, 'block1_conv2')
l1_p = Model.get_layer(vgg, 'block1_pool')
l2_1 = Model.get_layer(vgg, 'block2_conv1')
l2_2 = Model.get_layer(vgg, 'block2_conv2')
l2_p = Model.get_layer(vgg, 'block2_pool')
l3_1 = Model.get_layer(vgg, 'block3_conv1')
l3_2 = Model.get_layer(vgg, 'block3_conv2')
l3_3 = Model.get_layer(vgg, 'block3_conv3')
l3_p = Model.get_layer(vgg, 'block3_pool')
l4_1 = Model.get_layer(vgg, 'block4_conv1')
l4_2 = Model.get_layer(vgg, 'block4_conv2')
l4_3 = Model.get_layer(vgg, 'block4_conv3')
l4_p = Model.get_layer(vgg, 'block4_pool')
l5_1 = Model.get_layer(vgg, 'block5_conv1')
l5_2 = Model.get_layer(vgg, 'block5_conv2')
l5_3 = Model.get_layer(vgg, 'block5_conv3')
l5_p = Model.get_layer(vgg, 'block5_pool')
#Encoder: Basically re-building VGG layer by layer, because Keras's concat only takes tensors, not layers
x = l1_1(input_tensor)
o1 = l1_2(x)
x = l1_p(o1)
x = l2_1(x)
o2 = l2_2(x)
x = l2_p(o2)
x = l3_1(x)
x = l3_2(x)
o3 = l3_3(x)
x = l3_p(o3)
x = l4_1(x)
x = l4_2(x)
o4 = l4_3(x)
x = l4_p(o4)
x = l5_1(x)
x = l5_2(x)
o5 = l5_3(x)
x = l5_p(o5)
#Decoder layers: VGG architecture in reverse with skip connections and dropout layers
#Block 1
up1 = UpSampling2D()(x)
conv1 = Conv2D(512, 3, activation='relu', padding='same')(up1)
conv1 = Conv2D(512, 3, activation='relu', padding='same')(conv1)
conv1 = Conv2D(512, 3, activation='relu', padding='same')(conv1)
conv1 = add([conv1,o5])
batch1 = BatchNormalization()(conv1)
#Block 2
up2 = UpSampling2D()(batch1)
conv2 = Conv2D(512, 3, activation='relu', padding='same')(up2)
conv2 = Conv2D(512, 3, activation='relu', padding='same')(conv2)
conv2 = Conv2D(512, 3, activation='relu', padding='same')(conv2)
conv2 = add([conv2,o4])
batch2 = BatchNormalization()(conv2)
#Block 3
up3 = UpSampling2D()(batch2)
conv3 = Conv2D(256, 3, activation='relu', padding='same')(up3)
conv3 = Conv2D(256, 3, activation='relu', padding='same')(conv3)
conv3 = Conv2D(256, 3, activation='relu', padding='same')(conv3)
conv3 = add([conv3,o3])
batch3 = BatchNormalization()(conv3)
#Block 4
up4 = UpSampling2D()(batch3)
conv4 = Conv2D(128, 3, activation='relu', padding='same')(up4)
conv4 = Conv2D(128, 3, activation='relu', padding='same')(conv4)
conv4 = add([conv4,o2])
batch4 = BatchNormalization()(conv4)
#Block 5
up5 = UpSampling2D()(batch4)
conv5 = Conv2D(64, 3, activation='relu', padding='same')(up5)
conv5 = Conv2D(64, 3, activation='relu', padding='same')(conv5)
conv5 = add([conv5,o1])
batch5 = BatchNormalization()(conv5)
#Final prediction layer
soft5 = Conv2D(dims, kernel_size=8, strides=8, activation='softmax', padding='same')(batch5)
model = Model(input_tensor,soft5)
model.summary()
return model
答案 0 :(得分:2)
找到解决方案以防其他人遇到此问题。由于显而易见的原因,合并图层需要具有相同的维度。下采样/上采样时会出现问题。例如,如果下采样2倍,则宽度为115的图像将减小到57.5的上限,即58.当对此进行上采样时,得到的张量具有宽度116,这在尝试合并115时会导致问题。宽度为116的宽度层。我的案例的解决方案非常简单。由于我的所有训练数据大小相同,因此问题仅在推理期间发生。此时,如果图片的尺寸不能被32整除,我只需调整大小然后裁剪即可。