使用Dropout大幅优化PyTorch模型,实现图像识别

news2025/2/23 13:34:09

大家好,在机器学习模型中,如果模型的参数太多,而训练样本又太少,训练出来的模型很容易产生过拟合的现象。在训练神经网络时,过拟合具体表现在模型训练数据损失函数较小,预测准确率较高,但是在测试数据上损失函数比较大,预测准确率较低。Dropout可以比较有效的缓解过拟合的发生,在一定程度上达到正则化的效果。

1.机器学习中的Dropout正则化

Dropout正则化是机器学习领域中一种有效的技术,通过随机丢弃神经网络中的某些单元,实现对多个不同网络架构的并行训练。

这种方法对于减少模型在训练过程中的过拟合现象非常关键,有助于提升模型的泛化能力。

图片

深度网络

2.在PyTorch模型中集成Dropout

要在PyTorch模型中加入Dropout正则化,可以使用torch.nn.Dropout类来实现。这个类需要一个Dropout率作为输入参数,表示神经元被关闭的可能性,这可以应用于任何非输出层。

self.dropout = nn.Dropout(0.25)

3.观察Dropout对模型性能的影响

为了研究Dropout的效果,这里将训练一个用于图像分类的模型。最初,训练一个经过正则化的网络,然后是一个没有Dropout正则化的网络。两个模型都将在Cifar-10数据集上训练8个周期。

步骤1:首先,将导入需要实现网络的依赖项和库。

import torch
from torch import nn
from torch import optim
from torch.nn import functional as F
import torchvision
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

import matplotlib.pyplot as plt
import numpy as np

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)

步骤2:将加载数据集并准备数据加载器。

BATCH_SIZE = 32

transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

trainset = torchvision.datasets.CIFAR10(root="./data", train=True,
                                        download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=BATCH_SIZE,
                                          shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root="./data", train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=BATCH_SIZE,
                                         shuffle=False, num_workers=2)

CLASS_NAMES = ("plane", "car", "bird", "cat",
               "deer", "dog", "frog", "horse", "ship", "truck")

步骤3:加载并可视化一些数据

def show_batch(image_batch, label_batch):
    plt.figure(figsize=(10,10))
    for n in range(25):
        ax = plt.subplot(5,5,n+1)
        img = image_batch[n] / 2 + 0.5     # 取消归一化
        img = img.numpy()
        plt.imshow(np.transpose(img, (1, 2, 0)))
        plt.title(CLASS_NAMES[label_batch[n]])
        plt.axis("off")
sample_images, sample_labels = next(iter(trainloader))
show_batch(sample_images, sample_labels)

输出:

图片

步骤4:在Dropout正则化中实现网络

class Net(nn.Module):
    def __init__(self, input_shape=(3,32,32)):
        super(Net, self).__init__()
        
        self.conv1 = nn.Conv2d(3, 32, 3)
        self.conv2 = nn.Conv2d(32, 64, 3)
        self.conv3 = nn.Conv2d(64, 128, 3)
        
        self.pool = nn.MaxPool2d(2,2)
        
        n_size = self._get_conv_output(input_shape)
        
        self.fc1 = nn.Linear(n_size, 512)
        self.fc2 = nn.Linear(512, 10)
        
        self.dropout = nn.Dropout(0.25)
        
    def _get_conv_output(self, shape):
        batch_size = 1
        input = torch.autograd.Variable(torch.rand(batch_size, *shape))
        output_feat = self._forward_features(input)
        n_size = output_feat.data.view(batch_size, -1).size(1)
        return n_size
    
    def _forward_features(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = self.pool(F.relu(self.conv3(x)))
        return x
      
    def forward(self, x):
        x = self._forward_features(x)
        x = x.view(x.size(0), -1)
        x = self.dropout(x)
        x = F.relu(self.fc1(x))
        x = self.dropout(x)
        x = self.fc2(x)
        return x

步骤5:实现训练

def train(model, device, train_loader, optimizer, criterion, epoch, steps_per_epoch=20):
    # 将模型切换到训练模式。这对于像dropout、batchnorm等在训练和评估模式下表现不同的层是必要的
    model.train()

    train_loss = 0
    train_total = 0
    train_correct = 0

    # 我们循环遍历数据迭代器,并将输入数据提供给网络并调整权重。
    for batch_idx, (data, target) in enumerate(train_loader, start=0):
        
        # 从训练数据集中加载输入特征和标签
        data, target = data.to(device), target.to(device)
        
        # 将所有可学习权重参数的梯度重置为0
        optimizer.zero_grad()
        
        # 前向传播:传递训练数据集中的图像数据,预测图像所属的类别(在本例中为0-9)
        output = model(data)
        
        # 定义我们的损失函数,并计算损失
        loss = criterion(output, target)
        train_loss += loss.item()

        scores, predictions = torch.max(output.data, 1)
        train_total += target.size(0)
        train_correct += int(sum(predictions == target))
            
        # 将所有可学习权重参数的梯度重置为0
        optimizer.zero_grad()

        # 反向传播:计算损失相对于模型参数的梯度
        loss.backward()
        
        # 更新神经网络权重
        optimizer.step()

    acc = round((train_correct / train_total) * 100, 2)
    print("Epoch [{}], Loss: {}, Accuracy: {}".format(epoch, train_loss/train_total, acc), end="")

步骤6:实现测试函数

def test(model, device, test_loader, criterion, classes):
    # 将模型切换到评估模式。这对于像dropout、batchnorm等在训练和评估模式下表现不同的层是必要的
    model.eval()

    test_loss = 0
    test_total = 0
    test_correct = 0

    example_images = []
    with torch.no_grad():
        for data, target in test_loader:
            # 从测试数据集中加载输入特征和标签
            data, target = data.to(device), target.to(device)
            
            # 进行预测:传递测试数据集中的图像数据,预测图像所属的类别(在本例中为0-9)
            output = model(data)
            
            # 计算损失,累加批次损失
            test_loss += criterion(output, target).item()
            
            scores, predictions = torch.max(output.data, 1)
            test_total += target.size(0)
            test_correct += int(sum(predictions == target))

    acc = round((test_correct / test_total) * 100, 2)
    print("Test_loss: {}, Test_accuracy: {}".format(test_loss/test_total, acc))

步骤7:初始化网络的损失和优化器

net = Net().to(device)
print(net)

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters())

输出:

Net(
  (conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1))
  (conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1))
  (conv3): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1))
  (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (fc1): Linear(in_features=512, out_features=512, bias=True)
  (fc2): Linear(in_features=512, out_features=10, bias=True)
  (dropout): Dropout(p=0.25, inplace=False)
)

步骤8:开始训练

for epoch in range(8):
    train(net, device, trainloader, optimizer, criterion, epoch)
    test(net, device, testloader, criterion, CLASS_NAMES)

print("Finished Training")

输出:

Epoch [0], Loss: 0.0461193907892704, Accuracy: 45.45 Test_loss: 0.036131812924146654, Test_accuracy: 58.58
Epoch [1], Loss: 0.03446852257728577, Accuracy: 60.85 Test_loss: 0.03089196290373802, Test_accuracy: 65.27
Epoch [2], Loss: 0.029333480607271194, Accuracy: 66.83 Test_loss: 0.027052838513255118, Test_accuracy: 70.41
Epoch [3], Loss: 0.02650276515007019, Accuracy: 70.21 Test_loss: 0.02630699208676815, Test_accuracy: 70.99
Epoch [4], Loss: 0.024451716771125794, Accuracy: 72.41 Test_loss: 0.024404651895165445, Test_accuracy: 73.03
Epoch [5], Loss: 0.022718262011408807, Accuracy: 74.35 Test_loss: 0.023125074282288553, Test_accuracy: 74.86
Epoch [6], Loss: 0.021408387248516084, Accuracy: 75.76 Test_loss: 0.023151200053095816, Test_accuracy: 74.43
Epoch [7], Loss: 0.02033562403023243, Accuracy: 76.91 Test_loss: 0.023537022879719736, Test_accuracy: 73.93
Finished Training

4.没有Dropout正则化的网络

在这里将构建相同的网络,但是没有dropout层。在相同的数据集和周期数上训练网络,并评估Dropout对网络性能的影响,使用相同的训练和测试函数。

步骤1:实现网络

class Net(nn.Module):
    def __init__(self, input_shape=(3,32,32)):
        super(Net, self).__init__()
        
        self.conv1 = nn.Conv2d(3, 32, 3)
        self.conv2 = nn.Conv2d(32, 64, 3)
        self.conv3 = nn.Conv2d(64, 128, 3)
        
        self.pool = nn.MaxPool2d(2,2)
        
        n_size = self._get_conv_output(input_shape)
        
        self.fc1 = nn.Linear(n_size, 512)
        self.fc2 = nn.Linear(512, 10)
        
    def _get_conv_output(self, shape):
        batch_size = 1
        input = torch.autograd.Variable(torch.rand(batch_size, *shape))
        output_feat = self._forward_features(input)
        n_size = output_feat.data.view(batch_size, -1).size(1)
        return n_size
    
    def _forward_features(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = self.pool(F.relu(self.conv3(x)))
        return x
      
    def forward(self, x):
        x = self._forward_features(x)
        x = x.view(x.size(0), -1)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

步骤2:损失和优化器

net = Net().to(device)
print(net)

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters())

输出:

Net(
  (conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1))
  (conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1))
  (conv3): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1))
  (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (fc1): Linear(in_features=512, out_features=512, bias=True)
  (fc2): Linear(in_features=512, out_features=10, bias=True)
)

步骤3:开始训练

for epoch in range(8):
    train(net, device, trainloader, optimizer, criterion, epoch)
    test(net, device, testloader, criterion, CLASS_NAMES)

print("Finished Training")

输出:

Epoch [0], Loss: 0.04425342482566833, Accuracy: 48.29 Test_loss: 0.03506121407747269, Test_accuracy: 59.93
Epoch [1], Loss: 0.0317487561249733, Accuracy: 63.97 Test_loss: 0.029791217082738877, Test_accuracy: 66.4
Epoch [2], Loss: 0.026000032302737237, Accuracy: 70.83 Test_loss: 0.027046055325865747, Test_accuracy: 69.97
Epoch [3], Loss: 0.022179243130385877, Accuracy: 75.11 Test_loss: 0.02481114484965801, Test_accuracy: 72.95
Epoch [4], Loss: 0.01933788091301918, Accuracy: 78.26 Test_loss: 0.024382170912623406, Test_accuracy: 73.55
Epoch [5], Loss: 0.016771901984512807, Accuracy: 81.04 Test_loss: 0.024696413831412793, Test_accuracy: 73.53
Epoch [6], Loss: 0.014588635778725148, Accuracy: 83.41 Test_loss: 0.025593858751654625, Test_accuracy: 73.94
Epoch [7], Loss: 0.01255791916936636, Accuracy: 85.94 Test_loss: 0.026889967443048952, Test_accuracy: 73.69
Finished Training

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

gc.log中 CMS-concurrent-abortable-preclean

问题 在gc日志中看到 2024-06-26T16:16:07.5040800: 64690272.666: [CMS-concurrent-abortable-preclean-start]CMS: abort preclean due to time 2024-06-26T16:16:12.5530800: 64690277.716: [CMS-concurrent-abortable-preclean: 1.052/5.049 secs] [Times: user1.33 sys0…

点云处理实战 PCL求解点云表面曲率

目录 一、什么是曲率 二、曲率计算过程 三、pcl 求解点云局部曲率 四、思考?为何曲率计算会使用协方差矩阵? 五、推荐阅读 一、什么是曲率 曲率是几何学中用来描述曲线或曲面形状变化的一个量。它反映了曲线或曲面的弯曲程度。在不同的上下文中,曲率的定义和计算方式有…

C语言 指针——向函数传递字符串

目录 向函数传递字符串 计算实际字符个数 用字符数组编程实现字符串复制 用字符指针编程实现字符串复制 关于程序的效率的几点建议 向函数传递字符串 向函数传递字符串时  既可用 字符数组 作函数参数  也可用 字符指针 作函数参数 Simulating Call by reference &…

第二期书生·浦语大模型实战营优秀项目一览

书生浦语社区于 2023 年年底正式推出了书生浦语大模型实战营系列活动,至今已有两期五批次同学参加大模型学习、实战,线上课程累计学习超过 10 万人次。 实战营特设项目实践环节,提供 A100 算力支持,鼓励学员动手开发。第 2 期实战…

51单片机STC89C52RC——9.1 DS1302涓流充电计时芯片

目录 目的/效果 一,STC单片机模块 二,DS1302计时器 2.1 特性/板子位置 2.1.1 特性 2.1.2 板子上的位置 2.2 针脚定义 2.3 数据传输 2.3.1 读数据 2.3.2 写数据 2.4 BCD码 2.5 可编程涓流充电器 2.6 时钟动态设置 三,创建Keil项目…

算法导论 总结索引 | 第四部分 第十六章:贪心算法

1、求解最优化问题的算法 通常需要经过一系列的步骤,在每个步骤都面临多种选择。对于许多最优化问题,使用动态规划算法求最优解有些杀鸡用牛刀了,可以使用更简单、更高效的算法 贪心算法(greedy algorithm)就是这样的算…

云服务器部署LNMP Web环境教程合集(多版linux系统安装方法)

LNMP环境包括Linux、Nginx、MySQL和PHP,Nginx是一款小巧而高效的Web服务器软件,使用阿里云服务器搭建LNMP Web网站环境很简单,支持多种LNMP环境部署教程,可使用ROS模板部署、LNMP镜像以及基于不同Linux操作系统手动部署LNMP全流程…

华为仓颉编程语言正式发布!相比Java、Go、Swift优势在哪?附入门教程~

在2024年6月21日举行的华为开发者大会上,华为公司不仅对外宣布了其新一代鸿蒙操作系统HarmonyOS NEXT,还正式发布了他们自主研发的编程语言,名为仓颉。 我们一起看看仓颉编程语言的定位及其优势所在,以及它的入门教程&#x1f4aa…

Scania斯堪尼亚SHL题库综合能力性格测试真题题型解析及面试经验

一、走进Scania斯堪尼亚 Scania是一家成立于1891年的瑞典公司,专注于重型卡车和巴士的制造,以其模块化系统和环保设计闻名。作为全球领先的运输解决方案提供商,Scania不仅提供高质量的车辆,还提供相关服务和融资解决方案。公司秉…

大模型课程资料-全网最火29套全栈大模型项目实践

29套AI全栈大模型项目实战,人工智能视频课程-多模态大模型,微调技术训练营,大模型多场景实战,AI图像处理,AI量化投资,OPenCV视觉处理,机器学习,Pytorch深度学习,推荐系统…

国际现货黄金最新价格如何分析?结合较高的时间周期

国际现货黄金投资是一种24小时交易的品种,这意味着,在交易日我们打开电脑图表,分析完走势之后就有机会做交易了。但问题也出在这里,如果对国际现货黄金最新价格把握不住,分析和交易就无从谈起了,下面我们就…

【SkiaSharp绘图11】SKCanvas属性详解

文章目录 SKCanvas构造SKCanvas构造光栅 Surface构造GPU Surface构造PDF文档构造XPS文档构造SVG文档SKNoDrawCanvas 变换剪裁和状态构造函数相关属性DeviceClipBounds获取裁切边界(设备坐标系)ClipRect修改裁切区域IsClipEmpty当前裁切区域是否为空IsClipRect裁切区域是否为矩形…

2023: 芒种集•序言

2023: 芒种集•序言 2023: 芒种集•序言 从西南旅游回来,一直忙着整理游记“2024:追寻红色足迹”,之后又应初建平索要刘桂蓉遗作“我们一起走过”,于是把“别了,老屋”和诗作“二月”一并合编,把我写的悼念…

线性代数基础概念:矩阵

目录 线性代数基础概念:矩阵 1. 矩阵的定义 2. 矩阵的运算 3. 矩阵的特殊类型 4. 矩阵的秩 5. 矩阵的初等变换 6. 矩阵的特征值与特征向量 7. 矩阵的应用 8. 矩阵总结 总结 线性代数基础概念:矩阵 矩阵是线性代数中的另一个重要概念&#xff0…

数据结构——

1. 什么是并查集? 在计算机科学中,并查集(英文:Disjoint-set data structure,直译为不数据结构交集)是一种数据结构,用于处理一些不交集(Disjoint sets,一系列没有重复元…

使用 position:absolute; 定位的元素在ios上被遮盖

在ios上一个元素使用position:absolute;定位后,被其它元素遮盖 在使用absolute的元素上加一行代码 -webkit-transform: translate3d(0, 0, 0);

【YashanDB知识库】YAS-00103 no free block in dictionary cache

【问题分类】功能使用 【关键字】YAS-00103,no free block in dictionary cache 【问题描述】执行union all 太多子查询导致报错,例子如下: 【问题原因分析】 选择增大DICTIONARY_CACHE_SIZE 或 SHARE_POOL_SIZE 或 两者都增大 【解决/规…

杭州代理记账报税全程托管专业实力全面指南

杭州代理记税报税服务可以为企业提供全程托管财务管理解决方案,确保企业的财务工作专业、高效、合规。以下是杭州代理记税报税服务全面指南: https://www.9733.cn/news/detail/185.html 一、代理记账报税服务的内容 基础服务: 每日记&#xf…

使用supportFragmentManager管理多个fragment切换

android studio创建的项目就没有一个简单点的框架,生成的代码都是繁琐而复杂,并且不实用。 国内的页面一般都是TAB页面的比较多,老外更喜欢侧边菜单。 如果我们使用一个activity来创建程序,来用占位符管理多个fragment切换&…

Android性能分析工具-Perfetto基本使用

文章目录 一、Perfetto介绍二、抓取方法2.1 手机端直接抓取2.1.1 打开系统跟踪2.1.2 开始录制 2.2 使用 adb 抓取2.3 通过 Perfetto 网页自定义抓取 三、trace分析方法3.1 打开trace文件3.2 查看方法 一、Perfetto介绍 Perfetto 是一个用于性能检测和跟踪分析的生产级开源堆栈。…