深度学习pytorch实战第P3周--实现天气识别

>- **🍨 本文为[🔗365天深度学习训练营](https://mp.weixin.qq.com/s/0dvHCaOoFnW8SCp3JpzKxg) 中的学习记录博客**
>- **🍖 原作者:[K同学啊](https://mtyjkh.blog.csdn.net/)**

引言

1.复习上周

深度学习pytorch实战-第P2周-彩色图片识别icon-default.png?t=N7T8http://t.csdnimg.cn/f5l6F对于上周的学习,数据集是下载的

2.摆正心态

正如K同学所说,学到第三周左右就会有点感觉了,还真是这样,引领我入门,激发了我的兴趣,同时感谢同济子豪兄。

3.本机环境

见上文

4.学习目标

扎扎实实学好习,走好每一步。

一、前期准备

1.设置GPU

import torch
import torch.nn as nn
import torchvision.transforms as transforms
import torchvision
from torchvision import transforms, datasetsimport os,PIL,pathlib,randomdevice = torch.device("cuda" if torch.cuda.is_available() else "cpu")device

2.导入数据

data_dir = './weather_photos/'
print(data_dir)
data_dir = pathlib.Path(data_dir)data_paths = list(data_dir.glob('*'))
classeNames = [str(path).split("\\")[1] for path in data_paths]
classeNames
  • 第一步:使用pathlib.Path()函数将字符串类型的文件夹路径转换为pathlib.Path对象。
  • 第二步:使用glob()方法获取data_dir路径下的所有文件路径,并以列表形式存储在data_paths中。
  • 第三步:通过split()函数对data_paths中的每个文件路径执行分割操作,获得各个文件所属的类别名称,并存储在classeNames
  • 第四步:打印classeNames列表,显示每个文件所属的类别名称。

3.数据可视化

import matplotlib.pyplot as plt
from PIL import Image# 指定图像文件夹路径
image_folder = './weather_photos/cloudy/'# 获取文件夹中的所有图像文件
image_files = [f for f in os.listdir(image_folder) if f.endswith((".jpg", ".png", ".jpeg"))]# 创建Matplotlib图像
fig, axes = plt.subplots(3, 8, figsize=(16, 6))# 使用列表推导式加载和显示图像
for ax, img_file in zip(axes.flat, image_files):img_path = os.path.join(image_folder, img_file)img = Image.open(img_path)ax.imshow(img)ax.axis('off')# 显示图像
plt.tight_layout()
plt.show()

 

 图片大小处理

total_datadir = './data/'# 关于transforms.Compose的更多介绍可以参考:https://blog.csdn.net/qq_38251616/article/details/124878863
train_transforms = transforms.Compose([transforms.Resize([224, 224]),  # 将输入图片resize成统一尺寸transforms.ToTensor(),          # 将PIL Image或numpy.ndarray转换为tensor,并归一化到[0,1]之间transforms.Normalize(           # 标准化处理-->转换为标准正太分布(高斯分布),使模型更容易收敛mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # 其中 mean=[0.485,0.456,0.406]与std=[0.229,0.224,0.225] 从数据集中随机抽样计算得到的。
])total_data = datasets.ImageFolder(total_datadir,transform=train_transforms)
total_data

划分数据集(4:1)

train_size = int(0.8 * len(total_data))
test_size  = len(total_data) - train_size
train_dataset, test_dataset = torch.utils.data.random_split(total_data, [train_size, test_size])
train_dataset, test_dataset

 

batch_size = 32train_dl = torch.utils.data.DataLoader(train_dataset,batch_size=batch_size,shuffle=True,num_workers=1)
test_dl = torch.utils.data.DataLoader(test_dataset,batch_size=batch_size,shuffle=True,num_workers=1)
for X, y in test_dl:print("Shape of X [N, C, H, W]: ", X.shape)print("Shape of y: ", y.shape, y.dtype)break

 

二、构建简单的CNN网络

对于一般的CNN网络来说,都是由特征提取网络和分类网络构成,其中特征提取网络用于提取图片的特征,分类网络用于将图片进行分类

参数详解见上文。

import torch.nn.functional as Fclass Network_bn(nn.Module):def __init__(self):super(Network_bn, self).__init__()"""nn.Conv2d()函数:第一个参数(in_channels)是输入的channel数量第二个参数(out_channels)是输出的channel数量第三个参数(kernel_size)是卷积核大小第四个参数(stride)是步长,默认为1第五个参数(padding)是填充大小,默认为0"""self.conv1 = nn.Conv2d(in_channels=3, out_channels=12, kernel_size=5, stride=1, padding=0)self.bn1 = nn.BatchNorm2d(12)self.conv2 = nn.Conv2d(in_channels=12, out_channels=12, kernel_size=5, stride=1, padding=0)self.bn2 = nn.BatchNorm2d(12)self.pool1 = nn.MaxPool2d(2,2)self.conv4 = nn.Conv2d(in_channels=12, out_channels=24, kernel_size=5, stride=1, padding=0)self.bn4 = nn.BatchNorm2d(24)self.conv5 = nn.Conv2d(in_channels=24, out_channels=24, kernel_size=5, stride=1, padding=0)self.bn5 = nn.BatchNorm2d(24)self.pool2 = nn.MaxPool2d(2,2)self.fc1 = nn.Linear(24*50*50, len(classeNames))def forward(self, x):x = F.relu(self.bn1(self.conv1(x)))      x = F.relu(self.bn2(self.conv2(x)))     x = self.pool1(x)                        x = F.relu(self.bn4(self.conv4(x)))     x = F.relu(self.bn5(self.conv5(x)))  x = self.pool2(x)                        x = x.view(-1, 24*50*50)x = self.fc1(x)return xdevice = "cuda" if torch.cuda.is_available() else "cpu"
print("Using {} device".format(device))model = Network_bn().to(device)
model

三、训练模型

1.设置超参数

loss_fn    = nn.CrossEntropyLoss() # 创建损失函数
learn_rate = 1e-4 # 学习率
opt        = torch.optim.SGD(model.parameters(),lr=learn_rate)

2.编写训练函数

# 训练循环
def train(dataloader, model, loss_fn, optimizer):size = len(dataloader.dataset)  # 训练集的大小,一共60000张图片num_batches = len(dataloader)   # 批次数目,1875(60000/32)train_loss, train_acc = 0, 0  # 初始化训练损失和正确率for X, y in dataloader:  # 获取图片及其标签X, y = X.to(device), y.to(device)# 计算预测误差pred = model(X)          # 网络输出loss = loss_fn(pred, y)  # 计算网络输出和真实值之间的差距,targets为真实值,计算二者差值即为损失# 反向传播optimizer.zero_grad()  # grad属性归零loss.backward()        # 反向传播optimizer.step()       # 每一步自动更新# 记录acc与losstrain_acc  += (pred.argmax(1) == y).type(torch.float).sum().item()train_loss += loss.item()train_acc  /= sizetrain_loss /= num_batchesreturn train_acc, train_loss

 

3.编写测试函数

def test (dataloader, model, loss_fn):size        = len(dataloader.dataset)  # 测试集的大小,一共10000张图片num_batches = len(dataloader)          # 批次数目,313(10000/32=312.5,向上取整)test_loss, test_acc = 0, 0# 当不进行训练时,停止梯度更新,节省计算内存消耗with torch.no_grad():for imgs, target in dataloader:imgs, target = imgs.to(device), target.to(device)# 计算losstarget_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  /= sizetest_loss /= num_batchesreturn test_acc, test_loss

4.正式训练

epochs     = 20
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)train_loss.append(epoch_train_loss)test_acc.append(epoch_test_acc)test_loss.append(epoch_test_loss)template = ('Epoch:{:2d}, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%,Test_loss:{:.3f}')print(template.format(epoch+1, epoch_train_acc*100, epoch_train_loss, epoch_test_acc*100, epoch_test_loss))
print('Done')

 也不是伦茨越多越好

四、结果可视化

import matplotlib.pyplot as plt
#隐藏警告
import warnings
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='Training Accuracy')
plt.plot(epochs_range, test_acc, label='Test Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')plt.subplot(1, 2, 2)
plt.plot(epochs_range, train_loss, label='Training Loss')
plt.plot(epochs_range, test_loss, label='Test Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

五、保存模型并预测

# 1.保存模型# torch.save(model, 'model.pth') # 保存整个模型
torch.save(model.state_dict(), 'model_state_dict.pth') # 仅保存状态字典# 2. 加载模型 or 新建模型加载状态字典# model2 = torch.load('model.pth') 
# model2 = model2.to(device) # 理论上在哪里保存模型,加载模型也会优先在哪里,但是指定一下确保不会出错model2 = Network_bn().to(device) # 重新定义模型
model2.load_state_dict(torch.load('model_state_dict.pth')) # 加载状态字典到模型# 3.图片预处理
from PIL import Image
import torchvision.transforms as transforms# 输入图片预处理
def preprocess_image(image_path):image = Image.open(image_path)transform = transforms.Compose([transforms.Resize((224, 224)),  # 假设使用的是224x224的输入transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),])image = transform(image).unsqueeze(0)  # 增加一个批次维度return image# 4.预测函数(指定路径)
def predict(image_path, model):model.eval()  # 将模型设置为评估模式with torch.no_grad():  # 关闭梯度计算image = preprocess_image(image_path)image = image.to(device)  # 确保图片在正确的设备上outputs = model(image)_, predicted = torch.max(outputs, 1)  # 获取最可能的预测类别return predicted.item()# 5.预测并输出结果
image_path = "./weather_photos/shine/shine101.jpg"  # 替换为你的图片路径
prediction = predict(image_path, model)
class_names = ["cloudy", "rain", "shine", "sunrise"]  # Replace with your class labels
predicted_label = class_names[prediction]
print("Predicted class:", predicted_label)

 

Predicted class: shine
# 选取dataloader中的一个图像进行判断
import numpy as np
# 选取图像
imgs,labels = next(iter(train_dl))
image,label = imgs[0],labels[0]# 选取指定图像并展示
# 调整维度为 [224, 224, 3]
image_to_show = image.numpy().transpose((1, 2, 0))# 归一化
mean = np.array([0.485, 0.456, 0.406])
std = np.array([0.229, 0.224, 0.225])
image_to_show = std * image_to_show + mean
image_to_show = np.clip(image_to_show, 0, 1)# 显示图像
plt.imshow(image_to_show)
plt.show()# 将图像转移到模型所在的设备上(如果使用GPU)
image = image.to(device)# 预测
with torch.no_grad():output = model(image.unsqueeze(0))  # 添加批次维度# 输出预测结果
_, predicted = torch.max(output, 1)
class_names = ["cloudy", "rain", "shine", "sunrise"]  # Replace with your class labels
predicted_label = class_names[predicted]
print(f"Predicted: {predicted.item()}, Actual: {label.item()}")

 如何保存模型可以看这篇icon-default.png?t=N7T8http://t.csdnimg.cn/yCkr7

六,总结

构建数据集中

此次数据集不是直接从网上下载的,而是保存在本地的,那么我们构建数据集的代码就有3步了,第一步就是从我们的本地获取数据集,使用pathlib将路径转化为pathlib.path对象,使用glob方法获取路径下的所有文件路径并保存到datapath,通过spilt分割路径并保存在classname中,打印classname列表。这是在确保路径文件夹正确,且分类正确。接下来可以使用matplotlib.pyplot和PIL来获取图片,并可视化,过程中使用列表推导式加载和显示图像,第二步划分数据集,4:1比例划分并保存为dataset对象,第三步定义batch_size大小,使用dataloder加载器来管理数据,

构建cnn网络中

主要是特征提取网络和分类网络的构建,首先进行一个网络初始化init,定义网络结构,卷积层1,bn层1,(nn.BatchNorm2d(12) 是 PyTorch 中的一个批量归一化层。批量归一化用于加速神经网络的训练过程,并提高模型的泛化能力。在卷积神经网络中),卷积2,bn2,池化1,卷积4,bn层4,卷积5,bn层5,池化层2,全连接层1,然后定义进行前向传播结构,并在每一层(卷积+bn)进行relu函数返回给x,然后再池化,再relu,最后拉平,使用view函数,并传给fc层进行分类。

训练模型中

设置超参数,loss一般用交叉熵,学习率一般0.0001,opt采用sgd或者adam

编写训练函数中

编写训练函数时候,要使用size知道dataloaer加载的dataset大小长度,每batchnum就是dataloder的长度,定义训练集损失和准确率,获取图片和标签从dataloder中,计算误差,进行啊反向传播更新参数,每一步自动更新,记录acc和loss,最后计算train的acc和loss

编写测试函数同理

同理,再取图像之前加个当不进行训练时,停止梯度更新就行

来到了正式训练

定义epoch轮次,训练和特使的acc和loss定义,便于后续存储,轮次循环,model.train和model.eval,然后把每一批次的准确率loss都存在列表里,最后输出

最后可视化

定义plt窗口,可视化列表train_acc等等

保存模型

参上,现在我还有点不懂,慢慢学吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/620398.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初识集合框架

前言~🥳🎉🎉🎉 hellohello~,大家好💕💕,这里是E绵绵呀✋✋ ,如果觉得这篇文章还不错的话还请点赞❤️❤️收藏💞 💞 关注💥&#x1f…

贝叶斯公式中的先验概率、后验概率、似然概率

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。关…

mysql的下载、安装

首先进入官网:MySQL 点击“downloads”进入下载界面 2.往下滑动滚轮,点击“mysql community...(公开版)” 3.往下滑,找到并单击“install for Windows” 4.选择版本:初学者可以使用较低版本,较…

API网关工具Kong或nginx ingress实现对客户端IP的白名单限制,提高对外服务的访问安全

一、背景 部署在生产环境的应用,供内部服务调用外,还需要暴露外网访问。 比如consul ui管理界面,我们需要给到开发和测试人员,观察服务的注册情况。 再比如前端页面和后端接口在一起的服务,后端接口供内部服务接口调用…

项目文章 | Nature Commun细菌转录因子ChIP-seq揭示第二信使2‘,3‘-cGMP的新调控机制

转录因子是细菌中调控基因表达的关键蛋白质,它们能够识别并结合到DNA的特定序列上,从而启动或抑制基因的转录。细菌ChIP-seq可以帮助我们理解细菌中转录因子的调控网络,揭示其在细菌生长、代谢和适应环境等方面的作用。这种技术对于研究细菌的…

2024第十五届蓝桥杯 JAVA B组

目录 前言:试题 A: 报数游戏试题 B: 类斐波那契循环数试题C:分布式队列 前言: 没参加这次蓝桥杯算法赛,十四届蓝桥杯被狂虐,对算法又爱又恨,爱我会做的题,痛恨我连题都读不懂的题😭,十四届填空只…

龙蜥社区「人人都可以参与开源」——开源之路心得体会

在龙蜥社区的开源活动中,我深刻体会到了开源精神的伟大与力量。作为一个新手,一开始我对于如何参与开源活动感到有些迷茫,但通过龙蜥社区的引导和帮助,我找到了自己的方向,走上了开源之路。 龙蜥社区的开源活动是真正…

docker run启动一个开发备忘清单速查表 —— 筑梦之路

docker run -itd --name reference -p 3000:3000 registry.cn-beijing.aliyuncs.com/deanmr/reference:latest包含:运维,前端,后端,工具,命令,数据库 部分截图展示:

每天五分钟深度学习:逻辑回归算法的损失函数和代价函数是什么?

本文重点 前面已经学习了逻辑回归的假设函数,训练出模型的关键就是学习出参数w和b,要想学习出这两个参数,此时需要最小化逻辑回归的代价函数才可以训练出w和b。那么本节课我们将学习逻辑回归算法的代价函数是什么? 为什么不能平方差损失函数 线性回归的代价函数我们使用…

【嵌入式】交叉编译指南:将开源软件带到嵌入式世界

🧑 作者简介:阿里巴巴嵌入式技术专家,深耕嵌入式人工智能领域,具备多年的嵌入式硬件产品研发管理经验。 📒 博客介绍:分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

公众号文章的制作方法和步骤分享,纯干货!

无论是个人还是企业,都需要通过公众号来传递自己的声音和价值。如何制作一篇高质量的公众号文章呢?本文伯乐网络传媒将详细介绍公众号文章的制作方法和步骤。 一、文章类型概述 1. 图文教程:以图文结合的方式,向读者传授知识和技…

P1712 [NOI2016] 区间(线段树 + 贪心 + 双指针)

题目描述 在数轴上有 n 个闭区间从 1 至 n 编号,第 i 个闭区间为 [li​,ri​] 。 现在要从中选出 m 个区间,使得这 m 个区间共同包含至少一个位置。换句话说,就是使得存在一个 x ,使得对于每一个被选中的区间 [li​,ri​]&#…