2023年高校大数据挑战赛
A题 中文文本纠错
原题再现:
中文文本纠错的任务主要是针对中文文本中出现的错误进行检测和纠正,属于人工智能自然语言处理的研究子方向。中文文本纠错通常使用的场景有政务公文、裁判文书、新闻出版等,中文文本纠错对于以中文作为母语的使用者更为适用。基于此,本赛题主要选取中文母语者撰写的网络文本为校对评测数据,要求参赛者从拼写错误、语法错误、语病错误等多个方面考察中文文本纠错系统的自然语言理解能力和纠错能力。
【数据说明及其使用方法】
1、本次赛题选择网络文本作为纠错数据,要求参赛者从中检测并纠正错误,实现中文文本纠错系统。数据中包含的错误类型有:拼写错误,包括别字和别词;语法错误,包括冗余、缺失、乱序;语病错误,包括语义重复及句式杂糅。
2、本赛题提供的训练数据及验证数据见“数据集.zip”,训练集规模为10万句,验证集规模为1000句。参赛队伍也可以使用公开数据集及其他开放型数据对模型进行训练。
3、训练数据使用方法:
训练数据文件中,每一行为一条训练数据,每一条训练数据为json格式,ID字段为数据ID,source字:段为待纠正文本,target字段为纠正后的文本。训练数据样例:{“ID”: “ID18423310”, “source”: “洛赞曾经看到安妮在她的头发上戴着一条红色缎带,并称这对她来说太“年轻化”,郡钩位骄傲小姐回答说:“我队伍中的人总是年轻”。”,“target”: “洛赞曾经看到安妮在她的头发上戴着一条红色缎带,并称这对她来说太“年轻化”,这位骄傲的小姐回答说:“我的队伍中的人总是年轻”。”}
4、验证集使用方式:
具体的输入、输出格式如下:
输入:输入文件每行包含句子ID及相对应的待校对句子,句子ID及相对应的待校对句子之间用“\t”进行分割。
输出:输出文件每行包含句子ID及对应的纠错结果。纠错结果中每处错误包含错误位置、错误类型、错误字词及正确字词。每处错误及多处错误间均以英文逗号分隔,文件编码采用utf-8编码。
输入文件示例:pid=0011-1 关于瑞典时装公司拒绝使用新疆产品的言轮在华引发广泛声讨和抵制浪潮。pid=0011-2 给老百姓包括少数民族群众提供更多的就业机会,一般正常人都都会觉得是件好事。pid=0012-1 第三局比赛俄罗女排的气势被完全压制。pid=0011-4 因为他们自己上历史真的就这么干了上百年,所以现在以己度人;
输出文件示例,:pid=0011-1, 20, 别字, 轮, 论, pid=0011-2, 28, 冗余, 都, , pid=0012-1, 7, 缺失, , 斯, pid=0011-4, 6, 乱序, 上历史, 历史上,
【相关评价标准】
采用字级(Character Level)评价标准,基于整个测试集所有汉字的错误检测或纠正结果确定。错误检测(ErrorDetection)评估的是错误位置的侦测效果,错误纠正(ErrorCorrection)评估的是对应位置错误修正的效果。对于每个维度的评测,统一使用准确率(Precision)、召回率(Recall)和F1作为评价指标。
0 基于赛题提供的数据,请自主查阅资料,选择合适的方法完成如下任务:
任务一:分析数据集“train_large_v2.json”,自主进行数据预处理,选择合适的指标用于中文文本纠错,并说明选择指标的原因。
任务二:根据赛题的描述,请分析问题,并对比业界主流的解决问题方案,提出你的解决问题的思路,并设计相关模型。
任务三:使用任务二所构建的模型,对所提供的数据集进行模型训练,并纠正验证集中文本的中文错误。
任务四:对比分析优化过程中各个模型、训练方案的优劣势,自主选取评价方式和评价指标评估模型的优劣,并总结分析相关内容。
任务五:探究中文文本中每类错误的主要原因,找出相关的特征属性,并进行模式识别,挖掘可能存在的模式和规则。
整体求解过程概述(摘要)
随着国际交流的多元化,中文变得越来越具有吸引力。由于中文文本的语序与其他语序差别较大,许多中文学习者很难掌握中文的语序规则。因此,中文文本的词语语序纠错变得越来越重要。中文语法中文文本错误纠错通常分为两类:一类为拼写错误纠错,另一类为语法错误纠错并包含词语冗余、词语缺失、词语选择和词语语序(乱序)。本文针对中文文本的错误纠错进行研究,从经典的神经网络入手解决中文文本错误的问题。
针对问题1,首先分析数据集“train_large_v2.json”,其次构建数据集预处理的流程:语料清洗、去停用词、繁转简体、切分字词、生成标签。最后采用词向量表示和序列到序列的文本纠错的相关技术,为后续词语语序纠错模型及其改进打下了基础。
针对问题 2,构建了基于经典神经网络模型的词语语序纠错模型。鉴于人工提取特征过程中易造成信息丢失,而经典神经网络模型在特征提取中取得的优异性能,本文分别采用Bi-GRU、CNN和Transformer 经典神经网络用于序列到序列的词语语序纠错任务,并详细的分析模型的结构及原理。
针对问题3,在问题2所构建模型的基础上,首先在阿里云服务器上进行实验,基于Python3.6 和 Torch1.4.0 的 Linux 环境中进行模型的训练,其次对基于经典神经的词语语序纠错模型相关参数进行设定,最终纠正验证集中的中文错误,具体结果在附录所示。
针对问题4,采用字级(Character Level)评价标准,基于整个测试集所有汉字的错误检测或纠正结果确定。由于本文中文拼写纠错模型集检错与纠错为一体,因此根据具体实验设置了一些特定指标,分别为:误报率/错误识别率(FPR),检测准确率(DA),检测精确率(DP),检测召回率(DR),检测F值(DF),纠错准确率(CA),纠错精确率(CP),纠错召回率(CR)和纠错F值(CF)。其次引入了动态规划提高模型纠错效率,使用平滑技术应对数据稀疏问题。最后结果表明本文提出的基于Transformer模型实验结果接近平均水平,误报率/错误识别率FPR为0.1218较低,表现较好,其余指标也皆优于其他模型。
针对问题5,通过对前几个问题的分析总结,采用K-means算法进行聚类,验证集输入句子数为969条,含有错误的句子数480条,别字错误280个,冗余错误59个,缺失错误88个,乱序错误11个,语义重复73个,句式杂糅27个。结果显示中文文本中每类错误的主要原因为:别字错误排名第一(35%),词语缺失错误排第二(32%),语义重复排第三(20.5%)。
本文最后讨论了模型的优缺点,并对模型的应用与推广做了进一步的思考。
模型假设:
假设1:假设数据预处理之后的数据均为准确数据。
假设2:假设未在给出数据集内的其他因素对文本错误无显著影响。
假设3:假设所调查的相关影响因素数据都比较准确。
假设4:给定的数据集可全面体现整体情况。
问题重述:
针对于问题一,使用附件中的数据,进行数据预处理,选择合适的指标用于中文文本纠错,并说明选择指标的原因。
针对于问题二,分析问题,并对比业界主流的解决问题方案,并提出解决问题的思路,并设计相关模型。
针对于问题三,使用问题二所构建的模型,对所提供的数据集进行模型训练,并纠正验证集中文本的中文错误。
针对于问题四,对比分析优化过程中各个模型、训练方案的优劣势,自主选取评价方式和评价指标评估模型的优劣,并总结分析相关内容。
针对于问题五,探究中文文本中每类错误的主要原因,找出相关的特征属性,并进行模式识别,挖掘可能存在的模式和规则。
模型的建立与求解整体论文缩略图
全部论文及程序请见下方“ 只会建模 QQ名片” 点击QQ名片即可
程序代码:
部分程序如下:
import torch
import torch.nn as nn
import torch.optim as optim
from transformers import BertTokenizer, BertModel
# 超参数
MAX_LEN = 128
BATCH_SIZE = 32
EPOCHS = 10
LEARNING_RATE = 0.001
# 加载BERT模型和tokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
bert_model = BertModel.from_pretrained('bert-base-chinese')
class EntityModel(nn.Module):
def __init__(self, bert_model, hidden_size, num_tags):
super(EntityModel, self).__init__()
self.bert = bert_model
self.dropout = nn.Dropout(0.1)
self.bilstm = nn.LSTM(bidirectional=True, input_size=hidden_size, hidden_size=hidden_size // 2,
batch_first=True)
self.fc = nn.Linear(hidden_size, num_tags)
self.crf = CRF(num_tags)
def forward(self, input_ids, attention_mask, labels=None):
outputs = self.bert(input_ids, attention_mask=attention_mask)
sequence_output = outputs[0]
sequence_output = self.dropout(sequence_output)
lstm_output, _ = self.bilstm(sequence_output)
logits = self.fc(lstm_output)
if labels is not None:
loss = -self.crf(logits, labels, mask=attention_mask.byte())
return loss
else:
tags = self.crf.decode(logits, mask=attention_mask.byte())
return tags
# 数据预处理
with open('train_large_v2.json', 'r', encoding='utf-8') as file:
lines = file.readlines()
# 转换每一行的内容并写入新的txt文件
with open('output.txt', 'w', encoding='utf-8') as file:
for line in lines:
data = eval(line) # 将字符串转换为字典
source = data['source'] # 获取source字段的值
target = data['target'] # 获取target字段的值
source = source.replace(" ", "") # 去除source字段中的空格
target = target.replace(" ", "") # 去除target字段中的空格
file.write(f"{source} {target}\n") # 将转换后的内容写入新文件
def tokenize_and_preserve_labels(text, labels):
tokenized_text = []
token_labels = []
for word, label in zip(text, labels):
tokenized_word = tokenizer.tokenize(word)
n_subwords = len(tokenized_word)
tokenized_text.extend(tokenized_word)
token_labels.extend([label] * n_subwords)
return tokenized_text, token_labels
def pad_sequences(sequences, max_len, padding_value=0):
padded_sequences = torch.zeros((len(sequences), max_len)).long()
for i, seq in enumerate(sequences):
seq_len = len(seq)
if seq_len <= max_len:
padded_sequences[i, :seq_len] = torch.tensor(seq)
else:
padded_sequences[i, :] = torch.tensor(seq[:max_len])
return padded_sequences
def train(model, optimizer, train_dataloader):
model.train()
total_loss = 0
for step, batch in enumerate(train_dataloader):
input_ids = batch['input_ids'].to(device)
attention_mask = batch['attention_mask'].to(device)
labels = batch['labels'].to(device)
loss = model(input_ids, attention_mask, labels)
total_loss += loss.item()
optimizer.zero_grad()
loss.backward()
optimizer.step()
avg_train_loss = total_loss / len(train_dataloader)
return avg_train_loss