15.2. 情感分析:使用循環神經網絡 — 動手學深度學習 2.0.0 documentation (d2l.ai)
代碼
import torch
from torch import nn
from d2l import torch as d2lbatch_size = 64
train_iter, test_iter, vocab = d2l.load_data_imdb(batch_size)class BiRNN(nn.Module):def __init__(self, vocab_size, embed_size, num_hiddens,num_layers, **kwargs):super(BiRNN, self).__init__(**kwargs)self.embedding = nn.Embedding(vocab_size, embed_size)# 將bidirectional設置為True以獲取雙向循環神經網絡self.encoder = nn.LSTM(embed_size, num_hiddens, num_layers=num_layers,bidirectional=True)self.decoder = nn.Linear(4 * num_hiddens, 2)def forward(self, inputs):# inputs的形狀是(批量大小,時間步數)# 因為長短期記憶網絡要求其輸入的第一個維度是時間維,# 所以在獲得詞元表示之前,輸入會被轉置。# 輸出形狀為(時間步數,批量大小,詞向量維度)embeddings = self.embedding(inputs.T)self.encoder.flatten_parameters()# 返回上一個隱藏層在不同時間步的隱狀態,# outputs的形狀是(時間步數,批量大小,2*隱藏單元數)outputs, _ = self.encoder(embeddings)# 連結初始和最終時間步的隱狀態,作為全連接層的輸入,# 其形狀為(批量大小,4*隱藏單元數)encoding = torch.cat((outputs[0], outputs[-1]), dim=1)outs = self.decoder(encoding)return outsembed_size, num_hiddens, num_layers = 100, 100, 2
devices = d2l.try_all_gpus()
net = BiRNN(len(vocab), embed_size, num_hiddens, num_layers)def init_weights(m):if type(m) == nn.Linear:nn.init.xavier_uniform_(m.weight)if type(m) == nn.LSTM:for param in m._flat_weights_names:if "weight" in param:nn.init.xavier_uniform_(m._parameters[param])
net.apply(init_weights);glove_embedding = d2l.TokenEmbedding('glove.6b.100d')embeds = glove_embedding[vocab.idx_to_token]
embeds.shapenet.embedding.weight.data.copy_(embeds)
net.embedding.weight.requires_grad = Falselr, num_epochs = 0.01, 5
trainer = torch.optim.Adam(net.parameters(), lr=lr)
loss = nn.CrossEntropyLoss(reduction="none")
d2l.train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs,devices)#@save
def predict_sentiment(net, vocab, sequence):"""預測文本序列的情感"""sequence = torch.tensor(vocab[sequence.split()], device=d2l.try_gpu())label = torch.argmax(net(sequence.reshape(1, -1)), dim=1)return 'positive' if label == 1 else 'negative'predict_sentiment(net, vocab, 'this movie is so great')predict_sentiment(net, vocab, 'this movie is so bad')
代碼解析
這段代碼實現了一個用于情感分析的雙向循環神經網絡(BiRNN)。下面我將逐部分用中文解析它:
1. 導入所需的庫和模塊:
import torch
from torch import nn
from d2l import torch as d2l
這里導入了PyTorch庫、神經網絡模塊`nn`和基于PyTorch的深度學習庫`d2l`(深度學習的一本書)。
2. 加載數據集:
batch_size = 64
train_iter, test_iter, vocab = d2l.load_data_imdb(batch_size)
加載IMDB電影評論數據集,并用迭代器`train_iter`和`test_iter`進行訓練和測試。`vocab`是數據集的詞匯表。
3. 定義雙向循環神經網絡(BiRNN)模型:
class BiRNN(nn.Module):...
創建了一個名為`BiRNN`的類,用于定義雙向LSTM模型。模型有一個嵌入層(`embedding`),將詞匯映射到向量空間。LSTM層(`encoder`)設定為雙向,輸出經過全連接層(`decoder`)得到最終的分類結果。
4. 初始化模型參數:
def init_weights(m):...
net.apply(init_weights);
init_weights函數用于模型參數的初始化。`net.apply(init_weights);`使用這個函數來應用參數初始化。
5. 加載預訓練的詞向量:
glove_embedding = d2l.TokenEmbedding('glove.6b.100d')
embeds = glove_embedding[vocab.idx_to_token]
net.embedding.weight.data.copy_(embeds)
net.embedding.weight.requires_grad = False
使用GloVe預訓練的100維詞向量,并將它們復制到嵌入層`net.embedding`。同時設置`requires_grad = False`使得這些詞向量在訓練中不被更新。
6. 訓練模型:
lr, num_epochs = 0.01, 5
trainer = torch.optim.Adam(net.parameters(), lr=lr)
loss = nn.CrossEntropyLoss(reduction="none")
d2l.train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs, devices)
設置學習率和迭代次數,使用Adam優化器和交叉熵損失函數。用`d2l.train_ch13`函數來訓練和評估模型。
7. 定義預測函數:
def predict_sentiment(net, vocab, sequence):...
這個函數用于預測給定文本序列的情感標簽(積極或消極)。
8. 使用模型進行預測:
predict_sentiment(net, vocab, 'this movie is so great')
predict_sentiment(net, vocab, 'this movie is so bad')
調用`predict_sentiment`函數分別對兩個句子進行情感預測。
整體來看,這段代碼主要是利用循環神經網絡對電影評論的情感進行分類,它通過加載預訓練好的詞向量,構建一個雙向LSTM網絡,并在IMDB評論數據集上進行訓練和測試。最后定義了一個實用函數,用于預測輸入句子的情感傾向。