欢迎访问宙启技术站
智能推送

使用torchtext进行中文文本情感分析的实例

发布时间:2023-12-25 05:37:50

Torchtext是一个用于自然语言处理任务的PyTorch库,它提供了一些方便的工具和API,可以帮助我们进行文本分析任务,例如中文文本情感分析。下面是一个使用torchtext进行中文文本情感分析的实例,包括使用例子。

首先,我们需要准备一个用于情感分析的中文文本数据集。我们假设我们有一个包含中文文本和对应情感标签的数据集,可以是一个CSV文件或其他格式。每一行包含一个文本和对应的情感标签,例如:

文本,情感标签
我很高兴,正面
这个电影太无聊了,负面
今天的天气真好!,正面

在这个例子中,我们使用了两种情感标签:正面和负面。

接下来,我们可以使用torchtext加载数据集。首先,我们需要定义字段(Field)对象,用于指定文本和情感标签的处理方式,例如是否需要分词、是否需要转换为小写等。在这个例子中,我们使用默认参数。

from torchtext.data import Field, TabularDataset, BucketIterator

text_field = Field(sequential=True, lower=True, include_lengths=True)
label_field = Field(sequential=False, is_target=True)

fields = [('text', text_field), ('label', label_field)]
train_data, valid_data, test_data = TabularDataset.splits(
    path='dataset_path',
    train='train.csv',
    validation='valid.csv',
    test='test.csv',
    format='csv',
    fields=fields,
    skip_header=True
)

在上面的代码中,我们首先导入了需要的类和函数。然后,我们定义了两个字段对象:text_fieldlabel_field,并将其组成一个字段(Field)的列表。接下来,使用TabularDataset.splits()函数加载数据集,将每一行的文本和情感标签分别放入对应的字段中。

下一步是构建词汇表(Vocabulary)。我们可以使用build_vocab()函数根据训练数据构建词汇表。通过指定min_freq参数,我们可以将出现频率低于某个阈值的词语忽略掉。

text_field.build_vocab(train_data, min_freq=2)
label_field.build_vocab(train_data)

现在,我们可以创建数据迭代器(Iterator),用于批量化数据并进行训练和评估。我们可以使用BucketIterator类,它会根据文本长度自动将相似长度的文本放入同一个批次中。

train_iterator, valid_iterator, test_iterator = BucketIterator.splits(
    datasets=(train_data, valid_data, test_data),
    batch_size=32,
    sort_key=lambda x: len(x.text),
    sort_within_batch=True
)

在上面的代码中,我们使用BucketIterator.splits()函数创建数据迭代器,指定批次大小为32,并指定了一个sort_key函数,根据文本长度进行排序。

现在,我们可以定义模型并进行训练和评估。这里我们使用一个简单的循环神经网络(RNN)模型作为示例。

import torch
import torch.nn as nn
import torch.optim as optim

class SentimentModel(nn.Module):
    def __init__(self, input_dim, embedding_dim, hidden_dim, output_dim):
        super().__init__()
        self.embedding = nn.Embedding(input_dim, embedding_dim)
        self.rnn = nn.RNN(embedding_dim, hidden_dim)
        self.fc = nn.Linear(hidden_dim, output_dim)

    def forward(self, text, text_lengths):
        embedded = self.embedding(text)
        packed = nn.utils.rnn.pack_padded_sequence(embedded, text_lengths.cpu(), enforce_sorted=False)
        _, hidden = self.rnn(packed)
        return self.fc(hidden.squeeze(0))

input_dim = len(text_field.vocab)
embedding_dim = 100
hidden_dim = 256
output_dim = len(label_field.vocab)

model = SentimentModel(input_dim, embedding_dim, hidden_dim, output_dim)
optimizer = optim.Adam(model.parameters())
criterion = nn.CrossEntropyLoss()

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = model.to(device)
criterion = criterion.to(device)

def train(model, iterator, optimizer, criterion):
    model.train()
    
    epoch_loss = 0
    epoch_acc = 0
    
    for batch in iterator:
        text, text_lengths = batch.text
        labels = batch.label
        
        optimizer.zero_grad()
        
        predictions = model(text, text_lengths)
        
        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):
    model.eval()
    
    epoch_loss = 0
    epoch_acc = 0
    
    with torch.no_grad():
        for batch in iterator:
            text, text_lengths = batch.text
            labels = batch.label

            predictions = model(text, text_lengths)

            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)

def binary_accuracy(preds, y):
    rounded_preds = torch.argmax(preds, dim=1)
    correct = (rounded_preds == y).float()
    acc = correct.sum() / len(correct)
    return acc

N_EPOCHS = 10

best_valid_loss = float('inf')

for epoch in range(N_EPOCHS):
    train_loss, train_acc = train(model, train_iterator, optimizer, criterion)
    valid_loss, valid_acc = evaluate(model, valid_iterator, criterion)

    if valid_loss < best_valid_loss:
        best_valid_loss = valid_loss
        torch.save(model.state_dict(), 'sentiment-model.pt')

    print(f'Epoch: {epoch+1:02}')
    print(f'\tTrain Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%')
    print(f'\t Val. Loss: {valid_loss:.3f} |  Val. Acc: {valid_acc*100:.2f}%')

在上面的代码中,我们首先定义了一个简单的循环神经网络(RNN)模型,包含一个嵌入层、一个RNN层和一个全连接层。然后,我们定义了训练函数train()和评估函数evaluate(),用于训练和评估模型。在每个epoch结束时,我们保存具有最低验证损失的模型参数。

最后,我们进行模型的预测和评估。

model.load_state_dict(torch.load('sentiment-model.pt'))

test_loss, test_acc = evaluate(model, test_iterator, criterion)

print(f'Test Loss: {test_loss:.3f} | Test Acc: {test_acc*100:.2f}%')

以上就是使用torchtext进行中文文本情感分析的实例,包括数据准备、模型定义、训练和评估等步骤。你可以根据实际需求对代码进行修改和调整,例如选择不同的模型结构、调整超参数等。希望对你有所帮助!