如何使用Tensorflow Keras(tensorflow 2.0 alpha)训练尺寸可变的图像

时间:2019-05-13 09:17:52

标签: keras tensorflow2.0

我试图将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,它们非常有效。

0 个答案:

没有答案