Как реализовать апсэмплинг с маской (индексом) в tf.keras - PullRequest
0 голосов
/ 21 марта 2019

Я пытаюсь создать SegNet с помощью tf.keras, но у меня возникают проблемы при использовании tf.keras.layers.UpSampling.Я не знаю, как получить маску (индекс) maxpooling и использовать ее в tf.keras.layers.UpSampling.

Я видел код tf.keras.layers.UpSampling в https://github.com/tensorflow/tensorflow/blob/r1.12/tensorflow/python/keras/layers/convolutional.py Похоже, что нет реализации этой функции.

Затем я пытаюсь найти какой-то альтернативный метод, и я получил инструмент в 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, в исполняемом файле ('C: /Users/WWW/Desktop/untitled0.py', wdir = 'C: / Users / WWW / Desktop')

Файл "C: \ Soft \ Anaconda3 \ lib \"site-packages \ spyder \ utils \ site \ sitecustomize.py ", строка 710, в исполняемом файле исполняемого файла (имя файла, пространство имен)

Файл" C: \ Soft \ Anaconda3 \ lib \ site-packages \ spyder \ utils "\ site \ sitecustomize.py ", строка 101, в execfile exec (compile (f.read (), filename, 'exec'), пространство имен)

Файл" C: / Users / WWW / Desktop / untitled0.py ", строка 108, в модели = segmet (3,6)

Файл" C: /Users/WWW/Desktop/untitled0.py ", строка 102, в выходных данных сегмента = MaxUnpooling2D () ([выходные данные, маска])

Файл "C: \ Soft \ Anaconda3 \ lib \ site-packages \ensorflow \ python \ keras \ engine \ base_layer.py", строка 757, в вызов output = self.call (входные данные, * args, ** kwargs)

Файл "C: /Users/WWW/Desktop/untitled0.py", строка 69, в оси вызова = 0)

Файл "C: \ Soft \ Anaconda3 \ lib \ site-packages \ tenorflow \ python \ ops \ array_ops.py", строка 1124, в concat return gen_array_ops.concat_v2 (значения = значения, ось = ось, имя =имя)

Файл "C: \ Soft \ Anaconda3 \ lib \ site-packages \ tenorflow \ python \ ops \ gen_array_ops.py", строка 1202, в concat_v2 "ConcatV2", значения = значения, ось = ось, name = name)

Файл "C: \ Soft \ Anaconda3 \ lib \ site-packages \ensorflow \ python \ framework \ op_def_library.py", строка 483, в _apply_op_helper вызывает TypeError ("% s, которые не't all match. "Префикс%)

TypeError: Тензорные функции в списке, переданные в' значения '' ConcatV2 'Op, имеют типы [, int32, int32, int32], которые не все совпадают.

Поскольку входные данные в модели tf.keras не имеют фиксированного размера.Итак, output_shape в приведенном выше коде - [Нет, Нет, Нет, 3].Такие функции, как tf.concat и tf.reshape не могут обрабатывать 'None'.Тогда тензор потока дает ошибку.Я знаю, почему произошла ошибка, но я не знаю, как ее исправить.

Кто-нибудь может мне помочь?Спасибо.

...