Appearance
使用张量处理真实数据
本篇基于《Deep learning with PyTorch》 Chapter 4 不得不说纯英文的教材读起来还是太痛苦了
处理图像数据
图像加载与布局改变
图像被表示为一组按照规律网格排列的标量,该标量具有以像素为单位的高度和宽度。每个网格点(或像素)可能包含一个(灰度图像)或多个(RGB图像等)标量,这些标量通常代表不同的颜色或深度特征。 以RGB图像为例,其可以看作具有三个灰度颜色通道的三张图像的叠加,如图所示:
可以使用imageio模块来加载读取图片:
Python
import imageio.v3 as iio
# v3 的标准写法
img_arr = iio.imread('data/p1ch4/image-dog/bobby.jpg')
print(img_arr.shape)图片格式为:
Text
(720, 1280, 3)Tips:通常情况下TorchVision会是一个很好的选择 处理图像数据的PyTorch会要求数据张量为permute方法从而得到合适的布局。假设有
Python
img =torch.from_numpy(img_arr)
out = img.permute(2,0,1)此操作不会复制img的数据而是会使用其相同的储存,仅在张量层面调整其尺寸和步长信息,即如果img信息被更改,out也会随之变化。 以下为图像批量读取的代码示例:
Python
import os
import torch
import imageio
batch_size = 3 #批次
batch = torch.zeros(batch_size, 3, 256, 256, dtype=torch.uint8).cuda() # 在GPU创建全0占位张量
data_dir = '/data/p1ch4/image-cats'
filenames = [name for name in os.listdir(data_dir) if os.path.splitext(name)[-1] == '.png']
for i, filename in enumerate(filenames):
img_arr = imageio.imread(os.path.join(data_dir, filename))
# os.path.join 将图片路径与名称拼成完整图片路径
# imageio.imread 将图片以Numpy数组读取进内存
img_t = torch.from_numpy(img_arr) # 数组转化为张量
img_t = img_t.permute(2, 0, 1) # 调换维度顺序
img_t = img_t[:3] # 保留前3个通道确保格式一致
batch[i] = img_t # 将图片装入batch中标准化数据
神经网络通常以浮点型张量作为输入,且数值范围为 0 到 1 或 -1 到 1 之间神经网络训练表现较好,因此需要对数据进行标准化。一种方法是直接将像素值除以255:
Python
batch = batch.float()
batch /= 255.0另一种方法是计算输入数据的均值和标准差并对其进行缩放使得每个输出通道的均值为0,标准差为1:
Python
n_channels = batch.shape[1] # 取出Chaneel通道数
for c in range(n_channels):
mean = torch.mean(batch[:,c]) # 计算均值μ
std = torch.std(batch[:,c]) # 计算标准差σ
batch[:,c] = (batch[:,c]-mean)/std # 进行标准化对应到公式即为:
NOTE:这里只是对单批次图像进行归一化处理而不是对整个数据集进行处理
对于3D数据、表格和时间序列等的处理目前暂时不需要使用暂且搁置
为什么 PyTorch 要求 C×H×W 而不是 H×W×C? 因为卷积操作是在每个通道上独立进行的,C 在前可以让 GPU 更高效地按通道并行计算。而 imageio / PIL 读出来是 H×W×C(更符合人类直觉),所以每次加载图片都要 permute。 ↩︎