Pytorch-quickstart学习日志
学习参考网址:
https://docs.pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html
头文件解读:
import torch # 导入 PyTorch 的核心库,提供了张量计算、自动微分、GPU 加速等深度学习基础功能。
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor
1.import torch
导入 PyTorch 的核心库,提供了张量计算、自动微分、GPU 加速等深度学习基础功能。
2.from torch import nn
导入 PyTorch 的神经网络模块 torch.nn,用于构建和训练神经网络:
nn.Module:所有神经网络模块的基类
预定义层:如 nn.Linear(全连接层)、nn.Conv2d(卷积层)
激活函数:如 nn.ReLU、nn.Sigmoid
损失函数:如 nn.CrossEntropyLoss、nn.MSELoss
3.from torch.utils.data import DataLoader
导入数据加载器 DataLoader,用于批量处理和加载训练 / 测试数据:
支持自动批处理、并行加载、数据打乱等功能
是 PyTorch 数据处理流程的核心组件
4.from torchvision import datasets
导入 torchvision.datasets 模块,提供常用的公开数据集:
如 MNIST、CIFAR-10、ImageNet 等
支持自动下载和预处理
5.from torchvision.transforms import ToTensor
导入图像转换工具 ToTensor,用于将 PIL 图像或 NumPy 数组转换为 PyTorch 张量(Tensor):
同时会自动将像素值从 [0,255] 缩放到 [0.0,1.0]
是图像数据预处理的常用操作
training_data = datasets.FashionMNIST(
root="data", # 数据存储路径(会在当前目录下创建"data"文件夹)
train=True, # True:加载训练集(60,000张图像),False:加载测试集(10,000张)
download=True, # 若本地无数据,自动从网络下载
transform=ToTensor(), # 数据预处理:将PIL图像转为Tensor,并归一化到 [0, 1]
)
FashionMNIST 数据集特点:衣服分类(10个类别)
图像规格:
单通道灰度图,尺寸 28×28 像素
像素值范围:0(黑)~255(白)
在使用 FashionMNIST 或任何数据集时,了解其结构和元数据是很重要的。以下是几种获取这些信息的方法:
方法1:官方文档与数据集描述
最直接的方式是查阅 PyTorch 和 FashionMNIST 的官方文档:
PyTorch FashionMNIST 类文档:
https://pytorch.org/vision/stable/generated/torchvision.datasets.FashionMNIST.html
文档中明确提到了数据集的类别、图像尺寸等信息。
原始数据集官网:
https://github.com/zalandoresearch/fashion-mnist
这里提供了完整的数据集描述,包括 10 个类别标签的具体含义。

同时也明确了分类。
代码中直接查看数据集属性
举个例子:
# 查看类别名称
print("类别标签映射:",dataset.classes)
# 输出
# ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
# 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
#查看第一个样本:
sample = dataset[0]
print(type(sample))
print(len(sample))
print("样本内容",sample) #(<PIL.Image.Image image mode=L size=28x28 at 0x1895FD47DF0>, 9)
# 参看dataset[0],图像尺寸,标注尺寸
image,lable = dataset[0] # 取第一个样本
print(f"数据集类型:{type(dataset[0])}") # 输出: <class 'tuple'>
print(f"图像类型:{type(image)}") # 输出: PIL.Image.Image
print(f"图像类型:{image.size}") # 输出: (28,28)
其中dataset[0]是元组格式:重点看这句:
(<PIL.Image.Image image mode=L size=28x28 at 0x1895FD47DF0>, 9)
第一个元素:输入数据(图像)、类型:PIL.Image.Image(若transform=None)、内容:尺寸为(28, 28)的灰度图像(像素值 0-255)。
第二个元素:目标标签(类别) 类型:int 内容:0-9 的整数,对应衣物类别(如 0 表示 "T-shirt/top")。
为什么使用元组?
- 统一数据格式
深度学习任务中,每个样本通常需要同时包含:输入数据(如图像、文本)目标标签(如分类标签、回归值)
元组是一种轻量级的数据结构,能清晰地将两者绑定在一起,方便后续处理。 - 兼容数据加载器(DataLoader)
DataLoader 会自动对dataset中的元组进行批量处理:
将所有样本的输入数据堆叠为一个张量(如形状为[batch_size, 1, 28, 28])
将所有样本的标签堆叠为一个标签张量(如形状为[batch_size])
如果dataset[0]不是元组,DataLoader将无法正确解析输入和标签。 - 方便自定义数据集
当你自定义数据集时,只需遵循 “返回元组” 的约定,即可无缝接入 PyTorch 的训练流程。例如:
class MyDataset(torch.utils.data.Dataset):
def __getitem__(self, index):
img = ... # 加载图像
label = ... # 获取标签
return (img, label) # 必须返回元组
四、如何使用元组中的元素
1.解包元素
image, label = dataset[0] # 解包元组
print(f"图像尺寸: {image.size}") # 输出: (28, 28)
print(f"标签: {label}") # 输出: 9(假设是Ankle boot)
- 在数据加载器中处理
from torch.utils.data import DataLoader
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
for batch_images, batch_labels in dataloader:
# batch_images: 形状为 [32, 1, 28, 28] 的张量(输入数据)
# batch_labels: 形状为 [32] 的张量(标签)
pass
四维张量(Tensor)形状
PyTorch 中图像数据的张量形状遵循 通道优先(Channel-first) 格式,即维度顺序为:
[批次大小 (Batch Size), 通道数 (Channels), 高度 (Height), 宽度 (Width)]
各维度具体解释:
第 0 维:32(批次大小,Batch Size)
表示一次处理 32 张图像(即一个批次包含 32 个样本)。
作用:批量处理可加速训练,减少计算资源消耗(如 GPU 利用率更高)。
第 1 维:1(通道数,Channels)
表示图像的 颜色通道数:
1:单通道(灰度图,如 MNIST、FashionMNIST)。
3:三通道(RGB 彩色图,如 CIFAR-10)。
注意:PyTorch 中通道维度必须位于高度和宽度之前(通道优先)。
第 2-3 维:28 和 28(高度和宽度,Height & Width)
表示每张图像的尺寸为 28×28 像素。
例如:FashionMNIST 数据集的每张图像都是 28×28 像素的灰度图。
深度学习中,图像数据通常以四维张量形式存储:
批量维度(Batch):支持一次处理多张图像。
通道维度(Channel):区分颜色通道(灰度 / 彩色)。
空间维度(Height/Width):保留图像的空间结构(用于卷积操作)
豆包提问:batch_size怎么理解
在训练神经网络时,batch_size 表示每次迭代(iteration)中同时处理的样本数量。
若 batch_size = 32,则每次向模型输入 32 张图像 及其标签,计算一次梯度并更新模型参数。
若 训练集总共有 60,000 张图像,则一个 epoch(遍历完所有样本) 需要进行 60,000 / 32 ≈ 1875 次迭代。
这些相对比较简单了。
# Create data loaders.
train_dataloader = DataLoader(training_data, batch_size=batch_size)
test_dataloader = DataLoader(test_data, batch_size=batch_size)
for X, y in test_dataloader:
print(f"Shape of X [N, C, H, W]: {X.shape}")
print(f"Shape of y: {y.shape} {y.dtype}")
break
# Createing Models
# (1)确定加速器形式,Using cuda device
device = torch.accelerator.current_accelerator().type \
if torch.accelerator.is_available() else "cpu"
print(f"Using {device} device")
关键点:定义一个简单的神经网络的关键方法解析:
- init() 方法
用于定义网络的层结构:
nn.Flatten():将输入的多维张量(如图像)展平为一维向量。
例如:输入形状为 [batch_size, 1, 28, 28] 的图像,展平后变为 [batch_size, 784]。
个人理解:把拼图合成一张图片
nn.Linear():全连接层,实现线性变换 y = xW + b。
参数:in_features(输入维度)和 out_features(输出维度)。
【豆包问题】nn.Linear():怎么理解
一、核心功能与数学原理:
nn.Linear()实现了线性变换:
y=xW+b 其中:
x是输入张量,形状为 [batch_size, in_features]
W是权重矩阵,形状为 [in_features, out_features]
b是偏置向量,形状为 [out_features]
y是输出张量,形状为 [batch_size, out_features]
2.参数说明
nn.Linear(in_features, out_features, bias=True)
in_features:输入特征的维度(即输入神经元数量)。
out_features:输出特征的维度(即输出神经元数量)。
bias:是否添加偏置项(默认为 True)。
nn.Linear() 是 PyTorch 中实现全连接层的核心组件,基于公式 y=xW+b进行线性变换。
参数:通过 in_features 和 out_features 控制输入输出维度,支持批量处理。
【豆包问题】nn.ReLU():怎么理解
nn.ReLU():激活函数,引入非线性性,公式为 ReLU(x) = max(0, x)。
ReLU(Rectified Linear Unit)的定义为:
ReLU(x)=max(0,x)
即:当输入 x>0时,输出为x。当输入x≤0时,输出为0。
nn.Sequential():顺序容器,按顺序连接多个模块,简化前向传播代码。
- forward() 方法
定义数据的流动路径:
输入参数 x:通常是一个批次的输入数据(如 [batch_size, 1, 28, 28] 的图像张量)。
返回值 logits:模型的原始输出,未经过 softmax 激活函数。
若要得到概率分布,需额外调用 torch.nn.functional.softmax(logits, dim=1)。
Optimizing the Model Parameters
loss_fn = nn.CrossEntropyLoss() #交叉熵损失函数
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
#该函数要求模型输出未经归一化的分数(也就是 logits),而不是经过 softmax 处理后的概率分布。
两个关键的函数:
loss_fn = nn.CrossEntropyLoss()
为了训练一个模型,我们需要一个损失函数和一个优化器
优化器的配置:
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
其中,model.parameters()会提供需要训练的参数,lr=1e-3表示学习率被设置为 0.001。
这行代码的作用是创建一个交叉熵损失函数。
交叉熵损失函数主要用于多分类问题,它综合了LogSoftmax和NLLLoss这两个功能。
该函数要求模型输出未经归一化的分数(也就是 logits),而不是经过 softmax 处理后的概率分布。
这两个组件在训练深度学习模型的过程中起着至关重要的作用。在每个训练批次里,通常会按照以下步骤使用它们:
先把输入数据传递给模型,得到预测结果。
利用预测结果和真实标签,通过损失函数计算出损失值。
调用loss.backward()计算梯度。
使用优化器来更新模型的参数。
# 这段代码定义了神经网络的训练循环,是深度学习中最核心的部分。
# 将从数据流动、梯度计算、参数更新三个维度详细解析,
# 并结合可视化帮助你理解每个步骤的作用
def train(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset) #训练集总样本数
model.train() #设置模型为训练模式(影响BatchNorm、Dropout等层)
# 遍历数据加载器中的每个批次
for batch, (X, y) in enumerate(dataloader):
X, y = X.to(device), y.to(device) # 将数据移至GPU(如果有)
# 1. 前向传播:计算预测值和损失
# Compute prediction error
pred = model(X) # 模型预测
loss = loss_fn(pred, y) # 计算损失(预测值与真实标签的差异)
# 2. 反向传播:计算梯度
loss.backward() # 反向传播,计算每个参数的梯度
# 3. 参数更新:使用优化器调整权重
optimizer.step() # 根据梯度更新模型参数
optimizer.zero_grad() # 梯度清零,防止累积
# 打印训练进度
if batch % 100 == 0:
loss, current = loss.item(), (batch + 1) * len(X)
print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")
- 数据流动示意图
输入数据 (X) → 模型 (Model) → 预测值 (Pred)
[batch_size, 1, 28, 28] [batch_size, 10]
预测值 (Pred) + 真实标签 (y) → 损失函数 (Loss_fn) → 损失值 (Loss)
损失值 (Loss) → 反向传播 (backward) → 计算梯度 (grad)
梯度 (grad) → 优化器 (Optimizer) → 更新参数 (W ← W - lr·grad)
2. 批次训练流程
┌───────────────────────────────────────────────────────────┐
│ 对于每个批次 (X, y): │
│ │
│ ┌───────────────────┐ ┌───────────────────┐ │
│ │ 前向传播 │ │ 反向传播 │ │
│ │ │ │ │ │
│ │ X → model → pred │ │ loss → backward │ │
│ │ pred → loss_fn │ │ → 计算各参数梯度 │ │
│ └───────────────────┘ └───────────┬───────┘ │
│ │ │
│ ┌───────────────────┐ ┌───────────▼───────┐ │
│ │ 参数更新 │ │ 梯度清零 │ │
│ │ │ │ │ │
│ │ optimizer.step() │ │ optimizer.zero_grad() │ │
│ └───────────────────┘ └───────────────────┘ │
│ │
└───────────────────────────────────────────────────────────┘
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor
# Download training data from open datasets.
training_data = datasets.FashionMNIST(
root="data",
train=True,
download=True,
transform=ToTensor(),
)
# Download test data from open datasets.
test_data = datasets.FashionMNIST(
root="data",
train=False,
download=True,
transform=ToTensor(),
)
batch_size = 64
# Create data loaders.
train_dataloader = DataLoader(training_data, batch_size=batch_size)
test_dataloader = DataLoader(test_data, batch_size=batch_size)
for X, y in test_dataloader:
print(f"Shape of X [N, C, H, W]: {X.shape}")
print(f"Shape of y: {y.shape} {y.dtype}")
break
# Createing Models
# (1)确定加速器形式,Using cuda device
device = torch.accelerator.current_accelerator().type \
if torch.accelerator.is_available() else "cpu"
print(f"Using {device} device")
# Define model : 定义一个简单的神经网络#
# 模型怎么定义成这个形式,理解不上去啊
class NeuralNetwork(nn.Module):
def __init__(self): # 初始化网络结构
super().__init__() # 调用父类nn.Module的构造函数
# 定义网络层结构
self.flatten = nn.Flatten() #将多维输入展平为一维向量
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, 512), # 全连接层:输入784(28*28),输出512
nn.ReLU(), # Relu激活函数
nn.Linear(512, 512), # 第二个全连接层
nn.ReLU(),
nn.Linear(512, 10) # 输出层:10个类别(对应0-9的数字)
)
def forward(self, x):
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
model = NeuralNetwork().to(device)
print(model)
# Optimizing the Model Parameters
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
# 这段代码定义了神经网络的训练循环,是深度学习中最核心的部分。
# 将从数据流动、梯度计算、参数更新三个维度详细解析,
# 并结合可视化帮助你理解每个步骤的作用
def train(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset) #训练集总样本数
model.train() #设置模型为训练模式(影响BatchNorm、Dropout等层)
# 遍历数据加载器中的每个批次
for batch, (X, y) in enumerate(dataloader):
X, y = X.to(device), y.to(device) # 将数据移至GPU(如果有)
# 1. 前向传播:计算预测值和损失
# Compute prediction error
pred = model(X) # 模型预测
loss = loss_fn(pred, y) # 计算损失(预测值与真实标签的差异)
# 2. 反向传播:计算梯度
loss.backward() # 反向传播,计算每个参数的梯度
# 3. 参数更新:使用优化器调整权重
optimizer.step() # 根据梯度更新模型参数
optimizer.zero_grad() # 梯度清零,防止累积
if batch % 100 == 0:
loss, current = loss.item(), (batch + 1) * len(X)
print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")
def test(dataloader, model, loss_fn):
size = len(dataloader.dataset)
num_batches = len(dataloader)
model.eval()
test_loss, correct = 0, 0
with torch.no_grad():
for X, y in dataloader:
X, y = X.to(device), y.to(device)
pred = model(X)
test_loss += loss_fn(pred, y).item()
correct += (pred.argmax(1) == y).type(torch.float).sum().item()
test_loss /= num_batches
correct /= size
print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
epochs = 10
for t in range(epochs):
print(f"Epoch {t+1}\n-------------------------------")
train(train_dataloader, model, loss_fn, optimizer)
test(test_dataloader, model, loss_fn)
print("Done!")
torch.save(model.state_dict(), "model.pth")
print("Saved PyTorch Model State to model.pth")
model = NeuralNetwork().to(device)
model.load_state_dict(torch.load("model.pth", weights_only=True))
classes = [
"T-shirt/top",
"Trouser",
"Pullover",
"Dress",
"Coat",
"Sandal",
"Shirt",
"Sneaker",
"Bag",
"Ankle boot",
]
model.eval()
x, y = test_data[0][0], test_data[0][1]
with torch.no_grad():
x = x.to(device)
pred = model(x)
predicted, actual = classes[pred[0].argmax(0)], classes[y]
print(f'Predicted: "{predicted}", Actual: "{actual}"')
浙公网安备 33010602011771号