- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊 | 接辅导、项目定制
前言
希望接下来能好好研究深度学习的相关知识
一、代码及运行结果
1.引入库
import torch
import numpy as np
from matplotlib import pyplot as plt
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import torch.nn.functional as F
2.数据集
网址:Mnist数据集
3.数据加载
# 定义数据转换,将图像转换为张量
transformation = transforms.Compose([
transforms.ToTensor(),
])
# 创建训练数据集对象,指定数据存储路径、训练标志、数据转换和下载标志
train_ds = datasets.MNIST(
r'./raw',
train=True,
transform=transformation,
download=True
)
# 创建测试数据集对象,指定数据存储路径、训练标志、数据转换和下载标志
test_ds = datasets.MNIST(
r'./raw',
train=False,
transform=transformation,
download=True
)
# 创建训练数据加载器,指定训练数据集和批量大小,启用数据打乱
train_dl = torch.utils.data.DataLoader(train_ds, batch_size=64, shuffle=True)
# 创建测试数据加载器,指定测试数据集和批量大小
test_dl = torch.utils.data.DataLoader(test_ds, batch_size=256)
# 从训练数据加载器中获取一个批次的图像和标签
imgs, labels = next(iter(train_dl))
代码解析:
- transforms.Compose 创建了一个数据转换对象,将图像转换为张量的形式。
- datasets.MNIST 创建了训练和测试数据集的对象,指定了数据存储路径、训练标志、数据转换和下载标志。
- torch.utils.data.DataLoader
创建了训练和测试数据的加载器,指定了数据集和批量大小。在训练数据加载器中,还启用了数据打乱。 - next(iter(train_dl)) 从训练数据加载器中获取一个批次的图像和标签,用于模型训练。
总结:这段代码是为了加载MNIST数据集,并准备用于模型的训练和测试。
4.构建模型
# 定义神经网络模型类,继承自nn.Module
class Model(nn.Module):
# 构造函数,定义网络结构的层
def __init__(self):
super().__init__()
# 定义第一层线性层,输入大小为28*28,输出大小为120
self.liner_1 = nn.Linear(28*28, 120)
# 定义第二层线性层,输入大小为120,输出大小为84
self.liner_2 = nn.Linear(120, 84)
# 定义第三层线性层,输入大小为84,输出大小为10
self.liner_3 = nn.Linear(84, 10)
# 定义前向传播函数
def forward(self, input):
# 将输入的图像数据展平为一维向量,大小为28*28
x = input.view(-1, 28*28)
# 经过第一层线性层,并应用ReLU激活函数
x = F.relu(self.liner_1(x))
# 经过第二层线性层,并应用ReLU激活函数
x = F.relu(self.liner_2(x))
# 经过第三层线性层,得到最终输出
x = self.liner_3(x)
代码解析:
- nn.Module 是PyTorch中所有神经网络模型的基类。
- init 构造函数中定义了神经网络的结构,包括三个线性层(全连接层)。
- forward 函数定义了前向传播过程,其中图像数据经过线性层和 ReLU激活函数的处理,最终得到模型的输出。
- nn.Linear 表示线性层,即全连接层,它定义了一个线性变换。
- F.relu 是ReLU激活函数,用于引入非线性特性。
总结:输入图像经过线性层和激活函数的处理,逐渐提取和组合特征,最终得到模型的输出。这个模型的输出大小为10,适用于分类问题,例如MNIST手写数字分类。
5.训练模型
# 定义交叉熵损失函数
loss_fn = torch.nn.CrossEntropyLoss()
# 定义训练函数
def fit(epoch, model, trainloader, testloader):
correct = 0 # 用于记录训练集正确分类的样本数
total = 0 # 训练集总样本数
running_loss = 0 # 用于记录训练过程中的损失
# 遍历训练集
for x, y in trainloader:
y_pred = model(x) # 模型预测
loss = loss_fn(y_pred, y) # 计算损失
optim.zero_grad() # 梯度清零
loss.backward() # 反向传播
optim.step() # 更新权重
with torch.no_grad():
y_pred = torch.argmax(y_pred, dim=1)
correct += (y_pred == y).sum().item() # 统计正确分类的样本数
total += y.size(0) # 统计总样本数
running_loss += loss.item() # 累计损失值
epoch_loss = running_loss / len(trainloader.dataset) # 计算平均损失
epoch_acc = correct / total # 计算训练集准确率
# 在测试集上进行评估
test_correct = 0
test_total = 0
test_running_loss = 0
with torch.no_grad():
for x, y in testloader:
y_pred = model(x)
loss = loss_fn(y_pred, y)
y_pred = torch.argmax(y_pred, dim=1)
test_correct += (y_pred == y).sum().item()
test_total += y.size(0)
test_running_loss += loss.item()
epoch_test_loss = test_running_loss / len(testloader.dataset) # 计算测试集平均损失
epoch_test_acc = test_correct / test_total # 计算测试集准确率
# 打印训练和测试的指标信息
print('epoch: ', epoch,
'loss: ', round(epoch_loss, 3),
'accuracy:', round(epoch_acc, 3),
'test_loss: ', round(epoch_test_loss, 3),
'test_accuracy:', round(epoch_test_acc, 3)
)
return epoch_loss, epoch_acc, epoch_test_loss, epoch_test_acc
# 定义优化器,使用Adam优化器,学习率为0.001,优化模型的参数
optim = torch.optim.Adam(model.parameters(), lr=0.001)
# 定义训练的总轮数
epochs = 10
# 用于存储每个epoch的训练和测试指标
train_loss = []
train_acc = []
test_loss = []
test_acc = []
# 循环训练模型,迭代指定的轮数
for epoch in range(epochs):
# 调用fit函数进行模型训练和评估
epoch_loss, epoch_acc, epoch_test_loss, epoch_test_acc = fit(epoch,
model,
train_dl,
test_dl)
# 记录训练和测试的损失和准确率
train_loss.append(epoch_loss)
train_acc.append(epoch_acc)
test_loss.append(epoch_test_loss)
test_acc.append(epoch_test_acc)
代码解析:
- torch.nn.CrossEntropyLoss() 创建了交叉熵损失函数,适用于多类别分类问题。
- fit 函数是训练模型的函数,其中包含了训练和测试过程。
- 在训练过程中,通过前向传播得到预测结果,计算损失,进行反向传播更新模型权重。
- 记录训练过程中的损失、正确分类的样本数和总样本数,用于计算训练集准确率 。
- 在测试集上进行评估,同样记录测试过程中的损失、正确分类的样本数和总样本数,用于计算测试集准确率。
- 打印每个epoch的训练和测试指标信息,包括损失和准确率。
- torch.optim.Adam 创建了Adam优化器,用于调整模型参数以最小化损失。
- epochs 定义了总的训练轮数。每个epoch结束后,将训练和测试的损失、准确率记录到相应的列表中。
- 最终得到四个列表 train_loss, train_acc, test_loss,
test_acc,它们分别记录了每个epoch的训练损失、训练准确率、测试损失和测试准确率。这些列表可用于绘制训练曲线和测试曲线,以便更好地了解模型的性能。
二、总结
- 上述操作采用全链接模型,未涉及到卷积、池化等,后续会逐步完善。
- Transforms.ToTensor的作用:①将数据集转化为一个tensor;②归一化处理
- 在pytorch里面图片的表示形式: 【batch, channel, hight, width】