Regularization
Table of Contents
1. Regularization
1.1. 正则化的直观理解
以 L2 正则化为例, 假设加上损失函数之前:
- \(loss=C0\)
- \(\frac{\partial}{\partial{w_i}}loss= d0\)
加上 L2 正则化后:
- \(loss=C0+\frac{\alpha}{2}\sum{w^2}\)
- \(\frac{\partial}{\partial{w_i}}loss= d0+\alpha w_i\)
- 正则化后, 由损失函数的格式可知, w 会变得偏小
- w 变小, 会导致拟合曲线更加平滑. 因为在拟合曲线中, w 是 x 的系数, w 偏小即曲线的斜率会普遍变小, 从而更平滑
- 从 svm 的角度来看, L2 正则化项相当于一个约束, 要求 \(||w||\) 为某个值
- w 变小, 导致样本中的少量噪音并不会使损失函数有很大的变化, 从而减小训练时噪音的影响
1.2. 增加样本
正则化是为了解决 overfitting 问题. 模型中的变量与样本的比值越大, 越容易发生 overfitting. 所以在不减少模型中变量的数目的前提下, 增加样本可以减轻 overfitting
1.3. 简化网络
- 减少 ANN hidden layer 的个数
- 减少神经元的个数
1.4. L2 和 L1 正则化
1.4.1. 无正则化
import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_moons from matplotlib.colors import ListedColormap from torch.utils.data import Dataset, DataLoader import torch model = torch.nn.Sequential( torch.nn.Linear(2, 50), torch.nn.ReLU(), torch.nn.Linear(50, 1), torch.nn.Sigmoid()) class MoonDataset(Dataset): def __init__(self): X, Y = make_moons(n_samples=1000, noise=0.2) self.X = torch.from_numpy(X).float() self.Y = torch.from_numpy(Y).float().view(-1, 1) def __getitem__(self, index): return self.X[index], self.Y[index] def __len__(self): return len(self.X) dataset = MoonDataset() loader = DataLoader(dataset, batch_size=100) criterion = torch.nn.BCELoss() optimizer = torch.optim.Adam(model.parameters()) def add_regularization(loss): return loss def train(): for i in range(1000): for x, y in loader: loss = criterion(model(x), y) loss = add_regularization(loss) optimizer.zero_grad() loss.backward() optimizer.step() def visualize(): cm = ListedColormap(['#FF0000', '#0000FF']) plt.subplot(121) plt.scatter(x=dataset.X[:, 0], y=dataset.X[:, 1], c=dataset.Y[:, 0], cmap=cm) xx, yy = np.meshgrid(np.arange(-4, 4, 0.02), np.arange(-4, 4, 0.02)) X = np.c_[xx.ravel(), yy.ravel()] y_hat = model(torch.from_numpy(X).float()).detach().numpy() y_hat = (y_hat > 0.5)[:, 0] y_hat = y_hat.reshape(xx.shape) cm = ListedColormap(['#FF0000', '#0000FF']) plt.contour(xx, yy, y_hat, cmap=cm) x = next(model.parameters()).view(-1, 1) plt.subplot(122) plt.hist(x.detach().numpy(), bins=50) plt.show() return sum(x) train() visualize()
tensor([-7.9089])
1.4.2. L2 正则化
def add_regularization(loss): for name, param in model.named_parameters(): if 'bias' not in name: loss = loss + 0.5 * (0.001 * torch.sum(torch.pow(param, 2))) return loss train() visualize()
tensor([-5.5809])
可以看到 L2 正则化使得 w 的值变得较小
1.4.3. L1 正则化
def add_regularization(loss): for name, param in model.named_parameters(): if 'bias' not in name: loss = loss + (0.001 * torch.sum(torch.abs(param))) return loss train() visualize()
tensor([-7.9170])
L1 正则化:
- \(loss=C0+\frac{\alpha}{m}\sum{abs(w)}\)
\(\frac{\partial}{\partial{w_i}}loss= d0+\frac{\alpha}{m}*sgn(w_i)\)
L1 正则化与 L2 相比, 对 w 的修正是一个定值, 而不像 L2 那样是一个与 w 成比例的值. 这就导致当 w 较小时, L1 修正的范围会比 L2 大, 导致 w 容易减到 0 附近. 当 w 较大时, L1 修正的范围比 L2 小, 导致 w 较大.
反映到上面的直方图中, 许多值在零附近, 但值的范围与无正则化时类似.
所以 L1 会使得 w 比较稀疏, 适合做特征选择 (选择较大的 w 对应的特征)
1.4.4. 另一种解释
从 SVM 的角度来看, 正则化项可以看作是原优化问题的不等式约束, 例如对于 L2 来说, 即是 \(\sum{w_i^2} <= C\)
假设 w 为二维, 而 L2 是把 w 约束在一个圆内, 而 L1 是把 w 约束在一个菱形中.
可以看到 L1 优化时非常容易取得顶点位置, 导致部分权重为 0
1.5. Dropout
1.6. Batch Normalization
1.7. pytorch 中使用正则化
pytorch 通过 optim 的 weight_decay 实现 L2 正则化, 而不是 把 L2 加到 loss 上再进行 backward.
class SGD(Optimizer): def step(): # ... for p in group['params']: d_p = p.grad.data if weight_decay != 0: # add_ 会把 weight_decay*p.data 加到 p.grad.data 上 d_p.add_(weight_decay, p.data) # ...
1.7.1. weight_decay 和 l2 regularization 是等价的
\(C_0\) 为原始的 loss
加入 l2 regularization 后 \(C=C_0+\frac{\lambda}{2}w^2\)
梯度为: \(\frac{\partial C}{\partial w}=\frac{\partial C_0}{\partial w}+\lambda w\)
梯度更新后 \(w-\eta\frac{\partial C}{\partial w}= (1-\eta \lambda)w-\eta \frac{\partial C_0}{\partial w}\)
可以看到加入 l2 regularization 后相当于把先把 w 乘上一个系数 \(1-\eta \lambda\) 后再用原来的 loss 做梯度更新. 这里的系数 \(1-\eta\lambda\) 就相当于 pytorch 中的 wegith_decay 参数, 这里也能看出来 l2 regularization 对 w 的修正是与 w 的值成例的.
Backlinks
Auxiliary Classifier (Inception > Network > Auxiliary Classifier): inception 模型会输出两个 softmax, 分别为 F, G, 其中 F 称为 auxiliary classifier. F, G 训练时使用相同的标签, F 人为的增加了训练的难度, 相当于一种 regularization 的手段.
Inception (Inception > Network > Label Smoothing): 类似于知识蒸馏中的 soft label, 可以看做一种 regularization 手段.