如何在tf.keras

时间:2019-03-21 16:00:05

标签: python tf.keras

我正在尝试使用tf.keras构建SegNet,但是在使用tf.keras.layers.UpSampling时遇到了一些问题。我不知道如何获取maxpooling的mask(index)并将其用于tf.keras.layers.UpSampling。

我已经在https://github.com/tensorflow/tensorflow/blob/r1.12/tensorflow/python/keras/layers/convolutional.py中看到了tf.keras.layers.UpSampling的代码 似乎没有此功能的实现。

然后我尝试找到一些替代方法,并且在 https://github.com/ykamikawa/tf-keras-SegNet/blob/master/layers.py

我通过简单的测试尝试了此方法,但遇到了一些问题。代码如下:

from tensorflow.keras.layers import Layer
import tensorflow as tf

class MaxPoolingWithArgmax2D(Layer):

    def __init__(
            self,
            pool_size=(2, 2),
            strides=(2, 2),
            padding='same',
            **kwargs):
        super(MaxPoolingWithArgmax2D, self).__init__(**kwargs)
        self.padding = padding
        self.pool_size = pool_size
        self.strides = strides

    def call(self, inputs, **kwargs):
        padding = self.padding
        pool_size = self.pool_size
        strides = self.strides
        ksize = [1, pool_size[0], pool_size[1], 1]
        padding = padding.upper()
        strides = [1, strides[0], strides[1], 1]
        output, argmax = tf.nn.max_pool_with_argmax(
                inputs,
                ksize=ksize,
                strides=strides,
                padding=padding)
        argmax = tf.cast(argmax, tf.float32)
        return [output, argmax]

    def compute_output_shape(self, input_shape):
        ratio = (1, 2, 2, 1)
        output_shape = [
                dim//ratio[idx]
                if dim is not None else None
                for idx, dim in enumerate(input_shape)]
        output_shape = tuple(output_shape)
        return [output_shape, output_shape]

    def compute_mask(self, inputs, mask=None):
        return 2 * [None]


class MaxUnpooling2D(Layer):
    def __init__(self, size=(2, 2), **kwargs):
        super(MaxUnpooling2D, self).__init__(**kwargs)
        self.size = size

    def call(self, inputs, output_shape=None):
        updates, mask = inputs[0], inputs[1]
        with tf.variable_scope(self.name):
            mask = tf.cast(mask, tf.int32)
#            input_shape = tf.shape(updates, out_type='int32')
            input_shape = updates.shape
            #  calculation new shape
            if output_shape is None:
                output_shape = (
                        input_shape[0],
                        input_shape[1]*self.size[0],
                        input_shape[2]*self.size[1],
                        input_shape[3])
            self.output_shape1 = output_shape

            # calculation indices for batch, height, width and feature maps
            one_like_mask = tf.ones_like(mask, dtype='int32')
            batch_shape = tf.concat(
                    [[input_shape[0]], [1], [1], [1]],
                    axis=0)
            batch_range = tf.reshape(
                    tf.range(output_shape[0], dtype='int32'),
                    shape=batch_shape)
            b = one_like_mask * batch_range
            y = (mask // (output_shape[2] * output_shape[3]))
            x = (mask // output_shape[3]) % output_shape[2]
            feature_range = tf.range(output_shape[3], dtype='int32')
            f = one_like_mask * feature_range

            # transpose indices & reshape update values to one dimension
            updates_size = tf.size(updates)
            indices = tf.transpose(tf.reshape(
                tf.stack([b, y, x, f]),
                [4, updates_size]))
            values = tf.reshape(updates, [updates_size])
            ret = tf.scatter_nd(indices, values, output_shape)
            return ret

    def compute_output_shape(self, input_shape):
        mask_shape = input_shape[1]
        return (
                mask_shape[0],
                mask_shape[1]*self.size[0],
                mask_shape[2]*self.size[1],
                mask_shape[3]
                )


def segmet(channels_in,channels_out):
    inputs = tf.keras.layers.Input(shape=(None,None,channels_in))

    outputs,mask = MaxPoolingWithArgmax2D()(inputs)
    outputs = MaxUnpooling2D()([outputs,mask])

    model = tf.keras.models.Model(inputs,outputs,name='segnet')
    return model

if __name__ is '__main__':
    model = segmet(3,6)

我遇到如下错误:

  

回溯(最近通话最近一次):

     

文件“”,第1行,在       runfile('C:/Users/WWW/Desktop/untitled0.py',wdir ='C:/ Users / WWW / Desktop')

     

文件   “ C:\ Soft \ Anaconda3 \ lib \ site-packages \ spyder \ utils \ site \ sitecustomize.py”,   运行文件中的第710行       execfile(文件名,命名空间)

     

文件   “ C:\ Soft \ Anaconda3 \ lib \ site-packages \ spyder \ utils \ site \ sitecustomize.py”,   第101行,在execfile中       exec(compile(f.read(),文件名,'exec'),命名空间)

     

文件“ C:/Users/WWW/Desktop/untitled0.py”,第108行,在       型号= segmet(3,6)

     

segmet中的文件“ C:/Users/WWW/Desktop/untitled0.py”,第102行       输出= MaxUnpooling2D()([输出,掩码])

     

文件   “ C:\ Soft \ Anaconda3 \ lib \ site-packages \ tensorflow \ python \ keras \ engine \ base_layer.py”,   第757行,在致电中       输出= self.call(输入,* args,** kwargs)

     

通话中文件“ C:/Users/WWW/Desktop/untitled0.py”,第69行       轴= 0)

     

文件   “ C:\ Soft \ Anaconda3 \ lib \ site-packages \ tensorflow \ python \ ops \ array_ops.py”,   1124行,在concat       返回gen_array_ops.concat_v2(values = values,axis = axis,name = name)

     

文件   “ C:\ Soft \ Anaconda3 \ lib \ site-packages \ tensorflow \ python \ ops \ gen_array_ops.py”,   concat_v2中的第1202行       “ ConcatV2”,值=值,轴=轴,名称=名称)

     

文件   “ C:\ Soft \ Anaconda3 \ lib \ site-packages \ tensorflow \ python \ framework \ op_def_library.py”,   _apply_op_helper中的第483行       引发TypeError(“%s都不全。”%前缀)

     

TypeError:传递给“ ConcatV2” Op的“值”的列表中的张量具有   类型[,int32,int32,int32]不   全部匹配。

因为tf.keras模型中的输入没有固定大小。因此,以上代码中的output_shape为[None,None,None,3]。诸如tf.concat和tf.reshape之类的函数无法处理“无”。然后,张量流给出一个错误。我知道为什么会发生错误,但是我不知道如何解决它。

有人可以帮助我吗?谢谢。

0 个答案:

没有答案