深度学习-AlexNet(第一个深度卷积网络)

news2024/12/27 12:21:14

文章目录

  • 简介
  • 数据集
  • 模型搭建
  • 模型训练
  • 模型测试

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。

简介


AlexNet是第一个深度卷积网络模型,赢得了2012年ImageNet图像分类竞赛的冠军,自98年的LeNet后再次将深度学习研究引热,创造性的提出了很多方法且影响至今,如使用GPU进行训练,使用ReLU 作为非线性激活函数,使用 Dropout 防止过拟合,使用数据增强来提高模型准确率等。

Krizhevsky A, Sutskever I, Hinton G E, 2012. ImageNet classification with deep convolutional neural networks[C]//Advances in Neural Information Processing Systems 25. 1106-1114.

AlexNet模型结构如下:
在这里插入图片描述
包括5个卷积层、3个全连接层。分别部署在2个GPU上,这里写在一起即可。

  • 卷积层1
    输入RGB三通道,即3×224×224的图像;
    使用96个大小为11×11的卷积核,步长4,填充2;
    输出96×55×55特征;
    ReLu激活;
    最大池化,核大小3×3,步长2(重叠池化);
    输出96×27×27特征;

  • 卷积层2
    输入特征图大小96×27×27;
    使用256个大小为5×5的卷积核,步长1,填充2;
    输出256×27×27特征;
    ReLu激活;
    最大池化,核大小3×3,步长2(重叠池化);
    输出256×13×13特征;

  • 卷积层3
    输入特征图大小256×13×13;
    使用384个大小为3×3的卷积核,步长1,填充1;
    输出384×13×13特征;
    ReLu激活;

  • 卷积层4
    输入特征图大小384×13×13;
    使用384个大小为3×3的卷积核,步长1,填充1;
    输出384×13×13特征;
    ReLu激活;

  • 卷积层5
    输入特征图大小384×13×13;
    使用256个大小为3×3的卷积核,步长1,填充1;
    输出256×13×13特征;
    ReLu激活;
    最大池化,核大小3×3,步长2(重叠池化);
    输出256×6×6特征;

  • 全连接层1
    Droupout随机置0;
    输入25666,输出4096;
    ReLu激活;

  • 全连接层2
    Droupout随机置0;
    输入4096,输出4096;
    ReLu激活;

  • 全连接层1
    输入4096,输出分类数;

数据集


由于ImageNet数据集太大且不提供测试集的标签,这里使用torchversion封装的OxfordIIITPet数据集,包含猫狗共37类,每类约200张图片,共800M左右。

官网https://www.robots.ox.ac.uk/~vgg/data/pets/

在这里插入图片描述

由于该数据集尺寸不同,同一缩放为256×256大小,然后采用10剪切,裁出10张224×224大小。

import torch
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
import torchvision

pet_train = torchvision.datasets.OxfordIIITPet(root='./datasets/', download=True,
                                               transform=transforms.Resize((256, 256)))
pet_test = torchvision.datasets.OxfordIIITPet(root='./datasets/', split='test', download=True,
                                              transform=transforms.Resize((256, 256)))
print('训练/测试集大小:', len(pet_train), len(pet_test))
img, label = pet_train[0]
print('原图像大小和标签:', img.size, label)

tenCrop = transforms.TenCrop(224, vertical_flip=False)  # 上下左右中心,然后镜像共10张
img = tenCrop(img)
print('剪切后个数:', len(img))
print('剪切后图像大小:', img[0].size)

toTensor = transforms.ToTensor()  # 转为10个tensor
tensor_list = []
for i in range(len(img)):
    tensor_list.append(toTensor(img[i]))
img_tensor = torch.stack(tensor_list)
print(img_tensor.shape)

writer = SummaryWriter(log_dir='runs/pet')  # 可视化
writer.add_images(tag='train', img_tensor=img_tensor)
writer.close()

在这里插入图片描述

在这里插入图片描述

模型搭建


可以使用直接调用torchvision.models.AlexNet创建一个AlexNet模型。
以下是自定义模型,调整了一些细节,更贴近原文:

class AlexNet(nn.Module):
    def __init__(self, num_classes: int = 1000, dropout: float = 0.5) -> None:
        super().__init__()
        self.features = nn.Sequential(  # (-1,3,224,224)
            nn.Conv2d(in_channels=3, out_channels=96, kernel_size=11, stride=4, padding=2),
            nn.ReLU(inplace=True),  # (-1,96,55,55)
            nn.MaxPool2d(kernel_size=3, stride=2),  # (-1,96,27,27)
            nn.Conv2d(in_channels=96, out_channels=256, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),  # (-1,256,27,27)
            nn.MaxPool2d(kernel_size=3, stride=2),  # (-1,256,13,13)
            nn.Conv2d(in_channels=256, out_channels=384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),  # (-1,384,13,13)
            nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),  # (-1,384,13,13)
            nn.Conv2d(in_channels=384, out_channels=256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),  # (-1,256,13,13)
            nn.MaxPool2d(kernel_size=3, stride=2),  # (-1,256,6,6)
        )
        self.classifier = nn.Sequential(
            nn.Dropout(p=dropout),
            nn.Linear(256 * 6 * 6, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(p=dropout),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Linear(4096, num_classes)
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x = self.features(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x

插播反爬信息 )博主CSDN地址:https://wzlodq.blog.csdn.net/

模型训练


import torch
import torchvision
from torch import nn
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms


class AlexNet(nn.Module):
    def __init__(self, num_classes: int = 1000, dropout: float = 0.5) -> None:
        super().__init__()
        self.features = nn.Sequential(  # (-1,3,224,224)
            nn.Conv2d(in_channels=3, out_channels=96, kernel_size=11, stride=4, padding=2),
            nn.ReLU(inplace=True),  # (-1,96,55,55)
            nn.MaxPool2d(kernel_size=3, stride=2),  # (-1,96,27,27)
            nn.Conv2d(in_channels=96, out_channels=256, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),  # (-1,256,27,27)
            nn.MaxPool2d(kernel_size=3, stride=2),  # (-1,256,13,13)
            nn.Conv2d(in_channels=256, out_channels=384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),  # (-1,384,13,13)
            nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),  # (-1,384,13,13)
            nn.Conv2d(in_channels=384, out_channels=256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),  # (-1,256,13,13)
            nn.MaxPool2d(kernel_size=3, stride=2),  # (-1,256,6,6)
        )
        self.classifier = nn.Sequential(
            nn.Dropout(p=dropout),
            nn.Linear(256 * 6 * 6, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(p=dropout),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Linear(4096, num_classes)
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x = self.features(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x


# 创建模型
alexNet = AlexNet()
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
alexNet = alexNet.to(device)  # 若支持GPU加速
# 损失函数
loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.to(device)
# 优化器
learning_rate = 1e-2
optimizer = torch.optim.Adam(alexNet.parameters(), lr=learning_rate)
total_train_step = 0  # 总训练次数
total_test_step = 0  # 总测试次数
epoch = 10  # 训练轮数
writer = SummaryWriter(log_dir='runs/AlexNet')  # 可视化
# 数据
pet_train = torchvision.datasets.OxfordIIITPet(root='./datasets/', download=True,
                                               transform=transforms.Resize((256, 256)))

tenCrop = transforms.TenCrop(224, vertical_flip=False)  # 上下左右中心,然后镜像共10张
toTensor = transforms.ToTensor()  # 转为tensor
# 训练模型
for i in range(epoch):
    print("-----第{}轮训练开始-----".format(i + 1))
    loss_sum = 0
    alexNet.train()  # 训练模式
    for img, label in pet_train:
        img = tenCrop(img)  # 10剪切
        img_list, label_list = [], []  # 合为一个tensor
        for j in range(len(img)):
            img_list.append(toTensor(img[j]))
            label_list.append(label)
        imgs = torch.stack(img_list)
        labels = torch.tensor(label_list)
        imgs = imgs.to(device)  # 若GPU加速
        labels = labels.to(device)
        outputs = alexNet(imgs)  # 预测
        loss = loss_fn(outputs, labels)  # 计算损失
        optimizer.zero_grad()  # 清空之前梯度
        loss.backward()  # 反向传播
        optimizer.step()  # 更新参数
        total_train_step += 1  # 更新步数
        loss_sum += loss.item()
    writer.add_scalar("train_loss", loss_sum, total_train_step)
    torch.save(alexNet.state_dict(), "alexnet_{}.pkl".format(i))  # 保存模型
    # alexNet.load_state_dict(torch.load("alexnet_{}.pkl".format(i)))  # 加载模型
writer.close()

在这里插入图片描述

模型测试


import torch
import torchvision
from torch import nn
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms


class AlexNet(nn.Module):
    def __init__(self, num_classes: int = 1000, dropout: float = 0.5) -> None:
        super().__init__()
        self.features = nn.Sequential(  # (-1,3,224,224)
            nn.Conv2d(in_channels=3, out_channels=96, kernel_size=11, stride=4, padding=2),
            nn.ReLU(inplace=True),  # (-1,96,55,55)
            nn.MaxPool2d(kernel_size=3, stride=2),  # (-1,96,27,27)
            nn.Conv2d(in_channels=96, out_channels=256, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),  # (-1,256,27,27)
            nn.MaxPool2d(kernel_size=3, stride=2),  # (-1,256,13,13)
            nn.Conv2d(in_channels=256, out_channels=384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),  # (-1,384,13,13)
            nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),  # (-1,384,13,13)
            nn.Conv2d(in_channels=384, out_channels=256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),  # (-1,256,13,13)
            nn.MaxPool2d(kernel_size=3, stride=2),  # (-1,256,6,6)
        )
        self.classifier = nn.Sequential(
            nn.Dropout(p=dropout),
            nn.Linear(256 * 6 * 6, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(p=dropout),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Linear(4096, num_classes)
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x = self.features(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x


device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
epoch = 10  # 轮数
writer = SummaryWriter(log_dir='runs/AlexNet')  # 可视化
# 数据
pet_test = torchvision.datasets.OxfordIIITPet(root='./datasets/', split='test', download=True,
                                              transform=transforms.Resize((256, 256)))
tenCrop = transforms.TenCrop(224, vertical_flip=False)  # 上下左右中心,然后镜像共10张
toTensor = transforms.ToTensor()  # 转为tensor
# 损失函数
loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.to(device)
# 训练模型
for i in range(epoch):
    print("-----第{}个模型测试开始-----".format(i + 1))
    total_test_loss = 0  # 当前轮次模型测试所得损失
    total_accuracy = 0  # 当前轮次精确率
    alexNet = AlexNet()
    alexNet.load_state_dict(torch.load("alexnet_{}.pkl".format(i)))  # 加载模型
    for img, label in pet_test:
        img = tenCrop(img)  # 10剪切
        img_list, label_list = [], []  # 合为一个tensor
        for j in range(len(img)):
            img_list.append(toTensor(img[j]))
            label_list.append(label)
        imgs = torch.stack(img_list)
        labels = torch.tensor(label_list)
        imgs = imgs.to(device)  # 若GPU加速
        labels = labels.to(device)
        outputs = alexNet(imgs)  # 预测
        loss = loss_fn(outputs, labels)
        total_test_loss = total_test_loss + loss.item()
        accuracy = (outputs.argmax(1) == labels).sum()
        total_accuracy = total_accuracy + accuracy
    writer.add_scalar("test_loss", total_test_loss, i+1)
    writer.add_scalar("test_accuracy", total_accuracy / (10*len(pet_test)), i+1)
writer.close()

在这里插入图片描述
在这里插入图片描述

实际测试效果并不是很好,但是如果用ImageNet那样的大数据集,可能得跑很久,应该还是数据()的问题吧,强行压缩为256×256后10剪切,势必有损失和添加黑边等。

原创不易,请勿转载本不富裕的访问量雪上加霜
博主首页:https://wzlodq.blog.csdn.net/
来都来了,不评论两句吗👀
如果文章对你有帮助,记得一键三连❤

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

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

相关文章

Java项目:springboot销售团队后台管理系统

作者主页:源码空间站2022 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 该项目为后管系统,主要功能包括: 看板、业务机会管理、客户管理、联系人管理、我的日报、团队日报、主数据管理&#x…

【Linux】进程间通信之共享内存

目录🌈前言🌸1、System V共享内存🍡1.1、概念🍢1.2、原理🌺2、共享内存相关函数和指令🍡2.1、shmget函数(创建)🍢2.2、shmctl函数(控制)&#x1f…

TCP 的重传机制、选择确认、缓存与流量控制、连接管理、拥塞控制(计算机网络-运输层)

目录 TCP 的重传机制 TCP 的选择确认 TCP 的缓存与流量控制 TCP 的连接管理 TCP的拥塞控制 TCP 的重传机制 TCP 每发送一个报文段就设置一个超时计时器; TCP 使用指数加权移动平均算法计算 RTT 及其偏差的估计值,并据此计算超时重传时间&#xff1b…

8 NP完全性理论

8 NP完全性理论 p问题 NP问题 NP完全问题 NPC(complete ) NP难问题NP-hard p问题 是一类能够用**(确定的)算法**在多项式时间内求解的可判定问题 ●这种问题类型也称为多项式类型 NP问题 是一类能够用不确定算法在多项式时间内求解的可判定问题 在确定性计算模型下多项式时…

程序员高手解决问题,都是从正确的提问开始

回顾各大技术网站、社区、问答,我们发现:真正的程序员高手都极度擅长提问。 好的提问不但能得到建设性的解决方案,更加能激发人们的好奇心、创造力和学习的动力。 毫不夸张地说,会提问的程序员一开口就赢了! 所以今…

HashMap源码剖析(下)——java集合

系列文章目录 文章目录系列文章目录前言一、 回顾总结二、HashMap数据插入流程JDK1.8 HashMap的put方法源码如下:2.1 扩容机制2.2 链表树化2.3 红黑树转链三、查找总结四、删除五、遍历前言 既上一节内容 本节内容是,HashMap还有基本的数据功能;存储、删…

(三)GNSS定位中的定位系统和误差源

翻看了一下记录,离上一次GNSS内容的更新已经过去9个月了。时间过的太快,硕士生涯已经过去一半,有遗憾也有收获,过去的9个月经历了各种喜怒哀乐以及迷茫。永远相信美好的事情即将发生,GO LONG CHINA! 今天写…

魅族大会公布未来多项规划!全场景门店、旗舰新品明年将落地

如果说中国手机行业中哪个品牌的粉丝忠诚度最高,那恐怕魅族说第二,也没几家敢说第一。这些年来,虽然魅族手机经历风风雨雨,但依然有着非常庞大的粉丝基础。前不久刚刚结束的魅友大会2022大会现场人潮涌动,随着天南海北…

Linux系统下的常用查找指令及用法

find指令&#xff1a;将从指定目录向下递归地遍历其各个子目录&#xff0c;将满足条件的文件或者目录显示在终端&#xff0c; 语法&#xff1a;find[搜索范围][选项] 方式作用-name<查询方式>按照指定的文件名查找模式查找文件-user<用户名>查找属于指定用户名所有…

Java项目:springboot教务管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 1.系统默认超级管理员账号为admin&#xff0c;默认密码为123456 系统配置&#xff1a;用户管理、角色管理、权限管理 默认已配置好基本数据&…

4.3.2、分类编址的 IPv4 地址

分类编址的 IPv4 地址分为 A、B、C、D、E 五类 A 类地址的网络号部分占 888 比特&#xff0c;主机号部分占 242424 比特。网络号的最高位固定为 000B 类地址的网络号部分占 161616 比特&#xff0c;主机号部分占 161616 比特。网络号的最高两位固定为 101010C 类地址的网络号部…

Reason: CORS request did not succeed 浏览器

放上我的错误&#xff1a; 一定要坚信他给你的提提示&#xff01;&#xff01;&#xff01;一定要怀疑是浏览器的设置 因为我试过网上的两种方法&#xff0c;均无效 法一&#xff1a;将Access-Control-Allow-Origin设置为&#xff1a;* 法二&#xff1a;因为我使用的是vue3&…

深度学习——转置卷积(笔记)

1.卷积层和汇聚层通常会减少下采样输入图像的空间维度&#xff08;高和宽&#xff09;&#xff0c;语义分割对输入进行像素级别的输出&#xff0c;但是卷积会不断减小高宽&#xff0c;不利于像素级别的输出。通过转置卷积能增大输入的高和宽 2.具体操作&#xff1a;步幅为1没有…

uni-app整包更新与热更新方案(安卓和IOS)

原文链接&#xff1a;uni-app整包更新与热更新方案(安卓和IOS) 效果预览 大致效果&#xff1a; 打开App&#xff0c;进入首页&#xff08;首次&#xff09;&#xff0c;检测线上是否存在新版本&#xff0c;如果存在&#xff0c;弹窗提示用户是否进行版本更新。Android 有热更新…

VMware17虚拟机安装及Linux系统搭建(详细版)

✅作者简介&#xff1a;大家好&#xff0c;我是小杨 &#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; &#x1f4dc;前言&#xff1a; VMware是一个虚拟PC的软件&#xff0c;可以在现有的操作系统上虚…

虚拟机最小化方式安装Centos7后,ping和ifconfig都不可用解决方法

我用的是台式机&#xff0c;主机连接的是网线&#xff0c;在以最小化方式安装Centos7后&#xff0c;ping和ifconfig不可用。这里要记住&#xff0c;vm虚拟机使用网络适配器是&#xff1a;NAT 模式(N): 用于共享主机的 IP 地址 问题&#xff1a; ifconfig command not found p…

QT基本组件与常用类

目录 一、设计师 Designer&#xff08;掌握&#xff09; 二、布局 Layout 2.1 布局的基本使用&#xff08;掌握&#xff09; 2.2 布局属性&#xff08;掌握&#xff09; 2.3 伸展器&#xff08;掌握&#xff09; 2.4 嵌套&#xff08;掌握&#xff09; 2.5 伸展与策略&#xff…

【C语言进阶】想用好C++?那就一定要掌握动态内存管理

目录 &#x1f929;前言&#x1f929;&#xff1a; 一、动态内存概述⚔️&#xff1a; 1.什么是动态内存&#xff1a; 2.动态内存分配的意义&#xff1a; 二、常用的动态内存函数&#x1f3f9;&#xff1a; 1. malloc 和 free函数&#xff1a; ①. malloc 函数&#xff1a; …

基于PSO粒子群优化的带时间窗VRPTW问题matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 粒子群优化算法(PSO)是一种进化计算技术(evolutionary computation)&#xff0c;1995 年由Eberhart 博士和kennedy 博士提出&#xff0c;源于对鸟群捕食的行为研究 。该算法最初是受到飞鸟集群活…

数据结构初阶:树与二叉树(1)——堆

许久没发博客&#xff0c;在这里跟各位看客道声久等了~ 冬至已至&#xff0c;各位有没有吃上热乎的饺子呢 下面给各位奉上承载着满满干货的饺子吧&#xff1a; 目录 一、树 1. 树的结构定义 2. 树的相关概念 3. 树的表示 孩子兄弟表示法 二、二叉树 1. 二叉树的结构定义 2. 特…