Skip to content

ch10监督微调章节中未提到为啥lora模型里面要乘0.01。 #1

Open

Description

@jcchan23

在ch10监督微调章节中提到了LoRALinear的实现。

import torch
import torch.nn as nn

class LoRALinear(nn.Module):
    def __init__(self, original: nn.Linear, r: int = 8, alpha: int = 16):
        super().__init__()
        self.original = original
        self.original.weight.requires_grad_(False)  # 冻结 W
        out_dim, in_dim = original.weight.shape
        self.A = nn.Parameter(torch.randn(r, in_dim) * 0.01) # 这里的0.01的作用未提及。
        self.B = nn.Parameter(torch.zeros(out_dim, r))
        self.scale = alpha / r

    def forward(self, x):
        base_out = self.original(x)             # Wx
        lora_out = (x @ self.A.T) @ self.B.T    # xA^T B^T = (BA)x 的等价写法
        return base_out + self.scale * lora_out

然后文章下面花了一点篇幅讲解为啥self.B需要使用全0初始化,是因为BAx=0 → 训练起点等价原模型,避免一开始就破坏 pretrain。A 必须非零(Kaiming 类小方差初始化),否则 B 的梯度∂L/∂B = (∂L/∂y)·(Ax)^T含Ax=0因子 → B 永远学不动。两个都为 0 时双向卡死:B=0 让 A 的梯度 B^T·(∂L/∂y)·x^T 也为 0。所以 LoRA 选 "B=0 + A 随机" 这一组合:起点等价 base,且 B 第一步就有非零梯度。

但是没有讲解为啥self.A需要乘一个0.01,本质上是因为torch.randn(r, in_dim)是初始化一个[r, in_dim]的张量,生成来自标准正态分布(均值为 0,方差为 1 的高斯分布),乘上0.01之后,就变成了均值依然为0,但是方差变成0.01^2=1e-4的高斯分布的张量了,这样子同样能够起到降低初始训练对于原模型的影响,让模型起到一个平滑扰动的起始微调,和B的全0初始化的作用类似。

建议补充在原始文章中。

Activity

  1. yangfch3 commented on Sep 14, 2026

    @yangfch3
    Owner

    已补,谢谢 @jcchan23 健文大神~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions