【NLP】2.2 神经语言模型简介

文章介绍了非线性神经网络语言模型如何解决传统模型的问题,通过增加上下文并仅使参数线性增长。它使用k元语句作为输入,预测下一个词的概率分布。文章讨论了一种网络结构,包括one-hot编码的缺陷和词向量的引入,以及如何通过隐藏层映射改进表示。此外,还提到了神经网络语言模型(NNLM)的案例实现,展示了一个简单的模型训练过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

非线性神经网络语言模型可以解决一些传统语言模型中的问题:增加上下文的同时参数仅呈线性增长,缓解了人工设计的需要,支持不同上下文泛化性能。

  • 输入:k元语句(代码实现熵是 k 个词向量的拼接)
  • 输出:下个词的概率分布P

我们的目标是希望神经网络发现如下的规律,于是有了网络结构图:
P(C(wi)∣C(wi−4),C(wi−3),C(wi−2),C(wi−1))(2.2.1) P(C(w_i)|C(w_{i-4}),C(w_{i-3}),C(w_{i-2}),C(w_{i-1}))\tag{2.2.1} P(C(wi)C(wi4),C(wi3),C(wi2),C(wi1))(2.2.1)

image-20230618191118904

图2.2.1 网络结构图

2.2.1 one-hot 表示

先用最简单的方式表示每个词,one-hot 表示为:

  • dog=(0,0,0,0,1,0,0,...)dog = (0, 0, 0, 0, 1, 0, 0, ...)dog=(0,0,0,0,1,0,0,...)
  • cat=(0,0,0,0,0,0,0,0,1,0,...)cat = (0, 0, 0, 0 ,0 ,0, 0, 0 ,1, 0, ...)cat=(0,0,0,0,0,0,0,0,1,0,...)
  • eat=(0,1,0,0,...)eat = (0, 1, 0, 0, ...)eat=(0,1,0,0,...)

image-20230618191615505

图2.2.2 one-hot 表示

可是 one-hot 表示法有诸多缺陷,还是稠密的向量表示更好一些,那么如何转换呢?只需要加一个隐藏层映射一下就好了。映射之后的向量层如果单独拿出来看,还有办法找到原来的词是什么吗?

image-20230618191830200

图2.2.3 添加隐藏层映射

one-hot 表示法这时候就作为一个索引字典了,可以通过映射矩阵对应到具体的词向量。

image-20230618192010527

图2.2.4 映射矩阵

这样,这个神经网络的每个环节都没问题了,可以开始训练了。


独热编码:让计算机认识单词

image-20230617203749587

图2.2.5 独热编码

词典 VVV:新华词典里面把所有的词集合成一个集合 VVV

假设词典里面有 8 个单词,计算机不认识单词,但是我们要计算机认识单词。

独热编码:给出一个 8×88 \times 88×8 的矩阵。

  • “time”:10000000
  • “fruit”:01000000
  • ……
  • “banana”:00000001

余弦相似度 去计算两者的相似度,发现独热编码 计算得到的余弦相似度都为0,即这些单词都没有关联度(独热编码缺陷),于是就有了词向量的概念。

数学公式总结

输入向量 xxx,输出结果 yyy 的概率分布,两者的表达式如下所示,其中 www 代表词向量,vvv 代表词到词嵌入的映射,LMLMLM (Lamguage Model)是一个多层感知机:
100LM(w1:k)=softmax(hW2+b2)x=[v(w1);v(w2);...;v(wk)]h=g(xW1+b1)(2.2.2) \begin{align}{100} LM(w_{1:k})&=softmax(hW^2+b^2)\\ &x = [v(w_1);v(w_2);...;v(w_k)]\\ &h=g(xW^1+b^1) \end{align}\tag{2.2.2} 100LM(w1:k)=softmax(hW2+b2)x=[v(w1);v(w2);...;v(wk)]h=g(xW1+b1)(2.2.2)

  • vvv 就是映射矩阵
  • www 是输入的词向量
  • xxx 是将前 k 个词通过映射矩阵处理后的一个拼接
  • hhh 是隐藏层
  • W1W^1W1W2W^2W2 表示两个矩阵

2.3.2 神经网络语言模型(NNLM)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c3aGJCNx-1687508673257)(https://bucket-zly.oss-cn-beijing.aliyuncs.com/img/Typora/202306181936991.png)]

图2.2.5 NNLM_1

image-20230617204634468

图2.2.6 NNLM_2

假设有4个单词:w1,w2,w3,w4w_1,w_2,w_3,w_4w1,w2,w3,w4(4个单词的独热编码)。

  1. w1×Q=c1,  w2×Q=c2,  w3×Q=c3,  w4×Q=c4w_1 \times Q = c_1,\space \space w_2 \times Q = c_2,\space\space w_3 \times Q = c_3,\space\space w_4 \times Q = c_4w1×Q=c1,  w2×Q=c2,  w3×Q=c3,  w4×Q=c4
    • QQQ 就是一个随机矩阵(可学习),是一个参数
  2. C=[c1,c2,c3,c4]C = [c_1,c_2,c_3,c_4]C=[c1,c2,c3,c4]
  3. softmax(U[tanh(WC+b1)]+b2)==[0.1, 0.2, 0.5, 0.2]∈[1,VL]softmax(U[tanh(WC+b_1)]+b_2) == [ 0.1,\space0.2,\space0.5,\space0.2 ]\in[1,V_L]softmax(U[tanh(WC+b1)]+b2)==[0.1, 0.2, 0.5, 0.2][1,VL]。最后生成一个一维矩阵,其中矩阵的长度为词典的长度 VLV_LVL

2.3.3 词向量(神经网络语言模型的副产品 QQQ

给我任何一个词(“判断”),会给出相应的独热编码 [0,0,1,0,...,0][0,0,1,0,...,0][0,0,1,0,...,0]

  • W1×Q=c1W_1 \times Q = c_1W1×Q=c1c1c_1c1 就是 “判断” 这个词的词向量。

词向量:就是用一个向量来表示一个单词。独热编码也属于词向量,只是独热编码存储空间太大,且两者的余弦相似度都为0。

经过 QQQ 处理,可以控制词向量的维度(大小),也解决了相似度的问题。

通过神经网络语言模型,找到一个合适的 QQQ 矩阵,得到一个合适的词向量,这个词向量能够更加准确的表示这个词

2.3.4 案例实现

import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from tqdm import tqdm
from torch.autograd import Variable

dtype = torch.FloatTensor

sentences = ["i like dog", "i love coffee", "i hate milk", "i do nlp"]

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)}
# print(word_dict)

n_class = len(word_dict)

m = 2
n_step = 2
n_hidden = 2


def make_batch(sentence):
    input_batch = []
    target_batch = []

    for sen in sentence:
        word = sen.split()
        input = [word_dict[n] for n in word[:-1]]
        target = word_dict[word[-1]]

        input_batch.append(input)
        target_batch.append(target)

    return input_batch, target_batch


class NNLM(nn.Module):
    def __init__(self):
        super(NNLM, self).__init__()
        self.embed = nn.Embedding(n_class, m)
        self.W = nn.Parameter(torch.randn(n_step * m, n_hidden).type(dtype))
        self.d = nn.Parameter(torch.randn(n_hidden).type(dtype))
        self.U = nn.Parameter(torch.randn(n_hidden, n_class).type(dtype))
        self.b = nn.Parameter(torch.randn(n_class).type(dtype))

    def forward(self, x):
        x = self.embed(x)  # 4 x 2 x 2
        x = x.view(-1, n_step * m)
        tanh = torch.tanh(self.d + torch.mm(x, self.W))  # 4 x 2
        output = self.b + torch.mm(tanh, self.U)
        return output


model = NNLM()

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

input_batch, target_batch = make_batch(sentences)
input_batch = Variable(torch.LongTensor(input_batch))
target_batch = Variable(torch.LongTensor(target_batch))

for epoch in range(5000):
    optimizer.zero_grad()

    output = model(input_batch)  # input: 4 x 2

    loss = criterion(output, target_batch)

    if (epoch + 1) % 1000 == 0:
        print('epoch:', '%04d' % (epoch + 1), 'cost = {:.6f}'.format(loss.item()))

    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()])

image-20230623162348564

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值