TensorFlow上實現AutoEncoder自編碼器
一、概述
AutoEncoder大致是一個將資料的高維特徵進行壓縮降維編碼,再經過相反的解碼過程的一種學習方法。學習過程中通過解碼得到的最終結果與原資料進行比較,通過修正權重偏置引數降低損失函式,不斷提高對原資料的復原能力。學習完成後,前半段的編碼過程得到結果即可代表原資料的低維“特徵值”。通過學習得到的自編碼器模型可以實現將高維資料壓縮至所期望的維度,原理與PCA相似。
二、模型實現
1. AutoEncoder
首先在MNIST資料集上,實現特徵壓縮和特徵解壓並視覺化比較解壓後的資料與原資料的對照。
先看程式碼:
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
# 匯入MNIST資料
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
examples_to_show = 10
n_input = 784
# tf Graph input (only pictures)
X = tf.placeholder("float", [None, n_input])
# 用字典的方式儲存各隱藏層的引數
n_hidden_1 = 256 # 第一編碼層神經元個數
n_hidden_2 = 128 # 第二編碼層神經元個數
# 權重和偏置的變化在編碼層和解碼層順序是相逆的
# 權重引數矩陣維度是每層的 輸入*輸出,偏置引數維度取決於輸出層的單元數
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])),
}
# 每一層結構都是 xW + b
# 構建編碼器
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']))
return layer_2
# 構建解碼器
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']))
return layer_2
# 構建模型
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
# Run optimization op (backprop) and cost op (to get loss value)
_, 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!")
encode_decode = sess.run(
y_pred, feed_dict={X: mnist.test.images[:examples_to_show]})
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()
程式碼解讀:
首先,匯入將要使用到的各種庫和資料集,定義各個引數如學習率、訓練迭代次數等,清晰明瞭便於後期修改。由於自編碼器的神經網路結構非常有規律性,都是xW + b的結構,故將每一層的權重W和偏置b的變數tf.Variable統一置於一個字典中,通過字典的key值更加清晰明瞭的描述。模型構建思路上,將編碼器部分和解碼器部分分開構建,每一層的啟用函式使用Sigmoid函式,編碼器通常與編碼器使用同樣的啟用函式。通常編碼器部分和解碼器部分是一個互逆的過程,例如我們設計將784維降至256維再降至128維的編碼器,解碼器對應的就是從128維解碼至256維再解碼至784維。定義代價函式,代價函式表示為解碼器的輸出與原始輸入的最小二乘法表達,優化器採用AdamOptimizer訓練階段每次迴圈將所有的訓練資料都參與訓練。經過訓練,最終將訓練結果與原資料視覺化進行對照,如下圖,還原度較高。如果增大訓練迴圈次數或者增加自編碼器的層數,可以得到更好的還原效果。
執行結果:
2. Encoder
Encoder編碼器工作原理與AutoEncoder相同,我們將編碼得到的低維“特徵值”在低維空間中視覺化出來,直觀顯示資料的聚類效果。具體地說,將784維的MNIST資料一步步的從784到128到64到10最後降至2維,在2維座標系中展示遇上一個例子不同的是,在編碼器的最後一層中我們不採用Sigmoid啟用函式,而是將採用預設的線性啟用函式,使輸出為(-∞,+∞)。
完整程式碼:
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()
實驗結果:
由結果可知,2維編碼特徵有較好的聚類效果,圖中每個顏色代表了一個數字,聚集性很好。
當然,本次實驗所得到的結果只是對AutoEncoder做一個簡單的介紹,要想得到期望的效果,還應該設計更加複雜的自編碼器結構,得到區分性更好的特徵。
相關文章
- Keras上實現AutoEncoder自編碼器Keras
- 利用 TensorFlow 實現卷積自編碼器卷積
- seq2seq通俗理解----編碼器和解碼器(TensorFlow實現)
- 『TensorFlow』讀書筆記_降噪自編碼器筆記
- 深度學習讀書筆記之AE(自動編碼AutoEncoder)深度學習筆記
- xheditor編輯器上傳功能實現
- Conditional AutoEncoder的Pytorch完全實現PyTorch
- 使用TensorFlow可實現文章自動摘要
- ant指令碼實現的Android自動編譯指令碼Android編譯
- 預測電影偏好?如何利用自編碼器實現協同過濾方法
- 程式碼線上編譯器(上)- 編輯及編譯編譯
- 自編碼器及其相關模型模型
- 使阿里oss實現前端程式碼自動上傳阿里前端
- 如何在jsp上實現報表編輯器功能?JS
- Gitee Webhook 實現自動拉取程式碼並編譯程式碼GiteeWebHook編譯
- .net web core 如何編碼實現檔案上傳功能Web
- TensorFlow上實現卷積神經網路CNN卷積神經網路CNN
- 理解深度學習:神經網路的雙胞胎兄弟-自編碼器(上)深度學習神經網路
- 移動裝置上實現“詩人”也能用TensorFlow
- 基於Netty實現Redis協議的編碼解碼器NettyRedis協議
- java實現編輯器(一)Java
- 影像壓縮編碼碼matlab實現——行程編碼Matlab行程
- 影像壓縮編碼碼matlab實現——DM編碼Matlab
- 實時程式碼編輯器
- 編輯cron實現自動執行
- 圖自編碼器的起源和應用
- 快速瞭解 變分自編碼器 VAE
- 樹莓派上利用Tensorflow實現小車的自動駕駛樹莓派自動駕駛
- 使用 git hook 實現伺服器程式碼自動部署GitHook伺服器
- TensorFlow實現Batch NormalizationBATORM
- 使用tensorflow實現人臉融合轉移原始碼原始碼
- 影像壓縮編碼碼matlab實現——變換編碼Matlab
- 影像壓縮編碼碼matlab實現——算術編碼Matlab
- 硬解碼播放器上如何實現截GIF功能?播放器
- JS實現檔案自動上傳JS
- Vue(27)vue-codemirror實現線上程式碼編譯器Vue編譯
- Asp.Net Core 使用Monaco Editor 實現程式碼編輯器ASP.NET
- Quill編輯器實現原理初探UI