设计网站官网狗,wordpress特定用户特定分类,网页制作工具的选择,百度投诉中心在线申诉#x1f368; 本文为#x1f517;365天深度学习训练营 中的学习记录博客#x1f356; 原作者#xff1a;K同学啊 目标
1. 实现pytorch环境配置
2. 实现mnist手写数字识别
3. 自己写几个数字识别试试具体实现
#xff08;一#xff09;环境
语言环境#xff1a;Python… 本文为365天深度学习训练营 中的学习记录博客 原作者K同学啊 目标
1. 实现pytorch环境配置
2. 实现mnist手写数字识别
3. 自己写几个数字识别试试具体实现
一环境
语言环境Python 3.10 编 译 器: PyCharm 框 架:
二具体步骤
**1.**配置Pytorch环境
打开官网PyTorchGet started: 接下来是选择安装版本最难的就是确定Compute Platform的版本是否要使用GPU。所以先要确定CUDA的版本。 会发现pytorch官网根本没有对应12.7的版本先安装最新的试试呗选择12.4 安装命令pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124 安装完成我们建立python文件输入如下代码
import torch
x torch.rand(5, 3)
print(x) print(torch.cuda.is_available())---------output---------------
tensor([[0.3952, 0.6351, 0.3107],[0.8780, 0.6469, 0.6714],[0.4380, 0.0236, 0.5976],[0.4132, 0.9663, 0.7576],[0.4047, 0.4636, 0.2858]])
True从输出来看成功了。下面开始正式的mnist手写数字识别
2. 下载数据并加载数据
import torch
import torch.nn as nn
# import matplotlib.pyplot as plt
import torchvision # 第一步设置硬件设备有GPU就使用GPU没有就使用GPU
device torch.device(cuda if torch.cuda.is_available() else cpu)
print(device) # 第二步导入数据
# MNIST数据在torchvision.datasets中自带的可以通过代码在线下载数据。
train_ds torchvision.datasets.MNIST(root./data, # 下载的数据所存储的本地目录 trainTrue, # True为训练集False为测试集 transformtorchvision.transforms.ToTensor(), # 将下载的数据直接转换成张量格式 downloadTrue # True直接在线下载且下载到root指定的目录中,注意已经下载了第二次以后就不会再下载了 )
test_ds torchvision.datasets.MNIST(root./data, trainFalse, transformtorchvision.transforms.ToTensor(), downloadTrue ) # 第三步加载数据
# Pytorch使用torch.utils.data.DataLoader进行数据加载
batch_size 32
train_dl torch.utils.data.DataLoader(datasettrain_ds, # 要加载的数据集 batch_sizebatch_size, # 批次的大小 shuffleTrue, # 每个epoch重新排列数据 # 以下的参数有默认值可以不写 num_workers0, # 用于加载的子进程数默认值为0.注意在windows中如果设置非0有可能会报错 pin_memoryTrue, # True-数据加载器将在返回之前将张量复制到设备/CUDA 固定内存中。 如果数据元素是自定义类型或者collate_fn返回一个自定义类型的批次。 drop_lastFalse, #如果数据集大小不能被批次大小整除则设置为 True 以删除最后一个不完整的批次。 如果 False 并且数据集的大小不能被批大小整除则最后一批将保留。 默认值False timeout0, # 设置数据读取的超时时间 超过这个时间还没读取到数据的话就会报错。默认值0 worker_init_fnNone # 如果不是 None这将在步长之后和数据加载之前在每个工作子进程上调用并使用工作 id[0num_workers - 1] 中的一个 int的顺序逐个导入。默认None ) # 取一个批次看一下数据格式,数据的shape为[batch_size, channel, height, weight]
# batch_size是已经设定的32channel, height和weight分别是图片的通道数高度和宽度
images, labels next(iter(train_dl))
print(images.shape)看这个图片的shape是torch.size([32, 1, 28, 28])可以看图MNIST的数据集里的图像我猜应该是单色的channel1)28 * 28大小的图片height28, weight28)。 将图片可视化展示出来看看
# 数据可视化
plt.figure(figsize(20, 5)) # 指定图片大小 图像大小为20宽高5的绘图单位为英寸
for i , images in enumerate(images[:20]): # 维度缩减,npimg np.squeeze(images.numpy()) # 将整个figure分成2行10列绘制第i1个子图 plt.subplot(2, 10, i1) plt.imshow(npimg, cmapplt.cm.binary) plt.axis(off)
plt.show()**3.**构建CNN网络
num_classes 10 # MNIST数据集中是识别0-9这10个数字因此是10个类别。class Model(nn.Module):def __init__(self):super(Model, self).__init__()# 特征提取网络self.conv1 nn.Conv2d(1, 32, kernel_size3, padding1) # 第一层卷积卷积核大小3*3self.pool1 nn.MaxPool2d(2) # 池化层池化核大小为2*2self.conv2 nn.Conv2d(32, 64, kernel_size3, padding1) # 第二层卷积卷积核大小3*3self.pool2 nn.MaxPool2d(2)# 分类网络self.fc1 nn.Linear(1600, 64)self.fc2 nn.Linear(64, num_classes)def forward(self, x):x self.pool1(F.relu(self.conv1(x)))x self.pool2(F.relu(self.conv2(x)))x torch.flatten(x, start_dim1)x F.relu(self.fc1(x))x self.fc2(x)return x# 第四步加载并打印模型
# 将模型转移到GPU中
model Model().to(device)
summary(model))4.训练模型
# 第五步训练模型
loss_fn nn.CrossEntropyLoss() # 创建损失函数
learn_rate 1e-2 # 设置学习率
opt torch.optim.SGD(model.parameters(), lrlearn_rate) # 循环训练
def train(dataloader, model, loss_fn, optimizer): size len(dataloader.dataset) # 训练集的大小 num_batches len(dataloader) # 批次数目 train_loss, train_acc 0, 0 # 初始化训练损失率和正确率都为0 for X, y in dataloader: # 获取图片及标签 X, y X.to(device), y.to(device) # 将图片和标准转换到GPU中 # 计算预测误差 pred model(X) # 使用CNN网络预测输出pred loss loss_fn(pred, y) # 计算预测输出的pred和真实值y之间的差距 # 反向传播 optimizer.zero_grad() # grad属性归零 loss.backward() # 反向传播 optimizer.step() # 第一步自动更新 # 记录acc与loss train_acc (pred.argmax(1) y).type(torch.float).sum().item() train_loss loss.item() train_acc / size train_loss / num_batches return train_acc, train_loss # 测试函数,注意测试函数不需要进行梯度下降不进行网络权重更新所以不需要传入优化器
def test(dataloader, model, loss_fn): size len(dataloader.dataset) num_batches len(dataloader) test_loss, test_acc 0, 0 # 当不进行训练时停止梯度更新节省计算内存消耗 with torch.no_grad(): for imgs, targets in dataloader: imgs, target imgs.to(device), targets.to(device) # 计算 loss target_pred model(imgs) loss loss_fn(target_pred, target) test_loss loss.item() test_acc (target_pred.argmax(1) target).type(torch.float).sum().item() test_acc / size test_loss / num_batches return test_acc, test_loss # 正式训练
epochs 5
train_loss, train_acc, test_loss, test_acc [], [], [], [] for epoch in range(epochs): model.train() epoch_train_acc, epoch_train_loss train(train_dl, model, loss_fn, opt) model.eval() epoch_test_acc, epoch_test_loss test(test_dl, model, loss_fn) train_acc.append(epoch_train_acc) test_acc.append(epoch_test_acc) train_loss.append(epoch_train_loss) test_loss.append(epoch_test_loss) template Epoch: {:2d}, Train_acc:{:.1f}%, Train_loss: {:.3f}%, Test_acc: {:.1f}%, Test_loss: {:.3f}% print(template.format(epoch1, epoch_train_acc*100, epoch_train_loss, epoch_test_acc*100, epoch_test_loss))
print(Done)# 可见化一下训练结果
warnings.filterwarnings(ignore)
plt.rcParams[font.sans-serif] [SimHei] # 显示中文不标签不设置会显示中文乱码
plt.rcParams[axes.unicode_minus] False # 显示负号
plt.rcParams[figure.dpi] 100 # 分辨率 epochs_range range(epochs) plt.figure(figsize(12, 3))
plt.subplot(1, 2, 1) plt.plot(epochs_range, train_acc, label训练正确率)
plt.plot(epochs_range, test_acc, label测试正确率)
plt.legend(loclower right)
plt.title(训练与测试正确率) plt.subplot(1, 2, 2)
plt.plot(epochs_range, train_loss, label训练损失率)
plt.plot(epochs_range, test_loss, label测试损失率)
plt.legend(locupper right)
plt.title(训练与测试损失率) plt.show()四预测一下自己手写的数字
准备数据 再手动将每个数字切割成单独的一个文件 注意这里并没有将每个图片的大小切割成一致理论上切割成要求的28*28是最好。我这里用代码来重新生成28 * 28大小的图片。
import torch
import numpy as np
from PIL import Image
from torchvision import transforms
import torch.nn as nn
import torch.nn.functional as F
import matplotlib.pyplot as plt
import os, pathlib # 第一步设置硬件设备有GPU就使用GPU没有就使用GPU
device torch.device(cuda if torch.cuda.is_available() else cpu)
print(device) # 定义模型要把模型搞过来嘛不然加载模型会出错。
class Model(nn.Module): def __init__(self): super().__init__() # 特征提取网络 self.conv1 nn.Conv2d(1, 32, kernel_size3 ) # 第一层卷积卷积核大小3*3 self.pool1 nn.MaxPool2d(2) # 池化层池化核大小为2*2 self.conv2 nn.Conv2d(32, 64, kernel_size3) # 第二层卷积卷积核大小3*3 self.pool2 nn.MaxPool2d(2) # 分类网络 self.fc1 nn.Linear(1600, 64) self.fc2 nn.Linear(64, 10) def forward(self, x): x self.pool1(F.relu(self.conv1(x))) x self.pool2(F.relu(self.conv2(x))) x torch.flatten(x, start_dim1) x F.relu(self.fc1(x)) x self.fc2(x) return x # 加载模型
model torch.load(./models/cnn.pth)
model.eval() transform transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))
]) # 导入数据
data_dir ./mydata/handwrite
data_dir pathlib.Path(data_dir)
image_count len(list(data_dir.glob(*.jpg)))
print(图片总数量为, image_count) plt.rcParams[font.sans-serif] [SimHei] # 显示中文不标签不设置会显示中文乱码
plt.rcParams[axes.unicode_minus] False # 显示负号
plt.rcParams[figure.dpi] 100 # 分辨率
plt.figure(figsize(10, 10))
i 0
for input_file in list(data_dir.glob(*.jpg)): image Image.open(input_file) image_resize image.resize((28, 28)) # 将图片转换成 28*28 image image_resize.convert(L) # 转换成灰度图 image_array np.array(image) # print(image_array.shape) # (high, weight) image Image.fromarray(image_array) image transform(image) image torch.unsqueeze(image, 0) # 返回维度为1的张量 image image.to(device) output model(image) pred torch.argmax(output, dim1) image torch.squeeze(image, 0) # 返回一个张量其中删除了大小为1的输入的所有指定维度 image transforms.ToPILImage()(image) plt.subplot(10, 4, i1) plt.tight_layout() plt.imshow(image, cmapgray, interpolationnone) plt.title(实际值{}预测值{}.format(input_file.stem[:1], pred.item())) plt.xticks([]) plt.yticks([]) i 1
plt.show()准确性很低40张图片预测准确数量6,占比15.0%.。看图片感觉resize成28*28和转换成灰度图后图片本身已经失真比较严重了。先把图片像素翻转一下其实就是反色处理加上这段代码 准确率上了一个台阶40张图片预测准确数量30,占比75.0%.。但是看图片还是不清晰。
三总结
epochs5,预测的准确性达到97%如果增加迭代的次数到10准确性提升接近到99%。迭代20次则达到99.3提升不明显。 batch_size如何从32调整到64准确性差不太多 后续研究图片增强