睿智的seq2seq模型1——利用seq2seq模型對數字進行排列
學習前言
快樂學習新知識,seq2seq還是很重要的!
seq2seq簡要介紹
seq2seq屬於encoder-decoder結構的一種。
seq2seq的encoder常用循環神經網絡,可以使用LSTM或者RNN,當輸入一個字符串的時候,可以對其進行特徵提取,獲得語義編碼C。
而decoder則將encoder得到的編碼C作爲輸入,輸入到decoder的RNN中,得到輸出序列。
語義編碼C是輸入內容的特徵集合體,decoder可以講這個特徵集合體解碼成輸出序列。
利用seq2seq實現數組排序
實現的目標如下:
當輸入一列無序的數列後,可以對其進行排序。
實現方式
一、對輸入格式輸出格式進行定義
將輸入的1、2、3的格式轉化爲如下格式,第幾位爲1代表這個數字是幾:
由於數組的序列號是從0開始的,所以:
1轉化爲[0,1,0,0];
2轉化爲[0,0,1,0];
3轉化爲[0,0,0,1]。
這樣的格式轉換更有利於代碼處理。
二、建立神經網絡
1、神經網絡的輸入
假設輸入的數字組合是2、1、3。
輸入的順序就是循環神經網絡的時間順序STEP,也就是按時間序列輸入2、1、3。
本例子中輸入的維度爲4。
此時輸入的數組爲:
[[0,0,1,0],
[0,1,0,0],
[0,0,0,1]]
通過如下代碼就可以完成輸入編碼神經網絡的構建。
inputs = Input([STEP_SIZE,INPUT_SIZE])
x = LSTM(CELL_SIZE, input_shape=(STEP_SIZE, INPUT_SIZE))(inputs)
x = Dropout(0.25)(x)
示意圖如下:
2、語義編碼c的處理
上一步獲得的LSTM的輸出爲一個CELL_SIZE維的輸出向量,是一個濃縮的特徵。
由於我們的decoder也是一個LSTM模型,輸入就是這個濃縮的特徵,而且我們需要對STEP_SIZE個輸出進行排序。所以decoder的輸入序列的時間SIZE也是STEP_SIZE大小。
我們可以利用RepeatVector函數講encoder的輸出的語義編碼c重複STEP_SIZE次。
實現CELL_SIZE維向量 -> (STEP_SIZE, CELL_SIZE)維向量的轉換
實現代碼爲:
# CELL_SIZE-> STEP_SIZE,CELL_SIZE
# 分爲STEP_SIZE個時間序列
x = RepeatVector(STEP_SIZE)(x)
示意圖如下:
3、輸出神經網絡
輸出神經網絡的輸入是上一步獲得的(STEP_SIZE, CELL_SIZE)維向量。
輸出也是(STEP_SIZE, CELL_SIZE)維向量。
因此輸出神經網絡由兩部分組成,第一部分是普通的LSTM網絡,其會輸出(STEP_SIZE, CELL_SIZE)維度的向量。
第二部分是TimeDistributed+Dense,TimeDistributed+Dense意味着對LSTM網絡的每一個STEP的輸出進行全連接,會輸出(STEP_SIZE, INPUT_SIZE )維度的向量。
實現代碼、執行思路如下:
# STEP_SIZE, CELL_SIZE -> STEP_SIZE, NERVE_NUM
# 當return_sequences=True時,會輸出時間序列
# STEP_SIZE代表時間序列,CELL_SIZE代表每一個時間序列的輸出
x = LSTM(CELL_SIZE, return_sequences=True)(x)
# 對每一個STEP進行全連接
x = TimeDistributed(Dense(INPUT_SIZE))(x)
x = Dropout(0.5)(x)
x = Activation('softmax')(x)
示意圖如下:
4、網絡構建部分全部代碼
全部示意圖:
inputs = Input([STEP_SIZE,INPUT_SIZE])
x = LSTM(CELL_SIZE, input_shape=(STEP_SIZE, INPUT_SIZE))(inputs)
x = Dropout(0.25)(x)
# CELL_SIZE-> STEP_SIZE,CELL_SIZE
# 分爲STEP_SIZE個時間序列
x = RepeatVector(STEP_SIZE)(x)
# STEP_SIZE, CELL_SIZE -> STEP_SIZE, NERVE_NUM
# 當return_sequences=True時,會輸出時間序列
# STEP_SIZE代表時間序列,CELL_SIZE代表每一個時間序列的輸出
x = LSTM(CELL_SIZE, return_sequences=True)(x)
# 對每一個STEP進行全連接
x = TimeDistributed(Dense(INPUT_SIZE))(x)
x = Dropout(0.5)(x)
x = Activation('softmax')(x)
model = Model(inputs,x)
全部實現代碼
實現代碼爲:
from keras.models import Sequential
from keras.layers.core import Activation, RepeatVector, Dropout, Dense
from keras.layers import TimeDistributed,Input
from keras.models import Model
from keras.layers.recurrent import LSTM
import numpy as np
def encode(X, seq_len, vocab_size):
x = np.zeros((len(X), seq_len, vocab_size), dtype=np.float32)
for ind, batch in enumerate(X):
for j, elem in enumerate(batch):
x[ind, j, elem] = 1
return x
def batch_gen(batch_size=32, seq_len=10, max_no=100):
while True:
x = np.zeros((batch_size, seq_len, max_no), dtype=np.float32)
y = np.zeros((batch_size, seq_len, max_no), dtype=np.float32)
X = np.random.randint(max_no, size=(batch_size, seq_len))
Y = np.sort(X, axis=1)
for ind, batch in enumerate(X):
for j, elem in enumerate(batch):
x[ind, j, elem] = 1
for ind, batch in enumerate(Y):
for j, elem in enumerate(batch):
y[ind, j, elem] = 1
yield x, y
batch_size = 64
STEP_SIZE = 10
INPUT_SIZE = 75
CELL_SIZE = 100
inputs = Input([STEP_SIZE,INPUT_SIZE])
x = LSTM(CELL_SIZE, input_shape=(STEP_SIZE, INPUT_SIZE))(inputs)
x = Dropout(0.25)(x)
# CELL_SIZE-> STEP_SIZE,CELL_SIZE
# 分爲STEP_SIZE個時間序列
x = RepeatVector(STEP_SIZE)(x)
# STEP_SIZE, CELL_SIZE -> STEP_SIZE, NERVE_NUM
# 當return_sequences=True時,會輸出時間序列
# STEP_SIZE代表時間序列,CELL_SIZE代表每一個時間序列的輸出
x = LSTM(CELL_SIZE, return_sequences=True)(x)
# 對每一個STEP進行全連接
x = TimeDistributed(Dense(INPUT_SIZE))(x)
x = Dropout(0.5)(x)
x = Activation('softmax')(x)
model = Model(inputs,x)
model.summary()
model.compile(loss='categorical_crossentropy', optimizer='adam',
metrics=['accuracy'])
for ind, (X, Y) in enumerate(batch_gen(batch_size, STEP_SIZE, INPUT_SIZE)):
loss, acc = model.train_on_batch(X, Y)
if ind % 250 == 0:
print("ind:",ind)
testX = np.random.randint(INPUT_SIZE, size=(1, STEP_SIZE))
test = encode(testX, STEP_SIZE, INPUT_SIZE)
print("before is")
print(testX)
y = model.predict(test, batch_size=1)
print("actual sorted output is")
print(np.sort(testX))
print("sorting done by LSTM is")
print(np.argmax(y, axis=2))
print("\n")
效果爲:
ind: 0
before is
[[68 27 33 21 14 8 26 36 45 18]]
actual sorted output is
[[ 8 14 18 21 26 27 33 36 45 68]]
sorting done by LSTM is
[[55 55 55 55 55 55 55 52 52 52]]
ind: 250
before is
[[17 63 41 63 49 64 64 44 16 25]]
actual sorted output is
[[16 17 25 41 44 49 63 63 64 64]]
sorting done by LSTM is
[[ 7 16 32 44 49 49 49 63 64 69]]
ind: 500
before is
[[ 4 7 18 12 9 5 25 48 49 46]]
actual sorted output is
[[ 4 5 7 9 12 18 25 46 48 49]]
sorting done by LSTM is
[[ 0 2 7 7 18 18 25 48 48 58]]
……
ind: 3500
before is
[[36 19 72 45 34 67 39 38 60 3]]
actual sorted output is
[[ 3 19 34 36 38 39 45 60 67 72]]
sorting done by LSTM is
[[ 3 19 34 36 38 39 45 60 67 72]]