怕忘记了,记录一些学习内容:
下面内容来自:【BERT-多标签文本分类实战】
  【BERT-多标签文本分类实战】系列共七篇文章:

  【BERT-多标签文本分类实战】之一——实战项目总览
  【BERT-多标签文本分类实战】之二——BERT的地位与名词术语解释
  【BERT-多标签文本分类实战】之三——多标签文本分类的方向与常用数据集介绍
  【BERT-多标签文本分类实战】之四——数据集预处理
  【BERT-多标签文本分类实战】之五——BERT模型库的挑选与Transformers
  【BERT-多标签文本分类实战】之六——数据加载与模型代码
  【BERT-多标签文本分类实战】之七——训练-评估-测试与运行主程序

1基础知识

[1] bert的提出

  Bert模型是Google在2018年10月发布的语言表示模型,Bert在NLP领域横扫了11项任务的最优结果,可以说是18年NLP中最重要的突破。Bert模型的全称是Bidirectional Encoder Representations from Transformers,是通过训练Masked Language Model和预测下一句任务得到的模型。

  关于Bert具体训练的细节和更多的原理,有兴趣的读者可以去查看https://arxiv.org/abs/1810.04805原文。

[2] bert的地位

  从网络模型角度来说,地位大致如下:

  Fasttext -> TextCNN -> DPCNN -> TextRCNN -> TextBiLSTM+Attention -> HAN -> Transformer -> BERT

  从预训练网络模型角度来说,地位大致如下:(像较于预训练模型,预训练词向量现在已经被淘汰了)

  ELMo -> ERNIE -> GPT -> BERT -> XLNet

[3] Fine-tuning

   什么叫Fine-tuning? 使用预训练模型(例如BERT模型),在预训练模型末端添加一些未训练过的神经元层,然后训练新的模型来完成任务。

【注】此时bert模型的参数是有反向传播的

   为什么要Fine-tuning?

  1、更快速的开发。 首先,预训练模型权重已经编码了很多通用的语言信息。因此,训练微调模型所需的时间要少得多——就好像我们已经对网络的底层进行了广泛的训练,只需要将它们作为我们的分类任务的特征,并轻微地调整它们就好。

  2、更少的数据。 预训练这种方法,允许我们在一个比从头开始建立的模型所需要的数据集小得多的数据集上进行微调。从零开始建立的 NLP 模型的一个主要缺点是,我们通常需要一个庞大的数据集来训练我们的网络,以达到合理的精度,但是我们必须投入大量的时间和精力在数据集的创建上。通过对 BERT 进行微调,我们现在可以在更少的数据集上训练一个模型,使其达到良好的性能。

  3、更好的结果。 这种简单的微调程过程(通常在 BERT 的基础上增加一个全连接层,并训练几个 epochs)被证明可以在广泛的任务中以最小的调节代价来实现最先进的结果:分类、语言推理、语义相似度、问答问题等。与其实现定制的、有时还很难理解的网络结构来完成特定的任务,不如使用 BERT 进行简单的微调,也许是一个更好的(至少不会差)选择。

[4] Feature extract

  什么叫Feature extract? Bert的论文中对预训练好的 Bert模型设计了两种应用于具体领域任务的用法,一种是 fine-tune(微调) 方法,一种是 feature extract(特征抽取) 方法。

  feature extract(特征抽取)方法指的是调用预训练好的 Bert 模型,对新任务的句子做句子编码,将任意长度的句子编码成定长的向量。编码后,作为你自己设计的某种模型(例如 LSTM、SVM 等都由你自己定)的输入,等于说将 Bert 作为一个句子特征编码器,这种方法没有反向传播过程发生,至于如果后续把定长句子向量输入到 LSTM 种继续反向传播训练,那就不关 Bert 的事了。这也是一种常见的语言模型用法,同类的类似 ELMo。

  Feature extract与Fine-tuning的区别? fine tune(微调)方法指的是加载预训练好的 Bert 模型,其实就是一堆网络权重的值,把具体领域任务的数据集喂给该模型,在网络上继续反向传播训练,不断调整原有模型的权重,获得一个适用于新的特定任务的模型。这很好理解,就相当于利用 Bert 模型帮我们初始化了一个网络的初始权重,是一种常见的迁移学习手段。

[5] embedding层、词嵌入、word2vec、词向量

  embedding层:嵌入层,神经网络结构中的一层,由embedding_size个神经元组成,[可调整的模型参数]。是input输入层的输出。

  词嵌入:也就是word embedding…根据维基百科,被定义为自然语言处理NLP中的一组语言建模和特征学习技术的集体名称,其中来自词汇表的单词或者短语被映射成实数向量。

  word2vec:词嵌入这个技术的具体实现,也可以理解成是将向量从高维度映射到低维度的计算过程。 具体的包含两种处理方式也就是两个典型的模型—CBOW模型和SG模型。假设,原始数据有F个特征,通过one-hot编码后,表示成N维的向量,即input层的维度是N,和权重矩阵相乘,变成embedding_size维的向量。(embedding_size <N)

  词向量:也就是通过word2vec计算处理后的结果的释义。比如说…从input输入层到embedding层的权重矩阵,记作是N*embedding_size的,那么这个矩阵的一行就是一个词向量,是第几行就对应input输入层one-hot编码中第几列那个1所对应的词。

【注】常见的预训练词向量有,Stanford GloVe Embeddings、fastText word vectors

[6] bert与embedding的区别

  从模型的层数定义上来看,embedding只有一层神经网络模型,而bert有非常非常多层网络,而且有1亿多个参数。

  宏观上来看,bert和embedding是差不多的。在embedding层使用预训练词向量,就相当于bert使用了预训练的参数。bert和embedding都有Fine-tuning和Feature extract模式。只不过bert比embedding层数多得多、参数多得多。

参考来源:【BERT-多标签文本分类实战】之二——BERT的地位与名词术语解释

2.多标签分类的种类

[1] 多标签文本分类的若干小方向

  目前学术上,多标签文本分类任务大概可以分为3个小方向:

  •   · 普通多标签文本分类
  •   · 层级多标签文本分类
  •   · 极端多标签文本分类

  不同的小方向,数据集的特点比较不一样,任务的难点也不同。

[2] 普通多标签文本分类

  普通多标签文本分类就是指我们平常提到的多标签文本分类,英文称作multi-label text classification,MTC。

  MTC任务的数据集特点是:数据集中的每条文本,都对应着1-N个标签,在某些特殊数据集中有的文本甚至没有标签。数据集中的总类别标签往往不大,一般在几千以内,一些常用的数据集总标签数在几百、几十以内。而且我们说,MTC任务的数据集中的标签是平面的,标签之间没有归属关系、没有层次结构,是一维展开的。

  MTC任务的主要目标很朴素,就是尽量提高模型最后分类出来的各项评价指标,越理想越好。

  常用的MTC数据集有:

  Ren-CECps1.0: 一个多标签的中文情感语料库。它包含了37678 个中文博客的句子和 11 种情感标签,其中每句话被赋予一种或多种情感。

  Reuters-21578:是路透社金融新闻服务进行分类的常用数据集,其中包含了 7769 个训练文本和 3019 个测试文本,其中包含多个标签和单个标签。

  AAPD:从网络上收集了 55840 篇论文的摘要和相应学科类别,一篇学术论文属于一个或者多个学科,总共由 54个学科组成,目的是根据给定的摘要来预测学术论文相对应的学科。

  RCV1-V2:共有 804414篇新闻,每篇新闻故事分配有多个主题,共有 103 个主题。

  EUR-Lex:由欧盟法律组成的,里面包含了许多不同类型的文件,包括条约、立法、判例法和立法提案,共有 19314 个文档,3956 个分类。

  AmazonCat-13K:该数据集是来自于亚马逊,其中包括评论(评分,文字,帮助性投票),产品元数据(描述,类别信息,价格,品牌和图像特征)和链接(也可以查看/购买的图表),在做多标签文本分类得时候主要考虑的是类别信息。

  Amazon-670K:亚马逊商品的评论、产品的数据,和 AmazonCat-13K 的数据有类似之处,只是规模和商品不一样。

  Amazon-3M:亚马逊,包含的是产品的信息,链接以及产品的评论。

以上8个常用数据集的介绍信息来自论文《多标签文本分类研究进展 - 郝超》
本次系列实战项目,采用的数据集就是Reuters-21578。

[3] 层次多标签文本分类

  层次多标签文本分类是对文本标签具有层次化结构的数据集进行分类,英文称作Hierarchical Multi-label Text Classification, HMTC。

  HMTC任务特点是:标签之间具有层次结构,其中,一个标签可以被特殊化为子类然后被一个父类所包含。层次多标签可以采用树(Tree)或者有向无环图(DAG)进行表示。其中对于Tree结构来说,一个标签节点只有一个父节点;而对于DAG结构来说,一个标签节点可以有多个父节点。对于一个给定的样本,同时将一个或多个类标签指定给该样本,并且这些类标签以层次结构的形式存储,这就是层次多标签分类问题。

  常用的HMTC数据集有:

  BlurbGenreCollection(BGC):是作者收集的由书籍介绍以及层次结构的写作题材组成,共有91892 个文本,四个层级,146 个类别,四个层级分别有 7,46,77,16 个类别。

  WOS-11967(Web of Science):由 Web of Science 发表的论文的摘要组成,共有11967 个文本,两个层级,40 个类别,两个层级分别有 7,33个类别。

  WIPO-alpha2:共有四个层级,5229 个类别,四个层级分别有 8,114,451,4656 个类别。

  Enron:是一个邮件的语料数据集,共有三个层级,56 个类别,三个层级分别有 3,40,13 个类别.

  Reuters:是由路透社提供的人工新闻分类数据集,有超过 800000 条的数据,共有三个层级,101个类别,三个层级分别有 4,55,42 个类别。

以上5个常用数据集的介绍信息来自论文《层次多标签文本分类方法 - 赵海燕》

[4] 极端多标签文本分类

  极端多标签文本分类寻求从一个极端大的标签集合中为给定的文本输入找到相关的标签,英文称作Extreme Multi-label Text Classification, XMTC,其实也可以叫大规模多标签文本分类(Large Scale Multi-label Text Classification, LMTC),一样的意思。

  XMTC任务的特点是:标签的数量有成千上百万,特征空间也非常大,严重的样本稀疏性,巨大的内存消耗、显存消耗,成千上百万的标签往往还伴随着层次化结构。标签存在长尾分布,绝大部分标签仅仅有少量样本关联。

  XMTC任务的难点有很多。如何解决数据稀疏?如何使模型运行更高效?如何解决样本少的问题?去哪搞服务器跑代码,直接劝退了好吧!

[5] 总结

  数据集越大,越吃设备,所以建议大家还是从较为简单的普通多标签文本分类任务着手入门。其中,数据集最好选择一些不是太大的,例如:Reuters-21578、AAPD、RCV1-V2、EUR-Lex。

原文链接:https://blog.csdn.net/qq_43592352/article/details/12705906

5 BERT模型库的挑选与Transformer

[1] BERT模型库

  从BERT模型一经Google出世,到tensorflow与pytorch版本的BERT相继发布,再到不同下游任务的BERT模型被整合到transformers库,到底pip哪个库才能用BERT对于刚入门的同学来说是非常的不友好。

  其实大部分的人的需求都非常地简单:只想用BERT模型替代原始的嵌入层来得到文本表示。大部分的人更在乎的是如何把bert当作和embedding层一样的黑箱,输入文本,得到文本表征向量。

  这里,本项目使用的是Hugging Face的transformers库,因为它整合的太棒啦!transformers库里面有NLP里面很火的大模型,比如BERT、ALBERT、GPT、GPT2、XLNET等等。本项目只用到了transformers.BERT,其文档地址为:https://huggingface.co/docs/transformers/model_doc/bert

  本篇文章主要还是以实战为导向,简单说一下transformers.BERT要怎么用。想要深入使用,大家仔细看看上面贴的文档,写得非常好。

[2] transformers.BERT的下载

  其实在自己的模型里使用BERT非常简单,并不会像其他教程一样与transformers库耦合的很深,本次在数据集Reuters-21578上进行多标签文本分类的实战项目,就是在之前单标签文本分类任务上改动的。

单标签文本分类实战项目,请参考:【BERT-多标签文本分类实战】之一——实战项目总览

[2.1] 使用BERT前的准备

  使用BERT需要2个前置条件:

  1、安装transformers库;
  2、下载预训练参数文件。

  第一点不必赘述。第二点可说的比较多。首先,为什么要下载预训练参数文件?BERT它是预训练模型,有自己的网络结构,而且里面的参数达到上亿级别,BERT在大规模无监督语料上训练得到最终参数之后,是要把参数保存下来,之后有新的数据集要跑的时候,我们需要把这些参数数据载入到模型。除此之外,光有预训练参数文件不够,还需要一个配置文件,来告诉它模型的很多配置是多少(例如词典有多大、隐藏层维度是几等等)。最后还需要一个txt文件来存放词典。
  总结一下,BERT的预训练参数文件里有3个文件:1)参数数据;2)模型配置信息;3)txt词典。

[2.2] 预训练参数文件的挑选与下载

  BERT的参数文件有很多个版本:
image.png
  上面框出来的是我比较常用的两个。bert-base-uncased表示不区分大小写的英文模型,bert-base-chinese表示中文模型。
  假设我们要下载bert-base-uncased,我们到页面:https://huggingface.co/bert-base-uncased/tree/main,下载的文件已经在图中框出:
image.png
  由于本次实战使用的是pytorch框架,所以最终我们下载下来的文件是:
image.png
【注】只下载这三个就够了,其他都可以不下载。

[3] transformers.BERT的测试示例

  我们对BERT模型的需求是,利用它来编码句子。在我们的实战项目中,有一个测试.py文件,里面展示了BERT的基本用法。
image.png
  把下载下来的参数文件放在项目下,然后写代码开始测试:

import torch
from transformers import BertModel, BertTokenizer

pretrained_path = 'bert-base-uncased'
# 从文件夹中加载bert模型
model = BertModel.from_pretrained(pretrained_path)
# 从bert目录中加载词典
tokenizer = BertTokenizer.from_pretrained(pretrained_path)

# 输出字典的大小
print(f'vocab size :{tokenizer.vocab_size}')
# 把'[PAD]'编码
print(tokenizer.encode('[PAD]'))
# 把'[SEP]'编码
print(tokenizer.encode('[SEP]'))
vocab size :30522
[101, 0, 102]
[101, 102, 102]

  接下来对英文句子进行词典编码,这里主要是把英文句子,按照词典里面的词序进行转化:

# 把句子编码,默认加入了special tokens了,也就是句子开头加入了[CLS] 句子结尾加入了[SEP]
ids = tokenizer.encode("I love you transport", add_special_tokens=True, padding='max_length', truncation='only_first', max_length=6)
print(ids)

输出:
[101, 1045, 2293, 2017, 3665, 102]

【注】不要凌乱! 来总结一下到目前为止说了什么:
第一小节介绍了采用transformers库来使用BERT;
第二小节介绍了使用BERT要下载哪些东西;
第三小节给了一段测试代码,其实是让大家自己试试有没有下载成功,能不能把demo运行起来。

[4] transformers.BERT的实际使用

  第三小节给的代码只是demo。本节将介绍BERT的实际使用,很简单,只需要一个函数tokenizer.encode_plus,但是在写代码前,大家需要了解为什么要这样做。

[4.1] BERT模型的输入格式

  BERT要求我们:

  1、在句子的句首和句尾添加特殊的符号[CLS]和[SEP]
  2、给句子填充 or 截断,使每个句子保持固定的长度
  3、用 attention mask 来显示的区分填充的tokens和非填充的tokens。

  特殊符号:
  [SEP]

  在每个句子的结尾,需要添加特殊的[SEP]符号。

  在以输入为两个句子的任务中(例如:句子 A 中的问题的答案是否可以在句子 B 中找到),该符号为这两个句子的分隔符。

  目前为止还不清楚为什么要在单句中加入该符号,但既然这样要求我们就这么做吧。

  [CLS]

  在分类任务中,我们需要将[CLS]符号插入到每个句子的开头。

  这个符号有特殊的意义,BERT 包含 12 个 Transformer 层,每层接受一组 token 的 embeddings 列表作为输入,并产生相同数目的 embeddings 作为输出(当然,它们的值是不同的)。

  句长 & 注意力掩码(Attention Mask)

  很明显,数据集中句子长度的取值范围很大,BERT该如何处理这个问题呢?

  BERT有两个限制条件

  1、所有句子必须被填充或截断到固定的长度,句子最大的长度为512个tokens。
  2、填充句子要使用[PAD]符号,它在BERT词典中的下标为0。

  下图是最大长度为8个tokens的填充说明:
image.png
  Attention Mask是一个只有 0 和 1 组成的数组,标记哪些tokens是填充的,哪些不是的。掩码会告诉 BERT 中的Self-Attention机制不去处理这些填充的符号。


#### [4.2] BERT模型的最终使用方法
  首先使用tokenizer.encode_plus对文本编码:

from transformers import BertModel, BertTokenizer

# 参数文件地址
pretrained_path = 'bert-base-uncased'
# 加载bert模型
bert = BertModel.from_pretrained(pretrained_path)
# 加载分词器
tokenizer = BertTokenizer.from_pretrained(pretrained_path)

# 对英文文本content进行分词
encoded_dict = config.tokenizer.encode_plus(
                content,  # 输入文本
                add_special_tokens=True,  # 添加 '[CLS]' 和 '[SEP]'
                max_length=pad_size,  # 填充 & 截断长度
                pad_to_max_length=True,
                padding='max_length',
                truncation='only_first',
                return_attention_mask=True,  # 返回 attn. masks.
                return_tensors='pt'  # 返回 pytorch tensors 格式的数据
            )

# 编码后的文本
IDs = torch.squeeze(encoded_dict['input_ids'],0)
# 文本的 attention mask
MASKs = torch.squeeze(encoded_dict['attention_mask'],0)

  函数tokenizer.encode_plus包含以下步骤:

  · 将句子分词为 tokens。
  · 在两端添加特殊符号 [CLS] 和[SEP]。
  · 将 tokens 映射为下标 IDs。
  · 将列表填充或截断为固定的长度。
  · 创建 attention masks,将填充的和非填充 tokens 区分开来。

  更多参数请参考官方文档:https://huggingface.co/docs/transformers/model_doc/bert

  拿到了编码后的文本、文本的attention mask之后,作为输入放入bert模型里面跑:

out = bert(IDs, attention_mask=MASKs)

【注】这里演示的是基本使用方法,比较独立。真正应用在实战项目里,还是配着整体代码食用更佳。

1 声望0 粉丝

引用和评论

0 条评论