news 2026/1/5 12:46:07

第P4周:猴痘病识别

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第P4周:猴痘病识别
  • 🍨本文为🔗365天深度学习训练营中的学习记录博客

  • 🍖原作者:K同学啊

目录

一、 前期准备

1. 设置GPU

2. 导入数据

3. 划分数据集

二、构建简单的CNN网络

三、 训练模型

1. 设置超参数

2. 编写训练函数

3. 编写测试函数

4. 正式训练

四、 结果可视化

1. Loss与Accuracy图

2. 指定图片进行预测

五、保存并加载模型

六、个人总结

一、 前期准备

1. 设置GPU

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

2. 导入数据

import os,PIL,random,pathlib data_dir = './4-data/' data_dir = pathlib.Path(data_dir) data_paths = list(data_dir.glob('*')) classeNames = [str(path).split("\\")[1] for path in data_paths] classeNames
total_datadir = './4-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

3. 划分数据集

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 train_size,test_size batch_size = 32 train_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网络

import torch.nn.functional as F class 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.pool = 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.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.pool(x) x = F.relu(self.bn4(self.conv4(x))) x = F.relu(self.bn5(self.conv5(x))) x = self.pool(x) x = x.view(-1, 24*50*50) x = self.fc1(x) return x device = "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与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

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) # 计算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

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')

四、 结果可视化

1. Loss与Accuracy图

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 #分辨率 from datetime import datetime current_time = datetime.now() # 获取当前时间 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.xlabel(current_time) # 打卡请带上时间戳,否则代码截图无效 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()

2. 指定图片进行预测

>>> x = torch.zeros(2, 1, 2, 1, 2) >>> x.size() torch.Size([2, 1, 2, 1, 2]) >>> y = torch.squeeze(x) >>> y.size() torch.Size([2, 2, 2]) >>> y = torch.squeeze(x, 0) >>> y.size() torch.Size([2, 1, 2, 1, 2]) >>> y = torch.squeeze(x, 1) >>> y.size() torch.Size([2, 2, 1, 2]) >>> x = torch.tensor([1, 2, 3, 4]) >>> torch.unsqueeze(x, 0) tensor([[ 1, 2, 3, 4]]) >>> torch.unsqueeze(x, 1) tensor([[ 1], [ 2], [ 3], [ 4]]) from PIL import Image classes = list(total_data.class_to_idx) def predict_one_image(image_path, model, transform, classes): test_img = Image.open(image_path).convert('RGB') # plt.imshow(test_img) # 展示预测的图片 test_img = transform(test_img) img = test_img.to(device).unsqueeze(0) model.eval() output = model(img) _,pred = torch.max(output,1) pred_class = classes[pred] print(f'预测结果是:{pred_class}') # 预测训练集中的某张照片 predict_one_image(image_path='./4-data/Monkeypox/M01_01_00.jpg', model=model, transform=train_transforms, classes=classes)

五、保存并加载模型

# 模型保存 PATH = './model.pth' # 保存的参数文件名 torch.save(model.state_dict(), PATH) # 将参数加载到model当中 model.load_state_dict(torch.load(PATH, map_location=device))

六、个人总结

上述模型存在两个主要问题:1.过拟合 ;2.训练集数量小

现对模型进行改进

total_datadir = './4-data/' train_transforms = transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.RandomRotation(15), transforms.ColorJitter( brightness=0.3, contrast=0.3, saturation=0.3 ), transforms.ToTensor(), transforms.Normalize( mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] ) ]) test_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 = datasets.ImageFolder(total_datadir,transform=train_transforms) total_data batch_size = 32 train_dl = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_dl = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=True) 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 num_classes = len(classeNames) model = models.resnet18(pretrained=True) # 冻结 backbone(小数据集关键) for param in model.parameters(): param.requires_grad = False # 替换分类头 model.fc = nn.Linear(model.fc.in_features, num_classes) model = model.to(device) print(model) def train(dataloader, model, loss_fn, optimizer): size = len(dataloader.dataset) num_batches = len(dataloader) 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) optimizer.zero_grad() loss.backward() optimizer.step() 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 loss_fn = nn.CrossEntropyLoss() learn_rate = 1e-4 opt = torch.optim.AdamW( model.fc.parameters(), lr=1e-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 #分辨率 from datetime import datetime current_time = datetime.now() # 获取当前时间 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.xlabel(current_time) # 打卡请带上时间戳,否则代码截图无效 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()

总结:正确率升高,误差减小。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/3 13:59:08

旅游景点推广利器:训练地域标志性景观AI生成模型吸引游客

旅游景点推广利器:训练地域标志性景观AI生成模型吸引游客 在短视频与社交媒体主导注意力的时代,一个景区能否“出圈”,往往取决于它是否拥有一张令人过目不忘的视觉名片。黄山云海、丽江古城夜景、平遥城墙雪霁——这些深入人心的画面&#…

作者头像 李华
网站建设 2026/1/3 13:55:15

隐私保护合规设计:GDPR等法规遵循的技术实现

隐私保护合规设计:GDPR等法规遵循的技术实现 在医疗影像系统中训练一个AI模型来增强CT图像的可视化效果,听起来是个不错的创新点。但如果这些数据涉及患者隐私,而你又不能把它们上传到云端进行训练——怎么办?这正是全球成千上万企…

作者头像 李华
网站建设 2026/1/3 13:54:38

掌握这5种技术,让你的C++网络模块性能提升10倍

第一章:C网络模块性能优化的背景与意义在现代高性能服务器和分布式系统中,C因其对底层资源的精细控制能力,成为构建高并发网络服务的首选语言。随着互联网业务规模的不断扩张,用户请求量呈指数级增长,传统的同步阻塞式…

作者头像 李华
网站建设 2026/1/3 13:54:34

手把手教学:使用lora-scripts在PyCharm中完成Stable Diffusion风格LoRA训练

使用 lora-scripts 在 PyCharm 中完成 Stable Diffusion 风格 LoRA 训练 在如今的生成式 AI 浪潮中,Stable Diffusion 已成为图像创作领域的核心工具。但面对“如何让模型学会我的艺术风格?”这一问题,大多数人会被复杂的微调流程劝退——直到…

作者头像 李华
网站建设 2026/1/3 13:52:38

C++物理引擎性能优化实战:如何将计算耗时降低90%(内部技术揭秘)

第一章:C物理引擎性能优化实战:从理论到实践在开发高性能的实时模拟系统或游戏时,C物理引擎的效率直接决定了整体体验的流畅性。面对复杂的碰撞检测、刚体动力学计算和约束求解,必须采用系统性的优化策略来降低CPU开销并提升帧率稳…

作者头像 李华
网站建设 2026/1/3 13:52:02

方剂配伍规律总结:人工智能辅助中医药研究

方剂配伍规律总结:人工智能辅助中医药研究 在智能技术席卷各行各业的今天,中医药这一传承千年的医学体系也正悄然经历一场静默而深刻的变革。过去依赖师徒口传心授的经验积累,如今正在被数据驱动的智能模型逐步解析与重构。尤其是中药方剂中“…

作者头像 李华