# GPU版本
conda create -n py37testmaas python=3.7
pip install cryptography==3.4.8 tensorflow-gpu==1.15.5 torch==1.11.0 torchvision==0.12.0 torchaudio==0.11.0
pip install "modelscope[nlp]" -f https://modelscope.oss-cn-beijing.aliyuncs.com/releases/repo.html
# CPU版本
conda create -n py37testmaas python=3.7
pip install cryptography==3.4.8 tensorflow==1.15.5 torch==1.11.0 torchvision==0.12.0 torchaudio==0.11.0
pip install "modelscope[nlp]" -f https://modelscope.oss-cn-beijing.aliyuncs.com/releases/repo.html
点击右上角快速体验按钮,选在CPU或GPU机器运行实例,创建notebook执行推理或训练代码即可
第一次启动时可能会花费一些时间创建索引
地址信息处理是对地址相关文本的自动化挖掘、理解与关联。这项技术广泛地应用在社会生活的各个场景之中。例如我们常用的地图软件中就用到了大量的地址信息处理技术来构建POI库,实现POI搜索与推荐;在外卖物流行业中,对于地址的解析、定位准确率的提升则直接带来运力成本的大量降低;目前在诸多挪车、外呼、报警等场景下也用上了地址自动化处理技术,大大节省了接线员定位事故发生地的时间;在零售行业中,地址也是会员体系管理的核心要素。
地址由于其丰富的表达以及与地图联动的多模态属性,一直是自动化处理的一个难题。达摩院联合高德发布了多任务多模态地址预训练底座MGeo模型。该模型基于地图-文本多模态架构,使用多任务预训练(MOMETAS)技术融合了注意力对抗预训练(ASA)、句子对预训练(MaSTS)、多模态预训练,训练得到适合于多类地址任务的预训练底座,为下游广泛的地址处理任务带来性能提升。
在ModelScope中我们开源的版本是基于开源地址数据以及开源地图OpenStreetMap训练的MGeo预训练底座以及其在GeoGLUE地理语义评测榜中多个任务的下游模型。
地址信息处理涵盖了多种的NLP任务,从输入的形式来看可以分为:
我们针对这三种输入形态设计了三种预训练任务:注意力对抗预训练(ASA)、句子对预训练(MaSTS)、多模态预训练。并用多任务预训练(MOMETAS)技术将这三种预训练任务进行动态组合,训练得到适合于多类地址任务的预训练底座。
我们使用网络公开的地理语义数据与开源地图训练了MGeo社区版,在GeoGLUE上评测了MGeo模型与当下一些主流预训练模型的效果,模型规模均为base。
门址地址要素解析 | 地理实体对齐 | Query-POI库召回 | Query-POI相关性排序 | 地址Query成分分析 | WhereWhat切分 | |
---|---|---|---|---|---|---|
Bert | 90.41 | 78.88 | 24.59 | 81.52 | 65.06 | 69.65 |
Roberta | 90.79 | 78.84 | 39.37 | 83.20 | 64.65 | 66.44 |
Ernie | 90.63 | 79.44 | 24.03 | 81.82 | 66.48 | 67.73 |
Nezha | 91.17 | 79.77 | 35.31 | 81.38 | 67.70 | 70.13 |
StructBert | 91.22 | 78.83 | 43.10 | 83.51 | 67.47 | 68.74 |
MGeo社区版 | 92.39 | 79.99 | 54.18 | 86.09 | 70.19 | 79.55 |
为了推动地址处理技术社区发展,我们提炼了常用的地址处理任务并建立了地理语义理解能力评测基准GeoGLUE。我们使用MGeo底座在GeoGLUE中提供的任务数据集上进行了训练,训练效果见上一部分模型效果。训好的模型目前提供一键试用。
常见的门址地址作为寄递或外卖服务中用户位置的表达,一般包含以下几类信息:
基于MGeo训练好的模型已提供一键使用,详情见ModelCard : 点我试用训练好的门址地址要素解析模型
日常生活中输入的地理文本可以为以下几种形式:
基于MGeo训练好的模型已提供一键使用,详情见ModelCard : 点我试用训练好的地理实体对齐模型
POI(Point Of Interest,兴趣点)搜索是地图类应用的核心功能,需要根据用户的query找到对应地图上的POI。一个POI的组成通常是其对应的地址描述以及经纬度描述。本任务需要在给定用户query以及候选POI列表的情况下,根据POI与query的相关性程度对POI进行排序。
基于MGeo训练好的模型已提供一键使用,详情见ModelCard : 点我试用训练好的Query-POI相关性排序
用户在地图类服务中输入地址query用以查询相关地理元素信息。地址query除了包含标准门址信息外通常还包含:
基于MGeo训练好的模型已提供一键使用,详情见ModelCard : 点我试用训练好的地址Query成分分析模型
当一条地址包含多个地点描述时,通常需要对其进行切分,将原始地址切为where和what两部分。例如:
三里屯酒吧
这条描述,包含两个部分:三里屯、酒吧。用户的意图是想找三里屯附近的酒吧。因此需要将原始地址的“三里屯”识别为where部分,“酒吧”识别为what部分。
本任务目标是将输入地址做where和what的切分与识别。
基于MGeo训练好的模型已提供一键使用,详情见ModelCard : 点我试用训练好的WhereWhat切分模型
使用MGeo直接对输入的地址进行编码
from modelscope.models import Model
from modelscope.utils.constant import Tasks
from modelscope.preprocessors.nlp import Tokenize
model_id = 'damo/mgeo_backbone_chinese_base'
model = Model.from_pretrained(model_id, task=Tasks.backbone)
tokenizer = Tokenize.from_pretrained(model_id)
text = '文一西路'
output = tokenizer(text, return_tensors='pt')
enc_res = model(**output)
print(enc_res)
当用户有自己标注好的数据希望基于MGeo底座进行训练时,可使用自定义训练功能。我们针对序列标注、分类、排序三类任务提供示例代码。
以GeoGLUE的门址地址要素解析任务为例
import os
from modelscope.msdatasets import MsDataset
from modelscope.metainfo import Trainers, Preprocessors
from modelscope.utils.constant import ModelFile, Tasks
from modelscope.trainers import build_trainer
tmp_dir = 'tmp_dir'
def finetune(model_id,
train_dataset,
eval_dataset,
name=Trainers.nlp_text_ranking_trainer,
cfg_modify_fn=None,
**kwargs):
kwargs = dict(
model=model_id,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
work_dir=tmp_dir,
cfg_modify_fn=cfg_modify_fn,
**kwargs)
os.environ['LOCAL_RANK'] = '0'
trainer = build_trainer(name=name, default_args=kwargs)
trainer.train()
results_files = os.listdir(tmp_dir)
def cfg_modify_fn(cfg):
cfg.task = 'token-classification'
cfg['dataset'] = {
'train': {
'labels': label_enumerate_values,
'first_sequence': 'tokens',
'label': 'ner_tags',
'sequence_length': 128
}
}
cfg['preprocessor'] = {
'type': 'token-cls-tokenizer',
'padding': 'max_length'
}
cfg.train.max_epochs = 1
cfg.train.dataloader.batch_size_per_gpu = 32
cfg.train.optimizer.lr = 3e-5
cfg.train.hooks = [
{
'type': 'CheckpointHook',
'interval': 1
},
{
'type': 'TextLoggerHook',
'interval': 100
}, {
'type': 'IterTimerHook'
}, {
'type': 'EvaluationHook',
'by_epoch': True
}]
cfg.train.lr_scheduler.total_iters = int(len(train_dataset) / 32) * cfg.train.max_epochs
return cfg
def get_label_list(labels):
unique_labels = set()
for label in labels:
unique_labels = unique_labels | set(label)
label_list = list(unique_labels)
label_list.sort()
return label_list
# load dataset
train_dataset = MsDataset.load('GeoGLUE', subset_name='GeoETA', split='train', namespace='damo')
dev_dataset = MsDataset.load('GeoGLUE', subset_name='GeoETA', split='validation', namespace='damo')
label_enumerate_values = get_label_list(train_dataset._hf_ds['train']['ner_tags'] + dev_dataset._hf_ds['validation']['ner_tags'])
model_id = 'damo/mgeo_backbone_chinese_base'
finetune(
model_id=model_id,
train_dataset=train_dataset['train'],
eval_dataset=dev_dataset['validation'],
cfg_modify_fn=cfg_modify_fn,
name='nlp-base-trainer')
output_dir = os.path.join(tmp_dir, ModelFile.TRAIN_OUTPUT_DIR)
print(f'model is saved to {output_dir}')
如果需要从本地load用户自定义数据,可以先将数据处理为如下格式,并保存为train.json和dev.json:
{"tokens": ["浙", "江", "杭", "州", "市", "江", "干", "区", "九", "堡", "镇", "三", "村", "村", "一", "区"], "ner_tags": ["B-prov", "E-prov", "B-city", "I-city", "E-city", "B-district", "I-district", "E-district", "B-town", "I-town", "E-town", "B-community", "I-community", "E-community", "B-poi", "E-poi"]}
然后替换原流程中的train_dataset和dev_dataset为:
local_train = 'train.json'
local_test = 'dev.json'
train_dataset = MsDataset.load('json', data_files={'train': [local_train]})
dev_dataset = MsDataset.load('json', data_files={'validation': [local_test]})
以GeoGLUE的地理实体对齐任务为例
import os
from modelscope.msdatasets import MsDataset
from modelscope.metainfo import Trainers, Preprocessors
from modelscope.utils.constant import ModelFile, Tasks
from modelscope.trainers import build_trainer
tmp_dir = 'tmp_dir'
def finetune(model_id,
train_dataset,
eval_dataset,
name=Trainers.nlp_text_ranking_trainer,
cfg_modify_fn=None,
**kwargs):
kwargs = dict(
model=model_id,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
work_dir=tmp_dir,
cfg_modify_fn=cfg_modify_fn,
**kwargs)
os.environ['LOCAL_RANK'] = '0'
trainer = build_trainer(name=name, default_args=kwargs)
trainer.train()
results_files = os.listdir(tmp_dir)
def cfg_modify_fn(cfg):
cfg.task = Tasks.sentence_similarity
cfg['preprocessor'] = {'type': Preprocessors.sen_sim_tokenizer}
cfg.train.dataloader.batch_size_per_gpu = 64
cfg.evaluation.dataloader.batch_size_per_gpu = 64
cfg.train.optimizer.lr = 2e-5
cfg.train.max_epochs = 1
cfg['dataset'] = {
'train': {
'labels': ['not_match', 'partial_match', 'exact_match'],
'first_sequence': 'sentence1',
'second_sequence': 'sentence2',
'label': 'label',
'sequence_length': 128
}
}
cfg['evaluation']['metrics'] = "seq-cls-metric"
cfg.train.hooks = [
{
'type': 'CheckpointHook',
'interval': 1
},
{
'type': 'TextLoggerHook',
'interval': 100
}, {
'type': 'IterTimerHook'
}, {
'type': 'EvaluationHook',
'by_epoch': True
}]
cfg.train.lr_scheduler.total_iters = int(len(train_dataset) / 32) * cfg.train.max_epochs
return cfg
# load dataset
train_dataset = MsDataset.load('GeoGLUE', subset_name='GeoEAG', split='train', namespace='damo')
dev_dataset = MsDataset.load('GeoGLUE', subset_name='GeoEAG', split='validation', namespace='damo')
model_id = 'damo/mgeo_backbone_chinese_base'
finetune(
model_id=model_id,
train_dataset=train_dataset['train'],
eval_dataset=dev_dataset['validation'],
cfg_modify_fn=cfg_modify_fn,
name='nlp-base-trainer')
output_dir = os.path.join(tmp_dir, ModelFile.TRAIN_OUTPUT_DIR)
print(f'model is saved to {output_dir}')
如果需要从本地load用户自定义数据,可以先将数据处理为如下格式,并保存为train.json和dev.json:
{"sentence1": "兰花小区四小区五幢五单元", "sentence2": "乌兰小区四区5栋乌兰小区4区5栋", "label": "not_match"}
如果只有一个句子,去掉sentence2字段即可。更新原始代码中的labels字段为新数据集的标签:
cfg['dataset'] = {
'train': {
'labels': ['not_match', 'partial_match', 'exact_match'],
'first_sequence': 'sentence1',
'second_sequence': 'sentence2',
'label': 'label',
'sequence_length': 128
}
}
然后替换原流程中的train_dataset和dev_dataset为:
local_train = 'train.json'
local_test = 'dev.json'
train_dataset = MsDataset.load('json', data_files={'train': [local_train]})
dev_dataset = MsDataset.load('json', data_files={'validation': [local_test]})
以GeoGLUE的Query-POI排序任务为例
import os
from modelscope.msdatasets import MsDataset
from modelscope.metainfo import Trainers, Preprocessors
from modelscope.utils.constant import ModelFile, Tasks
from modelscope.trainers import build_trainer
tmp_dir = 'tmp_dir'
def finetune(model_id,
train_dataset,
eval_dataset,
name=Trainers.nlp_text_ranking_trainer,
cfg_modify_fn=None,
**kwargs):
kwargs = dict(
model=model_id,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
work_dir=tmp_dir,
cfg_modify_fn=cfg_modify_fn,
**kwargs)
os.environ['LOCAL_RANK'] = '0'
trainer = build_trainer(name=name, default_args=kwargs)
trainer.train()
results_files = os.listdir(tmp_dir)
def cfg_modify_fn(cfg):
neg_sample = 19
cfg.task = 'text-ranking'
cfg['preprocessor'] = {'type': 'mgeo-ranking'}
cfg.train.optimizer.lr = 5e-5
cfg['dataset'] = {
'train': {
'type': 'mgeo',
'query_sequence': 'query',
'pos_sequence': 'positive_passages',
'neg_sequence': 'negative_passages',
'text_fileds': ['text', 'gis'],
'qid_field': 'query_id',
'neg_sample': neg_sample,
'sequence_length': 64
},
'val': {
'type': 'mgeo',
'query_sequence': 'query',
'pos_sequence': 'positive_passages',
'neg_sequence': 'negative_passages',
'text_fileds': ['text', 'gis'],
'qid_field': 'query_id'
},
}
cfg.evaluation.dataloader.batch_size_per_gpu = 16
cfg.train.dataloader.batch_size_per_gpu = 3
cfg.train.dataloader.workers_per_gpu = 16
cfg.evaluation.dataloader.workers_per_gpu = 16
cfg['evaluation']['metrics'] = "mrr@1"
cfg.train.max_epochs = 1
cfg.model['neg_sample'] = neg_sample
cfg.model['gis_num'] = 2
cfg.model['finetune_mode'] = 'multi-modal'
cfg.train.hooks = [{
'type': 'CheckpointHook',
'interval': 1
}, {
'type': 'TextLoggerHook',
'interval': 100
}, {
'type': 'IterTimerHook'
}, {
'type': 'EvaluationHook',
'by_epoch': True
}]
# lr_scheduler的配置
cfg.train.lr_scheduler = {
"type": "LinearLR",
"start_factor": 1.0,
"end_factor": 0.5,
"total_iters": int(len(train_ds) / cfg.train.dataloader.batch_size_per_gpu) * cfg.train.max_epochs,
"options": {
"warmup": {
"type": "LinearWarmup",
"warmup_iters": int(len(train_ds) / cfg.train.dataloader.batch_size_per_gpu)
},
"by_epoch": False
}
}
return cfg
# load dataset
train_dataset = MsDataset.load('GeoGLUE', subset_name='GeoTES-rerank', split='train', namespace='damo')
dev_dataset = MsDataset.load('GeoGLUE', subset_name='GeoTES-rerank', split='validation', namespace='damo')
train_ds = train_dataset['train']
dev_ds = dev_dataset['validation']
model_id = 'damo/mgeo_backbone_chinese_base'
finetune(
model_id=model_id,
train_dataset=train_ds,
eval_dataset=dev_ds,
cfg_modify_fn=cfg_modify_fn,
name=Trainers.mgeo_ranking_trainer)
output_dir = os.path.join(tmp_dir, ModelFile.TRAIN_OUTPUT_DIR)
print(f'model is saved to {output_dir}')
如果需要从本地load用户自定义数据,可以先将数据处理为如下格式,并保存为train.json和dev.json:
{"query_id": 0, "query": "丽华公寓(通惠中路)向北检验检疫科学研究所", "query_gis": "[[], [], [], [], [], \"120.59443087451544,30.315515932852602\"]", "idx": "0", "positive_passages": [{"text": "杭州中新街(惠港二路)76饶平县检验检疫局", "gis": "[[], [], [], [], [], \"120.20509044775532,30.076259797983873\"]"}], "negative_passages": [{"text": "杭州中新街", "gis": "[[], [], [], [], [], \"120.20509044775532,30.076259797983873\"]"}]}
例子中的gis信息为空缺状态,用户可补充上自己的gis信息,模型在有gis和无gis的场景下均可以进行推断,gis信息的加入可以提升模型效果。更新原始代码中的neg_sample数量为自定义训练集的负例个数。
然后替换原流程中的train_ds和dev_ds为:
local_train = 'train.json'
local_test = 'dev.json'
train_dataset = MsDataset.load('json', data_files={'train': [local_train]})
dev_dataset = MsDataset.load('json', data_files={'validation': [local_test]})
train_ds = train_dataset.to_hf_dataset()
dev_ds = dev_dataset.to_hf_dataset()
@article{DBLP:journals/corr/abs-2210-10293,
author = {Hongqiu Wu and
Ruixue Ding and
Hai Zhao and
Boli Chen and
Pengjun Xie and
Fei Huang and
Min Zhang},
title = {Forging Multiple Training Objectives for Pre-trained Language Models
via Meta-Learning},
journal = {CoRR},
volume = {abs/2210.10293},
year = {2022},
url = {https://doi.org/10.48550/arXiv.2210.10293},
doi = {10.48550/arXiv.2210.10293},
eprinttype = {arXiv},
eprint = {2210.10293},
timestamp = {Mon, 24 Oct 2022 18:10:06 +0200},
biburl = {https://dblp.org/rec/journals/corr/abs-2210-10293.bib},
bibsource = {dblp computer science bibliography, https://dblp.org}
}
@misc{2301.04283,
Author = {Ruixue Ding and Boli Chen and Pengjun Xie and Fei Huang and Xin Li and Qiang Zhang and Yao Xu},
Title = {A Multi-Modal Geographic Pre-Training Method},
Year = {2023},
Eprint = {arXiv:2301.04283},
}
@misc{2206.12608,
Author = {Hongqiu Wu and Ruixue Ding and Hai Zhao and Pengjun Xie and Fei Huang and Min Zhang},
Title = {Adversarial Self-Attention for Language Understanding},
Year = {2022},
Eprint = {arXiv:2206.12608},
}
如果您在使用中遇到任何困难,请钉钉搜索加入答疑群,群号:44837352(官方答疑)26735013283(技术交流)