赞
踩
以下比较的前提是首先和BERT(transfomer)的对比
PS: 大模型基础和进阶付费课程(自己讲的):《AIGC大模型理论与工业落地实战》-CSDN学院 或者《AIGC大模型理论与工业落地实战》-网易云课堂
# 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)
F.layer_norm
):
hidden_states
(需要归一化的张量)、normalized_shape
(归一化的维度,通常是最后一维)、weight
和bias
(可学习的缩放和平移参数)以及eps
(为了数值稳定性添加的小常数)。torch.rsqrt()
)来计算方差的倒数(相当于标准差的倒数)。torch自带的LayerNorm是最完整的实现,包括了可学习的参数;而RMSNorm和自定义LayerNorm则省略了这些参数,可能会牺牲一些模型的表达能力,但在某些情况下可能更简单或更高效。RMSNorm特别适用于那些不需要额外参数的大规模模型。
# 普通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))
模型结构: 基本和llama基本一致, 只是各个linear层多了bias; 和Qwen基本一致, 除了o有bias
这是ROPE的二维表达方式,普通的ROPE是一维
# 原始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:多了一个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)
这段代码定义了一个名为flash_attention_forward
的函数,用于实现Flash Attention机制。以下是该函数的详细解释:
函数接受以下参数:
query_layer
:查询(query)层的输出。key_layer
:键(key)层的输出。value_layer
:值(value)层的输出。attention_mask
:注意力掩码,用于指示哪些位置应该被忽略。query_length
:查询序列的长度。softmax_scale
:可选的softmax缩放因子。_get_unpad_data
函数用于处理未填充的数据。它计算每个批次中的序列长度、累积和最大序列长度,并返回未填充数据的索引、累积序列长度和最大序列长度。
_upad_input
函数负责对输入进行解压和平铺操作。它根据attention_mask
计算出需要保留的序列部分,并将查询、键和值层的输出调整为未填充的形状。
dropout
变量用于控制dropout概率,如果模型处于训练状态,则使用self.attention_probs_dropout_prob
作为概率。
将查询、键和值层的输出进行转置,以便于后续的矩阵运算。
根据是否为因果自注意力(即是否为序列到序列任务)和注意力掩码的形状,选择不同的计算方法:
_upad_input
函数对输入进行解压和平铺,然后调用flash_attn_varlen_func
函数执行Flash Attention操作,并在计算完成后将结果恢复为原始形状。flash_attn_func
函数执行Flash Attention操作。最后,将注意力输出转置回原来的形状并返回。
总的来说,这段代码实现了Flash Attention机制,通过矩阵分解和局部注意力等技术优化了Transformer模型的计算效率和内存使用效率。在处理非因果自注意力任务时,它支持仅包含键填充掩码的情况,并在其他情况下退回到使用PyTorch内置的注意力计算方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。