睿智的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]]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章