ALBERT原理与实践

ALBERT的整体原理与笔者之前介绍BERT的原理与应用差不多。我们之前也讲过BERT有很多缺点,自它横空降生之时,很多小伙伴都基于它的缺点进行了改进,产生了各种各样的BERT类的文章,笔者之前也做了一些这些BERT与其他预训练模型的对比。

ALBERT当然也不例外,我们首先认识一下它最大的特点在哪?它减少了参数量,但维持了BERT的性能,但它只是降低了空间复杂度,把参数量从108M降到了12M,但并没有降低时间复杂度。我们用ALBERT进行预测的速度并没有加快,甚至在同等性能的模型对比中还慢了。

(ALBERT降参数量,但不减计算量。)

参数量对比

那么,ALBERT是怎么降低参数量?

主要通过Factorized embedding parameterization和Cross-layer parameter sharing两大机制。

接下来,笔者将详细介绍ALBERT的特点与相应的实践。

1. Factorized embedding parameterization(矩阵分解)

我们知道BERT的embedding大小为词汇表的长度V乘以每个字/单词embedding隐藏层大小H:V x H。

ALBERT通过参数E来分解这个embedding矩阵,让整体embedding参数变小,将V x H 转换成V x E + E x H ,当E远远小于H的时候,模型所需的参数将大大减少。实验证明参数E=128时,效果最佳。

举个例子,我们的中文BERT的词汇表大小大约为2万,参数量为20000×768 = 1536万 = 15M,用参数E拆解矩阵的话,参数量为20000×128 + 128×768=265.8304万 = 2M+,大概降低了12M,然而我们知道BERT的参数量大概在108M,所以矩阵分解带来的参数量降低并不是最大的。

2.Cross-layer parameter sharing(跨层参数共享)

从上一节我们知道矩阵分解并不是降低模型参数量的最大贡献者,那么接下来介绍的跨层参数共享就是ALBERT的重中之重了,因为他的存在减少了BERT模型的绝大部分的参数。

跨层共享的机制非常简单,就是单独用一个Self-Attention层循环12次,每一层的参数都一样。这样子我们就用1层的参数量来表示12层的参数,为此,模型的参数当然大大降低了。

为什么这个机制能行?作者提到给BERT的每一层参数做了分析,发现每一层的参数基本相似,因此直接共享了。

我们根据下图可以看出,在保持模型性能下降不至于太厉害的同时,选择所有层次参数共享,降低的参数量是最多的,所以,ALBERT默认所有层次参数共享。

跨层共享:参数量对比图

3.ALBERT的SOP任务(SENTENCE ORDER PREDICTION (SOP))

笔者在之前的推文中也有介绍,很多BERT类的模型在预训练的过程中放弃了NSP任务,因为它不仅没给下游任务的效果带来提升,反而伤害了整体的性能。为此,ALBERT同样也放弃了NSP任务,改用了SOP任务作为预训练任务。

SOP任务也很简单,它的正例和NSP任务一致(判断两句话是否有顺序关系),反例则是判断两句话是否为反序关系。

我们举个SOP例子

正例:1.朱元璋建立的明朝。2.朱元璋处决了蓝玉。

反例: 1.朱元璋处决了蓝玉。 2.朱元璋建立的明朝。

我们通过下图也可以看出,使用SOP的ALBERT,显然在fine-tune下游任务的效果更好。

4.ALBERT的预测速度

通过前面的介绍,我们知道了ALBERT降低了参数量,但并没有提升预测速度。至于出现这种情况的原因也很简单,BERT是12层Self-Attention堆叠而成,ALBERT同样也是12层Self-Attention堆叠而成,在预测的时候,tensor都是要经过12层Self-Attention,所以速度并没有提升。

我们可以看到同为BASE情况下的对比,ALBERT的速度会快一点。

但如果在同等性能对比的情况下,BERT-base比ALBERT-large快了11.2个BERT-xlarge。

BERT-base (Avg =82.3) :17.7x

ALBERT-large (Avg =82.4) :6.5x

5.ALBERT代码实践

笔者之前介绍过如何使用BERT来做下游任务,同样地,ALBERT也如此。只是我们将BERT替换成了ALBERT,本质上都是使用他们的权重来fine-tune下游任务。不过ALBERT的结构与之前ROBERT、ERNIE之类的BERT类模型有了很大改变。

2019BDCI互联网金融新实体发现 | 思路与代码框架分享(单模第一,综合第二)

因此,这里笔者附上了之前使用的代码,小伙伴们可以通过添加一下代码来使用ALBERT。添加完成之后,按照笔者之前介绍的代码框架操作运行即可。

① ALBERT的源码(官网可下载)

https://github.com/brightmart/albert_zh

在tf_utils文件夹添加ALBERT源码的modeling.py和bert_utils.py

②在model.py添加以下代码(引用ALBET的modeling.py代码)

import tensorflow as tf
import numpy as np
# from tf_utils.bert_modeling import BertModel, BertConfig, get_assignment_map_from_checkpoint, get_shape_list  # BERT
from tf_utils.modeling import BertModel, BertConfig, get_assignment_map_from_checkpoint, get_shape_list  # ALBERT
from tensorflow.contrib.crf import crf_log_likelihood,  viterbi_decode
from tensorflow.contrib.layers.python.layers import initializers
from tf_utils.crf_utils import rnncell as rnn
from tf_utils.bert_modeling import layer_norm

③ 在config.py添加ALBERT的权重路径

self.bert_file = '/data/wangzhili/pretrained_model/albert_xlarge_zh_177k/bert_model.ckpt'
self.bert_config_file = '/data/wangzhili/pretrained_model/albert_xlarge_zh_177k/bert_config.json'
self.vocab_file = '/data/wangzhili/pretrained_model/albert_xlarge_zh_177k/vocab.txt'

 

关注我的微信公众号~不定期更新相关专业知识~

内容 |阿力阿哩哩 

编辑 | 阿璃 

点个“在看”,作者高产似那啥~

发布了76 篇原创文章 · 获赞 5 · 访问量 6216

猜你喜欢

转载自blog.csdn.net/Chile_Wang/article/details/104453972