2018-03-18-Cycle GAN with Tensorflow (2)


Module

  • generator_resnet

def generator_resnet (image, options, reuse=False, name="generator"):
    with tf.variable_scope(name):
        # image is 256 x 256 x input_c_dim
        if reuse:
            tf.get_variable_scope().reuse_variables()
        else:
            assert tf.get_variable_scope().reuse is False

        def residule_block(x, dim, ks=3, s=1, name='res'):
            p = int((ks - 1) / 2)
            y = tf.pad(x, [[0, 0], [p, p], [p, p], [0, 0]], "REFLECT")
            y = instance_norm(conv2d(y, dim, ks, s, padding='VALID', name=name+'_c1'), name+'_bn1')
            y = tf.pad(tf.nn.relu(y), [[0, 0], [p, p], [p, p], [0, 0]], "REFLECT")
            y = instance_norm(conv2d(y, dim, ks, s, padding='VALID', name=name+'_c2'), name+'_bn2')
            return y + x

        # Justin Johnson's model from https://github.com/jcjohnson/fast-neural-style/
        # The network with 9 blocks consists of: c7s1-32, d64, d128, R128, R128, R128,
        # R128, R128, R128, R128, R128, R128, u64, u32, c7s1-3
        c0 = tf.pad(image, [[0, 0], [3, 3], [3, 3], [0, 0]], "REFLECT")
        c1 = tf.nn.relu(instance_norm(conv2d(c0, options.gf_dim, 7, 1, padding='VALID', name='g_e1_c'), 'g_e1_bn'))
        c2 = tf.nn.relu(instance_norm(conv2d(c1, options.gf_dim*2, 3, 2, name='g_e2_c'), 'g_e2_bn'))
        c3 = tf.nn.relu(instance_norm(conv2d(c2, options.gf_dim*4, 3, 2, name='g_e3_c'), 'g_e3_bn'))
        # define G network with 9 resnet blocks
        r1 = residule_block(c3, options.gf_dim*4, name='g_r1')
        r2 = residule_block(r1, options.gf_dim*4, name='g_r2')
        r3 = residule_block(r2, options.gf_dim*4, name='g_r3')
        r4 = residule_block(r3, options.gf_dim*4, name='g_r4')
        r5 = residule_block(r4, options.gf_dim*4, name='g_r5')
        r6 = residule_block(r5, options.gf_dim*4, name='g_r6')
        r7 = residule_block(r6, options.gf_dim*4, name='g_r7')
        r8 = residule_block(r7, options.gf_dim*4, name='g_r8')
        r9 = residule_block(r8, options.gf_dim*4, name='g_r9')

        d1 = deconv2d(r9, options.gf_dim*2, 3, 2, name='g_d1_dc')
        d1 = tf.nn.relu(instance_norm(d1, 'g_d1_bn'))
        d2 = deconv2d(d1, options.gf_dim, 3, 2, name='g_d2_dc')
        d2 = tf.nn.relu(instance_norm(d2, 'g_d2_bn'))
        d2 = tf.pad(d2, [[0, 0], [3, 3], [3, 3], [0, 0]], "REFLECT")
        pred = tf.nn.tanh(conv2d(d2, options.output_c_dim, 7, 1, padding='VALID', name='g_pred_c'))
        return pred

note that:
1.here instance norm be used.
Batch norm averages and standard deviations all pixels of a picture in a batch. The instance norm averages and standard deviations all pixels of a single picture.
What the style transfer wants is to match the deep activation distribution of the generated image with the distribution of the style image. This can actually be considered as a problem of domain adaptation. So in this case, instance norm is more suitable.
2.about pad
tf.pad
pad( tensor, #input tensor , paddings,
mode=’CONSTANT’, # it means 0 be filled up
name=None
)
example:


# 't' is [[1, 2, 3], [4, 5, 6]].
# 'paddings' is [[1, 1,], [2, 2]].
# 'constant_values' is 0.
# rank of 't' is 2.
pad(t, paddings, "CONSTANT") 
==> [[0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 2, 3, 0, 0],
 [0, 0, 4, 5, 6, 0, 0],
 [0, 0, 0, 0, 0, 0, 0]]
pad(t, paddings, "REFLECT") ==> [[6, 5, 4, 5, 6, 5, 4],
[3, 2, 1, 2, 3, 2, 1],
[6, 5, 4, 5, 6, 5, 4],
[3, 2, 1, 2, 3, 2, 1]]

note that:
'paddings' is [[1, 1,], [2, 2]]. means:
[1,1] refers to expanding one line up and one line down
[2,2] refers to 2 columns to the left and 2 columns to the right

and when "REFLECT" is on, 'paddings' is [[1, 1,], [2, 2]].
original
1, 2, 3
4, 5, 6

Scroll up one line, 123 as the up edge(axis of symmetry)
4,5,6
1,2,3
4,5,6

Scroll down one line, 456 as the axis of symmetry
4,5,6
1,2,3
4,5,6
1,2,3

turn left 2 rows, 4141 as axis of symmetry
6,5,4,5,6
3,2,1,2,3
6,5,4,5,6
3,2,1,2,3

turn right 2 rows, 6362 as axis of symmetry
6,5,4,5,6,5,4
3,2,1,2,3,2,1
6,5,4,5,6,5,4
3,2,1,2,3,2,1


OP

  • conv2d

def conv2d(input, filter, kernel, strides=1, stddev=0.02, name='conv2d'):
    with tf.variable_scope(name):
        w = tf.get_variable(
            'w',
            (kernel, kernel, input.get_shape()[-1], filter),
            initializer=tf.truncated_normal_initializer(stddev=stddev)
        )
        conv = tf.nn.conv2d(input, w, strides=[1, strides, strides, 1], padding='VALID')
        b = tf.get_variable(
            'b',
            [filter],
            initializer=tf.constant_initializer(0.0)
        )
        conv = tf.reshape(tf.nn.bias_add(conv, b), tf.shape(conv))
        return conv

compare with the following code :

def scope(default_name):
    def deco(fn):
        def wrapper(*args, **kwargs):
            if 'name' in kwargs:
                name = kwargs['name']
                kwargs.pop('name')
            else:
                name = default_name
            with tf.variable_scope(name):
                return fn(*args, **kwargs)
        return wrapper
    return deco

@scope('conv2d')
def conv2d(input, filter, kernel, strides=1, stddev=0.02):
    w = tf.get_variable(
        'w',
        (kernel, kernel, input.get_shape()[-1], filter),
        initializer=tf.truncated_normal_initializer(stddev=stddev)
    )
    conv = tf.nn.conv2d(input, w, strides=[1, strides, strides, 1], padding='VALID')
    b = tf.get_variable(
        'b',
        [filter],
        initializer=tf.constant_initializer(0.0)
    )
    conv = tf.reshape(tf.nn.bias_add(conv, b), tf.shape(conv))
    return conv

anyway, i prefer just using "with tf.variable_scope(name):"

  • res_block

def res_block(x, dim, name='res_block'):
    with tf.variable_scope(name):
        y = reflect_pad(x, name='rp1')
        y = conv2d(y, dim, 3, name='conv1')
        y = lrelu(y)
        y = reflect_pad(y, name='rp2')
        y = conv2d(y, dim, 3, name='conv2')
        y = lrelu(y)
        return tf.add(x, y)
2 level residual block
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 想从Tensorflow循环生成对抗网络开始。但是发现从最难的内容入手还是?太复杂了所以搜索了一下他的始祖也就是深...
    Feather轻飞阅读 5,073评论 1 4
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,923评论 18 139
  • 这个点了,却睡不着了,想写点什么,想起我的这些亲亲的朋友们,立马觉得人生幸福满满。 认识最久的,当然是你了,丽...
    我家的怡子阅读 709评论 15 62
  • 烦死了,心情不好,想太多太累,我是不是太啰嗦了,一点什么事情都放在心上,心里一点事情都要说出来,说多了别人觉得太啰...
    志梅阅读 173评论 0 0
  • 乾隆元年(1736年) 他举“博学鸿词”科,不赴而归 在江干市 肆酿酒为生,以布衣自乐 晚年家道衰落,贫困交加,但...
    云上文化阅读 303评论 0 0