前言
提醒:
文章内容为方便作者自己后日复习与查阅而进行的书写与发布,其中引用内容都会使用链接表明出处(如有侵权问题,请及时联系)。
其中内容多为一次书写,缺少检查与订正,如有问题或其他拓展及意见建议,欢迎评论区讨论交流。
文章目录
- 前言
- CNN介绍
- 数据集介绍
- FashionMNIST 数据集概述
- 主要特点:
- 类别标签:
- 目标:
- 为什么使用 FashionMNIST:
- 图像示例:
- 数据加载与预处理:
- 下载和加载 FashionMNIST(PyTorch 代码示例):
- 数据集使用场景:
- 数据集可视化
- 总结:
- 项目实例
- 代码
CNN介绍
可见于:
MNIST数据集_CNN
数据集介绍
FashionMNIST 数据集概述
FashionMNIST 是一个包含 10 个类别的图像数据集,用于训练和测试机器学习模型,特别是在图像分类任务中的应用。它是由 Zalando 提供的,目的是为了给机器学习社区提供一个标准化、简洁但具有挑战性的视觉分类数据集。FashionMNIST 是 MNIST 数据集的一个变种,后者包含手写数字图像。
主要特点:
- 图像大小:每张图像的分辨率为 28x28 像素,每个像素为灰度值(单通道,值在 0 到 255 之间)。
- 图像类型:这些图像展示了 10 种不同类型的时尚商品,例如鞋子、T 恤、外套等。
- 数据集结构:
- 训练集:60,000 张图像
- 测试集:10,000 张图像
- 类别:数据集包含 10 个类别,分别对应不同的服装商品(每个类别有对应的标签)。
类别标签:
- 0: T 恤/上衣
- 1: 裤子
- 2: 套头衫
- 3: 连衣裙
- 4: 外套
- 5: 凉鞋
- 6: 衬衫
- 7: 运动鞋
- 8: 包
- 9: 靴子
目标:
FashionMNIST 的目标是对每张 28x28 的灰度图像进行分类,判定该图像属于哪个类别(例如是 “T 恤”、“裤子” 还是 “运动鞋” 等)。因此,它是一个 多类分类 问题,通常被用来评估各种机器学习模型,尤其是在图像分类任务中的表现。
为什么使用 FashionMNIST:
FashionMNIST 与原始的 MNIST 数据集相似,但相比 MNIST(手写数字),FashionMNIST 的图像内容更加复杂且多样。这使得它在很多机器学习和深度学习领域成为了一个较为简单但富有挑战性的测试集。它被广泛应用于:
- 深度学习模型的评估:特别是用于测试卷积神经网络(CNN)等模型的性能。
- 学习和研究:它提供了一个简单且标准化的图像分类数据集,适用于机器学习入门或新模型的验证。
图像示例:
每张图像都是 28x28 像素的灰度图,显示的是一件衣物的图片。图像尺寸较小,适合在初学者的机器学习项目中进行训练,因为它不需要大量的计算资源。
数据加载与预处理:
FashionMNIST 数据集一般会在加载时进行一些标准的预处理步骤,如:
- 归一化:将像素值从
[0, 255]
范围映射到[0, 1]
范围,或者进行标准化,常常帮助提升模型的收敛速度。 - 转换:通常使用
transforms.ToTensor()
将图像转换为 PyTorch 中的 Tensor 格式。
下载和加载 FashionMNIST(PyTorch 代码示例):
import torchvision
from torchvision import transforms
# 加载训练集数据
train_data = torchvision.datasets.FashionMNIST(
root='data', # 存储路径
train=True, # 训练集
download=True, # 下载数据集
transform=transforms.ToTensor(), # 转换为 Tensor 格式
)
# 加载测试集数据
test_data = torchvision.datasets.FashionMNIST(
root='data',
train=False, # 测试集
download=True,
transform=transforms.ToTensor(),
)
这段代码使用 torchvision.datasets.FashionMNIST
来下载并加载训练和测试数据集,图像会被转换为 PyTorch 的 Tensor 格式。
数据集使用场景:
- 入门项目:对于初学者,FashionMNIST 是一个非常适合入门的图像分类数据集,因为它相对简单,且具有一定的挑战性。
- 模型对比与验证:在机器学习和深度学习领域,FashionMNIST 常常作为测试模型性能的标准数据集之一,用来对比不同算法(如支持向量机、KNN、神经网络等)的表现。
- 神经网络训练:尤其是卷积神经网络(CNN)在图像分类任务中的应用,FashionMNIST 为其提供了一个理想的训练平台。
数据集可视化
import torch
from torchvision import datasets, transforms
import matplotlib.pyplot as plt
import numpy as np
# 下载 FashionMNIST 数据集
transform = transforms.Compose([transforms.ToTensor()]) # 只需要转换为 Tensor
train_data = datasets.FashionMNIST(root='data', train=True, download=True, transform=transform)
# 获取前 10 张图像以及对应的标签
images, labels = zip(*[(train_data[i][0], train_data[i][1]) for i in range(10)])
# 类别名称映射
class_names = [
'T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot'
]
# 设置绘图
fig, axes = plt.subplots(1, 10, figsize=(15, 15)) # 创建 1 行 10 列的子图
for i in range(10):
ax = axes[i]
ax.imshow(images[i].squeeze(), cmap='gray') # squeeze 去掉多余的维度,cmap 为灰度色
ax.set_title(class_names[labels[i]]) # 标注类别名称
ax.axis('off') # 不显示坐标轴
plt.show() # 显示图像
运行结果:
总结:
FashionMNIST 是一个标准化的图像分类数据集,由 Zalando 提供。它由 10 类不同的时尚商品构成,训练集包含 60,000 张图像,测试集包含 10,000 张图像。它适用于深度学习、机器学习模型的训练和评估,尤其适合初学者学习和实验。
项目实例
代码
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
# 下载训练数据集FashionMNIST
training_data = torchvision.datasets.FashionMNIST(
root="data", # 数据集存储位置
train=True, # 使用训练集
download=True, # 如果数据集不存在,则下载
transform=transforms.ToTensor(), # 转换为Tensor
)
# 下载测试数据集FashionMNIST
test_data = torchvision.datasets.FashionMNIST(
root="data",
train=False, # 使用测试集
download=True,
transform=transforms.ToTensor(), # 转换为Tensor
)
# 标签的映射字典,数字标签对应的衣物类别名称
labels_map = {
0: "T-Shirt",
1: "Trouser",
2: "Pullover",
3: "Dress",
4: "Coat",
5: "Sandal",
6: "Shirt",
7: "Sneaker",
8: "Bag",
9: "Ankle Boot",
}
# 可视化FashionMNIST数据集中前9张图片
figure = plt.figure(figsize=(8, 8)) # 创建一个8x8的图像画布
cols, rows = 3, 3 # 设置行列数
for i in range(1, cols * rows + 1):
sample_idx = torch.randint(len(training_data), size=(1,)).item() # 随机选取一张图片
img, label = training_data[sample_idx] # 获取图片和标签
figure.add_subplot(rows, cols, i) # 在画布上添加子图
plt.title(labels_map[label]) # 设置图片的标题为标签对应的衣物类别
plt.axis("off") # 关闭坐标轴显示
plt.imshow(img.squeeze(), cmap="gray") # 显示图像,squeeze去掉多余维度,cmap设置为灰度图
plt.show() # 展示图像
# 设置训练过程中的超参数
num_epochs = 10 # 训练的轮数
batch_size = 32 # 批大小
weight_decay = 1e-4 # 权重衰减(L2正则化)
learning_rate = 0.001 # 学习率
# 创建数据加载器,训练集和测试集
train_dataloader = torch.utils.data.DataLoader(training_data, batch_size=batch_size)
test_dataloader = torch.utils.data.DataLoader(test_data, batch_size=batch_size)
# 打印测试集的一个batch的尺寸和标签类型
for X, y in test_dataloader:
print(f"Shape of X [N, C, H, W]: {X.shape}") # X是输入图像,N是批大小,C是通道数,H和W是图像的高和宽
print(f"Shape of y: {y.shape} {y.dtype}") # y是标签,显示其维度和数据类型
break # 只打印一个batch的信息
# 检测是否使用GPU进行训练
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device") # 输出当前使用的设备(CUDA or CPU)
# 定义一个简单的神经网络模型
class NeuralNet(nn.Module):
def __init__(self, input_size, hidden_size, num_classes):
super(NeuralNet, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size) # 第一层全连接层,输入784个特征,输出hidden_size个特征
self.relu = nn.ReLU() # ReLU激活函数
self.fc2 = nn.Linear(hidden_size, num_classes) # 第二层全连接层,输出num_classes个类别的预测值
def forward(self, x):
out = self.fc1(x) # 输入通过第一层
out = self.relu(out) # ReLU激活
out = self.fc2(out) # 输入通过第二层,输出结果
return out
# 假设输入是28x28的图像,展开为784维,隐藏层大小为500,分类数为10
model = NeuralNet(input_size=784, hidden_size=500, num_classes=10).to(device)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss() # 使用交叉熵损失函数,适用于多分类问题
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate, weight_decay=weight_decay) # 使用Adam优化器
# 开始训练模型
total_step = len(train_dataloader) # 获取训练集的总批次数
for epoch in range(num_epochs): # 遍历每一个epoch
for i, (images, labels) in enumerate(train_dataloader): # 遍历每一个batch
images = images.reshape(-1, 28*28).to(device) # 将28x28的图像展开成784维向量,转移到device(GPU/CPU)
labels = labels.to(device) # 标签转移到设备上
# 前向传播
outputs = model(images) # 将输入传入模型,得到预测输出
loss = criterion(outputs, labels) # 计算损失
# 反向传播和优化
optimizer.zero_grad() # 清零之前的梯度
loss.backward() # 计算当前梯度
optimizer.step() # 更新模型参数
# 每100个batch输出一次训练状态
if (i + 1) % 100 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{total_step}], Loss: {loss.item():.4f}')
# 训练完成后,在测试集上评估模型的准确率
model.eval() # 设置模型为评估模式(此时BatchNorm等层使用移动平均值而不是批量值)
with torch.no_grad(): # 不需要计算梯度
correct = 0
total = 0
for images, labels in test_dataloader:
images = images.reshape(-1, 28*28).to(device) # 将图像展开为784维
labels = labels.to(device) # 标签转移到设备上
outputs = model(images) # 获取模型的输出
_, predicted = torch.max(outputs.data, 1) # 获取预测类别,outputs.data返回模型的预测结果
total += labels.size(0) # 统计总样本数
correct += (predicted == labels).sum().item() # 统计预测正确的样本数
# 输出模型在测试集上的准确率
print(f'Test Accuracy of the model on the 10000 test images: {100 * correct / total} %')