from google.colab import drive |
Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).
import os |
import os |
from google.colab import drive |
Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).
import os |
import os |
cluener下载链接:数据下载
2.1 数据集划分和数据内容
- 训练集:10748
- 验证集:1343
- 测试集(无标签):1345
- 原始数据存储在json文件中。文件中的每一行是一条单独的数据,一条数据包括一个原始句子以及其上的标签,具体形式如下:
展开看就是:
{"text": "浙商银行企业信贷部叶老桂博士则从另一个角度对五道门槛进行了解读。叶老桂认为,对目前国内商业银行而言,", "label": {"name": {"叶老桂": [[9, 11]]}, "company": {"浙商银行": [[0, 3]]}}}
{"text": "生生不息CSOL生化狂潮让你填弹狂扫", "label": {"game": {"CSOL": [[4, 7]]}}}数据字段解释:
{
"text": "浙商银行企业信贷部叶老桂博士则从另一个角度对五道门槛进行了解读。叶老桂认为,对目前国内商业银行而言,",
"label": {
"name": {
"叶老桂": [
[9, 11],
[32, 34]
]
},
"company": {
"浙商银行": [
[0, 3]
]
}
}
}
以train.json为例,数据分为两列:text & label,其中text列代表文本,label列代表文本中出现的所有包含在10个类别中的实体。例如:
text: "北京勘察设计协会副会长兼秘书长周荫如"
label: {"organization": {"北京勘察设计协会": [[0, 7]]}, "name": {"周荫如": [[15, 17]]}, "position": {"副会长": [[8, 10]], "秘书长": [[12, 14]]}}
其中,organization,name,position代表实体类别,
"organization": {"北京勘察设计协会": [[0, 7]]}:表示原text中,"北京勘察设计协会" 是类别为 "组织机构(organization)" 的实体, 并且start_index为0,end_index为7 (注:下标从0开始计数)
"name": {"周荫如": [[15, 17]]}:表示原text中,"周荫如" 是类别为 "姓名(name)" 的实体, 并且start_index为15,end_index为17
"position": {"副会长": [[8, 10]], "秘书长": [[12, 14]]}:表示原text中,"副会长" 是类别为 "职位(position)" 的实体, 并且start_index为8,end_index为10,同时,"秘书长" 也是类别为 "职位(position)" 的实体,
并且start_index为12,end_index为14
数据分为10个标签类别,分别为: 地址(address),书名(book),公司(company),游戏(game),政府(goverment),电影(movie),姓名(name),组织机构(organization),职位(position),景点(scene) |
地址(address): **省**市**区**街**号,**路,**街道,**村等(如单独出现也标记),注意:地址需要标记完全, 标记到最细。 |
按照不同标签类别统计,训练集数据分布如下(注:一条数据中出现的所有实体都进行标注,如果一条数据出现两个地址(address)实体,那么统计地址(address)类别数据的时候,算两条数据):
【训练集】标签数据分布如下:地址(address):2829
书名(book):1131
公司(company):2897
游戏(game):2325
政府(government):1797
电影(movie):1109
姓名(name):3661
组织机构(organization):3075
职位(position):3052
景点(scene):1462
【验证集】标签数据分布如下:
地址(address):364
书名(book):152
公司(company):366
游戏(game):287
政府(government):244
电影(movie):150
姓名(name):451
组织机构(organization):344
职位(position):425
景点(scene):199
测试训练集句子长度%pylab inline
#最大句子长度50
train_df['text_len'] = train_df['words'].apply(lambda x: len(x))
print(train_df['text_len'].describe())
Populating the interactive namespace from numpy and matplotlib |
平台测试结果:
Roberta指的chinese_roberta_wwm_large模型。(roberta-wwm-large-ext)
模型 BiLSTM+CRF bert-base-chinese Roberta+Softmax Roberta+CRF Roberta+BiLSTM+CRF |
可见,Roberta+lstm和Roberta模型差别不大。
官方处理方法:softmax、crf和span,模型本体和运行代码见:CLUENER2020/pytorch_version/models/albert_for_ner.py | run_ner_crf.py。
为什么使用CRF提升这么大呢? softmax最终分类,只能通过输入判断输出,但是 CRF 可以通过学习转移矩阵,看前后的输出来判断当前的输出。这样就能学到一些规律(比如“O 后面不能直接接 I”“B-brand 后面不可能接 I-color”),这些规律在有时会起到至关重要的作用。
例如下面的例子,A 是没加 CRF 的输出结果,B 是加了 CRF 的输出结果,一看就懂不细说了
本文选取Roberta+lstm+lstm,标注方法选择BIOS。
“B”:(实体开始的token)前缀
“I” :(实体中间的token)前缀
“O”:无特别实体(no special entity)
“S”: 即Single,“S-X”表示该字单独标记为X标签
另外还有BIO、BIOE(“E-X”表示该字是标签X的词片段末尾的终止字)等。
NER作为序列标注任务,输出需要确定实体边界和类型。如果预先进行了分词处理,由于分词工具原本就无法保证绝对正确的分词方案,势必会产生错误的分词结果,而这将进一步影响序列标注结果。因此,我们不进行分词,在字层面进行BIOS标注。
我们采用BIOS标注对原始标签进行转换。B-X 代表实体X的开头,I-X代表实体的结尾,O代表不属于任何类型,S表示改词本身就是一个实体。范例:{"text": "浙商银行企业信贷部叶老桂博士则从另一个角度对五道门槛进行了解读。叶老桂认为,对目前国内商业银行而言,",
"label": {"name": {"叶老桂": [[9, 11],[32, 34]]}, "company": {"浙商银行": [[0, 3]]}}}
转换结果为:
['B-company', 'I-company', 'I-company', 'I-company', 'O', 'O', 'O', 'O', 'O', 'B-name', 'I-name', 'I-name', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'B-name', 'I-name', 'I-name', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'] |
这部分处理在data_process.ipynb文件中。
labels = ['address', 'book', 'company', 'game', 'government',
'movie', 'name', 'organization', 'position', 'scene']
label2id = {
"O": 0,
"B-address": 1,
"B-book": 2,
"B-company": 3,
'B-game': 4,
'B-government': 5,
'B-movie': 6,
'B-name': 7,
'B-organization': 8,
'B-position': 9,
'B-scene': 10,
"I-address": 11,
"I-book": 12,
"I-company": 13,
'I-game': 14,
'I-government': 15,
'I-movie': 16,
'I-name': 17,
'I-organization': 18,
'I-position': 19,
'I-scene': 20,
"S-address": 21,
"S-book": 22,
"S-company": 23,
'S-game': 24,
'S-government': 25,
'S-movie': 26,
'S-name': 27,
'S-organization': 28,
'S-position': 29,
'S-scene': 30
}
id2label = {_id: _label for _label, _id in list(label2id.items())}
再将BIOS标记转换为数字,pad之后装入dataloader输入模型。#每个句子都被pad到52的长度
train_df['label_len'] = train_df['pad_labels'].apply(lambda x: len(x))
print(train_df['label_len'].describe())
count 10748.0
mean 52.0
std 0.0
min 52.0
25% 52.0
50% 52.0
75% 52.0
max 52.0
Name: label_len, dtype: float64
words labels |
这部分代码在bert_softmax.ipynb和bert_lstm_crf.ipynb文件中。
训练过程为:
验证集分数为:
训练完,用模型预测验证集结果,与原标签对比
epoch6的时候f1=0.78,没有达到预期,还需要调整。
这篇文章用于记录阿里天池 NLP 入门赛,详细讲解了整个数据处理流程,以及如何从零构建一个模型,适合新手入门。
赛题以新闻数据为赛题数据,数据集报名后可见并可下载。赛题数据为新闻文本,并按照字符级别进行匿名处理。整合划分出14个候选分类类别:财经、彩票、房产、股票、家居、教育、科技、社会、时尚、时政、体育、星座、游戏、娱乐的文本数据。实质上是一个 14 分类问题。
赛题数据由以下几个部分构成:训练集20w条样本,测试集A包括5w条样本,测试集B包括5w条样本。
比赛地址:https://tianchi.aliyun.com/competition/entrance/531810/introduction
@[toc]
trainer参数设定参考:《huggingface transformers使用指南之二——方便的trainer》
本节参考官方文档:Load
数据集存储在各种位置,比如 Hub 、本地计算机的磁盘上、Github 存储库中以及内存中的数据结构(如 Python 词典和 Pandas DataFrames)中。无论您的数据集存储在何处,🤗 Datasets 都为您提供了一种加载和使用它进行训练的方法。
本节将向您展示如何从以下位置加载数据集:
比赛官方链接为:《零基础入门NLP - 新闻文本分类》。
讨论区有大佬张帆、惊鹊和张贤等人的代码,值得大家仔细阅读。
最后我的模型参考了这些代码的一些config,比如bert.config,lr等等。然后大佬们的代码对我来说还是太复杂,pytorch功力不够,看的吃力。所以自己用huggingface实现了。
第一步分词我就考虑了很久,没有像张帆他们那样用pytorch具体一步步写,而是参考HF主页的教程。所以一开始我是翻译了构建tokenizer的教程,如果对比赛代码中分词有疑问的可以参考。
主要思路:
FastText:快速的文本分类器
参考文档《word2vec原理和gensim实现》、《深入浅出Word2Vec原理解析》
本文重点使用TF-IDF+LightGBM
LightGBM:一种高效的gbdt梯度提升决策树
gbdt 是决策树的集成模型,它基于三个重要原则:
提升技巧
所以在gbdt方法中我们有很多决策树(弱学习器)。这些树是按顺序构建的:
第一棵树学习如何适应目标变量
task1:机器学习算法
用TF-IDF作为文档向量,分类器分别使用了岭回归、朴素贝叶斯、SVM、随机森林、Xgboost和lightGBM。
关于集成学习中的随机森林、Xgboost和lightGBM可以参考我在CSDN的帖子《集成学习4:整理总结》
task2:fasttext
参考帖子:《学习笔记四:word2vec和fasttext》
task3:bert
参考帖子《天池 入门赛-新闻文本分类-单个bert模型分数0.961》
@[toc]
一、基础介绍
1.1PyTorch 简介:
- Torch是一个有大量机器学习算法支持的科学计算框架,是一个与Numpy类似的张量(Tensor) 操作库,其特点是特别灵活,但因其采用了小众的编程语言是Lua,所以流行度不高。
- PyTorch是一个基于Torch的Python开源机器学习库,提供了两个高级功能:
- 具有强大的GPU加速的张量计算(如Numpy)
- 包含自动求导系统的深度神经网络
- PyTorch,通过反向求导技术,可以让你零延迟地任意改变神经网络的行为,而且其实现速度快
- 底层代码易于理解 +命令式体验 +自定义扩展
- 缺点,PyTorch也不例外,对比TensorFlow,其全面性处于劣势。例如目前PyTorch还不支持快速傅里 叶、沿维翻转张量和检查无穷与非数值张量等
@[toc]
torch.utils.data主要包括以下三个类: