(文章编辑bug太多,白码字了,只能简化说了。)通过encoder-decoder的结构形成一个负、正金字塔的瓶颈结构(必须是瓶颈结构,才能起到压缩的效果,不然就成了复制了),对数据进行压缩并还原,以还原程度为指标来训练网络。训练完网络就有了一个encoder和decoder,decoder先不管,encoder能把数据压缩,因为压缩还能还原,证明原数据有冗余,压缩后的code可以直接用来分类,而不是直接用原数据。所以在encoder后边接一个分类器就能完成分类工作。(如果你要进行分类工作,当你训练完auto-encoder,decoder应该是没有用的,下边会说)
结构示意
++++++++++++ input
++++++ encoder
+++ code
++++++ decoder
++++++++++++ output
下边放一个示意图:
如果要直观的解释auto-encoder实现了什么功能,如何实现,如果说压缩到z之后信息已经损失了,为什么还要恢复到x^?况且,本来最后也用不到decoder?
可以这样说,encoder把成绩从100~0分成了优良中差,既然z是瓶颈,恢复到x^时确实已经丢失信息了,优不知道对应91还是99了,但是,仍然要reconstruct到x^的意义是,有个参照来矫正,用x^和目标x对比,至少优还让你在九十多分,而不会到六十分以下,这一部分是要实现训练的功能,让auto-encoder有据可依。(那么,为何不直接用优良中差来训练z呢?因为你没有优良中差的标签,现实的神经网络,也不一定刚好用60分来标记差,如果可以,还要神经网络干嘛?回过头来讲,不就因为你不知道怎么给成绩分类优良中差,所以才要让它自动学习的嘛)
下图有loss公式(不用label训练),训练之后,decoder就没用了,注意,是没用了!!!要记住,目的是得到encoder!而VAE则是保留Decoder(当然,VAE的核心是学到z分布,只是相对auto-encoder,VAE是保留decoder)
这个才是完全体,抛弃decoder,用encoder直接作为输入的过渡(不过,反思一下,一定需要它么?我觉得在深度网络大行其道的当下,这个必要性不存在,网络容量够大,什么特征提取不来?都不耽误训练!够用!当然,这块是个人认为,有待求证)
大概去搜了一下网上的说法,关于auto-encoder在深度学习的必要性:
autoencoder方法可能的一些优势
(1)用于supervised learning可作为特征转换的手段
在观察到的数据上能探测到一些潜藏的structures,可以用于深度神经网络的pre-training部分,得到较好的初始的权重。(这是前边提到的分类问题,监督学习,也仅仅是预训练,感觉不是绝对的必要)
(2)用于unsupervised learning
density estimation和离群点检测(所谓离群点检测,大概也就是通过encoder再通过decoder,两者都要有,看重建之后的偏差,大于一个阈值就算离群点(前提,训练auto-encoder的数据一定要正常)。总的来说,这是偏向于人工去观察和可视化方面的,也就是说,一定程度上近似PCA的功能)
(3)学习数据的典型表示
小结:可能在不同场景下确实有些用处,没用到的暂时不讨论。理论上,压缩数据确实可能节省不少参数量和计算量。至少在本文提到的用于预处理特征从而进行分类,在网络性能没达到瓶颈的前提下(毕竟resnet都一百多层了,虽然我的显卡不行,土豪的显卡也不是瓶颈),用encoder处理不具有十足的必要性。尤其是BN的使用,使得一个精心挑选的初始化显得不是那么必要。相似的还有word2vec的n-gram,也算是一个简单的数据压缩,算是输入层面的一个转换。
todo:上边三点也不一定代表全部,有空也看看论文怎么说。
用三层auto-encoder进行训练,encoder逐层递减,decoder逐层递增。
训练结束后把encode的输出接到全连接层,实现分类预测。
图像压缩到3维大概是77%的准确率。可以把不同层的encode(en2、en1、en0)输出接入到全连接层,根据压缩程度不同,准确率不同。激活函数也有略微影响。暂时就不试所有情况了,有兴趣的可以多试试。
因为两层全连接层的输出同是10(encode输出是3维,所以fc1没设置太大,没意义;en2以前不小于12,所以fc1也没设太小),有点像平行输出,所以第二层不能再加tanh激活,准确率会下降。
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import numpy as np
tf.set_random_seed(1)
# Hyper Parameters
BATCH_SIZE = 64
LR = 0.002 # learning rate
CLR = 0.05 # classification learning rate
N_TEST_IMG = 5
IMG_SHOW_START = 5
# Mnist digits
mnist = input_data.read_data_sets('./mnist', one_hot=True) # use not one-hotted target data
test_x = mnist.test.images[:200]
test_y = mnist.test.labels[:200]
print(test_y.shape)
# plot one example
print(mnist.train.images.shape) # (55000, 28 * 28)
print(mnist.train.labels.shape) # (55000, 10)
# plt.imshow(mnist.train.images[0].reshape((28, 28)), cmap='gray')
# plt.title('%i' % np.argmax(mnist.train.labels[0]))
# plt.show()
# tf placeholder
tf_x = tf.placeholder(tf.float32, [None, 28*28]) # value in the range of (0, 1)
tf_y = tf.placeholder(tf.float32, [None, 10])
# encoder
en0 = tf.layers.dense(tf_x, 128, tf.nn.tanh)
en1 = tf.layers.dense(en0, 64, tf.nn.tanh)
en2 = tf.layers.dense(en1, 12, tf.nn.tanh)
# encoded = tf.layers.dense(en2, 3)
encoded = tf.layers.dense(en2, 3)
# decoder
de0 = tf.layers.dense(encoded, 12, tf.nn.tanh)
de1 = tf.layers.dense(de0, 64, tf.nn.tanh)
de2 = tf.layers.dense(de1, 128, tf.nn.tanh)
decoded = tf.layers.dense(de2, 28*28, tf.nn.sigmoid)
loss = tf.losses.mean_squared_error(labels=tf_x, predictions=decoded)
train = tf.train.AdamOptimizer(LR).minimize(loss)
#########################################################################################
#classification training
weights_fc1 = tf.Variable(initial_value = tf.truncated_normal([12,10],stddev=0.1),dtype=tf.float32)
biases_fc1 = tf.Variable(initial_value = tf.constant(0.1,shape = [10]))
weights_out = tf.Variable(initial_value = tf.truncated_normal([10,10],stddev=0.1),dtype=tf.float32)
biases_out = tf.Variable(initial_value = tf.constant(0.1,shape = [10]))
#fc1 = tf.nn.relu(tf.matmul(encoded, weights_fc1) + biases_fc1)#use layer encoded:0.754+
#fc1 = (tf.matmul(encoded, weights_fc1) + biases_fc1)#use layer encoded:0.63-
#fc1 = tf.nn.tanh(tf.matmul(encoded, weights_fc1) + biases_fc1)#use layer encoded:0.773+
fc1 = tf.nn.tanh(tf.matmul(en2,weights_fc1) + biases_fc1)#use layer en2:0.786+ #modify weights_fc1 correspondingly
pred = (tf.matmul(fc1, weights_out) + biases_out)#bad result in tanh
#pred = fc1#just use fc1 to predict #use layer en2:0.719+ in 80000 steps,0.7639 in 800000 steps
pred_loss = tf.reduce_mean(tf.losses.softmax_cross_entropy(onehot_labels=tf_y, logits = pred))
pred_train = tf.train.AdamOptimizer(CLR).minimize(pred_loss,var_list=[weights_fc1,weights_out,biases_fc1,biases_out])
pred_accuracy = tf.metrics.accuracy(labels = tf.argmax(tf_y,axis=1), predictions = tf.argmax(pred,axis=1))#dont forget axis=1
#########################################################################################
sess = tf.Session()
sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
# initialize figure
f, a = plt.subplots(2, N_TEST_IMG, figsize=(5, 2))
print(type(a))
print(a.shape)
plt.ion() # continuously plot
# original data (first row) for viewing
view_data = mnist.test.images[IMG_SHOW_START : IMG_SHOW_START + N_TEST_IMG]
idx = 0#can not change to other!!!!!!!!!!!!!!!!!!!!!!this is axes,not data#this is fixed rows 0
for i in range(N_TEST_IMG):
a[idx][i].imshow(np.reshape(view_data[i], (28, 28)), cmap='gray')
a[idx][i].set_xticks(()); a[idx][i].set_yticks(())
for step in range(8000):
b_x, b_y = mnist.train.next_batch(BATCH_SIZE)
_, encoded_, decoded_, loss_ = sess.run([train, encoded, decoded, loss], {tf_x: b_x})
if step % 100 == 0: # plotting
print('train loss: %.4f' % loss_)
#plotting decoded image (second row)
decoded_data = sess.run(decoded, {tf_x: view_data})
for i in range(N_TEST_IMG):
a[1][i].clear()#this is fixed rows 1
a[1][i].imshow(np.reshape(decoded_data[i], (28, 28)), cmap='gray')
a[1][i].set_xticks(()); a[1][i].set_yticks(())
plt.draw(); #plt.pause(0.01)
plt.ioff()
# visualize in 3D plot
view_data = test_x[:200]
encoded_data = sess.run(encoded, {tf_x: view_data})
fig = plt.figure(2); ax = Axes3D(fig)
X, Y, Z = encoded_data[:, 0], encoded_data[:, 1], encoded_data[:, 2]
for x, y, z, s in zip(X, Y, Z, np.argmax(test_y,axis = 1)):
c = cm.rainbow(int(255*s/9)); ax.text(x, y, z, s, backgroundcolor=c)
ax.set_xlim(X.min(), X.max()); ax.set_ylim(Y.min(), Y.max()); ax.set_zlim(Z.min(), Z.max())
plt.show()
#
for step in range(80000):
b_x, b_y = mnist.train.next_batch(BATCH_SIZE)
_ = sess.run([pred_train], {tf_x: b_x, tf_y:b_y})
if step % 100 == 0: # plotting
pred_, loss_, pred_loss_, accuracy_ = sess.run([ pred, loss, pred_loss, pred_accuracy],
{tf_x: test_x, tf_y: test_y})
print('auto-encoder train loss: %.4f' % loss_)
print('classification train loss: %.4f' % pred_loss_)
print('classification train accuracy: %.4f' % accuracy_[1])
#print('pred_: ' ,np.argmax(pred_,axis=1), ' label: ' ,np.argmax(test_y,axis=1))
plt.ioff()
压缩前后对比
https://github.com/huqinwei/tensorflow_demo/blob/master/auto_encoder_demo.py