自編碼器AutoEncoder
我們先構架一個神經網絡模型,這個模型是收集一張圖片,接受這個圖片後,神經網絡給這個圖片壓縮,最後再從壓縮的圖片中還原,是不是感覺有點抽象,其實我也覺得這樣的解釋不太恰當,那就讓我們更加的具體一點來深入瞭解下這個自編碼。
現在假設我們剛纔構建的模型是這個樣子,我們可以從圖片中看出來,我們剛纔上傳給自編碼模型的圖片實質上是經過壓縮以後再進行解壓的一個過程。當壓縮的時候,原有的圖片的質量被縮減(降維),解壓的時候,用信息量小卻包含了所有信息的文件來恢復出原來的圖片(還原)。那麼,爲什麼要這麼做呢?當神經網絡要輸入大量的信息,比如高清圖片的時候,輸入的圖像數量可以達到上千萬,要神經網絡直接從輸入的數據量中進行學習,是一件非常費力不討好的工作,因此我們就想,爲什麼不壓縮一下呢?提取出原圖片中最具有代表性的信息,縮減輸入中的信息量,然後在把縮減過後的信息放入到神經網絡中學習,這樣學習起來就變得輕鬆了,所以自編碼就是能在這個時候發揮作用,現在我們假設從上圖中的輸入層中的信息A解壓縮到隱含層中得到a,然後用隱含層的a和輸入層的A進行對比,得到預測誤差,再進行反向傳遞,然後逐步的提高自編碼的準確率,訓練一段時間後在中間隱含層獲得的一個部分的數據a就是源數據的精髓,可以從上面那個模型看出,從頭到尾,我們只用到了這個輸入的信息A,並沒有用到數據A所對應的數據標籤,所以我們這時候可以得出結論,自編碼是一種非監督學習,通常我們在使用自編碼的時候通常只會使用自編碼的前半部分,這個部分也叫作EnCode,編碼器,編碼器可以得到源數據的精髓。
然後我們只需要在創建一個小的神經網絡模型再去學習這個精髓中的數據,不僅可以減少神經網絡的負擔,並且同樣可以達到一個很好的效果。
同樣的如果我們通過自編碼整理數據,他能從各種數據中篩選總結出各種數據的特徵,如果把這個圖片的類型特徵都整理好放到一個圖片上,那麼數據類型都可以很好的用源數據的類型區分出來,如果你瞭解PCA主成分分析,自編碼的功能和他類似,甚至在某些部分超出了PCA,換句話說,自編碼可以和PCA一樣可以給特殊屬性降維。
下面是用mnist數據集進行壓縮然後再還原到原圖的一個網絡
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_ephches= 20 #訓練次數
batch_size = 256 #每批送入數據數目
display_step = 1 #訓練多少次打印一次
example_to_show = 15 #展示多少張圖片
total_batch = mnist.train.images.shape[0]//batch_size #每一輪訓練要多少次,計算公式爲 數據量/batch_size
n_input = 784 #輸入數據的維度28*28
n_hidden_1 = 256 #第一層維度256
n_hidden_2 = 32 #第二層維度128
X = tf.placeholder(dtype=tf.float32, shape=[None, n_input])
#下面是我以字典的形式定義了權重和偏置,然後引用的時候直接輸入字典的鍵,就會有相應的value
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_h1': tf.Variable(tf.random_normal([n_hidden_1])),
'encoder_h2': tf.Variable(tf.random_normal([n_hidden_2])),
'decoder_h1': tf.Variable(tf.random_normal([n_hidden_1])),
'decoder_h2': 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_h1']))
layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['encoder_h2']), biases['encoder_h2']))
return layer_2
#定義解碼器
def decoder(x):
layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['decoder_h1']), biases['decoder_h1']))
layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['decoder_h2']), biases['decoder_h2']))
return layer_2
encoder_op = encoder(X)
decoder_op = decoder(encoder_op)
y_pre = decoder_op
y_true = X
cost = tf.reduce_mean(tf.square(y_pre - y_true))
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)
#展示圖片的函數
def show_image(batches=0):
#encode_decode = sess.run(y_pre, feed_dict={X: mnist.test.images[batches:(batches+1)*example_to_show]})
encode_decode = sess.run(y_pre, feed_dict={X: mnist.test.images[:example_to_show]})
f, a = plt.subplots(2, example_to_show, figsize=(15, 3))
for i in range(example_to_show):
#a[0][i].imshow(np.reshape(mnist.test.images[batches + i], (28, 28)))
a[0][i].imshow(np.reshape(mnist.test.images[i], (28, 28)))
a[1][i].imshow(np.reshape(encode_decode[i], (28, 28)))
plt.pause(1)
plt.close()
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
show_image()
for epoch in range(training_ephches):
for i in range(total_batch):
batch_xs, batch_ys = mnist.train.images[batch_size * i: batch_size * (i+1)],\
mnist.train.labels[batch_size * i: batch_size * (i+1)]
sess.run(optimizer, feed_dict={X: batch_xs})
if epoch % display_step == 0:
print('Epoch:{:2} ,cost={:.4f}'.format(epoch+1,
sess.run(cost, feed_dict={X: batch_xs})))
show_image(epoch)
print("Optimization Finished!")
第一張圖是訓練一個epoch後的效果,第二張圖是訓練15個epoch後得到的效果。