复习2

73 阅读8分钟

image.png

image.png

image.png

image.png

image.png

硬约束:权重 不可 超过某个值 不然 就是对于某个特征过拟合了 image.png

image.png

image.png

image.png

image.png 批归一化(Batch Normalization)的原理是这样的:

  1. 为什么需要它:
  • 解决内部协变量偏移问题
  • 加快训练速度
  • 允许使用更大的学习率
  • 降低对初始化的敏感度
  • 具有轻微正则化效果
  1. 计算步骤:
# 假设输入是一个batch的数据x
# Step 1: 计算均值
μ = (1/m) * Σx   # m是batch size

# Step 2: 计算方差
σ² = (1/m) * Σ(x - μ)²

# Step 3: 标准化
x̂ = (x - μ) / √(σ² + ε)   # ε是很小的数,防止除0

# Step 4: 缩放和平移
y = γ * x̂ + β   # γ和β是可学习的参数
  1. 训练和预测时的区别:
  • 训练时:使用当前batch的统计量(μ, σ²)
  • 预测时:使用训练时所有batch统计量的移动平均值
  1. 优点:
  • 加快训练收敛速度
  • 缓解梯度消失问题
  • 降低对初始化的依赖
  1. 缺点:
  • 小batch size效果不好
  • 计算开销增加
  • RNN中使用较复杂

记住一点:BatchNorm是在每个batch内部进行归一化,而不是在整个数据集上。

在实际训练中,BatchNorm通常是这样用的:

  1. 在PyTorch中的使用:
import torch.nn as nn

class MyModel(nn.Module):
    def __init__(self):
        super().__init__()
        # 对于CNN
        self.conv1 = nn.Conv2d(3, 64, 3)
        self.bn1 = nn.BatchNorm2d(64)  # 2d是因为是图像数据
        self.relu = nn.ReLU()

        # 对于全连接层
        self.fc1 = nn.Linear(64, 32)
        self.bn2 = nn.BatchNorm1d(32)  # 1d是因为是向量

    def forward(self, x):
        # 常见顺序:Conv/Linear -> BN -> ReLU
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)

        x = self.fc1(x)
        x = self.bn2(x)
        x = self.relu(x)
        return x
  1. 在训练时:
# 训练模式
model.train()
for batch in train_loader:
    optimizer.zero_grad()
    output = model(batch)
    loss = criterion(output, target)
    loss.backward()
    optimizer.step()
  1. 在验证/测试时:
# 评估模式 - BN会使用运行时统计量
model.eval()
with torch.no_grad():
    output = model(test_data)
  1. 一些实践经验:
  • batch size不要太小,通常至少32
  • 通常放在激活函数前面
  • 如果用了BN,通常就不需要在卷积层用bias了
  • 学习率可以适当调大
  • 对模型初始化不用太敏感
  1. 常见问题排查:
# 检查BN层的running_mean和running_var
for name, module in model.named_modules():
    if isinstance(module, nn.BatchNorm2d):
        print(f"{name} running_mean: {module.running_mean.mean().item()}")
        print(f"{name} running_var: {module.running_var.mean().item()}")

image.png

d

image.png

c

image.png gpt1: 我选择答案 b. "estimated using running averages"(使用滑动平均估计)。

原因解释:

  1. 在测试阶段,BatchNorm使用的均值和方差是训练过程中累积的滑动平均值
  2. 这些统计量在训练过程中不断更新:
    running_mean = momentum * running_mean + (1 - momentum) * current_batch_mean
    running_var = momentum * running_var + (1 - momentum) * current_batch_var
    
  3. 选项a不太准确,因为不是直接从训练集预计算的,而是通过滑动平均累积的
  4. 选项c和d明显不对,因为我们确定使用的是滑动平均值

这样做的好处是:

  • 使推理结果更稳定
  • 不依赖于当前batch的统计量
  • 能反映整个训练过程中的数据分布

gpt2: 我选B: estimated using running averages (使用滑动平均估计)

原因是:

  1. 在训练阶段,BatchNorm会计算每个batch的均值和方差

  2. 同时会用一个momentum参数来更新running averages (滑动平均值)

  3. 在测试阶段,我们不能用单个batch的统计量(因为batch size可能很小,不具代表性),也不能用整个训练集预计算的固定值

  4. 所以使用训练过程中累积的running averages是最合适的方法

    • 这些running averages能较好地反映整体数据分布
    • 在测试时保持稳定性

在PyTorch中,这是通过BN层的running_mean和running_var属性来实现的。

image.png

image.png

image.png

image.png

image.png

image.png

让我用更通俗的方式解释,假设我们在开发一个二手房价格预测系统:

最大似然估计(MLE)的做法

  • 就像一个单纯的学生,只看眼前的数据
  • 比如收集了100套房子的数据:
    • A小区90平米,售价200万
    • B小区100平米,售价230万
    • 等等...
  • 然后直接用这些数据拟合出一个公式:
    • "房价 = 2万元/平米 × 面积 + 50万元"
  • 特点:完全相信数据,不管这个结果是否符合常识

贝叶斯推断的做法

  • 像一个有经验的房产专家:
    • 首先有自己的专业判断(先验知识)
    • "这个区域每平米价格应该在1.5-2.5万之间"
    • "普通住宅的基础价格应该在30-70万之间"
  • 然后看到实际数据后:
    • 结合经验和数据
    • 给出更谨慎的预测:
    • "这套90平的房子,售价大概率在200-240万之间"
    • 而不是给出一个精确但可能不准的数字

为什么贝叶斯更好?

  1. 考虑了专业经验
  2. 知道预测有不确定性
  3. 不会被异常数据带偏
  4. 更符合现实世界的决策方式

这就像找一个二手房评估师:

  • 新手可能就是简单看数据(MLE)
  • 老专家会用经验+数据来判断(贝叶斯)

再比如

"选男朋友"

最大似然估计(MLE)

  • 相亲选手小美:纯看条件挑对象
  • 数据收集:身高180✓ 年薪50W✓ 有车有房✓
  • 立刻下结论:"这就是我命中注定的真命天子!"
  • 结果:可能翻车,因为没考虑其他重要因素

贝叶斯推断

  • 相亲选手小芳:结合经验看对象
  • 先验知识:"帅哥通常都有大量追求者"
  • 新数据:"这人条件是不错,但总给我发朋友圈广告..."
  • 谨慎结论:"虽然各项指标都很棒,但我觉得还是再观察观察,可能是传销..."

总结:

  • MLE就像初恋:冲动、只看表面✨
  • 贝叶斯就像大龄剩女:谨慎、看得深远🧐

"选女朋友"

最大似然估计选手小明:

  • 数据说明一切:身高165✓ 体重45kg✓ 长发飘飘✓
  • "这就是我的女神!立刻表白!"
  • 结果发现:原来是个网红滤镜...🤡

贝叶斯推断选手老王:

  • 先验经验:"颜值太高的通常都很麻烦"
  • 观察数据:"确实很漂亮,但每天都在蹦迪..."
  • 贝叶斯结论:"虽然是女神级别,但性格可能不合适,再看看吧"
  • 后来发现:果然是个酒吧托!😱

总结:

  • MLE = 初哥:看到美女就晕头转向
  • 贝叶斯 = 老司机:经验教会我要多观察
  • 贝叶斯还会算概率:"这妹子是真心的概率只有30%..." 🤔

确实,贝叶斯方法就像是"老司机",不会被表面数据骗到,总是结合经验来判断。而MLE就像是"菜鸟",看到漂亮数据就上头,容易翻车。

这就是为什么在机器学习中,处理复杂问题时更喜欢用贝叶斯方法 - 毕竟谁也不想训练出一个"容易被骗"的模型是吧?😄

数据增强就像给模型"补课"- 通过对原始数据做各种变换来扩充训练集。以人脸识别为例:

  1. 基础变换:
  • 翻转:让模型认识"左照片"和"右照片"也是同一个人
  • 旋转:歪着头拍的照片也要认得
  • 缩放:远近拍摄都不怕
  1. 高级变换:
  • 改变亮度/对比度:适应不同光线条件
  • 加噪声:模拟真实场景的干扰
  • 遮挡部分:戴口罩、墨镜也能认出来

就像教小孩认人:从各个角度、不同表情、穿不同衣服都给看看,这样见到新照片才不会懵。这种方法显著提高了模型泛化能力,减少了过拟合。

让我用"约会软件刷照片"来解释一下混淆矩阵 😂

真实情况 vs 预测结果:

TP (True Positive):

  • 真帅哥被右滑 ✓
  • "确实是高富帅,没看走眼!"

FP (False Positive):

  • 照片P太狠被右滑 ✗
  • "约见后发现上当了..."

TN (True Negative):

  • 真渣男被左滑 ✓
  • "一眼就看出来是骗子!"

FN (False Negative):

  • 真诚好男人被左滑 ✗
  • "完了,错过一个真心人..."

这就解释了为什么刷照片要谨慎:

  • 不是所有高颜值都是真实的(小心FP)
  • 也别错过了外表普通但内在优秀的(注意FN) 😏

image.png

image.png

Precision (精确率) = TP/(TP+FP)

  • "你看对眼的人里,到底有几个是真香的?"
  • 例如:10个看上的人,3个真实靠谱,精确率就是30%
  • "眼光够不够准的问题" 👀

Recall (召回率) = TP/(TP+FN)

  • "优质对象你到底遇到了几个?错过了几个?"
  • 例如:圈子里10个好对象,你只看对了3个,召回率就是30%
  • "你错过了多少真爱的问题" 💔

Accuracy (准确率) = (TP+TN)/(TP+TN+FP+FN)

  • "你的眼光总体靠谱程度"
  • 包括:正确看对了好的,也正确避开了渣的
  • "整体判断水平的问题" 🎯

F1-score = 2×(Precision×Recall)/(Precision+Recall)

  • 精确率和召回率的调和平均
  • "既要眼光准,又不能错过太多"
  • "相亲综合能力分" 😎

举个例子:

  • 你面对100个异性

  • 30个是好对象(P),70个是渣(N)

  • 你看上了20个(Predicted P),没看上80个(Predicted N)

  • 其中看上的20个里面有10个真的好(TP)

  • 那么:

    • Precision = 10/20 = 50% (眼光一般)
    • Recall = 10/30 = 33% (错过不少)
    • Accuracy = (10+60)/100 = 70% (总体还行)
    • F1 = 40% (综合评分凑合)

记住:没有最好的指标,要根据场景选择关注重点!

  • 找对象:宁可错过(低Recall),不要看错(高Precision)
  • 找工作:宁可多投几个(低Precision),不要错过机会(高Recall) 😉

image.png

image.png

image.png

image.png

image.png