#P3658. 第3题-支持LoRA的Attention实现
-
ID: 3001
Tried: 146
Accepted: 32
Difficulty: 7
所属公司 :
华为
时间 :2025年9月12日-AI岗
-
算法标签>LoRA微调
第3题-支持LoRA的Attention实现
1. LoRA 思路
-
原始权重 Wq 冻结;
-
新增低秩矩阵 $A\in \mathbb{R}^{r\times d}, B\in \mathbb{R}^{d\times r}$,形成:
Wq′=Wq+BA -
若 r=0,直接用原始 Wq。
2. Attention 计算步骤
-
计算
$$Q = XW_q'^\top,\quad K = XW_k^\top,\quad V = XW_v^\top $$ -
打分并缩放
S=dQK⊤ -
对每一行做 稳定 softmax。
-
输出
O=softmax(S)V
3. 实现要点
- float64 精度,避免溢出;
- softmax 时对每行减去最大值;
- 输出拉平,保留四位小数,
-0.0000
特判为0.0000
。
代码实现
import sys
import numpy as np
def softmax(x):
"""
计算softmax函数
"""
x = x.astype(np.float64)
max_vals = np.max(x, axis=1, keepdims=True)
exp_vals = np.exp(x - max_vals)
return exp_vals / np.sum(exp_vals, axis=1, keepdims=True)
def linear_attention_with_adapters(x, wq, wk, wv, A, B):
"""
实现带有LoRA适配器的线性注意力机制
"""
d = x.shape[1]
# 应用LoRA适配器(如果提供)
if A is not None and B is not None and A.size > 0 and B.size > 0:
effective_wq = wq + B @ A
else:
effective_wq = wq
# 计算查询、键和值
Q = x @ effective_wq.T
K = x @ wk.T
V = x @ wv.T
# 计算注意力分数
scale_factor = 1.0 / np.sqrt(d)
attention_scores = (Q @ K.T) * scale_factor
# 应用softmax得到注意力权重
attention_weights = softmax(attention_scores)
# 计算输出
output = attention_weights @ V
return output
def format_output(values):
"""
格式化输出,确保-0.0000显示为0.0000
"""
formatted_values = []
for value in values:
formatted = f"{value:.4f}"
if formatted == "-0.0000":
formatted = "0.0000"
formatted_values.append(formatted)
return formatted_values
def main():
# 读取输入数据
data = list(map(float, sys.stdin.read().strip().split()))
iterator = iter(data)
# 读取维度参数
batch_size = int(next(iterator))
dimension = int(next(iterator))
rank = int(next(iterator))
# 读取输入矩阵
x = np.array([next(iterator) for _ in range(batch_size * dimension)]).reshape(batch_size, dimension)
# 读取权重矩阵
wq = np.array([next(iterator) for _ in range(dimension * dimension)]).reshape(dimension, dimension)
wk = np.array([next(iterator) for _ in range(dimension * dimension)]).reshape(dimension, dimension)
wv = np.array([next(iterator) for _ in range(dimension * dimension)]).reshape(dimension, dimension)
# 读取LoRA适配器参数(如果存在)
if rank > 0:
A = np.array([next(iterator) for _ in range(rank * dimension)]).reshape(rank, dimension)
B = np.array([next(iterator) for _ in range(dimension * rank)]).reshape(dimension, rank)
else:
A = None
B = None
# 计算输出
output = linear_attention_with_adapters(x, wq, wk, wv, A, B)
# 格式化和打印结果
flat_output = output.reshape(-1)
formatted_output = format_output(flat_output)
print(" ".join(formatted_output))
if __name__ == "__main__":
main()
题目内容
相对于全量微调,LoRA微调提出了一种低秩分解的方法,只需在原模型参数基础上增加少量的可训练参数,大幅降低计算成本和内存占用。具体而言,对于原始的预训练权重矩阵W,LORA做以下改进:
W′=W+B×A
W为原始权重(冻结不变),B∈Rd×r和 A∈Rr×d为新增的低秩矩阵,r<<d,秩r一般很小。微调时只更新 A、B这两个矩阵,显著减少训练的参数数量。请实现支持LoRA的Attention计算
函数LoRA_Attention(x,Wa,Wk,Wv,A,B) 。为简化实现,仅需支持Attention中Q的LoRA结构实现即可。实现时请使用float64位精度。
输入描述
第1行: b,d,r,其中b为batch size,d为特征的长度,r为LoRA矩阵的秩,b≥1,d≥1,r≥0
第2行:输入x,长度为b×d
第3−5行: Wq,Wk,Wv,长度为d×d
若r>0,则:
第6行:A,长度为r×d
第7行:B,长度为d×r
输出描述
LoRAAttention计算的结果,输出保留四位小数,不足四位小数的补0
样例1
输入
2 5 3
-0.58 -0.52 -0.02 0.56 0.79 0.06 -0.64 -0.04 -0.20 -0.38
0.24 -0.72 -0.66 0.96 0.02 -0.43 -0.24 0.19 -0.85 -0.35 0.69 -0.09 0.99 0.21 -0.06 0.55 0.57 0.97 0.58 -0.16 0.64 0.02 -0.71 0.53 -0.90
0.07 -0.16 -0.47 -0.32 -0.92 0.13 -0.74 -0.87 0.05 0.33 0.37 0.75 0.57 0.14 -0.62 0.67 -0.62 -0.85 0.09 -0.90 0.22 0.97 -0.68 0.61 0.48
0.39 -0.74 0.84 0.21 0.44 -0.59 -0.07 -0.84 -0.70 0.86 -0.12 -0.06 0.45 -0.43 -0.09 -0.73 0.56 -0.62 0.36 -0.87 -0.97 -0.48 0.71 0.07 -0.28
0.25 0.58 -0.04 -0.94 0.45 -0.60 0.89 0.94 0.35 -0.76 -0.47 -0.40 0.10 0.23 0.25
-0.18 -0.11 0.60 0.37 0.75 0.51 -0.76 -0.39 -0.81 -0.88 -0.43 -0.88 0.15 -0.46 -0.24
输出
0.3499 0.0803 0.0376 -0.1791 0.3952 0.4112 0.2240 -0.0239 -0.2177 0.4478
样例2
输入
1 3 2
0.58 -0.65 -0.63
-0.74 -0.71 0.65 0.70 -0.14 0.01 -0.84 0.20 0.25
-0.60 0.51 -0.12 -0.35 0.57 -0.38 -0.44 -0.82 0.53
0.14 0.03 -0.27 0.10 -0.12 0.85 -0.55 0.10 -0.43
0.65 0.32 -0.42 -0.62 -0.88 -0.70
-0.66 0.49 0.09 -0.21 0.48 0.41
输出
0.2318 -0.3995 -0.1131