基于NNLM的语言模型实现教程
2025-07-06 01:53:05作者:鲍丁臣Ursa
本教程将详细介绍如何使用PyTorch实现一个简单的神经网络语言模型(NNLM)。我们将从理论背景到代码实现,逐步解析这个经典的自然语言处理模型。
神经网络语言模型(NNLM)简介
神经网络语言模型(Neural Network Language Model, NNLM)是由Bengio等人在2003年提出的经典模型,它首次将神经网络应用于语言建模任务。与传统n-gram模型相比,NNLM具有以下优势:
- 能够自动学习词语的分布式表示(词向量)
- 可以捕捉更长的上下文依赖关系
- 解决了传统方法的维度灾难问题
实现细节解析
数据准备
我们使用三个简单的英文句子作为训练数据:
sentences = ["i like dog", "i love coffee", "i hate milk"]
首先需要构建词汇表,并为每个单词分配唯一的索引:
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
number_dict = {i: w for i, w in enumerate(word_list)}
n_class = len(word_dict) # 词汇表大小
批处理生成
make_batch
函数负责将原始句子转换为模型可处理的输入输出对:
def make_batch():
input_batch = []
target_batch = []
for sen in sentences:
word = sen.split() # 使用空格分词
input = [word_dict[n] for n in word[:-1]] # 前n-1个词作为输入
target = word_dict[word[-1]] # 最后一个词作为目标
input_batch.append(input)
target_batch.append(target)
return input_batch, target_batch
模型架构
NNLM模型包含以下几个关键组件:
- 词嵌入层(Embedding Layer):将离散的词语索引映射为连续的向量表示
- 隐藏层(Hidden Layer):学习词语组合的非线性特征
- 输出层(Output Layer):预测下一个词的概率分布
具体实现如下:
class NNLM(nn.Module):
def __init__(self):
super(NNLM, self).__init__()
self.C = nn.Embedding(n_class, m) # 词嵌入层
self.H = nn.Linear(n_step * m, n_hidden, bias=False) # 隐藏层
self.d = nn.Parameter(torch.ones(n_hidden)) # 隐藏层偏置
self.U = nn.Linear(n_hidden, n_class, bias=False) # 输出层权重1
self.W = nn.Linear(n_step * m, n_class, bias=False) # 输出层权重2
self.b = nn.Parameter(torch.ones(n_class)) # 输出层偏置
def forward(self, X):
X = self.C(X) # 获取词嵌入 [batch_size, n_step, m]
X = X.view(-1, n_step * m) # 展平 [batch_size, n_step * m]
tanh = torch.tanh(self.d + self.H(X)) # 非线性变换
output = self.b + self.W(X) + self.U(tanh) # 最终输出
return output
训练过程
训练过程采用标准的监督学习范式:
- 定义损失函数(交叉熵损失)
- 选择优化器(Adam)
- 迭代训练模型
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(5000):
optimizer.zero_grad()
output = model(input_batch)
loss = criterion(output, target_batch)
if (epoch + 1) % 1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
模型预测
训练完成后,我们可以使用模型进行预测:
predict = model(input_batch).data.max(1, keepdim=True)[1]
print([sen.split()[:2] for sen in sentences], '->', [number_dict[n.item()] for n in predict.squeeze()])
输出结果将展示模型如何根据前两个词预测第三个词。
关键参数说明
n_step
:上下文窗口大小,即使用前n-1个词预测第n个词n_hidden
:隐藏层维度m
:词嵌入维度n_class
:词汇表大小
总结
通过本教程,我们实现了一个简单的NNLM模型,它可以:
- 自动学习词语的分布式表示
- 基于上下文预测下一个词
- 展示神经网络在语言建模中的应用
虽然这个实现相对简单,但它包含了NNLM的核心思想。在实际应用中,可以通过增加模型复杂度、使用更大规模的训练数据来提升模型性能。