PyTorch搭建N-gram模型实现单词预测

N-gram模型就是假设预测这个单词只与前面的N-1个单词有关,并不是和前面所有的词都有关系。

所以,对于1-gram(每个词都是独立分布的):

P(w1, w2, w3, … , wn) = P(w1)P(w2|w1)P(w3|w1w2)P(w4|w1w2w3)…P(wn|w1w2…wn-1)

                                     ≈ P(w1)P(w2)P(w3)P(w4)…P(wn)

2-gram(每个词都与左边最近的那个词有关):

P(w1, w2, w3, … , wn) = P(w1)P(w2|w1)P(w3|w1w2)P(w4|w1w2w3)…P(wn|w1w2…wn-1)

                                     ≈P(w1)P(w2|w1)P(w3|w2)P(w4|w3)…P(wn|wn-1)

3-gram(每个词都与左边最近的那两个词有关):

P(w1, w2, w3, … , wn) = P(w1)P(w2|w1)P(w3|w1w2)P(w4|w1w2w3)…P(wn|w1w2…wn-1)

                                     ≈ P(w1)P(w2|w1)P(w3|w1w2)P(w4|w2w3)…P(wn|wn-2wn-1)

而:P(w2|w1)=语料库中w1和w2出现的次数/语料库中w1出现的次数

对于这个条件概率,传统的方法是统计语料中每个词出现的频率,根据贝叶斯定理来估计这个条件概率,这里我们就可以用词嵌入对其进行代替,然后最大化条件概率从而优化词向量,据此进行预测。

下面对代码进行说明:

  • 首先添加引用,net里面是定义的n-gram模型,
import torch
from torch import nn, optim
import net
class n_gram(nn.Module):
    def __init__(self, vocab_size, context_size, n_dim):
        super(n_gram, self).__init__()

        self.embed = nn.Embedding(vocab_size, n_dim)   # (vocab_size,n_dim)
        self.classify = nn.Sequential(
            nn.Linear(context_size * n_dim, 128),   
            nn.ReLU(True),
            nn.Linear(128, vocab_size)
        )

    def forward(self, x):
        voc_embed = self.embed(x)  # 得到词嵌入  context_size*n_dim
        voc_embed = voc_embed.view(1, -1)  # 将两个词向量拼在一起  1*(context_size*n_dim)
        out = self.classify(voc_embed)   # 1*vocab_size
        return out
  • 定义一些参数和语料库
CONTEXT_SIZE = 2  # 2-gram
EMBEDDING_DIM = 10  # 词向量的维度

test_sentence = """We always knew our daughter Kendall was 
                going be a performer of some sort. 
                She entertained people in our small town 
                by putting on shows on our front porch when 
                she was only three or four. Blonde-haired, 
                blue-eyed, and beautiful, she sang like a 
                little angel and mesmerized1 everyone.""".split()

trigram = [((test_sentence[i], test_sentence[i+1]), test_sentence[i+2])
            for i in range(len(test_sentence)-2)]

这里的 CONTEXT_SIZE =2 表示我们由前面2个单词来预测这个单词,EMBEDDING_DIM 表示词嵌入的维度。

接着我们建立训练集,将单词三个分组,前面两个作为输入,最后一个作为预测的结果。

  • 对单词进行编码,用数字表示每个单词,只有这样才能传入nn.Embedding得到词向量。
# 建立每个词与数字的编码,据此构建词嵌入
vocb = set(test_sentence)  # 使用 set 将重复的元素去掉
word_to_idx = {word: i for i, word in enumerate(vocb)}
idx_to_word = {word_to_idx[word]: word for word in word_to_idx}
  • 初始化模型,定义损失和优化函数
model = net.n_gram(len(word_to_idx), CONTEXT_SIZE, EMBEDDING_DIM)
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=1e-2, weight_decay=1e-5)
  • 训练
for epoch in range(100):
    train_loss = 0
    for word, label in trigram:
        word = torch.LongTensor([word_to_idx[i] for i in word])  # 将两个词作为输入
        label = torch.LongTensor([word_to_idx[label]])
        # 前向传播
        out = model(word)
        loss = criterion(out, label)
        train_loss += loss.item()
        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    if (epoch + 1) % 20 == 0:
        print('epoch: {}, Loss: {:.6f}'.format(epoch + 1, train_loss / len(trigram)))

  • 测试
model = model.eval()
word, label = trigram[15]
print('\ninput:{}'.format(word))
print('label:{}'.format(label))
word = torch.LongTensor([word_to_idx[i] for i in word])
out = model(word)
pred_label_idx = out.max(1)[1].item()  # 第一行的最大值的下标
predict_word = idx_to_word[pred_label_idx]  # 得到对应的单词
print('real word is {}, predicted word is {}'.format(label, predict_word))

可以发现预测值和label值一样,虽然是在训练集上,但是在一定程度上也说明这个小模型能够处理N-gram模型的问题。

  • 附上完整代码:
import torch
from torch import nn, optim
import net

CONTEXT_SIZE = 2  # 2-gram
EMBEDDING_DIM = 10  # 词向量的维度

test_sentence = """We always knew our daughter Kendall was 
                going be a performer of some sort. 
                She entertained people in our small town 
                by putting on shows on our front porch when 
                she was only three or four. Blonde-haired, 
                blue-eyed, and beautiful, she sang like a 
                little angel and mesmerized1 everyone.""".split()


trigram = [((test_sentence[i], test_sentence[i+1]), test_sentence[i+2])
            for i in range(len(test_sentence)-2)]

# 建立每个词与数字的编码,据此构建词嵌入
vocb = set(test_sentence)  # 使用 set 将重复的元素去掉
word_to_idx = {word: i for i, word in enumerate(vocb)}
idx_to_word = {word_to_idx[word]: word for word in word_to_idx}

model = net.n_gram(len(word_to_idx), CONTEXT_SIZE, EMBEDDING_DIM)
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=1e-2, weight_decay=1e-5)


for epoch in range(100):
    train_loss = 0
    for word, label in trigram:
        word = torch.LongTensor([word_to_idx[i] for i in word])  # 将两个词作为输入
        label = torch.LongTensor([word_to_idx[label]])
        # 前向传播
        out = model(word)
        loss = criterion(out, label)
        train_loss += loss.item()
        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    if (epoch + 1) % 20 == 0:
        print('epoch: {}, Loss: {:.6f}'.format(epoch + 1, train_loss / len(trigram)))

model = model.eval()
word, label = trigram[15]
print('\ninput:{}'.format(word))
print('label:{}'.format(label))
word = torch.LongTensor([word_to_idx[i] for i in word])
out = model(word)
pred_label_idx = out.max(1)[1].item()  # 第一行的最大值的下标
predict_word = idx_to_word[pred_label_idx]  # 得到对应的单词
print('real word is {}, predicted word is {}'.format(label, predict_word))

 

  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
### 回答1: 我可以给你一些关于使用PyTorch搭建HR-Net的建议:1. 先了解HR-Net的基本架构,然后熟悉PyTorch提供的相关API;2. 使用PyTorch搭建HR-Net的基本结构,并设置相应的参数;3. 调整参数,以获得最佳模型;4. 在测试集上进行验证,以确保模型具有良好的性能。 ### 回答2: HR-Net是一种用于人体关键点检测的神经网络模型,我们可以使用PyTorch搭建HR-Net。在搭建HR-Net之前,我们需要进行一些准备工作。 首先,我们需要安装PyTorch库。可以通过以下命令安装PyTorch: ``` pip install torch torchvision ``` 然后,我们需要下载HR-Net的代码和预训练的权重。可以在GitHub上找到HR-Net的代码库,并下载。下载完成后,解压缩代码包。 接下来,我们可以在PyTorch中定义HR-Net的网络结构。HR-Net基于两个主要的网络模块:骨干网络和多分支特征融合模块。 在骨干网络中,我们可以选择使用一些常见的神经网络模型,如ResNet、AlexNet等。我们可以在PyTorch中创建这些骨干网络,并将其作为HR-Net的输入。 在多分支特征融合模块中,我们通过将不同尺度的特征图进行融合,来提高人体关键点检测的准确性。我们可以在PyTorch实现这个多分支特征融合模块,并将其添加到HR-Net中。 最后,我们可以加载HR-Net的预训练权重,并将其用于人体关键点检测任务。我们可以使用PyTorch的数据加载器来加载训练数据,并使用预定义的损失函数和优化器来训练模型。 使用PyTorch搭建HR-Net可以使我们更轻松地实现人体关键点检测任务,并利用PyTorch的丰富功能来优化和扩展HR-Net模型。 ### 回答3: 使用PyTorch搭建HR-Net可以通过以下步骤完成: 1. 安装PyTorch:首先要在计算机上安装PyTorch库,可以通过在终端或命令提示符中运行适用于您的系统的安装命令来完成。 2. 导入必要的库:在Python脚本中,导入PyTorch以及其他必要的库,如numpy、matplotlib等。 3. 构建HR-Net模型:HR-Net是一种深度卷积神经网络体系结构,它具有多个分支并行处理低分辨率和高分辨率特征。可以使用PyTorch的nn.Module类构建HR-Net模型,并定义需要的卷积、池化、Batch Normalization等操作层。 4. 定义前向传播函数:在HR-Net模型类中,定义一个前向传播函数,该函数定义了输入数据通过模型时的计算流程。在这个函数中,可以将输入数据传递到HR-Net的各个分支,然后将其联合起来形成最终的输出。 5. 定义损失函数和优化器:为了训练HR-Net模型,需要定义一个损失函数来度量模型的输出和真实标签之间的差距,并选择一个优化器来更新模型的参数。PyTorch提供了各种损失函数和优化器的选项,可以根据具体问题的需求选择合适的函数和优化器。 6. 训练模型:使用已定义的损失函数和优化器,在训练数据上进行模型的训练。通过将训练数据输入到HR-Net模型中,并计算其输出与真实标签之间的损失,根据这个损失来更新模型的参数。 7. 测试模型:在训练完成后,可以使用测试数据来评估模型的性能。将测试数据输入到HR-Net模型中,获取模型预测输出,并与真实标签进行比较,可以计算一些评价指标,例如准确率、精确率、召回率等。 8. 调整模型和超参数:根据测试结果,可以对模型和超参数进行调整,以优化模型的性能。可以更改模型的结构、增加或减少训练数据,调整学习率等。 9. 保存和加载模型:在训练完成后,可以将模型保存到磁盘上,以便后续使用。同时,也可以从保存的模型文件中加载已经训练好的模型,并在新的数据上进行预测。 以上是使用PyTorch搭建HR-Net的一般步骤,具体实现过程中可以根据需要进行进一步的细化和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值