自編碼網路與時間訊號分解
最近一直在研究與自編碼相關的深度學習知識,關於自編碼相關的數學知識請移步相關的解釋網站,這裡不再贅述。一直想利用tensorflow實現一個自編碼的小例子,網上列出的例子大部分都是和官方例子相似的影象處理的例項程式碼。這些例子對於沒有影象處理的人來說有些晦澀,所以想自己設計一個自編碼網路的例子來說明一下深度學習在自編碼網路中的作用,突然想到大名鼎鼎的傅立葉變換其實也可以利用自編碼網路來實現。
傅立葉分解在工程學上常用於時間訊號處理,即將所有訊號看稱為基函式為一系列頻率不同的三角函式的線性組合。因此我們可以選用兩個基函式線性組成的時間序列為訓練對向,通過自編碼網路訓練來獲取基函式。
設定 y = a * sin(x) + b * sin(2*x) 在x屬於[0, PI/2]的區間內均勻取樣30的點來表示訊號。 這樣就可以利用隨機生成a和b來生成大量的訓練資料。
FIG1 訓練訊號集
FIG2 典型自編碼網路的結構
網路結構:
第一層作為輸入層,因此神經元的維數為訊號的長度, 因為本例訊號取樣長度為30,故第一層的維數為30;
第二層為隱藏層,訊號由兩個基函式的線性組合,我們期望隱藏層的節點值正好是訊號係數,故隱藏層的維數為2;
第三層為輸出層,相當於還原訊號,維數為30;
啟用函式:
隱藏層選用sigmoid函式,輸出層不用啟用函式。不使用啟用函式的目的是為了實現解碼即:
y = ahidden1 * w1 + ahidden2 * w2
w1, w2 為輸出層係數矩陣的兩行值,最後期待w1, w2 接近兩個基函式在選定區間的波形,就能實現利用自編碼網路實現類似傅立葉變換的訊號分解。
目標函式:
目標函式為min(y-x)^2
FIG3 訓練結果
從訓練結果可以看出,分解訊號的效果是達到了,但精度還有待進一步提高。其中青色和紅色為精確基函式,藍色和綠色為訓練結果。
關於如何提高精度,期待高手指教。
程式碼附上:
#!/usr/bin/Python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
from matplotlib import pyplot as plt
if __name__ == "__main__":
PI = 3.1415926
totalSize = 300
factor_data = np.float32(np.random.uniform(0,1, size= (totalSize,2)))
x = np.linspace(0.0, PI, num=30)
template = np.array([np.sin(x), np.sin(2 * x)])
singles = np.float32(np.dot(factor_data, template))
trainSingles = []
for i in range(totalSize):
onesingle = []
for j in range(30):
onesingle.append(singles[i][j])
trainSingles.append(onesingle)
n_input = 30
n_hidden = 2
n_output = 30
batch_size = 1
learning_rate = 0.05
totalSteps = 1
X = tf.placeholder(tf.float32, [None,n_input])
yTrue = X
wEncoder = tf.Variable(tf.random_normal([n_input, n_hidden]))
wDecoder = tf.Variable(tf.random_normal([n_hidden, n_output]))
bEncode = tf.Variable(tf.random_normal([n_hidden]))
bDecoder = tf.Variable(tf.random_normal([n_output]))
hiddenlayer = tf.nn.sigmoid(tf.add(tf.matmul(X, wEncoder), bEncode))
Y = tf.add(tf.matmul(hiddenlayer,wDecoder), bDecoder)
cost = tf.reduce_mean(tf.pow(Y - yTrue, 2))
opt = tf.train.RMSPropOptimizer(learning_rate).minimize(cost)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for step in range(totalSteps):
for i in range(int(totalSize / batch_size)):
_,c = sess.run([opt,cost],feed_dict={ X:[trainSingles[i]]})
if step%20 == 0:
print("step"+str(step)+":"+ str(c))
sess.run(wDecoder)
w = wDecoder.eval()
plt.figure()
plt.plot(x,w[0])
plt.plot(x,w[1])
plt.plot(x,np.sin(x))
plt.plot(x,np.sin(2*x))
plt.show()