网站优化和网站推广,做一套网站开发多少钱,wordpress mysql 分表,成都建设网站公司哪家好手把手教你从零开始实现一个基于Pytorch的卷积神经网络CNN#xff08;新手适用#xff09;一#xff1a; model.py#xff1a;创建模块-CSDN博客 从零开始实现一个基于Pytorch的卷积神经网络 - 知乎
目录
1 设备device定义
2 训练模型定义
3 开始训练
3.1 step、batch…手把手教你从零开始实现一个基于Pytorch的卷积神经网络CNN新手适用一 model.py创建模块-CSDN博客 从零开始实现一个基于Pytorch的卷积神经网络 - 知乎
目录
1 设备device定义
2 训练模型定义
3 开始训练
3.1 step、batchsize和数据集中图片数的关系
3.2 关于类型转换
4 保存模型
5 训练过程可视化
5.1 损失
5.1.1 损失的计算 5.1.2 平均损失的计算
5.2 准确率
5.2.1 准确率计算
5.2.2 平均准确率计算 6. train.py完整代码
7. 训练结果 1 设备device定义
通过torch.device()来指定使用的设备device然后通过.to()方法将模型和数据放到指定的设备上这样我们就可以通过定义device来指定是在cpu还是显卡上进行训练了而且在多显卡的情况下也可以指定使用其中的某一张显卡进行训练。
torch.cuda.is_available()可以判断本设备是否支持CUDA如果支持就返回True不支持就返回False。这个函数可以让其自动判断是否支持CUDA加速并自动选择设备。
device torch.device(cuda:0 if torch.cuda.is_available() else cpu)
model.to(device)
2 训练模型定义
初始化和导入模型定义超参数、数据集和DataLoader定义损失函数loss function和优化器optimizer启用梯度torch.set_grad_enabled(True)
代码如下其中的具体解释可看知乎原文。
# 训练数据
import torch
import torchvision
import torch.nn as nn
import torch.utils.data as Data# 1. 导入模型文件并且定义
from model import LeNet
model LeNet()
# 2. 定义参数轮数批次和学习率
Epoch 5
batch_size 64
lr 0.001
# 3. 获取训练数据
train_data torchvision.datasets.MNIST(root./data,trainTrue,transformtorchvision.transforms.ToTensor(),downloadFalse)
#定义train data的数据集
train_loader Data.DataLoader(train_data, batch_sizebatch_size, shuffleTrue, num_workers0, drop_lastTrue)
# 4. 定义损失函数、优化器
loss_function nn.CrossEntropyLoss()
optimizer torch.optim.Adam(model.parameters(), lrlr)
# 5. 梯度计算
torch.set_grad_enabled(True)
#启用Batch Normalization层和Dropout层
model.train() model.train()方法该方法用于启用Batch Normalization层和Dropout层。虽然模型中并没有这两层但是我们不妨将其加上并作为一个习惯以免在真正需要时忘记。 3 开始训练
1) 获得DataLoader中的数据x和标签y
2) 将优化器的梯度清零
3) 将数据送入模型中获得预测的结果y_pred
4) 将标签和预测结果送入损失函数获得损失
5) 将损失值反向传播
6) 使用优化器对模型的参数进行更新
# 训练
for epoch in range(Epoch):for step,data in enumerate(train_data):# 取出data中的数据和标签x,ydata# 优化器梯度清零optimizer.zero_grad()# 计算预测值y_pred model(x.to(device,torch.float))# 计算损失loss loss_function(y_pred, y.to(device, torch.long))# 梯度更新loss.backward()# 优化器更新模型参数optimizer.step()
3.1 step、batchsize和数据集中图片数的关系 一个 epoch 表示将训练数据集中的所有样本都用于训练一次。步数steps表示在一个 epoch 中所执行的批次数量。 step的计算方法将总样本数除以批次大小。 我们在前面定义的batchsize是64且丢弃最后一批手写数字数据集中有6万张图片60000/64937.5故每个epoch中有step937。 3.2 关于类型转换
# 计算预测值y_pred model(x.to(device,torch.float))# 计算损失loss loss_function(y_pred, y.to(device, torch.long))
两行中都涉及到了类型转换。在深度学习中通常希望输入数据和模型参数的数据类型是一致的这样可以避免类型不匹配的错误并且可以更有效地利用硬件加速器如 GPU进行计算。
第一行把y_pred输入数据转换为 torch.float 类型的目的是确保模型接收到的数据类型与模型参数的数据类型匹配。在很多情况下神经网络模型的参数通常是浮点数类型float因此将输入数据转换为 torch.float 类型可以确保与模型参数的类型匹配。 在深度学习中通常使用整数类型如 torch.long来表示类别标签或离散值。许多损失函数例如交叉熵损失函数在计算损失时需要模型输出的预测值和真实标签值具有相同的数据类型。 4 保存模型
把模型的定义和参数全保存在一个文件中后面可以直接使用训练好的权重文件。
torch.save(model, ./LeNet.pkl) 5 训练过程可视化
查看训练过程中的损失和准确率等等过程参数。
可以在每隔一定的step后输出当前损失和准确率的平均值。MNIST的训练集共有六万张图像而我们的batch_size是64且丢弃最后一批因此在每个Epoch中有937个step实际训练59968张图像。可以每迭代100次后输出当前Epoch的损失和准确率的平均值并输出当前处在哪一次Epoch和step。
5.1 损失
5.1.1 损失的计算
对每次计算产生的损失进行相加把结果放在running_loss中因此我们需要在反向传播后添加一个累加操作。由于loss在我们之前定义的设备上因此我们需要获得loss的值然后将其传回cpu并转换为float类型即 # 计算损失loss loss_function(y_pred, y.to(device, torch.long))# 梯度更新loss.backward()# 累加梯度running_loss float(loss.data.cpu()) 5.1.2 平均损失的计算
如果当前step是100次则计算一次平均损失。由于step从0开始所以需要1.
loss_avg running_loss / (step 1)
5.2 准确率
5.2.1 准确率计算 acc 预测正确的数目 / 总数目 y_pred是一个二维的张量其形状为[batch_size, num_classes]在这边channel是10即十个数字。如果我们将batch中的任意一行提取出来就获得了一个10维的向量向量里的每个数代表与其下标所对应的标签的相关性相关性越大则代表越有可能是这个数字。 因此我们需要获得这个向量中最大数的下标在pytorch中我们可以用.argmax(dim)方法实现输入维度dim即可返回这个维度下最大值的下标即pred y_pred.argmax(dim1)。在此基础上我们就可以计算其预测正确的数量了
先获取pred的值即模型预测的图片的类别然后传回cpu用筛选模型预测的标签和图片标注的标签相等的个数然后使用.sum相加统计预测正确的个数。
acc保存的即是模型预测正确的个数。
acc (pred.data.cpu()y.data).sum() 5.2.2 平均准确率计算
接下来先对steps进行统计设置每轮数中的每100个steps计算一次平均损失、准确率等。
平均损失值 损失值 / steps
平均准确率 预测正确的个数 / 总个数 # 判断该step是不是该epoch中的第100步if step%10099:# 平均损失 损失值/stepsloss_avg running_loss / (step1)# 平均准确率 预测正确的数量/总个数acc_avg float(acc / ((step 1) * batch_size))# 输出print(Epoch, epoch 1, ,step, step 1, | Loss_avg: %.4f % loss_avg, |Acc_avg:%.4f % acc_avg) 6. train.py完整代码
# 训练数据
import torch
import torchvision
import torch.nn as nn
import torch.utils.data as Data
# 导入模型文件并且定义
from model import LeNetmodel LeNet()
# 定义参数轮数批次和学习率
Epoch 5
batch_size 64
lr 0.001# 获取训练数据
train_data torchvision.datasets.MNIST(root./data,trainTrue,transformtorchvision.transforms.ToTensor(),downloadFalse)
#定义train data的数据集
train_loader Data.DataLoader(train_data, batch_sizebatch_size, shuffleTrue, num_workers0, drop_lastTrue)
# 定义损失函数、优化器
loss_function nn.CrossEntropyLoss()
optimizer torch.optim.Adam(model.parameters(), lrlr)
#梯度计算
torch.set_grad_enabled(True)
#启用Batch Normalization层和Dropout层
model.train()
device torch.device(cuda:0 if torch.cuda.is_available() else cpu)
model.to(device)# 训练
for epoch in range(Epoch):# 定义损失值和准确率running_loss 0.0acc 0.0for step,data in enumerate(train_loader):# 取出data中的数据和标签x为数据y为标签x,ydata# 优化器梯度清零optimizer.zero_grad()# 计算预测值y_pred model(x.to(device,torch.float))# 计算损失loss loss_function(y_pred, y.to(device, torch.long))# 梯度更新loss.backward()# 累加梯度running_loss float(loss.data.cpu())# 取出预测的最大值pred y_pred.argmax(dim1)# 统计预测正确的个数acc (pred.data.cpu()y.data).sum()# 优化器更新模型参数optimizer.step()# 判断该step是不是该epoch中的第100步if step%10099:# 平均损失 损失值/stepsloss_avg running_loss / (step1)# 平均准确率 预测正确的数量/总个数acc_avg float(acc / ((step 1) * batch_size))# 输出print(Epoch, epoch 1, ,step, step 1, | Loss_avg: %.4f % loss_avg, |Acc_avg:%.4f % acc_avg)# 保存模型
torch.save(model, ./LeNet.pkl) 7. 训练结果
可以看到loss呈下降趋势acc提升。