LLM - Transformer LLaMA2 结构分析与 LoRA 详解

目录

一.引言

二.图说 LLM

1.Transformer 结构

◆ Input、Output Embedding

◆ PositionEmbedding

◆ Multi-Head-Attention

◆ ADD & Norm

◆ Feed Forward

◆ Linear & Softmax

2.不同 LLM 结构

◆ Encoder-Only

◆ Encoder-Decoder

◆ Decoder-Only 

3.LLaMA-2 结构

◆ Input Embedding

◆ RMSNorm

◆ RoPE

◆ Attention

◆ SwiGLU

◆ MLP

三.数说 LoRA

1.LLaMA-2 7B 原始参数

2.LLaMA-2 7B LoRA 参数

3.Peft Add LoRA Adapter

◆ LoraModel

◆ add_adapter

◆ _find_and_replace

◆ mark_only_lora_as_trainable

◆ Linear 

◆ update_layer

◆ reset_lora_parameters

四.总结


一.引言

 大模型进行 Lora 微调时,需要指定 lora_target,以 LLama2 为例,官方指出可以使用下述层:

--lora_target 'q_proj,v_proj,k_proj,o_proj,gate_proj,down_proj,up_proj'

看过 Transformer 的同学对 Q/K/V 肯定不陌生,但是 gate、up、down 又是什么鬼;还有 Lora 指定不同 lora_target 时可训练参数会调整,具体每个地方增加了多少参数也没搞明白。结合上述问题,博主本文对 Transformer、LLaMA-2 以及 LoRA 的一些基础知识进行分享~

二.图说 LLM

1.Transformer 结构

左侧为多个 Encoder Block 叠加,右侧为多个 Decoder Block 叠加,二者合在一起为整体的 Transformer 结构。关于 Transformer 这里简单介绍其各个结构,更具体的详解会在文末给出参考链接,大家可以深入学习。

Input、Output Embedding

NLP 最基本的 Embedding 层,可以通过 Word2vec、Bert 等预训练方式获取 Token_Id 的 Embedding,也可以端到端训练得到,当我们输入原始文本后,Text 经过 Tokenizer 处理得到 Input_ids,Input_ids 再经过 Embedding 层就获得原始的词向量了。

PositionEmbedding

除了原始的单词 Embeeding 外,Transformer 还引入了 position Embedding 表示单词在句子中的位置。实验表明,引入 Position Embedding 比不引入 Position Embedding 的效果更好,一般 PositionEmbedding 用于表示单词在句子中的绝对位置或相对位置。Position Embedding 维度与上面的单词 Embeeding 维度相同,可以训练也可以使用公式计算,Transformer 中采用了后者,计算公式为:

- pos 代表单词在句子中的位置 

- d 标识 Position Embedding 的维度

- 2i、2i+1 标识偶数和奇数的维度

计算得到 PE 后与原 Embeeding 相加进入后续逻辑。

Tips:

这里奇数和偶数位置的编码方法使用了正弦 sin 和余弦 cos 的不同的函数。这里奇数位置和偶数位置的区别在于他们所应用的正弦和余弦函数的角频率,通过调整角频率,可以使得奇数和偶数位置的编码方式有所不同。通过调整角频率,可以使得奇数和偶数位置编码的值在编码空间呈现不同的变化模式。这样的设计旨在为相邻位置提供不同的位置编码,以增加模型对序列中位置信息的敏感度。

Multi-Head-Attention

上图为 Multi-Head Attention [多头注意力] 结构,在计算的时候,会将 Embedding + Position Embeeding 相加的结果,分别经过 Q-Query-Linear、K-Key-Linear 和 V-Value-Linear 进行一次线性变换送入后续逻辑。

Scaled Dot-Product 负责将 Linear 转化的 Q/K/V 进行 Attention 计算,其中 Q/K MatMul 乘法后为了防止内积过大,会除以 \sqrt{d_k} 进行 Scale 操作,最后通过 Softmax 归一化并与 Value 向量相乘得到最后的输出。

Multi-Head Attention 旨在学习向量不同特征空间的表现,所以 Multi-Head Attention 会有多个 Linear 和 Scaled Dot-Product,最终将多个 head 对应的 Attention 结果 Concat 再过一层 Linear 传到下一层作为 Input。

ADD & Norm

 ADD & Norm 看字面意思就知道它是由 ADD 和 Norm 两个部分组成,其计算公式如下:

其中 X 代表上一步的输出,从图中可以看到 Feed Forward 和 Multi-Head Attention 都会输出到 ADD & Norm 层,这里结构与 RNN 的残差网络类似,将原始输入与上一步的输出相加。结果相加后通过 Norm 层就行归一化加速收敛。

Feed Forward

Feed Forward 层采用两层全连接,第一层为 Relu 第二层不使用激活函数。

Linear & Softmax

经过多层 Block 的堆叠,终于到达最终的 Linear 层,使用 LLM 我们常看到的 lm_head 就是一种 Linear,该层负责生成语言模型的输出。它是模型架构中的最后一层,用于将 Transformer 编码器的输出转化为预测下一个词或生成文本的概率分布。

具体来说,Linear 层会对编码器的输出进行线性变换,将其映射到与词汇表大小相同的向量空间。这样做的目的是为了预测下一个词的概率分布。通常,线性变换后的输出经过 softmax 函数处理,以获得归一化的概率分布,其中每个词的概率表示在给定前文条件下该词是下一个出现的可能性。

在训练阶段,可以使用交叉熵损失函数来比较模型输出的概率分布与实际的下一个词的标签,并通过反向传播更新模型参数。而在生成阶段,可以根据概率分布进行采样,以生成连贯的文本。

2.不同 LLM 结构

最新的大语言模型基本都是基于上述 Transformer 结构进行拓展:

Encoder-Only

▲ 包含一个单独的编码器,没有显式的解码器部分。
▲ 主要用于 AutoEncoder 等任务,其主要学习数据的压缩标识

Encoder-Only 学习的压缩表示可以用于特征提取,数据降维等任务,具有较好的泛化能力。最常见的就是 Bert,这里所有输出 token 都能看到过去和未来的所有输入 Token,因此对于 NLU [Natural Language Understanding] 自然语言文本理解和分析的任务很友好。

Tips 常见的 NLU 任务如下:

- 语句分类 [Sentence Classification] 根据给定文本判断其标签,如情感分类、垃圾邮件分类

- 意图识别 [Intent Recognition] 识别用户输入表的的意图或目的,如天气、餐厅查询

- 实体识别 [Named Entity Recognition] 从文本中识别标注实体,如人名、地点识别

- 信息抽取 [Infomation Extraction] 从文本中提取特定含义信息,如从新闻提取摘要

- 关系抽取 [Relation Extraction] 识别本文与实体的关系,如 "Apple" 与 "Steve Jobs" 的关系

- 问答系统 [Question Answering] 为给定问题找到答案,如阅读理解,知识库问答。

这些任务旨在让计算机能够理解和处理自然语言文本,从而支持各种应用场景,如智能助手、虚拟客服、搜索引擎等。NLU 任务的目标是将自然语言转化为结构化的表示形式,以便计算机能够更好地理解和响应用户的需求。

Encoder-Decoder

▲ 由一个编码器和一个解码器组成,常用于序列到序列(Sequence-to-Sequence)任务,如机器翻译、语音识别等。
▲ 编码器将输入序列编码为固定长度的向量,解码器从该向量生成输出序列。

Encoder-Decoder 适用于需要输入和输出之间存在复杂映射的任务,能够处理变长序列,并且可以用于翻译、生成等多种任务。GLM、T5、Bart 都已普遍应用。

Decoder-Only 

 Decoder-Only 相比前两个分支明显枝繁叶茂,硕果累累,最出名的就算是 GPT 家族了。 

▲ 只包含解码器部分,没有显式的编码器。通常用于条件生成任务,其中给定一些条件信息,模型通过解码器生成相应的输出。
▲ 与 Encoder 相比二者 Multi-Head Attention 相差一个 MASK,会导致前文无法使用后文未知的消息,第二个 Multi-Head Attention 则与 Encoder 相似。

实际应用中,Decoder-Only 适用于从条件信息中生成输出的任务,例如图像描述生成,文本生成。常见的 chat 模型就基于 Decoder-Only。

3.LLaMA-2 结构

LLaMA-2 采用 Decoder-Only 的架构,由 Attention 和 MLP 层堆叠而成,Lora 微调 LLaMA-2 时这些 target 对应的结构也能在图中找出了。

--lora_target 'q_proj,v_proj,k_proj,o_proj,gate_proj,down_proj,up_proj'

与传统 Transformer 结构相比,其主要做了如下修改:

RMSNorm - 传统结构 Norm 放在 Att 后,这里将 Norm 前置

RoPE 编码 - 更换了 Position Embedding 的编码方式

MLP 层更新 - 增加了 UP 和 Donw 的线性层并使用 SiLU 激活 

与 LLaMA-1 相比,其增加了一倍 Context Length 达到 4096,使其处理长文本能力更强:

Input Embedding

这里与常规 transformer 的输入层逻辑一致。

RMSNorm

Bert、GPT 常用的均值方差归一化 LayerNorm 为:

y = \frac{x-Mean(x)}{\sqrt{Var(x)+\varepsilon }}*W+B

RMS 意为 root mean square 均方根,用于衡量一组数值的平均值大小:

RMS(x)=\sqrt{\frac{1}{n}\sum x_i^2}

RMSNorm 发现 LayerNorm 的取消中心偏移即 Mean(x) 效果激活不变且可以提高计算效率,最终公式为:

RMSNorm=\frac{x}{\sqrt{RMS(x)+\varepsilon )}}*W

LLaMA-2 在 Embedding 和 Attention Output 后都引入了 RMSNorm。

RoPE

对于 Q-Query、K-Key 第 m 个位置的向量 q,通过下述方法得到 Position Embedding:

d 为 Embedding 的维度,θ 为预设的非零常数,RoPE 旋转位置嵌入的实现过程如下图:

Attention

 Attention 部分的 QKV 与先前相似,除了引入 RoPE 旋转位置嵌入外,还引入了 Causal Mask:

BART原理简介与代码实战_Congqing He的博客-CSDN博客

Causal Mask 的引入使得前文无法获得下文的知识,例如 'I love eating lunch' 中 love 只能获得 'I' 和 'love' 的信息。剩下就是常规的 Attention 与 Softmax 操作,最后的 o 代表 Output,其参数维度与 Q/K/V 的 Linear 相同。

SwiGLU

SwiGLU 又称 SiLU,与 GeGLU 相比用 Swish 替代了 GeLU:

其中 ⓧ 代表逐元素乘法,Swish 公式为:

Swish_\beta (x)=x\sigma (\beta x)

其中 σ 代表 sigmoid 函数,其示意图如下: 

从图像可以看出 SiLU 更像是 ReLU 的平滑版本。 

MLP

这里 MLP 的表达式为:

donw(up(x) \times SiLU(gate(x)))

其中 up、down 与 gate 是三个维度相同的 Linear 层。

三.数说 LoRA

1.LLaMA-2 7B 原始参数

    model = AutoModelForCausalLM.from_pretrained(base_model,config=config,torch_dtype=torch.float16,low_cpu_mem_usage=True,trust_remote_code=True,revision='main')model_vocab_size = model.get_input_embeddings().weight.size(0)tokenzier_vocab_size = len(tokenizer)print(model.get_input_embeddings().weight.size())print(f"Vocab of the base model: {model_vocab_size}")print(f"Vocab of the tokenizer: {tokenzier_vocab_size}")for name,param in model.named_parameters():print(name, param.numel(), param.requires_grad)

这里我们直接加载 LLaMA-2 7B 模型,看看每一层参数的情况:

model.embed_tokens.weight 131072000 True
model.layers.0.self_attn.q_proj.weight 16777216 True
model.layers.0.self_attn.k_proj.weight 16777216 True
model.layers.0.self_attn.v_proj.weight 16777216 True
model.layers.0.self_attn.o_proj.weight 16777216 True
model.layers.0.mlp.gate_proj.weight 45088768 True
model.layers.0.mlp.down_proj.weight 45088768 True
model.layers.0.mlp.up_proj.weight 45088768 True
model.layers.0.input_layernorm.weight 4096 True
model.layers.0.post_attention_layernorm.weight 4096 True...
model.layers.31.self_attn.q_proj.weight 16777216 True
model.layers.31.self_attn.k_proj.weight 16777216 True
model.layers.31.self_attn.v_proj.weight 16777216 True
model.layers.31.self_attn.o_proj.weight 16777216 True
model.layers.31.mlp.gate_proj.weight 45088768 True
model.layers.31.mlp.down_proj.weight 45088768 True
model.layers.31.mlp.up_proj.weight 45088768 True
model.layers.31.input_layernorm.weight 4096 True
model.layers.31.post_attention_layernorm.weight 4096 True
model.norm.weight 4096 True
lm_head.weight 131072000 True

这里可以看到 LLaMA-2 7B 共堆叠了 32 个 Block,其中有我们 lora_target 熟悉的层:

--lora_target 'q_proj,v_proj,k_proj,o_proj,gate_proj,down_proj,up_proj'

通过上面 LLaMA-2 结构的分析,相信这几个层在哪我们起码已经知道了,下面看看每一个 Block 的参数量:

前面已经介绍了 LLaMA-2 将 Context Length 扩展至 4096,这里  layernorm 参数量为 4096,一个单独 Block 的参数量为 2 亿左右。再看下整体的参数量:

这里打印得到的 Token 数为 32000,32000 * 4096 = 131072000 与 Input Embedding 和 lm_head 层的参数可以匹配。32 个 Decoder 再加上 Norm 和最后的 lm_head,总参数 6.94B ≈ 7B。

2.LLaMA-2 7B LoRA 参数

    lora_config = LoraConfig(task_type=TaskType.CAUSAL_LM,inference_mode=False,r=8,lora_alpha=32,lora_dropout=0.1,target_modules=["q_proj","v_proj","k_proj","o_proj","gate_proj","down_proj","up_proj"])model = get_peft_model(model, lora_config)for name,param in model.named_parameters():print(name, param.numel(), param.requires_grad)

增加 LoraConfig 结合 peft 获取 LoRA 后的模型,这里秩 r = 8,再看下每层的情况:

base_model.model.model.embed_tokens.weight 131072000 False
base_model.model.model.layers.0.self_attn.q_proj.weight 16777216 False
base_model.model.model.layers.0.self_attn.q_proj.lora_A.default.weight 32768 True
base_model.model.model.layers.0.self_attn.q_proj.lora_B.default.weight 32768 True
base_model.model.model.layers.0.self_attn.k_proj.weight 16777216 False
base_model.model.model.layers.0.self_attn.k_proj.lora_A.default.weight 32768 True
base_model.model.model.layers.0.self_attn.k_proj.lora_B.default.weight 32768 True
base_model.model.model.layers.0.self_attn.v_proj.weight 16777216 False
base_model.model.model.layers.0.self_attn.v_proj.lora_A.default.weight 32768 True
base_model.model.model.layers.0.self_attn.v_proj.lora_B.default.weight 32768 True
base_model.model.model.layers.0.self_attn.o_proj.weight 16777216 False
base_model.model.model.layers.0.self_attn.o_proj.lora_A.default.weight 32768 True
base_model.model.model.layers.0.self_attn.o_proj.lora_B.default.weight 32768 True
base_model.model.model.layers.0.mlp.gate_proj.weight 45088768 False
base_model.model.model.layers.0.mlp.gate_proj.lora_A.default.weight 32768 True
base_model.model.model.layers.0.mlp.gate_proj.lora_B.default.weight 88064 True
base_model.model.model.layers.0.mlp.down_proj.weight 45088768 False
base_model.model.model.layers.0.mlp.down_proj.lora_A.default.weight 88064 True
base_model.model.model.layers.0.mlp.down_proj.lora_B.default.weight 32768 True
base_model.model.model.layers.0.mlp.up_proj.weight 45088768 False
base_model.model.model.layers.0.mlp.up_proj.lora_A.default.weight 32768 True
base_model.model.model.layers.0.mlp.up_proj.lora_B.default.weight 88064 True
base_model.model.model.layers.0.input_layernorm.weight 4096 False
base_model.model.model.layers.0.post_attention_layernorm.weight 4096 False...
base_model.model.model.norm.weight 4096 False
base_model.model.lm_head.weight 131072000 False

依旧是 32 个 Decoder 的堆叠,可以看到在我们制定的 target_model 上都增加了对应的 LoRA weight,由于我们的 Context Length x r = 4096 x 8 = 32768 可得矩阵 A 的维度,通过 lora_B 的 88604 维度也可以反推出,88604 / 8 = 11008 矩阵 B 的维度 8 x 11008,不过看原图中 LoRA 的维度是属于 R^{ d\times d},这里有一点疑问,大家可以提供下思路:

单个 Decoder 参数量:

参数量为 2 亿,可以看到 r = 8 较低时,整体训练的参数量占比很低,我们计算下 r = 8 时全部可训练参数的占比:

624640 * 32 [32 个 Decoder 的 Lora 参数量] / (6940798976 [LLaMA-2 7B 总参数量] + 624640 * 32) = 0.002871583154398789,只占总参数比的 0.287%,所以一直都说 LoRA 可以有效减少参数训练量。同理,根据上面的 API 和算法,我们可以计算不同秩 r 对应的可选参数量并打印:

3.Peft Add LoRA Adapter

代码版本为 peft==0.4.0,类位置为:src/peft/tuners/lora.py

LoraModel

class LoraModel(torch.nn.Module):"""Creates Low Rank Adapter (Lora) model from a pretrained transformers model."""def __init__(self, model, config, adapter_name):super().__init__()self.model = modelself.forward = self.model.forwardself.peft_config = configself.add_adapter(adapter_name, self.peft_config[adapter_name])# transformers models have a .config attribute, whose presence is assumed later onif not hasattr(self, "config"):self.config = {"model_type": "custom"}

LoraModel 初始化除了获取原始的基模型和 peft_config 外,执行了 add_adapter 添加 LoRA 层的逻辑,下面我们看下 add_adapter 方法主要实现什么功能。

add_adapter

    def add_adapter(self, adapter_name, config=None):if config is not None:model_config = getattr(self.model, "config", {"model_type": "custom"})if hasattr(model_config, "to_dict"):model_config = model_config.to_dict()config = self._prepare_lora_config(config, model_config)self.peft_config[adapter_name] = configself._find_and_replace(adapter_name)if len(self.peft_config) > 1 and self.peft_config[adapter_name].bias != "none":raise ValueError("LoraModel supports only 1 adapter with bias. When using multiple adapters, set bias to 'none' for all adapters.")mark_only_lora_as_trainable(self.model, self.peft_config[adapter_name].bias)if self.peft_config[adapter_name].inference_mode:_freeze_adapter(self.model, adapter_name)

这里 config 配置部分我们先忽略,主要注意这两行:

_find_and_replace -> 寻找并替换

mark_only_lora_as_trainable -> 标记 lora 层可训

_find_and_replace

    def _find_and_replace(self, adapter_name):lora_config = self.peft_config[adapter_name]self._check_quantization_dependency()is_target_modules_in_base_model = False# 获取模型内层的 Namekey_list = [key for key, _ in self.model.named_modules()]for key in key_list:# 检查是否为 lora_target 指定的 layerif not self._check_target_module_exists(lora_config, key):continueis_target_modules_in_base_model = Trueparent, target, target_name = _get_submodules(self.model, key)if isinstance(target, LoraLayer) and isinstance(target, torch.nn.Conv2d):...elif isinstance(target, LoraLayer) and isinstance(target, torch.nn.Embedding):...elif isinstance(target, LoraLayer):...# Conv2D、Embedding 和 loraLayer 的情况忽略# 因为我们这里是为 Base Model 增加 LoRA Layer,所以进入 else 逻辑else:new_module = self._create_new_module(lora_config, adapter_name, target)self._replace_module(parent, target_name, new_module, target)if not is_target_modules_in_base_model:raise ValueError(f"Target modules {lora_config.target_modules} not found in the base model. "f"Please check the target modules and try again.")

这里先用 model.named_modules 获取 Base Model 全部层的 name,例如 layers.x.mlp.up_proj,随后遍历每一个 name 是否属于 lora_target 所指范畴,随后根据 lora_config 调用_create_new_module 获取新的 Lora Adapter,最后执行 _replace_module。如果 target_modules 不存在于 base_model,会抛出异常。例如我们将 Baichuan 的 'W_pack' 传给 LLaMA-2 就会抛出该异常。

 _create_new_module

根据 in_features 和 out_features 与 bias 构建 Linear 层。

new_module = Linear(adapter_name, in_features, out_features, bias=bias, **kwargs)

 _replace_module

将 old_model 的 weight 和 bias 赋值到 new_model,并 to_device 将 new_model 分配到 old_model 对应的 device 上。

    def _replace_module(self, parent_module, child_name, new_module, old_module):setattr(parent_module, child_name, new_module)new_module.weight = old_module.weightif hasattr(old_module, "bias"):if old_module.bias is not None:new_module.bias = old_module.biasif getattr(old_module, "state", None) is not None:new_module.state = old_module.statenew_module.to(old_module.weight.device)# dispatch to correct devicefor name, module in new_module.named_modules():if "lora_" in name:module.to(old_module.weight.device)if "ranknum" in name:module.to(old_module.weight.device)

mark_only_lora_as_trainable

# had to adapt it for `lora_only` to work
def mark_only_lora_as_trainable(model: nn.Module, bias: str = "none") -> None:for n, p in model.named_parameters():if "lora_" not in n:p.requires_grad = Falseif bias == "none":returnelif bias == "all":for n, p in model.named_parameters():if "bias" in n:p.requires_grad = Trueelif bias == "lora_only":for m in model.modules():if isinstance(m, LoraLayer) and hasattr(m, "bias") and m.bias is not None:m.bias.requires_grad = Trueelse:raise NotImplementedError

判断 lora_ 是否在 param_name 中,随后决定是否训练。

Linear 

class Linear(nn.Linear, LoraLayer):# Lora implemented in a dense layerdef __init__(self,adapter_name: str,in_features: int,out_features: int,r: int = 0,lora_alpha: int = 1,lora_dropout: float = 0.0,fan_in_fan_out: bool = False,  # Set this to True if the layer to replace stores weight like (fan_in, fan_out)is_target_conv_1d_layer: bool = False,**kwargs,):init_lora_weights = kwargs.pop("init_lora_weights", True)nn.Linear.__init__(self, in_features, out_features, **kwargs)LoraLayer.__init__(self, in_features=in_features, out_features=out_features)# Freezing the pre-trained weight matrix 原始 weight Freezingself.weight.requires_grad = Falseself.fan_in_fan_out = fan_in_fan_outif fan_in_fan_out:self.weight.data = self.weight.data.T# 初始化 LoRA 参数并更新 LoRA-A LoRA-Bnn.Linear.reset_parameters(self)self.update_layer(adapter_name, r, lora_alpha, lora_dropout, init_lora_weights)self.active_adapter = adapter_nameself.is_target_conv_1d_layer = is_target_conv_1d_layer

上面 _create_new_module 方法根据 fan_in、fan_out 创建了 Linear,这里 Linear 也是 Lora 类中实现的,继承了 nn.linear,主要关注 update_layer 方法。

update_layer

    def update_layer(self, adapter_name, r, lora_alpha, lora_dropout, init_lora_weights):self.r[adapter_name] = rself.lora_alpha[adapter_name] = lora_alphaif lora_dropout > 0.0:lora_dropout_layer = nn.Dropout(p=lora_dropout)else:lora_dropout_layer = nn.Identity()self.lora_dropout.update(nn.ModuleDict({adapter_name: lora_dropout_layer}))# Actual trainable parametersif r > 0:self.lora_A.update(nn.ModuleDict({adapter_name: nn.Linear(self.in_features, r, bias=False)}))self.lora_B.update(nn.ModuleDict({adapter_name: nn.Linear(r, self.out_features, bias=False)}))self.scaling[adapter_name] = lora_alpha / rif init_lora_weights:self.reset_lora_parameters(adapter_name)self.to(self.weight.device)

首先根据 lora_config 定义 lora_alpha 和 lora_dropout_ratio,如果 r > 0 则 update lora_A 和 lora_B,scaling 层根据 lora_alpha 和 r 计算,最后 reset_lora_parameters。

reset_lora_parameters

    def reset_lora_parameters(self, adapter_name):if adapter_name in self.lora_A.keys():# initialize A the same way as the default for nn.Linear and B to zeronn.init.kaiming_uniform_(self.lora_A[adapter_name].weight, a=math.sqrt(5))nn.init.zeros_(self.lora_B[adapter_name].weight)if adapter_name in self.lora_embedding_A.keys():# initialize a the same way as the default for nn.linear and b to zeronn.init.zeros_(self.lora_embedding_A[adapter_name])nn.init.normal_(self.lora_embedding_B[adapter_name])

这里 lora_A 采用 Kaiming 初始化,这是一种常用的神经网络权重初始化方法,旨在有效地初始化深度神经网络,lora_B 采用零初始化。不过 lora_A 这里与原文的正态分布初始化有所不同。

四.总结

这里整理了 Transformer 、LLM 和 LoRA 的一些基础知识,结合最后 LoRA 的参数量与代码,我们可以很轻松的得到可训的参数与参数量,同时也可以在 LoRA 的时候增加更多自定义的功能。

!!! 最后特别感谢下面大佬们的输出:

Transformer: Transformer模型详解(图解最完整版) - 知乎

LLaMA V1/2: LLaMA v1/2模型结构总览 - 知乎

LLM 基座: [Transformer 101系列] 初探LLM基座模型 - 知乎 

GLU: https://arxiv.org/pdf/2002.05202.pdf

LLaMA 2: https://arxiv.org/pdf/2307.09288.pdf

RoPE: https://arxiv.org/pdf/2104.09864.pdf

Peft: GitHub - huggingface/peft at v0.4.0

LoRA: 大模型训练——PEFT与LORA介绍_常鸿宇的博客-CSDN博客 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/32167.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

写给 Android 应用工程师的 Binder 原理剖析

一. 前言 这篇文章我酝酿了很久,参考了很多学习文档,读了很多源码,却依旧不敢下笔。生怕自己理解上还有偏差,对大家造成误解,贻笑大方。又怕自己理解不够透彻,无法用清晰直白的文字准确的表达出 Binder 的…

机器学习——卷积神经网络基础

卷积神经网络(Convolutional Neural Network:CNN) 卷积神经网络是人工神经网络的一种,是一种前馈神经网络。最早提出时的灵感来源于人类的神经元。 通俗来讲,其主要的操作就是:接受输入层的输入信息&…

【论文阅读】Deep Instance Segmentation With Automotive Radar Detection Points

基于汽车雷达检测点的深度实例分割 一个区别: automotive radar 汽车雷达 : 分辨率低,点云稀疏,语义上模糊,不适合直接使用用于密集LiDAR点开发的方法 ; 返回的物体图像不如LIDAR精确,可以…

Kuebernetes资源控制管理

第四阶段 时 间:2023年8月11日 参加人:全班人员 内 容: Kuebernetes资源控制管理 目录 Kubectl命令工具 一、kubectl 命令行的语法 二、kubectl命令列表 三、使用 Kubectl 工具容器资源 (一)创建Pod &…

第十六次CCF计算机软件能力认证

第一题:小中大 在数据分析中,最小值最大值以及中位数是常用的统计信息。 老师给了你 n 个整数组成的测量数据,保证有序(可能为升序或降序),可能存在重复的数据。 请统计出这组测量数据中的最大值、中位数以及最小值&am…

Mysql SUBSTRING_INDEX - 按分隔符截取字符串

作用: 按分隔符截取字符串 语法: SUBSTRING_INDEX(str, delimiter, count) 属性: 参数说明str必需的。一个字符串。delimiter必需的。分隔符定义,是大小写敏感,且是多字节安全的count必须的。大于0或者小于0的数值…

最强的表格组件—AG Grid使用以及License Key Crack

PS: 想要官方 License Key翻到最后面 Ag Grid简介 Ag-Grid 是一个高级数据网格,适用于JavaScript/TypeScript应用程序,可以使用React、Angular和Vue等流行框架进行集成。它是一种功能强大、灵活且具有高度可定制性的表格解决方案,提供了丰富…

2005-2020年280个地级市绿色全要素生产率测算原始数据

2005-2020年280个地级市绿色全要素生产率测算原始数据 1、时间:2005-2020年 2、来源:中国城市统计年鉴、中国区域统计年鉴、中国能源年鉴、中国环境年鉴等 3、范围:280个地级市 4、指标:年末单位从业人员数、规模以上工业企业…

React(5)

1.受控组件案例 1.1之前的影院案例改写 import React, { Component } from react import axios from axios import BetterScroll from better-scroll import ./css/02_tab.cssexport default class Cinema extends Component {constructor() {super();this.state {cinemaLis…

【Docker晋升记】No.1--- Docker工具核心组件构成(镜像、容器、仓库)及性能属性

文章目录 前言🌟一、Docker工具🌟二、Docker 引擎🌏2.1.容器管理:🌏2.2.镜像管理:🌏2.3.资源管理:🌏2.4.网络管理:🌏2.5.存储管理:&am…

时序预测 | MATLAB实现BO-LSTM贝叶斯优化长短期记忆神经网络时间序列预测

时序预测 | MATLAB实现BO-LSTM贝叶斯优化长短期记忆神经网络时间序列预测 目录 时序预测 | MATLAB实现BO-LSTM贝叶斯优化长短期记忆神经网络时间序列预测效果一览基本介绍模型搭建程序设计参考资料 效果一览 基本介绍 MATLAB实现BO-LSTM贝叶斯优化长短期记忆神经网络时间序列预…

10. Docker Swarm(一)

目录 1、前言 2、Docker Swarm体系架构 2.1、简单介绍 2.2、体系架构 3、简单使用 3.1、环境准备 3.2、初始化master节点 3.3、建立worker节点 3.4、查看集群的节点信息 3.5、部署应用 3.5.1、创建Dockerfile文件 3.5.2、构建镜像 3.5.3、将镜像上传到Docker仓库 …

Node 使用 MySQL

1、安装驱动 使用 npm 进行安装 mysql $ npm install mysql 2、连接数据库 在以下实例中根据你的实际配置修改数据库用户名、及密码及数据库名: test.js 文件 var mysql require(mysql); var connection mysql.createConnection({host : localhost…

JavaFx异常: Not on FX application thread; currentThread = Timer-0

我的定时器任务中有两个控件: FXML TextArea Display; FXML Label Label_Display; 执行下方代码会抛出:Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread Timer-0 Timer_tas…

自动化更新导致的各种问题解决办法

由于最近自动化频频更新导致出现各种问题,因此在创建驱动对象代码时改成这种方式 我最近就遇到了由于更新而导致的代码报错,报错信息如下: 复制内容如下: Exception in thread “main” org.openqa.selenium.remote.http.Connecti…

大连交通大学813软件工程考研习题

1.什么是软件生存周期模型?有哪些主要模型? 生存周期模型:描述软件开发过程中各种活动如何执行的模型。对软件开发提供强有力的支持,为开发过程中的活动提供统一的政策保证,为参与开发的人员提供帮助和指导,是软件生存周期模型…

Kendo UI for jQuery,一个现代的jQuery UI组件!

Kendo UI for jQuery是什么? Kendo UI for jQuery是完整的jQuery UI组件库,可快速构建出色的高性能响应式Web应用程序。Kendo UI for jQuery提供在短时间内构建现代Web应用程序所需要的工具,从多个UI组件中选择,并轻松地将它们组…

Unity-UGUI优化策略

界面出栈规则: 界面目录导航、策划界面回退需求造成界面套娃问题,夹带一系列层级问题,应该和策划进行友好沟通,避免界面不合理的出栈入栈规则 overdraw: 尽量减少同屏 半透明物体渲染 Unity 之 UGUI优化(…

湘大 XTU OJ 1148 三角形 题解(非常详细):根据题意朴素模拟+观察样例分析需要计算几轮 具体到一般

一、链接 1148 三角形 二、题目 题目描述 给一个序列,按下面的方式进行三角形累加,求其和值。 比如序列为 1,2,3,4,5 1 2 3 4 53 5 7 98 12 1620 2848输入 有多组样例。每个样例的第一行是一个整数N(1≤N≤100),表示序列的大小&…

Azure Kinect DK + ROS1 Noetic使用教程

作者: Herman Ye Galbot Auromix 版本: V1.0 测试环境: Ubuntu20.04 更新日期: 2023/08/08 注1: 本文内容中的硬件由 Galbot 提供支持。 注2: Auromix 是一个机器人爱好者开源组织。 注3: 本文在…