在写网络时,常常要自己导入数据和预处理,其中很关键的一点就是要将Numpy数据转化到torch.tensor,这里就牵扯到一个问题,在Np.array中,一张RGB图像的储存是按照[H,W,C]进行存储的,而在Torch中,图像是按照[C,H,W]进行存储,而且在进行torchvision.transforms.ToTensor中会自动将文件转存为[C,H,W], 我的疑问是:1.Numpy中数据是如何储存又该如何去读? 2. ToTensor操作后的数据和在Numpy中自行reshape为[C,H,W]是否一致?
对于问题1,如果是三维的Numpy
import numpy as np
x3 = np.random.randint(0,10,(3,2,4))
print('>>> --------------------------3-D-------------------------------- <<<')
print(x3)
[print('the {}st layer is\n {}\n'.format(i,x3[:,:,i])) for i in range(4)]
得到的结果为
x3
[[[5 6 1 7]
[9 9 7 3]]
[[6 6 8 6]
[5 1 7 0]]
[[8 5 7 0]
[5 8 9 4]]]
若以图像去看这个三维nparray,有
the 0st layer is
[[5 9]
[6 5]
[8 5]]
the 1st layer is
[[6 9]
[6 1]
[5 8]]
the 2st layer is
[[1 7]
[8 7]
[7 9]]
the 3st layer is
[[7 3]
[6 0]
[0 4]]
可以发现对于3D-array, x3中遍历每一个块的第j列对应了图像第j层的逐行遍历。也即我们可以以这种角度去理解三维的np.array,经过ToTensor后,矩阵变为
tensor([[[5, 9],
[6, 5],
[8, 5]],
[[6, 9],
[6, 1],
[5, 8]],
[[1, 7],
[8, 7],
[7, 9]],
[[7, 3],
[6, 0],
[0, 4]]], dtype=torch.int32)
也即在将原矩阵的第2维提到第0维时,并不改变图像。那么如果我们在np.array时就将3-D的矩阵转化为2-D,再转为Tensor后重新reshape为3-D,结果是否会有改变呢?
a = []
[a.append(x3[:,:,i].flatten().reshape(1,x3[:,:,0].size)) for i in range(3)]
aa = np.concatenate(a,axis=0)
tensor_aa = trans(aa).reshape(3,4,2)
# 检验两者是否相同
tensor_x3.equal(tensor_aa)
#输出:True,所以有时候为了避免三维图像转化时候忘记调channel位置,可以选择将其转化为二维。
一个重点在于,导入数据时我们面对的不仅仅是三维,第四维数据Batch_size是存在的,此时就算拉直了原始数据降低了一维,输出的矩阵仍是三维的,那么为什么仅仅将三维变成二维的呢?如果我们选择直接将三维变成一维的,这样数据矩阵的大小就是data_sizeXimage_pixel_size
tensor_aaa = trans(aa.reshape(1,x3.size))
tensor_x3.equal(tensor_aaa.reshape(3,4,2))
#输出:True,这也证明我们可以将数据先拉直为1维转化为Tensor后再转化为3维。
现在回答问题2,既然都是reshape,那么能否我提前将np.array变为[C,H,W]大小,这样得到的和[H,W,C]经过ToTensor后一致吗?结果是不一致的,大家自行进行以下这个操作,并与torch张量对比就可以看到。至于原因尚不清楚,欢迎对此有理解的朋友赐教。
此外,值得一提的是,如果是以下的操作,结果表明此时进行reshape其实只是一个数据转化而已:
import torch
import numpy as np
a = torch.rand(10,3,7,8)
b = a.numpy()
im1 = a[0]
cvt_hwc = a.permute([0,2,3,1])
print('The size of cvt_hwc is:\t{}'.format(cvt_hwc.shape))
im2 = cvt_hwc[0]
im2_0 = im2[:,:,0]
im2[:,:,0].eq(im1[0])
结果为:
tensor([[True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True]])