看完这篇我就不信还有人不懂卷积神经网络!

news2024/11/18 0:13:08

看完这篇我就不信还有人不懂卷积神经网络!

前言

在深度学习大🔥的当下,我知道介绍卷积神经网络的文章已经在全网泛滥,但我还是想要写出一点和别人不一样的东西,尽管要讲的知识翻来覆去还是那么一些,但我想尽可能做到极其通俗易懂,只要稍微有点计算机和线性代数基础的同学都能看懂。

水平有限,但凡有错误或理解不到位的地方,欢迎各位大佬指出🙏

什么是神经网络?

在介绍卷积神经网络之前,我们先回顾一下神经网络的基本知识📖。就目前而言,神经网络是深度学习算法的核心,我们所熟知的很多深度学习算法的背后其实都是神经网络。神经网络由节点层组成,通常包含一个输入层、一个或多个隐藏层和一个输出层,我们所说的几层神经网络通常指的是隐藏层的个数,因为输入层和输出层通常是固定的。节点之间相互连接并具有相关的权重和阈值。如果节点的输出高于指定的阈值,则激活该节点并将数据发送到网络的下一层。否则,没有数据被传递到网络的下一层。关于节点激活的过程有没有觉得非常相似?没错,这其实就是生物的神经元产生神经冲动的过程的模拟。

image.png

神经网络类型多样,适用于不同的应用场景。例如,循环神经网络(RNN)通常用于自然语言处理和语音识别,而卷积神经网络(ConvNetsCNN)则常用于分类和计算机视觉任务。在 CNN 产生之前,识别图像中的对象需要手动的特征提取方法。现在,卷积神经网络为图像分类和对象识别任务提供了一种更具可扩展性的方法,它利用线性代数的原理,特别是矩阵乘法,来识别图像中的模式。但是,CNN的计算要求很高,通常需要图形处理单元 (GPU) 来训练模型,否则训练速度很慢。

什么是卷积神经网络?

卷积神经网络是一种基于卷积计算的前馈神经网络。与普通的神经网络相比,它具有局部连接、权值共享等优点,使其学习的参数量大幅降低,且网络的收敛速度也更快。同时,卷积运算能更好地提取图像的特征。卷积神经网络的基本组件有卷积层、池化层和全连接层。卷积层是卷积网络的第一层,其后可以跟着其他卷积层或池化层,最后一层是全连接层。越往后的层识别图像越大的部分,较早的层专注于简单的特征,例如颜色和边缘。随着图像数据在 CNN 的各层中前进,它开始识别物体的较大元素或形状,直到最终识别出预期的物体。

image.png

下面将简单介绍这几种基本组件的相关原理和作用。

卷积层

卷积层是 CNN 的核心组件,其作用是提取样本的特征。它由三个部分组成,即输入数据、过滤器和特征图。在计算机内部,图像以像素矩阵的形式存储。若输入数据是一个RGB图像,则由 3D 像素矩阵组成,这意味着输入将具有三个维度——高度、宽度和深度。过滤器,也叫卷积核、特征检测器,其本质是一个二维(2-D)权重矩阵,它将在图像的感受野中移动,检查特征是否存在。

卷积核的大小不一,但通常是一个 3x3 的矩阵,这也决定了感受野的大小。不同卷积核提取的图像特征也不同。从输入图像的像素矩阵的左上角开始,卷积核的权重矩阵与像素矩阵的对应区域进行点积运算,然后移动卷积核,重复该过程,直到卷积核扫过整个图像。这个过程就叫做卷积。卷积运算的最终输出就称为特征图、激活图或卷积特征

image.png

如上图所示☝,特征图中的每个输出值不必连接到输入图像中的每个像素值,它只需要连接到应用过滤器的感受野。由于输出数组不需要直接映射到每个输入值,卷积层(以及池化层)通常被称为“部分连接”层。这种特性也被描述为局部连接

当卷积核在图像上移动时,其权重是保持不变的,这被称为权值共享。一些参数,如权重值,是在训练过程中通过反向传播和梯度下降的过程进行调整的。在开始训练神经网络之前,需要设置三个影响输出体积大小的超参数:

  1. 过滤器的数量 :影响输出的深度。例如,三个不同的过滤器将产生三个不同的特征图,从而产生三个深度。
  2. 步长(Stride) :卷积核在输入矩阵上移动的距离或像素数。虽然大于等于 2 的步长很少见,但较大的步长会产生较小的输出。
  3. 零填充(Zero-padding) :通常在当过滤器不适合输入图像时使用。这会将输入矩阵之外的所有元素设置为零,从而产生更大或相同大小的输出。有三种类型的填充:
    • Valid padding:这也称为无填充。在这种情况下,如果维度不对齐,则丢弃最后一个卷积。
    • Same padding:此填充确保输出层与输入层具有相同的大小。
    • Full padding:这种类型的填充通过在输入的边界添加零来增加输出的大小。

在每次卷积操作之后,CNN 的特征图经过激活函数(SigmoidReLULeaky ReLU等)的变换,从而对输出做非线性的映射,以提升网络的表达能力。

image.png

CNN 有多个卷积层时,后面的层可以看到前面层的感受野内的像素。例如,假设我们正在尝试确定图像是否包含自行车。我们可以把自行车视为零件的总和,即由车架、车把、车轮、踏板等组成。自行车的每个单独部分在神经网络中构成了一个较低级别的模式,各部分的组合则代表了一个更高级别的模式,这就在 CNN 中创建了一个特征层次结构。

image.png

池化层

为了减少特征图的参数量,提高计算速度,增大感受野,我们通常在卷积层之后加入池化层(也称降采样层)。池化能提高模型的容错能力,因为它能在不损失重要信息的前提下进行特征降维。这种降维的过程一方面使得模型更加关注全局特征而非局部特征,另一方面具有一定的防止过拟合的作用。池化的具体实现是将感受域中的值经过聚合函数后得到的结果作为输出。池化有两种主要的类型:

  • 最大池化(Max pooling):当过滤器在输入中移动时,它会选择具有最大值的像素发送到输出数组。与平均池化相比,这种方法的使用频率更高。
  • 平均池化(Average pooling):当过滤器在输入中移动时,它会计算感受域内的平均值以发送到输出数组。

img

全连接层

全连接层通常位于网络的末端,其结构正如其名。如前所述,输入图像的像素值在部分连接层中并不直接连接到输出层。但是,在全连接层中,输出层中的每个节点都直接连接到前一层中的节点,特征图在这里被展开成一维向量。

该层根据通过前几层提取的特征及其不同的过滤器执行分类任务。虽然卷积层和池化层倾向于使用 ReLu 函数,但 FC 层通常用 Softmax 激活函数对输入进行适当分类,产生 [0, 1] 之间的概率值。

自定义卷积神经网络进行手写数字识别

  • 导包
python复制代码import time
import numpy as np
import torch
import torch.nn.functional as F
from torchvision import datasets
from torchvision import transforms
from torch.utils.data import DataLoader

if torch.cuda.is_available():
    torch.backends.cudnn.deterministic = True
  • 设置参数 & 加载数据集
ini复制代码##########################
### SETTINGS
##########################

# Device
device = torch.device("cuda:3" if torch.cuda.is_available() else "cpu")

# Hyperparameters
random_seed = 1
learning_rate = 0.05
num_epochs = 10
batch_size = 128

# Architecture
num_classes = 10

##########################
### MNIST DATASET
##########################

# Note transforms.ToTensor() scales input images
# to 0-1 range
train_dataset = datasets.MNIST(root='data', 
                               train=True, 
                               transform=transforms.ToTensor(),
                               download=True)

test_dataset = datasets.MNIST(root='data', 
                              train=False, 
                              transform=transforms.ToTensor())


train_loader = DataLoader(dataset=train_dataset, 
                          batch_size=batch_size, 
                          shuffle=True)

test_loader = DataLoader(dataset=test_dataset, 
                         batch_size=batch_size, 
                         shuffle=False)

# Checking the dataset
for images, labels in train_loader:  
    print('Image batch dimensions:', images.shape)
    print('Image label dimensions:', labels.shape)
    break
  • 模型定义
ini复制代码##########################
### MODEL
##########################

class ConvNet(torch.nn.Module):

    def __init__(self, num_classes):
        super(ConvNet, self).__init__()
        
        # calculate same padding:
        # (w - k + 2*p)/s + 1 = o
        # => p = (s(o-1) - w + k)/2
        
        # 28x28x1 => 28x28x8
        self.conv_1 = torch.nn.Conv2d(in_channels=1,
                                      out_channels=8,
                                      kernel_size=(3, 3),
                                      stride=(1, 1),
                                      padding=1) # (1(28-1) - 28 + 3) / 2 = 1
        # 28x28x8 => 14x14x8
        self.pool_1 = torch.nn.MaxPool2d(kernel_size=(2, 2),
                                         stride=(2, 2),
                                         padding=0) # (2(14-1) - 28 + 2) = 0
        # 14x14x8 => 14x14x16
        self.conv_2 = torch.nn.Conv2d(in_channels=8,
                                      out_channels=16,
                                      kernel_size=(3, 3),
                                      stride=(1, 1),
                                      padding=1) # (1(14-1) - 14 + 3) / 2 = 1                 
        # 14x14x16 => 7x7x16                             
        self.pool_2 = torch.nn.MaxPool2d(kernel_size=(2, 2),
                                         stride=(2, 2),
                                         padding=0) # (2(7-1) - 14 + 2) = 0

        self.linear_1 = torch.nn.Linear(7*7*16, num_classes)

        for m in self.modules():
            if isinstance(m, torch.nn.Conv2d) or isinstance(m, torch.nn.Linear):
                m.weight.data.normal_(0.0, 0.01)
                m.bias.data.zero_()
                if m.bias is not None:
                    m.bias.detach().zero_()
        
        
    def forward(self, x):
        out = self.conv_1(x)
        out = F.relu(out)
        out = self.pool_1(out)

        out = self.conv_2(out)
        out = F.relu(out)
        out = self.pool_2(out)
        
        logits = self.linear_1(out.view(-1, 7*7*16))
        probas = F.softmax(logits, dim=1)
        return logits, probas

    
torch.manual_seed(random_seed)
model = ConvNet(num_classes=num_classes)

model = model.to(device)

optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)  
  • 模型训练
scss复制代码def compute_accuracy(model, data_loader):
    correct_pred, num_examples = 0, 0
    for features, targets in data_loader:
        features = features.to(device)
        targets = targets.to(device)
        logits, probas = model(features)
        _, predicted_labels = torch.max(probas, 1)
        num_examples += targets.size(0)
        correct_pred += (predicted_labels == targets).sum()
    return correct_pred.float()/num_examples * 100
    

start_time = time.time()    
for epoch in range(num_epochs):
    model = model.train()
    for batch_idx, (features, targets) in enumerate(train_loader):
        
        features = features.to(device)
        targets = targets.to(device)

        ### FORWARD AND BACK PROP
        logits, probas = model(features)
        cost = F.cross_entropy(logits, targets)
        optimizer.zero_grad()
        
        cost.backward()
        
        ### UPDATE MODEL PARAMETERS
        optimizer.step()
        
        ### LOGGING
        if not batch_idx % 50:
            print ('Epoch: %03d/%03d | Batch %03d/%03d | Cost: %.4f' 
                   %(epoch+1, num_epochs, batch_idx, 
                     len(train_loader), cost))
    
    model = model.eval()
    print('Epoch: %03d/%03d training accuracy: %.2f%%' % (
          epoch+1, num_epochs, 
          compute_accuracy(model, train_loader)))

    print('Time elapsed: %.2f min' % ((time.time() - start_time)/60))
    
print('Total Training Time: %.2f min' % ((time.time() - start_time)/60))
  • 模型评估
python复制代码with torch.set_grad_enabled(False): # save memory during inference
    print('Test accuracy: %.2f%%' % (compute_accuracy(model, test_loader)))

输出如下👇

Test accuracy: 97.97%

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

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

相关文章

寒假思维训练计划day11

每日一题,这两天有事,断更了一天,今天补上,感觉状态也不太好,来道1500的题压压惊。 宣传一下我总结的几个构造题模型,一点个人的浅薄见解: 1、前后缀贪心,比如说观察前后缀的sum&…

关于运维·关于Zabbix监控平台的面试点

目录 引言:明人不说暗话,今天分享几个在面试的时候常被问到关于Zabbix监控平台的面试点 1、zabbix的优点 2、zabbix的缺点 3、zabbix的监控模式 4、zabbix自定义监控怎么做 5、zabbix的自动发现功能 6、zabbix分布式监控有什么特点 引言&#xff1…

QtAV:基于Qt和FFmpeg的跨平台高性能音视频播放框架

目录 一.简介 1.特性 2.支持的平台 3.简单易用的接口 二.编译 1.下载依赖包 2.开始编译 2.1克隆 2.2修改配置文件 2.3编译 三.试用 一.简介 官网地址:http://www.qtav.org/ Github地址:https://github.com/wang-bin/QtAV 1.特性 ●支持大部分…

【新书推荐】Web3.0应用开发实战(从Web 2.0到Web 3.0)

第一部分 Flask简介 第1章 安装 1.1 创建应用目录 1.2 虚拟环境 1.2.1 创建虚拟环境 1.2.2 使用虚拟环境 1.3 使用pip安装Python包 1.4 使用pipregs输出包 1.5 使用requirements.txt 1.6 使用pipenv管理包 第2章 应用的基本结构 2.1 网页显示过程 2.2 初始化 2.3 路由和视图函数…

Vue 2生命周期已达终点,正式结束使命

Vue.js是一款流行的JavaScript框架,拥有广泛的应用和开发者社区。自Vue.js 2发布以来,它在前端开发中扮演了重要角色,并且被广泛采用。然而,技术的发展是无法阻挡的,随着2024年的到来,Vue 2的生命周期也走到…

Multi-Concept Customization of Text-to-Image Diffusion——【论文笔记】

本文发表于CVPR 2023 论文地址:CVPR 2023 Open Access Repository (thecvf.com) Github官方代码地址: github.com 一、Intorduction 最近的文本到图像模型能够根据文本提示生成高质量的图像,可以覆盖广泛的物体、风格和场景。尽管这些模型…

Java方法及方法重载的详解

目录 一、方法的概念及使用 1.1 方法的概念 1.2 方法的定义 1.3 方法调用的执行过程 1.4 实参和形参的关系 1.5 没有返回值的方法 二、方法的重载 2.1 方法重载存在的原因 2.2 方法重载的概念 一、方法的概念及使用 1.1 方法的概念 方法就是一个代码片段. 类似于 C …

6.4.1认识Amor SWF to Video Converter2

6.4.1认识Amor SWF to Video Converter2 安装完Amor SWF to Video Converter2 (本书使用Amor SWF to Video Converter2.4.9版本)后,单击【开始】|【程序】|【Amor SWF to Video Converter】|【Amor SWF to Video Converter】,启动Amor SWF to Video Con…

软件测试阶段简介_单元测试、集成测试、配置项测试、系统测试

文章目录 前言一、软件测试“V”模型二、单元测试三、集成测试四、配置项测试五、系统测试总结 前言 一般来说,按照软件的研制阶段划分,软件测试可分为单元测试、集成测试、配置项测试、系统测试等。本文将对上述各测试阶段进行逐一介绍。 一、软件测试…

K8S Informer机制原理解读 | Reflector

Reflector Informer可以对Kubernetes API Server的资源执行监控(Watch)操作,资源类型可以是Kubernetes内置资源,也可以是CRD自定义资源,其中最核心的功能是Reflector。Reflector用于监控指定资源的Kubernetes资源&…

CSS 实现卡片以及鼠标移入特效

CSS 实现卡片以及鼠标移入特效 文章目录 CSS 实现卡片以及鼠标移入特效0、效果预览默认鼠标移入后 1、创建卡片组件2、添加样式3、完整代码 0、效果预览 默认 鼠标移入后 在本篇博客中,我们将探讨如何使用 CSS 来实现卡片组件,并添加鼠标移入特效&#…

中顺洁柔宣布:年底前发出1.3亿年终奖金

1月15日,中顺洁柔在广东中山顺利举行了2023年的年度会议。会议上,该企业宣布2023年公司销售和生产条线基层员工收入增幅10%,并将发出1.3亿元的年终奖金。在年华交替之际,这一举措成为了行业瞩目的焦点。 年会上,中顺洁…

防爆气象站需要如何维护

TH-FBCQX2 在工业生产中,防爆气象站是保障安全生产的重要设备之一。由于其特殊的使用环境和功能,防爆气象站的维护保养工作显得尤为重要。 一、日常维护保养 清洁:防爆气象站的外部和内部组件需要定期清洁,以去除灰尘、油渍和杂质…

分类预测 | Matlab实现ISSA-SVM基于多策略混合改进的麻雀搜索算法优化支持向量机的数据分类预测

分类预测 | Matlab实现ISSA-SVM基于多策略混合改进的麻雀搜索算法优化支持向量机的数据分类预测 目录 分类预测 | Matlab实现ISSA-SVM基于多策略混合改进的麻雀搜索算法优化支持向量机的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 基于多策略混合改进的麻…

Kafka Console Client 的 Consumer Group

以往使用 kafka-console-consumer.sh 消费 Kafka 消息时并没有太在意过 Consumer Group,在命令行中也不会使用 --group 参数,本文针对 Kafka Console Client 命令行中的 Consumer Group 进行一次统一说明。 1. 如不设置 --group 参数会自动生成一个 Con…

Flink编程——风险欺诈检测

Flink 风险欺诈检测 文章目录 Flink 风险欺诈检测背景准备条件FraudDetectionJob.javaFraudDetector.java 代码分析执行环境创建数据源对事件分区 & 欺诈检测输出结果运行作业欺诈检测器 欺诈检测器 v1:状态欺诈检测器 v2:状态 时间完整的程序期望的…

vue:菜单栏联动内容页面tab

一、需求 需要实现效果:左侧菜单栏与右侧内容部分联动,当点击左侧的菜单,右侧会展示对应的tab,没有点击时,不展示(如刚进入页面没有点击菜单,则没有tab);点击后没有关闭…

Java 设计者模式以及与Spring关系(一)单例和建造者模式

简介: 本文是个系列一次会出两个设计者模式作用,如果有关联就三个,除此外还会讲解在spring中作用。 23设计者模式以及重点模式 我们都知道设计者模式有3类23种设计模式,标红是特别重要的设计者模式建议都会,而且熟读于心。标蓝是…

计算机毕业设计 基于SpringBoot的红色革命文物征集管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…

C#,因数分解(质因子分解)Pollard‘s Rho算法的源代码

因数分解(也称为质因子分解):将一个大整数分解它的质因子之乘积的算法。 Pollard Rho算法的基本思路:先判断当前数是否是素数(质数),如果是,则直接返回。如果不是,继续找…