想象你有一个向量(比如嵌入向量 [1.2, -0.5, 3.1]
),L2范数就是计算这个向量的 “几何长度”。
就像在三维空间中,计算点 (1.2, -0.5, 3.1)
到原点 (0,0,0)
的距离。
对于一个向量 x = [x₁, x₂, ..., xn]
,它的L2范数是:
∥ x ∥ 2 = x 1 2 + x 2 2 + ⋯ + x n 2 \|x\|_2 = \sqrt{x_1^2 + x_2^2 + \cdots + x_n^2} ∥x∥2=x12+x22+⋯+xn2
import torch
x = torch.tensor([3.0, 4.0])
l2_norm = torch.norm(x, p=2) # 计算 sqrt(3² + 4²) = 5.0
print(l2_norm) # 输出: tensor(5.)
在机器学习中,L2正则化(也叫权重衰减)的作用是:
假设你在考试复习:
EmbLoss
类的作用这个类计算所有输入嵌入矩阵的 L2范数之和(或L2范数的平方和),作为正则化损失。
相当于对模型说:“嵌入向量不要太大,否则我会惩罚你!”
参数 | 作用 |
---|---|
norm=2 |
指定使用L2范数(设为1则用L1范数) |
require_pow |
True 时计算 ‖embedding‖₂²(平方和),False 时计算 ‖embedding‖₂(原始范数) |
假设我们有:
user_emb
:形状 (100, 64)
(100个用户,每个用户64维向量)item_emb
:形状 (200, 64)
(200个物品,每个物品64维向量)require_pow=False
loss_func = EmbLoss(norm=2)
loss = loss_func(user_emb, item_emb, require_pow=False)
计算过程:
user_emb
计算L2范数:
item_emb
同样操作最简公式版
L = 1 N ∑ k ∥ E k ∥ p \mathcal{L} = \frac{1}{N} \sum_{k} \|E_k\|_p L=N1k∑∥Ek∥p
数学表达式:
L = 1 100 ∑ u = 1 100 ∥ u u ∥ 2 + 1 200 ∑ i = 1 200 ∥ v i ∥ 2 \mathcal{L} = \frac{1}{100} \sum_{u=1}^{100} \|\mathbf{u}_u\|_2 + \frac{1}{200} \sum_{i=1}^{200} \|\mathbf{v}_i\|_2 L=1001u=1∑100∥uu∥2+2001i=1∑200∥vi∥2
require_pow=True
loss = loss_func(user_emb, item_emb, require_pow=True)
计算过程:
user_emb
计算L2范数的平方:
self.norm
)item_emb
同样操作最简公式版
L = 1 N ⋅ p ∑ k ∥ E k ∥ p p \mathcal{L} = \frac{1}{N \cdot p} \sum_{k} \|E_k\|_p^p L=N⋅p1k∑∥Ek∥pp
数学表达式:
L = 1 100 × 2 ∑ u = 1 100 ∥ u u ∥ 2 2 + 1 200 × 2 ∑ i = 1 200 ∥ v i ∥ 2 2 \mathcal{L} = \frac{1}{100 \times 2} \sum_{u=1}^{100} \|\mathbf{u}_u\|_2^2 + \frac{1}{200 \times 2} \sum_{i=1}^{200} \|\mathbf{v}_i\|_2^2 L=100×21u=1∑100∥uu∥22+200×21i=1∑200∥vi∥22
require_pow
选项?require_pow=False
(直接L2范数)require_pow=True
(L2范数的平方)weight_decay
)。import torch
import torch.nn as nn
# 定义损失类
class EmbLoss(nn.Module):
def __init__(self, norm=2):
super().__init__()
self.norm = norm
def forward(self, *embeddings, require_pow=False):
if require_pow:
loss = sum(
torch.norm(embedding, p=self.norm).pow(self.norm) # ‖E‖²
for embedding in embeddings
) / sum(embedding.shape[0] for embedding in embeddings) / self.norm
else:
loss = sum(
torch.norm(embedding, p=self.norm) # ‖E‖
for embedding in embeddings
) / sum(embedding.shape[0] for embedding in embeddings)
return loss
# 模拟数据
user_emb = torch.randn(100, 64) # 100个用户嵌入
item_emb = torch.randn(200, 64) # 200个物品嵌入
# 计算损失
loss_func = EmbLoss(norm=2)
print("L2 Norm Loss:", loss_func(user_emb, item_emb, require_pow=False))
print("L2 Squared Loss:", loss_func(user_emb, item_emb, require_pow=True))
假设输出:
L2 Norm Loss: tensor(8.02) # 所有嵌入向量的平均L2长度
L2 Squared Loss: tensor(64.33) # 所有嵌入向量的平均平方和/2
L2 Norm Loss
:平均每个向量的长度为8.02(希望这个值不要太大)L2 Squared Loss
:平方和后更敏感(值更大),用于严格限制大权重EmbLoss
:计算所有嵌入矩阵的平均L2范数(或平方),作为正则项。require_pow=True
(标准L2正则化)norm=1
(L1范数)通过这个类,你可以灵活地控制嵌入向量的规模,从而提升模型的泛化能力!