硬约束:权重 不可 超过某个值 不然 就是对于某个特征过拟合了
批归一化(Batch Normalization)的原理是这样的:
- 为什么需要它:
- 解决内部协变量偏移问题
- 加快训练速度
- 允许使用更大的学习率
- 降低对初始化的敏感度
- 具有轻微正则化效果
- 计算步骤:
# 假设输入是一个batch的数据x
# Step 1: 计算均值
μ = (1/m) * Σx # m是batch size
# Step 2: 计算方差
σ² = (1/m) * Σ(x - μ)²
# Step 3: 标准化
x̂ = (x - μ) / √(σ² + ε) # ε是很小的数,防止除0
# Step 4: 缩放和平移
y = γ * x̂ + β # γ和β是可学习的参数
- 训练和预测时的区别:
- 训练时:使用当前batch的统计量(μ, σ²)
- 预测时:使用训练时所有batch统计量的移动平均值
- 优点:
- 加快训练收敛速度
- 缓解梯度消失问题
- 降低对初始化的依赖
- 缺点:
- 小batch size效果不好
- 计算开销增加
- RNN中使用较复杂
记住一点:BatchNorm是在每个batch内部进行归一化,而不是在整个数据集上。
在实际训练中,BatchNorm通常是这样用的:
- 在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
- 在训练时:
# 训练模式
model.train()
for batch in train_loader:
optimizer.zero_grad()
output = model(batch)
loss = criterion(output, target)
loss.backward()
optimizer.step()
- 在验证/测试时:
# 评估模式 - BN会使用运行时统计量
model.eval()
with torch.no_grad():
output = model(test_data)
- 一些实践经验:
- batch size不要太小,通常至少32
- 通常放在激活函数前面
- 如果用了BN,通常就不需要在卷积层用bias了
- 学习率可以适当调大
- 对模型初始化不用太敏感
- 常见问题排查:
# 检查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()}")
d
c
gpt1:
我选择答案 b. "estimated using running averages"(使用滑动平均估计)。
原因解释:
- 在测试阶段,BatchNorm使用的均值和方差是训练过程中累积的滑动平均值
- 这些统计量在训练过程中不断更新:
running_mean = momentum * running_mean + (1 - momentum) * current_batch_mean running_var = momentum * running_var + (1 - momentum) * current_batch_var
- 选项a不太准确,因为不是直接从训练集预计算的,而是通过滑动平均累积的
- 选项c和d明显不对,因为我们确定使用的是滑动平均值
这样做的好处是:
- 使推理结果更稳定
- 不依赖于当前batch的统计量
- 能反映整个训练过程中的数据分布
gpt2: 我选B: estimated using running averages (使用滑动平均估计)
原因是:
-
在训练阶段,BatchNorm会计算每个batch的均值和方差
-
同时会用一个momentum参数来更新running averages (滑动平均值)
-
在测试阶段,我们不能用单个batch的统计量(因为batch size可能很小,不具代表性),也不能用整个训练集预计算的固定值
-
所以使用训练过程中累积的running averages是最合适的方法
- 这些running averages能较好地反映整体数据分布
- 在测试时保持稳定性
在PyTorch中,这是通过BN层的running_mean和running_var属性来实现的。
让我用更通俗的方式解释,假设我们在开发一个二手房价格预测系统:
最大似然估计(MLE)的做法:
- 就像一个单纯的学生,只看眼前的数据
- 比如收集了100套房子的数据:
- A小区90平米,售价200万
- B小区100平米,售价230万
- 等等...
- 然后直接用这些数据拟合出一个公式:
- "房价 = 2万元/平米 × 面积 + 50万元"
- 特点:完全相信数据,不管这个结果是否符合常识
贝叶斯推断的做法:
- 像一个有经验的房产专家:
- 首先有自己的专业判断(先验知识)
- "这个区域每平米价格应该在1.5-2.5万之间"
- "普通住宅的基础价格应该在30-70万之间"
- 然后看到实际数据后:
- 结合经验和数据
- 给出更谨慎的预测:
- "这套90平的房子,售价大概率在200-240万之间"
- 而不是给出一个精确但可能不准的数字
为什么贝叶斯更好?
- 考虑了专业经验
- 知道预测有不确定性
- 不会被异常数据带偏
- 更符合现实世界的决策方式
这就像找一个二手房评估师:
- 新手可能就是简单看数据(MLE)
- 老专家会用经验+数据来判断(贝叶斯)
再比如
"选男朋友"
最大似然估计(MLE) :
- 相亲选手小美:纯看条件挑对象
- 数据收集:身高180✓ 年薪50W✓ 有车有房✓
- 立刻下结论:"这就是我命中注定的真命天子!"
- 结果:可能翻车,因为没考虑其他重要因素
贝叶斯推断:
- 相亲选手小芳:结合经验看对象
- 先验知识:"帅哥通常都有大量追求者"
- 新数据:"这人条件是不错,但总给我发朋友圈广告..."
- 谨慎结论:"虽然各项指标都很棒,但我觉得还是再观察观察,可能是传销..."
总结:
- MLE就像初恋:冲动、只看表面✨
- 贝叶斯就像大龄剩女:谨慎、看得深远🧐
"选女朋友"
最大似然估计选手小明:
- 数据说明一切:身高165✓ 体重45kg✓ 长发飘飘✓
- "这就是我的女神!立刻表白!"
- 结果发现:原来是个网红滤镜...🤡
贝叶斯推断选手老王:
- 先验经验:"颜值太高的通常都很麻烦"
- 观察数据:"确实很漂亮,但每天都在蹦迪..."
- 贝叶斯结论:"虽然是女神级别,但性格可能不合适,再看看吧"
- 后来发现:果然是个酒吧托!😱
总结:
- MLE = 初哥:看到美女就晕头转向
- 贝叶斯 = 老司机:经验教会我要多观察
- 贝叶斯还会算概率:"这妹子是真心的概率只有30%..." 🤔
确实,贝叶斯方法就像是"老司机",不会被表面数据骗到,总是结合经验来判断。而MLE就像是"菜鸟",看到漂亮数据就上头,容易翻车。
这就是为什么在机器学习中,处理复杂问题时更喜欢用贝叶斯方法 - 毕竟谁也不想训练出一个"容易被骗"的模型是吧?😄
数据增强就像给模型"补课"- 通过对原始数据做各种变换来扩充训练集。以人脸识别为例:
- 基础变换:
- 翻转:让模型认识"左照片"和"右照片"也是同一个人
- 旋转:歪着头拍的照片也要认得
- 缩放:远近拍摄都不怕
- 高级变换:
- 改变亮度/对比度:适应不同光线条件
- 加噪声:模拟真实场景的干扰
- 遮挡部分:戴口罩、墨镜也能认出来
就像教小孩认人:从各个角度、不同表情、穿不同衣服都给看看,这样见到新照片才不会懵。这种方法显著提高了模型泛化能力,减少了过拟合。
让我用"约会软件刷照片"来解释一下混淆矩阵 😂
真实情况 vs 预测结果:
TP (True Positive):
- 真帅哥被右滑 ✓
- "确实是高富帅,没看走眼!"
FP (False Positive):
- 照片P太狠被右滑 ✗
- "约见后发现上当了..."
TN (True Negative):
- 真渣男被左滑 ✓
- "一眼就看出来是骗子!"
FN (False Negative):
- 真诚好男人被左滑 ✗
- "完了,错过一个真心人..."
这就解释了为什么刷照片要谨慎:
- 不是所有高颜值都是真实的(小心FP)
- 也别错过了外表普通但内在优秀的(注意FN) 😏
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) 😉