经典视觉神经网络1 CNN

news2025/1/12 4:05:45

一、概述

        输入的图像都很大,使用全连接网络的话,计算的代价较高,图像也很难保留原本特征。

        卷积神经网络(Convolutional Neural Network,CNN)是一种专门用于处理具有网格状结构数据的深度学习模型。主要应用于计算机视觉任务,但它的成功启发了在其他领域应用,如自然语言处理等。

        CNN网络主要有三部分构成:卷积层、池化层和全连接层构成;卷积层负责提取图像中的局部特征;池化层用来大幅降低运算量并特征增强;全连接层类似神经网络的部分,用来输出想要的结果。

1、全连接网络处理图像缺陷

        参数结束了巨大:假设使用 100*1000的输入,神经元存在1000*1000,那么其中需要使用权重参数达到 10的十二次方。

        表达能力:全连接无法利用好图片像素的空间特性,降低了学习效率

2、卷积思想

        分为两个部分:卷和积 ; 卷 表示从左上 开始到右上,最后到右下的循环过程;积 表示将每次卷的内容进行乘积求和。

2.1、局部连接

        没有全连接方式,空间距离越近的像素相互影响越大;局部特征完成目标的识别

2.2、权重共享

        从一块区域学习的信息应用到其他区域;减少参数量,降低学习难度和计算量

二、 卷积层  Convolutional

1、卷积核

        一个矩阵,用于提取图像的特征(根据数值内容处理为具体特征意义的数值)

        卷积核(过滤器)的个数决定了卷积层输出特征矩阵的通道数;卷积核的大小一般设置为奇数形式的n*n,少数出现n*m(n决定行的卷积,m决定列的卷积)

2、卷积计算

原图像:5*5 的矩阵,经过边缘填充变成7*7的矩阵;                 卷积核:3*3的矩阵;  特征图: 5*5的矩阵

        卷积计算过程就是将卷积核放在图片信息上移动计算,每次达到下一个位置时,重合区域点对点相乘后全部相加,这个值就是特征图的一个格子数据,图像遍历完成后,所有的结果拼接变为特征图。

        如下图,左上角的区域对于卷积核位置相乘相加:

API:

        nn.Conv2d

参数:in_channels=  int   图像信息的通道数

           out_channels=  int   输出特征图的通道数

           kernel_size= int 或 tuple  卷积核的大小

           stride= int 或 tuple  步长默认1,表示行或列的移动距离

           padding= int,默认0   填充,保障边缘信息被提取

           dilation= int 或 tuple  默认1,表示无间隔,若为1表示每次卷积核映射图像数据时,点位要行列都间隔1个格子。

           groups 分组

           bias=  默认True,需要偏置

           padding_mode= str  填充模式,默认zero填充

           device= 设备

           dtype= 数据类型

代码:

import torch
import torch.nn as nn 
from matplotlib import pyplot as plt 

def test001():
    img = plt.imread('./data/1.jpg')
    img = torch.tensor(img, dtype=torch.float32).permute(2,0,1).unsqueeze(0)
    # 创建卷积核
    conv = nn.Conv2d(in_channels=3,  # 与输入特征图的通道数相同
                     out_channels=3,  # 决定输出特征图的通道数
                     kernel_size = 3, # 卷积核的大小
                     padding=1 # 填充周边
                    )
    img_c  = conv(img)
    img_c = img_c.permute(0,2,3,1).squeeze(0)
    plt.imshow(img_c.detach().numpy())
    plt.show()

def test002():
    input = torch.randn(10,2,5,6)
    # 创建卷积核
    conv = nn.Conv2d(in_channels=2,  # 与输入特征图的通道数相同
                     out_channels=3,  # 决定输出特征图的通道数
                     kernel_size = (3,5), # 卷积核的大小
                     padding=0, # 填充周边
                     stride=1,
                     bias=True
                    )
    output = conv(input) 
    # n = (w-f+2p)/s+1 --> H: (5-3+2*0)/1+1=3  W: (6-5+2*0)/1+1=2
    # w 通道大小
    # f 卷积核大小
    # p 填充大小
    # s 步长大小
    print(output.shape)

if __name__ == '__main__':
    test001()

3、卷积计算的底层表示

        

4、padding  边缘填充

        每次卷积都会对图像矩阵的行列数降低,若想要保持图像大小不变,则需要填充边缘,一般设置padding值为 (图像矩阵大小 - 卷积核大小)/2

       如卷积计算的动图,就是padding设置为1 也就是图像矩阵大小减去卷积核大小(5-3)/2 的值

5、stride 步长

        stride太小:重复计算较多,计算量大,训练效率降低;

        stride太大:会造成信息遗漏,无法有效提炼数据背后的特征;

        步长为1:

         步长为2:

6、多通道计算

        输入通道多时(图片一般为三通道或四通道),需要卷积核的 in_channels 等于输入通道数(卷积核的通道数与输入通道数一致 ;卷积核的个数与输出通道数一致);

        

7、多卷积核计算

        从不同到的视角、不同的角度对图像特征进行提取。

8、特征图大小

        计算方式:

        若行列并不相等(图像、卷积核等),那么就需要单独计算:

        H_{out} = \frac{H_{in}-K_H+2*P}{S}+1               W_{out} = \frac{W_{in}-K_W+2*P}{S}+1

9、参数共享

        若数据为 32*32*3 的图像,使用了10*5*5的卷积核进行卷积操作(只需要考虑图像的通道了,图像大小不重要,因为参数共享),那么其需要的权重参数为

  • 5*5*3 =75 表示每一个卷积核所需要的参数 
  • 10*75=750 表示全部卷积核所需要的参数
  • 若考虑偏置系数,则需要加上每个卷积核一个偏置系数,总共为760个参数

若是选择使用全连接,那么所有的连接都需要使用权重参数(图像大小):32*32  *  3* 10*5*5 +10*5*5  = 768,250

三、池化层 Pooling

1、意义

        降低数据维度,减小模型,提高计算速度;主要用于对卷积层处理后的特征图进行下采样操作。

2、计算方式

       分为了 最大池化 maxpolling 和  平均池化  avgpooling

2.1、最大池化

        选取映射内容中最大的数值

        

2.2、平均池化

        所有映射值的平均值

        

3、步长 stride

        步长为1和步长为2 的对比

4、边缘填充 padding

5、多通道计算

        对每个输入通道分别池化,而不是像卷积层那样将各个通道的输入相加。

        池化层的输出和输入的通道数保持相等。

6、API

        nn.MaxPool2d

参数:kernel_size = int 或 tuple  池化核,于卷积核一样

           stride= int 或 tuple ,步长

           padding= int 或 tuple ,填充

           dilation=  int 或 tuple ,膨胀

           return_indices=  默认false,不返回取值对于下标

           ceil_mode=  默认false,向上取整

import torch
import torch.nn as nn

def test01():
    torch.manual_seed(1)
    # 输入数据
    input = torch.randint(0,255,(1,64,224,224))
    print("输入数据:\n",input[0][0][:6,:6])
    # 池化核
    pool = nn.MaxPool2d(kernel_size=2,# 池化核大小
                        stride=2,
                        return_indices=True)
    
    # 对数据池化
    out,return_indices  = pool(input)
    print("下标:\n",return_indices[0][0][:6,:6])
    print("输出结果:\n",out.shape)

if __name__ == '__main__':
    test01()

四、卷积扩展

1、反卷积

        因为一般情况下,使用卷积会造成缩小,所以需要使用填充对图像大小调整,称为反卷积

2、空洞卷积(膨胀)

        使用参数 dilation 控制膨胀程度,1表示不膨胀,2表示膨胀一格距离。

        

import torch
import torch.nn as nn

def test003():
    torch.manual_seed(1)
    # 输入数据
    x = torch.randn(1,1,7,7)
    # 创建一个卷积核
    conv = nn.Conv2d(in_channels=1,
                    out_channels=1, 
                    kernel_size=3, 
                    stride=1,
                    dilation=2,
                    )
    out = conv(x)
    print(out.shape)
    print(out)


if __name__ == '__main__':
    test003()

3、可分离卷积

3.1、空间可分离卷积

        将卷积核拆分为两个独立的核计算(3*3 --> 3*1  + 1*3 ),拆分后计算量比标准卷积更少。

如图:5*5 的数据矩阵需要使用3*3的卷积核计算,先使用3*1的卷积核计算得到3*5得数据,在使用1*3得卷积和得到3*3得数据结果。

import torch
import torch.nn as nn

# def test004():
class nornalModel(nn.Module):
    def __init__(self):
        super(nornalModel, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=8, 
                               out_channels=8, 
                               kernel_size=3,
                               stride=1,
                               padding=0,
                               bias=False)
        
    def forward(self, x):
        self.conv1.weight.data.fill_(1)
        x = self.conv1(x)
        return x



class waveModel(nn.Module):
    def __init__(self):
        super(waveModel, self).__init__()
        self.conv1 = nn.Conv2d(
                    in_channels=8, 
                    out_channels=8, 
                    kernel_size=(3,1),
                    stride=1,
                    padding=0,
                    bias=False
                    )
        self.conv2 = nn.Conv2d(
                    in_channels=8, 
                    out_channels=8, 
                    kernel_size=(1,3),
                    stride=1,
                    padding=0,
                    bias=False
                    )
    def forward(self,x):
        self.conv1.weight.data.fill_(1)
        self.conv2.weight.data.fill_(1)
        x = self.conv1(x)
        x = self.conv2(x)
        return x


if __name__ == '__main__':
    torch.manual_seed(1)
    input = torch.randn(1,8,5,5)
    model1 = nornalModel()
    for name, param in model1.named_parameters():
        print(name, param.shape)

    
    torch.manual_seed(1)
    input = torch.randn(1,8,5,5)
    model2 = waveModel()
    for name, param in model2.named_parameters():
        print(name, param.shape)

# conv1.weight torch.Size([8, 8, 3, 3])
# conv1.weight torch.Size([8, 8, 3, 1])
# conv2.weight torch.Size([8, 8, 1, 3])

3.2、深度可分离卷积

        在空间分离基础上加入通道分离,使用参数 groups进行划分(要求输入通道和输出通道都能被groups设定整数值整除);也就是使用卷积核得不同通道处理输入输出得不同通道。

import torch
import torch.nn as nn

class Net1(nn.Module):
    def __init__(self):
        super(Net1, self).__init__()
        self.conv1 = nn.Conv2d(
                        in_channels=8,
                        out_channels=8,
                        kernel_size=3,
                        stride=1,
                        bias=False
                    )
        
    def forward(self, x):
        return self.conv1(x)

class deepmovemodel(nn.Module):
    def __init__(self):
        super(deepmovemodel, self).__init__()
        self.conv1 = nn.Conv2d(
                        in_channels=8,
                        out_channels=8,
                        kernel_size=3,
                        stride=1,
                        bias=False,
                        groups=8  # 卷积核数量等于通道数
                    )
        self.conv2 = nn.Conv2d(
                        in_channels=8,
                        out_channels=8,
                        kernel_size=1,
                        stride=1,
                        bias=False
                    )
        
    def forward(self, x):
        x = self.conv1(x)
        torch.ones_like(self.conv2.weight.data)
        x = self.conv2(x)
        return x

if __name__ == '__main__':
    torch.manual_seed(1)
    input = torch.randn(1,8,5,5)

    model1 = Net1()
    for name, param in model1.named_parameters():
        print(name,param.size())
    
    model2 = deepmovemodel()
    for name, param in model2.named_parameters():
        print(name,param.size())


# conv1.weight torch.Size([8, 8, 3, 3])
# conv1.weight torch.Size([8, 1, 3, 3])
# conv2.weight torch.Size([8, 8, 1, 1])

3.3、扁平卷积

        等同空间可分离卷积,如3*3得卷积核被拆分为3个1*1得卷积核,分别计算通道、宽度、高度三个方面内容。

3.4、分组卷积

        等同深度可分离卷积。

        AlexNet论文中最先提出来的概念,当时主要为了解决GPU显存不足问题。

        卷积核被分成不同的组,每组负责对相应的输入层进行卷积计算,最后再进行合并。

3.5、感受野

        理解为视野范围。

        卷积操作从左到右为5*5矩阵经过3*3的卷积核卷积后得到3*3的矩阵,在经过3*3的卷积核卷积后得到1*1的矩阵,效果等同于5*5矩阵直接经过5*5的卷积核卷积操作。

        感受野就是逆向的结果,两个3*3的卷积核且步长为1,感受野为5*5;同理,三个3*3的卷积核,感受野就为7*7,四个3*3为9*9(步长为1)

        感受野的作用:假设原本输入大小为  h × w × C,并且使用了C个卷积核,那么标准的一个7*7卷积核就需要 c* (h*w*c) = 49C^2 ,使用三个3*3的卷积核,那么其感受野也还是7*7,但是参数就变成了 3*C*(3*3*C) = 27C^2

五、卷积神经网络案例

1、模型结构

输入:(1,32,32)通道为1,宽高为32的数据

卷积层1:输入1 个通道(等于输入数据的通道数),输出6个通道(卷积核个数),卷积核大小为3*3;

特征图1:数据32*32,卷积核3*3,步长1,填充0:(32-3+2*0)/1  +1 =30,所以为6个30*30的特征图

池化层1:使用6个2*2的池化核进行处理

特征图2:30*30池化后(2*2,步长为2)结果为其一半 15*15

卷积层2:输入6个通道,输出16个通道,卷积核为3*3

特征图3:15*15卷积后得到13*13 的大小;  16个13*13

池化层2:使用16个2*2的池化核进行处理

特征图4:13*13池化后(2*2,步长为2)结果为其一半(向下取整,因为步长为2,所以取不到最右边和最下边的数据); 16个6*6

全连接1:输入需要16*6*6=576 维,输出为 120维

全连接2:输入120维,输出为 84维

全连接3:输入84维,输出为 10维

2、使用代码展现网络模型

import torch
import torch.nn as nn

class numberModee(nn.Module):
    def __init__(self):
        super(numberModee, self).__init__()
        self.C1 = nn.Sequential(
                        nn.Conv2d(
                            in_channels=1, # 输入通道
                            out_channels=6, # 输出通道
                            kernel_size=3, # 卷积核大小
                            stride=1, # 步长
                            padding=0 # 填充
                            ),
                        nn.ReLU()
                        )
        
        self.S2 = nn.MaxPool2d(kernel_size=2,
                               stride=2,
                               padding=0)
        self.C3 = nn.Sequential(
                        nn.Conv2d(
                            in_channels=6, 
                            out_channels=16,
                            kernel_size=3, 
                            stride=1, 
                            padding=0),
                        nn.ReLU()
                        )
        self.S4 = nn.MaxPool2d(kernel_size=2,
                               stride=2,
                               padding=0)
        self.C5 = nn.Sequential(
                        nn.Linear(16*6*6, 120),
                        nn.ReLU()
                        )
        self.F6 = nn.Sequential(
                        nn.Linear(120, 84),
                        nn.ReLU()
                        )
        self.OUTPUT = nn.Sequential(
                        nn.Linear(84, 10),
                        nn.Softmax(dim=1)
                        )
    def forward(self, x):
        x = self.C1(x)
        x = self.S2(x)
        x = self.C3(x)
        x = self.S4(x)
        x = x.view(x.size(0),-1)
        x = self.C5(x)
        x = self.F6(x)
        x = self.OUTPUT(x)
        return x


if __name__ == '__main__':
    input = torch.randn(1, 1, 32, 32)
    print(input)
    print(input.shape)
    net = numberModee()
    out = net(input) 
    # 6 @ 30*30  
    # 6 @ 15*15
    # 16 @ 13*13
    # 16 @ 6*6
    # 120
    # 84
    # 10
    print(out)
    print(out.shape)

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

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

相关文章

黑马程序员MybatisPlus/Docker相关内容

Day01 MP相关知识 1. mp配置类: 2.条件构造器: 具体的实现例子: ①QuerryWapper: ②LambdaQueryWrapper: 3.MP的自定义SQL 4.MP的Service层的实现 5.IService下的Lambda查询 原SQL语句的写法: Lambda 查询语句的…

通讯专题4.1——CAN通信之计算机网络与现场总线

从通讯专题4开始,来学习CAN总线的内容。 为了更好的学习CAN,先从计算机网络与现场总线开始了解。 1 计算机网络体系的结构 在我们生活当中,有许多的网络,如交通网(铁路、公路等)、通信网(电信、…

低级爬虫实现-记录HCIP云架构考试

因工作需要考HCIP云架构(HCIP-Cloud Service Solution Architect)证书, 特意在淘宝上买了题库, 考过了。 事后得知自己被坑了, 多花了几十大洋。 所以想着在授权期内将题库“爬”下来, 共享给大家。 因为整个过程蛮有…

最新AI问答创作运营系统(SparkAi系统),GPT-4.0/GPT-4o多模态模型+联网搜索提问+问答分析+AI绘画+管理后台系统

目录 一、人工智能 系统介绍文档 二、功能模块介绍 系统快速体验 三、系统功能模块 3.1 AI全模型支持/插件系统 AI大模型 多模态模型文档分析 多模态识图理解能力 联网搜索回复总结 3.2 AI智能体应用 3.2.1 AI智能体/GPTs商店 3.2.2 AI智能体/GPTs工作台 3.2.3 自…

借助 AI 工具,共享旅游-卡-项目助力年底增收攻略

年底了,大量的商家都在开始筹备搞活动,接下来的双十二、元旦、春节、开门红、寒假,各种活动,目的就是为了拉动新客户。 距离过年还有56 天,如何破局? 1、销售渠道 针对旅游卡项目,主要销售渠道…

AndroidStudio-常见界面控件

一、Button package com.example.review01import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button import android.widget.TextViewclass Review01Activity : AppCompatActivity() {override fun onCreate(savedInstanceStat…

【SpringMVC】参数传递 重定向与转发 REST风格

文章目录 参数传递重定向与转发REST风格 参数传递 ModelAndView:包含视图信息和模型数据信息 public ModelAndView index1(){// 返回页面ModelAndView modelAndView new ModelAndView("视图名");// 或// ModelAndView modelAndView new ModelAndView(…

Vue网页屏保

Vue网页屏保 在vue项目中&#xff0c;如果项目长时间未操作需要弹出屏幕保护程序&#xff0c;以下为网页屏保效果&#xff0c;看板内容为连接的资源。 屏保组件 <template><div v-if"isActive" class"screensaver" click"disableScreens…

计算机网络复习5——运输层

运输层解决的是进程之间的逻辑通信问题 两个主机进行通信归根结底是两个主机中的应用程序互相通信&#xff0c;又称为“端到端的通信” 端口 运行在计算机中的进程是用进程标识符来标志的。但不同的操作系统标识进程的方法不统一&#xff0c;因特网重新以统一的方法对TCP/IP…

qtcanpool 知 10:包管理雏形

文章目录 前言痛点转机雏形实践后语 前言 曾听闻&#xff1a;C/Qt 没有包管理器&#xff0c;开发起来太不方便。这是一个有过 node.js 开发经验的人对 Qt 的吐槽。 确实&#xff0c;像 python、golang、node.js 这些编程语言都有包管理器&#xff0c;给用户带来了极佳的开发体…

ASP.NET Core 9.0 静态资产传递优化 (MapStaticAssets )

一、结论 &#x1f4a2;先看结论吧&#xff0c; MapStaticAssets 在大多数情况下可以替换 UseStaticFiles&#xff0c;它已针对为应用在生成和发布时了解的资产提供服务进行了优化。 如果应用服务来自其他位置&#xff08;如磁盘或嵌入资源&#xff09;的资产&#xff0c;则应…

LeetCode 力扣 热题 100道(十五)搜索插入位置(C++)

给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 代码如下所示&#xff1a; class Solution { public:int searchIns…

WPF+LibVLC开发播放器-音量控制和倍速控制

界面 界面上增加音量的控件和倍速控制控件 音量控制 主要也是一个Slider进度条控件来实现音量调节 我们这里设置默认的最大值为100&#xff0c;默认Value值也为100&#xff0c;默认声音开到最大 这里目前完全由前端控制音量调节&#xff0c;可以直接使用ValueChanged事件实…

Vue3技术开发,使用纯CSS3动手制作一个3D环绕的相册展示效果,支持传入任意图片.3D轮播相册的组件

主要讲述封装一个3D轮播相册的组件&#xff0c;效果图如下&#xff0c;仅仅传入一个图片的数组即可&#xff0c;效果如下&#xff1a; 使用Vue3技术开发&#xff0c;支持传入任意张数的图片。 使用方法 <template><Swiper :list"list" /> </templat…

python怎么将字母大写

Python中有三种将字母转换为大写的方法&#xff1a;upper()、capitalize()、title()。 下面通过实例给大家介绍具体用法&#xff1a; str "www.php.com" print(str.upper()) # 把所有字符中的小写字母转换成大写字母 print(str.lower()) # 把所有字…

将vscode上的项目提交到github上

1.windows终端中 创建github仓库 创建完成 提交代码 git init git config --global user.email "fuyulai2024163.com" git config --global user.name "Fuyulai-Hub" git add . git commit -m "first commit" git remote add origin https://g…

【期末JavaEE项目】springboot+vue3完成中国铁路12306网站的业务实现【原创】

&#x1f939;‍♀️潜意识Java&#xff1a;个人主页 &#x1f399;告诉你&#xff1a;Java是世界上最美好的语言 &#x1f48e;比较擅长的领域&#xff1a;前端开发 是的&#xff0c;我需要您的&#xff1a; &#x1f9e1;点赞❤️关注&#x1f499;收藏&#x1f49b; 是…

浅谈CI持续集成

1.什么是持续集成 持续集成&#xff08;Continuous Integration&#xff09;&#xff08;CI&#xff09;是一种软件开发实践&#xff0c;团队成员频繁地将他们的工作成果集成到一起(通常每人每天至少提交一次&#xff0c;这样每天就会有多次集成)&#xff0c;并且在每次提交后…

电子商务人工智能指南 1/6 - 搜索、广告和发现

介绍 81% 的零售业高管表示&#xff0c; AI 至少在其组织中发挥了中等至完全的作用。然而&#xff0c;78% 的受访零售业高管表示&#xff0c;很难跟上不断发展的 AI 格局。 近年来&#xff0c;电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…

【Git教程 之 版本控制】

Git教程 之 版本控制 Git教程 之 版本控制版本控制版本控制类型单用户版本控制系统&#xff08;VCS&#xff09;单用户版本控制系统&#xff08;VCS&#xff09;特点常见的单用户版本控制系统&#xff08;VCS&#xff09; 集中式版本控制系统&#xff08;CVCS&#xff09;集中式…