数据集标准化所需的均值和标准差

求标准化所需的mean和std的三种方法

什么是标准化?

这里所说的标准化是针对pytorch中的 transforms.Normalize(mean=..., std=...)函数而言,即 z-score标准化
x ∗ = x − x ˉ σ x^* = \frac{x - \bar{x}}{\sigma} x=σxxˉ

下面给出方法代码,注意,由于我使用的数据集是灰度图片,所以计算一个通道就可以了 。如果使用RGB图片,只需额外在循环语句里加几行代码以计算另外两个通道的相关参数就行了。

方法一

求整个数据集每张图片的均值、标准差之和,再除以数据集里图片个数作为整个数据集的标准化所需的参数: 其基本思想如下图:
在这里插入图片描述
代码如下:

import os
import numpy as np
from PIL import Image


if __name__ == '__main__':
    filepath = r"C:/Users/xxx/images/"  # 数据集目录
    pathDir = os.listdir(filepath)  # 数据集目录下图片
    num = len(pathDir)  # 这里(512,512)是每幅图片的尺寸

    print("Computing mean...")
    data_mean = 0.
    for idx in range(len(pathDir)):
        filename = pathDir[idx]
        img = Image.open(os.path.join(filepath, filename)).convert('L')
        img = np.array(img) / 255.0
        data_mean += np.mean(img)  # 取三维矩阵中第一维的所有数据
		# 由于使用的是灰度图片,所以计算一个通道就可以了
    data_mean = data_mean / num

    print("Computing var...")
    data_std = 0.
    for idx in range(len(pathDir)):
        filename = pathDir[idx]
        img = Image.open(os.path.join(filepath, filename)).convert('L')
        img = np.array(img) / 255.0
        data_std += np.std(img)

    data_std = data_std / num
    print("mean:{}".format(data_mean))
    print("std:{}".format(data_std))

方法二

求整个数据集所有图片的均值和标准差: 基本思想就是将数据集中所有图片给拼接成一个大图片,求这个大图片的均值和标准差作为整个数据集的标准化所需的参数。代码如下:

import os
import numpy as np
from PIL import Image


if __name__ == '__main__':
    filepath = r"C:/Users/xxx/images/"  # 数据集目录
    pathDir = os.listdir(filepath)  # 数据集目录下图片
    num = len(pathDir) * 512 * 512  # 数据集目录下图片尺寸

    print("Computing mean...")
    data_mean = 0.
    for idx in range(len(pathDir)):
        filename = pathDir[idx]
        img = Image.open(os.path.join(filepath, filename)).convert('L')
        img = np.array(img)
        img = img.astype(np.float64) / 255.0
        data_mean += np.sum(img)
		# 由于使用的是灰度图片,所以计算一个通道就可以了
    data_mean = data_mean / num

    print("Computing std...")
    data_std = 0.

    for idx in range(len(pathDir)):
        filename = pathDir[idx]
        img = Image.open(os.path.join(filepath, filename)).convert('L')
        img = np.array(img)
        img = img.astype(np.float64) / 255.0
        data_std += np.sum((img - data_mean) ** 2)

    data_std = np.sqrt(data_std / num)

    print("mean:{}".format(data_mean))
    print("std:{}".format(data_std))

方法三

计算单张图片的均值标准差,每张图片各自标准化。就是说每张图片标准化时使用的mean和std都是根据当前读入的图片,实时计算出来的mean和std,从而对该张图片进行标准化。 代码如下:

def data_transform(image_object, label_object):
    tensor_transform = transforms.ToTensor()
    image_object = tensor_transform(image_object)
    # 由于使用的是灰度图片,所以计算一个通道就可以了
    image_mean = image_object[0, :, :].mean()
    image_std = image_object[0, :, :].std()
    normalize_transform = transforms.Normalize(mean=image_mean, std=image_std)
    image_object = normalize_transform(image_object)

    if label_object is not None:
        label_object = tensor_transform(label_object)
        return image_object, label_object

    return image_object

说明

  1. 方法三给的是一个函数,只需要在构建数据集的时候调用这个函数就行了。方法一、二的、则可以视为单独对数据集的一个分析脚本,计算出来的mean和std直接在数据集构建的时候放入 transforms.Normalize(mean=..., std=...)参数即可。
  2. 根据概率论与数理统计的知识,方法一和方法二计算出来的均值是相同的,但是标准差并不相同 ,严格来说,方法二计算出来的标准差才是整个数据集真正的标准差,方法一计算出来的标准差只是在数据集的图片分布满足一定条件时,对真正的标准差的一个近似估计。(表达可能有误,我对概率论那边也不是很熟,如果说错了,请提醒我纠正,谢谢)
  3. 方法三提供的方法是我自己想出来的,因为在使用方法一、二计算出来的均值标准差进行标准化的时候,有的图片中的很多像素值都会超过[0, 1]这个范围,个人感觉可能不太好,于是写出来了这个函数,对每张图片各自进行标准化。而在实际测试时,发现经此函数归一化后的也是可以顺利训练出具有良好性能的模型的。放在这里并不代表其完全符合数据集标准化的思想,只是作为一种可行的方法。
### 数据标准化的重要性 为了提高机器学习模型的表现,数据标准化是一个重要的预处理步骤。通过缩放不同特征到相同的尺度范围,能够加速梯度下降收敛速度并提升某些基于距离计算的算法性能[^1]。 ### 正确实施数据标准化的方法 对于训练集测试集的数据标准化操作应当遵循如下原则: - **仅使用来自训练集的信息来拟合标准化器**:这意味着应该先利用训练集中样本的学习参数(如均值标准差),再应用这些参数去变换训练集本身以及后续待预测的新数据——即验证/测试集合。 - **保持一致性**:确保应用于训练集上的相同转换逻辑也严格作用于测试集上,从而维持两者之间的一致性可比性。 下面给出Python环境下采用`scikit-learn`库实现这一过程的具体代码实例: ```python from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler import numpy as np # 假设X为输入特征矩阵,y为目标变量向量 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # 创建StandardScaler对象 scaler = StandardScaler() # 使用训练集fit_transform方法既求得所需的统计量又完成对训练集本身的标准化 X_train_scaled = scaler.fit_transform(X_train) # 对测试集只做transform而不重新fit,保证使用的均值方差来自于训练集 X_test_scaled = scaler.transform(X_test) ``` 上述做法有效地防止了任何形式的信息泄露问题发生,即避免让模型提前接触到它不应该知道的关于未来或未见数据的知识[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值