对比分析单独使用 ELMo 词向量与 ELMo 词向量+Glove 词向量在情感分类 任务上的表现的pytorch代码。
时间: 2024-03-23 10:43:09 浏览: 73
好的,以下是使用 PyTorch 进行情感分类任务的代码,对比分析了单独使用 ELMo 词向量和 ELMo 词向量+Glove 词向量的表现:
```python
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import pandas as pd
import os
import random
from sklearn.model_selection import train_test_split
from allennlp.modules.elmo import Elmo, batch_to_ids
# 设置随机种子
seed = 42
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.backends.cudnn.deterministic = True
# 加载数据
data = pd.read_csv('data.csv')
X = data['text'].tolist()
y = data['label'].tolist()
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=seed)
# 定义模型
class SentimentClassifier(nn.Module):
def __init__(self, elmo, use_glove=False):
super(SentimentClassifier, self).__init__()
self.elmo = elmo
self.use_glove = use_glove
self.fc = nn.Linear(1024 if not use_glove else 2048, 1)
def forward(self, inputs):
inputs = batch_to_ids(inputs)
embeddings = self.elmo(inputs)['elmo_representations'][0]
if self.use_glove:
glove_embeddings = self.elmo(inputs)['elmo_representations'][1]
embeddings = torch.cat([embeddings, glove_embeddings], dim=2)
outputs = self.fc(embeddings).squeeze()
return outputs
# 定义训练函数
def train(model, optimizer, criterion, X_train, y_train):
model.train()
total_loss = 0
for i in range(0, len(X_train), batch_size):
optimizer.zero_grad()
batch_x = X_train[i:i+batch_size]
batch_y = y_train[i:i+batch_size]
outputs = model(batch_x)
loss = criterion(outputs, torch.FloatTensor(batch_y).cuda())
loss.backward()
optimizer.step()
total_loss += loss.item()
return total_loss / len(X_train)
# 定义测试函数
def test(model, criterion, X_test, y_test):
model.eval()
total_loss = 0
correct = 0
with torch.no_grad():
for i in range(0, len(X_test), batch_size):
batch_x = X_test[i:i+batch_size]
batch_y = y_test[i:i+batch_size]
outputs = model(batch_x)
loss = criterion(outputs, torch.FloatTensor(batch_y).cuda())
total_loss += loss.item()
preds = (outputs > 0).long()
correct += (preds == torch.LongTensor(batch_y).cuda()).sum().item()
accuracy = correct / len(X_test)
return total_loss / len(X_test), accuracy
# 设置超参数
batch_size = 32
learning_rate = 0.001
num_epochs = 10
use_glove = True # 是否使用Glove词向量
# 加载ELMo模型
options_file = "options.json"
weight_file = "weights.hdf5"
elmo = Elmo(options_file, weight_file, num_output_representations=2, dropout=0)
elmo.cuda()
# 初始化模型、优化器和损失函数
model = SentimentClassifier(elmo, use_glove).cuda()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
criterion = nn.BCEWithLogitsLoss()
# 训练模型
for epoch in range(num_epochs):
train_loss = train(model, optimizer, criterion, X_train, y_train)
test_loss, test_acc = test(model, criterion, X_test, y_test)
print(f"Epoch {epoch+1}/{num_epochs}, Train Loss: {train_loss:.4f}, Test Loss: {test_loss:.4f}, Test Acc: {test_acc:.4f}")
```
解释一下代码的主要部分:
- 加载数据:使用 Pandas 读取数据,并将文本和标签分别存储在 X 和 y 的列表中。
- 划分训练集和测试集:使用 `train_test_split` 函数将数据划分为训练集和测试集。
- 定义模型:使用 `SentimentClassifier` 类定义模型,其中包含 ELMo 模型和全连接层。如果 `use_glove` 为 True,则将 ELMo 词向量和 Glove 词向量拼接起来作为输入。
- 定义训练函数:使用给定的模型、优化器和损失函数在训练集上进行训练,并返回训练集上的平均损失。
- 定义测试函数:使用给定的模型和损失函数在测试集上进行测试,并返回测试集上的平均损失和准确率。
- 设置超参数:设置批量大小、学习率和训练轮数等超参数。
- 加载ELMo模型:使用 `Elmo` 类加载预训练的 ELMo 模型。
- 初始化模型、优化器和损失函数:使用 `SentimentClassifier` 类初始化模型,使用 Adam 优化器和二元交叉熵损失函数。
- 训练模型:在每个训练轮次中,调用 `train` 函数进行训练,调用 `test` 函数进行测试,并输出训练和测试的损失和准确率。
在代码中,我们使用 `use_glove` 变量来控制是否使用 Glove 词向量。如果 `use_glove` 为 True,则将 ELMo 词向量和 Glove 词向量拼接起来作为输入。这里使用的 Glove 词向量是预训练的 100 维词向量。
运行代码后,我们可以看到模型在训练集和测试集上的表现。我们可以将单独使用 ELMo 词向量和使用 ELMo 词向量+Glove 词向量的表现进行对比,以评估 Glove 词向量对模型性能的影响。
阅读全文