睿智的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(100, input_shape=(STEP_SIZE, INPUT_SIZE))(inputs)
x = Dropout(0.25)(x)
示意图如下:
2、语义编码c的处理
上一步获得的LSTM的输出为一个100维的输出向量,是一个浓缩的特征。
# INPUT_SIZE-> STEP_SIZE,INPUT_SIZE
# 分为STEP_SIZE个时间序列
x = RepeatVector(STEP_SIZE)(x)
由于我们的decoder也是一个LSTM模型,输入就是这个浓缩的特征,而且我们需要对STEP_SIZE个输出进行排序。所以decoder的输入序列的时间SIZE也是STEP_SIZE大小。
我们可以利用RepeatVector函数讲encoder的输出的语义编码c重复STEP_SIZE次。
实现INPUT_SIZE维向量 -> (STEP_SIZE, INPUT_SIZE)维向量的转换
实现代码为:
x = RepeatVector(STEP_SIZE)(x)
示意图如下:
3、输出神经网络
输出神经网络的输入是上一步获得的(STEP_SIZE, INPUT_SIZE)维向量。
输出也是(STEP_SIZE, INPUT_SIZE)维向量。
因此输出神经网络由两部分组成,第一部分是普通的LSTM网络,其会输出(STEP_SIZE, NERVE_NUM)维度的向量。
第二部分是TimeDistributed+Dense,TimeDistributed+Dense意味着对LSTM网络的每一个STEP的输出进行全连接,会输出(STEP_SIZE, INPUT_SIZE )维度的向量。
实现代码、执行思路如下:
# STEP_SIZE, INPUT_SIZE -> STEP_SIZE, NERVE_NUM
# 当return_sequences=True时,会输出时间序列
# STEP_SIZE代表时间序列,NERVE_NUM代表每一个时间序列的输出
x = LSTM(100, return_sequences=True)(x)
# TimeDistributed的作用
# 对每一个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(100, input_shape=(STEP_SIZE, INPUT_SIZE))(inputs)
x = Dropout(0.25)(x)
# INPUT_SIZE-> STEP_SIZE,INPUT_SIZE
# 分为10个时间序列
x = RepeatVector(STEP_SIZE)(x)
# STEP_SIZE, INPUT_SIZE -> STEP_SIZE, NERVE_NUM
# 当return_sequences=True时,会输出时间序列
# STEP_SIZE代表时间序列,NERVE_NUM代表每一个时间序列的输出
x = LSTM(100, 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
inputs = Input([STEP_SIZE,INPUT_SIZE])
x = LSTM(100, input_shape=(STEP_SIZE, INPUT_SIZE))(inputs)
x = Dropout(0.25)(x)
# INPUT_SIZE-> STEP_SIZE,INPUT_SIZE
# 分为10个时间序列
x = RepeatVector(STEP_SIZE)(x)
# STEP_SIZE, INPUT_SIZE -> STEP_SIZE, NERVE_NUM
# 当return_sequences=True时,会输出时间序列
# 10代表时间序列,100代表每一个时间序列的输出
x = LSTM(100, 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]]
来源:CSDN
作者:Bubbliiiing
链接:https://blog.csdn.net/weixin_44791964/article/details/103984867