标准化
在我们把数据导入模型进行训练的时候,我们首先要对数据进行标准化处理,为什么需要进行标准化呢?
简要地说,为了保证网络可以良好的收敛,在不清楚各个维度的相对重要程度之前,标准化使得输入的各个维度分布相近,从而允许我们在网络训练过程中,对各个维度“一视同仁”(即设置相同的学习率、正则项系数、权重初始化、以及激活函数)。反过来,当我们使用全局相同的学习率、权重初始化、以及激活函数等网络设置时,方差更大的维度将获得更多的重视。
常用的标准化分为三种:
- 规范化方法
- 正规化方法
- 归一化
正规化方法的标准化的公式如下:
x ̅ 为均值,s为标准差,标准化后我们数据的均值为0,方差为1
想要进行标准化,首先需要求出均值和标准差,对于猫狗数据集我们通过程序求出均值和标准差:
import numpy as np
import cv2
import os
from PIL import Image
# img_h, img_w = 32, 32
img_h, img_w = 32, 32 #经过处理后你的图片的尺寸大小
means, stdevs = [], []
img_list = []
imgs_path = r".\test" #数据集的路径采用绝对引用
imgs_path_list = os.listdir(imgs_path)
len_ = len(imgs_path_list)
i = 0
for item in imgs_path_list:
img = cv2.imread(os.path.join(imgs_path, item))
img = cv2.resize(img, (img_w, img_h))
img = img[:, :, :, np.newaxis]
img_list.append(img)
i += 1
print(i, '/', len_)
imgs = np.concatenate(img_list, axis=3)
imgs = imgs.astype(np.float32) / 255.
for i in range(3):
pixels = imgs[:, :, i, :].ravel() # 拉成一行
means.append(np.mean(pixels))
stdevs.append(np.std(pixels))
# BGR --> RGB , CV读取的需要转换,PIL读取的不用转换
means.reverse()
stdevs.reverse()
print("normMean = {}".format(means))
print("normStd = {}".format(stdevs))
输入:
normMean = [0.4757419, 0.45063725, 0.39034033]
normStd = [0.26056913, 0.25479528, 0.25940257]
因为是RGB图片,有三个颜色通道,所以三个值;得到了均值和标准差我们就可以用transforms的Normalize函数来进行标准化了:
transform = transforms.Compose([
transforms.Resize(32), # 缩放图片,保持长宽比不变,最短边为32像素
transforms.CenterCrop(32), # 从图片中间开始切割出32*32大小的图片
transforms.ToTensor(), # 将图片转换成Tensor,归一化至[0,1]
#标准化至[-1,1],规定均值和标准差
transforms.Normalize(mean=[0.475, 0.451, 0.390], std=[0.261, 0.255, 0.259])
])