albert 的主要改进点在于两点:
1、因式分解词汇embedding参数(当然和数学里边的因式分解不一样),这里采用了矩阵映射的方法,把大的词汇矩阵分解成两个小矩阵,把hidden_size与embedding_size进行分割,这个分割不需要增加一些无意义的参数增加,说实话这些好处都没有什么用处,作者在代码里就简单的做了矩阵的映射变换。
2、另外一个就是夸层参数共享,
这两个改进都在不影响精度的情况下,减少了参数。
尽管坐着的代码比较准确,或者说效果不错,但还是想着以批判的态度去说明这些事情,比如作者说的:
From a modeling perspective, WordPiece embeddings are meant to learn context-independent representations, whereas hidden-layer embeddings are meant to learn context-dependent representations.
意思就是说词汇embedding学习的是独立于上下文的表示,hidden-layers size representation表示的是基于当前上下文的词汇表示。WordPiece embeddings更多的应该是基于大量样本上下文的统一表示,所以这句话感觉有问题,例如word2vec,训练后,如果输入“苹果”,相似词语会出现 “苹果公司”,“小苹果歌曲”,这说明苹果这个词汇表示的向量是大量样本涵盖的综合信息,当然如果作者所说的上下文是当前文章的上下文,仔细想想是我考虑错了。
由于针对自然语言模型的词汇embedding 的词汇一般都非常大,所以如果
E
≡
H
E\equiv H
E≡H
那么如果H增大,就会直接导致词汇之间的映射维度变大,而且大部分参数都是稀疏训练的,所以,利用映射来隔离词汇表示与上下文动态表示。用公式表示如下:
其中E如果远小于H,那么对应的参数会大幅度较小,例如 V=1000个词汇个数,H=768(在bert中是这个数字),E=128(在albert中最小模型的数值),那么倍数关系式3.393666倍。
针对夸层参数共享,如果按照实现代码,很容易实现,直接利用tensorflow的
with tf.variable_scope(name_variable_scope,
reuse=True if (share_parameter_across_layers and layer_idx > 0) else False):
就可以在for循环中使用同一个参数模型的共享。不过大牛还是大牛,利用最简单的方式,却使得模型减少参数而精度不受影响。
代码也正符合了论文里边的一句话:
the default decision for ALBERT is to share all parameters across layers
共享了tranformer块的所有参数,包括FFN以及self attention层。