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

用torchtext构建中文命名实体识别(NER)模型

发布时间:2023-12-31 22:35:58

TorchText是一个用于文本处理的Python库,提供了一种方便的方式来处理文本数据,并准备将其用于深度学习模型的训练。在本文中,我们将使用TorchText构建一个中文命名实体识别(NER)模型,以识别文本中的命名实体(如人名、地名等)。我们将使用已经标注好的中文NER数据集进行模型训练和测试。

首先,我们需要安装TorchText库。可以使用以下命令进行安装:

pip install torchtext

接下来,我们需要准备中文NER数据集。在本例中,我们将使用人民日报标注的中文命名实体识别数据集。可以从以下链接下载数据集:https://github.com/OYE93/Chinese-NER(在README.md文件中有下载链接)。

数据集包含了训练集、验证集和测试集。每个集合中的每行代表一个文本序列和其对应的标签序列。标签序列中的每个标签对应于文本序列中的每个字符。

接下来,我们将使用TorchText的数据处理工具将数据集转换为可以被模型直接使用的格式。以下是一个使用TorchText进行数据处理的例子:

from torchtext.data import Field, Dataset, Example

# 字符标签的Field
tag_field = Field(sequential=True, include_lengths=True, batch_first=True, lower=False, pad_token=None, unk_token=None)

# 文本序列的Field(字符级别)
text_field = Field(sequential=True, include_lengths=True, batch_first=True, lower=False, pad_token=None, unk_token=None)

def read_data(file_path):
    data = []
    with open(file_path, 'r', encoding='utf-8') as f:
        lines = f.readlines()
        text = ''
        tags = ''
        for line in lines:
            line = line.strip()
            if line == '':
                if len(text) > 0 and len(tags) > 0:
                    example = Example.fromlist([list(text), list(tags)], [('text', text_field), ('tags', tag_field)])
                    data.append(example)
                    text = ''
                    tags = ''
            else:
                word, tag = line.split()
                text += word
                tags += tag
        if len(text) > 0 and len(tags) > 0:
            example = Example.fromlist([list(text), list(tags)], [('text', text_field), ('tags', tag_field)])
            data.append(example)
    return Dataset(data, [('text', text_field), ('tags', tag_field)])

# 读取训练集、验证集和测试集
train_dataset = read_data('train.txt')
valid_dataset = read_data('valid.txt')
test_dataset = read_data('test.txt')

# 构建词表
text_field.build_vocab(train_dataset, vectors=None, min_freq=2)
tag_field.build_vocab(train_dataset)

# 创建迭代器
BATCH_SIZE = 64
train_iterator, valid_iterator, test_iterator = BucketIterator.splits(
    (train_dataset, valid_dataset, test_dataset),
    batch_size=BATCH_SIZE,
    sort_key=lambda x: len(x.text),
    sort_within_batch=True,
    device=device
)

在上述代码中,我们首先定义了两个Field对象:一个用于表示标签序列,另一个用于表示文本序列。然后,我们定义了一个函数来读取数据文件并创建Examples。每个Example包含一个文本序列和一个标签序列。最后,我们使用这些Examples创建数据集,并使用build_vocab方法构建词表。

接下来,我们可以定义我们的模型。在本例中,我们将使用BiLSTM-CRF模型作为示例。以下是一个使用PyTorch实现的BiLSTM-CRF模型的示例:

import torch
import torch.nn as nn
import torch.optim as optim
from torchcrf import CRF

class BiLSTM_CRF(nn.Module):
    def __init__(self, vocab_size, tagset_size, embedding_dim, hidden_dim, num_layers):
        super(BiLSTM_CRF, self).__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)
        self.lstm = nn.LSTM(embedding_dim, hidden_dim, num_layers=num_layers, bidirectional=True, batch_first=True)
        self.hidden2tag = nn.Linear(hidden_dim * 2, tagset_size)
        self.crf = CRF(tagset_size)

    def forward(self, sentences):
        embedded = self.embedding(sentences)
        lstm_out, _ = self.lstm(embedded)
        tag_space = self.hidden2tag(lstm_out)
        return tag_space

# 初始化模型
VOCAB_SIZE = len(text_field.vocab)
TAGSET_SIZE = len(tag_field.vocab)
EMBEDDING_DIM = 100
HIDDEN_DIM = 128
NUM_LAYERS = 2

model = BiLSTM_CRF(VOCAB_SIZE, TAGSET_SIZE, EMBEDDING_DIM, HIDDEN_DIM, NUM_LAYERS)

# 定义损失函数和优化器
loss_function = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 模型训练
NUM_EPOCHS = 10
for epoch in range(NUM_EPOCHS):
    running_loss = 0.0
    for batch in train_iterator:
        sentences, sentence_lengths = batch.text
        tags, _ = batch.tags

        optimizer.zero_grad()

        tag_scores = model(sentences)

        loss = loss_function(tag_scores.view(-1, TAGSET_SIZE), tags.view(-1))
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
    print('Epoch: %d, Loss: %.4f' % (epoch+1, running_loss / len(train_iterator)))

在上述代码中,我们首先定义了一个BiLSTM-CRF模型,其中包含一个嵌入层、一个双向LSTM层和一个线性层。然后,我们定义了损失函数和优化器。接下来,使用训练集进行模型训练,将每个batch传递给模型,计算损失并进行梯度下降优化。

最后,我们可以使用测试集对模型进行测试。以下是一个示例:

correct = 0
total = 0

with torch.no_grad():
    for batch in test_iterator:
        sentences, sentence_lengths = batch.text
        tags, _ = batch.tags

        output = model(sentences)

        _, predicted = torch.max(output.data, 2)

        total += tags.size(1)
        correct += (predicted == tags).sum().item()

accuracy = 100 * correct / total
print('Test Accuracy: %.2f%%' % accuracy)

在上述代码中,我们首先定义了两个变量来跟踪正确的预测和总预测数量。然后,使用测试集进行预测,并计算预测的准确率。

这是使用TorchText构建一个中文NER模型的基本示例。你可以根据自己的需求和数据集的不同来进一步优化模型。希望本文对你有所帮助!