1>>>>指针网络样例中数据格式为:要求有"text"和"labels" [ { "id": 0, "text": "常建良,男,", "labels": [ [ "T0", "NAME", 0, 3, "常建良" ],[],... ] },{},... ] 2>>>>本项目中处理的是文档分割, 以文档为一个样例,每个句子作为一个Pointer对象。 指针网络样例中在数据处理时,当end位置超过maxlen时直接抛弃这一条标注信息了。 》》》本项目中先忽略:因为实际分档太长需要切分处理时会出现不完整的情况,看看实验结果再分析 处理: 1、随机生成一定数量的样本(文档,已分句), 返回格式:text:[[句子组成的一篇文档],[],[],...], label:[[一篇文档的每个试题的start、end位置], [], ...] 2、文档文本处理-->句子数量判断-->太长(大于510个句子),训练时切割分批处理; 将每个句子转为token_id---->长度限制处理---->模型编码[sent_num, seq_len, hidden_dim] --->句子向量[sent_num, hidden_dim] 批次训练:[bs, sent_num, hidden_dim],bs=1,2,4... 3、文档标签"TOPIC"处理,"labels":[["TOPIC",start,end],["TOPIC",start,end], [],...] 每个topic对应一个试题,start、end表示句子索引,start/end==-1时表示不存在 小批量样本(200个txt样本)训练测试结果【指针网络】: 因为完整文档需要截断(由于内存限制)导致训练时有一定震荡 测试集效果: [eval] precision=0.9657 recall=0.9172 f1_score=0.9408 precision recall f1-score support TOPIC 0.97 0.92 0.94 676 micro-f1 0.97 0.92 0.94 676 验证:发现指针网络中,bert的output采取cls的位置比较好,预测时只用start_pred进行判断 还有编码的token长度尽量长点,不要太短 -------------------------------------------------------- 人工制作样本训练效果(选取1000个):token长度选取的240,lr=2e-5 划分的logit值取0.5时: [eval] precision=0.9348 recall=0.9725 f1_score=0.9533 precision recall f1-score support TOPIC 0.93 0.97 0.95 1018 micro-f1 0.93 0.97 0.95 1018 划分的logit值取0.6时: [eval] precision=0.9399 recall=0.9686 f1_score=0.9540 precision recall f1-score support TOPIC 0.94 0.97 0.95 1018 micro-f1 0.94 0.97 0.95 1018 划分的logit值取0.7时: [eval] precision=0.9444 recall=0.9686 f1_score=0.9564 precision recall f1-score support TOPIC 0.94 0.97 0.96 1018 micro-f1 0.94 0.97 0.96 1018 划分的logit值取0.8时: [eval] precision=0.9498 recall=0.9656 f1_score=0.9576 precision recall f1-score support TOPIC 0.95 0.97 0.96 1018 micro-f1 0.95 0.97 0.96 1018 划分的logit值取0.9时: [eval] precision=0.9586 recall=0.9548 f1_score=0.9567 precision recall f1-score support TOPIC 0.96 0.95 0.96 1018 micro-f1 0.96 0.95 0.96 1018 训练过程中发现loss值震荡比较大,一直在0.2-0.4,不过到第10轮时,出现了更多的0.1-0.2,少部分0.1以下和0.2以上, 但验证集的准确率一直在0.78-0.79,f1一直在0.69,很低。 10万样本训练一轮8小时,很慢,训练到前3轮时,loss值还一直处于0.3-0.5,还待继续训练; 【后发现】:评估指标计算的时候有误差,差一点也算错,实际上需要局部调整(比如只判断start位置是否相等即可,以为题与题之间往往是挨着的) 所以样本标注中,可以不考虑单独隔开题型行或试卷开头的非题目信息 此外,在训练中,当lr = 1e-4,other_lr = 3e-4,出现训练一半时,loss变得很大,验证集的precision、recall和f1_score都变成了0 训练完的模型说明: PointerNet_topic_ner_model_release_test.pt:基于1000份样本训练10轮得到; PointerNet_topic_ner_model_release_2.pt:基于10w or 6w份样本训练2轮得到; 调整了根据预测标签进行试题切分的策略后测试集的f1值还不错! checkpoints/PointerNet_topic_ner_model_with_2_task_release_1.pt:基于10w 份样本训练2轮得到,f1:0.9767 checkpoints/PointerNet_topic_ner_model_with_2_task_release_2.pt:基于10w 份样本训练3轮得到,验证集f1:0.9779, 测试集f1:0.9792 2024.4.26 接下来:还需重新训练,用:去除了空句子的样本 + lr设为1e-5 + 试题内容判断一起训练 样本缺失一种“全是答案”情况,还需生成一批样本,只针对必须含有详细答案的情况, 若是答案只有ABCD,无意义;先沟通冯重生总结一下大概的类型! 数据样本清洗后格式简化,如何与源文档建立联系?==>见predictor.py 2024.4.28:验证了“将试题内容判断(是否属于试题内容)”加入一起训练,方案实践可行。 2024.4.30:测试了一套学生卷,发现答案部分也准确分割出来了 2024.4.30接下来:1、数学、物理学生卷答案需总结大概样式; 2、将训练好的模型部署为服务,请模型切题融合到原来的结构化解析服务中; 3、基于相同数据训练一个题型判断模型。题型类别包含数学和物理中所有题型 训练数据格式处理只改标签,其他不变; 模型结构:取bert输出后dropout,再接个线性层或2个线性层; 加多个任务一起训练:粗分:选择、填空、解答、实验... 细分:单选、多选、单空、多空