基于PaddleNLP的⼩样本学习策略库EFL实现中⽂科学⽂献学科分类
基于Few-shot Learning实现中⽂科学⽂献学科分类
近年来,机器学习和深度学习在许多领域中取得了成功。但深度学习模型的成功,却依赖于⼤量训练数据。⽽在现实世界的真实场景中,某些类别只有少量数据或少量标注数据,⽽对⽆标签数据进⾏标注将会消耗⼤量的时间和⼈⼒。相反,⼈类只需要通过少量数据即可实现快速学习。例如,⼀个智⼒正常的初中⽣,甚⾄是⼩学⽣只需要学习过少量的古诗词,就能按照⾃⼰的想法创造出新的古诗词,这就是机器学习和⼈类学习之间存在的差距。⼩样本学习(Few-Shot Learning)的概念被提出,有助于机器学习更多接近⼈类思维。
Few-Shot任务旨在研究如何从少量有监督的训练样本中学习出具有良好泛化性的模型,对训练数据很少或监督数据获取成本极⾼的应⽤场景有很⼤价值。
⼀、数据集简介
⼩样本学习测评基准
FewCLUE是为中⽂NLP定制的⼩样本学习测评基准。其中有针对9个场景的⼦数据集:
PRSTMT:电商评论情感分析;
CSLDCP:中⽂科学⽂献学科分类;
TNEWS:新闻分类;
IFLYTEK:APP应⽤描述主题分类;
OCNLI: ⾃然语⾔推理;
BUSTM: 对话短⽂本匹配;
CHID:成语阅读理解;
CSL:摘要判断关键词判别;
CLUEWSC: 代词消歧
中⽂科学⽂献学科分类数据集
本项⽬主要基于FewCLUE⾥的CSLDCP:中⽂科学⽂献学科分类数据集。该数据集⼀共有7979条数据,其中包括67个类别的⽂献类别,这些类别来⾃于分别归属于13个⼤类,范围从社会科学到⾃然科学,⽂本为⽂献的中⽂摘要。
数据样例
{"content": "通过⼏年的观察和实践,初步掌握了盆栽菊花的栽培技术及⽅法,并进⾏了总结,以满⾜⼈们对花卉消费的需求,提⾼观赏植物的商品价值,为企业化⽣产的盆菊提供技术指导。",
"label": "园艺学",
"id": 1770}
{"content": "GPS卫星导航定位精度的⾼低很⼤程度上取决于站星距离(即伪距)的测量误差.载波相位平滑伪距在保证环路参数满⾜动态应⼒误差要求的基础上。。。本⽂详细论述了载波相位平滑伪距的原理和⼯程实现⽅法,并进⾏了仿真验证.",
"label": "航空宇航科学与技术",
"id": 979}
每⼀条数据有三个属性,从前往后分别是 id,ntence,label。其中label标签,Positive 表⽰正向,Negative 表⽰负向。
数据加载
PaddleNLP 内置了 FewCLUE 数据集,可以直接⽤来进⾏训练、评估、预测。
# 安装最新版本的PaddleNLP
!python -m pip install --upgrade paddlenlp==2.0.2-i /pypi/simple
from paddlenlp.datats import load_datat
# 通过指定 "fewclue" 和数据集名字 name="csldcp" 即可⼀键加载 FewCLUE 中的 csldcp 数据集
train_ds, public_test_ds, test_ds = load_datat("fewclue", name="csldcp", splits=("train_0","test_public","test"))
查看训练集、验证集和测试集的第⼀条数据:
print(train_ds.data[0])
{'content': '为保证发动机在不同的转速时都具有最佳点⽕提前⾓,同时提⾼摩托车的防盗能⼒,提出⼀种基于转速匹配的点⽕提前⾓和防盗控制⽅法.利⽤磁电机脉冲计算发动机转速,线⽣调整点⽕信号的触发延迟时间,实现点⽕提前⾓的精确控制.根据转速信息,结合GSM和GPS对点⽕器进⾏远程点
⽕使能控制,设计数字点⽕器实现对摩托车进⾏跟踪与定位,并给出点⽕器的软硬件结构和详细设计.台架测试和道路测试表明所设计的基于发动机转速的数字点⽕器点⽕提前⾓控制精确,点⽕性能好,防盗能⼒强、范围⼴.', 'label': '控制科学与⼯程', 'id': 805}
print(public_test_ds.data[0])
{'content': '对⿊龙江省东部五星Cu-Ni-Pt-Pd矿床的矿体和与成矿有关的镁铁质杂岩的PGE-Au以及铁族、亲铜元素的地球化学特征研究表明:它们均以亏损Cr、I PGE和富集Ni、Co、Cu、Pt和Pd(Pt<Pd)为特征,与成矿有关的镁铁质岩来⾃地幔部分熔融形成的⽞武岩浆,岩浆(房)演化以结晶分离为主,伴随熔离作⽤.结合地质和岩相学特征,初步确定铜镍硫化物矿化在岩浆熔离作⽤的基础上产⽣,⽽铂钯矿化则主要发⽣在岩浆期后,以热液交代作⽤为主产⽣.因此,五星矿床是⼀个岩浆型铜镍硫化物和铂钯热液型复合的内⽣矿床.', 'label': '地质学/地质资源与地质⼯程', 'id': 0}
print(test_ds.data[0])
{'id': 0, 'content': '⾦⼭⾦矿床是中国西天⼭地区⼀个⼤型浅成低温热液型⾦矿,矿体产出主要受各种断裂构造控制.在多年勘探⼯作的基础上,通过野外填图和⼤量的勘探线剖⾯分析,笔者总结出断裂构造活动经历了成矿前、热液成矿期和成矿后3期.断裂控矿基本规律是:北西向断裂总体控制矿床的分布位置,南北向断裂晚期活动造成叠加富集成矿,北东向断裂早期伴随中酸性岩脉活动,成矿后活动
造成矿体断开和升降,东西向-北西西断裂早期伴随⽕⼭喷发活动,成矿后活动切断南北向矿体.同时还总结了矿区的找矿评价标志.'}
⼆、通过Entailment构建⼩样本学习器
论⽂地址:
⼤型预训练语⾔模型(LMs)作为⼩样本学习器已经表现出了⾮凡的能⼒,然⽽,他们的成功在很⼤程度上取决于模型参数量的提升,这使得其训练,部署和服务具有挑战性。
在《Entailment as Few-Shot Learner》中,作者提出了⼀种新的⽅法,名为EFL(Entailment as Few-shot Learner),它可以将⼩的语⾔模型变成更好的⼩样本学习器。这种⽅法的关键思想是将潜在的NLP任务重新表述为⼀个entailment任务,然后只需⽤8个例⼦就可微调模型。
EFL⽅法可以:
1. 与基于⽆监督的对⽐学习的数据增强⽅法⾃然结合;
2. 容易扩展到多语⾔的⼩样本学习。
对18个标准的NLP任务进⾏的系统评估表明,这种⽅法将现有的各种SOTA⼏率学习⽅法提⾼了12%,并产⽣了与500倍⼤的模型(如GPT-3)具备竞争性的⼩样本性能。
⼀开始我还不太理解Entailment,我看了看EFL的训练源代码:
model = ansformers.ErnieForSequenceClassification.from_pretrained('ernie-1.0', num_class=2)
⽽ErnieForSequenceClassification的源码在PaddleNLP/paddlenlp/transformers/ernie/modeling.py,具体内容如下所⽰:
task_name: FewCLUE 中的数据集名字
device: 使⽤ cpu/gpu 进⾏训练
negative_num: 负样本采样个数,对于多分类任务,负样本数量对效果影响很⼤。负样本数量参数取值范围为 [1, class_num - 1] save_dir: 模型存储路径
batch_size:每个GPU/CPU的训练批⼤⼩
learning_rate:Adam的初始学习速率
epochs:要执⾏的训练总数
max_q_length: ⽂本的最⼤截断长度
!python -u -m paddle.distributed.launch --gpus "0" \
work/train.py \
--task_name "csldcp" \
--device gpu \
--negative_num 66 \
--save_dir "./checkpoints" \
--batch_size 32 \
--learning_rate 1e-5 \
--epochs 2 \
--max_q_length 512
----------- Configuration Arguments -----------
gpus: 0
heter_worker_num: None
heter_workers:
http_port: None
ips: 127.0.0.1
log_dir: log
nproc_per_node: None
run_mode: None
rver_num: None
rvers:
training_script: work/train.py
training_script_args: ['--task_name', 'csldcp', '--device', 'gpu', '--negative_num', '66', '--save_dir', './checkpoints', '--batch_size', '32', '--learning_rate', '1e-5', '--epochs', '2', '--max_q_length', '512']
worker_num: None
workers:
------------------------------------------------
WARNING 2021-06-27 17:55:35,673 launch.py:357] Not found distinct arguments and compiled with cuda or xpu. Default u collective mode
launch train in GPU mode!
INFO 2021-06-27 17:55:35,674 launch_utils.py:510] Local start 1 process. First process distributed environment info (Only For Debug):
+=======================================================================================+
| Distributed Envs Value |
+---------------------------------------------------------------------------------------+
| PADDLE_TRAINER_ID 0 |
| PADDLE_CURRENT_ENDPOINT 127.0.0.1:41017 |
| PADDLE_TRAINERS_NUM 1 |
| PADDLE_TRAINER_ENDPOINTS 127.0.0.1:41017 |
| PADDLE_RANK_IN_NODE 0 |
| PADDLE_LOCAL_DEVICE_IDS 0 |
| PADDLE_WORLD_DEVICE_IDS 0 |
| FLAGS_lected_gpus 0 |
| FLAGS_lected_accelerators 0 |
+=======================================================================================+
INFO 2021-06-27 17:55:35,675 launch_utils.py:514] details abouts PADDLE_TRAINER_ENDPOINTS can be found in log/endpoints.log, and detail running logs maybe found in log/workerlog.0
launch proc_id:22646 idx:0
[2021-06-27 17:55:37,237] [ INFO] - Already cached /home/aistudio/.paddlenlp/models/ernie-1.0/ernie_v1_chn_ba.pdparams
W0627 17:55:37.238456 22646 :404] Plea NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.0, Runtime API Vers ion: 10.1
W0627 17:55:37.243487 22646 :422] device: 0, cuDNN Version: 7.6.
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/layers.py:1297: UrWarning: Skip loading for classifier.weight. classifier.weight is not found in the provided dict.
warnings.warn(("Skip loading for {}. ".format(key) + str(err)))
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/layers.py:1297: UrWarning: Skip loading for classifier.bias. cl assifier.bias is not found in the provided dict.
warnings.warn(("Skip loading for {}. ".format(key) + str(err)))
[2021-06-27 17:55:42,191] [ INFO] - Found /home/aistudio/.paddlenlp/models/ernie-1.
global step 200, epoch: 1, batch: 200, loss: 0.04065, speed: 0.06 step/s
global step 400, epoch: 1, batch: 400, loss: 0.02934, speed: 0.06 step/s
global step 600, epoch: 1, batch: 600, loss: 0.13510, speed: 0.06 step/s
global step 800, epoch: 1, batch: 800, loss: 0.03925, speed: 0.06 step/s
global step 1000, epoch: 1, batch: 1000, loss: 0.00930, speed: 0.06 step/s
epoch:1, dev_accuracy:58.408, total_num:1784
global step 1200, epoch: 2, batch: 77, loss: 0.01942, speed: 0.01 step/s
global step 1400, epoch: 2, batch: 277, loss: 0.00554, speed: 0.06 step/s
global step 1600, epoch: 2, batch: 477, loss: 0.00251, speed: 0.06 step/s
global step 1800, epoch: 2, batch: 677, loss: 0.00384, speed: 0.06 step/s
global step 2000, epoch: 2, batch: 877, loss: 0.00228, speed: 0.06 step/s
global step 2200, epoch: 2, batch: 1077, loss: 0.01744, speed: 0.06 step/s
epoch:2, dev_accuracy:60.594, total_num:1784
INFO 2021-06-27 19:26:53,708 launch.py:266] Local process completed.
四、模型效果评估