使用auto-encoder實現數據壓縮、分類預測

原理簡介:

(文章編輯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

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章