蒙icp备网站建设,东坑东莞网站建设,南京网站建设 奥美通全网营销,vr功能网站建设司法阅读理解
1 任务目标
1.1 任务说明
裁判文书中包含了丰富的案件信息#xff0c;比如时间、地点、人物关系等等#xff0c;通过机器智能化地阅读理解裁判文书#xff0c;可以更快速、便捷地辅助法官、律师以及普通大众获取所需信息。 本次任务覆盖多种法律文书类型比如时间、地点、人物关系等等通过机器智能化地阅读理解裁判文书可以更快速、便捷地辅助法官、律师以及普通大众获取所需信息。 本次任务覆盖多种法律文书类型包括民事、刑事、行政问题类型为多步推理即对于给定问题只通过单句文本很难得出正确回答模型需要结合多句话通过推理得出答案。
1.2 评分要求
分数由两部分组成。首先读懂已有代码并添加适量注释。使用已有代码在训练数据上进行训练并且完成开发集评测这部分占60%评分依据为模型的开发集性能和报告报告主要包括对于模型基本原理的介绍需要同学阅读代码进行学习。 第二部分进行进一步的探索和尝试我们将在下一小节介绍可能的尝试并在报告中汇报尝试的方法以及结果这部分占40%。同学需要提交代码和报告在报告中对于两部分的实验都进行介绍。
1.3 探索和尝试
使用2019年的阅读理解数据集CJRC作为辅助数据集帮助模型提高阅读理解能力使用别的预训练语言模型完成该实验例如THUNLP提供的司法BERT对于新的模型架构进行探索例如加入图神经网络GNN来加强模型的推理能力
1.4 参考资料 CAIL2020——阅读理解 [NLP_Novice/5.司法阅读理解(CAIL 2020) (github.com)](https://github.com/yingcongshaw/NLP_Novice/tree/529278f3afb89947b4e657973618fb73c5ec2d45/5.司法阅读理解(CAIL 2020)) 2 数据集
2.1 数据说明
本任务数据集包括约5100个问答对其中民事、刑事、行政各约1700个问答对均为需要多步推理的问题类型。为了进行评测按照9:1的划分数据集分为了训练集和测试集。注意 该数据仅用于本课程的学习请勿进行传播。
发放的文件为train.json和dev.json为字典列表字典包含字段为
_id案例的唯一标识符。context案例内容抽取自裁判文书的事实描述部分。数据格式与HotpotQA数据格式一致不过只包含一个篇章篇章包括标题第一句话和切割后的句子列表。question针对案例提出的问题每个案例只标注一个问题。answer问题的回答包括片段、YES/NO、据答几种类型对于拒答类答案应该是unknown。supporting_facts回答问题的依据是个列表每个元素包括标题第一句话和句子编号从0开始。
同学们需根据案例描述和问题给出答案及答案依据最终会综合两部分的效果并作为评判依据评价方法与HotpotQA一致。
我们提供基础的模型代码在baseline目录下
2.2 数据处理代码
本案例通过 data_process.py 对数据进行处理该代码主要功能是读取问答数据文件解析并转换数据为适合BERT模型输入的格式并保存处理后的数据。通过定义Example和InputFeatures类代码能够有效地组织和处理问答样本的数据。下面对该代码进行解释。 导入必要的库 argparse用于解析命令行参数。json用于解析JSON格式的数据。gzip和pickle用于数据的压缩和序列化。tqdm用于显示处理进度。BertTokenizer来自transformers库用于文本的分词处理。os用于操作文件和目录。 定义数据模型类 Example用于存储单个问答样本的原始数据包括问题ID、类型、文档标记、问题文本等信息。 class Example(object):def __init__(self, qas_id, qas_type, doc_tokens, question_text, sent_num, sent_names, sup_fact_id, para_start_end_position, sent_start_end_position, entity_start_end_position, orig_answer_textNone, start_positionNone, end_positionNone):# 初始化问答样本的数据InputFeatures用于存储转换后的特征数据这些特征将用于模型的输入包括经过分词处理的文档和问题、输入ID、掩码和段落ID等。 class InputFeatures(object):def __init__(self, qas_id, doc_tokens, doc_input_ids, doc_input_mask, doc_segment_ids, query_tokens, query_input_ids, query_input_mask, query_segment_ids, sent_spans, sup_fact_ids, ans_type, token_to_orig_map, start_positionNone, end_positionNone):# 初始化转换后的特征数据数据读取函数(read_examples) def read_examples(full_file):# 打开并读取输入文件JSON 格式with open(full_file, r, encodingutf-8) as reader:full_data json.load(reader)...return examples # 返回所有样本列表读取JSON格式的HotpotQA数据文件。处理每个问题案例包括分词、标注支持事实、确定答案位置等。创建Example对象的列表。 特征转换函数(convert_examples_to_features) def convert_examples_to_features(examples, tokenizer, max_seq_length, max_query_length):# max_query_length 50features []for (example_index, example) in enumerate(tqdm(examples)):...features.append(InputFeatures(...))return features # 返回所有转换后的特征将Example对象转换为InputFeatures对象包括使用Bert分词器处理文档和问题文本。处理答案文本将字符位置转换为分词后的标记位置。创建句子跨度、支持事实ID等特征。对特征数据进行填充以满足模型输入的序列长度要求。 辅助函数 check_in_full_paras检查答案是否在段落中。_largest_valid_index获取有效的最大索引。get_valid_spans获取有效的跨度列表。_improve_answer_span改进答案的标记跨度以更好地匹配注释答案。 主函数(if __name__ __main__:) 解析命令行参数包括输出文件路径、是否进行小写处理、序列最大长度等。加载Bert分词器。读取并处理数据将原始数据转换为模型输入所需的特征数据。序列化特征数据并保存到文件。
2.3 数据处理 下载Bert 首先需要下载合适的分词器模型如 chinese_bert_wwm 下载链接。 训练数据预处理 执行以下命令运行 data_process.py 对训练数据进行数据处理得到 train_example.pkl.gz 与 train_feature.pkl.gz。 --example_output 将原始数据处理为示例数据存储在 Example 对象中。 --feature_output 将示例数据转换为模型可以直接使用的特征数据存储在 InputFeatures 对象中。 !python baseline/data_process.py \--tokenizer_path ./models/chinese_bert_wwm \--full_data ./data/train.json \--example_output ./output/data/chinese-bert-wwm/train_example.pkl.gz \--feature_output ./output/data/chinese-bert-wwm/train_feature.pkl.gz 测试数据预处理 执行以下命令运行 data_process.py 对测试数据进行数据处理得到 dev_example.pkl.gz 与 dev_feature.pkl.gz。 !python baseline/data_process.py \--tokenizer_path ./models/chinese_bert_wwm \--full_data ./data/dev.json \--example_output ./output/data/chinese-bert-wwm/dev_example.pkl.gz \--feature_output ./output/data/chinese-bert-wwm/dev_feature.pkl.gz 3 模型训练
3.1 中文预训练的模型
本实验需要通过自己寻找一个比较好的中文预训练模型用于训练数据通过寻找找到了以下中文预训练模型。 Chinese-BERT-wwm Chinese-BERT-wwm (Whole Word Masking BERT for Chinese) 是一种基于 BERT 的中文预训练模型专门针对中文文本进行了优化仓库为 ymcui/Chinese-BERT-wwm: Pre-Training with Whole Word Masking for Chinese BERT中文BERT-wwm系列模型 (github.com)。该模型的主要特点是采用了全词掩码策略即在训练过程中掩码的是整个词而不是单个汉字。这种策略有助于模型更好地理解词汇级别的信息而不仅仅是字符级别的信息。 模型特点 Whole Word Masking在训练时将整个词作为一个单元进行掩码提高模型对词汇的理解能力。适用领域适用于各种中文自然语言处理任务如文本分类、问答系统、文本生成等。使用场景适合需要精确理解中文词汇语义的任务。 Chinese-RoBERTa-wwm-ext Chinese-RoBERTa-wwm-ext 是在 Chinese-BERT-wwm 基础上进一步优化的模型。RoBERTa (Robustly optimized BERT approach) 是 BERT 的改进版仓库为 ymcui/Chinese-BERT-wwm: Pre-Training with Whole Word Masking for Chinese BERT中文BERT-wwm系列模型 (github.com)。该模型通过更大的数据集和更长时间的训练提高了模型的性能。Chinese-RoBERTa-wwm-ext 继承了这些改进并结合了全词掩码策略。 模型特点 Robustly Optimized优化了训练过程和超参数增强了模型的鲁棒性和性能。Whole Word Masking继续采用全词掩码策略提高中文词汇理解。Extended Dataset使用了更大规模的数据集进行训练提高了模型的泛化能力。使用场景适合更高精度要求的中文自然语言处理任务。 thunlp_ms thunlp_ms 是由清华大学自然语言处理与社会人文计算实验室 (THUNLP) 提供的一个民事文书BERT预训练模型。数据来源为全部民事文书训练数据大小有2654万篇文书词表大小22554模型大小370MB。仓库为thunlp/OpenCLaP: Open Chinese Language Pre-trained Model Zoo (github.com)下载链接 https://thunlp.oss-cn-qingdao.aliyuncs.com/bert/ms.zip 。 thunlp_xs thunlp_xs 是由清华大学自然语言处理与社会人文计算实验室 (THUNLP) 提供的一个刑事文书BERT预训练模型。数据来源为全部刑事文书训练数据大小有663万篇文书词表大小22554模型大小370MB。仓库为thunlp/OpenCLaP: Open Chinese Language Pre-trained Model Zoo (github.com)下载链接 https://thunlp.oss-cn-qingdao.aliyuncs.com/bert/xs.zip 。
3.2 模型训练代码
本案例通过 run_cail.py 训练和评估基于BERT模型的问答系统。以下是对代码中关键功能的详细介绍 导入必要的库和模块 argparse 用于解析命令行参数。 os.path.join 用于路径拼接。 tqdm 用于显示进度条。 transformers.BertModel 和 transformers.BertConfig 用于加载和配置BERT模型。 transformers.optimization.AdamW 和 transformers.optimization.get_linear_schedule_with_warmup 用于优化和学习率调度。 torch 和 torch.nn 为PyTorch库用于构建和训练神经网络。 全局配置和辅助函数 set_seed 函数设置随机种子确保实验可复现。 数据处理和分发函数 dispatch 函数将数据分发到GPU。 损失计算函数 compute_loss 函数计算模型的损失值包括起始位置、结束位置、类型预测和支持段落的损失。 预测函数 predict 函数在模型评估阶段运行使用模型对数据进行预测并生成预测结果的字典。 训练函数 train_epoch 函数执行一个训练周期调用train_batch函数处理每个批次的数据。 train_batch 函数处理单个批次的数据执行前向传播、损失计算、反向传播和优化器步骤。 主函数 在 if __name__ __main__: 块中脚本执行以下操作 解析命令行参数。 设置GPU数量和随机种子。 初始化数据加载器和数据集。 加载或配置BERT模型。 初始化优化器、学习率调度器和损失函数。 执行训练循环包括训练和评估阶段。 训练和评估循环 训练循环包括多次迭代由 args.epochs 指定每个迭代都会遍历训练数据集。 在训练过程中如果设置了 predict_during_train则在每个epoch的指定步骤进行评估。 训练结束后保存模型的状态字典并记录训练和评估的损失。 混合精度训练 如果 args.fp16 为真则使用Apex库的自动混合精度AMP功能来加速训练并减少内存使用。 数据并行 使用 torch.nn.DataParallel 实现模型的数据并行可以在多个GPU上同时训练模型。 日志记录 训练过程中通过打印语句记录损失和其他统计信息。 结束训练 当达到最大epoch数或满足其他退出条件时脚本将停止训练。
3.3 模型训练 训练指令 输入以下命令进行模型训练本实验分别对以上4个中文预训练模型进行训练。 !python baseline/run_cail.py \--name chinese-bert-wwm \--bert_model ./models/chinese_bert_wwm \--data_dir ./output/data/chinese-bert-wwm \--batch_size 2 \--eval_batch_size 32 \--lr 1e-5 \--gradient_accumulation_steps 4 \--seed 56 \--epochs 25 其中参数含义如下 --name chinese-bert-wwm: --name 指定了运行此次实验的名称或标识这里设置为 chinese-bert-wwm。--bert_model ./models/chinese_bert_wwm: 指定BERT模型的路径。--data_dir ./output/data/chinese-bert-wwm: 指定存放数据的目录数据可能包括预处理后的训练集、验证集等。--batch_size 2: 设置训练时每个batch的大小为2。--eval_batch_size 32: 设置评估时每个batch的大小为32。--lr 1e-5: 设置学习率为 1e-5即0.00001。--gradient_accumulation_steps 4: 设置梯度累积的步数为4这意味着每4个batch执行一次优化器更新。--seed 56: 设置随机种子为56以确保结果的可复现性。--epochs 25: 设置训练的总周期数为25。 训练结果 训练结束后得到了每个epoch的.pth的 checkpoints 文件与.json的 submissions 文件用于后续模型测试。
4 模型测试
4.1 模型测试指标
在自然语言处理NLP和信息检索领域EM、F1、Prec和Recall是几个关键的性能评估指标它们用于衡量模型预测结果的质量。以下是每个指标的详细介绍 Exact Match (EM) - 精确匹配: 精确匹配是衡量预测答案是否与真实答案完全一致的指标。如果两个答案的文本完全相同那么它们被认为是精确匹配的。例如如果真实答案是 “New York”预测答案也是 “New York”则EM为1或100%如果预测答案是 “New york” 或 “纽约”则EM为0因为它们与真实答案不完全相同。 F1 Score (F1) - F1 分数: F1分数是精确度Precision和召回率Recall的调和平均数用于衡量模型的准确性和完整性的平衡。F1分数的范围是0到11表示完美的预测0表示最差的预测。公式为 F 1 2 × ( Precision × Recall Precision Recall ) F1 2 \times \left(\frac{\text{Precision} \times \text{Recall}}{\text{Precision} \text{Recall}}\right) F12×(PrecisionRecallPrecision×Recall)F1分数特别适用于处理不平衡的数据集其中某些类别的样本可能比其他类别多得多。 Precision (Prec) - 精确度: 精确度是指预测为正类别中实际为正类别的比例。换句话说它衡量了所有被模型预测为正确答案中实际上也是正确答案的比例。公式为 Precision T P T P F P \text{Precision} \frac{TP}{TP FP} PrecisionTPFPTP其中TP真正例是正确预测为正的样本数量FP假正例是错误预测为正的样本数量。 Recall (Recall) - 召回率: 召回率也称为真正率或灵敏度它衡量了所有实际正类别中被模型正确预测为正类别的比例。公式为 Recall T P T P F N \text{Recall} \frac{TP}{TP FN} RecallTPFNTP其中FN假负例是被错误预测为负的正样本数量。 SP (Supporting Facts) 结果: 支持事实是指那些直接支撑或解释答案的文本段落或句子。在多跳问答multi-hop QA中答案通常需要依据文档中的多个不同部分进行推理得出这些不同的部分即为支持事实。在评估脚本中update_sp 函数用于计算模型预测的支持事实与真实支持事实之间的匹配程度包括精确度Precision、召回率Recall和F1分数。 Joint 结果: Joint评估考虑了答案的准确性以及支持事实的准确性。在这种评估方式中只有当模型同时正确预测了答案以及所有相关的支持事实时才认为该问题是完全正确的。例如在eval函数中计算联合精确度joint EM时仅当答案的精确匹配EM和支持事实的精确匹配sp_EM同时为真时联合精确度才计为1这反映了模型在整体任务上的表现。
4.2 模型测试代码
本案例没有提供模型测试代码通过 CAIL2020——阅读理解 得到测试代码 evaluate.py 。evalutae.py 是一个用于评估问答系统性能的Python脚本主要用于计算精确匹配Exact Match, EM、F1分数以及其他相关指标。以下是对脚本中关键功能的详细介绍 导入模块 sys: 用于访问与Python解释器密切相关的变量和函数。 ujson: 一个用于解析和生成JSON的库比标准的json库更快。 re: 正则表达式库用于文本匹配。 string: 包含字符串常量和字符串相关的函数。 collections.Counter: 用于计数的容器方便统计元素出现次数。 pickle: 用于序列化和反序列化Python对象。 答案标准化函数 normalize_answer(s): 将答案文本进行标准化处理包括去除文章a, an, the、替换空白字符、去除标点符号和转换为小写。 评估函数 f1_score(prediction, ground_truth): 计算预测答案和真实答案之间的F1分数包括精确度Precision、召回率Recall和F1分数本身。 exact_match_score(prediction, ground_truth): 计算预测答案和真实答案是否完全匹配。 update_answer(metrics, prediction, gold): 更新答案评估指标包括精确匹配、F1分数、精确度和召回率。 支持事实评估函数 update_sp(metrics, prediction, gold): 更新支持事实Supporting Facts, SP的评估指标包括精确匹配、F1分数、精确度和召回率。 主评估函数 eval(prediction_file, gold_file): 读取预测结果文件和真实结果文件然后对每个问题的答案和支持事实进行评估计算整体的评估指标。 联合评估 脚本还计算了答案和支持事实的联合评估指标即在答案精确匹配的情况下支持事实也精确匹配的情况。 主函数 if __name__ __main__: 块是脚本的入口点它使用命令行参数指定的预测结果文件和真实结果文件进行评估并打印出评估结果。
4.3 模型测试
输入以下指令进行模型测试得到每个epoch的测试结果。
for i in range(1,26):!python baseline/evaluate.py ./output/submissions/chinese-bert-wwm/pred_seed_56_epoch_{i}_99999.json ./data/dev.json 测试结果如下
{em: 0.125, f1: 0.19567546419134832, prec: 0.2086390213622355, recall: 0.19941998427586816, sp_em: 0.15079365079365079, sp_f1: 0.25401549508692367, sp_prec: 0.3197751322751322, sp_recall: 0.22890211640211638, joint_em: 0.001984126984126984, joint_f1: 0.03492904180069224, joint_prec: 0.05480599647266315, joint_recall: 0.028516452877447276}
{em: 0.45634920634920634, f1: 0.5561908302303119, prec: 0.5700169126508411, recall: 0.5635363963342302, sp_em: 0.15674603174603174, sp_f1: 0.43485764676240873, sp_prec: 0.5851851851851851, sp_recall: 0.3772156084656083, joint_em: 0.05952380952380952, joint_f1: 0.25640473686157556, joint_prec: 0.3713905252595728, joint_recall: 0.2208404364186486}
{em: 0.49404761904761907, f1: 0.580694477531037, prec: 0.5979415040426944, recall: 0.5836045772516851, sp_em: 0.23015873015873015, sp_f1: 0.589451630820679, sp_prec: 0.6803791887125223, sp_recall: 0.5631283068783066, joint_em: 0.12103174603174603, joint_f1: 0.3814845473719221, joint_prec: 0.4563021126066761, joint_recall: 0.36503795669254235}
... 分别对4个中文预训练模型进行测试结果如下。 chinese-bert-wwm 基础结果 SP (Supporting Facts) 结果 joint 结果 chinese_roberta_wwm_ext 基础结果 SP (Supporting Facts) 结果 joint 结果 thunlp_ms 基础结果 SP (Supporting Facts) 结果 joint 结果 thunlp_xs 基础结果 SP (Supporting Facts) 结果 joint 结果
将 4 个预训练模型训练25轮后的结果列成表格结果如下。
模型/指标emf1precrecallsp_emsp_f1sp_precsp_recalljoint_emjoint_f1joint_precjoint_recallchinese-bert-wwm0.6765870.7602720.7793380.7660720.3690480.7141640.7525040.7185180.2817460.5845570.6266060.593274chinese_roberta_wwm_ext0.6587300.7318370.7572500.7371340.4285710.7491910.7924770.7483800.3174600.5856850.6363130.593407thunlp_ms0.5000000.5851270.5992090.5931840.2599210.6116620.6973540.5910380.1686510.3952910.4569520.387666thunlp_xs0.4880950.5733470.5828910.5868750.1964290.5764920.6548890.5601850.1309520.3747350.4225320.376051
5 探索和尝试
本章使用2019年的阅读理解数据集CJRC作为辅助数据集帮助模型提高阅读理解能力。 转换数据集 2019年的阅读理解数据集CJRC格式与本实验用的数据集格式不同需要先将格式转换为2020年的数据集然后将2个数据集融合。 def convert_context_to_2020(context_2019):把2019年案例内容根据标点符号分句构造成2020年的原始标准格式context_2020[]pattern r,|\.|\:|;|!|\?|:||。||||result_list re.split(pattern, context_2019)context_2020.append(result_list[0])context_2020.append(result_list)return [context_2020]def get_supporting_facts_sen_id(context_2019, answer_start, answer_text):把2019年案例的回答依据构造成2020年的格式。pattern r,|\.|\:|;|!|\?|:||。||||sen_list re.split(pattern, context_2019)answer_index 0sen_id {}for i, sen in enumerate(sen_list):# 在分句后的案例内容中查找行号index sen.find(answer_text)if index 0 :sen_id[i] abs(answer_start - answer_index - index)answer_index len(sen)supporting_fact []supporting_fact.append(sen_list[0])if len(sen_id) 0 :supporting_fact.append(-1)else:supporting_fact.append( min(sen_id, keysen_id.get))return [supporting_fact]train_2019 []
for i, case_2019 in enumerate(full_data_2019[data]):case_2020 {}# 遍历qas, question_2019 {}# 先取question_2019为truefor qa in case_2019[paragraphs][0][qas]:# 过滤answers为空的questionif qa[is_impossible]true and len(qa[answers]) 0 and qa[answers][0][answer_start] !-1:question_2019qabreakif len(question_2019)0: for qa in case_2019[paragraphs][0][qas]:# 过滤answers为空的questionif qa[is_impossible]false and len(qa[answers]) 0 and qa[answers][0][answer_start] !-1:question_2019qaanswer_txt qa[answers][0][text]# 取出answers的text为yes或no的第一个questionif answer_txt.lower() yes or answer_txt.lower() no:breakcase_2020[_id] i5055case_2020[context] convert_context_to_2020(case_2019[paragraphs][0][context])case_2020[question] question_2019[question]case_2020[answer] question_2019[answers][0][text]case_2020[supporting_facts] get_supporting_facts_sen_id(case_2019[paragraphs][0][context],question_2019[answers][0][answer_start],question_2019[answers][0][text])train_2019.append(case_2020)数据训练 !python /home/mw/project/run_cail.py \--name chinese-bert-wwm \--bert_model /home/mw/input/law_QA5449/5 法律智能问答案例/models/chinese_wwm_pytorch \--data_dir /home/mw/input/law_QA5449/chinese-bert-wwm_add2019/chinese-bert-wwm_add2019 \--prediction_path /home/mw/work/law_QA/predictions \--checkpoint_path /home/mw/work/law_QA/checkpoints \--batch_size 2 \--eval_batch_size 32 \--lr 1e-5 \--gradient_accumulation_steps 4 \--seed 56 \--epochs 25模型测试 for i in range(1,26):!python /home/mw/project/evaluate.py /home/mw/work/law_QA/predictions/chinese-bert-wwm/pred_seed_56_epoch_{i}_99999.json /home/mw/input/law_QA5449/5 法律智能问答案例/data/dev.json基础结果 SP (Supporting Facts) 结果 joint 结果 对比数据 模型/指标emf1precrecallsp_emsp_f1sp_precsp_recalljoint_emjoint_f1joint_precjoint_recallchinese-bert-wwm_20190.6547610.7341390.7540810.7367860.3829360.7131560.7739080.6990070.3035710.5648230.6248780.558694chinese-bert-wwm0.6765870.7602720.7793380.7660720.3690480.7141640.7525040.7185180.2817460.5845570.6266060.593274chinese_roberta_wwm_ext0.6587300.7318370.7572500.7371340.4285710.7491910.7924770.7483800.3174600.5856850.6363130.593407thunlp_ms0.5000000.5851270.5992090.5931840.2599210.6116620.6973540.5910380.1686510.3952910.4569520.387666thunlp_xs0.4880950.5733470.5828910.5868750.1964290.5764920.6548890.5601850.1309520.3747350.4225320.376051
发现仅在 sp_prec 、joint_em 两个值取得最高值并没有明显提升。