循环神经网络与Transformer架构深入解析
立即解锁
发布时间: 2025-08-31 01:07:03 阅读量: 15 订阅数: 16 AIGC 


企业级NLP实战指南
### 循环神经网络与Transformer架构深入解析
#### 1. 循环神经网络(RNN)改进探索
在自然语言处理(NLP)领域,55%的准确率并不理想,这也凸显了我们需要更优架构的原因。不过,在循环序列模型框架内,仍存在一些更好的选择。
##### 1.1 双向RNN(Bidirectional RNN)
双向RNN的理念与BERT中使用的双向Transformer类似,但在双向RNN里,方向性更为明显。它并非仅从左至右遍历句子,而是为隐藏状态设置了两条可同时计算的“路径”,最终会得到一个从左到右的隐藏状态序列和一个独立的从右到左的隐藏状态序列。
双向RNN虽会增加一定计算量,但通常无需过多调整就能提升性能。只要计算可行,应优先选用双向RNN变体。不过,在实际应用中,很多适合用RNN解决的问题(相较于Transformer)并不具备双向结构。例如在文本生成任务中,模型无法“预知”序列结尾,因为结尾正是待生成的内容。双向RNN在处理输入较大的简单NLP任务(如文档分类或摘要)时或许最为有用,此时Transformer虽可能效果更佳,但计算成本过高。
以IMDb文本分类问题为例,由于能一次性获取整个序列,可通过设置`bidirectional=True`来使用双向RNN。这样会得到两个隐藏状态,将它们拼接后传入全连接层,代码如下:
```python
class TextClassifier(nn.Module):
def __init__(self, vocab_size, hidden_size):
super(TextClassifier, self).__init__()
self.emb = nn.Embedding(vocab_size, hidden_size)
self.rnn = nn.RNN(hidden_size, hidden_size,
bidirectional=True, batch_first=True)
self.fc1 = nn.Linear(hidden_size * 2, 10)
self.fc2 = nn.Linear(10, 2)
def forward(self, x):
x = self.emb(x)
_, x = self.rnn(x)
x = torch.cat((x[0], x[1]), dim=-1)
x = self.fc1(x)
out = self.fc2(x)
return out
```
训练代码如下:
```python
learn = Learner(dls, TextClassifier(len(dls.vocab[0]), 100),
loss_func=CrossEntropyLossFlat(),
metrics=accuracy)
learn.fit(10)
```
训练结果如下表所示:
| epoch | train_loss | valid_loss | accuracy | time |
| --- | --- | --- | --- | --- |
| 0 | 0.682959 | 0.663150 | 0.606560 | 00:08 |
| 1 | 0.676049 | 0.679050 | 0.566600 | 00:08 |
| 2 | 0.659499 | 0.711453 | 0.541720 | 00:08 |
| 3 | 0.671983 | 0.681267 | 0.562640 | 00:08 |
| 4 | 0.639950 | 0.636450 | 0.643600 | 00:08 |
| 5 | 0.623661 | 0.645424 | 0.624920 | 00:08 |
| 6 | 0.625853 | 0.648754 | 0.628800 | 00:07 |
| 7 | 0.590960 | 0.616835 | 0.664600 | 00:08 |
| 8 | 0.599594 | 0.628637 | 0.665120 | 00:08 |
| 9 | 0.549145 | 0.599172 | 0.683880 | 00:08 |
由此可见,简单的反向阅读操作显著提升了模型的准确率。需要注意的是,Transformer本身不存在方向性概念,因其能并行处理输入的所有单词;而对于循环模型,采用双向结构是在增加一定计算成本的前提下提升性能的简单有效方法。
##### 1.2 基于RNN的序列到序列模型
只要能以某种方式利用RNN得到的隐藏状态构建模型,就能构建用于大多数常见NLP任务的模型。PyTorch的`nn.RNN`会返回每个时间步最后一层的隐藏状态,可像训练Transformer时那样使用这些隐藏状态。
例如,构建用于机器翻译的RNN模型时,可将任务拆分为编码器和解码器两个阶段。编码器创建隐藏状态,解码器利用该状态生成另一种语言的文本。
很多之前提及的任务既可用RNN解决,也可用Transformer解决。若资源允许,可对两者都进行实验。一般而言,从头开始训练时,RNN相对更容易。但目前,预训练的大型Transformer模型数量远多于RNN。
##### 1.3 长短期记忆网络(LSTM)
LSTM网络是对RNN架构的重大改进。本质上,LSTM与普通RNN差别不大,大多数RNN都是通过一个单元块在循环中更新隐藏状态,而LSTM采用了更复杂的单元块。
LSTM块并非用单个向量表示隐藏状态,而是使用两个向量,并配备相应机制来管理状态更新。在实际应用中,可使用PyTorch内置的`nn.LSTM`类,将`nn.RNN`替换为`nn.LSTM`即可,代码如下:
`
0
0
复制全文
相关推荐










