我对修改后的 U-Net 架构的输入维度有一两个问题。为了节省您的时间并更好地理解/重现我的结果,我将发布代码和输出尺寸。修改后的U-Net架构是来自的MultiResUNet架构https://github.com/nibtehaz/MultiResUNet/blob/master/MultiResUNet.py https://github.com/nibtehaz/MultiResUNet/blob/master/MultiResUNet.py。并基于本文https://arxiv.org/abs/1902.04049 https://arxiv.org/abs/1902.04049请不要因为这段代码的长度而关闭。您只需复制粘贴即可,重现我的结果的时间不会超过 10 秒。此外,您不需要为此提供数据集。使用 TF.v1.9 Keras v.2.20 进行测试。
import tensorflow as tf
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Conv2DTranspose, concatenate, BatchNormalization, Activation, add
from tensorflow.keras.models import Model
from tensorflow.keras.activations import relu
###{ 2D Convolutional layers
# Arguments: ######################################################################
# x {keras layer} -- input layer #
# filters {int} -- number of filters #
# num_row {int} -- number of rows in filters #
# num_col {int} -- number of columns in filters #
# Keyword Arguments:
# padding {str} -- mode of padding (default: {'same'})
# strides {tuple} -- stride of convolution operation (default: {(1, 1)})
# activation {str} -- activation function (default: {'relu'})
# name {str} -- name of the layer (default: {None})
# Returns:
# [keras layer] -- [output layer]}
# # ############################################################################
def conv2d_bn(x, filters ,num_row,num_col, padding = "same", strides = (1,1), activation = 'relu', name = None):
x = Conv2D(filters,(num_row, num_col), strides=strides, padding=padding, use_bias=False)(x)
x = BatchNormalization(axis=3, scale=False)(x)
if(activation == None):
return x
x = Activation(activation, name=name)(x)
return x
# our 2D transposed Convolution with batch normalization
# 2D Transposed Convolutional layers
# Arguments: #############################################################
# x {keras layer} -- input layer #
# filters {int} -- number of filters #
# num_row {int} -- number of rows in filters #
# num_col {int} -- number of columns in filters
# Keyword Arguments:
# padding {str} -- mode of padding (default: {'same'})
# strides {tuple} -- stride of convolution operation (default: {(2, 2)})
# name {str} -- name of the layer (default: {None})
# Returns:
# [keras layer] -- [output layer] ###################################
def trans_conv2d_bn(x, filters, num_row, num_col, padding='same', strides=(2, 2), name=None):
x = Conv2DTranspose(filters, (num_row, num_col), strides=strides, padding=padding)(x)
x = BatchNormalization(axis=3, scale=False)(x)
return x
# Our Multi-Res Block
# Arguments: ############################################################
# U {int} -- Number of filters in a corrsponding UNet stage #
# inp {keras layer} -- input layer #
# Returns: #
# [keras layer] -- [output layer] #
###################################################################
def MultiResBlock(U, inp, alpha = 1.67):
W = alpha * U
shortcut = inp
shortcut = conv2d_bn(shortcut, int(W*0.167) + int(W*0.333) +
int(W*0.5), 1, 1, activation=None, padding='same')
conv3x3 = conv2d_bn(inp, int(W*0.167), 3, 3,
activation='relu', padding='same')
conv5x5 = conv2d_bn(conv3x3, int(W*0.333), 3, 3,
activation='relu', padding='same')
conv7x7 = conv2d_bn(conv5x5, int(W*0.5), 3, 3,
activation='relu', padding='same')
out = concatenate([conv3x3, conv5x5, conv7x7], axis=3)
out = BatchNormalization(axis=3)(out)
out = add([shortcut, out])
out = Activation('relu')(out)
out = BatchNormalization(axis=3)(out)
return out
# Our ResPath:
# ResPath
# Arguments:#######################################
# filters {int} -- [description]
# length {int} -- length of ResPath
# inp {keras layer} -- input layer
# Returns:
# [keras layer] -- [output layer]#############
def ResPath(filters, length, inp):
shortcut = inp
shortcut = conv2d_bn(shortcut, filters, 1, 1,
activation=None, padding='same')
out = conv2d_bn(inp, filters, 3, 3, activation='relu', padding='same')
out = add([shortcut, out])
out = Activation('relu')(out)
out = BatchNormalization(axis=3)(out)
for i in range(length-1):
shortcut = out
shortcut = conv2d_bn(shortcut, filters, 1, 1,
activation=None, padding='same')
out = conv2d_bn(out, filters, 3, 3, activation='relu', padding='same')
out = add([shortcut, out])
out = Activation('relu')(out)
out = BatchNormalization(axis=3)(out)
return out
# MultiResUNet
# Arguments: ############################################
# height {int} -- height of image
# width {int} -- width of image
# n_channels {int} -- number of channels in image
# Returns:
# [keras model] -- MultiResUNet model###############
def MultiResUnet(height, width, n_channels):
inputs = Input((height, width, n_channels))
# downsampling part begins here
mresblock1 = MultiResBlock(32, inputs)
pool1 = MaxPooling2D(pool_size=(2, 2))(mresblock1)
mresblock1 = ResPath(32, 4, mresblock1)
mresblock2 = MultiResBlock(32*2, pool1)
pool2 = MaxPooling2D(pool_size=(2, 2))(mresblock2)
mresblock2 = ResPath(32*2, 3, mresblock2)
mresblock3 = MultiResBlock(32*4, pool2)
pool3 = MaxPooling2D(pool_size=(2, 2))(mresblock3)
mresblock3 = ResPath(32*4, 2, mresblock3)
mresblock4 = MultiResBlock(32*8, pool3)
# Upsampling part
up5 = concatenate([Conv2DTranspose(
32*4, (2, 2), strides=(2, 2), padding='same')(mresblock4), mresblock3], axis=3)
mresblock5 = MultiResBlock(32*8, up5)
up6 = concatenate([Conv2DTranspose(
32*4, (2, 2), strides=(2, 2), padding='same')(mresblock5), mresblock2], axis=3)
mresblock6 = MultiResBlock(32*4, up6)
up7 = concatenate([Conv2DTranspose(
32*2, (2, 2), strides=(2, 2), padding='same')(mresblock6), mresblock1], axis=3)
mresblock7 = MultiResBlock(32*2, up7)
conv8 = conv2d_bn(mresblock7, 1, 1, 1, activation='sigmoid')
model = Model(inputs=[inputs], outputs=[conv8])
return model
现在回到 UNet 架构中输入/输出维度不匹配的问题。
如果我选择过滤器高度/宽度 (128,128) 或 (256,256) 或 (512,512) 并执行以下操作:
model = MultiResUnet(128, 128,3)
display(model.summary())
Tensorflow 为我提供了整个架构的完美结果。现在如果我这样做
model = MultiResUnet(36, 36,3)
display(model.summary())
我收到此错误:
-------------------------------------------------- -------------------------- ValueError Traceback(最近调用
最后)在
----> 1 模型 = MultiResUnet(36, 36,3)
2 显示(model.summary())
在 MultiResUnet 中(高度、宽度、
n_通道)
25
26 up5 = 连接([Conv2DTranspose(
---> 27 32*4, (2, 2), 步长=(2, 2), 填充='相同')(mresblock4), mresblock3], 轴=3)
28 mresblock5 = MultiResBlock(32*8, up5)
29
〜/miniconda3/envs/MastersTheenv/lib/python3.6/site-packages/tensorflow/python/keras/layers/merge.py
连接(输入,轴,**kwargs)
第682章 一个张量,输入沿轴的串联axis
。
第683章
--> 684 返回连接(轴=轴,**kwargs)(输入)
第685章
第686章
〜/miniconda3/envs/MastersTheenv/lib/python3.6/site-packages/tensorflow/python/keras/engine/base_layer.py
在call(自身、输入、*args、**kwargs)
第694章
第695章
--> 696 self.build(input_shapes)
第697章
第698章输入形状。
〜/miniconda3/envs/MastersTheenv/lib/python3.6/site-packages/tensorflow/python/keras/utils/tf_utils.py
在包装器中(实例,input_shape)
146 其他:
[第 147 章]
--> 148 输出形状 = fn(实例, 输入形状)
149如果output_shape不是None:
150 if isinstance(输出形状,列表):
〜/miniconda3/envs/MastersTheenv/lib/python3.6/site-packages/tensorflow/python/keras/layers/merge.py
在构建(自身,input_shape)中
第388章
[第 389 章] '
--> 390 '获得输入形状:%s' % (input_shape))
第391章
第392章
值错误:AConcatenate
层需要具有匹配形状的输入
除了连续轴之外。获得输入形状:[(None, 8, 8, 128),
(无、9、9、128)]
为什么 Conv2DTranspose 给我错误的尺寸
(无、8、8、128)
代替
(无、9、9、128)
为什么当我选择 (128,128)、(256,256) 等过滤器大小(32 的倍数)时 Concat 函数不会抱怨因此,为了概括这个问题,我怎样才能使这个 UNet 架构适用于任何过滤器大小我该如何处理 Conv2DTranspose 层,生成比实际需要的尺寸少一维(宽度/高度)的输出(当过滤器大小不是 32 的倍数或不对称时),为什么不这样做如果其他过滤器尺寸是 32 的倍数,则会发生这种情况。如果我有的话会怎样可变输入尺寸 ??
任何帮助将不胜感激。
干杯,
H