📚博客主页:knighthood2001
✨公众号:认知up吧 (目前正在带领大家一起提升认知,感兴趣可以来围观一下)
🎃知识星球:【认知up吧|成长|副业】介绍
❤️如遇文章付费,可先看看我公众号中是否发布免费文章❤️
🙏笔者水平有限,欢迎各位大佬指点,相互学习进步!
为什么需要归一化
将数据转换成标准正态分布(也称为标准化或归一化)的主要目的是改善机器学习模型的训练效果。以下是详细原因和优势:
原因:
-
均一性:
- 不同特征的数值范围可能相差很大,如果不进行标准化,特征值较大的特征会对模型的训练产生更大的影响,而特征值较小的特征可能被忽略。
- 标准化后,所有特征的均值为0,标准差为1,使得每个特征在同一数量级上,有助于模型公平地对待每一个特征。
-
加速梯度下降:
- 在神经网络训练中,梯度下降算法用于优化模型参数。
- 如果输入数据没有标准化,梯度下降过程可能会变得非常慢,因为不同特征的值差异大,可能导致梯度的更新步长不一致,模型需要更多的迭代次数才能收敛。
-
提高数值稳定性:
- 在计算过程中,特别是使用反向传播算法时,标准化数据可以减少数值计算中的溢出或下溢问题。
- 数值稳定性提高后,模型的训练过程更稳定,收敛速度更快。
-
激活函数的有效区间:
- 常见的激活函数(如Sigmoid, Tanh)在输入接近均值0的区域梯度最大,模型训练效果最好。
- 如果数据没有经过标准化,激活函数可能会饱和(即输出接近其极值),导致梯度接近0,无法有效更新权重。
优势:
-
提升模型性能:
- 经过标准化处理后的数据,使得模型训练更快、效果更好。
- 模型能够更好地捕捉数据中的模式,提高预测性能。
-
改进数值问题:
- 标准化后的数据,有助于避免在计算过程中出现数值问题,提高算法的鲁棒性。
实现方式:
标准化通常通过以下方式实现:
-
均值-方差标准化(Z-score normalization):
- 计算每个特征的均值
μ
和标准差σ
。 - 对每个特征进行标准化:[ x’ = \frac{x - \mu}{\sigma} ]
- 使得每个特征的均值为0,标准差为1。
- 计算每个特征的均值
-
最小-最大标准化(Min-Max normalization):
- 将数据缩放到特定的范围(通常是0到1)。
- 对每个特征进行缩放:[ x’ = \frac{x - x_{min}}{x_{max} - x_{min}} ]
- 使得每个特征的值都在0到1之间。
归一化处理的步骤即是将图像像素值标准化到0到1之间,为后续的均值和方差计算做好准备。这一步的核心思想就是希望通过标准化,使得数据更适合于神经网络的训练,提高模型的训练效果和性能。
python代码
原始数据如下图:
from PIL import Image
import os
import numpy as np# 文件夹路径,包含所有图片文件,这里不区分训练集验证集
folder_path = 'data_cat_dog'# 初始化累积变量
total_pixels = 0
sum_normalized_pixel_values = np.zeros(3) # 如果是RGB图像,需要三个通道的均值和方差# 遍历文件夹中的图片文件
for root, dirs, files in os.walk(folder_path):for filename in files:if filename.endswith(('.jpg', '.jpeg', '.png', '.bmp')): # 可根据实际情况添加其他格式image_path = os.path.join(root, filename)image = Image.open(image_path)image_array = np.array(image)# 归一化像素值到0-1之间normalized_image_array = image_array / 255.0# print(image_path)# print(normalized_image_array.shape)# 累积归一化后的像素值和像素数量total_pixels += normalized_image_array.size # 计算像素数量,宽*高*通道数sum_normalized_pixel_values += np.sum(normalized_image_array, axis=(0, 1))# axis=0 通常表示沿着第一个维度(通常是行)进行操作,而 axis=1 表示沿着第二个维度(通常是列)进行操作。# 计算均值
mean = sum_normalized_pixel_values / total_pixelssum_squared_diff = np.zeros(3)
for root, dirs, files in os.walk(folder_path):for filename in files:if filename.endswith(('.jpg', '.jpeg', '.png', '.bmp')):image_path = os.path.join(root, filename)image = Image.open(image_path)image_array = np.array(image)# 归一化像素值到0-1之间normalized_image_array = image_array / 255.0# print(normalized_image_array.shape)# print(mean.shape)# print(image_path)try:diff = (normalized_image_array - mean) ** 2sum_squared_diff += np.sum(diff, axis=(0, 1))except:print(f"捕获到自定义异常")# diff = (normalized_image_array - mean) ** 2# sum_squared_diff += np.sum(diff, axis=(0, 1))
# 计算方差
variance = sum_squared_diff / total_pixelsprint("Mean:", mean)
print("Variance:", variance)
其中,虽然是三通道图片,但是有些图片,没有三通道,因此可能就会出错,需要把这种图片排除掉。
计算结果
运算结果如下
Mean: [0.16207108 0.15101928 0.13847153]
Variance: [0.05800501 0.05212834 0.04776142]
后续,就可以将这个数据,放到图像数据预处理中,也就是先对图像归一化处理,好处见上面。
这也看出来,不同的数据集,其归一化结果不同。