睿智的seq2seq模型1——利用seq2seq模型对数字进行排列

时光总嘲笑我的痴心妄想 提交于 2020-01-15 14:56:25

学习前言

快乐学习新知识,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]]
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!