Повышение дискретизации с использованием слоев 3d_transposed_convolution - PullRequest
0 голосов
/ 10 января 2019

Предположим, у меня есть тензор 4D x из предыдущего слоя с формой [2, 2, 7, 7, 64], где batch = 2, depth = 2, height = 7, width = 7 и in_channels = 64.

И я бы хотел увеличить его до тензора с формой [2, 4, 14, 14, 32]. Возможно, следующие шаги - это передать его в форме, подобной [2, 8, 28, 28, 16], [2, 16, 112, 112, 1] и т. Д.

Я новичок в Tensorflow и знаю, что реализации транспонированной свертки между CAFFE и Tensorflow разные. Я имею в виду, что в CAFFE вы можете определить размер вывода, изменив шаги ядра. Однако в тензорном потоке все сложнее.

Так, как я могу сделать это с tf.layers.conv3d_transpose или tf.nn.conv3d_transpose?

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

1 Ответ

0 голосов
/ 23 января 2019

Вы можете выполнять повышающую дискретизацию как tf.layers.conv3d_transpose , так и tf.nn.conv3d_transpose .

Рассмотрим ваш входной тензор как:

input_layer = tf.placeholder(tf.float32, (2, 2, 7, 7, 64)) # batch, depth, height, width, in_channels

С tf.nn.conv3d_transpose нам нужно позаботиться о создании переменных (весов и смещений):

def conv3d_transpose(name, l_input, w, b, output_shape, stride=1):
    transp_conv = tf.nn.conv3d_transpose(l_input, w, output_shape, strides=[1, stride, stride, stride, 1], padding='SAME')
    return tf.nn.bias_add(transp_conv, b, name=name)

# Create variables for the operation
with tf.device('/cpu:0'):  
    # weights will have the shape [depth, height, width, output_channels, in_channels]
    weights = tf.get_variable(name='w_transp_conv', shape=[3, 3, 3, 32, 64])
    bias = tf.get_variable(name='b_transp_conv', shape=[32]) 

t_conv_layer = conv3d_transpose('t_conv_layer', input_layer, weights, bias,
                                output_shape=[2, 4, 14, 14, 32], stride=2)
print(t_conv_layer) 
# Tensor("t_conv_layer:0", shape=(2, 4, 14, 14, 32), dtype=float32)

С tf.layers.conv3d_transpose, который позаботится о создании весов и смещений, мы используем один и тот же входной тензор input_layer:

t_conv_layer2 = tf.layers.conv3d_transpose(input_layer, filters=32, kernel_size=[3, 3, 3],
                                           strides=(2, 2, 2), padding='SAME', name='t_conv_layer2')
print(t_conv_layer2)  
# Tensor("t_conv_layer2/Reshape_1:0", shape=(2, 4, 14, 14, 32), dtype=float32) 

Чтобы получить другие повышенные частоты тензоров, вы можете повторить эту процедуру, изменив шаги по мере необходимости:

Пример с tf.layers.conv3d_transpose:

t_conv_layer3 = tf.layers.conv3d_transpose(t_conv_layer2, filters=16, kernel_size=[3, 3, 3],
                                           strides=(2, 2, 2), padding='SAME', name='t_conv_layer3')
t_conv_layer4 = tf.layers.conv3d_transpose(t_conv_layer3, filters=8, kernel_size=[3, 3, 3], 
                                           strides=(2, 2, 2), padding='SAME',   name='t_conv_layer4')
t_conv_layer5 = tf.layers.conv3d_transpose(t_conv_layer4, filters=1, kernel_size=[3, 3, 3], 
                                           strides=(1, 2, 2), padding='SAME', name='t_conv_layer5')
print(t_conv_layer5)
# Tensor("t_conv_layer5/Reshape_1:0", shape=(2, 16, 112, 112, 1), dtype=float32)

Примечание: , поскольку tf.nn.conv3d_transpose фактически является градиентом tf.nn.conv3d, вы можете убедиться, что переменная output_shape является правильной, рассмотрев операцию пересылки с tf.nn .conv3d.

def print_expected(weights, shape, stride=1):
    output = tf.constant(0.1, shape=shape)
    expected_layer = tf.nn.conv3d(output, weights, strides=[1, stride, stride, stride, 1], padding='SAME')
    print("Expected shape of input layer when considering the output shape ({} and stride {}): {}".format(shape, stride, expected_layer.get_shape()))

Поэтому, чтобы получить транспонированную свертку с формой [2, 4, 14, 14, 32], мы можем проверить, например, шаги 1 и 2:

print_expected(weights, shape=[2, 4, 14, 14, 32], stride=1) 
print_expected(weights, shape=[2, 4, 14, 14, 32], stride=2)

, который печатает и подтверждает, что второй вариант (с использованием шага 2) является правильным для получения тензора с желаемой формой:

Expected shape of input layer when considering the output shape ([2, 4, 14, 14, 32] and stride 1): (2, 4, 14, 14, 64)
Expected shape of input layer when considering the output shape ([2, 4, 14, 14, 32] and stride 2): (2, 2, 7, 7, 64) 
...