LoRA:低秩分解微调与代码

传统的微调,即微调全量参数,就是上面的公式,但是我们可以通过两个矩阵,来模拟这个全量的矩阵,如果原来的W是(N * N)维度,我们可以通过两个(N * R) 和 (R * N)的矩阵矩阵乘,来模拟微调的结果。

方法很简单,直接上代码

1. LoRA层:

python3 复制代码
import math

class LoRALayer(torch.nn.Module):
    def __init__(self, in_dim, out_dim, rank, alpha):
        super().__init__()
        self.A = torch.nn.Parameter(torch.empty(in_dim, rank))
        torch.nn.init.kaiming_uniform_(self.A, a=math.sqrt(5))  # similar to standard weight initialization
        self.B = torch.nn.Parameter(torch.zeros(rank, out_dim))
        self.alpha = alpha

    def forward(self, x):
        x = self.alpha * (x @ self.A @ self.B)
        return x

LoRALayer就是LoRA的旁侧连接,包括了两个矩阵A和B,A初始化,但是B是全0矩阵,这保证一开始LoRA对模型没有影响,即输出和原来完全相同。

我们注意到了两个参数,一个是rank,一个是alpha。rank控制了LoRA旁侧连接的秩,这就是LoRA微调参数量较小的原因所在,因为他是由两个小的矩阵构成的。alpha控制LoRA对原来Linear的影响。

2. LoRA替代层

知道了LoRA的原理,现在只需要在模型中加入LoRA即可。但是LoRA要如何加入呢,在模型中加入的话,需要修改前向传播的逻辑才能人为的修改,不难想到另外一种方法,我们直接替代原来的Linear层,用LinearWithLoRA替换,新的层既有原来的Linear,也有LoRA。

python 复制代码
class LinearWithLoRA(torch.nn.Module):
    def __init__(self, linear, rank, alpha):
        super().__init__()
        self.linear = linear
        self.lora = LoRALayer(
            linear.in_features, linear.out_features, rank, alpha
        )

    def forward(self, x):
        return self.linear(x) + self.lora(x)

3. 冻结原始参数

python3 复制代码
total_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
print(f"Total trainable parameters before: {total_params:,}")

for param in model.parameters():
    param.requires_grad = False

total_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
print(f"Total trainable parameters after: {total_params:,}")

4. 修改网络

最后,我们只需要遍历网络,得到所有Linear层,并将他们设置为LinearWithLoRA即可。

python3 复制代码
def replace_linear_with_lora(model, rank, alpha):
    for name, module in model.named_children():
        if isinstance(module, torch.nn.Linear):
            # Replace the Linear layer with LinearWithLoRA
            setattr(model, name, LinearWithLoRA(module, rank, alpha))
        else:
            # Recursively apply the same function to child modules
            replace_linear_with_lora(module, rank, alpha)
相关推荐
十铭忘2 小时前
MOTIONGPT3:人类运动作为第二模态
人工智能
weigangwin3 小时前
采用 mem0 之前,先决定 Agent 到底允许记住什么
人工智能·opencv·ai·llm·memory·ai agent·mem0
木木学AI3 小时前
AI客服系统技术选型:Agentic架构与传统规则引擎的能力差异评估
人工智能·架构
hhzz3 小时前
Python大数据实战(十六):音乐推荐系统——基于协同过滤算法构建个性化歌单引擎
大数据·人工智能·python·数据挖掘·数据分析
带娃的IT创业者3 小时前
突破算力与安全的边界:深度解析 Mythos AI 的“受信发布”机制与技术影响
人工智能·安全·大语言模型·ai安全·mythos ai·受信发布·ai监管
dreamread3 小时前
2026紫微八字同排工具怎么选:看盘面切换、功能边界和学习路径
人工智能·软件工具·传统文化
耍酷的魔镜3 小时前
核心设计理念:5W2H、JSON-LD 与通用知识图谱
人工智能·json·知识图谱
星河耀银海4 小时前
大模型安全:对抗攻击与防御方法
人工智能·安全·大模型
xsdick4 小时前
抛弃 OpenClawd吧!我用 Go 打造了企业级 Swarm(蜂群)agent,更智能,更安全、性能快 5 倍、成本直降80%
人工智能·ai·ai编程
xiaoxiaoxiaolll4 小时前
AI赋能CFD:从Fluent仿真到物理信息机器学习流体工程
人工智能