Я пытаюсь создать 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'.Тогда тензор потока дает ошибку.Я знаю, почему произошла ошибка, но я не знаю, как ее исправить.
Кто-нибудь может мне помочь?Спасибо.