日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BERT用的LayerNorm可能不是你认为的那个Layer Norm?

發布時間:2023/12/8 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BERT用的LayerNorm可能不是你认为的那个Layer Norm? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?作者 | 王坤澤

單位 | 悉尼大學

研究方向 | NLP

有關 Batch norm 和 Layer norm 的比較可以算上是算法領域的八股文了,為什么 BERT 不用 batch norm 而用 layer norm 的問題都被問爛了,知乎上隨便一搜都有很多人講解 BN 和 LN 的區別。通常來說大家都會給這張圖:

▲ BN vs LN

大家會說,針對 CV 和 NLP 兩種問題,這里的三個維度表示的信息不同:

如果只看 NLP 問題,假設我們的 batch 是(2,3,4)的,也就是 batch_size = 2, seq_length = 3, dim = 4 的,假設第一個句子是 w1 w2 w3,第二個句子是 w4 w5 w6,那么這個 tensor 可以寫為:

[[w11,?w12,?w13,?w14],?[w21,?w22,?w23,?w24],?[w31,?w32,?w33,?w34] [w41,?w42,?w43,?w44],?[w51,?w52,?w53,?w54],?[w61,?w62,?w63,?w64]]

我們發現,如果是 BN 的話,會對同一個 batch 里對應位置上的 token 求平均值,也就是說 (w11+w12+w13+w14+w41+w42+w43+w44)/8是其中一個 mean,一共會求出 3 個 mean,也就是上圖里 C 個(seq_length)個 mean。

但是如果是 LN 的話,看起來是對每個 sample 里的所有 feature 求 mean,也就是(w11+w12+w13+w14+w21+w22+w23+w24+w31+w32+w33+w34)/12,可以求出一共 2 個 mean,也就是圖里 N(batch_size)個 mean。

我一直對這個計算深信不疑,認為 BERT 里也是這樣的實現,但是有一天我在這個回答看到了?@猛猿?的這個回答:為什么 Transformer 要用 LayerNorm?[1]?其中作者給出了兩張圖:

▲ 都是 Layer norm 但是卻不一樣

左圖和我們認為的 LN 一致,也是我一直認為的 LN,但是右圖卻是在一個 token 上求平均,帶回我們原來的問題,對于一個(2,3,4)的 tensor,(w11+w12+w13+w14)/4 是一個 mean,一共會有 2*3=6 個 mean。

那到底,BERT 里是 batch_size個mean(左圖的計算方法),還是 batch_size*seq_length 個 mean(右圖的計算方法)呢?我們得看看源碼。

BERT 或者說 transformer encoder 的 pytorch 源碼比較著名的應該是 torch 自帶的 transformer encoder 和 hugging face 自己寫的,我們一個個看。

#?torch.nn.TransformerEncoderLayer #?https://github.com/pytorch/pytorch/blob/master/torch/nn/modules/transformer.py #?412行 self.norm1?=?LayerNorm(d_model,?eps=layer_norm_eps,?**factory_kwargs)#?huggingface?bert_model #?https://github.com/huggingface/transformers/blob/3223d49354e41dfa44649a9829c7b09013ad096e/src/transformers/models/bert/modeling_bert.py#L378 #?382行 self.LayerNorm?=?nn.LayerNorm(config.hidden_size,?eps=config.layer_norm_eps)

可以看到,無論是火炬自帶還是捧著臉復現的 transformer encoder 或者叫 bert layer,里面用的都是 torch 自己的 nn.LayerNorm,并且參數都是對應為 768 的 hidden dimension(變形金剛把它叫做 d_model,波特把它叫做 hidden_size)。

那我們看看 nn.LayerNorm(dim) 是一個什么效果,以下代碼修改自?Understanding torch.nn.LayerNorm in nlp [2]

import?torchbatch_size,?seq_size,?dim?=?2,?3,?4 embedding?=?torch.randn(batch_size,?seq_size,?dim)layer_norm?=?torch.nn.LayerNorm(dim,?elementwise_affine?=?False) print("y:?",?layer_norm(embedding))eps:?float?=?0.00001 mean?=?torch.mean(embedding[:,?:,?:],?dim=(-1),?keepdim=True) var?=?torch.square(embedding[:,?:,?:]?-?mean).mean(dim=(-1),?keepdim=True)print("mean:?",?mean.shape) print("y_custom:?",?(embedding[:,?:,?:]?-?mean)?/?torch.sqrt(var?+?eps))

在以上代碼中,我先生成了一個 emb,然后使用 nn.LayerNorm(dim) 計算它 layer nrom 后的結果,同時,我手動計算了一個在最后一維上的 mean(也就是說我的 mean 的維度是 2*3,也就是一共 6 個 mean),如果這樣算出來的結果和我調 nn.LayerNorm(dim) 一致,那就說明,nn.LayerNorm(dim) 會給我們 (batch_size*seq_length) 個 mean,也就是剛才上圖里右邊的方法。計算后結果如下:

y:??tensor([[[-0.2500,??1.0848,??0.6808,?-1.5156],[-1.1630,?-0.7052,??1.3840,??0.4843],[-1.3510,??0.4520,?-0.4354,??1.3345]],[[?0.4372,?-0.4610,??1.3527,?-1.3290],[?0.2282,??1.3853,?-0.2037,?-1.4097],[-0.9960,?-0.6184,?-0.0059,??1.6203]]]) mean:??torch.Size([2,?3,?1]) y_custom:??tensor([[[-0.2500,??1.0848,??0.6808,?-1.5156],[-1.1630,?-0.7052,??1.3840,??0.4843],[-1.3510,??0.4520,?-0.4354,??1.3345]],[[?0.4372,?-0.4610,??1.3527,?-1.3290],[?0.2282,??1.3853,?-0.2037,?-1.4097],[-0.9960,?-0.6184,?-0.0059,??1.6203]]])

確實一致,也就是說,至少在 torch 自帶和 hugging face 復現的 bert 里,layernorm 實際上和右圖一致是對每個 token 的 feature 單獨求 mean

那么如果我們想像左圖里求出 batch_size 個 mean,怎么用 nn.LayerNorm 實現呢?只需要修改 nn.LayerNorm 的參數為 nn.LayerNorm([seq_size,dim]) 即可,代碼如下,大家可以跑一下,發現這樣和求 batch_size 個 mean 是一致的:

import?torchbatch_size,?seq_size,?dim?=?2,?3,?4 embedding?=?torch.randn(batch_size,?seq_size,?dim)layer_norm?=?torch.nn.LayerNorm([seq_size,dim],?elementwise_affine?=?False) print("y:?",?layer_norm(embedding))eps:?float?=?0.00001 mean?=?torch.mean(embedding[:,?:,?:],?dim=(-2,-1),?keepdim=True) var?=?torch.square(embedding[:,?:,?:]?-?mean).mean(dim=(-2,-1),?keepdim=True)print("mean:?",?mean.shape) print("y_custom:?",?(embedding[:,?:,?:]?-?mean)?/?torch.sqrt(var?+?eps))

最后一個問題,按圖右這么求,那豈不是和 InstanceNorm 一樣了嗎?同樣我做了一個代碼實驗:

from?torch.nn?import?InstanceNorm2d instance_norm?=?InstanceNorm2d(3,?affine=False) x?=?torch.randn(2,?3,?4) output?=?instance_norm(x.reshape(2,3,4,1))?#InstanceNorm2D需要(N,C,H,W)的shape作為輸入 print(output.reshape(2,3,4))layer_norm?=?torch.nn.LayerNorm(4,?elementwise_affine?=?False) print(layer_norm(x))

可以跑一下,發現確實是一致的。

結論:BERT 里的 layernorm 在 torch 自帶的? transformer encoder 和 hugging face 復現的 bert 里,實際上都是在做 InstanceNorm。

那么,最開始 Vaswani 在 attention is all you need 里提出的使用 layernorm 是什么呢?tf.tensor2tensor 的作者也是 Vaswani,那么我認為 tf.tensor2tensor 應該是符合作者最初的源碼設計的,通過翻閱源碼(看了無數的文件,大家可以試試,真的很多,各種 function 封裝...),我確認了作者自己的代碼里的 layernorm 使用的參數也是最后一維的 dimension,那么也就是說,原作者本質上也是用的 InstanceNorm

最后想問問,InstanceNorm 是 LayerNorm 的一種嗎?為啥我沒看到相關的說法?

參考文獻

[1]?https://www.zhihu.com/question/487766088/answer/2309239401

[2]?https://stackoverflow.com/questions/70065235/understanding-torch-nn-layernorm-in-nlp

更多閱讀

#投 稿?通 道#

?讓你的文字被更多人看到?

如何才能讓更多的優質內容以更短路徑到達讀者群體,縮短讀者尋找優質內容的成本呢?答案就是:你不認識的人。

總有一些你不認識的人,知道你想知道的東西。PaperWeekly 或許可以成為一座橋梁,促使不同背景、不同方向的學者和學術靈感相互碰撞,迸發出更多的可能性。?

PaperWeekly 鼓勵高校實驗室或個人,在我們的平臺上分享各類優質內容,可以是最新論文解讀,也可以是學術熱點剖析、科研心得競賽經驗講解等。我們的目的只有一個,讓知識真正流動起來。

📝?稿件基本要求:

? 文章確系個人原創作品,未曾在公開渠道發表,如為其他平臺已發表或待發表的文章,請明確標注?

? 稿件建議以?markdown?格式撰寫,文中配圖以附件形式發送,要求圖片清晰,無版權問題

? PaperWeekly 尊重原作者署名權,并將為每篇被采納的原創首發稿件,提供業內具有競爭力稿酬,具體依據文章閱讀量和文章質量階梯制結算

📬?投稿通道:

? 投稿郵箱:hr@paperweekly.site?

? 來稿請備注即時聯系方式(微信),以便我們在稿件選用的第一時間聯系作者

? 您也可以直接添加小編微信(pwbot02)快速投稿,備注:姓名-投稿

△長按添加PaperWeekly小編

🔍

現在,在「知乎」也能找到我們了

進入知乎首頁搜索「PaperWeekly」

點擊「關注」訂閱我們的專欄吧

·

總結

以上是生活随笔為你收集整理的BERT用的LayerNorm可能不是你认为的那个Layer Norm?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。