图像数据
作为图像数据,相较于结构化数据(表格数据)他的特点在于他每个样本的的形状并不是(特征数,),而是(宽,高,通道数)
灰度图像
结构化数据(如表格)的形状通常是 (样本数, 特征数),例如 (1000, 5) 表示 1000 个样本,每个样本有 5 个特征。图像数据的形状更复杂,需要保留空间信息(高度、宽度、通道),因此不能直接用一维向量表示。其中颜色信息往往是最开始输入数据的通道的含义,因为每个颜色可以用红绿蓝三原色表示,因此一般输入数据的通道数是 3。
MNIST 数据集是手写数字的 灰度图像,每个像素点的取值范围为 0-255(黑白程度),因此 通道数为 1。图像尺寸统一为 28×28 像素。
彩色图像
在 PyTorch 中,图像数据的形状通常遵循 (通道数, 高度, 宽度) 的格式(即 Channel First 格式),这与常见的 (高度, 宽度, 通道数)(Channel Last,如 NumPy 数组)不同。---注意顺序关系,
注意点:
1. 如果用matplotlib库来画图,需要转换下顺序
2. 模型输入通常需要 批次维度(Batch Size),形状变为 (批次大小, 通道数, 高度, 宽度)。例如,批量输入 10 张 MNIST 图像时,形状为 (10, 1, 28, 28)。
# 打印一张彩色图像,用cifar-10数据集
import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
# 设置随机种子确保结果可复现
torch.manual_seed(42)
# 定义数据预处理步骤
transform = transforms.Compose([
transforms.ToTensor(), # 转换为张量并归一化到[0,1]
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) # 标准化处理
])
# 加载CIFAR-10训练集
trainset = torchvision.datasets.CIFAR10(
root='./data',
train=True,
download=True,
transform=transform
)
# 创建数据加载器
trainloader = torch.utils.data.DataLoader(
trainset,
batch_size=4,
shuffle=True
)
# CIFAR-10的10个类别
classes = ('plane', 'car', 'bird', 'cat', 'deer',
'dog', 'frog', 'horse', 'ship', 'truck')
# 随机选择一张图片
sample_idx = torch.randint(0, len(trainset), size=(1,)).item()
image, label = trainset[sample_idx]
# 打印图片形状
print(f"图像形状: {image.shape}") # 输出: torch.Size([3, 32, 32])
print(f"图像类别: {classes[label]}")
# 定义图像显示函数(适用于CIFAR-10彩色图像)
def imshow(img):
img = img / 2 + 0.5 # 反标准化处理,将图像范围从[-1,1]转回[0,1]
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0))) # 调整维度顺序:(通道,高,宽) → (高,宽,通道)
plt.axis('off') # 关闭坐标轴显示
plt.show()
# 显示图像
imshow(image)
图像模型的定义
黑白图像
# 定义两层MLP神经网络
class MLP(nn.Module):
def __init__(self):
super(MLP, self).__init__()
self.flatten = nn.Flatten() # 将28x28的图像展平为784维向量
self.layer1 = nn.Linear(784, 128) # 第一层:784个输入,128个神经元
self.relu = nn.ReLU() # 激活函数
self.layer2 = nn.Linear(128, 10) # 第二层:128个输入,10个输出(对应10个数字类别)
def forward(self, x):
x = self.flatten(x) # 展平图像
x = self.layer1(x) # 第一层线性变换
x = self.relu(x) # 应用ReLU激活函数
x = self.layer2(x) # 第二层线性变换,输出logits
return x
# 初始化模型
model = MLP()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device) # 将模型移至GPU(如果可用)
from torchsummary import summary # 导入torchsummary库
print("\n模型结构信息:")
summary(model, input_size=(1, 28, 28)) # 输入尺寸为MNIST图像尺寸
彩色图像
class MLP(nn.Module):
def __init__(self, input_size=3072, hidden_size=128, num_classes=10):
super(MLP, self).__init__()
# 展平层:将3×32×32的彩色图像转为一维向量
# 输入尺寸计算:3通道 × 32高 × 32宽 = 3072
self.flatten = nn.Flatten()
# 全连接层
self.fc1 = nn.Linear(input_size, hidden_size) # 第一层
self.relu = nn.ReLU()
self.fc2 = nn.Linear(hidden_size, num_classes) # 输出层
def forward(self, x):
x = self.flatten(x) # 展平:[batch, 3, 32, 32] → [batch, 3072]
x = self.fc1(x) # 线性变换:[batch, 3072] → [batch, 128]
x = self.relu(x) # 激活函数
x = self.fc2(x) # 输出层:[batch, 128] → [batch, 10]
return x
# 初始化模型
model = MLP()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device) # 将模型移至GPU(如果可用)
from torchsummary import summary # 导入torchsummary库
print("\n模型结构信息:")
summary(model, input_size=(3, 32, 32)) # CIFAR-10 彩色图像(3×32×32)
batch_size与模型定义的关系
模型定义:完全无关
`class MLP(nn.Module)` 中无需提及batch_size
torchsummary:只需要样本形状(不含batch维度)
`summary(model, input_size=(1, 28, 28))`
DataLoader:在此设置batch_size
`DataLoader(dataset, batch_size=64)`
训练循环:数据自动以batch形式输入模型
`for data, target in train_loader: ...`
@浙大疏锦行