栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

关于transforms.Normalize的真正理解

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

关于transforms.Normalize的真正理解

我们都知道 当图像数据输入时 需要对图像数据进行预处理 常用的预处理方法 本文不再赘述 本文重在讲讲transform.ToTensor和transforms.Normalize。

问题
transform.ToTensor(),
transform.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))

究竟是什么意思 (0.5,0.5,0.5),(0.5,0.5,0.5)又是怎么来的呢

transform.ToTensor() 是将输入的数据shape W H C —— C W H将所有数除以255 将数据归一化到【0 1】 代码示例
import torch
import numpy as np
from torchvision import transforms
import cv2
#自定义图片数组 数据类型一定要转为‘uint8’,不然transforms.ToTensor()不会归一化
data np.array([
 [[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
 [[2,2,2],[2,2,2],[2,2,2],[2,2,2],[2,2,2]],
 [[3,3,3],[3,3,3],[3,3,3],[3,3,3],[3,3,3]],
 [[4,4,4],[4,4,4],[4,4,4],[4,4,4],[4,4,4]],
 [[5,5,5],[5,5,5],[5,5,5],[5,5,5],[5,5,5]]
 ],dtype uint8 )
print(data)
print(data.shape) # 5 5 3 
data transforms.ToTensor()(data)
print(data)
print(data.shape) # 3 5 5 
tensor([[[0.0039, 0.0039, 0.0039, 0.0039, 0.0039],
 [0.0078, 0.0078, 0.0078, 0.0078, 0.0078],
 [0.0118, 0.0118, 0.0118, 0.0118, 0.0118],
 [0.0157, 0.0157, 0.0157, 0.0157, 0.0157],
 [0.0196, 0.0196, 0.0196, 0.0196, 0.0196]],
 [[0.0039, 0.0039, 0.0039, 0.0039, 0.0039],
 [0.0078, 0.0078, 0.0078, 0.0078, 0.0078],
 [0.0118, 0.0118, 0.0118, 0.0118, 0.0118],
 [0.0157, 0.0157, 0.0157, 0.0157, 0.0157],
 [0.0196, 0.0196, 0.0196, 0.0196, 0.0196]],
 [[0.0039, 0.0039, 0.0039, 0.0039, 0.0039],
 [0.0078, 0.0078, 0.0078, 0.0078, 0.0078],
 [0.0118, 0.0118, 0.0118, 0.0118, 0.0118],
 [0.0157, 0.0157, 0.0157, 0.0157, 0.0157],
 [0.0196, 0.0196, 0.0196, 0.0196, 0.0196]]])
transforms.Normalize()

看了许多文章 都是说 transform.Normalize()通过公式

x (x - mean) / std

即同一纬度的数据减去这一维度的平均值 再除以标准差 将归一化后的数据变换到【-1,1】之间。可真是这样吗

求解mean和std

我们需要求得一批数据的mean和std 代码如下

import torch
import numpy as np
from torchvision import transforms
# 这里以上述创建的单数据为例子
data np.array([
 [[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
 [[2,2,2],[2,2,2],[2,2,2],[2,2,2],[2,2,2]],
 [[3,3,3],[3,3,3],[3,3,3],[3,3,3],[3,3,3]],
 [[4,4,4],[4,4,4],[4,4,4],[4,4,4],[4,4,4]],
 [[5,5,5],[5,5,5],[5,5,5],[5,5,5],[5,5,5]]
 ],dtype uint8)
#将数据转为C,W,H 并归一化到[0 1]
data transforms.ToTensor()(data)
# 需要对数据进行扩维 增加batch维度
data torch.unsqueeze(data,0)
nb_samples 0.
#创建3维的空列表
channel_mean torch.zeros(3)
channel_std torch.zeros(3)
print(data.shape)
N, C, H, W data.shape[:4]
data data.view(N, C, -1) #将w,h维度的数据展平 为batch channel,data,然后对三个维度上的数分别求和和标准差
print(data.shape)
#展平后 w,h属于第二维度 对他们求平均 sum(0)为将同一纬度的数据累加
channel_mean data.mean(2).sum(0) 
#展平后 w,h属于第二维度 对他们求标准差 sum(0)为将同一纬度的数据累加
channel_std data.std(2).sum(0)
#获取所有batch的数据 这里为1
nb_samples N
#获取同一batch的均值和标准差
channel_mean / nb_samples
channel_std / nb_samples
print(channel_mean, channel_std)

以此便可求得均值和标准差。我们再带入公式

x (x - mean) / std
自己实现
data np.array([
 [[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
 [[2,2,2],[2,2,2],[2,2,2],[2,2,2],[2,2,2]],
 [[3,3,3],[3,3,3],[3,3,3],[3,3,3],[3,3,3]],
 [[4,4,4],[4,4,4],[4,4,4],[4,4,4],[4,4,4]],
 [[5,5,5],[5,5,5],[5,5,5],[5,5,5],[5,5,5]]
 ],dtype uint8 )
data transforms.ToTensor()(data)
for i in range(3):
 data[i,:,:] (data[i,:,:] - channel_mean[i]) / channel_std[i]
print(data)
tensor([[[-1.3856, -1.3856, -1.3856, -1.3856, -1.3856],
 [-0.6928, -0.6928, -0.6928, -0.6928, -0.6928],
 [ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
 [ 0.6928, 0.6928, 0.6928, 0.6928, 0.6928],
 [ 1.3856, 1.3856, 1.3856, 1.3856, 1.3856]],
 [[-1.3856, -1.3856, -1.3856, -1.3856, -1.3856],
 [-0.6928, -0.6928, -0.6928, -0.6928, -0.6928],
 [ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
 [ 0.6928, 0.6928, 0.6928, 0.6928, 0.6928],
 [ 1.3856, 1.3856, 1.3856, 1.3856, 1.3856]],
 [[-1.3856, -1.3856, -1.3856, -1.3856, -1.3856],
 [-0.6928, -0.6928, -0.6928, -0.6928, -0.6928],
 [ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
 [ 0.6928, 0.6928, 0.6928, 0.6928, 0.6928],
 [ 1.3856, 1.3856, 1.3856, 1.3856, 1.3856]]])
官方实现
data np.array([
 [[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
 [[2,2,2],[2,2,2],[2,2,2],[2,2,2],[2,2,2]],
 [[3,3,3],[3,3,3],[3,3,3],[3,3,3],[3,3,3]],
 [[4,4,4],[4,4,4],[4,4,4],[4,4,4],[4,4,4]],
 [[5,5,5],[5,5,5],[5,5,5],[5,5,5],[5,5,5]]
 ],dtype uint8 )
data transforms.ToTensor()(data)
data transforms.Normalize(channel_mean, channel_std)(data)
print(data)
tensor([[[-1.3856, -1.3856, -1.3856, -1.3856, -1.3856],
 [-0.6928, -0.6928, -0.6928, -0.6928, -0.6928],
 [ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
 [ 0.6928, 0.6928, 0.6928, 0.6928, 0.6928],
 [ 1.3856, 1.3856, 1.3856, 1.3856, 1.3856]],
 [[-1.3856, -1.3856, -1.3856, -1.3856, -1.3856],
 [-0.6928, -0.6928, -0.6928, -0.6928, -0.6928],
 [ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
 [ 0.6928, 0.6928, 0.6928, 0.6928, 0.6928],
 [ 1.3856, 1.3856, 1.3856, 1.3856, 1.3856]],
 [[-1.3856, -1.3856, -1.3856, -1.3856, -1.3856],
 [-0.6928, -0.6928, -0.6928, -0.6928, -0.6928],
 [ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
 [ 0.6928, 0.6928, 0.6928, 0.6928, 0.6928],
 [ 1.3856, 1.3856, 1.3856, 1.3856, 1.3856]]])

我们观察数据发现 通过求解的均值和标准差 求得的标准化的值 并非在【-1 1】 ( 借此谴责部分博客 )。

结论

经过这样处理后的数据符合标准正态分布 即均值为0 标准差为1。使模型更容易收敛。并非是归于【-1 1】

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/268130.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号