tensorflow 实现基本AutoEncoder,降噪自编码器

Auto-Encoder(AE)是20世纪80年代晚期提出的,它是一种无监督学习算法,使用了反向传播算法,让目标值等于输入值。基本的AE可视为一个三层神经网络结构:一个输入层、一个隐藏层和一个输出层,其中输出层与输入层具有相同的规模。

AE最初是作为一个降维手段来进行的,要是编码器那里没有使用非线性部分,那么就可以等价为PCA算法来使用。(初始的维数大于编码器输出的维数的时候)

而现在编码器的输出维数大于输入的维数(over-complete setting),获取更高维,更加有意义的表示。

AE有一个问题就是要是直接对上面的损失函数(平方误差或者交叉熵)进行训练的话,很可能就会得到一个恒等函数。解决此问题的常用的一些方法,有在损失函数里面引入稀疏性(sparse AE),或者在网络中引入随机性(如RBM,Denoising AE)。

 

标准自编码器(在基本的自编码器里面引入正则化项就行,一般是L1或者L2正则化项。)

标准自编码器实则是对权重的设置提出要求,限制权重,避免过大



最左边的是一个输入层,中间是隐藏层,最右边是输出层,输出层的神经元数量完全等于输入层神经元的数量。隐藏层的神经元数量少于输出层。 自编码网络的作用是,将输入样本压缩到隐藏层,再在输出端重建样本。其目标是使输出和输入之间尽量的小。

神经网络权重矩阵的初始化,经验之谈,xaviar initialization。如果权重初始化得太小,那信号在每层间传递是逐渐缩小而难以产生作用,但是如果权重初始化得太大,那信号将在每层间逐渐放大并且导致发散和失效。xaviar initialization就是让均值满足为0,方差是

损失函数:

实现基本自编码器

# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
import Utils

class Autoencoder(object):

    def __init__(self, n_input, n_hidden, transfer_function=tf.nn.softplus, optimizer = tf.train.AdamOptimizer()):
        # softplus: ln(exp(x) + 1) 它的倒数就是sigmoid函数,它限制左边始终大于0,右边没有限制
        self.n_input = n_input
        self.n_hidden = n_hidden
        self.transfer = transfer_function

        network_weights = self._initialize_weights()
        self.weights = network_weights

        # model
        # n_input 指的是输入的维度
        self.x = tf.placeholder(tf.float32, [None, self.n_input])
        self.hidden = self.transfer(tf.add(tf.matmul(self.x, self.weights['w1']), self.weights['b1']))
        # 将隐藏层的输出限制在大于0的空间里面,
        # 这就是一个非线性环节,只限制左端,并没有限制右端
        self.reconstruction = tf.add(tf.matmul(self.hidden, self.weights['w2']), self.weights['b2'])
        # 在这里重构结果,只是隐藏环节的一个线性变换,
        # 并没有加上任何非线性的环节,所以后面求重构误差的时候,
        # 直接使用均方误差就行(因为这里并没有使用非线性环节进行归一化,要是使用了,可以利用交叉熵)

        # cost
        self.cost = 0.5 * tf.reduce_sum(tf.pow(tf.sub(self.reconstruction, self.x), 2.0))
        # 做减法,然后平方,这里使用的是重构误差最小,使用均方误差
        self.optimizer = optimizer.minimize(self.cost)

        init = tf.initialize_all_variables()
        self.sess = tf.Session()
        self.sess.run(init)


    def _initialize_weights(self):
        all_weights = dict()
        all_weights['w1'] = tf.Variable(Utils.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

    def partial_fit(self, X):
        cost, opt = self.sess.run((self.cost, self.optimizer), feed_dict={self.x: X})
        return cost

    def calc_total_cost(self, X):
        return self.sess.run(self.cost, feed_dict = {self.x: X})

    def transform(self, X):
        # 这个函数在整个自编码器训练好了之后,使用它可以将原始数据进行编码,得到的结果就是编码形式
        return self.sess.run(self.hidden, feed_dict={self.x: X})

    def generate(self, hidden = None):
        # 这部分就是解码函数,用作解码用
        if hidden is None:
            hidden = np.random.normal(size=self.weights["b1"])
        return self.sess.run(self.reconstruction, feed_dict={self.hidden: hidden})

    def reconstruct(self, X):
        # 先进行编码,然后进行解码,得到的最后结果
        return self.sess.run(self.reconstruction, feed_dict={self.x: X})

    def getWeights(self):
        # 得到编码用的权值矩阵
        return self.sess.run(self.weights['w1'])

    def getBiases(self):
        # 得到编码器的偏重值
        return self.sess.run(self.weights['b1'])
降噪自编码器
emptyclass AdditiveGaussianNoiseAutoencoder(object):
    # 在初始的数据中加入高斯噪声。在实现降噪自编码器的时候,
    # 只是在输入加进去的时候,在输入上加上高斯噪声就行
    # 其他的部分和基本自编码器一样
    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'])

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

        init = tf.initialize_all_variables()
        self.sess = tf.Session()
        self.sess.run(init)
        
        
        
        
class MaskingNoiseAutoencoder(object):
    # 将有些数据直接忽略掉,即直接将一部分数据直接赋予0
    def __init__(self, n_input, n_hidden, transfer_function = tf.nn.softplus, optimizer = tf.train.AdamOptimizer(),
                 dropout_probability = 0.95):
        self.n_input = n_input
        self.n_hidden = n_hidden
        self.transfer = transfer_function
        self.dropout_probability = dropout_probability
        self.keep_prob = tf.placeholder(tf.float32)

        network_weights = self._initialize_weights()
        self.weights = network_weights

        # model
        # 直接在输入数据上使用dropout来实现它,这样就实现了masking noise
        self.x = tf.placeholder(tf.float32, [None, self.n_input])
        self.hidden = self.transfer(tf.add(tf.matmul(tf.nn.dropout(self.x, self.keep_prob), self.weights['w1']),
                                           self.weights['b1']))
        self.reconstruction = tf.add(tf.matmul(self.hidden, self.weights['w2']), self.weights['b2'])

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

        init = tf.initialize_all_variables()
        self.sess = tf.Session()
        self.sess.run(init)









 

















猜你喜欢

转载自blog.csdn.net/hwang4_12/article/details/62890569