keras中seq2seq实现
- 这里只是简单的一个例子
输入序列 | 目标序列 |
---|---|
[13, 28, 18, 7, 9, 5] | [18, 28, 13] |
[29, 44, 38, 15, 26, 22] | [38, 44, 29] |
[27, 40, 31, 29, 32, 1] | [31, 40, 27] |
1.输入序列与目标序列向量化
- 设置GPU进行计算
import tensorflow as tf
tf.debugging.set_log_device_placement(True)
- 导入需要的函数和包
from numpy import array
from numpy import argmax
from keras.utils import to_categorical
import numpy as np
- 定义数据生成函数
# 随机产生在(1,n_features)区间的整数序列,序列长度为n_steps_in
def generate_sequence(length, n_unique):
return [np.random.randint(1, n_unique-1) for _ in range(length)]
这个函数的目的是产生长度为length,数据范围为(1,n_unique)之间的整数。
generate_sequence(10,100)
产生10个在(1,100)之间的整数
[9, 37, 38, 73, 4, 1, 42, 97, 48, 17]
- 构造LSTM模型所需要的数据
def get_dataset(n_in, n_out, cardinality, n_samples):
X1, X2, y = list(), list(), list()
for _ in range(n_samples):
# 生成输入序列
source = generate_sequence(n_in, cardinality) #n_in就是代表生成序列的个数,生成n个1到n_unique-1的数
# 定义目标序列,这里就是输入序列的前n_out个数据
target = source[:n_out]
target.reverse() #对数据做一个逆序(前后调转)
# 向前偏移一个时间步目标序列
target_in = [0] + target[:-1]
# 直接使用to_categorical函数进行on_hot编码
src_encoded = to_categorical(source, num_classes=cardinality) #这里就是将向量进行one_hot编码的
tar_encoded = to_categorical(target, num_classes=cardinality)
tar2_encoded = to_categorical(target_in, num_classes=cardinality)
X1.append(src_encoded)
X2.append(tar2_encoded)
y.append(tar_encoded)
return array(X1), array(X2), array(y)
to_categorical(list,num)的作用是对一个数进行one_hot编码,其输入的参数有两个,list表示的是一个整数列表,例如[3,2,5,1,2],num就是one_hot编码时向量的长度,其有一个要求就是num>max(list)。
# one_hot解码,看一下那些位置不为0
def one_hot_decode(encoded_seq):
return [argmax(vector) for vector in encoded_seq]
这里用这个one_hot解码的主要作用是来进行还原,看一下那些位置不为0。
- 输入参数
n_features = 50 + 1 #在输入时可以理解为,每个向量的长度
n_steps_in = 6 #可以看作时间不
n_steps_out = 3
# 生成处理后的输入序列与目标序列,这里测试产生了一个序列样本
X1, X2, y = get_dataset(n_steps_in, n_steps_out, n_features, 100)
X1作为encoder的输入,X2作为decoder的输入,且encoder的输出同时也作为decoder的输入,y时最终的标签
one_hot_decode(X1[1])
one_hot_decode(X2[1])
one_hot_decode(y[1])
[21, 49, 21, 34, 48, 46]
[0, 21, 49]
[21, 49, 21]
2.构造seq2seq模型
- 导入所需的网络
from numpy import array
from numpy import argmax
from numpy import array_equal
from keras.utils import to_categorical
from keras.models import Model
from keras.layers import Input
from keras.layers import LSTM
from keras.layers import Dense
- 构造网络
# 构造Seq2Seq训练模型model, 以及进行新序列预测时需要的的Encoder模型:encoder_model 与Decoder模型:decoder_model
def define_models(n_input, n_output, n_units):
# 训练模型中的encoder
encoder_inputs = Input(shape=(None, n_input))
encoder = LSTM(n_units, return_state=True)
#上述参数下,encoder_outputs和state_h都是最后一步的hidden_state
# state_c 存放最后一个时间步的cell_state
encoder_outputs, state_h, state_c = encoder(encoder_inputs)
encoder_states = [state_h, state_c] #仅保留编码状态向量
# 训练模型中的decoder
decoder_inputs = Input(shape=(None, n_output))
decoder_lstm = LSTM(n_units, return_sequences=True, return_state=True)
#上述参数下,decoder_outputs是全部时间步的hidden_state
#第一个_存放的是最后一个时间步的hidden_state
#第二个_存放的是最后一个时间步的cell state
decoder_outputs, _, _ = decoder_lstm(decoder_inputs,initial_state=encoder_states)
decoder_dense = Dense(n_output, activation='softmax')
decoder_outputs = decoder_dense(decoder_outputs)
model = Model([encoder_inputs, decoder_inputs], decoder_outputs)
# 新序列预测时需要的encoder
encoder_model = Model(encoder_inputs, encoder_states)
# 新序列预测时需要的decoder
decoder_state_input_h = Input(shape=(n_units,))
decoder_state_input_c = Input(shape=(n_units,))
decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c]
decoder_outputs, state_h, state_c = decoder_lstm(decoder_inputs, initial_state=decoder_states_inputs)
decoder_states = [state_h, state_c]
decoder_outputs = decoder_dense(decoder_outputs)
decoder_model = Model([decoder_inputs] + decoder_states_inputs, [decoder_outputs] + decoder_states)
# 返回需要的三个模型
return model, encoder_model, decoder_model
其中model是训练的网络,encoder_model是预测时的encoder模型,decoder_model是预测时的decoder模型。其中在LSTM模型中return_sequence和return_state的参数设置得到不同结果见另一个博客。https://www.jianshu.com/p/a74bb5a623dd
model, encoder_model, decoder_model = define_models(10,5,15)
model.summary()
Model: "model_19"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_25 (InputLayer) (None, None, 10) 0
__________________________________________________________________________________________________
input_26 (InputLayer) (None, None, 5) 0
__________________________________________________________________________________________________
lstm_13 (LSTM) [(None, 15), (None, 1560 input_25[0][0]
__________________________________________________________________________________________________
lstm_14 (LSTM) [(None, None, 15), ( 1260 input_26[0][0]
lstm_13[0][1]
lstm_13[0][2]
__________________________________________________________________________________________________
dense_7 (Dense) (None, None, 5) 80 lstm_14[0][0]
==================================================================================================
Total params: 2,900
Trainable params: 2,900
Non-trainable params: 0
__________________________________________________________________________________________________
encoder包含了一个lstm结构,decoder包含一个lstm结构和一个全连接层,encoder的输出作为decoder的输入,在模型中可以看见,lstm_14中与之相关联的为input,lstm_13,其中lstm_13是encoder的输出。
def predict_sequence(infenc, infdec, source, n_steps, cardinality):
"""
infenc:encoder_model
infdec:decoder_model
"""
# 输入序列编码得到编码状态向量
state = infenc.predict(source)
# 初始目标序列输入:通过开始字符计算目标序列第一个字符,这里是0
target_seq = array([0.0 for _ in range(cardinality)]).reshape(1, 1, cardinality)
# 输出序列列表
output = list()
for t in range(n_steps):
# predict next char
yhat, h, c = infdec.predict([target_seq] + state)
# 截取输出序列,取后三个
output.append(yhat[0,0,:])
# 更新状态
state = [h, c]
# 更新目标序列(用于下一个词预测的输入)
target_seq = yhat
return array(output)
``
3 评估模型效果
total, correct = 100, 0
for _ in range(total):
X1, X2, y = get_dataset(n_steps_in, n_steps_out, n_features, 1)
target = predict_sequence(infenc, infdec, X1, n_steps_out, n_features)
if array_equal(one_hot_decode(y[0]), one_hot_decode(target)):
correct += 1
print('Accuracy: %.2f%%' % (float(correct)/float(total)*100.0))
4 完整代码
from numpy import array
from numpy import argmax
from numpy import array_equal
from keras.utils import to_categorical
from keras.models import Model
from keras.layers import Input
from keras.layers import LSTM
from keras.layers import Dense
import numpy
import tensorflow as tf
tf.debugging.set_log_device_placement(True)
# 随机产生在(1,n_features)区间的整数序列,序列长度为n_steps_in
def generate_sequence(length, n_unique):
return [np.random.randint(1, n_unique-1) for _ in range(length)]
# 构造LSTM模型输入需要的训练数据
def get_dataset(n_in, n_out, cardinality, n_samples):
X1, X2, y = list(), list(), list()
for _ in range(n_samples):
# 生成输入序列
source = generate_sequence(n_in, cardinality)
# 定义目标序列,这里就是输入序列的前三个数据
target = source[:n_out]
target.reverse()
# 向前偏移一个时间步目标序列
target_in = [0] + target[:-1]
# 直接使用to_categorical函数进行on_hot编码
src_encoded = to_categorical(source, num_classes=cardinality)
tar_encoded = to_categorical(target, num_classes=cardinality)
tar2_encoded = to_categorical(target_in, num_classes=cardinality)
X1.append(src_encoded)
X2.append(tar2_encoded)
y.append(tar_encoded)
return array(X1), array(X2), array(y)
# 构造Seq2Seq训练模型model, 以及进行新序列预测时需要的的Encoder模型:encoder_model 与Decoder模型:decoder_model
def define_models(n_input, n_output, n_units):
# 训练模型中的encoder
encoder_inputs = Input(shape=(None, n_input))
encoder = LSTM(n_units, return_state=True)
encoder_outputs, state_h, state_c = encoder(encoder_inputs)
encoder_states = [state_h, state_c] #仅保留编码状态向量
# 训练模型中的decoder
decoder_inputs = Input(shape=(None, n_output))
decoder_lstm = LSTM(n_units, return_sequences=True, return_state=True)
decoder_outputs, _, _ = decoder_lstm(decoder_inputs, initial_state=encoder_states)
decoder_dense = Dense(n_output, activation='softmax')
decoder_outputs = decoder_dense(decoder_outputs)
model = Model([encoder_inputs, decoder_inputs], decoder_outputs)
# 新序列预测时需要的encoder
encoder_model = Model(encoder_inputs, encoder_states)
# 新序列预测时需要的decoder
decoder_state_input_h = Input(shape=(n_units,))
decoder_state_input_c = Input(shape=(n_units,))
decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c]
decoder_outputs, state_h, state_c = decoder_lstm(decoder_inputs, initial_state=decoder_states_inputs)
decoder_states = [state_h, state_c]
decoder_outputs = decoder_dense(decoder_outputs)
decoder_model = Model([decoder_inputs] + decoder_states_inputs, [decoder_outputs] + decoder_states)
# 返回需要的三个模型
return model, encoder_model, decoder_model
def predict_sequence(infenc, infdec, source, n_steps, cardinality):
# 输入序列编码得到编码状态向量
state = infenc.predict(source)
# 初始目标序列输入:通过开始字符计算目标序列第一个字符,这里是0
target_seq = array([0.0 for _ in range(cardinality)]).reshape(1, 1, cardinality)
# 输出序列列表
output = list()
for t in range(n_steps):
# predict next char
yhat, h, c = infdec.predict([target_seq] + state)
# 截取输出序列,取后三个
output.append(yhat[0,0,:])
# 更新状态
state = [h, c]
# 更新目标序列(用于下一个词预测的输入)
target_seq = yhat
return array(output)
# one_hot解码
def one_hot_decode(encoded_seq):
return [argmax(vector) for vector in encoded_seq]
# 参数设置
n_features = 10 + 1
n_steps_in = 6
n_steps_out = 3
# 定义模型
train, infenc, infdec = define_models(n_features, n_features, 16)
train.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc'])
# 生成训练数据
import numpy as np
X1, X2, y = get_dataset(n_steps_in, n_steps_out, n_features, 1000)
print(X1.shape,X2.shape,y.shape)
# 训练模型
train.fit([X1, X2], y, epochs=500)
# 评估模型效果
total, correct = 100, 0
for _ in range(total):
X1, X2, y = get_dataset(n_steps_in, n_steps_out, n_features, 1)
target = predict_sequence(infenc, infdec, X1, n_steps_out, n_features)
if array_equal(one_hot_decode(y[0]), one_hot_decode(target)):
correct += 1
print('Accuracy: %.2f%%' % (float(correct)/float(total)*100.0))
# 查看预测结果
for _ in range(10):
X1, X2, y = get_dataset(n_steps_in, n_steps_out, n_features, 1)
target = predict_sequence(infenc, infdec, X1, n_steps_out, n_features)
print('X=%s y=%s, yhat=%s' % (one_hot_decode(X1[0]), one_hot_decode(y[0]), one_hot_decode(target)))
keras中seq2seq实现的更多相关文章
- keras中VGG19预训练模型的使用
keras提供了VGG19在ImageNet上的预训练权重模型文件,其他可用的模型还有VGG16.Xception.ResNet50.InceptionV3 4个. VGG19在keras中的定义: ...
- keras中的mini-batch gradient descent (转)
深度学习的优化算法,说白了就是梯度下降.每次的参数更新有两种方式. 一. 第一种,遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度,更新梯度.这种方法每更新一次参数都要把数据集里的所有样本都看 ...
- keras中的模型保存和加载
tensorflow中的模型常常是protobuf格式,这种格式既可以是二进制也可以是文本.keras模型保存和加载与tensorflow不同,keras中的模型保存和加载往往是保存成hdf5格式. ...
- keras中的loss、optimizer、metrics
用keras搭好模型架构之后的下一步,就是执行编译操作.在编译时,经常需要指定三个参数 loss optimizer metrics 这三个参数有两类选择: 使用字符串 使用标识符,如keras.lo ...
- Keras中RNN不定长输入的处理--padding and masking
在使用RNN based model处理序列的应用中,如果使用并行运算batch sample,我们几乎一定会遇到变长序列的问题. 通常解决变长的方法主要是将过长的序列截断,将过短序列用0补齐到一个固 ...
- 深度学习基础系列(十一)| Keras中图像增强技术详解
在深度学习中,数据短缺是我们经常面临的一个问题,虽然现在有不少公开数据集,但跟大公司掌握的海量数据集相比,数量上仍然偏少,而某些特定领域的数据采集更是非常困难.根据之前的学习可知,数据量少带来的最直接 ...
- 深度学习基础系列(五)| 深入理解交叉熵函数及其在tensorflow和keras中的实现
在统计学中,损失函数是一种衡量损失和错误(这种损失与“错误地”估计有关,如费用或者设备的损失)程度的函数.假设某样本的实际输出为a,而预计的输出为y,则y与a之间存在偏差,深度学习的目的即是通过不断地 ...
- (数据科学学习手札44)在Keras中训练多层感知机
一.简介 Keras是有着自主的一套前端控制语法,后端基于tensorflow和theano的深度学习框架,因为其搭建神经网络简单快捷明了的语法风格,可以帮助使用者更快捷的搭建自己的神经网络,堪称深度 ...
- keras中自定义Layer
最近在学习SSD的源码,其中有两个自定的层,特此学习一下并记录. import keras.backend as K from keras.engine.topology import InputSp ...
随机推荐
- 万字长文深入理解java中的集合-附PDF下载
目录 1. 前言 2. List 2.1 fail-safe fail-fast知多少 2.1.1 Fail-fast Iterator 2.1.2 Fail-fast 的原理 2.1.3 Fail- ...
- day05 selenium基本使用
本文通过举例介绍selenium的基本使用方法,用来爬取京东笔记本电脑的商品信息,包括名称,url,价格,评价信息. from selenium import webdriver # 导入键盘Keys ...
- Kubernetes 使用 Ingress 实现灰度发布功能
使用 Ingress 实现灰度发布 一.Canary 规则说明 Ingress-Nginx 是一个K8S ingress工具,支持配置 Ingress Annotations 来实现不同场景下的灰度发 ...
- 初始化vue项目
1.创建vue项目命令 vue init webpack deaxios # 使用脚手架创建项目 deaxios(项目名,随便取得) cd deaxios # 进入项目 npm install axi ...
- shell脚本之编程基础介绍
1.shell脚本简介 1.1 shell是什么? shell是一个命令解释器,它在操作系统的最外层负责直接与用户对话,把用户的输入解释给操作系统:并处理各种各样的操作系统的输入,将结果输出到屏幕返回 ...
- week01-绪论作业
一.有理数的抽象数据模型 ADT Rational { 数据对象: D={e1,e2|e1,e2属于ElemType类型}//ElemType为自定义的整数集合类型 数据关系: R={<e1,e ...
- vscode 插件配置指北
Extension Manifest 就像 chrome 插件使用 manifest.json 来管理插件的配置一样,vscode 的插件也有一个 manifest,而且就叫 package.json ...
- QQ彩贝热销时装
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- lvs负载简介,原理,常见使用案例及Keepalived高可用
Lvs简介 基础概念 LVS(Linux Virtual Server)即Linux虚拟服务器,是由张文嵩博士主导的开源负载均衡项目,目前LVS已经被集成到Linux内核模块中(2.6及以上版本内核) ...
- Torrent文件的解析与转换
Torrent简介 BitTorrent协议的种子文件(英语:Torrent file)可以保存一组文件的元数据.这种格式的文件被BitTorrent协议所定义.扩展名一般为".torren ...