文本分类模型的训练、调优、蒸馏

目前已经完成的事情

目前有12个模型。

其中BERT的七个变种模型,因为使用的是BERT-base-chinese的预训练模型和词表,所以不要自己做embedding,换上数据集和标签就可以跑

  1. BertOrigin,

  1. BertCNN,

  1. BertLSTM,

  1. BertATT,

  1. BertRCNN,

  1. BertCNNPlus,

  1. BertDPCNN

前五个传统深度学习的模型,他们是在英文的SST-2数据集上跑的。后面换成中文的word embedding的数据集,需要找一个已经训练好的中文word embedding的一个词表,来做向量化表示

  1. TextCNN

  1. TextRNN

  1. LSTM_ATT

  1. TextRCNN

  1. TransformerText

Bert变种的那7个模型,用来下面7个数据集,一个是中文的THUCNews,其他的都是英文的数据集。这7个数据集和12个模型,后面做论文的时候可以用来作为模型基线,作为测试用的数据集。

  • 情感分类: 采用 IMDB, SST-2, 以及 Yelp 数据集。

  • IMDB: run_imdb.py,两个类别,积极评论和消极评论。 IMDB 影评数据集包含了50000 条用户评价,评价的标签分为消极和积极, 25000 条影评用于训练集,25,000 条用于测试集

  • SST-2:run_SST2.py。把文本分成积极和消极

  • Yelp:

  • run_yelp_review_full.py,5个类别,[极度不满意,有点不满意,中立,有点满意,超级满意],还是那七个模型

  • run_yelp_review_polarity.py,2个类别,积极和消极

  • 问题分类: 采用 TREC 和 Yahoo! Answers 数据集。

  • Yahoo! Answers:run_yahoo_answers.py,10个类别。模型还是上面那7个.

  • 主题分类: 采用 AG's News,DBPedia 以及 CNews。

  • AG's News:run_ag_news.py。有四个类别:“World”, “Sports”, “Business”, “Sci/Tech”

  • DBPedia:run_dbpedia.py,14个类别,如公司、教育机构、艺术家、电影。它实际上是从维基百科项目创建的信息中提取的结构化内容集。TorchText提供的DBpedia数据集有63000个属于14个类的文本实例。它包括5600个训练实例和70000个测试实例。

  • THUCNews:

  • run_THUCNews.py,类别有10个,[u'房产', u'科技', u'财经', u'游戏', u'娱乐', u'时尚', u'时政', u'家居', u'教育', u'体育'],模型用的那7个

想问的问题:

  • 关于模型蒸馏。一般 在工业界的实际应用,是不是不做模型蒸馏。耗费的计算资源很大,但是以后用模型做推理就不用占那么大显存了(模型参数少了,导致的),以后分类的速度也会提高一点。

  • 老师,你们在工业界是不是有几套成熟成型、用的特别溜的模型。常见的NLP任务(文本分类;文本相似度;实体识别...还有什么常见的任务,每个任务总得有最少两套模型用的很溜的Baseline模型,是什么模型。——我估计你们不会像我这样,从github代码过来,自己去推测package的版本号,自己处理数据集。

  • BERT本身只是语言模型,不做分类——我不认同

  • BERT那个positional encoding,后面是如何做的word emdding,老师说模型里有做。

  • 图像和文字,感觉没有那么大的鸿沟。进来都转化为矩阵,做的任务也十分类似。图像是三原色256,三个矩阵叠加。文字做embedding向量化,后面就是矩阵被网络各种处理,最后做的任务也是类似,编码器:分类、回归;解码器:文本生成、图像生成..

还做了的就是恶补了一下 RNN, LSTM, Seq2Seq model,Attention, self-attention,Transforme,这些BERT的前置知识,以及BERT本身和BERT的变种。这样周六的课,我才能参与讨论。

文本分类基础知识

什么是文本分类任务?

主题分类

判断邮件是否是垃圾邮件

情感分析

对话系统中的意图识别:如判断聊天用户的意图是“问发货时间”还是问“退换货收货地址

分类模型的发展历史

  1. 规则:通过关键词,查词表,按照一定的规则来判断文本属于哪个类别

  1. 机器学习:Logistic Regression, SVM, 集成学习

  1. 传统深度学习:FastText、TextCNN、BiLSTM

  1. 前沿深度学习:Transformer、Bert系列

分类任务的扩展任务

  1. 序列标注任务

单字标S, 一个单词的开头表B,结尾标E,中间标M

  1. 句子对分类任务

不同于一般的句子分类任务输入的一条句子,这里同时输入的是两个句子

白日依山尽,黄河入海流” ——> 下一句?“是”

黄河入海流,白日依山尽”——>是下一句吗?“不是”

BERT的训练过程中经常做个这个任务,也就是NSP Next Sentence Prediction

  1. 多标签分类任务

比如一条新闻可能同时涉及 “政治”“经济” “科技”,这一条新闻就被同时打上了3个不同的标签

分类任务的评估指标Metrics

  • 错误率Error rate

分类错误的样本数占总样本数的比例

E表示Error rate,f表示模型-分类器,D表示训练样本。E(f;D)表示基于D这个训练样本下,训练出来的分类器的误差

m表示训练样本D中样本的数量。I( )是一个指示函数,括号内的条件成立时,整个函数的值为1,否则为0。f(xi)是是分类器对样本xi的预测分类标签,yi对应样本本xi的真实标签。这里的意思就是如果 预测的标签和真实的标签不相等,就会记作1。

比如10个样本进行预测,预测10次,错了3次。错误率是30%

  • accuracy

1-Error_rate,就是acc。

比如分类了10次,有9次都是分的和label标签一样,acc就是90%

所有的罪犯里,有多少大比例都被抓到了?——清理坏人,除恶务尽的力度。(尽可能把坏人抓干净)

  • 四个格子加起来(True Positive+True Negative+False Positive+False Negative),一定等于总样本数量

  • accuracy就是所有分类分对的(T打头的,TP和TN),除以总共的Sample size(就是四个格子加在一起)

  • 查准率(precision),我判断为阳性的里面,有多少比例真的是阳性呢?

分母:我判断为阳性的(TP TN FP FN 这里四个里面带P,就是我判断为阳性的,一共有两个,也就是TP和FP)。

分子:里面真的是阳性的,且被我判断为阳性的(你去TP TN FP FN这个四个选项里面,挑带T的,只有两个,也就是TP和TN。这两个里面被我判断为阳性的,你找这两个里面带P的,只有一个,也就是TP)

为什么叫precision呢?你判断为阳性positive且真是阳性的,占你总判断为阳性的比例。你判断为阳性这个行为的准确性

抓到的罪犯里面,有多少真是罪犯?——precision=(1-冤枉好人的概率)。(冤假错案的比例尽可能低,也就是precision尽可能的高)

  • 查全率(recall):所有的阳性中,多大比例被你识别出来了

分母:所有的 真感染

分子:是阳性且被你识别出来的

为什么叫recall呢?召回召回,是从你关注的特定领域(所有感染的人)中召回目标类别(真感染了,还能被你判定为阳性)的比例

precision和recall的分子都是TP,precision——所有你判断为阳性里面有多准;recall——所有真感染的人里面,多少能被你召回来住院隔离

precision和recall之间是矛盾的。

为了提高你的precision,使得你判断为阳性的患者确实是真感染的比例提高,你最自然的做法是,尽量少的判定病人感染了。

如果你想提高你的recall,保证所有感染的人中,尽可能多的人能被你判定为阳性,你最简单的做法就是,尽可能多的把来看病的患者判定为阳性。

precision的提高,会让你减少判定为positive的数量;recall的做法,会让你增加判断为positive的数量。所以二者是矛盾的。于是下面出来了一个平衡precision和recall的指标,f1 score,让你可以兼顾这两个内在是矛盾的指标。

  • f1-score

分子是乘法,分母是加法。假设precision和recall都等于1,分子为2×1×1,分母为1+1,分子分母一除等于2/2=1。真好和最完美的分数等于1相吻合。

这个公式其实对precision和recall进行了加权平均(权重各50%)。不信的话,你可以看上面我对F1 score做的恒等变形(分子分母同时除以recall×precision),得到上面第三个式子。

Bagging, Boosting, Random Forest, XGboost

集成学习做分类

什么是“集成”?

先生成一组“个体学习器”,再通过某种策略结合起来,产生输出

"集成"的关键是个体学习器的生成,有两种生成个体学习器的方法

  • Bagging:学习器之间是并行生成。既然“学习器”生成的过程是并行的,也就是说不同的“个体学习器”之间是互不影响的,自然他们之间的依赖也是比较弱的。Bagging方法的代表是随机森林。

  • Boosting:”个体学习器“之间是串行生成的。上一个”个体学习器“生成完毕了,才会去生成下一个”个体学习器“。这样”个体学习器“之间的依赖比较强。Boosting的代表是AdaBoost和GBDT(Gradient Boosting Decision Tree)

个体学习器的选择标准:

要”好“:如果是三个表现很差的模型,即使集成出来,也是一个差的模型。个体学习器本身的表现要是还不错的,否则垃圾+垃圾,最后还是个垃圾。

要“不同”:如果三个个体学习器本身和类似,比如你让三个模型投票都说往东,那你拿“同质化”的三个模型集成在一起,和用一个模型——不做集成,又有什么区别?

Bagging更关注“不同”(因为“个体学习器”的生成是并行的,“个体学习器”之间的依赖比较少)

Boosting更关注“好”

结合模型的策略是:直接取平均,投票,学习法

Bagging

Bagging的整体流程

  1. 使用自助法进行采样,采样出T个样本的子集

  1. 分别使用T个样本子集,训练T个“个体学习器"。此时就有了T个分类模型

  1. 然后使用平均或者投票来产生输出

前面说了bagging更关注“不同”。这个不同来自于哪里?

来自于“对训练样本的不同划分”来实现的。你想啊,每个模型(就是这里的“个体学习器”)训练使用的样本都不同(样本间也是有不小差异的),那它每个模型捕捉到了不同的关于这个数据集的特征,这样他们才能一起“群策群力”。

随机森林

随机森林是集成了Bagging这个方法的代表模型。

  • 随机森林集成了bagging的这个“优良传统”

Random Forest它还是使用自助法将训练集通过采样拆分成多个子集,用这些数据集的子集来训练和产生个体学习器

  • 随机森林在相比bagging,有下面这些特色

“个体学习器”采用“决策树”

决策树的标准的决策树每次划分,考虑所有属性;但是这个随机森林,每次划分决策树的时候,只考虑一部分的属性子集

  • 随机森林有下面这些优势

简单、容易实现

计算开销小

在很多任务中,都性能强大

随机森林的"随机性" 体现在:(1)通过采样划分出来每个数据集子集的随机性,(2)随机的属性选择

Boosting

首先Boosting是串行来训练的。

“个体学习器1”训练好了,再去训练“个体学习器2”。也就是说,“个体学习器2”的训练是基于“个体学习器1”的。“个体学习器2”是比“个体学习器1”好的,个体学习器3”是比“个体学习器3”好的。这样一路训练T次,"个体学习器"变得越来越强,直到“个体学习器T”达到最强。

42:59

TextCNN

原始的、经典的CNN

卷积神经网络的三个特点

  1. 局部连接,一个输出只与部分输入相连接。连接的多少,取决于卷积核的宽度。

  1. 参数共享,所有输出共享一个卷积核

  1. 平移不变性:“先平移,再卷积”,与“先卷积,再平移”,效果相同。用公式表达就是, f(x)与g(x)分别表示卷积和平移操作。

  1. 当我们只关心某个特征是否出现,而不关心这个特征出现的位置的时候,这个性质就起了作用。

CNN比起RNN的优势

速度快。因为卷积操作可以并行,但是RNN只有序列上前一个位置的计算完成,才能开始去计算序列的下一个位置的东西。

一个标准的卷积层有3个阶段构成

  1. 卷积阶段:并行计算多个卷积,产生一组线性激活响应

  1. 探测阶段:每一个线性激活响应都会再过一个非线性激活函数,比如ReLU

  1. 池化阶段:使用池化函数,来进一步调整输出。

卷积的平移不变性是池化这个操作引入的。

TextCNN

TextCNN卷积核的shape是这样的,假设你word embedding使得一个单词用300维的向量来表示,那么这个卷积核的一个维度也是300,保证这个卷积核卡着每个词的embedding走。卷积核的另一个维度是你可以自己随意设定的,比如设成2,就是每次卷积运算,参与运算的有两个字;你设成8,就是每次卷积有8个元素参与。通过由大到小的不同size的卷积核就可以捕捉一句话局部几个词的特征,以及一条句子的特征。卷积核的滑动是沿着一个方向滑动。embeddding那个方向是卡着embedding长度,不会做任何滑动的。

整个TextCNN网络包括4层:embedding层、卷积层、池化层、全连接分类层。

IDCNN

Iterated Dilated CNN迭代的膨胀(空洞)卷积神经网络

优势:在不堆积更多卷积层的基础上,指数级扩大网络捕获上下文的能力。指数级增加网络的感受野。

DCNN任务在序列标注任务中,池化会降低精度(池化是一种降采样,会损失精度,是一种有损的摘要),于是抛弃了池化。因为最终预测的是每个词对应的序列标注的label。那肯定是到了最后分类,保留下来的信息越多越好了,否则做的任务是比较长一个句子,每个词的标注,到了最后几层信息都很少了,还要升维来实现每个句子的单词都能有属性标签。

但是在文本分类任务中,其实是没有必要抛弃掉池化的。因为池化被看做是对文本内容的抽象,然后我们使用这个抽象过、提炼过的信息来进行分类

Lattice LSTM

....

Trick——加入标签平滑和对抗训练的技术--一数据中加入扰动,这个扰动和梯度有关(FGM=Fast Gradient Method;PGD=Projected Gradient Descent; )

Transformer对于词语的编码,并没有使用传统的那些word2vec的方法,比如Skip-gram, bag of words.它抛弃到了原有的这些word embedding的方法。整个模型,去掉最后的softmax层,那么多参数,其实都是在表示这文字,和这些文字的内在语义。在上面这个模型图左下角这个input embedding,这里注意,这个embedding并不是word embedding那个embedding。在BERT这些模型里面,都有一个vocab.txt,所有的中国的character单字,包括标点,英文的字母、表情符号,一共几万个里面都有。每个字符都用它在vocab.txt中的位置(index数字)来表示。然后在这个input embedding中做一次线性变换

首先要构建这样一个矩阵token embedding matrix,矩阵的维度是 vocab_size × d_model. (vocab_size是词汇量的大小,d_model是词向量的长度,也就是说每一个词都用一个d_model维的向量表示,所有的词合起来就构成了这个矩阵)

然后TensorFlow的这个函数(tf.nn.embeddinglookup)就是查询这个句子中每一个词在上面那个matrix中是用哪一条向量来表示,然后把这些向量拼起来。组成一个矩阵。比如说一个句子有T1个单词,那么这条句子最后的向量表示就是一个size为 T1×d_model的矩阵。

BERT那个voab.txt里面有三万个词,这三万个词从embedding矩阵中去查他们的embedding向量。这个embedding其实是不跟着参数更新的,是固定的。因为值都是从embedding矩阵中查的,一旦embedding矩阵定下来,后面就不会动了。

右下角输入的这个应该是翻译的标准答案。用来和后面模型生成别的翻译结果,对比来算loss

自编码模型:bert 是AutoEncoding ——一句话里遮挡几个词,用没遮挡的词去预测这个遮挡的词

优势:可以利用到上下文信息

劣势:训练的时候mask的两个词的生成是独立的。但是你做推理的时候,其实这两个被遮挡的词实际并不是独立的,是有dependent,所以有偏差了(discrepancy)。

自回归模型:ELMo 、GPT、XLNet系列使用的是Transformer的解码器,是AutoReg——用这个词以前的所有词去预测下一个词

劣势:只能用到这个字以前的内容,来预测下一个字,不能使用这个字以后的信息

优势:上面那个东西的劣势他没有,是无偏差的(no discrepancy)。

BERT中一般有三种word embedding的方式(这个过程也叫tokenize,也叫token embedding)

  • word piece: 把单词或者一个中文字,映射成一个数字

  • char level: today 变成 t o d a y ,每个字母对应一个表示

  • sub-word: today拆成 词根 词缀 to# #day

BERT最大输入长度序列为512,超过512的只截取前512个词。不足这个长度的padding到这个长度。

假设BERT使用word piece这个方法,这就没有使用任何过去提出的word embedding方法了

一个好的预训练模型有两部分

  1. good model structure(BERT用的是Transformer的 Encoder)

  1. pretrained task(mask句子中的词,预测遮挡的这个词;next sentence prediction).除了这两个,还有下面这些任务。这是BERT在下游任务进行fine tuning的一些任务

  1. 句子对分类:sentence pair classification tasks:比如A B两个句子是否同一个意思,是否是同一个作者说过的话,是否长度一致,等等

  1. 文本分类:single sentence classification tasks: 比如 给SST-2进行情感分类

  1. 阅读理解question and answering tasks:在SQuAD 数据集上做的,实际就是有一大段文本,你提出问题,模型可以从这一段文本中把你要问的问题的答案找到。

  1. 序列标注:single sentence tagging 比如用bert对句子进行NER

BERT不适用于自然语言生成任务。因为BERT是自编码模型,是用[mask]两边的词去预测中间的词。你不管是算法模型去做生成任务,还是人说话,都是先说第一个字,再说第二个字,然后第三个字。所以NLG任务用自回归模型是最合适的,你不可能说,我说出这个词是同时考虑了前一个词和后一个词,才想出来的。因为你不可能这个字还么说,就已经知道后面五个词自己计划说什么。

ALBERT 的主要贡献是精简BERT的模型参数,在不降低模型性能的情况下,减少模型参数。

ALBERT的模型结构与BERT相似,进行了以下几点改造:

1、对embedding层进行因式分解

2、对attention layer 进行了权重共享

3、将Bert中的NSP(next sentence prediction)改为SOP(sentence order prediction)

RoBERTa的创新和改进之处

  1. 用了Byte-Pair Encoding(BPE)。

  1. 就是把一个英文拆成词根词缀(实际上是character level representatiion + word-level representation,),比如government,statement,apartment 拆成 govern ment, state ment, apart ment。

  1. 这个方法之前就有,别人也用过,只不过RoBERTa把这个词根词缀的vocabulary词表的容量从30k扩大到了50k。这样词表的那个词嵌入矩阵就会从30k×hidden size,膨胀到50k×hidden size,表示文本的参数量迅速扩大。

  1. 用这个BPE的好处是,一些词表中原来没有的词,网上新造的词,比如niubility牛逼,就会被拆成 niu bility,后面那个bility就和ability里面的bility一样,表示某种能力。

  1. Dynamic Masking。

  1. 每次训练,动态的选择15%的词进行mask,而不是使用固定那几个位置进行遮挡。

  1. Batch size and longer training time.

  1. 作者将batch size从BERT模型的256提高到2k,8k,分数有所提高。

  1. 扩大语料库的收录的语料内容,把一些书籍和维基百科上的文本呀爬下来,扩大数据集。数据集从16G扩大到了160G.

  1. 增加训练的时间

  1. Next Sentence Prediction是不必要的。,去掉这个任务以后,performance score有所提高。用Full sentence和Doc sentence 替代sentence segment后,分数也会提高。

基于上面这些改进,我们可以说原始的BERT本身并没有充分训练好。RoBERTa才是一个训练更充分的模型,目前以及基本替代了BERT的地位。

FiBERT的创新改进之处

他这个FiBERT是把BERT在金融的文本上在summarization这个任务进行专门训练(把原始的BERT迁移到金融领域的语料上做fine-tune)

使用下面这些trick,防止模型在训练过程中,进行灾难性的遗忘。

  1. slanted(倾斜的) triangular learning rate。学习率呈现一个金字塔的三角形,学习率先上升再下降

  1. discrimative(有区别的) fine tuning。对于网络里面不同层,使用不同的学习率。越浅的模型,使用约小的学习率。因为约浅的层,学到了更多的学到的是更加局部的特征

  1. Global Freezing。在训练的过程中,保证一些参数不调整。

K-BERT

本任务适用于知识+推理的任务上(knowledge graph原来就可以做这个)

一句话概括KBER是什么?把知识推理融入到了预训练模型BERT里面来。

K-BERT一共有四个组件,Knowledge layer,Embedding Layer, Seeing Layer,Mask-Transformer Encoder

  • knowledge layer:负责把知识图谱的信息融入到输入中来,把输入的信息表征成一个可以让BERT学习的内容。知识图谱的数据一般是三元组,有三个元素(subject主体 , relation关系, object客体)比如这句话“Tim Cook came to Beijing”. Tim Cook是主体,Beijing是客体,came to是主体和客体之间的关系。

  • 把知识图谱融入到原先的句子里。这样我们就拥有了一条主线(原始句子),若干个分支表征(句子上每一个实体的延伸出来的知识表示)的一种知识表示。

  • Embedding layer:

  • 为了尽可能的保留原始句子的顺序sequence order,根据原始的句子顺序,给每个词都加了一个soft-position embedding, 比如这句话 Tim Cook came to Beijing. 这个五个词分别获得被embedding上 1 2 3 4 5,

  • Token embedding

  • Segment embedding,应该是同一个句子就都打上A,不同的句子打上B,再一句不同的句子就打上个C。用来区分是不是同一个句子的

  • 然后上面三种embedding加在一起。

  • Sentence Tree上的这个句子,有些东西是不应该看到前后文的,比如说,这里的now,应该可以看到前面的Beijing visiting Tim这些信息,但是和Beijing有关的信息,如capital China City,now就不应该看得到,因为和now无关呀。

  • sentence tree下面那些小分支上的信息,应该被处于tree根节点的一些 词看见。比如 capital city now is a 这些数据应该被Beijing看见,因为这些都能够为Beijing这个词补充一些信息,对一个词的相关信息多了,我们做任务的效果自然会更好。

  • 上面这两种需求都是通过这个visible matrix来实现的。

KG-Bert

论文全名:BERT for knowledge graph completion

知识图谱补全工作

实际上是对知识图谱的三元组进行一个二分类或多分类的工作。分类的时候就是判断给出的和三元组(subject主体, object客体,relation)是True还是False

SpanBert是改变mask的形式

猜你喜欢

转载自blog.csdn.net/Albert233333/article/details/129680945