1TensorFlow实现自编码器-1.2TensorFlow实现降噪自动编码器设计计算图

1TensorFlow实现自编码器-1.2TensorFlow实现降噪自动编码器设计计算图

参考:
http://blog.csdn.net/hwang4_12/article/details/62890569

Denoising AutoEncoders降噪自动编码器:
降噪自动编码器DA是自动编码器的基础上,训练数据加入噪声,所以自动编码器必须学习去去除这种噪声而获得真正的没有被噪声污染过的输入。因此,这就迫使编码器去学习输入信号的更加鲁棒的表达,这也是它的泛化能力比一般编码器强的原因。DA可以通过梯度下降算法去训练。

这里写图片描述

Raw input:原始输入信号
Corrupted input:添加噪声
Hidden code(representation):隐藏层对噪声进行编码
reconstruction:编码完了,传入到这个重建模块。
KL(reconstruction|raw input):重建后与原始信号比较误差。
有了误差以后,可以使用优化算法,梯度下降算法,不断调节Hidden code和reconstruction里面的参数,Hidden code和reconstruction里面都是神经网络

TensorFlow实现降噪自动编码器
首先,导入Numpy,Sklearn.preprocessing,tensorflow,MNIST数据集

import numpy as np
import sklearn.preprocessing as prep
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

注:
在tensorflow的log日志等级如下:
- 0:显示所有日志(默认等级)
- 1:显示info、warning和error日志
- 2:显示warning和error信息
- 3:显示error日志信息

如果网络的权重初始化的太小,那信号将会在层间传递时逐渐缩小而难以产生作用;如果权重初始化的太大,那信号将在每层间传递时逐渐放大最终导致发散。

自编码器中会用到一种参数初始化方法:Xavier Initialization。该初始化方法会根据某一层网络的输入输出节点数量自动调整最合适的随机分布。让初始化权重不大不小,正好合适。从数学角度讲,就是让权重满足0均值,方差为 2nin+nout 。随机分布的形式可以是均匀分布或者高斯分布。

#Xavier均匀初始化
#fan_in是输入节点的数量,fan_out是输出节点的数量。
def xavier_init(fan_in ,fan_out,constant=1):
    low = -constant * np.sqrt(6.0 / (fan_in + fan_out))
    high = constant * np.sqrt(6.0 / (fan_in + fan_out))
    return tf.random_uniform((fan_in,fan_out),minval=low,maxval=high,dtype=tf.float32)

上面代码,通过tf.random_uniform创建了一个均匀分布,区间为: (6nin+nout,6nin+nout)

上述均匀分布的方差可以根据公式计算出来:
D(x)=(maxmin)2/12=2nin+nout

因此,上面是一个标准均匀分布的Xavier初始化实现,fan_in是输入节点的数量,fan_out是输出节点的数量。

下面我们定义一个降噪自编码器类。这个类会包含一个构造函数init(),还有一些常用的成员函数。

# 加性高斯噪声的自动编码
class AdditiveGaussianNoiseAutoencoder(object):

首先,我们实现构造函数init(),从构造函数中设计计算图。

# 加性高斯噪声的自动编码
class AdditiveGaussianNoiseAutoencoder(object):
    # 在初始的数据中加入高斯噪声。在实现降噪自编码器的时候,
    # 只是在输入加进去的时候,在输入上加上高斯噪声就行
    # 其他的部分和基本自编码器一样
    #n_input:输入变量数;n_hidden:隐含层节点数;transfer_function:隐含层激活函数;optimizer:优化器;scale:高斯噪声系数
    def __init__(self, n_input, n_hidden, transfer_function=tf.nn.softplus,  optimizer=tf.train.AdamOptimizer(),scale=0.1):
        self.n_input = n_input
        self.n_hidden = n_hidden
        # n_input,n_hidden都是输入和隐藏层的维度
        self.transfer = transfer_function
        self.scale = tf.placeholder(tf.float32)
        self.training_scale = scale
        # scale 就是一个标量
        network_weights = self._initialize_weights()
        self.weights = network_weights

n_input:输入变量数;
n_hidden:隐含层节点数;
transfer_function:隐含层激活函数;
optimizer:优化器;
scale:高斯噪声系数;

Class内的scale声明成一个占位符placeholder,参数初始化则使用了接下来定义的_initialize_weights函数。我们只用了一个隐含层。

# 加性高斯噪声的自动编码
class AdditiveGaussianNoiseAutoencoder(object):
    def __init__(self, n_input, n_hidden, transfer_function=tf.nn.softplus, optimizer=tf.train.AdamOptimizer(),scale=0.1):
        ...#此处为省略

        # model
        self.x = tf.placeholder(tf.float32, [None, self.n_input])
        # none不给定具体的值,它由输入的数目来决定
        self.hidden = self.transfer(tf.add(tf.matmul(self.x + scale * tf.random_normal((n_input,)),self.weights['w1']),self.weights['b1']))
        # 在输入的时候,在输入的数据上加上一些高斯噪声,
        # tf.random_normal((n_input,)) 默认给的是一个均值为0,标准差是1的正态分布的随机数。
        self.reconstruction = tf.add(tf.matmul(self.hidden, self.weights['w2']), self.weights['b2'])

x:一维的数量为n_input的placeholder;

建立一个能提取特征的隐含层:
先对输入x添加高斯噪声,即self.x + scale * tf.random_normal((n_input,));
再用tf.matmul()让被噪声污染的信号与隐藏层的权重相乘,再用tf.add()添加偏置;
最后使用transfer()对加权汇总结果进行激活函数处理。

经过隐藏层后,在输出层进行数据复原和重建操作,即建立reconstruction层,这时候就不需要激活函数了, 直接将隐含层的输出self.hidden乘以输出层的权重w2再加上输出层的偏置b2。

self.cost = 0.5 * tf.reduce_sum(tf.pow(tf.subtract(self.reconstruction, self.x), 2.0))
self.optimizer = optimizer.minimize(self.cost)

init = tf.global_variables_initializer()
self.sess = tf.Session() 
self.sess.run(init)
print("begin ti run session...")

自编码器的损失函数:平方误差损失(重建信号和原始信号的误差平方和)。
使用优化器(由构造函数参数指定,默认是Adam)对损失节点进行优化。
添加初始化节点,初始化所有变量,启动会话,运行初始化节点。

class AdditiveGaussianNoiseAutoencoder(object):
    def __init__(self, n_input, n_hidden, transfer_function=tf.nn.softplus, optimizer=tf.train.AdamOptimizer(),scale=0.1):
        ...#此处为省略

      def _initialize_weights(self):
        all_weights = dict()
        all_weights['w1'] = tf.Variable(xavier_init(self.n_input, self.n_hidden))
        # 在初始化的时候,就只是第一个权重矩阵是赋予一些随机值,其他的都是赋予全0矩阵
        all_weights['b1'] = tf.Variable(tf.zeros([self.n_hidden], dtype=tf.float32))
        all_weights['w2'] = tf.Variable(tf.zeros([self.n_hidden, self.n_input], dtype=tf.float32))
        all_weights['b2'] = tf.Variable(tf.zeros([self.n_input], dtype=tf.float32))
        return all_weights
    #变量初始化函数:创建一个dicts,包含所有Variable类型的变量w1,b1,w2,b2
    #隐藏层:w1用前面写的xavier_init函数初始化,传入输入节点数和隐含节点数,即可得到一个比较适合softplus等激活函数的初始状态,b1初始化为0

产生一个AdditiveGaussianNoiseAutoencoder类的对象实例,调用tf.summary.FileWriter把计算图写入文件,使用TensorBoard查看

AGN_AC = AdditiveGaussianNoiseAutoencoder(n_input=784,n_hidden=200,
transfer_function=tf.nn.softplus,optimizer=tf.train.AdamOptimizer(learning_rate=0.01),scale=0.01)

print('把计算图写入事件文件,在TensorBoard里面查看')
writer = tf.summary.FileWriter(logdir='logs',graph=AGN_AC.sess.graph)
writer.close()

计算图如下:
这里写图片描述

附上代码:

import numpy as np
import sklearn.preprocessing as prep
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

# Xvaier均匀初始化
# fan_in是输入节点的数量,fan_out是输出节点的数量。
def xavier_init(fan_in, fan_out, constant=1):
    low = -constant * np.sqrt(6.0 / (fan_in + fan_out))
    high = constant * np.sqrt(6.0 / (fan_in + fan_out))
    return tf.random_uniform((fan_in, fan_out), minval=low, maxval=high, dtype=tf.float32)

# 加性高斯噪声的自动编码
class AdditiveGaussianNoiseAutoencoder(object):
    # 在初始的数据中加入高斯噪声。在实现降噪自编码器的时候,
    # 只是在输入加进去的时候,在输入上加上高斯噪声就行
    # 其他的部分和基本自编码器一样
    # n_input:输入变量数;n_hidden:隐含层节点数;transfer_function:隐含层激活函数;optimizer:优化器;scale:高斯噪声系数;
    # Class内的scale声明成一个占位符placeholder,参数初始化则使用了接下来定义的_initialize_weights函数。我们只用了一个隐含层。
    def __init__(self, n_input, n_hidden, transfer_function=tf.nn.softplus, optimizer=tf.train.AdamOptimizer(),
                 scale=0.1):
        self.n_input = n_input
        self.n_hidden = n_hidden
        # n_input,n_hidden都是输入和隐藏层的维度
        self.transfer = transfer_function
        self.scale = tf.placeholder(tf.float32)
        self.training_scale = scale
        # scale 就是一个标量
        network_weights = self._initialize_weights()
        self.weights = network_weights

        # model
        self.x = tf.placeholder(tf.float32, [None, self.n_input])
        # none不给定具体的值,它由输入的数目来决定
        self.hidden = self.transfer(
            tf.add(tf.matmul(self.x + scale * tf.random_normal((n_input,)), self.weights['w1']), self.weights['b1']))
        # 在输入的时候,在输入的数据上加上一些高斯噪声,
        # tf.random_normal((n_input,)) 默认给的是一个均值为0,标准差是1的正态分布的随机数。

        self.reconstruction = tf.add(tf.matmul(self.hidden, self.weights['w2']), self.weights['b2'])

        # x:一维的数量为n_input的placeholder;
        # 建立一个能提取特征的隐含层:
        # 先对输入x添加高斯噪声,即self.x + scale * tf.random_normal((n_input,));
        #  再用tf.matmul()让被噪声污染的信号与隐藏层的权重相乘,再用tf.add()添加偏置;
        # 最后使用transfer()对加权汇总结果进行激活函数处理。

        # 经过隐藏层后,在输出层进行数据复原和重建操作,即建立reconstruction层,这时候就不需要激活函数了,
        # 直接将隐含层的输出self.hidden乘以输出层的权重w2再加上输出层的偏置b2。

        # cost
        self.cost = 0.5 * tf.reduce_sum(tf.pow(tf.subtract(self.reconstruction, self.x), 2.0))
        self.optimizer = optimizer.minimize(self.cost)

        init = tf.global_variables_initializer()
        self.sess = tf.Session()
        self.sess.run(init)
        print("begin ti run session...")


    def _initialize_weights(self):
        all_weights = dict()
        all_weights['w1'] = tf.Variable(xavier_init(self.n_input, self.n_hidden))
        # 在初始化的时候,就只是第一个权重矩阵是赋予一些随机值,其他的都是赋予全0矩阵
        all_weights['b1'] = tf.Variable(tf.zeros([self.n_hidden], dtype=tf.float32))
        all_weights['w2'] = tf.Variable(tf.zeros([self.n_hidden, self.n_input], dtype=tf.float32))
        all_weights['b2'] = tf.Variable(tf.zeros([self.n_input], dtype=tf.float32))
        return all_weights
    #变量初始化函数:创建一个dicts,包含所有Variable类型的变量w1,b1,w2,b2
    #隐藏层:w1用前面写的xavier_init函数初始化,传入输入节点数和隐含节点数,即可得到一个比较适合softplus等激活函数的初始状态,b1初始化为0

#产生一个AdditiveGaussianNoiseAutoencoder类的对象实例,调用tf.summary.FileWriter把计算图写入文件,使用TensorBoard查看
AGN_AC = AdditiveGaussianNoiseAutoencoder(n_input=784,n_hidden=200,transfer_function=tf.nn.softplus,optimizer=tf.train.AdamOptimizer(learning_rate=0.01),scale=0.01)

print('把计算图写入事件文件,在TensorBoard里面查看')
writer = tf.summary.FileWriter(logdir='logs',graph=AGN_AC.sess.graph)
writer.close()

关于Xavier Initialization,参考以下:
http://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf
https://www.leiphone.com/news/201703/3qMp45aQtbxTdzmK.html
http://blog.csdn.net/shuzfan/article/details/51338178

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值