发布于 

tensorflow笔记(8)

####非监督学习 Autoencoder

今天我们会来聊聊用神经网络如何进行非监督形式的学习. 也就是 autoencoder, 自编码.

自编码 autoencoder 是一种什么码呢. 他是不是 条形码? 二维码? 打码? 其中的一种呢? NONONONO. 和他们统统没有关系. 自编码是一种神经网络的形式.如果你一定要把他们扯上关系, 我想也只能这样解释啦.

原来有时神经网络要接受大量的输入信息, 比如输入信息是高清图片时, 输入信息量可能达到上千万, 让神经网络直接从上千万个信息源中学习是一件很吃力的工作. 所以, 何不压缩一下, 提取出原图片中的最具代表性的信息, 缩减输入信息量, 再把缩减过后的信息放进神经网络学习. 这样学习起来就简单轻松了. 所以, 自编码就能在这时发挥作用. 通过将原数据白色的X 压缩, 解压 成黑色的X, 然后通过对比黑白 X ,求出预测误差, 进行反向传递, 逐步提升自编码的准确性. 训练好的自编码中间这一部分就是能总结原数据的精髓. 可以看出, 从头到尾, 我们只用到了输入数据 X, 并没有用到 X 对应的数据标签, 所以也可以说自编码是一种非监督学习. 到了真正使用自编码的时候. 通常只会用到自编码前半部分.

编码器 Encoder

编码器能得到原数据的精髓, 然后我们只需要再创建一个小的神经网络学习这个精髓的数据,不仅减少了神经网络的负担, 而且同样能达到很好的效果.

他能从原数据中总结出每种类型数据的特征, 如果把这些特征类型都放在一张二维的图片上, 每种类型都已经被很好的用原数据的精髓区分开来. 如果你了解 PCA 主成分分析, 再提取主要特征时, 自编码和它一样,甚至超越了 PCA. 换句话说, 自编码 可以像 PCA 一样 给特征属性降维.

解码器 Decoder

至于解码器 Decoder, 我们也能那它来做点事情. 我们知道, 解码器在训练的时候是要将精髓信息解压成原始信息, 那么这就提供了一个解压器的作用, 甚至我们可以认为是一个生成器 (类似于GAN). 那做这件事的一种特殊自编码叫做 variational autoencoders, 你能在这里找到他的具体说明.

Autoencoder

Autoencoder 简单来说就是将有很多Feature的数据进行压缩,之后再进行解压的过程。 本质上来说,它也是一个对数据的非监督学习,如果大家知道 PCA (Principal component analysis), 与 Autoencoder 相类似,它的主要功能即对数据进行非监督学习,并将压缩之后得到的“特征值”,这一中间结果正类似于PCA的结果。 之后再将压缩过的“特征值”进行解压,得到的最终结果与原始数据进行比较,对此进行非监督学习。如果大家还不是非常了解,请观看机器学习简介系列里的 Autoencoder 那一集; 如果对它已经有了一定的了解,那么便可以进行代码阶段的学习了。大概过程如下图所示:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("tmp/data/", one_hot=False)

learning_rate = 0.01
training_epochs = 5  #五组训练
batch_size = 256
display_step = 1
examples_to_show = 10

# 我们的MNIST数据,每张图片大小是28x28 pix,即 784 Feature
# Network Parameters
n_input = 784  # MNIST data input (img shape: 28*28)
# tf Graph input (only pictures)
X = tf.placeholder("float", [None, n_input])

# 在压缩环节:我们要把这个Features不断压缩,
# 经过第一个隐藏层压缩至256个 Features,再经过第二个隐藏层压缩至128个。
# 在解压环节:我们将128个Features还原至256个,再经过一步还原至784个。
# 在对比环节:比较原始数据与还原后的拥有 784 Features 的数据进行 cost 的对比,
# 根据 cost 来提升我的 Autoencoder 的准确率,下图是两个隐藏层的 weights 和 biases 的定义:

# hidden layer settings
n_hidden_1 = 256  # 1sr layer num features
n_hidden_2 = 128  # 2nd layer num features
weights = {
    'encoder_h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
    'encoder_h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
    'decoder_h1': tf.Variable(tf.random_normal([n_hidden_2, n_hidden_1])),
    'decoder_h2': tf.Variable(tf.random_normal([n_hidden_1, n_input])),
}
biases = {
    'encoder_b1': tf.Variable(tf.random_normal([n_hidden_1])),
    'encoder_b2': tf.Variable(tf.random_normal([n_hidden_2])),
    'decoder_b1': tf.Variable(tf.random_normal([n_hidden_1])),
    'decoder_b2': tf.Variable(tf.random_normal([n_input])),
}

# 下面来定义Encoder和Decoder,使用的Activiation function是
# sigmoid, 压缩之后的值应该在[0,1]这个范围内。
# 在decoder过程中,通常使用对应与encoder的Activation function:


# Building the encoder
def encoder(x):
    # Encoder Hidden layer with sigmoid activation #1
    layer_1 = tf.nn.sigmoid(
        tf.add(tf.matmul(x, weights['encoder_h1']), biases['encoder_b1']))
    # Decoder Hidden layer with sigmoid activation #2
    layer_2 = tf.nn.sigmoid(
        tf.add(
            tf.matmul(layer_1, weights['encoder_h2']), biases['encoder_b2']))
    return layer_2


# Building the decoder
def decoder(x):
    # Encoder Hidden layer with sigmoid activation #1
    layer_1 = tf.nn.sigmoid(
        tf.add(tf.matmul(x, weights['decoder_h1']), biases['decoder_b1']))
    # Decoder Hidden layer with sigmoid activation #2
    layer_2 = tf.nn.sigmoid(
        tf.add(
            tf.matmul(layer_1, weights['decoder_h2']), biases['decoder_b2']))
    return layer_2


# 来实现 Encoder 和 Decoder 输出的结果:
# Construct model
encoder_op = encoder(X)  # 128 Features
decoder_op = decoder(encoder_op)  # 784 Features

# Prediction
y_pred = decoder_op  # After
# Targets (Labels) are the input data.
y_true = X  # Before

#再通过我们非监督学习进行对照,
# 即对 “原始的有 784 Features 的数据集” 和 “通过 ‘Prediction’
# 得出的有 784 Features 的数据集” 进行最小二乘法的计算,
# 并且使 cost 最小化:

# Define loss and optimizer, minimize the squared error
cost = tf.reduce_mean(tf.pow(y_true - y_pred, 2))
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)

# 最后,通过Matplotlib的pyplot模块将结果显示出来,
# 注意在输出时MNIST数据集经过压缩之后x的最大值是1,而非255

# Launch the graph
with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())
    total_batch = int(mnist.train.num_examples / batch_size)
    # Training cycle
    for epoch in range(training_epochs):
        # Loop over all batches
        for i in range(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            # Run optimization op (backprop) and cost op (to get loss value)
            _, c = sess.run([optimizer, cost], feed_dict={X: batch_xs})
            # Display logs per epoch step
            if epoch % display_step == 0:
                print('Epoch:', '%04d' % (epoch + 1), 'cost=',
                      '{:.9f}'.format(c))

    print('Optimization Finished!')

    # # Applyinh encode and decode over test set
    encode_decode = sess.run(
        y_pred, feed_dict={
            X: mnist.test.images[:examples_to_show]
        })
    # Compare original imamges with their reconstructions
    f, a = plt.subplots(2, 10, figsize=(10, 2))
    for i in range(examples_to_show):
        a[0][i].imshow(np.reshape(mnist.test.images[i], (28, 28)))
        a[1][i].imshow(np.reshape(encode_decode[i], (28, 28)))
    plt.show()

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 @shyiuanchen 创建,使用 Stellar 作为主题。