我试图将tensorflow(2.0 alpha)keras应用于我先前的项目代码。但是我遇到了一个问题。全卷积网络能够馈入各种大小的输入。因为卷积运算不依赖于要素图的大小。因此,在先前版本的tensorflow(1.6)中,我可以训练一个模型,将占位符大小设置为(None,None,None,3)。但是,我无法将相同的机制应用于tensorflow keras代码。
class Conv(L.Layer):
def __init__(self,filters, kernel_size = (3,3), activation = None, strides = (1,1), padding = "same" ,output_padding = None, dropout_rate = .0, **kwargs):
super(Conv, self).__init__(**kwargs)
self.relu = L.ReLU()
self.dropout = L.Dropout(rate = dropout_rate)
self.conv = L.Conv2D(filters = filters, activation = activation, kernel_size = kernel_size, strides = strides, padding = padding)
def call(self, inputs):
process = self.conv(inputs)
process = self.relu(process)
process = self.dropout(process)
return process
from keras import backend as B
class FCN_VGG16(K.Model):
def __init__(self, **kwargs):
super(FCN_VGG16, self).__init__(**kwargs)
self.input_tensor = L.Input(shape=(None, None, 3))
self.vgg_fe = VGG16(include_top=False, weights='imagenet', input_tensor = self.input_tensor, pooling=None)
self.vgg_fe.trainable = False
self.deconv_1 = K.Sequential([L.ReLU(),
L.Dropout(rate = .4),
L.Convolution2DTranspose(filters = 512, activation = None,
kernel_size = (3,3), strides = (2,2), padding = "valid",
output_padding = None)
])
self.deconv_2 = K.Sequential([L.ReLU(),
L.Dropout(rate = .3),
L.Convolution2DTranspose(filters = 256, activation = None,
kernel_size = (3,3), strides = (2,2), padding = "valid",
output_padding = None)
])
self.deconv_3 = K.Sequential([L.ReLU(),
L.Dropout(rate = .2),
L.Convolution2DTranspose(filters = 128, activation = None,
kernel_size = (3,3), strides = (2,2), padding = "valid",
output_padding = None)
])
self.deconv_4 = K.Sequential([L.ReLU(),
L.Dropout(rate = .1),
L.Convolution2DTranspose(filters = 64, activation = None,
kernel_size = (3,3), strides = (2,2), padding = "valid",
output_padding = None)
])
self.deconv_5 = K.Sequential([L.ReLU(),
L.Dropout(rate = .1),
L.Convolution2DTranspose(filters = 64, activation = None,
kernel_size = (3,3), strides = (2,2), padding = "valid",
output_padding = None)
])
self.conv_cls = Conv(2, kernel_size = (1,1), activation = 'softmax')
def shape_difference(self, x1, x2):
dw = x1.shape[1] - x2.shape[1]
dh = x1.shape[2] - x2.shape[2]
return dw, dh
def call(self, inputs):
process = inputs
for layer in self.vgg_fe.layers:
process = layer(process)
if layer.name == 'block3_pool':
process_block3_pool = process
elif layer.name == 'block1_pool':
process_block1_pool = process
process = self.deconv_1(process)
process = self.deconv_2(process)
dw, dh = self.shape_difference(process, process_block3_pool)
sw = dw//2
sh = dh//2
aw = dw%2
ah = dh%2
process = process[:,sw:process.shape[1]-(sw+aw),sh:process.shape[2]-(sh+ah),:] + process_block3_pool
process = self.deconv_3(process)
process = self.deconv_4(process)
dw, dh = self.shape_difference(process, process_block1_pool)
sw = dw//2
sh = dh//2
aw = dw%2
ah = dh%2
process = process[:,sw:process.shape[1]-(sw+aw),sh:process.shape[2]-(sh+ah),:] + process_block1_pool
process = self.deconv_5(process)
dw, dh = self.shape_difference(process, inputs)
sw = dw//2
sh = dh//2
aw = dw%2
ah = dh%2
process = process[:,sw:process.shape[1]-(sw+aw),sh:process.shape[2]-(sh+ah),:]
process = self.conv_cls(process)
return process
model = FCN_VGG16()
model.compile(optimizer=K.optimizers.Adam(0.0001),
loss = K.losses.sparse_categorical_crossentropy,#'sparse_categorical_crossentropy',
metrics = ['accuracy'])
for i in range(len(img_)):
print(img_[i].shape)
model.fit(img_[i], lab_[i], batch_size=1, epochs= 1)
在上述代码中,img_包含彼此不同的图像。
---------------------------------------------------------------------------
InvalidArgumentError Traceback (most recent call last)
<ipython-input-9-453e77d4d45a> in <module>()
1 for i in range(len(img_)):
2 print(img_[i].shape)
----> 3 model.fit(img_[i], lab_[i], batch_size=1, epochs= 1)
c:\programdata\anaconda3\envs\ts\lib\site-packages\tensorflow\python\keras\engine\training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_freq, max_queue_size, workers, use_multiprocessing, **kwargs)
871 validation_steps=validation_steps,
872 validation_freq=validation_freq,
--> 873 steps_name='steps_per_epoch')
874
875 def evaluate(self,
c:\programdata\anaconda3\envs\ts\lib\site-packages\tensorflow\python\keras\engine\training_arrays.py in model_iteration(model, inputs, targets, sample_weights, batch_size, epochs, verbose, callbacks, val_inputs, val_targets, val_sample_weights, shuffle, initial_epoch, steps_per_epoch, validation_steps, validation_freq, mode, validation_in_fit, prepared_feed_values_from_dataset, steps_name, **kwargs)
350
351 # Get outputs.
--> 352 batch_outs = f(ins_batch)
353 if not isinstance(batch_outs, list):
354 batch_outs = [batch_outs]
c:\programdata\anaconda3\envs\ts\lib\site-packages\tensorflow\python\keras\backend.py in __call__(self, inputs)
3215 value = math_ops.cast(value, tensor.dtype)
3216 converted_inputs.append(value)
-> 3217 outputs = self._graph_fn(*converted_inputs)
3218 return nest.pack_sequence_as(self._outputs_structure,
3219 [x.numpy() for x in outputs])
c:\programdata\anaconda3\envs\ts\lib\site-packages\tensorflow\python\eager\function.py in __call__(self, *args, **kwargs)
556 raise TypeError("Keyword arguments {} unknown. Expected {}.".format(
557 list(kwargs.keys()), list(self._arg_keywords)))
--> 558 return self._call_flat(args)
559
560 def _filtered_call(self, args, kwargs):
c:\programdata\anaconda3\envs\ts\lib\site-packages\tensorflow\python\eager\function.py in _call_flat(self, args)
625 # Only need to override the gradient in graph mode and when we have outputs.
626 if context.executing_eagerly() or not self.outputs:
--> 627 outputs = self._inference_function.call(ctx, args)
628 else:
629 self._register_gradient()
c:\programdata\anaconda3\envs\ts\lib\site-packages\tensorflow\python\eager\function.py in call(self, ctx, args)
413 attrs=("executor_type", executor_type,
414 "config_proto", config),
--> 415 ctx=ctx)
416 # Replace empty list with None
417 outputs = outputs or None
c:\programdata\anaconda3\envs\ts\lib\site-packages\tensorflow\python\eager\execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
64 else:
65 message = e.message
---> 66 six.raise_from(core._status_to_exception(e.code, message), None)
67 except TypeError as e:
68 if any(ops._is_keras_symbolic_tensor(x) for x in inputs):
c:\programdata\anaconda3\envs\ts\lib\site-packages\six.py in raise_from(value, from_value)
InvalidArgumentError: The given optional does not match the expected shape for component 0. Expected: [?,31,28,512]. Actual: [1,30,21,512].
[[{{node training/Adam/gradients/sequential/dropout/cond_grad/If/then/_236/gradients/dropout/mul_1_grad/Shape/OptionalGetValue}}]]
[[GroupCrossDeviceControlEdges_0/training/Adam/Adam/Const/_117]] [Op:__inference_keras_scratch_graph_4258]
实际上,我通过使用渐变磁带功能解决了此问题。但是,我想使用许多内置的keras,它们非常有效。