TF之LSTM:基于Tensorflow框架采用PTB数据集建立LSTM网络的自然语言建模

本文涉及的产品
NLP自然语言处理_基础版,每接口每天50万次
NLP自然语言处理_高级版,每接口累计50万次
NLP 自学习平台,3个模型定制额度 1个月
简介: TF之LSTM:基于Tensorflow框架采用PTB数据集建立LSTM网络的自然语言建模

关于PTB数据集


PTB (Penn Treebank Dataset)文本数据集是语言模型学习中目前最被广泛使用数据集。

ptb.test.txt    #测试集数据文件

ptb.train.txt   #训练集数据文件

ptb.valid.txt   #验证集数据文件

这三个数据文件中的数据已经经过了预处理,包含了10000 个不同的词语和语句结束标记符(在文本中就是换行符)以及标记稀有词语的特殊符号。

为了让使用PTB数据集更加方便,TensorFlow提供了两个函数来帮助实现数据的预处理。首先,TensorFlow提供了ptb_raw_data函数来读取PTB的原始数据,并将原始数据中的单词转化为单词ID。

训练数据中总共包含了929589 个单词,而这些单词被组成了一个非常长的序列。这个序列通过特殊的标识符给出了每句话结束的位置。在这个数据集中,句子结束的标识符ID为2。

数据集的下载地址:TF的PTB数据集     (别的数据集不匹配的话会出现错误)


代码实现


  本代码使用2层 LSTM 网络,且每层有 200 个隐藏单元。在训练中截断的输入序列长度为 32,且使用 Dropout 和梯度截断等方法控制模型的过拟合与梯度爆炸等问题。当简单地训练 3 个 Epoch 后,测试复杂度(Perplexity)降低到了 210,如果多轮训练会更低。



# -*- coding: utf-8 -*-

from __future__ import absolute_import

from __future__ import division

from __future__ import print_function

import collections

import os

import sys

import tensorflow as tf

Py3 = sys.version_info[0] == 3

def _read_words(filename):

 with tf.gfile.GFile(filename, "r") as f:

   if Py3:

     return f.read().replace("\n", "<eos>").split()

   else:

     return f.read().decode("utf-8").replace("\n", "<eos>").split()

def _build_vocab(filename):

 data = _read_words(filename)

 counter = collections.Counter(data)

 count_pairs = sorted(counter.items(), key=lambda x: (-x[1], x[0]))

 words, _ = list(zip(*count_pairs))

 word_to_id = dict(zip(words, range(len(words))))

 return word_to_id

def _file_to_word_ids(filename, word_to_id):

 data = _read_words(filename)

 return [word_to_id[word] for word in data if word in word_to_id]

def ptb_raw_data(data_path=None):

 """Load PTB raw data from data directory "data_path".

 Reads PTB text files, converts strings to integer ids,

 and performs mini-batching of the inputs.

 The PTB dataset comes from Tomas Mikolov's webpage:

 http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz

 Args:

   data_path: string path to the directory where simple-examples.tgz has

     been extracted.

 Returns:

   tuple (train_data, valid_data, test_data, vocabulary)

   where each of the data objects can be passed to PTBIterator.

 """

 train_path = os.path.join(data_path, "ptb.train.txt")

 valid_path = os.path.join(data_path, "ptb.valid.txt")

 test_path = os.path.join(data_path, "ptb.test.txt")

 word_to_id = _build_vocab(train_path)

 train_data = _file_to_word_ids(train_path, word_to_id)

 valid_data = _file_to_word_ids(valid_path, word_to_id)

 test_data = _file_to_word_ids(test_path, word_to_id)

 vocabulary = len(word_to_id)

 return train_data, valid_data, test_data, vocabulary

def ptb_producer(raw_data, batch_size, num_steps, name=None):

 """Iterate on the raw PTB data.

 This chunks up raw_data into batches of examples and returns Tensors that

 are drawn from these batches.

 Args:

   raw_data: one of the raw data outputs from ptb_raw_data.

   batch_size: int, the batch size.

   num_steps: int, the number of unrolls.

   name: the name of this operation (optional).

 Returns:

   A pair of Tensors, each shaped [batch_size, num_steps]. The second element

   of the tuple is the same data time-shifted to the right by one.

 Raises:

   tf.errors.InvalidArgumentError: if batch_size or num_steps are too high.

 """

 with tf.name_scope(name, "PTBProducer", [raw_data, batch_size, num_steps]):

   raw_data = tf.convert_to_tensor(raw_data, name="raw_data", dtype=tf.int32)

   data_len = tf.size(raw_data)

   batch_len = data_len // batch_size

   data = tf.reshape(raw_data[0 : batch_size * batch_len],

                     [batch_size, batch_len])

   epoch_size = (batch_len - 1) // num_steps

   assertion = tf.assert_positive(

       epoch_size,

       message="epoch_size == 0, decrease batch_size or num_steps")

   with tf.control_dependencies([assertion]):

     epoch_size = tf.identity(epoch_size, name="epoch_size")

   i = tf.train.range_input_producer(epoch_size, shuffle=False).dequeue()

   x = tf.strided_slice(data, [0, i * num_steps],

                        [batch_size, (i + 1) * num_steps])

   x.set_shape([batch_size, num_steps])

   y = tf.strided_slice(data, [0, i * num_steps + 1],

                        [batch_size, (i + 1) * num_steps + 1])

   y.set_shape([batch_size, num_steps])

   return x, y

from reader import *

import tensorflow as tf

import numpy as np

data_path = 'F:/File_Python/Python_daydayup/data/simple-examples/data'  #F:/File_Python/Python_daydayup/data/simple-examples/data

# 隐藏层单元数与LSTM层级数

hidden_size = 200

num_layers = 2

#词典规模

vocab_size = 10000

learning_rate = 1.0

train_batch_size = 16

# 训练数据截断长度

train_num_step = 32

# 在测试时不需要使用截断,测试数据为一个超长序列

eval_batch_size = 1

eval_num_step = 1

num_epoch = 3

#结点不被Dropout的概率

keep_prob = 0.5

# 用于控制梯度爆炸的参数

max_grad_norm = 5

# 通过ptbmodel 的类描述模型

class PTBModel(object):

   def __init__(self, is_training, batch_size, num_steps):

       # 记录使用的Batch大小和截断长度

       self.batch_size = batch_size

       self.num_steps = num_steps

       # 定义输入层,维度为批量大小×截断长度

       self.input_data = tf.placeholder(tf.int32, [batch_size, num_steps])

       # 定义预期输出

       self.targets = tf.placeholder(tf.int32, [batch_size, num_steps])

       # 定义使用LSTM结构为循环体,带Dropout的深度RNN

       lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(hidden_size)

       if is_training:

           lstm_cell = tf.nn.rnn_cell.DropoutWrapper(lstm_cell, output_keep_prob=keep_prob)

       cell = tf.nn.rnn_cell.MultiRNNCell([lstm_cell] * num_layers)

       # 初始化状态为0

       self.initial_state = cell.zero_state(batch_size, tf.float32)

       # 将单词ID转换为单词向量,embedding的维度为vocab_size*hidden_size

       embedding = tf.get_variable('embedding', [vocab_size, hidden_size])

       # 将一个批量内的单词ID转化为词向量,转化后的输入维度为批量大小×截断长度×隐藏单元数

       inputs = tf.nn.embedding_lookup(embedding, self.input_data)

       # 只在训练时使用Dropout

       if is_training: inputs = tf.nn.dropout(inputs, keep_prob)

       # 定义输出列表,这里先将不同时刻LSTM的输出收集起来,再通过全连接层得到最终输出

       outputs = []

       # state 储存不同批量中LSTM的状态,初始为0

       state = self.initial_state

       with tf.variable_scope('RNN'):

           for time_step in range(num_steps):

               if time_step > 0: tf.get_variable_scope().reuse_variables()

               # 从输入数据获取当前时间步的输入与前一时间步的状态,并传入LSTM结构

               cell_output, state = cell(inputs[:, time_step, :], state)

               # 将当前输出加入输出队列

               outputs.append(cell_output)

       # 将输出队列展开成[batch,hidden*num_step]的形状,再reshape为[batch*num_step, hidden]

       output = tf.reshape(tf.concat(outputs, 1), [-1, hidden_size])

       # 将LSTM的输出传入全连接层以生成最后的预测结果。最后结果在每时刻上都是长度为vocab_size的张量

       # 且经过softmax层后表示下一个位置不同词的概率

       weight = tf.get_variable('weight', [hidden_size, vocab_size])

       bias = tf.get_variable('bias', [vocab_size])

       logits = tf.matmul(output, weight) + bias

       # 定义交叉熵损失函数,一个序列的交叉熵之和

       loss = tf.contrib.legacy_seq2seq.sequence_loss_by_example(

           [logits],  # 预测的结果

           [tf.reshape(self.targets, [-1])],  # 期望正确的结果,这里将[batch_size, num_steps]压缩为一维张量

           [tf.ones([batch_size * num_steps], dtype=tf.float32)])  # 损失的权重,所有为1表明不同批量和时刻的重要程度一样

       # 计算每个批量的平均损失

       self.cost = tf.reduce_sum(loss) / batch_size

       self.final_state = state

       # 只在训练模型时定义反向传播操作

       if not is_training: return

       trainable_variable = tf.trainable_variables()

       # 控制梯度爆炸问题

       grads, _ = tf.clip_by_global_norm(tf.gradients(self.cost, trainable_variable), max_grad_norm)

       # 如果需要使用Adam作为优化器,可以改为tf.train.AdamOptimizer(learning_rate),学习率需要降低至0.001左右

       optimizer = tf.train.GradientDescentOptimizer(learning_rate)

       # 定义训练步骤

       self.train_op = optimizer.apply_gradients(zip(grads, trainable_variable))

def run_epoch(session, model, data, train_op, output_log, epoch_size):

   total_costs = 0.0

   iters = 0

   state = session.run(model.initial_state)

   # # 使用当前数据训练或测试模型

   for step in range(epoch_size):

       x, y = session.run(data)

       # 在当前批量上运行train_op并计算损失值,交叉熵计算的是下一个单词为给定单词的概率

       cost, state, _ = session.run([model.cost, model.final_state, train_op],

                                       {model.input_data: x, model.targets: y, model.initial_state: state})

       # 将不同时刻和批量的概率就可得到困惑度的对数形式,将这个和做指数运算就可得到困惑度

       total_costs += cost

       iters += model.num_steps

       # 只在训练时输出日志

       if output_log and step % 100 == 0:

           print("After %d steps, perplexity is %.3f" % (step, np.exp(total_costs / iters)))

   return np.exp(total_costs / iters)

def main():

   train_data, valid_data, test_data, _ = ptb_raw_data(data_path)

   # 计算一个epoch需要训练的次数

   train_data_len = len(train_data)

   train_batch_len = train_data_len // train_batch_size

   train_epoch_size = (train_batch_len - 1) // train_num_step

   valid_data_len = len(valid_data)

   valid_batch_len = valid_data_len // eval_batch_size

   valid_epoch_size = (valid_batch_len - 1) // eval_num_step

   test_data_len = len(test_data)

   test_batch_len = test_data_len // eval_batch_size

   test_epoch_size = (test_batch_len - 1) // eval_num_step

   initializer = tf.random_uniform_initializer(-0.05, 0.05)

   with tf.variable_scope("language_model", reuse=None, initializer=initializer):

       train_model = PTBModel(True, train_batch_size, train_num_step)

   with tf.variable_scope("language_model", reuse=True, initializer=initializer):

       eval_model = PTBModel(False, eval_batch_size, eval_num_step)

   # 训练模型。

   with tf.Session() as session:

       tf.global_variables_initializer().run()

       train_queue = ptb_producer(train_data, train_model.batch_size, train_model.num_steps)

       eval_queue = ptb_producer(valid_data, eval_model.batch_size, eval_model.num_steps)

       test_queue = ptb_producer(test_data, eval_model.batch_size, eval_model.num_steps)

       coord = tf.train.Coordinator()

       threads = tf.train.start_queue_runners(sess=session, coord=coord)

       for i in range(num_epoch):

           print("In iteration: %d" % (i + 1))

           run_epoch(session, train_model, train_queue, train_model.train_op, True, train_epoch_size)

           valid_perplexity = run_epoch(session, eval_model, eval_queue, tf.no_op(), False, valid_epoch_size)

           print("Epoch: %d Validation Perplexity: %.3f" % (i + 1, valid_perplexity))

       test_perplexity = run_epoch(session, eval_model, test_queue, tf.no_op(), False, test_epoch_size)

       print("Test Perplexity: %.3f" % test_perplexity)

       coord.request_stop()

       coord.join(threads)

if __name__ == "__main__":

   main()

 


相关文章
|
3月前
|
机器学习/深度学习 算法 安全
【PSO-LSTM】基于PSO优化LSTM网络的电力负荷预测(Python代码实现)
【PSO-LSTM】基于PSO优化LSTM网络的电力负荷预测(Python代码实现)
208 0
|
5月前
|
机器学习/深度学习 算法 数据挖掘
基于WOA鲸鱼优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
本项目基于MATLAB 2022a/2024b实现,采用WOA优化的BiLSTM算法进行序列预测。核心代码包含完整中文注释与操作视频,展示从参数优化到模型训练、预测的全流程。BiLSTM通过前向与后向LSTM结合,有效捕捉序列前后文信息,解决传统RNN梯度消失问题。WOA优化超参数(如学习率、隐藏层神经元数),提升模型性能,避免局部最优解。附有运行效果图预览,最终输出预测值与实际值对比,RMSE评估精度。适合研究时序数据分析与深度学习优化的开发者参考。
|
5月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于GA遗传优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
本内容包含基于BiLSTM与遗传算法(GA)的算法介绍及实现。算法通过MATLAB2022a/2024b运行,核心为优化BiLSTM超参数(如学习率、神经元数量),提升预测性能。LSTM解决传统RNN梯度问题,捕捉长期依赖;BiLSTM双向处理序列,融合前文后文信息,适合全局信息任务。附完整代码(含注释)、操作视频及无水印运行效果预览,适用于股票预测等场景,精度优于单向LSTM。
|
5月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于PSO粒子群优化TCN-LSTM时间卷积神经网络时间序列预测算法matlab仿真
本内容展示了一种基于粒子群优化(PSO)与时间卷积神经网络(TCN)的时间序列预测方法。通过 MATLAB2022a 实现,完整程序运行无水印,核心代码附详细中文注释及操作视频。算法利用 PSO 优化 TCN 的超参数(如卷积核大小、层数等),提升非线性时间序列预测性能。TCN 结构包含因果卷积层与残差连接,结合 LSTM 构建混合模型,经多次迭代选择最优超参数,最终实现更准确可靠的预测效果,适用于金融、气象等领域。
|
2月前
|
机器学习/深度学习 数据采集 资源调度
基于长短期记忆网络定向改进预测的动态多目标进化算法(LSTM-DIP-DMOEA)求解CEC2018(DF1-DF14)研究(Matlab代码实现)
基于长短期记忆网络定向改进预测的动态多目标进化算法(LSTM-DIP-DMOEA)求解CEC2018(DF1-DF14)研究(Matlab代码实现)
|
2月前
|
机器学习/深度学习 传感器 数据采集
基于贝叶斯优化CNN-LSTM混合神经网络预测(Matlab代码实现)
基于贝叶斯优化CNN-LSTM混合神经网络预测(Matlab代码实现)
486 0
|
5月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于PSO粒子群优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
本项目基于MATLAB2022a/2024b开发,结合粒子群优化(PSO)算法与双向长短期记忆网络(BiLSTM),用于优化序列预测任务中的模型参数。核心代码包含详细中文注释及操作视频,涵盖遗传算法优化过程、BiLSTM网络构建、训练及预测分析。通过PSO优化BiLSTM的超参数(如学习率、隐藏层神经元数等),显著提升模型捕捉长期依赖关系和上下文信息的能力,适用于气象、交通流量等场景。附有运行效果图预览,展示适应度值、RMSE变化及预测结果对比,验证方法有效性。
|
5月前
|
机器学习/深度学习 数据采集 算法
基于GWO灰狼优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
本项目基于Matlab 2022a/2024b实现,结合灰狼优化(GWO)算法与双向长短期记忆网络(BiLSTM),用于序列预测任务。核心代码包含数据预处理、种群初始化、适应度计算及参数优化等步骤,完整版附带中文注释与操作视频。BiLSTM通过前向与后向处理捕捉序列上下文信息,GWO优化其参数以提升预测性能。效果图展示训练过程与预测结果,适用于气象、交通等领域。LSTM结构含输入门、遗忘门与输出门,解决传统RNN梯度问题,而BiLSTM进一步增强上下文理解能力。
|
8月前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【害虫识别】系统~卷积神经网络+TensorFlow+图像识别+人工智能
害虫识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了12种常见的害虫种类数据集【"蚂蚁(ants)", "蜜蜂(bees)", "甲虫(beetle)", "毛虫(catterpillar)", "蚯蚓(earthworms)", "蜚蠊(earwig)", "蚱蜢(grasshopper)", "飞蛾(moth)", "鼻涕虫(slug)", "蜗牛(snail)", "黄蜂(wasp)", "象鼻虫(weevil)"】 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Djan
494 1
基于Python深度学习的【害虫识别】系统~卷积神经网络+TensorFlow+图像识别+人工智能
|
8月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于GA遗传优化TCN-LSTM时间卷积神经网络时间序列预测算法matlab仿真
本项目基于MATLAB 2022a实现了一种结合遗传算法(GA)优化的时间卷积神经网络(TCN)时间序列预测算法。通过GA全局搜索能力优化TCN超参数(如卷积核大小、层数等),显著提升模型性能,优于传统GA遗传优化TCN方法。项目提供完整代码(含详细中文注释)及操作视频,运行后无水印效果预览。 核心内容包括:1) 时间序列预测理论概述;2) TCN结构(因果卷积层与残差连接);3) GA优化流程(染色体编码、适应度评估等)。最终模型在金融、气象等领域具备广泛应用价值,可实现更精准可靠的预测结果。

热门文章

最新文章