视觉经典神经网络学习01_CNN(1)

news2024/12/4 1:26:14

一、概述

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

卷积神经网络(Convolutional Neural Network)是含有卷积层的神经网络。卷积层的作用就是用来自动学习、提取图像的特征。

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

二、卷积思想

1、相关概念

Convolution,输入信息与卷积核(滤波器,Filter)的乘积。

卷:从左往右,从上往下;积:乘积,求和

局部连接

  • 局部连接可以更好地利用图像中的结构信息,空间距离越相近的像素其相互影响越大。

  • 根据局部特征完成目标的可辨识性。

权重共享

  • 图像从一个局部区域学习到的信息应用到其他区域。

  • 减少参数,降低学习难度。

2、卷积层

1.卷积核

在卷积神经网络中,卷积核是非常重要的,它们被用来提取图像中的特征。

  • 卷积核的个数:卷积核(过滤器)的个数决定了其输出特征矩阵的通道数

  • 卷积核的值:卷积核的值是自定义的,根据想要提取的特征来进行设置,后续进行更新。

  • 卷积核的大小:常见的卷积核有1×1、3×3、5×5等,一般都是奇数 × 奇数。

2.卷积计算

卷积的过程是将卷积核在图像上进行滑动计算,每次滑动到一个新的位置时,卷积核和图像进行点对点的计算,并将其求和得到一个新的值,然后将这个新的值加入到特征图中,最终得到一个新的特征图。

  1. input 表示输入的图像

  2. filter 表示卷积核, 也叫做滤波器

  3. input 经过 filter 的得到输出为最右侧的图像,该图叫做特征图

 

卷积的重要性在于它可以将图像中的特征与卷积核进行卷积操作,从而提取出图像中的特征

可以通过不断调整卷积核的大小、卷积核的值和卷积操作的步长,可以提取出不同尺度和位置的特征。

单特征图卷积输出:

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


def showing(img):
    plt.imshow(img)
    plt.show()

def test01():
    # 获取当前脚本文件所在的目录路径
    current_path = os.path.dirname(__file__)
    print(current_path)
    # 找到该路径下的图像
    img_path = os.path.join(current_path,'data','1,png')
    # 转换为相对路径
    img_path = os.path.relpath(img_path)

    # 使用plt读取图片
    img = plt.imread(img_path)
    # print(img.shape) # # torch.Size([808, 576, 4])

    # 创建卷积核
    """
    in_channels 输入通道数
    out_channels 输出通道数
    kernel_size 卷积核大小
    stride 步长
    padding 填充
    bias 布尔值 卷积层是否包含偏置项
    """
    conv = nn.Conv2d(
        in_channels=4,
        out_channels=1,
        kernel_size=3, 
        stride=1,
        padding=0,
        bias=True
    )
    # 注意:卷积层对输入的数据有形状要求 [batch, channel, height, width]
    # 需要进行形状转换  且转换为张量 HWC->CHW->NCHW
    img = torch.tensor(img,dtype=torch.float).permute(2,0,1).unsqueeze(0)
    print(img.shape) # torch.Size([1, 4, 808, 576])

    # 卷积操作
    out = conv(img)
    print(img.shape) # torch.Size([1, 1, 808, 576])

    # 将BCHW->HWC 便于显示
    img = img.squeeze(0).permute(1, 2, 0)
    showimg(img.detach().numpy())

多特征图卷积输出:

# 多特征图输出
def test002():
    dir = os.path.dirname(__file__)
    img = plt.imread(os.path.join(dir, 'data', '1.png'))

    # 定义一个多特征图输出的卷积核
    conv = nn.Conv2d(
        in_channels=4, 
        out_channels=3,  # 三个输出
        kernel_size=3, 
        stride=1, 
        padding=1)

    # 图形要进行变形处理
    img = torch.tensor(img).permute(2, 0, 1).unsqueeze(0)
    print(img.shape) # torch.Size([1, 4, 808, 576])

    # 使用卷积核对图片进行卷积计算
    outimg = conv(img)
    print(outimg.shape) # torch.Size([1, 3, 808, 576])

    # 把图形形状转换回来以方便显示 BCHW->CHW->HWC
    outimg = outimg.squeeze(0).permute(1, 2, 0)
    print(outimg.shape) # torch.Size([808, 576, 3])

    # 显示这三张特征图
    for idx in range(outimg.shape[2]):
        showing(outimg[:,:,idx].squeeze(-1).detach())
3.边缘填充 padding

通过上面的卷积计算,我们发现最终的特征图比原始图像要小,如果想要保持图像大小不变, 可在原图周围添加padding来实现。

更重要的,边缘填充还更好的保护了图像边缘数据的特征

4.步长 stride

按照步长为1来移动卷积核,计算特征图如下所示:

 如果我们把 Stride 增大为2,也是可以提取特征图的,如下图所示:

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

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

5.多通道卷积计算

实际中的图像都是多个通道组成的:

 就需要:

  1. 当输入有多个通道(Channel), 例如RGB三通道, 此时要求卷积核需要有相同的通道数

  2. 卷积核通道与对应的输入图像通道进行卷积。

  3. 将每个通道的卷积结果按位相加得到最终的特征图。

(图片中的结果应为 -71) 

6.多卷积核卷积计算

实际对图像进行特征提取时, 我们需要使用多个卷积核进行特征提取。这个多个卷积核可以理解为从不同到的视角、不同的角度对图像特征进行提取。

输出特征图的大小计算方式(粗略版,以后会补充):

  1. 输入图像大小: W x W

  2. 卷积核大小: F x F

  3. Stride: S

  4. Padding: P

  5. 输出图像大小: N x N

输出特征图大小计算: 

import torch
import torch.nn as nn


"""卷积输出图大小"""
def test01():
    input = torch.randn(1,1,5,5)
    
    # 创建卷积核
    conv = nn.Conv2(
        in_channels=1,
        out_channels=1,
        kernel_size=3,
        stride=1,
        padding=0,
        bias=True
    )
    # 输出图大小(5-3+2*0)/1+1=3

    out = conv(input)
    print(out.shape) # torch.Size([1, 1, 3, 3])

 多卷积核——神经网络构建:

import torch
import torch.nn as nn
import torch.nn.functional as F

class MyNet(nn.Module):
    def __init__(self):
        super(MyNet, self).__init__()
        # 卷积层 隐藏层
        self.conv1 = nn.Conv2d(
            in_channels=1, # 输入通道数
            out_channels=32, # 输出通道数
            kernel_size=3, # 卷积核大小
            padding=0, 
            stride=1 # 步长
            )
        # 输出特征图大小 30*30
        self.conv2 = nn.Conv2d(
            in_channels=32, # 输入通道数
            out_channels=128, # 输出通道数
            kernel_size=3, # 卷积核大小
            padding=0, 
            stride=1 # 步长
            )
        # 输出特征图大小 28*28
        self.conv3 = nn.Conv2d(
            in_channels=128, # 输入通道数
            out_channels=512, # 输出通道数
            kernel_size=3, # 卷积核大小
            padding=0, 
            stride=1 # 步长
            )
        # 输出特征图大小 26*26
        
        # 线性层 输出层
        # 分类判断 10分类
        self.fc = nn.Linear(512*26*26,10)

    def forward(self,x):
        # 前向传播
        x = F.relu(self.conv1(x))
        x = F.relu(self.conv2(x))
        x = F.relu(self.conv3(x))
        # 输出 NCHW->ND 线性层需要(batch_size, num_features)的输入形式
        x = x.view(x.size(0),-1)
        x = self.fc(x)
        x = nn.Softmax(dim=1)(x)
        return x


if __name__ == '__main__':
    input = torch.randn(64,1,32,32)
    net = MyNet()
    out = net(input)
    print(out.shape) # torch.Size([64, 10])
    # print(out)
 7.卷积参数共享

数据是 32×32×3 的图像,用 10 个 5×5×3 的filter来进行卷积操作,所需的权重参数:

  • 5×5×3 = 75,表示每个卷积核只需要 75 个参数。

  • 10个不同的卷积核,就需要10*75 = 750 个卷积核参数。

  • 如果还考虑偏置参数$b$,最终需要 750+10=760 个参数。

全连接层的参数量

import torch
import torch.nn as nn


class MyNet(nn.Module):
    def __init__(self):
        super(MyNet, self).__init__()
        # 隐藏层 线性层
        self.linear1 = nn.Linear(60*60*3, 38*38*3)
        # 输出层
        self.fc = nn.Linear(38*38*3,10)

    def forward(self, x):
        x = self.linear1(x)
        return x
    

if __name__ == '__main__':
    linearmodel = MyNet()
    # 获取网络参数
    params = linearmodel.named_parameters()
    for name,param in params: 
        print(name,param)

卷积层的参数量

import torch
import torch.nn as nn


class MyConv(nn.Module):
    def __init__(self):
        super(MyConv,self).__init__()

        self.conv1 = nn.Conv2d(
            in_channels=3,  # 输入通道数
            out_channels=8,  # 输出通道数
            kernel_size=3,  # 卷积核大小
            stride=1,  # 步长
            padding=0,  # 填充
            bias=True
        )

        # 输出层
        self.fc = nn.Linear(30*30*8,10)

    def forward(self,x):
        x = self.conv1(x)
        # x = x.view(-1,30*30*8)
        x=x.view(x.size(0),-1)
        print(x.shape)
        x = self.fc(x)
        return x
    

if __name__ == "__main__":
    convmodel = MyConv()
    input = torch.randn(1,3,64,64)
    out = convmodel(input)
    print(out.shape)
    # params = convmodel.named_parameters()
    # for name,param in params: 
    #     print(name,param)
8.卷积计算
import torch
import torch.nn as nn


class MyConv(nn.Module):
    def __init__(self):
        super(MyConv,self).__init__()

        self.conv1 = nn.Conv2d(
            in_channels=3,  # 输入通道数
            out_channels=8,  # 输出通道数
            kernel_size=3,  # 卷积核大小
            stride=1,  # 步长
            padding=0,  # 填充
            bias=True
        )

        # 输出层
        self.fc = nn.Linear(30*30*8,10)

    def forward(self,x):
        x = self.conv1(x)
        # x = x.view(-1,30*30*8)
        x=x.view(x.size(0),-1)
        print(x.shape)
        x = self.fc(x)
        return x
    

if __name__ == "__main__":
    convmodel = MyConv()
    input = torch.randn(1,3,64,64)
    out = convmodel(input)
    print(out.shape)
    # params = convmodel.named_parameters()
    # for name,param in params: 
    #     print(name,param)

 

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

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

相关文章

【golang】单元测试,以及出现undefined时的解决方案

单元测试 要对某一方法进行测试时,例如如下这一简单减法函数,选中函数名后右键->转到->测试 1)Empty test file 就是一个空文件,我们可以自己写测试的逻辑 但是直接点绿色箭头运行会出问题: 找不到包。我们要在…

DVWA靶场通关——DOM型XSS漏洞

一、DOM型XSS攻击概述 DOM型XSS(DOM-based Cross-Site Scripting,DOM XSS)是一种跨站脚本攻击(XSS)的变种,它与传统的反射型XSS(Reflected XSS)或存储型XSS(Stored XSS&a…

【Unity 动画】设置跟运动(Apply Root)模型跟着动画产生位移

一、导入的动画本身必须有跟随动画产生位移或者旋转的效果 二、导入Unity后 在Unity中,根运动(Root Motion)是指动画中角色根节点的移动和旋转。根节点通常是角色的根骨骼(Root Bone),它决定了角色的整体…

Spring AI 框架介绍

Spring AI是一个面向人工智能工程的应用框架。它的目标是将Spring生态系统的设计原则(如可移植性和模块化设计)应用于AI领域,并推广使用pojo作为AI领域应用的构建模块。 概述 Spring AI 现在(2024/12)已经支持语言,图像&#xf…

C++小问题

怎么分辨const修饰的是谁 是限定谁不能被改变的? 在C中,const关键字的用途和位置非常关键,它决定了谁不能被修改。const可以修饰变量、指针、引用等不同的对象,并且具体的作用取决于const的修饰位置。理解const的规则能够帮助我们…

近几年,GIS专业的五类就业方向!

近二十几年来,地理信息科学毕业生的就业方向在不断发生变化。 早期的地理信息科学技术主要应用于政府部门,因此学生就业主要在高校、交通运输、规划勘测设计、国土、矿业、水利电力、通讯、农林、城市建设、旅游等国家政府部门或事业单位。 随着地理信…

【Maven】继承和聚合

5. Maven的继承和聚合 5.1 什么是继承 Maven 的依赖传递机制可以一定程度上简化 POM 的配置,但这仅限于存在依赖关系的项目或模块中。当一个项目的多个模块都依赖于相同 jar 包的相同版本,且这些模块之间不存在依赖关系,这就导致同一个依赖…

2、Three.js初步认识场景Scene、相机Camera、渲染器Renderer三要素

三要素之间关系: 有了虚拟场景Scene,相机录像Camera,在相机小屏幕上看到的Renderer Scene当前空间 Mesh人在场景 Camera相机录像 Renderer显示器上 首先先描述下Scene: 这个场景为三要素之一,一切需要展示的东西都需…

工厂方法模式的理解和实践

在软件开发中,设计模式是一种经过验证的解决特定问题的通用方案。工厂方法模式(Factory Method Pattern)是创建型设计模式之一,它提供了一种创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推…

Vue教程|搭建vue项目|Vue-CLI2.x 模板脚手架

一、项目构建环境准备 在构建Vue项目之前,需要搭建Node环境以及Vue-CLI脚手架,由于本篇文章为上一篇文章的补充,也是为了给大家分享更为完整的搭建vue项目方式,所以环境准备部分采用Vue教程|搭建vue项目|V…

无人机主控芯片技术与算法详解!

一、无人机主控芯片核心技术 高性能CPU: 无人机需要高性能的CPU来处理复杂的飞行控制算法、图像处理和数据传输等任务。目前,无人机的CPU主要有大疆自研的飞控系统、高通提供的无人机设计平台Snapdragon Flight,以及基于开源平台APM、Px4等…

GaussDB(类似PostgreSQL)常用命令和注意事项

文章目录 前言GaussDB(类似PostgreSQL)常用命令和注意事项1. 连接到GaussDB数据库2. 查看当前数据库中的所有Schema3. 进入指定的Schema4. 查看Schema下的表、序列、视图5. 查看Schema下所有的表6. 查看表结构7. 开始事务8. 查询表字段注释9. 注意事项&a…

探索AI新世界!热门工具与学习资源免费获取

​抖知书老师推荐: 人工智能技术的迅速发展让人们既充满期待又有些迷茫。有人担忧被AI技术取代,有人却积极拥抱这场科技浪潮。无论你处于哪种心态,人工智能已经深入到我们生活的方方面面。如果你希望轻松掌握最新的AI工具与动态,…

[STM32]从零开始的STM32 FreeRTOS移植教程

一、前言 如果能看到这个教程的话,说明大家已经学习嵌入式有一段时间了。还记得嵌入式在大多数时候指的是什么吗?是的,我们所说的学习嵌入式大部分时候都是在学习嵌入式操作系统。从简单的一些任务状态机再到复杂一些的RTOS,再到最…

基于Java Springboot房屋租赁App且微信小程序

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA/eclipse 微信…

【docker】9. 镜像操作与实战

镜像操作案例 查找镜像 docker search busybox下载镜像 docker pull busybox:1.36.0查看镜像及列表存储位置 rootLAPTOP-H2EI4I6A:~# docker images busybox REPOSITORY TAG IMAGE ID CREATED SIZE busybox latest 517b897a6a83 2 months a…

Qt 2D绘图之三:绘制文字、路径、图像、复合模式

参考文章链接: Qt 2D绘图之三:绘制文字、路径、图像、复合模式 绘制文字 除了绘制图形以外,还可以使用QPainter::darwText()函数来绘制文字,也可以使用QPainter::setFont()设置文字所使用的字体,使用QPainter::fontInfo()函数可以获取字体的信息,它返回QFontInfo类对象…

Gooxi Eagle Stream 2U双路通用服务器:性能强劲 灵活扩展 稳定易用

人工智能的高速发展开启了飞轮效应,实施数字化变革成为了企业的一道“抢答题”和“必答题”,而数据已成为现代企业的命脉。以HPC和AI为代表的新业务就像节节攀高的树梢,象征着业务创新和企业成长。但在树梢之下,真正让企业保持成长…

图数据库 | 10、图数据库架构设计——高性能图存储架构(上)

老夫在之前的三大篇内容中,介绍了图数据库的三大组件—图计算、图存储以及图查询语言。(都归拢在图数据库原理、架构与应用这个专栏中了,感兴趣的朋友可以在去找阅读。) 接下来,老夫还将继续深化这三大组件&#xff0…

保护数据,构建信任:联邦学习与差分隐私在AI训练中的实践

文章目录 摘要引言什么是联邦学习?AI模型训练中的数据隐私挑战数据隐私面临的主要问题 联邦学习与差分隐私技术联邦学习的关键流程代码示例差分隐私技术联邦学习与差分隐私结合案例 QA环节总结参考资料 摘要 在人工智能快速发展的背景下,模型训练对数据…