基于 pytorch-lightning
和 transformers
框架实现各类 NLP
任务
- 搭建好
pytorch GPU
深度学习环境
conda create -n pytorch python=3.8
conda activate pytorch
conda install pytorch cudatoolkit -c pytorch
- 安装
lightningnlp
pip install lightningnlp
- 在
https://pytorch-geometric.com/whl/
中找到与torch
版本对应的torch_scatter
,下载后使用pip
安装到环境中
import torch
print(torch.__version__) # 1.12.0
print(torch.version.cuda) # 11.3
# 以python=3.8, torch=1.12.0, cuda=11.3为例
wget https://data.pyg.org/whl/torch-1.12.0%2Bcu113/torch_scatter-2.1.0%2Bpt112cu113-cp38-cp38-linux_x86_64.whl
pip install torch_scatter-2.1.0+pt112cu113-cp38-cp38-linux_x86_64.whl
本项目也提供了docker安装方式
训练数据示例
{
"text": "以色列大规模空袭开始!伊朗多个军事目标遭遇打击,誓言对等反击",
"label": "news_military"
}
模型 | 论文 | 备注 |
---|---|---|
fc | 全连接层分类 | |
mdp | Multi-Sample Dropout for Accelerated Training and Better Generalization. | 使用 MultiSampleDropout ,类似于模型融合 |
训练代码示例
import os
os.environ['TRANSFORMERS_NO_ADVISORY_WARNINGS'] = 'true'
import pytorch_lightning as pl
from pytorch_lightning.loggers import WandbLogger # 需要安装wandb
from transformers import BertTokenizerFast
from lightningnlp.callbacks import LoggingCallback
from lightningnlp.task.text_classification import (
TextClassificationDataModule,
TextClassificationTransformer,
)
pl.seed_everything(seed=42)
pretrained_model_name_or_path = "hfl/chinese-roberta-wwm-ext" # 预训练模型
tokenizer = BertTokenizerFast.from_pretrained(pretrained_model_name_or_path)
dm = TextClassificationDataModule(
tokenizer=tokenizer,
train_batch_size=16, # 训练集batch_size
validation_batch_size=16, # 验证集batch_size
num_workers=16, # 多进程加载数据
dataset_name="datasets/tnews", # 训练数据所在目录
train_file="train.json", # 训练集文件名
validation_file="dev.json", # 验证集文件名
train_max_length=256,
cache_dir="datasets/tnews", # 数据缓存路径
)
model = TextClassificationTransformer(
downstream_model_name="fc", # 模型名称
downstream_model_type="bert", # 预训练模型类型
pretrained_model_name_or_path=pretrained_model_name_or_path,
tokenizer=tokenizer,
label_map=dm.id2label,
learning_rate=2e-5,
output_dir="outputs/tnews/fc", # 模型保存路径
)
model_ckpt = pl.callbacks.ModelCheckpoint(
dirpath="outputs/tnews/fc",
filename="best_model",
monitor="val_accuracy",
save_top_k=1,
mode="max",
)
wandb_logger = WandbLogger(project="Text Classification", name="fc")
trainer = pl.Trainer(
logger=wandb_logger,
accelerator="gpu",
devices=1,
max_epochs=12,
val_check_interval=0.5,
gradient_clip_val=1.0,
callbacks=[model_ckpt, LoggingCallback()]
)
trainer.fit(model, dm)
from lightningnlp.task.text_classification import TextClassificationPipeline
pipeline = TextClassificationPipeline(model_name_or_path="outputs/tnews/fc", model_name="fc", model_type="bert")
text = "以色列大规模空袭开始!伊朗多个军事目标遭遇打击,誓言对等反击"
print(pipeline(text))
训练数据示例
{
"text": "结果上周六他们主场0:3惨败给了中游球队瓦拉多利德,近7个多月以来西甲首次输球。",
"entities": [
{
"id": 0,
"entity": "瓦拉多利德",
"start_offset": 20,
"end_offset": 25,
"label": "organization"
},
{
"id": 1,
"entity": "西甲",
"start_offset": 33,
"end_offset": 35,
"label": "organization"
}
]
}
模型 | 论文 | 备注 |
---|---|---|
softmax | 全连接层序列标注并使用 BIO 解码 |
|
crf | Conditional Random Fields: Probabilistic Models for Segmenting and Labeling Sequence Data | 全连接层+条件随机场,并使用 BIO 解码 |
cascade-crf | 先预测实体再预测实体类型 | |
span | 使用两个指针网络预测实体起始位置 | |
global-pointer | GlobalPointer:用统一的方式处理嵌套和非嵌套NER、Efficient GlobalPointer:少点参数,多点效果 | |
mrc | A Unified MRC Framework for Named Entity Recognition. | 将实体识别任务转换为阅读理解问题,输入为实体类型模板+句子,预测对应实体的起始位置 |
tplinker | TPLinker: Single-stage Joint Extraction of Entities and Relations Through Token Pair Linking. | 将实体识别任务转换为表格填充问题 |
lear | Enhanced Language Representation with Label Knowledge for Span Extraction. | 改进 MRC 方法效率问题,采用标签融合机制 |
w2ner | Unified Named Entity Recognition as Word-Word Relation Classification. | 统一解决嵌套实体、不连续实体的抽取问题 |
cnn | An Embarrassingly Easy but Strong Baseline for Nested Named Entity Recognition. | 改进 W2NER 方法,采用卷积网络提取实体内部token之间的关系 |
训练代码示例
import os
os.environ['TRANSFORMERS_NO_ADVISORY_WARNINGS'] = 'true'
import pytorch_lightning as pl
from pytorch_lightning.loggers import WandbLogger
from transformers import BertTokenizerFast
from lightningnlp.callbacks import LoggingCallback
from lightningnlp.task.named_entity_recognition import (
CRFNerDataModule,
NamedEntityRecognitionTransformer,
)
pl.seed_everything(seed=42)
pretrained_model_name_or_path = "hfl/chinese-roberta-wwm-ext" # 预训练模型
tokenizer = BertTokenizerFast.from_pretrained(pretrained_model_name_or_path)
dm = CRFNerDataModule(
tokenizer=tokenizer,
train_batch_size=16, # 训练集batch_size
validation_batch_size=16, # 验证集batch_size
num_workers=16, # 多进程加载数据
dataset_name="xusenlin/cmeee", # huggingface数据集
train_max_length=256,
validation_max_length=256,
cache_dir="datasets/cmeee", # 数据缓存路径
task_name="cmeee-bert-crf", # 自定义任务名称
is_chinese=True,
)
model = NamedEntityRecognitionTransformer(
downstream_model_name="crf", # 模型名称
downstream_model_type="bert", # 预训练模型类型
pretrained_model_name_or_path=pretrained_model_name_or_path,
tokenizer=tokenizer,
labels=dm.label_list,
learning_rate=2e-5,
average="micro",
output_dir="outputs/cmeee/crf", # 模型保存路径
)
model_ckpt = pl.callbacks.ModelCheckpoint(
dirpath="outputs/cmeee/crf",
filename="best_model",
monitor="val_f1_micro",
save_top_k=1,
mode="max",
)
wandb_logger = WandbLogger(project="Named Entity Recognition", name="cmeee-bert-crf")
trainer = pl.Trainer(
logger=wandb_logger,
accelerator="gpu",
devices=1,
max_epochs=12,
val_check_interval=0.5,
gradient_clip_val=1.0,
callbacks=[model_ckpt, LoggingCallback()]
)
trainer.fit(model, dm)
本项目在 huggingface 上提供了一个训练好的模型作为示例可供测试和使用,运行以下代码会自动下载模型并进行预测
from pprint import pprint
from lightningnlp.task.named_entity_recognition import NerPipeline
pipline = NerPipeline(model_name_or_path="xusenlin/cmeee-global-pointer", model_name="global-pointer", model_type="bert")
text = "结果上周六他们主场0:3惨败给了中游球队瓦拉多利德,近7个多月以来西甲首次输球。"
pprint(pipline(text))
训练数据示例
{
"text": "查尔斯·阿兰基斯(Charles Aránguiz),1989年4月17日出生于智利圣地亚哥,智利职业足球运动员,司职中场,效力于德国足球甲级联赛勒沃库森足球俱乐部",
"spo_list": [
{
"predicate": "出生地",
"object_type": "地点",
"subject_type": "人物",
"object": "圣地亚哥",
"subject": "查尔斯·阿兰基斯"
},
{
"predicate": "出生日期",
"object_type": "Date",
"subject_type": "人物",
"object": "1989年4月17日",
"subject": "查尔斯·阿兰基斯"
}
]
}
模型 | 论文 | 备注 |
---|---|---|
casrel | A Novel Cascade Binary Tagging Framework for Relational Triple Extraction. | 两阶段关系抽取,先抽取出句子中的主语,再通过指针网络抽取出主语对应的关系和宾语 |
tplinker | TPLinker: Single-stage Joint Extraction of Entities and Relations Through Token Pair Linking. | 将关系抽取问题转换为主语-宾语的首尾连接问题 |
spn | Joint Entity and Relation Extraction with Set Prediction Networks. | 将关系抽取问题转为为三元组的集合预测问题,采用 Encoder-Decoder 框架 |
prgc | PRGC: Potential Relation and Global Correspondence Based Joint Relational Triple Extraction. | 先抽取句子的潜在关系类型,然后对于给定关系抽取出对应的主语-宾语对,最后通过全局对齐模块过滤 |
pfn | A Partition Filter Network for Joint Entity and Relation Extraction. | 采用类似 LSTM 的分区过滤机制,将隐藏层信息分成实体识别、关系识别和共享三部分,对与不同的任务利用不同的信息 |
grte | A Novel Global Feature-Oriented Relational Triple Extraction Model based on Table Filling. | 将关系抽取问题转换为单词对的分类问题,基于全局特征抽取模块循环优化单词对的向量表示 |
gplinker | GPLinker:基于GlobalPointer的实体关系联合抽取 |
训练代码示例
import os
os.environ['TRANSFORMERS_NO_ADVISORY_WARNINGS'] = 'true'
import pytorch_lightning as pl
from pytorch_lightning.loggers import WandbLogger
from transformers import BertTokenizerFast
from lightningnlp.callbacks import LoggingCallback
from lightningnlp.task.relation_extraction import (
GPLinkerDataModule,
RelationExtractionTransformer,
)
pl.seed_everything(seed=42)
pretrained_model_name_or_path = "hfl/chinese-roberta-wwm-ext" # 预训练模型
tokenizer = BertTokenizerFast.from_pretrained(pretrained_model_name_or_path)
dm = GPLinkerDataModule(
tokenizer=tokenizer,
train_batch_size=16, # 训练集batch_size
validation_batch_size=16, # 验证集batch_size
num_workers=16, # 多进程加载数据
dataset_name="xusenlin/duie", # huggingface数据集
train_max_length=256,
validation_max_length=256,
cache_dir="datasets/duie", # 数据缓存路径
task_name="duie-bert-gplinker", # 自定义任务名称
is_chinese=True,
)
model = RelationExtractionTransformer(
downstream_model_name="gplinker", # 模型名称
downstream_model_type="bert", # 预训练模型类型
pretrained_model_name_or_path=pretrained_model_name_or_path,
tokenizer=tokenizer,
predicates=dm.predicate_list,
learning_rate=2e-5,
average="micro",
output_dir="outputs/duie/gplinker", # 模型保存路径
)
model_ckpt = pl.callbacks.ModelCheckpoint(
dirpath="outputs/duie/gplinker",
filename="best_model",
monitor="val_f1_micro",
save_top_k=1,
mode="max",
)
wandb_logger = WandbLogger(project="Relation Extraction", name="duie-bert-gplinker")
trainer = pl.Trainer(
logger=wandb_logger,
accelerator="gpu",
devices=1,
max_epochs=12,
val_check_interval=0.5,
gradient_clip_val=1.0,
callbacks=[model_ckpt, LoggingCallback()]
)
trainer.fit(model, dm)
本项目在 huggingface 上提供了一个训练好的模型作为示例可供测试和使用,运行以下代码会自动下载模型并进行预测
from pprint import pprint
from lightningnlp.task.relation_extraction import RelationExtractionPipeline
pipline = RelationExtractionPipeline(model_name_or_path="xusenlin/duie-gplinker", model_name="gplinker", model_type="bert")
text = "查尔斯·阿兰基斯(Charles Aránguiz),1989年4月17日出生于智利圣地亚哥,智利职业足球运动员,司职中场,效力于德国足球甲级联赛勒沃库森足球俱乐部。"
pprint(pipline(text))
-
UIE(Universal Information Extraction):Yaojie Lu等人在ACL-2022中提出了通用信息抽取统一框架
UIE
。 -
该框架实现了实体抽取、关系抽取、事件抽取、情感分析等任务的统一建模,并使得不同任务间具备良好的迁移和泛化能力。
-
为了方便大家使用
UIE
的强大能力,PaddleNLP借鉴该论文的方法,基于ERNIE 3.0
知识增强预训练模型,训练并开源了首个中文通用信息抽取模型UIE
。 -
该模型可以支持不限定行业领域和抽取目标的关键信息抽取,实现零样本快速冷启动,并具备优秀的小样本微调能力,快速适配特定的抽取目标。
👉 命名实体识别
from pprint import pprint
from lightningnlp.task.uie import UIEPredictor
# 实体识别
schema = ['时间', '选手', '赛事名称']
# uie-base模型已上传至huggingface,可自动下载,其他模型只需提供模型名称将自动进行转换
uie = UIEPredictor("xusenlin/uie-base", schema=schema)
pprint(uie("2月8日上午北京冬奥会自由式滑雪女子大跳台决赛中**选手谷爱凌以188.25分获得金牌!")) # Better print results using pprint
输出:
[{'时间': [{'end': 6,
'probability': 0.9857378532924486,
'start': 0,
'text': '2月8日上午'}],
'赛事名称': [{'end': 23,
'probability': 0.8503089953268272,
'start': 6,
'text': '北京冬奥会自由式滑雪女子大跳台决赛'}],
'选手': [{'end': 31,
'probability': 0.8981548639781138,
'start': 28,
'text': '谷爱凌'}]}]
👉 实体关系抽取
from pprint import pprint
from lightningnlp.task.uie import UIEPredictor
# 关系抽取
schema = {'竞赛名称': ['主办方', '承办方', '已举办次数']}
# uie-base模型已上传至huggingface,可自动下载,其他模型只需提供模型名称将自动进行转换
uie = UIEPredictor("xusenlin/uie-base", schema=schema)
pprint(uie("2022语言与智能技术竞赛由**中文信息学会和**计算机学会联合主办,百度公司、**中文信息学会评测工作委员会和**计算机学会自然语言处理专委会承办,已连续举办4届,成为全球最热门的中文NLP赛事之一。")) # Better print results using pprint
输出:
[{'竞赛名称': [{'end': 13,
'probability': 0.7825402622754041,
'relations': {'主办方': [{'end': 22,
'probability': 0.8421710521379353,
'start': 14,
'text': '**中文信息学会'},
{'end': 30,
'probability': 0.7580801847701935,
'start': 23,
'text': '**计算机学会'}],
'已举办次数': [{'end': 82,
'probability': 0.4671295049136148,
'start': 80,
'text': '4届'}],
'承办方': [{'end': 39,
'probability': 0.8292706618236352,
'start': 35,
'text': '百度公司'},
{'end': 72,
'probability': 0.6193477885474685,
'start': 56,
'text': '**计算机学会自然语言处理专委会'},
{'end': 55,
'probability': 0.7000497331473241,
'start': 40,
'text': '**中文信息学会评测工作委员会'}]},
'start': 0,
'text': '2022语言与智能技术竞赛'}]}]
👉 事件抽取
from pprint import pprint
from lightningnlp.task.uie import UIEPredictor
# 事件抽取
schema = {"地震触发词": ["地震强度", "时间", "震中位置", "震源深度"]}
# uie-base模型已上传至huggingface,可自动下载,其他模型只需提供模型名称将自动进行转换
uie = UIEPredictor("xusenlin/uie-base", schema=schema)
pprint(uie("**地震台网正式测定:5月16日06时08分在云南临沧市凤庆县(北纬24.34度,东经99.98度)发生3.5级地震,震源深度10千米。")) # Better print results using pprint
输出:
[{'地震触发词': {'end': 58,
'probability': 0.9977425932884216,
'relation': {'地震强度': [{'end': 56,
'probability': 0.9980800747871399,
'start': 52,
'text': '3.5级'}],
'时间': [{'end': 22,
'probability': 0.9853301644325256,
'start': 11,
'text': '5月16日06时08分'}],
'震中位置': [{'end': 50,
'probability': 0.7874020934104919,
'start': 23,
'text': '云南临沧市凤庆县(北纬24.34度,东经99.98度)'}],
'震源深度': [{'end': 67,
'probability': 0.9937973618507385,
'start': 63,
'text': '10千米'}]},
'start': 56,
'text': '地震'}}]
👉 评论观点抽取
from pprint import pprint
from lightningnlp.task.uie import UIEPredictor
# 事件抽取
schema = {'评价维度': ['观点词', '情感倾向[正向,负向]']}
# uie-base模型已上传至huggingface,可自动下载,其他模型只需提供模型名称将自动进行转换
uie = UIEPredictor("xusenlin/uie-base", schema=schema)
pprint(uie("店面干净,很清静,服务员服务热情,性价比很高,发现收银台有排队")) # Better print results using pprint
输出:
[{'评价维度': [{'end': 20,
'probability': 0.9817040258681473,
'relations': {'情感倾向[正向,负向]': [{'probability': 0.9966142505350533,
'text': '正向'}],
'观点词': [{'end': 22,
'probability': 0.957396472711558,
'start': 21,
'text': '高'}]},
'start': 17,
'text': '性价比'},
{'end': 2,
'probability': 0.9696849569741168,
'relations': {'情感倾向[正向,负向]': [{'probability': 0.9982153274927796,
'text': '正向'}],
'观点词': [{'end': 4,
'probability': 0.9945318044652538,
'start': 2,
'text': '干净'}]},
'start': 0,
'text': '店面'}]}]
👉 情感分类
from pprint import pprint
from lightningnlp.task.uie import UIEPredictor
# 事件抽取
schema = '情感倾向[正向,负向]'
# uie-base模型已上传至huggingface,可自动下载,其他模型只需提供模型名称将自动进行转换
uie = UIEPredictor("xusenlin/uie-base", schema=schema)
pprint(uie("这个产品用起来真的很流畅,我非常喜欢")) # Better print results using pprint
输出:
[{'情感倾向[正向,负向]': {'end': 0,
'probability': 0.9990023970603943,
'start': 0,
'text': '正向'}}]
如果 LightningNLP
对您的研究有帮助,欢迎引用
@misc{=lightningnlp,
title={LightningNLP: An Easy-to-use NLP Library},
author={senlin xu},
howpublished = {\url{https://github.com/xusenlinzy/lightningblocks}},
year={2022}
}
我们借鉴了Lightning-transformers
关于模型使用的优秀设计,在此对Lightning-transformers
作者及其开源社区表示感谢。