Tensorflow实现 Bidirectional LSTM Classifier

本文介绍双向递归神经网络(Bi-RNN)及其在时间序列分类任务上的优势,并通过一个实例展示了如何使用TensorFlow实现双向LSTM分类器,并在MNIST数据集上进行测试。
部署运行你感兴趣的模型镜像

1.双向递归神经网络

双向递归神经网络(Bidirectional Recurrent Neural Networks, Bi-RNN),是由Schuster和Paliwal于1997年首次提出的,和LSTM是在同一年被提出的。Bi-RNN的主要目标是增加RNN可利用的信息。RNN无法利用某个历史输入的未来信息,Bi-RNN则正好相反,它可以同时使用时序数据中某个输入的历史及未来数据。 

Bi-RNN网络结构的核心是把一个普通的单项的RNN拆成两个方向,一个随时序正向的,一个逆着时序的反向的,如图。


在需要上下文的环境中,Bi-RNN将会非常有用,比如在手写文字识别时,如果有当前要识别的单词的前面和后面一个单词的信息,那么将非常有利于识别。同样,我们在阅读文章时,有时候也需要通过下文的语境来推测文中某句话的准确含义。对很多分类问题,比如手写文字识别,机器翻译,蛋白结构预测等,使用Bi-RNN将会大大提升模型效果。

Bi-RNN中的每个RNN单元既可以是传统的RNN,也可以是LSTM单元或者GRU单元,同样也可以叠加多层Bi-RNN,进一步抽象的提炼出特征。如果最后使用作分类任务,我们可以将Bi-RNN的输出序列连接一个全连接层,或者连接全局平均池化Global Average Pooling,最后再接Softmax层,这部分和使用卷积神经网络部分一致,如果有不理解Softmax这些概念的建议看下cs231n系列的课程,里面的概念还是讲解的非常清晰的。

2.代码实现

    下面我们就使用tensorflow实现一个Bidirectional LSTM Classifier,并在MNIST数据集上进行测试。

# !/usr/bin/python3
# -*- coding:utf-8 -*-
__auther__ = 'gavin'

#代码主要是使用Bidirectional LSTM Classifier对MNIST数据集上进行测试
#导入常用的数据库,并下载对应的数据集
import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

#设置对应的训练参数
learning_rate = 0.01
max_samples = 400000
batch_size = 128
display_step = 10 # 每间隔10次训练就展示一次训练情况

n_input = 28
n_steps = 28
n_hidden = 256
n_classes = 10

#创建输入x和学习目标y的placeholder,这里我们的样本被理解为一个时间序列,
# 第一个维度是时间点n_step,第二个维度是每个时间点的数据n_inpt。同时,在最后创建Softmax层的权重和偏差
x = tf.placeholder("float", [None, n_steps, n_input])
y = tf.placeholder("float", [None, n_classes])

# 因为是双向LSTM,有forward和backward两个LSTM的cell,
# 所以weights的参数量也翻倍,变为2×n_hidden
weights = tf.Variable(tf.random_normal([2 * n_hidden, n_classes]))
biases = tf.Variable(tf.random_normal([n_classes]))

#定义Bidirectional LSTM网络的生成函数
def BiRNN(x, weights, biases):

    x = tf.transpose(x, [1, 0, 2])
    x = tf.reshape(x, [-1, n_input])
    # 将x拆成长度为n_steps的列表,列表中每个tensor尺寸都是(batch_size,n_input),这样符合LSTM单元
    x = tf.split(x, n_steps) 

    lstm_fw_cell = tf.contrib.rnn.BasicLSTMCell(n_hidden, forget_bias = 1.0)
    lstm_bw_cell = tf.contrib.rnn.BasicLSTMCell(n_hidden, forget_bias = 1.0)

    outputs, _, _ = tf.contrib.rnn.static_bidirectional_rnn(lstm_fw_cell,
                                                            lstm_bw_cell, x,
                                                            dtype = tf.float32)
    return tf.matmul(outputs[-1], weights) + biases

#使用tf.nn.softmax_cross_entropy_with_logits进行softmax处理并计算损失
pred = BiRNN(x, weights, biases)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits = pred, labels = y))
optimizer = tf.train.AdamOptimizer(learning_rate = learning_rate).minimize(cost)

correct_pred = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

init = tf.global_variables_initializer()

#开始执行训练和测试操作
with tf.Session() as sess:
    sess.run(init)
    step = 1
    while step * batch_size < max_samples:
        batch_x, batch_y = mnist.train.next_batch(batch_size)
        batch_x = batch_x.reshape((batch_size, n_steps, n_input))
        sess.run(optimizer, feed_dict = {x: batch_x, y: batch_y})
        if step % display_step == 0:
            acc = sess.run(accuracy, feed_dict = {x: batch_x, y: batch_y})
            loss = sess.run(cost, feed_dict = {x: batch_x, y: batch_y})
            print("Iter" + str(step * batch_size) + ", Minibatch Loss = " + \
                "{:.6f}".format(loss) + ", Training Accuracy = " + \
                "{:.5f}".format(acc))
        step += 1
    print("Optimization Finished!")
# 全部训练迭代结束后,我们使用训练好的模型,对mnist.test.images中全部的测试数据进行预测,并将准确率展示出来。


    test_len = 10000
    test_data = mnist.test.images[:test_len].reshape((-1, n_steps, n_input))
    test_label = mnist.test.labels[:test_len]
    print("Testing Accuracy:", sess.run(accuracy, feed_dict = {x: test_data, y: test_label}))

     在完成了40万个样本训练后,我们看一下模型在训练集和测试集上的表现。在训练集上我们的预测准确率都非常高,基本都是1,而在包含1000个样本的测试集上也有0.9853的准确率。



Bidirectional LSTM Classifier在MNIST数据集上的表现虽然不如卷积神经网络,但也达到了一个很不错的水平 。

Bi-RNN乃至双向LSTM网络在时间序列分类任务上能达到较好的表现,是因为它能做到同时利用时间序列的历史和未来信息,结合上下文信息,对结果进行综合判定。虽然在图片这种空间结构显著的数据上不如卷积神经网络,但在无空间结构的单纯的时间序列上,相信Bi-RNN和Bi-LSTM会更具优势。

  














您可能感兴趣的与本文相关的镜像

TensorFlow-v2.15

TensorFlow-v2.15

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

### BERT 与 LSTM 的结合方式 在自然语言处理任务中,BERT 提供了上下文感知的词向量表示,而 LSTM(长短期记忆网络)擅长捕捉序列数据中的长期依赖关系。将两者结合可以进一步提升模型对文本语义的理解能力。具体来说,BERT 负责提取输入文本的基础嵌入,然后将其作为 LSTM 的输入进行时序建模。 在 PyTorch 中实现这一结构的关键在于:BERT 输出的张量需要适配 LSTM 的输入格式,并且确保梯度传播路径正确。通常的做法是将 BERT 的最后一层隐藏状态输出作为 LSTM 的输入序列,其形状为 `[batch_size, seq_length, hidden_size]`,正好符合 LSTM 所需的三维输入要求 [^1]。 ### 模型结构示例代码 以下是一个基于 PyTorch 实现的 BERT + LSTM 模型示例,适用于文本分类或序列标注任务: ```python import torch import torch.nn as nn from transformers import BertModel, BertTokenizer class BertLSTMModel(nn.Module): def __init__(self, num_classes, lstm_hidden_size=512, num_layers=1, dropout=0.3): super(BertLSTMModel, self).__init__() self.bert = BertModel.from_pretrained('bert-base-uncased') self.tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') # 定义 LSTM 层 self.lstm = nn.LSTM( input_size=768, # BERT 嵌入维度 hidden_size=lstm_hidden_size, num_layers=num_layers, bidirectional=True, # 可选双向 LSTM batch_first=True ) # 分类器头 self.classifier = nn.Sequential( nn.Dropout(dropout), nn.Linear(lstm_hidden_size * 2, num_classes) # 双向 LSTM 需要乘以 2 ) def forward(self, input_ids, attention_mask): outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask) sequence_output = outputs.last_hidden_state # [batch_size, seq_len, 768] # 通过 LSTMlstm_output, (h_n, c_n) = self.lstm(sequence_output) # [batch_size, seq_len, hidden_size * 2] # 使用最后一个时间步的输出进行分类 final_output = lstm_output[:, -1, :] # [batch_size, hidden_size * 2] logits = self.classifier(final_output) return logits ``` 上述代码定义了一个典型的 BERT-LSTM 架构,其中 BERT 提取词级嵌入,LSTM 进一步建模上下文依赖性。最后使用一个全连接层完成分类任务。该结构适用于多种 NLP 任务,如文本分类、命名实体识别等 [^1]。 ### 训练与调优建议 在训练过程中,需要注意以下几点: - **学习率设置**:BERT 的学习率应小于 LSTM 部分的学习率,例如 BERT 使用 `2e-5`,而 LSTM 使用 `5e-4`。 - **冻结策略**:初期训练可冻结 BERT 参数,仅训练 LSTM 和分类器;待模型初步收敛后解冻 BERT 进行微调。 - **序列长度限制**:BERT 对输入长度有限制(通常为 512),因此在处理长文本时可能需要截断或滑动窗口拼接。 - **Dropout 与 Batch Size**:适当增加 Dropout 率和 Batch Size 可缓解过拟合,尤其在小数据集上效果更明显 [^1]。 ### 总结 BERT 与 LSTM 的结合能够有效融合静态语义表示与动态序列建模能力,在实际应用中展现出良好的泛化性能。PyTorch 提供了灵活的模块支持,使得构建此类复合模型变得直观高效。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值