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 的詞彙一般都非常大,所以如果
那麼如果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層。