温州网站建设哪家公司好,外贸用什么网站开发客户,wordpress每篇文章怎么加关键词,游戏开发培训班Pytorch从零开始实战——天气识别
本系列来源于365天深度学习训练营
原作者K同学 文章目录 Pytorch从零开始实战——天气识别环境准备数据集模型选择模型训练数据可视化总结 环境准备
本文基于Jupyter notebook#xff0c;使用Python3.8#xff0c;Pytorch2.0.1cu118使用Python3.8Pytorch2.0.1cu118torchvision0.15.2需读者自行配置好环境且有一些深度学习理论基础。 第一步导入常用包。
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import torchvision
import torch.nn.functional as F
import torchvision.transforms as transforms
import random
import time
import numpy as np
import pandas as pd
import datetime
import gc
import pathlib
import os
import PIL
os.environ[KMP_DUPLICATE_LIB_OK]True # 用于避免jupyter环境突然关闭
torch.backends.cudnn.benchmarkTrue # 用于加速GPU运算的代码创建设备对象。
device torch.device(cuda if torch.cuda.is_available() else cpu)
device # device(typecuda)设置随机数种子
torch.manual_seed(428)
torch.cuda.manual_seed(428)
torch.cuda.manual_seed_all(428)
random.seed(428)
np.random.seed(428)数据集
本次实验使用的天气图片数据集共有1127张天气图片分别存在’cloudy’, ‘sunrise’, ‘shine’, rain’四个文件夹中其中文件夹名代表类别。数据集获取可联系K同学。 导入数据集。 根据自己数据集存放的路径转换为pathlib.Path对象然后获取路径下的所有文件路径使用字符串分割函数获取文件名也就是类别名。
data_dir ./data/weather_photos
data_dir pathlib.Path(data_dir) # 转换为pathlib.Path对象data_paths list(data_dir.glob(*)) # 获取data_dir路径下的所有文件路径
data_paths # data/weather_photos/xxxx
classNames [str(path).split(/)[2] for path in data_paths]
classNames # [cloudy, sunrise, shine, rain]对数据集进行预处理。调整到相同的尺寸转换为张量对象并进行标准化处理。使用torchvision.datasets.ImageFolder函数读取数据集并且使用文件名当做数据集的标签。
total_dir ./data/weather_photos
train_transforms transforms.Compose([transforms.Resize([224, 224]), # 调整相同的尺寸transforms.ToTensor(),transforms.Normalize( # 标准化处理--转换为标准正太分布mean[0.485, 0.456, 0.406],std[0.229, 0.224, 0.225])
])
total_data torchvision.datasets.ImageFolder(total_dir, transformtrain_transforms) # 通过total_dir下的子文件夹当做标签
total_data我们根据8:2划分训练集和测试集。
# 划分数据集
train_size int(0.8 * len(total_data))
test_size len(total_data) - train_size
train_ds, test_ds torch.utils.data.random_split(total_data, [train_size, test_size])
len(train_ds), len(test_ds) # (901, 226)又是前面几篇出现的函数随机查看五张图片。
def plotsample(data):fig, axs plt.subplots(1, 5, figsize(10, 10)) #建立子图for i in range(5):num random.randint(0, len(data) - 1) #首先选取随机数随机选取五次#抽取数据中对应的图像对象make_grid函数可将任意格式的图像的通道数升为3而不改变图像原始的数据#而展示图像用的imshow函数最常见的输入格式也是3通道npimg torchvision.utils.make_grid(data[num][0]).numpy()nplabel data[num][1] #提取标签 #将图像由(3, weight, height)转化为(weight, height, 3)并放入imshow函数中读取axs[i].imshow(np.transpose(npimg, (1, 2, 0))) axs[i].set_title(nplabel) #给每个子图加上标签axs[i].axis(off) #消除每个子图的坐标轴plotsample(train_ds)使用DataLoder将它按照batch_size批量划分并将数据集顺序打乱。
batch_size 32
train_dl torch.utils.data.DataLoader(train_ds, batch_sizebatch_size, shuffleTrue)
test_dl torch.utils.data.DataLoader(test_ds, batch_sizebatch_size, shuffleTrue)
for X, y in test_dl:print(X.shape) # 32, 3, 224, 224print(y) # 3 0 2 0 3 2 0 0 2 1....break模型选择
本文使用卷积神经网络大致流程是卷积-卷积-池化-卷积-卷积-池化-线性层并进行数据归一化处理本文选用的卷积核大小为5 * 5。
class Model(nn.Module):def __init__(self):super(Model, self).__init__()self.conv1 nn.Conv2d(3, 12, kernel_size5, stride1, padding0)self.bn1 nn.BatchNorm2d(12)self.conv2 nn.Conv2d(12, 12, kernel_size5, stride1, padding0)self.bn2 nn.BatchNorm2d(12)self.pool2 nn.MaxPool2d(2, 2)self.conv3 nn.Conv2d(12, 24, kernel_size5, stride1, padding0)self.bn3 nn.BatchNorm2d(24)self.conv4 nn.Conv2d(24, 24, kernel_size5, stride1, padding0)self.bn4 nn.BatchNorm2d(24)self.pool4 nn.MaxPool2d(2, 2)self.fc1 nn.Linear(24 * 50 * 50, len(classNames))def forward(self, x):x F.relu(self.bn1(self.conv1(x)))x F.relu(self.bn2(self.conv2(x)))x self.pool2(x)x F.relu(self.bn3(self.conv3(x)))x F.relu(self.bn4(self.conv4(x)))x self.pool4(x)x x.view(-1, 24 * 50 * 50)x self.fc1(x)return x使用summary展示模型架构。
from torchsummary import summary
# 将模型转移到GPU中
model Model().to(device)
summary(model, input_size(3, 224, 224))模型训练
定义超参数本次选择的学习率为0.0001经实验最初设置为0.01效果并不是很好。
loss_fn nn.CrossEntropyLoss()
learn_rate 0.0001
opt torch.optim.SGD(model.parameters(), lrlearn_rate)训练函数。
def train(dataloader, model, loss_fn, opt):size len(dataloader.dataset)num_batches len(dataloader)train_acc, train_loss 0, 0for X, y in dataloader:X, y X.to(device), y.to(device)pred model(X)loss loss_fn(pred, y)opt.zero_grad()loss.backward()opt.step()train_acc (pred.argmax(1) y).type(torch.float).sum().item()train_loss loss.item()train_acc / sizetrain_loss / num_batchesreturn train_acc, train_loss测试函数。
def test(dataloader, model, loss_fn):size len(dataloader.dataset)num_batches len(dataloader)test_acc, test_loss 0, 0with torch.no_grad():for X, y in dataloader:X, y X.to(device), y.to(device)pred model(X)loss loss_fn(pred, y)test_acc (pred.argmax(1) y).type(torch.float).sum().item()test_loss loss.item()test_acc / sizetest_loss / num_batchesreturn test_acc, test_loss开始训练训练20轮在测试集准确率达到94.7%还是很不错的。
import time
epochs 20
train_loss []
train_acc []
test_loss []
test_acc []T1 time.time()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)print(epoch:%d, train_acc:%.1f%%, train_loss:%.3f, test_acc:%.1f%%, test_loss:%.3f% (epoch 1, epoch_train_acc * 100, epoch_train_loss, epoch_test_acc * 100, epoch_test_loss))
print(Done)
T2 time.time()
print(程序运行时间:%s毫秒 % ((T2 - T1)*1000))数据可视化
使用matplotlib进行训练数据、测试数据的可视化。
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, labelTraining Accuracy)
plt.plot(epochs_range, test_acc, labelTest Accuracy)
plt.legend(loclower right)
plt.title(Training and Validation Accuracy)plt.subplot(1, 2, 2)
plt.plot(epochs_range, train_loss, labelTraining Loss)
plt.plot(epochs_range, test_loss, labelTest Loss)
plt.legend(locupper right)
plt.title(Training and Validation Loss)
plt.show()总结
经过几次实验发现三个问题 1.经过实验将学习率从0.01改为0.0001模型效果会好很多。 2.有的时候每轮epoch准确率一直为百分之20多可能是模型陷入局部最小值或鞍点所以后续可以引入提前停止。 3.无脑的增加层数并不会使模型效果变好。