基于深度学习的中国传统特色图像的风格迁移创新实训第二周(1)

这周的工作主要是分工合作,合作实现上周论文中的部分方法:

小组工作是分函数实现的,下面我将介绍一些负责的函数部分:

读入图片,返回划分了patch的:

def image(batch_size, height, width, path, preprocess_fn, epochs=2, shuffle=True):
    filenames = [join(path, f) for f in listdir(path) if isfile(join(path, f))]
    if not shuffle:
        filenames = sorted(filenames)

    png = filenames[0].lower().endswith('png') #将以png为后缀名的文件名变为小写 
    #string——input——producer会产生一个文件队列

    filename_queue = tf.train.string_input_producer(filenames, shuffle=shuffle, num_epochs=epochs)
    reader = tf.WholeFileReader()
    _, img_bytes = reader.read(filename_queue)
    image = tf.image.decode_png(img_bytes, channels=3) if png else tf.image.decode_jpeg(img_bytes, channels=3)
#解码png或jpeg格式的图片
    processed_image = preprocess_fn(image, height, width)
    return tf.train.batch([processed_image], batch_size, dynamic_pad=True)

因为训练数据可能会有不同规格的形式,直接把获取到的数据作为训练集可能会有所限制,

有时候,对数据的预处理与规范化是不可或缺的一步

比如,在本次实验中,当使用relu(如下图)作为激活函数时,如果数据集中在函数的负数区域,那么结果会有很多0

 

但是实际上,结果不可能为0,尤其是在回归问题上

其中一种解决方法是改变激活函数,选取其他形式的激活函数,比如sigmod

但是鉴于relu有一些本身的优点,我们可能无法避免的使用relu,因此,将数据规范化到y的正方向就是必要的步骤

在这个程序里,我们需要对数据进行规范化,其中用到的函数为batch_normalize

该函数的作用是将一数据以batch为单位进行规范化处理

主要代码实现如下:

def batch_norm(x, size, training, decay=0.999):
    beta = tf.Variable(tf.zeros([size]), name='beta')
    scale = tf.Variable(tf.ones([size]), name='scale')
    pop_mean = tf.Variable(tf.zeros([size]))
    pop_var = tf.Variable(tf.ones([size]))
    epsilon = 1e-3

    batch_mean, batch_var = tf.nn.moments(x, [0, 1, 2])
    train_mean = tf.assign(pop_mean, pop_mean * decay + batch_mean * (1 - decay))
    train_var = tf.assign(pop_var, pop_var * decay + batch_var * (1 - decay))

    def batch_statistics():
        with tf.control_dependencies([train_mean, train_var]):
            return tf.nn.batch_normalization(x, batch_mean, batch_var, beta, scale, epsilon, name='batch_norm')

    def population_statistics():
        return tf.nn.batch_normalization(x, pop_mean, pop_var, beta, scale, epsilon, name='batch_norm')

    return tf.cond(training, batch_statistics, population_statistics)

其中,首先调用tensorflow的moments方法,计算输入batch(即x)的均值和方差

然后,通过公式

pop_mean, pop_mean * decay + batch_mean * (1 - decay)
pop_var= pop_var * decay + batch_var * (1 - decay)

采用迭代法来使得pop_mean 与 pop_var 收敛

在方法中定义了两个私有方法:

    def batch_statistics():
        with tf.control_dependencies([train_mean, train_var]):
            return tf.nn.batch_normalization(x, batch_mean, batch_var, beta, scale, epsilon, name='batch_norm')

    def population_statistics():
        return tf.nn.batch_normalization(x, pop_mean, pop_var, beta, scale, epsilon, name='batch_norm')

    return tf.cond(training, batch_statistics, population_statistics)

这两个方法分别用到tensorflow的control_dependencies 和 batch_normaliaztion

在方法之后返回,需要用到这两个私有方法

注重可以获得归一化之后的结果

通过这样,当使用激活函数relu的时候,就可以使输出的数据更具有普遍性而不是全为0,或者是一个很小的或很大的数

 



猜你喜欢

转载自blog.csdn.net/mingzhao0220/article/details/79973341