LLaMa、Qwen、ChatGLM、ChatGLM2的區(qū)別
以下比較的前提是首先和BERT(transfomer)的對比
感謝幫忙給我github repository的star,更多最新模型長期更新:https://github.com/zysNLP/quickllm
LLaMa:
-
去掉bias
-
LayNorm方式:RMSnorm:https://zhuanlan.zhihu.com/p/650231190
# torch自帶LayerNorm if self.norm_mode == 'torch_buildin': return F.layer_norm(hidden_states, self.normalized_shape, self.weight, self.bias, self.eps) # RMSnorm: t5、大模型系列均使用 elif self.norm_mode == 'rmsnorm': variance = hidden_states.float().pow(2).mean(-1, keepdim=True) o = (hidden_states.float() * torch.rsqrt(variance + self.eps)).type_as(hidden_states)
-
torch自帶LayerNorm (
F.layer_norm
):- 這是PyTorch庫中內(nèi)置的Layer Normalization實(shí)現(xiàn)。
- 輸入?yún)?shù)包括:
hidden_states
(需要?dú)w一化的張量)、normalized_shape
(歸一化的維度,通常是最后一維)、weight
和bias
(可學(xué)習(xí)的縮放和平移參數(shù))以及eps
(為了數(shù)值穩(wěn)定性添加的小常數(shù))。 - 它首先計(jì)算輸入在指定維度上的均值和方差,然后使用這些統(tǒng)計(jì)量對輸入進(jìn)行歸一化,并通過應(yīng)用可學(xué)習(xí)的縮放和平移參數(shù)來恢復(fù)模型的表達(dá)能力。
-
RMSNorm (Root Mean Square Normalization):
- 只計(jì)算輸入的方差(即每個(gè)元素的平方的平均值),然后通過元素級操作計(jì)算歸一化后的輸出。
- 具體步驟如下:
- 計(jì)算輸入的平方的平均值(variance)。
- 使用逆平方根(
torch.rsqrt()
)來計(jì)算方差的倒數(shù)(相當(dāng)于標(biāo)準(zhǔn)差的倒數(shù))。 - 將輸入與計(jì)算出的標(biāo)準(zhǔn)差倒數(shù)相乘,得到歸一化的結(jié)果。
torch自帶的LayerNorm是最完整的實(shí)現(xiàn),包括了可學(xué)習(xí)的參數(shù);而RMSNorm和自定義LayerNorm則省略了這些參數(shù),可能會(huì)犧牲一些模型的表達(dá)能力,但在某些情況下可能更簡單或更高效。RMSNorm特別適用于那些不需要額外參數(shù)的大規(guī)模模型。
-
torch自帶LayerNorm (
-
feedForward不同, 三層全連接
# 普通bert的FFN: self.outDense(self.inter_act_fn(self.interDense(x))) # llama、qwen的FFN: self.outDense(self.inter_act_fn(self.interDense(x)) * self.interDense2(x))
-
新增rotary相對位置編碼(RoPE)
InternLM:
模型結(jié)構(gòu): 基本和llama基本一致, 只是各個(gè)linear層多了bias; 和Qwen基本一致, 除了o有bias
-
FeedForward和Llama一致, 三個(gè)dense層
-
除了qkvo有bias, 其余均沒有bias
Qwen:
-
FeedForward和Llama一致, 三個(gè)dense層
-
除了qkv有bias, 其余均沒有bias
-
和InternLM基本一致, 唯一的差別是InternLM的multiHeadAttention.o有bias
ChatGLM
-
rotary(RoPE)使用的updown+position_encoding_2d
這是ROPE的二維表達(dá)方式,普通的ROPE是一維
-
qkv合并成一個(gè)權(quán)重convert時(shí)不是concat在一起的
-
attention_mask的最后一個(gè)token僅能訪問之前的, 之前的tokens可以互相訪問
-
跳躍連接有權(quán)重設(shè)計(jì);embedding之后沒有l(wèi)ayernorm
# 原始bert,LayerNorm + multiHeadAttention + dropout + FFN + dropout + x+ FFN:其中x來自第一次FFN之后
x = self.attnLayerNorm(hidden_states, conditional_emb) if self.pre_layernorm else hidden_states # pre/post layernorm
self_attn_output = self.multiHeadAttention(x, attention_mask, past_key_value=past_key_value, position_ids=position_ids)
residual = x if self.apply_residual_post_layernorm else hidden_states
hidden_states = self.dropout_add(self_attn_output[0], residual)
hidden_states = self.attnLayerNorm(hidden_states, conditional_emb) if not self.pre_layernorm else hidden_states
x = self.ffnLayerNorm(hidden_states, conditional_emb) if self.pre_layernorm else hidden_states # pre/post layernorm
feedforward_output = self.feedForward(x)
residual = x if self.apply_residual_post_layernorm else hidden_states
hidden_states = self.dropout_add(feedforward_output, residual) # x在這
hidden_states = self.ffnLayerNorm(hidden_states, conditional_emb) if not self.pre_layernorm else hidden_states
# GhatGLM:LayerNorm + multiHeadAttention + alpha*x + FFN + alpha*x:多了一個(gè)alpha,其中x來自一開始的LayerNorm之后
x = self.attnLayerNorm(hidden_states)
alpha = (2 * self.num_hidden_layers) ** 0.5
self_attn_output = self.multiHeadAttention(x, attention_mask, past_key_value=past_key_value, **model_kwargs)
hidden_states = x * alpha + self_attn_output[0]
x = self.ffnLayerNorm(hidden_states)
hidden_states = x *alpha + self.feedForward(x)
ChatGLM2
-
不使用Unilm式的mask
-
flash_attention
這段代碼定義了一個(gè)名為
flash_attention_forward
的函數(shù),用于實(shí)現(xiàn)Flash Attention機(jī)制。以下是該函數(shù)的詳細(xì)解釋:-
函數(shù)接受以下參數(shù):
-
query_layer
:查詢(query)層的輸出。 -
key_layer
:鍵(key)層的輸出。 -
value_layer
:值(value)層的輸出。 -
attention_mask
:注意力掩碼,用于指示哪些位置應(yīng)該被忽略。 -
query_length
:查詢序列的長度。 -
softmax_scale
:可選的softmax縮放因子。
-
-
_get_unpad_data
函數(shù)用于處理未填充的數(shù)據(jù)。它計(jì)算每個(gè)批次中的序列長度、累積和最大序列長度,并返回未填充數(shù)據(jù)的索引、累積序列長度和最大序列長度。 -
_upad_input
函數(shù)負(fù)責(zé)對輸入進(jìn)行解壓和平鋪操作。它根據(jù)attention_mask
計(jì)算出需要保留的序列部分,并將查詢、鍵和值層的輸出調(diào)整為未填充的形狀。 -
dropout
變量用于控制dropout概率,如果模型處于訓(xùn)練狀態(tài),則使用self.attention_probs_dropout_prob
作為概率。 -
將查詢、鍵和值層的輸出進(jìn)行轉(zhuǎn)置,以便于后續(xù)的矩陣運(yùn)算。
-
根據(jù)是否為因果自注意力(即是否為序列到序列任務(wù))和注意力掩碼的形狀,選擇不同的計(jì)算方法:
- 如果不是因果自注意力且注意力掩碼為二維(表示僅包含鍵填充掩碼),則使用Flash Attention進(jìn)行計(jì)算。首先調(diào)用
_upad_input
函數(shù)對輸入進(jìn)行解壓和平鋪,然后調(diào)用flash_attn_varlen_func
函數(shù)執(zhí)行Flash Attention操作,并在計(jì)算完成后將結(jié)果恢復(fù)為原始形狀。 - 如果不是因果自注意力但注意力掩碼不符合要求,則發(fā)出警告并使用PyTorch內(nèi)置的注意力計(jì)算方法。
- 如果是因果自注意力,則直接調(diào)用
flash_attn_func
函數(shù)執(zhí)行Flash Attention操作。
- 如果不是因果自注意力且注意力掩碼為二維(表示僅包含鍵填充掩碼),則使用Flash Attention進(jìn)行計(jì)算。首先調(diào)用
-
最后,將注意力輸出轉(zhuǎn)置回原來的形狀并返回。
總的來說,這段代碼實(shí)現(xiàn)了Flash Attention機(jī)制,通過矩陣分解和局部注意力等技術(shù)優(yōu)化了Transformer模型的計(jì)算效率和內(nèi)存使用效率。在處理非因果自注意力任務(wù)時(shí),它支持僅包含鍵填充掩碼的情況,并在其他情況下退回到使用PyTorch內(nèi)置的注意力計(jì)算方法。
-
-
multi_query_attention
-
- "multi_query_attention"是一種創(chuàng)新的注意力機(jī)制設(shè)計(jì),它擴(kuò)展了傳統(tǒng)Transformer中的單查詢注意力機(jī)制。
- 在Multi-Query Attention中,每個(gè)位置的輸入可能會(huì)生成多個(gè)查詢向量,這些查詢向量可以獨(dú)立地參與注意力計(jì)算,并與鍵(key)和值(value)矩陣進(jìn)行交互。
- 多個(gè)查詢向量可以捕捉到輸入的不同方面或信息源,增強(qiáng)模型的理解和表達(dá)能力。例如,一個(gè)查詢可能關(guān)注詞匯級別的信息,另一個(gè)查詢可能關(guān)注句法或語義級別的信息。
- 具體實(shí)現(xiàn)可能包括對輸入向量進(jìn)行分解、復(fù)制或?qū)W習(xí)多個(gè)查詢權(quán)重等技術(shù)。生成的多個(gè)查詢向量將分別用于計(jì)算注意力分?jǐn)?shù),并與相應(yīng)的值向量進(jìn)行加權(quán)求和,得到最終的注意力輸出。
NLP基礎(chǔ)付費(fèi)課程(自己講的):《AIGC大模型理論與工業(yè)落地實(shí)戰(zhàn)》 折扣方式:文章來源:http://www.zghlxwxcb.cn/news/detail-772696.html
公眾號”NLP小講堂“回復(fù)自己的聯(lián)系方式,或github中issue留言聯(lián)系方式。課程五折。文章來源地址http://www.zghlxwxcb.cn/news/detail-772696.html
到了這里,關(guān)于LLaMa、Qwen、ChatGLM、ChatGLM2的區(qū)別的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!