pyTorch自然语言处理简单例子

正文共5225个字,预计阅读时间12分钟。


最近在学pyTorch的实际应用例子。这次说个简单的例子:给定一句话,判断是什么语言。这个例子是比如给定一句话:


Give it to me

判断是  ENGLISH


me gusta comer en la cafeteria

判断是  SPANISH


就是这么简单的例子。

来看怎么实现:
准备数据 格式  [(语句,类型),...]
data是train的时候用的语句,test_data是test的时候用的语句


data = [ ("me gusta comer en la cafeteria".split(), "SPANISH"),         ("Give it to me".split(), "ENGLISH"),         ("No creo que sea una buena idea".split(), "SPANISH"),         ("No it is not a good idea to get lost at sea".split(), "ENGLISH") ] test_data = [("Yo creo que si".split(), "SPANISH"),              ("it is lost on me".split(), "ENGLISH")]


因为文本计算机室识别不出来的,他们只认识01串,也就是数字。所以我们得把文本映射到数字上。


word_to_ix = {}for sent, _ in data + test_data:    f

or word in sent:      

 if word not in word_to_ix: word_to_ix[word] = len(word_to_ix) print(word_to_ix)


输出word_to_ix (意思是word to index)是:


{'me': 0, 'gusta': 1, 'comer': 2, 'en': 3, 'la': 4, 'cafeteria': 5, 'Give': 6, 'it': 7, 'to': 8, 'No': 9, 'creo': 10, 'que': 11, 'sea': 12, 'una': 13, 'buena': 14, 'idea': 15, 'is': 16, 'not': 17, 'a': 18, 'good': 19, 'get': 20, 'lost': 21, 'at': 22, 'Yo': 23, 'si': 24, 'on': 25}


这里先提前设置下接下来要用到的参数


VOCAB_SIZE = len(word_to_ix) NUM_LABELS = 2#只有两类 ENGLISH  SPANISH


固定模板

def init(self, num_labels, vocab_size):初始化,就是输入和输出的大小。这里我们要输入是一个句子,句子最大就是拥有所有字典的词,这里也就是vocab_size(下面再说怎么将一句话根据字典转换成一个数字序列的),输出就是分类,这里分为2类,即num_labels。这里我们用的是线性分类 ,即nn.Linear()。


def forward(self, bow_vec):bow_vec是一个句子的数字化序列,经过self.linear()得到一个线性结果(也就是预测结果),之后对这个结果进行softmax(这里用log_softmax是因为下面的损失函数用的是NLLLoss() 即负对数似然损失,需要log以下)


class BoWClassifier(nn.Module):

#nn.Module 这是继承torch的神经网络模板    

def __init__(self, num_labels, vocab_size):       

 super(BoWClassifier, self).__init__()        

self.linear = nn.Linear(vocab_size, num_labels)    

def forward(self, bow_vec):    

   return F.log_softmax(self.linear(bow_vec))

def make_bow_vector(sentence, word_to_ix)


大概能看懂什么意思吧。就是把一个句子sentence通过word_to_ix转换成数字化序列.比如  sentence=我 是 一只 小 小 鸟   word_to_id={你:0,我:1,他:2,不:3,是:4,大:5,小:6,猪:7,鸟:8,,} make_bow_vector之后的结果是[0,1,0,0,1,0,2,0,1]
view()就是改变下向量维数。这里是讲len(word_to_ix)1->1len(word_to_ix)


def make_bow_vector(sentence, word_to_ix):    vec = torch.zeros(len(word_to_ix))    for word in sentence:        vec[word_to_ix[word]] += 1    return vec.view(1, -1)


这个就不用说了吧  一样。(如果想知道torch.LongTensor啥意思的话。可以看看。Torch中,Tensor主要有ByteTensor(无符号char),CharTensor(有符号),ShortTensor(shorts), IntTensor(ints), LongTensor(longs), FloatTensor(floats), DoubleTensor(doubles),默认存放为double类型,如果需要特别指出,通过torch.setdefaulttensortype()方法进行设定。例如torch.setdefaulttensortype(‘torch.FloatTensor’)。 )


def make_target(label, label_to_ix):    return torch.LongTensor([label_to_ix[label]])


这里再介绍下model.parameters()这个函数。他的返回结果是model里的所有参数。这里我们用的是线性函数,所以就是f(x)=Ax+b中的A和b(x即输入的数据),这些参数在之后的反馈和更新参数需要的。


model = BoWClassifier(NUM_LABELS, VOCAB_SIZE)

for param in model.parameters():    

print("param:", param)


可以看出A是2len(vocab_size),b是21


param: Parameter containing:Columns 0 to 9 0.0786  0.1596  0.1259  0.0054  0.0558 -0.0911 -0.1804 -0.1526 -0.0287 -0.1086-0.0651 -0.1096 -0.1807 -0.1907 -0.0727 -0.0179  0.1530 -0.0910  0.1943 -0.1148Columns 10 to 19 0.0452 -0.0786  0.1776  0.0425  0.1194 -0.1330 -0.1877 -0.0412 -0.0269 -0.1572-0.0361  0.1909  0.1558  0.1309  0.1461 -0.0822  0.1078 -0.1354 -0.1877  0.0184Columns 20 to 25 0.1818 -0.1401  0.1118  0.1002  0.1438  0.0790 0.1812 -0.1414 -0.1876  0.1569  0.0804 -0.1897

[torch.FloatTensor of size 2x26]param: Parameter containing: 0.1859 0.1245[torch.FloatTensor of size 2]


我们再看看model的def forward(self, bow_vec):怎么用。这里就想下面的代码一样,直接在mode()填一个参数即可,就调用forward函数。


sample = data[0] bow_vector = make_bow_vector(sample[0], word_to_ix) log_probs = model(autograd.Variable(bow_vector))

print("log_probs", log_probs)


输出是:(就是log_softmax后的值)


log_probs Variable containing:-0.6160 -0.7768[torch.FloatTensor of size 1x2]


我们这里看看在test上的预测


label_to_ix = { "SPANISH": 0, "ENGLISH": 1 }

for instance, label in test_data:    

bow_vec = autograd.Variable(make_bow_vector(instance, word_to_ix))    

log_probs = model(bow_vec)    

print log_probsprint next(model.parameters())[:,word_to_ix["creo"]]


结果是


Variable containing:

-0.5431 -0.8698

[torch.FloatTensor of size 1x2]

Variable containing:

-0.7405 -0.6480

[torch.FloatTensor of size 1x2]

Variable containing:

-0.0467 0.1065

[torch.FloatTensor of size 2]


下面就该进行重要的部分了。循环训练和更新参数
这里我们用的损失函数是nn.NLLLoss()负对数似然损失
优化依然用的最常见的optim.SGD() 梯度下降法
一般训练5-30次最终优化基本不再变化


每一步过程:
a.首先都要model.zero_grad(),因为接下来要极端梯度,得清零,以防问题
b.将数据向量化(也可以说是数字序列化,转成计算机能看懂的形式)
c.得到预测值
d.求损失loss_function
e.求梯度loss.backward()
f.更新参数optimizer.step()


loss_function = nn.NLLLoss() optimizer = optim.SGD(model.parameters(), lr=0.1)for epoch in range(100):    for instance, label in data:        model.zero_grad()        bow_vec = autograd.Variable(make_bow_vector(instance, word_to_ix))        target = autograd.Variable(make_target(label, label_to_ix))        log_probs = model(bow_vec)        loss = loss_function(log_probs, target)        loss.backward()        optimizer.step()


在测试集上测试


for instance, label in test_data:    

bow_vec = autograd.Variable(make_bow_vector(instance, word_to_ix))    

log_probs = model(bow_vec)  

 print log_probs


我们在结果上很容易看到第一个例子预测是SPANISH最大,第二个是ENGLISH最大。成功了。


Variable containing:-0.0842 -2.5161[torch.FloatTensor of size 1x2]Variable containing:-2.4886 -0.0867[torch.FloatTensor of size 1x2]


原文链接:https://www.jianshu.com/p/7b2d9e6e3633


查阅更为简洁方便的分类文章以及最新的课程、产品信息,请移步至全新呈现的“LeadAI学院官网”:

www.leadai.org


请关注人工智能LeadAI公众号,查看更多专业文章

大家都在看

LSTM模型在问答系统中的应用

基于TensorFlow的神经网络解决用户流失概览问题

最全常见算法工程师面试题目整理(一)

最全常见算法工程师面试题目整理(二)

TensorFlow从1到2 | 第三章 深度学习革命的开端:卷积神经网络

装饰器 | Python高级编程

今天不如来复习下Python基础


处理示例 在这个示例中,我们将使用PyTorch LSTM模型来处理自然语言文本数据。我们将使用一个简单的情感分析任务作为例子,模型将接收一段英文文本并预测该文本的情感是正面的还是负面的。 首先,我们需要将文本数据转换为数字表示,以便LSTM模型可以处理。我们将使用预先训练好的词向量来表示每个单词。我们可以使用GloVe词向量,它是一种常见的预训练词向量。我们可以使用torchtext库来加载GloVe词向量,并将文本数据转换为数字表示。 ```python import torch import torchtext from torchtext.datasets import IMDB from torchtext.data import Field, LabelField, BucketIterator # 设置随机种子以确保结果可重复 SEED = 1234 torch.manual_seed(SEED) torch.backends.cudnn.deterministic = True # 定义数据字段 TEXT = Field(tokenize='spacy', lower=True) LABEL = LabelField(dtype=torch.float) # 加载IMDB数据集 train_data, test_data = IMDB.splits(TEXT, LABEL) # 构建词汇表 TEXT.build_vocab(train_data, max_size=10000, vectors='glove.6B.100d') LABEL.build_vocab(train_data) # 定义批处理大小和设备 BATCH_SIZE = 64 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 创建迭代器 train_iterator, test_iterator = BucketIterator.splits( (train_data, test_data), batch_size=BATCH_SIZE, device=device) ``` 接下来,我们可以定义LSTM模型。LSTM模型由一个嵌入层、一个LSTM层和一个全连接层组成。嵌入层将数字表示的文本转换为词向量表示,LSTM层将词向量序列作为输入并输出最后一个时间步的隐藏状态,最后一个全连接层将隐藏状态映射到情感标签。 ```python import torch.nn as nn class LSTMModel(nn.Module): def __init__(self, input_dim, embedding_dim, hidden_dim, output_dim): super().__init__() self.embedding = nn.Embedding(input_dim, embedding_dim) self.lstm = nn.LSTM(embedding_dim, hidden_dim) self.fc = nn.Linear(hidden_dim, output_dim) def forward(self, text): # text = [sent len, batch size] embedded = self.embedding(text) # embedded = [sent len, batch size, emb dim] output, (hidden, cell) = self.lstm(embedded) # output = [sent len, batch size, hid dim] # hidden = [1, batch size, hid dim] # cell = [1, batch size, hid dim] prediction = self.fc(hidden.squeeze(0)) # prediction = [batch size, output dim] return prediction ``` 最后,我们可以训练和测试模型。我们将使用二元交叉熵损失和Adam优化器来训练模型。在每个时期结束时,我们将计算模型在测试集上的精度。 ```python import torch.optim as optim # 定义模型、损失和优化器 INPUT_DIM = len(TEXT.vocab) EMBEDDING_DIM = 100 HIDDEN_DIM = 256 OUTPUT_DIM = 1 model = LSTMModel(INPUT_DIM, EMBEDDING_DIM, HIDDEN_DIM, OUTPUT_DIM) criterion = nn.BCEWithLogitsLoss() optimizer = optim.Adam(model.parameters()) # 将模型移动到设备上 model = model.to(device) criterion = criterion.to(device) # 定义计算准确率的函数 def binary_accuracy(preds, y): rounded_preds = torch.round(torch.sigmoid(preds)) correct = (rounded_preds == y).float() acc = correct.sum() / len(correct) return acc # 定义训练和测试函数 def train(model, iterator, optimizer, criterion): epoch_loss = 0 epoch_acc = 0 model.train() for batch in iterator: text = batch.text labels = batch.label optimizer.zero_grad() predictions = model(text).squeeze(1) loss = criterion(predictions, labels) acc = binary_accuracy(predictions, labels) loss.backward() optimizer.step() epoch_loss += loss.item() epoch_acc += acc.item() return epoch_loss / len(iterator), epoch_acc / len(iterator) def evaluate(model, iterator, criterion): epoch_loss = 0 epoch_acc = 0 model.eval() with torch.no_grad(): for batch in iterator: text = batch.text labels = batch.label predictions = model(text).squeeze(1) loss = criterion(predictions, labels) acc = binary_accuracy(predictions, labels) epoch_loss += loss.item() epoch_acc += acc.item() return epoch_loss / len(iterator), epoch_acc / len(iterator) # 训练模型 N_EPOCHS = 10 for epoch in range(N_EPOCHS): train_loss, train_acc = train(model, train_iterator, optimizer, criterion) test_loss, test_acc = evaluate(model, test_iterator, criterion) print(f'Epoch: {epoch+1:02}') print(f'\tTrain Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%') print(f'\t Test Loss: {test_loss:.3f} | Test Acc: {test_acc*100:.2f}%') ``` 这个简单的LSTM模型在IMDB数据集上的测试精度约为88%。可以尝试调整模型超参数、使用更大的预训练词向量或使用其他LSTM变体来进一步提高模型性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值