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

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

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

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

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

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

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

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

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

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

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

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

归一化

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

在这里插入图片描述

接下来开始计算mean 和 std: 

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

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


normalizer = transforms.Normalize(mean=channel_mean, std=channel_std)

# 归一化后得到可处理的值
data = normalizer(image)

反归一化

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

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

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

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

# 定义一个image图像,torch.Size([1, 3, 319, 256])
image = torch.rand([1,3,319,256])

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


# 这是归一化的 mean 和std 
channel_mean = torch.tensor([-0.5321, -0.8102, -0.5532])
channel_std = torch.tensor([1.2582, 1.0009, 0.9211])
# 这是反归一化的 mean 和std 
MEAN = [-mean/std for mean, std in zip(channel_mean, channel_std)]
STD = [1/std for std in channel_std]

# 归一化和反归一化生成器
normalizer = transforms.Normalize(mean=channel_mean, std=channel_std)
denormalizer = transforms.Normalize(mean=MEAN, std=STD)

# 归一化得到可处理的值
data = normalizer(image)
# 反归一化得到原图
image2 = denormalizer(data)

image ≈ image2

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

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

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

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

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
社会演员多的头像社会演员多普通用户
上一篇 2023年2月25日 上午11:12
下一篇 2023年2月25日 上午11:13

相关推荐