您的位置:首页 > 理论基础 > 计算机网络

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

2017-03-17 16:19 483 查看
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)


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  神经网络 算法