参考这篇:https://www.zhihu.com/question/41490383
顺带一说,最高票答主的回答质量都挺高的,值得关注。
环境:macOS-10.13.4, Python-3.6, Tensorflow-1.4.1
自编码器AE
先直接看一下它的网络结构吧:
它可以简单的分为两个结构,左边的叫做Encoder,俗称编码器,右边的叫做Decoder,俗称解码器。
我们需要的不是它的输出层,而是中间的那一层,所以它到底是怎么工作的呢?
首先它是用来干嘛的?
它是一种【无监督学习】,不需要标签的,比如上面那个网络,直接从输入层输入一亿个四元向量,然后进入隐含层的两个节点进行计算,再输出四个输出节点,我们希望,【输出与输入越接近越好】,那么,中间的两个节点所表示的,其实就可以描述为特征。
所以它就是用来提取特征用的。
再举一个跟神经网络无关的例子,LED屏上的数字,七根火柴棍就可以描述出来0-9十个数字。换句话说就是十个数字可以拆成七个具有【0,1】状态的特征,这些特征通过一定的顺序又可以组合成原来的十个数字。
而现实中的很多东西也一样,比如小猫的脸的照片,有眼睛,鼻子,嘴巴,脸上的毛等等等,如果我们构造一个三层神经网络,让输出的图片尽量的和输入的相同,隐藏的层的节点数小于输入层,那么我们拿到隐藏层后,在很大程度上是可以复现出原来的照片的,这是不是很神奇呢。
提取特征换句话说类似于降维或者提取主成分,但又不相同的,AE是一种非常好的模型去完成这个。
那么回到之前的网络结构,Encoder就是输入层到隐含层的过程,Decoder就是隐含层到输出层的过程,是不是现在大致就能够理解了。编码指的是提取输入的东西的特征,看能不能找到一些可以共同描述这些输入的东西,解码就是通过找到的特征再重新组合,看能不能尝试把输入的东西再拼回来。
根据《Tensorflow实战》中的讲解,这个思路最原始是来自于摄影。有人发现把一张风景照片剪成8*8的64份后,再换个顺序或者和别的同类型的照片的碎片进行拼一拼,又能拼出来一些比较好看的照片。
它用的也是bp算法进行反向传播从而使用optimizer降低loss。
稀疏自编码器Sparse Auto Encoder
我们希望的是自编码器的隐藏节点不要太多,同时在一次运算里,被激活的节点也要远远小于被抑制的节点,否则就会出现一些直接拷贝输入层的内容呀等等的奇怪的现象。这个可以使用相对熵来控制,在最上面的参考中有比较详细的说明,这里不再赘述。
降噪自编码器Denosing Auto Encoder
神经网络都是对输入比较敏感的,如果有噪声的话,AE要尽量去掉噪声增强鲁棒性,一般我们可以梯度下降来解决。同样最上面的参考中有详细的说明,这里不再赘述。
其他
别的关于AE也没有什么好说的,看了我的第二篇深度学习的文章的话,并且下了Tensorflow和matplotlib,就直接运行一下下面的代码试试把,直接对MNIST手写数字集上做的一个AE,最后显示的是在二维坐标上的聚类效果,想做科研的朋友可以多试试这段代码。代码来源:https://blog.csdn.net/marsjhao/article/details/68950697
import tensorflow as tf
import matplotlib.pyplot as plt
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=False)
learning_rate = 0.01
training_epochs = 10
batch_size = 256
display_step = 1
n_input = 784
X = tf.placeholder("float", [None, n_input])
n_hidden_1 = 128
n_hidden_2 = 64
n_hidden_3 = 10
n_hidden_4 = 2
weights = {
'encoder_h1': tf.Variable(tf.truncated_normal([n_input, n_hidden_1],)),
'encoder_h2': tf.Variable(tf.truncated_normal([n_hidden_1, n_hidden_2],)),
'encoder_h3': tf.Variable(tf.truncated_normal([n_hidden_2, n_hidden_3],)),
'encoder_h4': tf.Variable(tf.truncated_normal([n_hidden_3, n_hidden_4],)),
'decoder_h1': tf.Variable(tf.truncated_normal([n_hidden_4, n_hidden_3],)),
'decoder_h2': tf.Variable(tf.truncated_normal([n_hidden_3, n_hidden_2],)),
'decoder_h3': tf.Variable(tf.truncated_normal([n_hidden_2, n_hidden_1],)),
'decoder_h4': tf.Variable(tf.truncated_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])),
'encoder_b3': tf.Variable(tf.random_normal([n_hidden_3])),
'encoder_b4': tf.Variable(tf.random_normal([n_hidden_4])),
'decoder_b1': tf.Variable(tf.random_normal([n_hidden_3])),
'decoder_b2': tf.Variable(tf.random_normal([n_hidden_2])),
'decoder_b3': tf.Variable(tf.random_normal([n_hidden_1])),
'decoder_b4': tf.Variable(tf.random_normal([n_input])),
}
def encoder(x):
layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['encoder_h1']),
biases['encoder_b1']))
layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['encoder_h2']),
biases['encoder_b2']))
layer_3 = tf.nn.sigmoid(tf.add(tf.matmul(layer_2, weights['encoder_h3']),
biases['encoder_b3']))
# 为了便于编码层的输出,编码层随后一层不使用激活函数
layer_4 = tf.add(tf.matmul(layer_3, weights['encoder_h4']),
biases['encoder_b4'])
return layer_4
def decoder(x):
layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['decoder_h1']),
biases['decoder_b1']))
layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['decoder_h2']),
biases['decoder_b2']))
layer_3 = tf.nn.sigmoid(tf.add(tf.matmul(layer_2, weights['decoder_h3']),
biases['decoder_b3']))
layer_4 = tf.nn.sigmoid(tf.add(tf.matmul(layer_3, weights['decoder_h4']),
biases['decoder_b4']))
return layer_4
encoder_op = encoder(X)
decoder_op = decoder(encoder_op)
y_pred = decoder_op
y_true = X
cost = tf.reduce_mean(tf.pow(y_true - y_pred, 2))
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)
with tf.Session() as sess:
# tf.initialize_all_variables() no long valid from
# 2017-03-02 if using tensorflow >= 0.12
if int((tf.__version__).split('.')[1]) < 12 and int((tf.__version__).split('.')[0]) < 1:
init = tf.initialize_all_variables()
else:
init = tf.global_variables_initializer()
sess.run(init)
total_batch = int(mnist.train.num_examples/batch_size)
for epoch in range(training_epochs):
for i in range(total_batch):
batch_xs, batch_ys = mnist.train.next_batch(batch_size) # max(x) = 1, min(x) = 0
_, c = sess.run([optimizer, cost], feed_dict={X: batch_xs})
if epoch % display_step == 0:
print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(c))
print("Optimization Finished!")
encoder_result = sess.run(encoder_op, feed_dict={X: mnist.test.images})
plt.scatter(encoder_result[:, 0], encoder_result[:, 1], c=mnist.test.labels)
plt.colorbar()
plt.show()