L2范数(L2 Norm)

1. 什么是L2范数?

直观理解

想象你有一个向量(比如嵌入向量 [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} x2=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.)

2. 为什么需要L2正则化?

在机器学习中,L2正则化(也叫权重衰减)的作用是:

  1. 防止过拟合:惩罚过大的参数值,让模型权重保持较小。
  2. 稳定训练:避免某些特征权重过大而主导模型。
类比

假设你在考试复习:

  • 不控制学习量(无正则化):疯狂刷题到凌晨3点,结果考试时过度依赖特定题型,遇到新题就懵。
  • 控制学习量(L2正则化):每天适度学习,知识掌握更均衡,考试更稳定。

3. EmbLoss 类的作用

这个类计算所有输入嵌入矩阵的 L2范数之和(或L2范数的平方和),作为正则化损失。
相当于对模型说:“嵌入向量不要太大,否则我会惩罚你!”

参数解释
参数作用
norm=2指定使用L2范数(设为1则用L1范数)
require_powTrue 时计算 ‖embedding‖₂²(平方和),False 时计算 ‖embedding‖₂(原始范数)

4. 分步拆解代码

场景设定

假设我们有:

  • 用户嵌入矩阵 user_emb:形状 (100, 64)(100个用户,每个用户64维向量)
  • 物品嵌入矩阵 item_emb:形状 (200, 64)(200个物品,每个物品64维向量)
(1) 当 require_pow=False
loss_func = EmbLoss(norm=2)
loss = loss_func(user_emb, item_emb, require_pow=False)

计算过程

  1. user_emb 计算L2范数:
    • 对每个用户的64维向量求L2范数 → 得到100个标量
    • 对这100个标量求平均值
  2. item_emb 同样操作
  3. 将两部分结果相加

最简公式版
L = 1 N ∑ k ∥ E k ∥ p \mathcal{L} = \frac{1}{N} \sum_{k} \|E_k\|_p L=N1kEkp

数学表达式
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=1100uu2+2001i=1200vi2

(2) 当 require_pow=True
loss = loss_func(user_emb, item_emb, require_pow=True)

计算过程

  1. user_emb 计算L2范数的平方:
    • 先对每个用户向量求L2范数 → 100个标量
    • 对这些标量平方 → 100个平方值
    • 求平均值后除以2(self.norm
  2. item_emb 同样操作
  3. 将两部分结果相加

最简公式版

L = 1 N ⋅ p ∑ k ∥ E k ∥ p p \mathcal{L} = \frac{1}{N \cdot p} \sum_{k} \|E_k\|_p^p L=Np1kEkpp

数学表达式
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=1100uu22+200×21i=1200vi22


5. 为什么需要 require_pow 选项?

(1) require_pow=False(直接L2范数)
  • 特点:更温和的正则化,对大数值的惩罚是线性的。
  • 适用场景:需要稀疏性时(某些维度接近0)。
(2) require_pow=True(L2范数的平方)
  • 特点:对大数值惩罚更严厉(平方放大差异)。
  • 数学优势:与标准L2正则化一致(如PyTorch的 weight_decay)。
  • 物理意义:实际计算的是 所有嵌入向量的平方和(即Frobenius范数)。

6. 完整示例代码

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))

7. 输出结果的意义

假设输出:

L2 Norm Loss: tensor(8.02)       # 所有嵌入向量的平均L2长度
L2 Squared Loss: tensor(64.33)   # 所有嵌入向量的平均平方和/2
  • L2 Norm Loss:平均每个向量的长度为8.02(希望这个值不要太大)
  • L2 Squared Loss:平方和后更敏感(值更大),用于严格限制大权重

总结

  • L2范数:衡量嵌入向量的“长度”,用于控制模型复杂度。
  • EmbLoss:计算所有嵌入矩阵的平均L2范数(或平方),作为正则项。
  • 如何选择
    • 常规用途:require_pow=True(标准L2正则化)
    • 需要稀疏性:norm=1(L1范数)

通过这个类,你可以灵活地控制嵌入向量的规模,从而提升模型的泛化能力!

### 如何在 PyTorch 中使用 L2 范数 `torch.norm` 函数 #### 使用方法概述 为了计算张量的L2范数,在调用`torch.norm`函数时设置参数`p=2`即可。这适用于向量和矩阵形式的输入数据。 #### 向量的L2范数计算实例 对于一维张量(即向量),可以通过如下方式来获取其L2范数: ```python import torch vector = torch.tensor([-4., -3., -2., -1., 0., 1., 2., 3., 4.]) l2_norm_vector = torch.norm(vector, p=2) print(l2_norm_vector) # 输出应接近于7.7460 ``` 上述代码创建了一个包含负数到正数值的一维浮点型张量,并对其应用了L2范数运算[^4]。 #### 矩阵的L2范数计算实例 当处理二维或多维张量(如矩阵)并希望沿特定维度求解L2范数时,可通过设定`dim`参数指定期望的操作轴线: ```python matrix = vector.view(3, 3) # 计算整个矩阵的Frobenius范数,默认行为相当于设置了p='fro' full_matrix_l2_fro = torch.norm(matrix) # 对每一列分别计算L2范数 column_wise_l2 = torch.norm(matrix, p=2, dim=0) # 对每一行分别计算L2范数 row_wise_l2 = torch.norm(matrix, p=2, dim=1) print(f"Full matrix Fro norm: {full_matrix_l2_fro}") print(f"Column-wise L2 norms: {column_wise_l2}") print(f"Row-wise L2 norms: {row_wise_l2}") ``` 这里展示了三种不同情况下的L2范数计算:整体矩阵、按列以及按行的方式[^1]。 #### 关键参数解释 - **input**: 输入张量。 - **p (float)**: 指定要使用的范数类型;对于L2范数而言,应该设为2。 - **dim (int or tuple of ints, optional)**: 如果提供了此参数,则表示沿着哪个维度进行操作;如果不提供,则默认在整个张量上执行全局范数计算。 - **keepdim (bool, optional)**: 是否保持输出张量具有相同的尺寸结构作为输入张量,仅当指定了`dim`时有效。 - **dtype (torch.dtype, optional)**: 可选地指定返回值的数据类型。 通过调整这些参数选项,可以根据具体需求灵活运用`torch.norm`来进行各种类型的范数计算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值