• 【Pytorch基础知识】数据的归一化和反归一化


    一张正常的图,或者说是人眼习惯的图是这样的:

    但是,为了神经网络更快收敛,我们在深度学习网络过程中通常需要将读取的图片转为tensor并归一化(此处的归一化transforms.Normalize()操作)输入到网络中进行系列操作。

    如果将转成的tensor再直接转为图片,就会变成下图,和我们眼睛看到是不一样感觉。

    这是因为,将图片转为tensor并归一化,tensor之中会有负值,和我们正常看到的是不一样的,如果不进行反归一化到 [0,1],就会变成下图,会觉得变扭。

    我们正常看到的图片tensor是[0,255]或者[0,1]

    解释transforms.Normalize()归一化后的图像,满足均值为0方差为1,被限定在一定的数值内,一般的数值为[-1,1]。

    这个过程中,我们需要进行如下操作,才能把图片转为tensor操作再转为图片(人眼习惯的)这里的tensor操作是transforms系列操作。

    归一化的目的:使得预处理的数据被限定在一定的范围内,从而消除奇异样本数据导致的不良影响。数据归一化处理后,可以加快梯度下降求最优解的速度,且有可能提高精度(如KNN)。

    反归一化的目的:为了还原原来人眼可以识别的图。


    归一化

    一幅图片的格式为【批数据的数量× 通道数× 高× 宽】

    在这里插入图片描述

    接下来开始计算mean 和 std: 

    1. nb_samples = 0
    2. #创建3维的空列表
    3. channel_mean = torch.zeros(3)
    4. channel_std = torch.zeros(3)
    5. print(image.shape)
    6. N, C, H, W = image.shape[:4]
    7. image = image.view(N, C, -1) #将w,h维度的数据展平,为batch,channel,data,然后对三个维度上的数分别求和和标准差
    8. print(image.shape)
    9. #展平后,w,h属于第二维度,对他们求平均,sum(0)为将同一纬度的数据累加
    10. channel_mean += image.mean(2).sum(0)
    11. #展平后,w,h属于第二维度,对他们求标准差,sum(0)为将同一纬度的数据累加
    12. channel_std += image.std(2).sum(0)
    13. #获取所有batch的数据,这里为1
    14. nb_samples += N
    15. #获取同一batch的均值和标准差
    16. channel_mean /= nb_samples
    17. channel_std /= nb_samples
    18. print(channel_mean, channel_std)

    然后利用transforms.Normalize 进行转换:

    1. normalizer = transforms.Normalize(mean=channel_mean, std=channel_std)
    2. # 归一化后得到可处理的值
    3. data = normalizer(image)

    反归一化

    根据归一化计算得到的mean和std,我们可以反推出反归一化的 mean 和 std,从而利用 transforms.Normalize 进行转换,计算方法如下:

    MEAN是指归一化时计算出来的均值,de_MEAN是计算出来反归一化的均值,后面需要用。


    综合上面的讲解及代码,整合最后的代码为下:

    1. # 定义一个image图像,torch.Size([1, 3, 319, 256])
    2. image = torch.rand([1,3,319,256])
    3. # 计算原图的 mean 和std
    4. nb_samples = 0
    5. #创建3维的空列表
    6. channel_mean = torch.zeros(3)
    7. channel_std = torch.zeros(3)
    8. print(image.shape)
    9. N, C, H, W = image.shape[:4]
    10. #将w,h维度的数据展平,为batch,channel,data,然后对三个维度上的数分别求和和标准差
    11. image = image.view(N, C, -1)
    12. print(image.shape)
    13. #展平后,w,h属于第二维度,对他们求平均,sum(0)为将同一纬度的数据累加
    14. channel_mean += image.mean(2).sum(0)
    15. #展平后,w,h属于第二维度,对他们求标准差,sum(0)为将同一纬度的数据累加
    16. channel_std += image.std(2).sum(0)
    17. #获取所有batch的数据,这里为1
    18. nb_samples += N
    19. #获取同一batch的均值和标准差
    20. channel_mean /= nb_samples
    21. channel_std /= nb_samples
    22. print(channel_mean, channel_std)
    23. # 这是归一化的 mean 和std
    24. channel_mean = torch.tensor([-0.5321, -0.8102, -0.5532])
    25. channel_std = torch.tensor([1.2582, 1.0009, 0.9211])
    26. # 这是反归一化的 mean 和std
    27. MEAN = [-mean/std for mean, std in zip(channel_mean, channel_std)]
    28. STD = [1/std for std in channel_std]
    29. # 归一化和反归一化生成器
    30. normalizer = transforms.Normalize(mean=channel_mean, std=channel_std)
    31. denormalizer = transforms.Normalize(mean=MEAN, std=STD)
    32. # 归一化得到可处理的值
    33. data = normalizer(image)
    34. # 反归一化得到原图
    35. image2 = denormalizer(data)

    image ≈ image2

    因为浮点数计算有误差,所以不会完全一样,但是问题不大~

     这样就可以得到tensor转换后的原图了。

    好了,大功告成,完结撒花!

    欢迎关注、点赞、收藏、评论、分享给好友,一起学习有趣的新知识!!! 

  • 相关阅读:
    Spring中@Value的三种使用方式
    Spring Boot+MyBatis+MySQL+Spring MVC之论坛首页开发
    数字化转型的关键在于节省时间
    接口测试的几种方法
    RabbitMQ-基本概念/环境配置
    数据结构——排序算法——插入排序
    重启人生计划-大梦方醒
    python构造函数使print输出不同颜色的文本
    分类算法(Classification Algorithm)需求记录
    HarmonyOS SDK,赋能开发者实现更具象、个性化开发诉求
  • 原文地址:https://blog.csdn.net/Thebest_jack/article/details/127767330