一.文本需求分析
在我们的旅游计划中,很重要的一个部分就是时间与地点的规划,不一样的时间所看到的风景是完全不一样的,因此时间是一个非常重要的内容,首先我们的数据爬取是根据地点来进行的,因此我们需要对数据进行处理,使每一个数据都具有时间特点,因此我们考虑给每一个数据都加上时间,考虑到我们有很多具有时间特征的数据,因此我们考虑通过神经网络的方法来实现我们的设想。夏天的济南秋天的济南
二.步骤设计
1.准备数据
首先我们在之前的数据中将其分为有月份的和没有月份的两个部分,之后将其用来训练和测试模型,我们使用python来进行分类,首先在我们的数据中,instruction中有一系列的标签,我们选择有月份的来进行训练,将其summary进行训练,将月份进行测试。
2.文本预处理
我们将使用一个BERT模型进行文本处理和特征提取,因此需要首先将文本转化为BERT模型可接受的格式
3.构建模型
我们将使用一个预训练的模型进行微调以识别月份信息
4.模型推理
训练完成后,我们将使用训练好的模型对新文本进行月份识别。
三.实现步骤
1.安装必要的库
pip install torch transformers
2.准备数据
创建一个包含文本和标签的数据集,标签采用BIO标记
解决联合标注问题的最简单的方法,就是将其转化为原始标注问题。标准做法就是使用BIO标注。
BIO标注:将每个元素标注为“B-X”、“I-X”或者“O”。其中,“B-X”表示此元素所在的片段属于X类型并且此元素在此片段的开头,“I-X”表示此元素所在的片段属于X类型并且此元素在此片段的中间位置,“O”表示不属于任何类型。
比如,我们将 X 表示为名词短语(Noun Phrase, NP),则BIO的三个标记为:
(1)B-NP:名词短语的开头
(2)I-NP:名词短语的中间
(3)O:不是名词短语
import pandas as pd
data = {
'text': [
"我计划在今年的5月和10月去旅行,5月份去北京,10月份去上海。",
"另外,我还考虑在7月去广州。"
],
'labels': [
"O O O O O O B-MONTH O B-MONTH O O O O O O B-MONTH O B-MONTH O O O O O O O",
"O O O O O O O B-MONTH O O O O O"
]
}
df = pd.DataFrame(data)
df.to_csv('month_recognition_data.csv', index=False)
3.文本预处理
使用 transformers
库中的 BertTokenizer
进行文本预处理。
from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
def preprocess(texts, labels, tokenizer, max_len=128):
input_ids = []
attention_masks = []
label_ids = []
for text, label in zip(texts, labels):
encoding = tokenizer.encode_plus(
text,
max_length=max_len,
padding='max_length',
truncation=True,
return_attention_mask=True,
return_tensors='pt'
)
input_ids.append(encoding['input_ids'])
attention_masks.append(encoding['attention_mask'])
label_id = [0 if lbl == 'O' else 1 for lbl in label.split()]
label_id = label_id + [0] * (max_len - len(label_id))
label_ids.append(label_id)
return torch.cat(input_ids, dim=0), torch.cat(attention_masks, dim=0), torch.tensor(label_ids)
texts = df['text'].values
labels = df['labels'].values
input_ids, attention_masks, label_ids = preprocess(texts, labels, tokenizer)
4.进行训练
使用预训练的 BERT 模型进行微调。
import torch
from torch.utils.data import DataLoader, TensorDataset, RandomSampler
from transformers import BertForTokenClassification, AdamW
# 创建数据加载器
batch_size = 16
dataset = TensorDataset(input_ids, attention_masks, label_ids)
dataloader = DataLoader(dataset, sampler=RandomSampler(dataset), batch_size=batch_size)
# 加载预训练的 BERT 模型
model = BertForTokenClassification.from_pretrained('bert-base-chinese', num_labels=2)
model.cuda()
# 设置优化器
optimizer = AdamW(model.parameters(), lr=5e-5)
# 训练模型
epochs = 3
for epoch in range(epochs):
model.train()
total_loss = 0
for step, batch in enumerate(dataloader):
batch_input_ids, batch_attention_masks, batch_labels = tuple(t.to('cuda') for t in batch)
model.zero_grad()
outputs = model(batch_input_ids, attention_mask=batch_attention_masks, labels=batch_labels)
loss = outputs.loss
total_loss += loss.item()
loss.backward()
optimizer.step()
avg_loss = total_loss / len(dataloader)
print(f"Epoch {epoch+1}/{epochs} - Loss: {avg_loss}")
5. 模型推理
使用训练好的模型进行月份识别。
def predict(text, model, tokenizer):
model.eval()
encoding = tokenizer.encode_plus(
text,
max_length=128,
padding='max_length',
truncation=True,
return_attention_mask=True,
return_tensors='pt'
)
input_ids = encoding['input_ids'].to('cuda')
attention_mask = encoding['attention_mask'].to('cuda')
with torch.no_grad():
outputs = model(input_ids, attention_mask=attention_mask)
logits = outputs.logits
predictions = torch.argmax(logits, dim=2)
tokens = tokenizer.convert_ids_to_tokens(input_ids[0])
predicted_labels = [label for token, label in zip(tokens, predictions[0].tolist()) if token != '[PAD]']
return predicted_labels
text = "我计划在今年的5月和10月去旅行,5月份去北京,10月份去上海。"
predicted_labels = predict(text, model, tokenizer)
print(predicted_labels)
之后我们很遗憾的发现,该模型要求的数据量远大于我们的数据集,我们采取的方法很难实现我们的要求,在进行训练时loss值持续震荡,对新数据拟合程度不高,因此我们决定放弃该方法,选择其他的方法来实现我们的设想