红旗网站建设,wordpress自动内链,天美大象果冻星空的制作方法,狗和女主人做爰网站笔记为自我总结整理的学习笔记#xff0c;若有错误欢迎指出哟~ 往期文章#xff1a; 【深度学习】pytorch——快速入门 CIFAR-10分类 CIFAR-10简介CIFAR-10数据集分类实现步骤一、数据加载及预处理实现数据加载及预处理归一化的理解访问数据集Dataset对象Dataloader对象 二、… 笔记为自我总结整理的学习笔记若有错误欢迎指出哟~ 往期文章 【深度学习】pytorch——快速入门 CIFAR-10分类 CIFAR-10简介CIFAR-10数据集分类实现步骤一、数据加载及预处理实现数据加载及预处理归一化的理解访问数据集Dataset对象Dataloader对象 二、定义网络三、定义损失函数和优化器(loss和optimizer)四、训练网络并更新网络参数enumerate函数 五、测试网络部分数据集实际的label部分数据集预测的label整个测试集 CIFAR-10简介
CIFAR-10是一个常用的图像分类数据集每张图片都是 3×32×323通道彩色图片分辨率为 32×32。
它包含了10个不同类别每个类别有6000张图像其中5000张用于训练1000张用于测试。这10个类别分别为飞机、汽车、鸟类、猫、鹿、狗、青蛙、马、船和卡车。
CIFAR-10分类任务是将这些图像正确地分类到它们所属的类别中。对于这个任务可以使用深度学习模型如卷积神经网络(CNN)来实现高效的分类。
CIFAR-10分类任务是一个比较典型的图像分类问题在计算机视觉领域中被广泛使用是检验深度学习模型表现的一个重要基准。
CIFAR-10数据集分类实现步骤
使用torchvision加载并预处理CIFAR-10数据集定义网络定义损失函数和优化器训练网络并更新网络参数测试网络
一、数据加载及预处理
实现数据加载及预处理
import torch as t
import torchvision as tv
import torchvision.transforms as transforms
from torchvision.transforms import ToPILImage
show ToPILImage() # 可以把Tensor转成Image方便可视化# 第一次运行程序torchvision会自动下载CIFAR-10数据集大约100M。
# 如果已经下载有CIFAR-10可通过root参数指定# 定义对数据的预处理
transform transforms.Compose([transforms.ToTensor(), # 转为Tensortransforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), # 归一化])# 训练集
trainset tv.datasets.CIFAR10( # PyTorch提供的CIFAR-10数据集的类用于加载CIFAR-10数据集。rootD:/深度学习基础/pytorch/data/, # 设置数据集存储的根目录。trainTrue, # 指定加载的是CIFAR-10的训练集。downloadTrue, # 如果数据集尚未下载设置为True会自动下载CIFAR-10数据集。transformtransform) # 设置数据集的预处理方式。# 数据加载器
trainloader t.utils.data.DataLoader(trainset, # 指定了要加载的训练集数据即CIFAR-10数据集。batch_size4, # 每个小批量(batch)的大小是4即每次会加载4张图片进行训练。shuffleTrue, # 在每个epoch训练开始前会打乱训练集中数据的顺序以增加训练效果。num_workers2) # 使用2个进程来加载数据以提高数据的加载速度。# 测试集
testset tv.datasets.CIFAR10(D:/深度学习基础/pytorch/data/,trainFalse, downloadTrue, transformtransform)testloader t.utils.data.DataLoader(testset,batch_size4, shuffleFalse,num_workers2)classes (plane, car, bird, cat,deer, dog, frog, horse, ship, truck)这段代码主要是使用PyTorch和torchvision库来加载并处理CIFAR-10数据集其中包括训练集和测试集。
import torch as t 和 import torchvision as tv 导入了PyTorch和torchvision库。import torchvision.transforms as transforms 导入了torchvision.transforms模块用于进行数据转换和增强操作。from torchvision.transforms import ToPILImage 导入了ToPILImage类它可以将Tensor对象转换为PIL Image对象以方便后续的可视化操作。show ToPILImage() 创建一个ToPILImage对象用于将张量(Tensor)对象转换为PIL Image对象以便于后续的可视化操作。transform transforms.Compose([...]) 定义对数据的预处理操作将多个预处理操作组合在一起形成一个数据预处理的管道。该管道首先使用transforms.ToTensor()函数将图像转换为张量(Tensor)对象然后使用transforms.Normalize()函数对图像进行归一化操作以便于后续的训练。trainset tv.datasets.CIFAR10([...]) 使用tv.datasets.CIFAR10()函数加载CIFAR-10数据集并指定数据集的存储位置、是否为训练集、是否需要下载等参数。还可以通过transform参数来指定对数据进行的预处理操作。trainloader t.utils.data.DataLoader([...]) 使用PyTorch的DataLoader类来创建一个数据加载器该加载器可以按照指定的批量大小将数据集分成小批量进行加载。可以指定加载器的参数如批量大小、是否随机洗牌、使用的进程数等。testset tv.datasets.CIFAR10([...]) 和 testloader t.utils.data.DataLoader([...]) 与训练集的加载方式类似只是将参数中的train改为False表示这是测试集。classes (plane, car, bird, cat, deer, dog, frog, horse, ship, truck) 定义了CIFAR-10数据集中包含的10个类别。
注tv.datasets.CIFAR10()函数会自动下载CIFAR-10数据集并存储到指定位置如果已经下载过该数据集可以通过root参数来指定数据集的存储位置避免重复下载浪费时间和带宽。
归一化的理解
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), # 归一化transforms.Normalize()函数实现了对图像数据进行归一化操作。该函数的参数是均值和标准差在CIFAR-10数据集中每个像素有3个通道(R,G,B)因此传入的均值和标准差是一个长度为3的元组。这里(0.5, 0.5, 0.5)表示每个通道的均值为0.5(0.5, 0.5, 0.5)表示每个通道的标准差也为0.5。具体地对于每个像素的每个通道该函数执行以下计算
input[channel] (input[channel] - mean[channel]) / std[channel]其中input[channel]表示一个像素的某个通道的像素值mean[channel]和std[channel]分别表示该通道的均值和标准差。通过这样的归一化操作每个通道的像素值都将落在-1到1之间从而便于模型的训练。
因此这行代码的作用是对CIFAR-10数据集中的图像进行归一化将每个通道的像素值映射到-1到1之间。
访问数据集
Dataset对象
Dataset对象是一个数据集可以按下标访问返回形如(data, label)的数据。
(data, label) trainset[100] # 从训练集中获取第100个样本的数据图像和标签。
print(classes[label]) # (data 1) / 2是为了还原被归一化的数据将之前归一化的数据重新映射到0到1的范围内。
show((data 1) / 2).resize((200, 200))输出为
ship
Dataloader对象
Dataloader是一个可迭代的对象它将dataset返回的每一条数据拼接成一个batch并提供多线程加速优化和数据打乱等操作。当程序对dataset的所有数据遍历完一遍之后相应的对Dataloader也完成了一次迭代
dataiter iter(trainloader)
images, labels next(dataiter) # 返回4张图片及标签
print(.join(%11s%classes[labels[j]] for j in range(4)))
show(tv.utils.make_grid((images1)/2)).resize((400,100))使用iter(trainloader)将训练数据加载器转换成一个迭代器对象dataiter。 使用next(dataiter)从迭代器中获取下一个批次的数据。这里假设每个批次的大小为4所以images和labels分别是一个包含4张图片和对应标签的张量。 通过一个循环遍历了这4张图片的标签并使用classes[labels[j]]将每个标签转换为对应的类别名称。classes是一个包含CIFAR-10数据集各个类别名称的列表。 使用tv.utils.make_grid()函数将这4张图片拼接成一张网格图并通过(images1)/2将像素值从[-1, 1]的范围映射到[0, 1]的范围。使用show()函数显示图像并调用resize()对图像进行调整大小再使用print()输出调整大小后的图像。
输出为 cat truck plane deer
二、定义网络
LeNet网络self.conv1第一个参数为3通道因为CIFAR-10是3通道彩图
import torch.nn as nn
import torch.nn.functional as Fclass Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 nn.Conv2d(3, 6, 5) self.conv2 nn.Conv2d(6, 16, 5) self.fc1 nn.Linear(16*5*5, 120) self.fc2 nn.Linear(120, 84)self.fc3 nn.Linear(84, 10)def forward(self, x): x F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) x F.max_pool2d(F.relu(self.conv2(x)), 2) x x.view(x.size()[0], -1) # -1表示会自适应的调整剩余的维度x F.relu(self.fc1(x))x F.relu(self.fc2(x))x self.fc3(x) return xnet Net()
print(net)输出为
Net((conv1): Conv2d(3, 6, kernel_size(5, 5), stride(1, 1))(conv2): Conv2d(6, 16, kernel_size(5, 5), stride(1, 1))(fc1): Linear(in_features400, out_features120, biasTrue)(fc2): Linear(in_features120, out_features84, biasTrue)(fc3): Linear(in_features84, out_features10, biasTrue)
)模型包含以下层
self.conv1: 输入通道数为3输出通道数为6卷积核大小为5x5的卷积层。self.conv2: 输入通道数为6输出通道数为16卷积核大小为5x5的卷积层。self.fc1: 输入大小为16x5x5输出大小为120的全连接层。self.fc2: 输入大小为120输出大小为84的全连接层。self.fc3: 输入大小为84输出大小为10的全连接层。
模型的前向传播函数(forward)
先经过第一个卷积层然后应用ReLU激活函数和2x2的最大池化操作。再经过第二个卷积层同样应用ReLU激活函数和2x2的最大池化操作。通过x.view(x.size()[0], -1)将特征张量x展平为一维向量以便输入全连接层。依次经过两个全连接层并使用ReLU激活函数进行非线性变换。最后一层是一个全连接层输出大小为10对应CIFAR-10数据集的10个类别。这里没有使用激活函数因为该模型将其输出直接作为分类的得分。
总体而言该模型由两个卷积层和三个全连接层组成用于对CIFAR-10数据集进行图像分类。
三、定义损失函数和优化器(loss和optimizer)
from torch import optim
criterion nn.CrossEntropyLoss() # 交叉熵损失函数
optimizer optim.SGD(net.parameters(), lr0.001, momentum0.9)nn.CrossEntropyLoss()创建了一个交叉熵损失函数的实例用于计算分类任务中的损失。交叉熵损失函数通常用于多类别分类问题它将模型的输出与真实标签进行比较并计算出一个数值作为损失值用来衡量模型预测与真实标签之间的差异。 optim.SGD(net.parameters(), lr0.001, momentum0.9)创建了一个随机梯度下降SGD优化器的实例。 net.parameters()表示要优化的模型参数即神经网络中的权重和偏置。 lr0.001是学习率learning rate控制每次参数更新的步长大小。 momentum0.9表示动量momentum参数用于加速优化过程并避免陷入局部最优解。
四、训练网络并更新网络参数
t.set_num_threads(8) # 设置线程数为 8以加速训练过程。
for epoch in range(2): # 指定训练的轮数为 2 轮epoch即遍历整个数据集两次。running_loss 0.0 # 记录当前训练阶段的损失值for i, data in enumerate(trainloader, 0):# 输入数据inputs, labels data# 梯度清零optimizer.zero_grad() # 每个 batch 开始时将优化器的梯度缓存清零以避免梯度累积# forward backward outputs net(inputs)loss criterion(outputs, labels) # 进行前向传播然后计算损失函数 lossloss.backward() # 自动计算损失函数相对于模型参数的梯度# 更新参数 optimizer.step() # 使用优化器 optimizer 来更新模型的权重和偏置以最小化损失函数# 打印log信息# loss 是一个scalar,需要使用loss.item()来获取数值不能使用loss[0]running_loss loss.item()if i % 2000 1999: # 每2000个batch打印一下训练状态print([%d, %5d] loss: %.3f \% (epoch1, i1, running_loss / 2000))running_loss 0.0
print(Finished Training)输出结果
[1, 2000] loss: 2.247
[1, 4000] loss: 1.974
[1, 6000] loss: 1.753
[1, 8000] loss: 1.605
[1, 10000] loss: 1.527
[1, 12000] loss: 1.472
[2, 2000] loss: 1.424
[2, 4000] loss: 1.386
[2, 6000] loss: 1.331
[2, 8000] loss: 1.303
[2, 10000] loss: 1.300
[2, 12000] loss: 1.275
Finished Trainingenumerate函数
enumerate是Python内置函数之一用于将一个可迭代的对象如列表、元组、字符串等组合为一个索引序列。它返回一个枚举对象包含了原始对象中的元素以及对应的索引值。
enumerate函数的一般语法如下
enumerate(iterable, start0)其中iterable是要进行枚举的可迭代对象start是可选参数表示起始的索引值默认为0。
下面是一个简单的例子来说明enumerate函数的用法
fruits [apple, banana, cherry]
for index, fruit in enumerate(fruits):print(index, fruit)输出结果
0 apple
1 banana
2 cherry在上述示例中enumerate函数将列表fruits中的元素与对应的索引值配对然后通过for循环依次取出每个元素和索引值进行打印。
在机器学习或深度学习中enumerate函数常常与循环结合使用用于遍历数据集或批次数据并同时获取数据的索引值。这在模型训练过程中很有用可以方便地记录当前处理的数据的位置信息。
五、测试网络
部分数据集实际的label
dataiter iter(testloader)
images, labels next(dataiter) # 一个batch返回4张图片
print(实际的label: , .join(\%08s%classes[labels[j]] for j in range(4)))
show(tv.utils.make_grid(images1)/2).resize((400,100))输出结果
实际的label: cat ship ship plane部分数据集预测的label
# 计算图片在每个类别上的分数
outputs net(images)
# 得分最高的那个类
_, predicted t.max(outputs.data, 1)print(预测结果: , .join(%5s\% classes[predicted[j]] for j in range(4)))输出结果
预测结果: cat car ship plane整个测试集
correct 0 # 预测正确的图片数
total 0 # 总共的图片数# 使用 torch.no_grad() 上下文管理器表示在测试过程中不需要计算梯度以提高速度和节约内存
with t.no_grad():for data in testloader:images, labels dataoutputs net(images)_, predicted t.max(outputs, 1)total labels.size(0)correct (predicted labels).sum()print(10000张测试集中的准确率为: %d %% % (100 * correct / total))输出结果
10000张测试集中的准确率为: 54 %训练的准确率远比随机猜测(准确率10%)好。