Jupyter AI

15 从零学NLP系列教程:只生成语言模型之RNN与LSTM

📅发表日期: 2024-08-10

🏷️分类: NLP小白

👁️阅读次数: 0

在前一篇中,我们讨论了语言模型中的N-gram模型,它通过基于词的n个前一个词的条件概率来捕捉语言的统计特性。然而,N-gram模型存在词汇稀疏和上下文信息不足的问题。在这篇文章中,我们将深入探讨基于循环神经网络(RNN)和长短期记忆(LSTM)网络的语言模型,这些模型能够更好地处理序列数据,并有效捕捉长程依赖关系。

循环神经网络(RNN)

RNN是一种用于处理序列数据的神经网络架构。在传统的神经网络中,输入的每一项都是独立的,而在RNN中,网络的输出不仅与当前输入有关,还与之前的状态(即之前的输入)相关。这种结构使得RNN能够处理可变长度的序列。

RNN的工作原理

在每个时间步骤,RNN接收输入向量xtx_t和前一个隐藏状态ht1h_{t-1},并生成当前的隐藏状态hth_t. 这个过程可以用以下公式表示:

ht=f(Whht1+Wxxt+b)h_t = f(W_h h_{t-1} + W_x x_t + b)

其中,WhW_hWxW_x 是权重矩阵,bb是偏置项,ff是激活函数(通常使用tanhReLU)。

最后,RNN会通过一个输出层生成当前时间步骤的输出yty_t

yt=Wyht+byy_t = W_y h_t + b_y

示例:简单RNN语言模型

假设我们要生成一句话,“我爱自然语言处理”。在训练过程中,我们可以将这句话转换为一个字符序列。

import numpy as np

# 简单的字符到索引的映射
chars = '我爱自然语言处理'
char_to_idx = {ch: i for i, ch in enumerate(chars)}
idx_to_char = {i: ch for i, ch in enumerate(chars)}

# 超参数
hidden_size = 10
learning_rate = 0.01

# 初始化权重
W_h = np.random.randn(hidden_size, hidden_size) * 0.01
W_x = np.random.randn(hidden_size, len(chars)) * 0.01
W_y = np.random.randn(len(chars), hidden_size) * 0.01

# 训练过程等...

长短期记忆网络(LSTM)

虽然RNN在序列处理方面表现优越,但它在学习长程依赖时常常会遇到“梯度消失”或“梯度爆炸”的问题。为了解决这一问题,LSTM被提出。

LSTM的结构

LSTM通过引入三个门(输入门、遗忘门和输出门)来控制信息的流动,以此来保持长期的记忆。LSTM的工作机制可以通过以下公式描述:

  1. 遗忘门(Forget Gate):
ft=σ(Wf[ht1,xt]+bf)f_t = \sigma(W_f [h_{t-1}, x_t] + b_f)
  1. 输入门(Input Gate):
i_t = \sigma(W_i [h_{t-1}, x_t] + b_i)$$

\tilde{C}t = \tanh(W_C [h{t-1}, x_t] + b_C)$$

  1. 当前单元状态:
C_t = f_t * C_{t-1} + i_t * \tilde{C}_t$$ 4. 输出门(Output Gate):

o_t = \sigma(W_o [h_{t-1}, x_t] + b_o)$$

  1. 当前隐藏状态:
h_t = o_t * \tanh(C_t)$$ ### 示例:LSTM语言模型 对于生成语言模型,LSTM模型同样可以应用于序列生成。以下是一个简单的LSTM实现示例: ```python import numpy as np class LSTM: def __init__(self, input_size, hidden_size): self.W_f = np.random.randn(hidden_size, input_size + hidden_size) * 0.01 # Forget gate self.W_i = np.random.randn(hidden_size, input_size + hidden_size) * 0.01 # Input gate self.W_C = np.random.randn(hidden_size, input_size + hidden_size) * 0.01 # Cell gate self.W_o = np.random.randn(hidden_size, input_size + hidden_size) * 0.01 # Output gate self.hidden_size = hidden_size self.C_prev = np.zeros((hidden_size, 1)) self.h_prev = np.zeros((hidden_size, 1)) def forward(self, x): combined = np.vstack((self.h_prev, x)) f_t = self.sigmoid(np.dot(self.W_f, combined)) i_t = self.sigmoid(np.dot(self.W_i, combined)) C_hat_t = np.tanh(np.dot(self.W_C, combined)) self.C_prev = f_t * self.C_prev + i_t * C_hat_t o_t = self.sigmoid(np.dot(self.W_o, combined)) self.h_prev = o_t * np.tanh(self.C_prev) return self.h_prev @staticmethod def sigmoid(x): return 1 / (1 + np.exp(-x)) # 使用LSTM生成字符序列... ``` ## 总结 本文介绍了基于RNN和LSTM的语言模型。与N-gram模型相比,这些模型能够更有效地捕捉序列中的上下文信息和长程依赖性。在下篇文章中,我们将探讨更先进的语言模型 —— Transformers。这一模型引入了自注意力机制,并已成为现代自然语言处理的重要组成部分。通过不断改进,我们希望能实现更高性能的语言生成和理解任务。

💬 评论

暂无评论