归一化
归一化(Normalization)是为了消除不同数据之间的量纲,方便数据比较和共同处理,比如在神经网络中,归一化可以加快训练网络的收敛性;
1. 把数据变为(0,1)之间的小数,主要是为了方便数据处理,因为将数据映射到0~1范围之内,可以使处理过程更加便捷、快速。例如 nn.normalize()进行归一化。
2. 把有量纲表达式变换为无量纲表达式,成为纯量。经过归一化处理的数据,处于同一数量级,可以消除指标之间量纲和量纲单位的影响,提高不同数据指标之间的可比性。
3. 主要算法:线性转换,即min-max归一化(常用方法)
y=(x-min)/(max-min)
def minmaxscaler(data):
min = np.amin(data)
max = np.amax(data)
return (data - min)/(max-min)
这种方法有个缺陷就是当有新数据加入时,可能导致max和min的变化,需要重新定义。对于outlier非常敏感,因为outlier影响了max或min值,所以这种方法只适用于数据在一个范围内分布的情况。无法消除量纲对方差、协方差的影响。
标准化
标准化(Standarlization)是为了方便数据的下一步处理,而进行的数据缩放等变换,并不是为了方便与其他数据一同处理或比较,比如数据经过0-1均值标准化后,更利于使用标准正态分布的性质进行处理;
在分类、聚类算法中,需要使用距离来度量相似性的时候、或者使用PCA技术进行降维的时候,新的数据由于对方差进行了归一化,这时候每个维度的量纲其实已经等价了,每个维度都服从均值为0、方差1的正态分布,在计算距离的时候,每个维度都是去量纲化的,避免了不同量纲的选取对距离计算产生的巨大影响。
def feature_normalize(data):
mu = np.mean(data,axis=0)
std = np.std(data,axis=0)
return (data - mu)/std
在pytorch使用时
import torch
import torchvision
import torchvision.transforms as transforms
transform = transforms.Compose(
[transforms.ToTensor(), # 函数接受PIL Image或numpy.ndarray,将其先由HWC转置为CHW格式,再转为float后每个像素除以255.
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
shuffle=True, num_workers=2)
# get some random training images
dataiter = iter(trainloader)
images, labels = dataiter.next()
上例均值和标准差都是0.5
注意:torchvision.transforms.ToTensor() 函数接受PIL Image或numpy.ndarray,将其先由HWC转置为CHW格式,再转为float后每个像素除以255.
# 反标准化
def unnormalized_show(img):
img = img * std + mu # unnormalize
npimg = img.numpy()
plt.figure()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
正则化
正则化(Regularization)是利用先验知识,在处理过程中引入正则化因子(regulator),增加引导约束的作用,比如在逻辑回归中使用正则化,可以有效降低过拟合的现象。
L0 & L1
L0范数:权值向量w ww中非0的元素的个数。
L1范数(稀疏规则算子,Lasso Regularization):权值向量w ww中各个元素绝对值之和,通常表示为||w||1
如果使用L0范数来规则化一个参数矩阵W,即意味着希望W的大部分元素都是0。L1正则化可以产生稀疏权值矩阵,即产生一个稀疏模型,可以用于特征选择。
L0范数很难优化求解(NP问题);
L1范数是L0范数的最优凸近似,而且L1比L0更容易优化求解。
1. 权重衰减(weight decay)
L2正则化的目的就是为了让权重衰减到更小的值,在一定程度上减少模型过拟合的问题,所以权重衰减也叫L2正则化。
L2正则化与权重衰减系数L2正则化就是在代价函数后面再加上一个正则化项:
其中C0代表原始的代价函数,后面那一项就是L2正则化项,它是这样来的:所有参数w的平方的和,除以训练集的样本大小n。λ就是正则项系数,权衡正则项与C0项的比重。系数λ就是权重衰减系数。
1.2 为什么可以对权重进行衰减
我们对加入L2正则化后的代价函数进行推导,先求导:
可以发现L2正则化项对b的更新没有影响,但是对于w的更新有影响:
在不使用L2正则化时,求导结果中w前系数为1,现在w前面系数为1-ηλ/n,因为η、λ、n都是正的,所以1-ηλ/n小于1,它的效果是减小w,这也就是权重衰减(weight decay)的由来。当然考虑到后面的导数项,w最终的值可能增大也可能减小。
另外,需要提一下,对于基于mini-batch的随机梯度下降,w和b更新的公式跟上面给出的有点不同:
对比上面w的更新公式,可以发现后面那一项变了,变成所有导数加和,乘以η再除以m,m是一个mini-batch中样本的个数。
1.3 权重衰减(L2正则化)的作用:
权重衰减(L2正则化)可以避免模型过拟合问题。思考:L2正则化项有让w变小的效果,但是为什么w变小可以防止过拟合呢?原理:(1)从模型的复杂度上解释:更小的权值w,从某种意义上说,表示网络的复杂度更低,对数据的拟合更好(这个法则也叫做奥卡姆剃刀),而在实际应用中,也验证了这一点,L2正则化的效果往往好于未经正则化的效果。(2)从数学方面的解释:过拟合的时候,拟合函数的系数往往非常大,为什么?如下图所示,过拟合,就是拟合函数需要顾忌每一个点,最终形成的拟合函数波动很大。在某些很小的区间里,函数值的变化很剧烈。这就意味着函数在某些小区间里的导数值(绝对值)非常大,由于自变量值可大可小,所以只有系数足够大,才能保证导数值很大。而正则化是通过约束参数的范数使其不要太大,所以可以在一定程度上减少过拟合情况。
optimizer = optim.Adam(model.parameters(),lr=learning_rate,weight_decay=0.01)