当前位置: 首页 > news >正文

企业网站结构网站套用模板

企业网站结构,网站套用模板,成熟网站开发单位,温州门户网站【模型学习】LoRA的原理,及deepseek-vl2下LoRA实现 LoRA(Low-Rank Adaptation)是一种针对大型语言模型的微调技术,旨在降低微调过程中的计算和内存需求。其核心思想是通过引入低秩矩阵来近似原始模型的全秩矩阵,从而减…

【模型学习】LoRA的原理,及deepseek-vl2下LoRA实现

LoRA(Low-Rank Adaptation)是一种针对大型语言模型的微调技术,旨在降低微调过程中的计算和内存需求。其核心思想是通过引入低秩矩阵来近似原始模型的全秩矩阵,从而减少参数数量和计算复杂度。

基本原理

在LoRA中,原始模型的全秩矩阵被分解为低秩矩阵的乘积。

具体来说,对于一个全秩矩阵W,LoRA将其分解为两个低秩矩阵A和B的乘积,即W ≈ A * B。

其中,A和B的秩远小于W的秩,从而显著减少了参数数量。

在这里插入图片描述

其实现流程为:

  • 在原始预训练语言模型旁边增加一个旁路,做降维再升维的操作来模拟内在秩
  • 用**随机高斯分布初始化 A,**用零矩阵初始化B,训练时固定预训练模型的参数,只训练矩阵 A 与矩阵 B
  • 训练完成后,将 B 矩阵与 A 矩阵相乘后合并预训练模型参数作为微调后的模型参数

在这里插入图片描述

W是原始的权重矩阵,A是一个尺寸为dr的矩阵,B是一个尺寸为rd’的矩阵,r是低秩矩阵的秩

通过这种分解,原始矩阵W的更新仅由A和B的乘积决定

LoRA引入了一个缩放因子α,使得更新公式为

在这里插入图片描述

DeepSeek_vl2中LoRA的参数在

class DeepseekV2Config(PretrainedConfig):kv_lora_rank=512,  # 键值对LoRA的秩q_lora_rank=1536,  # 查询LoRA的秩

LoRA 的核心思想是通过对预训练模型中的特定层进行低秩矩阵插入,实现参数高效微调而无需修改原始权重

对于语言模型,通常选择影响权重更新较大的模块,例如q_projk_proj(负责查询和键的变换),v_proj(值的变换),以及o_proj(输出投影)等。

Rotary Embedding:虽然在一些实现中会对嵌入进行微调,但通常LoRA不会直接用于rotary_emb,因为它通常是固定的。


MLP层中的Gate、Up和Down投影

  • gate_proj:控制门投影 -

  • up_proj:上升投影 -

  • down_proj:下降投影 -

    MLP层的Gate、Up和Down投影通常涉及大量的可训练参数,因此对这些投影进行LoRA微调,可以在不显著增加计算负担的情况下优化模型表现。

    通过低秩适应,LoRA能够在减少参数量的同时,增强模型对复杂模式的适应能力。

    这些曾在处理非线性变换时起到重要作用,通常也是LoRA微调的目标。


在这里插入图片描述

DeepSeek_vl2 LoRA实现

class DeepseekVLV2ForCausalLM(DeepseekVLV2PreTrainedModel):def __init__(self, config):# 1. 视觉编码器 - SigLIP ViT (无LoRA)self.vision = VisionTransformer(...)# 2. 投影器 - 连接视觉和语言self.projector = MlpProjector(...)# 3. 语言模型 - DeepSeek-V2 (有LoRA)self.language = DeepseekV2ForCausalLM(language_config)

LoRA只在语言模型中实现,并且Deepseekvl2的语言模型是用的llama框架(虽然我也没接触过)

Copied from transformers.models.llama.modeling_llama.LlamaAttention with Llama->DeepseekV2

from transformers.models.llama.modeling_llama import (LlamaAttention,LlamaFlashAttention2
)ATTENTION_CLASSES = {# MLA (Multi-Latent Attention) - DeepSeek-V2的默认注意力"eager": DeepseekV2Attention,                    # 标准MLA实现"flash_attention_2": DeepseekV2FlashAttention2,  # MLA + Flash Attention 2# MLA的别名"mla_eager": DeepseekV2Attention,"mla_flash_attention_2": DeepseekV2FlashAttention2,# MHA (Multi-Head Attention) - 传统注意力"mha_eager": LlamaAttention,                     # 标准MHA实现"mha_flash_attention_2": LlamaFlashAttention2   # MHA + Flash Attention 2
}# 在SS-lora.py中,可以这样配置:
lora_config = {'enable_lora': True,'q_lora_rank': 256,'kv_lora_rank': 128,'_attn_implementation': 'flash_attention_2'  # 选择注意力类型
}# 在模型初始化时
config = DeepseekV2Config(**language_config)
config._attn_implementation = lora_config.get('_attn_implementation', 'eager')

deepseek_vl2下完整的LoRA调用层次

DeepseekVLV2ForCausalLM
├── self.language = DeepseekV2ForCausalLM(language_config)├── DeepseekV2ForCausalLM.__init__(config)├── self.model = DeepseekV2Model(config)├── DeepseekV2Model.__init__(config)├── self.embed_tokens = nn.Embedding(...)├── self.layers = nn.ModuleList([...])├── DeepseekV2DecoderLayer(config, layer_idx)├── self.self_attn = ATTENTION_CLASSES[attn_implementation]├── DeepseekV2Attention(config, layer_idx)  # 包含LoRA│   ├── q_a_proj, q_b_proj (LoRA)│   ├── kv_a_proj, kv_b_proj (LoRA)│   └── 其他注意力组件└── 或者 DeepseekV2FlashAttention2├── self.mlp = DeepseekV2MLP/MoE└── 层归一化└── self.norm = DeepseekV2RMSNorm(...)└── self.lm_head = nn.Linear(...)

具体的看下DeepseekV2Attention(config, layer_idx)中的调用代码

class DeepseekV2Attention(nn.Module):def __init__(self, config, layer_idx):# LoRA参数self.q_lora_rank = config.q_lora_rank      # 1536self.kv_lora_rank = config.kv_lora_rank    # 512# LoRA层if self.q_lora_rank is not None:self.q_a_proj = nn.Linear(hidden_size, q_lora_rank)self.q_b_proj = nn.Linear(q_lora_rank, output_dim)self.kv_a_proj_with_mqa = nn.Linear(self.hidden_size,config.kv_lora_rank + config.qk_rope_head_dim,bias=config.attention_bias,)self.kv_a_layernorm = DeepseekV2RMSNorm(config.kv_lora_rank)self.kv_b_proj = nn.Linear(config.kv_lora_rank,self.num_heads* (self.q_head_dim - self.qk_rope_head_dim + self.v_head_dim),bias=False,)   

到这里为止我们也就确定了A和B,但我们需要知道q和KV为什么需要生成两组A,B。缩放因子α和参数r又在代码中哪里体现了

这里进行补充说明理解

本文信息在完整的输入进来

实际上,本文信息所有token都经过相同的输入hidden_states = self.embed_tokens(input_ids)  # [batch, seq_len, hidden_size]# 然后通过不同的投影层生成Q、K、V
q = self.q_proj(hidden_states)  # 查询投影
k = self.k_proj(hidden_states)  # 键投影  
v = self.v_proj(hidden_states)  # 值投影在DeepSeek-VL2中,K和V被合并处理:
# 合并的KV投影 (DeepseekV2Attention中可以找到对应的处理方式)
self.kv_a_proj_with_mqa = nn.Linear(self.hidden_size,config.kv_lora_rank + config.qk_rope_head_dim,  # 512 + 64 = 576bias=config.attention_bias,
)def forward(self, hidden_states):# 1. 生成Q(查询)if self.q_lora_rank is None:q = self.q_proj(hidden_states)  # 标准投影else:q = self.q_b_proj(self.q_a_layernorm(self.q_a_proj(hidden_states)))  # LoRA投影# 2. 生成合并的KVcompressed_kv = self.kv_a_proj_with_mqa(hidden_states)  # 4096 → 576# 3. 分离K和Vcompressed_kv, k_pe = torch.split(compressed_kv, [self.kv_lora_rank, self.qk_rope_head_dim], dim=-1)# compressed_kv: [batch, seq_len, 512] - 用于生成K和V# k_pe: [batch, seq_len, 64] - RoPE位置编码# 4. 通过B矩阵生成最终的K和Vkv_b_proj = self.kv_b_proj.weight.view(self.num_heads, -1, self.kv_lora_rank)# 从512维度扩展到最终的K和V维度通过kv_lora_b分离出K和V,也就是B矩阵
k = kv_lora_b_k(compressed_kv) → [batch, seq_len, k_dim]
v = kv_lora_b_v(compressed_kv) → [batch, seq_len, v_dim]

通过以上细读代码,其实我们可以注意到DeepSeek-VL2中的LoRA实现没有显式的缩放因子α

DeepSeek-VL2的LoRA实现是"替换式"而非"加法式"

# 标准LoRA(加法式)
output = original_projection(x) + α * lora_projection(x)# DeepSeek-VL2 LoRA(替换式)
output = lora_projection(x)  # 直接替换原始投影对相应的步骤进行简单实现
# 查询LoRA
if self.q_lora_rank is None:q = self.q_proj(hidden_states)  # 原始投影
else:q = self.q_b_proj(self.q_a_layernorm(self.q_a_proj(hidden_states)))  # LoRA投影# 键值LoRA
compressed_kv = self.kv_a_proj_with_mqa(hidden_states)
compressed_kv = self.kv_a_layernorm(compressed_kv)

这里的r也对用的表示为LoRA他降维的维度

lora_config = {'q_lora_rank': 256,    # r参数'kv_lora_rank': 128,   # r参数# 没有α参数,因为DeepSeek-VL2不使用
}# q_lora_rank = 256 表示:
q_a_proj: 4096 → 256    # A矩阵:降维到256
q_b_proj: 256 → 6144    # B矩阵:从256升维到输出维度# kv_lora_rank = 128 表示:
kv_a_proj: 4096 → 128   # A矩阵:降维到128  
kv_b_proj: 128 → 8192   # B矩阵:从128升维到输出维度# 原始全连接层
W: [6144, 4096]  # 完整权重矩阵# LoRA分解
A: [256, 4096]   # r=256,降维矩阵
B: [6144, 256]   # r=256,升维矩阵# 数学表示
W ≈ B * A  # 低秩近似

总结来说,如果我们在调用DeepSeek_vl2的LoRA时,其实只需要关心Q_r和KV_r这两组参数值就可以了,值得注意的kv_lora_rank的A和B矩阵是架构必需的,q_lora_rank才是可选的!

def _freeze_backbone_parameters(self):for name, param in self.backbone.named_parameters():# 只训练LoRA相关参数if 'q_a_proj' in name or 'q_b_proj' in name or 'kv_a_proj' in name or 'kv_b_proj' in name:param.requires_grad = True  # 可训练else:param.requires_grad = False  # 冻结# 可训练参数(requires_grad = True)
✅ q_a_proj.weight, q_a_proj.bias
✅ q_b_proj.weight
✅ kv_a_proj.weight, kv_a_proj.bias  # KV的A矩阵
✅ kv_b_proj.weight                   # KV的B矩阵# 冻结参数(requires_grad = False)
❌ q_proj.weight, q_proj.bias(如果存在)
❌ o_proj.weight, o_proj.bias
❌ vision编码器的所有参数
❌ projector的所有参数
❌ language模型的其他参数# 在原始DeepSeek-VL2中,所有参数默认都是可训练的:
# ✅ vision编码器的所有参数
# ✅ projector的所有参数  
# ✅ language模型的所有参数
# ✅ 包括q_proj, kv_proj, o_proj等# 没有内置的冻结机制
http://www.dtcms.com/a/496193.html

相关文章:

  • 2025年--Lc196-712. 两个字符串的最小ASCII删除和(动态规划在字符串的应用)--Java版
  • 淄博有做网站的吗第一免费营销型网站
  • 怎样做模板网站免费网站提交入口
  • 网站建设是要考虑什么东西做网站有底薪吗
  • 买卖合同审查要点及指南
  • Mui框架做网站专项培训网站建设方案
  • Marin说PCB之POC电路layout设计仿真案例---16
  • M部分权限的撤销
  • 建立网站一般多少钱怎样用网站做app
  • 申威(sw_64)架构下如何安装java-1.8.0-swjdk的rpm包?​
  • 性能测试之性能调优详解
  • sql日志打印控制台及存储
  • 青岛城乡住房建设厅网站软件开发外包是什么意思
  • 网站公司的未来中国城乡住房和建设部网站
  • 算法416. 分割等和子集
  • 编织网站建设网站建设考核
  • 2-SpringCloud-Consul服务注册与发现和分布式配置管理
  • 前后端分离项目java+vue 加密一般用几种加密方式,具体是什么加密,怎么用的
  • 从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
  • matlab_学习_均分数据
  • 深圳免费建站山东省建设节能协会网站
  • 青岛万维网站设计珠宝类企业网站(手机端)
  • 【展厅多媒体】触摸查询一体机实现数据可视化
  • linux学习笔记(37)mysql视图详解
  • 自定义配置小程序tabbar逻辑思路
  • 临沂网站制作网站微信商城搭建
  • 月牙河做网站公司搜索引擎排名规则
  • 多字节串口收发IP设计(七)串口接收模块合并及排故(含源码)
  • 建立网站的意义哪个建站平台较好
  • 如何进行坡度分析