《tensorflow》实战学习笔记(一)——实现自编码器

1 自编码器简介

        传统的机器学习很大程度上依赖于好的特征工程,比如对数值型,日期时间型,种类型等特征的提取,特征工程往往是非常耗时耗力的。尤其是在图像,语音和视频中提取到有效的特征就更难了。深度学习则可以解决人工难以提取有效特征的问题,它可以大大缓解机器学习模型对特征工程的依赖。深度学习早期一度被认为是一种无监督的特征学习。模仿了人脑的特征逐层抽象提取的过程。这其中有两点很重要:一是无监督学习,即不需要标注数据就可以对数据进行一定程度的学习,这种学习是对数据内容的组织形式的学习,提取的是频繁出现的特征;二是逐层抽取,特征是需要不断抽象的,就像人总是从简单基础的概念开始学习,再到复杂的概念。
        自编码器是一种能够通过无监督学习,学到输入数据高效表示的人工神经网络。输入数据的这一高效表示称为编码,其维度一般远小于输入数据,使得自编码器可用于降维。更重要的是,自编码器可作为强大的特征检测器(feature detectors),应用于深度神经网络的预训练。此外,自编码器还可以随机生成与训练数据类似的数据,这被称作生成模型(generative model)。

2 tensorflow实现自编码器

        去噪自编码器的使用范围最广也最通用。因此本节实现的是最具代表性的去噪自编码器。

import numpy as np
import sklearn.preprocessing as prep
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 参数初始化方法,Xavier初始化器在Caffe的早期版本中被频繁使用,它的特点是会根据某一层网络的输入输出节点数量自动调整最合适的分布
# 如果深度学习模型的权重初始化的太小,那信号将在每层间传递时竹间缩小而难以产生作用;如果权重初始化得太大,那信号将在每层间传递时逐渐放大并导致发散和失效。
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_weights = self._initialize_weights()
        self.weights = network_weights

        # 定义网络结构
        self.x = tf.placeholder(tf.float32, [None, self.n_input])
        self.hidden = self.transfer(tf.add(tf.matmul(
            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'])

        # 定义自编码器的损失函数
        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)

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

    # 用一个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

    # 自编码器训练完毕后,在测试集上对模型性能进行评测时求损失的函数
    def calc_total_cost(self, X):
        return self.sess.run(self.cost, feed_dict={self.x:X, self.scale:self.training_scale})

    # 返回自编码器隐含层的输出结果,目的是提供一个接口来获取抽象后的特征,自编码器的隐含层的最主要功能就是学习出数据中的高阶特征。
    def transfrom(self, X):
        return self.sess.run(self.hidden, feed_dict={self.x:X, self.scale:self.training_scale})

    # 将隐含层的输出结果作为输入,通过之后的重建层将提取到高阶特征复原为原始数据。
    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, self.scale:self.training_scale})

    # 获取隐含层权重
    def getWeights(self):
        return self.sess.run(self.weights['w1'])

    # 获取隐含层的偏执系数b1
    def getBiases(self):
        return self.sess.run(self.weights['b1'])

# 利用mnist数据集进行性能测试
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

# 定义一个对训练/训练数据进行标准化处理的函数,标准化即让数据变成0均值,且标准差为1的分布。
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数据的函数(不放回抽样,可提高数据的利用效率)
def get_random_block_from_data(data, batch_size):
    start_index = np.random.randint(0, len(data)-batch_size)
    return data[start_index:(start_index+batch_size)]


X_train, X_test = standard_scale(mnist.train.images, mnist.test.images)
n_samples = int(mnist.train.num_examples)
training_epochs = 20
batch_size = 128
display_step = 1

# 创建一个AGN自编码器的实例
autoencoder = AdditiveGaussianNoiseAutoencoder(n_input=784,
                                               n_hidden=200,
                                               transfer_function=tf.nn.softplus,
                                               optimizer=tf.train.AdamOptimizer(learning_rate=0.001),
                                               scale=0.01)
# 开始训练
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_data(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))

print("Total cost:"+str(autoencoder.calc_total_cost(X_test)))

参考:
[1]: https://www.cnblogs.com/royhoo/p/Autoencoders.html
(x_x)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值