代码:
import numpy as np
import sklearn.preprocessing as prep
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
##均匀分布的Xaiver初始化器
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
class 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
self.transfer = transfer_function
self.scale = tf.placeholder(tf.float32)
self.training_scale = scale
network_wegihts = self._initialize_weights()
self.weights =network_wegihts
#接下来开始定义网络结构
#为输入x创建一个维度为n_input的placeholder
self.x = tf.placeholder(tf.float32,[None,self.n_input])
#简历一个能提取特征的隐含层
self.hidden = self.transfer(tf.add(tf.matmul(
# 将x加上 噪声
self.x+scale * tf.random_normal((n_input,)),
self.weights['w1']),self.weights['b1']))
self.reconstruction = tf.add(tf.matmul(self.hidden,
self.weights['w2']),
self.weights['b2'])
##接下来定义自编码器的损失函数,这里直接使用平方误差作为cost
#用tf.subtact计算输出和输入只差
#使用tf.pow求差的平方,最后使用reduce_sum求和即可得到平方误差
self.cost = 0.5 * tf.reduce_sum(tf.pow(tf.subtract(
self.reconstruction,self.x),2.0))
#在定义训练操作为优化器self.optimizer对损失self.cost进行优化
self.optimizer = optimizer.minimize(self.cost)
#最后创建session,并且初始化自编码器的全部模型参数
init = tf.global_variables_initializer()
self.sess = tf.Session()
self.sess.run(init)
#下面再来看一下参数初始化函数_initialize_weights
def _initialize_weights(self):
#先创建一个名为all_weights的字典dict
all_weight = dict()
#然后将w1,b1,w2,b2全部存入其中
all_weight['w1']=tf.Variable(xavier_init(self.n_input,
self.n_hidden))
all_weight['b1'] = tf.Variable(tf.zeros([self.n_hidden],
dtype = tf.float32))
all_weight['w2'] = tf.Variable(tf.zeros([self.n_hidden,
self.n_input],
dtype = tf.float32))
all_weight['b2'] = tf.Variable(tf.zeros([self.n_input],
dtype = tf.float32))
#最后染回all_weights
return all_weight
#我们定义计算损失cost及执行一步训练的函数partial_fit
#函数里只需要让Session执行两个计算图的节点,分别是算是cost和训练过程optimizer
#输入的feed_dict包括输入数据x以及噪声的稀疏scale
#函数partial_fit做的就是用一个batch数据进行训练并且返回当前的损失cost
def partial_fit(self,X):
cost ,opt = self.sess.run((self.cost,self.optimizer),
feed_dict={self.x: X, self.scale: self.training_scale})
return cost
#我们也只需要一个只求损失cost的函数calc_total_cost
#这里就只让Session执行一个计算图节点self.cost
#传入的参数和前面的partial_fit一直
#这个函数是在自编码器训练完毕之后,在测试集上对模型性能进行评测会用到的
#它不会像partial_fit那样出发训练操作
def calc_total_cost(self,X):
return self.sess.run(self.cost,feed_dict = {self.x:X,
self.scale:self.training_scale})
#我们还定义了transform函数,它范湖自编码器隐含层的输出结果
#目的是提供一个借口来获取抽象后的特征,自编码器的隐含层的最主要功能就
#是学习出数据中的高阶特征
def transform(self,X):
return self.sess.run(self.hidden,feed_dict = {self.x:X,
self.scale:self.training_scale})
#我们再定义generate函数,它将隐含层的输出结果作为输入,通过之后
#的重建层就提取到的高阶特征复原为原始数据。
#这个借口和前面的transform正好将整个自编码器拆分为两个部门
#这里的generate接口是后半部门,将高阶特征复原成原始数据的步骤
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})
#接下来定义reconstruct函数,它整体运行一遍复原过程,包括提取高阶特征
#和通过高阶特征复原数据,即包括transform和generate凉快
#输入数据是原数据,输出数据是复原后的数据
def reconstruct(self,X):
return self.sess.run(self.reconstruction,feed_dict ={self.x:X,
self.scale:self.training_scale})
#这里的getWeights函数作用his获取隐含层的权重w1
def getWegiths(self):
return self.sess.run(self.weights['w1'])
#getBiases函数则是获取隐含层的偏置系数b1
def getBiases(self):
return self.sess.run(self.weights['b1'])
#至此,去噪自编码器的class就全部定义玩了,包括神经网络的设计
#权重的初始化
#接下来依然使用TensorFlow提供的读取示例数据的函数载入MNIST数据集
mnist = input_data.read_data_sets("MNIST_data/", False, one_hot=True)
def standard_scale(X_train,X_test):
preprocessor = prep.StandardScaler().fit(X_train)
X_train = preprocessor.transform(X_train)
X_test = preprocessor.transform(X_test)
return X_train,X_test
#在定义一个获取随机block数据的函数:取一个从0到len(data)-batch_size
#之间的随机证书,再以这个随机数作为block的起始位置,然后顺序渠道一个batch_size的数据
#需要注意的是,这属于不放回抽样,可以提高数据的利用效率
def get_random_block_from_date(data,batch_size):
start_index = np.random.randint(0,len(data)-batch_size)
return data[start_index:(start_index+batch_size)]
#使用之前定义的standard_scale函数对训练集,测试集进行标准化变换
X_train,X_test = standard_scale(mnist.train.images,mnist.test.images)
#接下来定义几个常用参数,总训练书样本数,最大的训练的轮数(epoch)为20
#batch_size设为128,并设置每隔一轮 epoch 就显示一次损失cost
n_samples = int(mnist.train.num_examples)
training_epochs = 20
batch_size = 128
display_step = 1
#创建一个AGN自编码器的示例,定义模型输入节点数n_input为784
#自编码器的隐含层节点数n_hidden为200
#隐含层的激活函数transfer_function为softplus
#优化器optimizer为Adam且学习速率为0.001,同时将噪声的稀疏scale设为0.01
autoencoder = AdditiveGaussianNoiseAutoencoder(n_input=784,
n_hidden= 200,
transfer_function=tf.nn.softplus,
optimizer=tf.train.AdamOptimizer(learning_rate=0.001),
scale=0.1)
#下面开始训练过程,在每一轮循环开始时,我们将平均损失avg_cost设为0
#并且计算总共需要的batch数,注意这里使用的是不放回抽样,所以并不能保证
#每个样本都被抽到并且参加训练。
#然后在每一次循环中,先使用get_random_block_from_data函数随机抽到一个block
#然后使用成员函数partial_fit训练这个batch的数据并且计算当前的cost
#最后将当前的cost正和岛avg_cost中。
#在每一轮的迭代之后,显示当前的迭代数和这一轮迭代的平均cost
#我们在第一轮迭代时,cost大约是19000,在最后一轮迭代时,cost大约为7000
#再接着训练cost也很难继续降低了
for epoch in range(training_epochs):
avg_cost = 0.
total_batch = int(n_samples/batch_size)
for i in range(total_batch):
batch_xs = get_random_block_from_date(X_train,batch_size)
cost = autoencoder.partial_fit(batch_xs)
avg_cost += cost / n_samples*batch_size
if epoch % display_step ==0:
print("Epoch:",'%04d' % (epoch + 1),"cost=",
"{:.9f}".format(avg_cost))
#最后对训练完的模型进行性能测试
#这里使用之前定义的成员函数cal_total_cost对测试机X_tst进行测试
print("Total cost:" + str(autoencoder.calc_total_cost(X_test)))
结果输出:
Epoch: 0001 cost= 18638.076740909
Epoch: 0002 cost= 13241.218212500
Epoch: 0003 cost= 10876.398575000
Epoch: 0004 cost= 10911.524663636
Epoch: 0005 cost= 9740.812732386
Epoch: 0006 cost= 10174.114690341
Epoch: 0007 cost= 9456.718578409
Epoch: 0008 cost= 9387.242152841
Epoch: 0009 cost= 9165.076931818
Epoch: 0010 cost= 9166.083271591
Epoch: 0011 cost= 8543.039659091
Epoch: 0012 cost= 8987.161418182
Epoch: 0013 cost= 8467.093871023
Epoch: 0014 cost= 8143.928632955
Epoch: 0015 cost= 8076.231632955
Epoch: 0016 cost= 8216.031440909
Epoch: 0017 cost= 8471.644106818
Epoch: 0018 cost= 8246.171704545
Epoch: 0019 cost= 8256.087601136
Epoch: 0020 cost= 8158.641851136
Total cost:671721.44