10 卷积神经网络CNN(基础篇)

news2024/11/27 22:45:52

文章目录

    • 全连接
    • CNN过程
      • 卷积过程
      • 下采样过程
      • 全连接层
    • 卷积原理
      • 单通道卷积
      • 多通道卷积
      • 改进多通道
    • 总结以及课程代码
      • 卷积改进
        • Padding
        • Stride
      • 下采样过程
        • 大池化层(Max Pooling)
      • 简单卷积神经网络的实现
    • 课程代码

本篇课程来源: 链接
部分文本来源参考: 链接
以及强烈推荐Birandaの

全连接

前篇中的完全由线性层串行而形成的网络层为全连接层,即,对于某一层的每个输出都将作为下一层的输入。即作为下一层而言,每一个输入值和每一个输出值之前都存在权重。

在全连接层中,实际上是把原先空间状态上的信息,转换为了一维的信息,使得原有的空间相对位置所蕴含的信息丢失。

下文仍以MNIST数据集为例。

CNN过程

卷积实际上是把原始图像仍然按照空间的结构来进行保存数据。

在这里插入图片描述

卷积过程

1×28×28指的是 C ( c h a n n l e ) × W ( w i d t h ) × H ( H i g h t ) C(channle) \times W(width) \times H(Hight) C(channle)×W(width)×H(Hight)即通道数 × \times × 图像宽度 × \times × 图像高度​,通道可以理解为层数,通过同样大小的多层图像堆叠才形成了最原始的图。

在这里插入图片描述

可以抽象的理解成原先的图是一个立方体性质的,卷积是将立方体的长宽高按照新的比例进行重新分割而成的。

如下图所示,底层是一个 3 × W × H 3 \times W \times H 3×W×H的原始图像,卷积的处理是每次对其中一个Patch进行处理,也就是从原数图像的左上角开始依次抽取一个 3 × W ′ × H ′ 3 \times W' \times H' 3×W×H的图像对其进行卷积,输出一个 C ′ × W ′ ′ × H ′ ′ C' \times W'' \times H'' C×W′′×H′′的子图。

在这里插入图片描述

下采样过程

下采样的目的是减少特征图像的数据量,降低运算需求。在下采样过程中,通道保持不变,图像的宽度和高度发生改变

在这里插入图片描述

全连接层

先将原先多维的卷积结果通过全连接层转为一维的向量,再通过多层全连接层将原向量转变为可供输出的向量。

在前文的卷积过程与下采样过程,实际上是一种特征提取的手段或者过程,真正用于分类的过程是后续的全连接层。

卷积原理

单通道卷积

设定对于规格为 1 × W × H 1 \times W \times H 1×W×H的原图,利用一个规格为 1 × W ′ × H ′ 1 \times W' \times H' 1×W×H的卷积核进行卷积处理的数乘操作。

则需要从原始数据的左上角开始依次选取与核的规格相同( 1 × W ′ × H ′ 1 \times W' \times H' 1×W×H)的输入数据进行数乘操作,并将求得的数值作为一个Output值进行填充。

在这里插入图片描述
Patch在原图上进行滑动时,每次只滑动一个像素,即包含重复计算的部分

在这里插入图片描述
最后求得的Output的像素矩阵,即是对原图像,在设定的卷积核下的卷积结果,是一个规格为 1 × W ′ × H ′ 1 \times W' \times H' 1×W×H的图像。

在这里插入图片描述

多通道卷积

对于多通道图像( N × W × H N \times W \times H N×W×H),每一个通道是一个单通道的图像( 1 × W × H 1 \times W \times H 1×W×H)都要有一个自己的卷积核( 1 × W ′ × H ′ 1 \times W' \times H' 1×W×H)来进行卷积。

在这里插入图片描述
对于分别求出来的矩阵,需要再次进行求和才能得到最后的输出矩阵,最终的输出矩阵仍然是一个 1 × W ′ × H ′ 1 \times W' \times H' 1×W×H的 图像。

在这里插入图片描述
将平面的图像转为立体的角度即如下图

在这里插入图片描述

改进多通道

多通道卷积中,每次只能把 N N N个通道转变为1个通道,而无法在通道这个维度进行增加或降低。

因此,为了对通道进行更加灵活的操作,可以将原先 N × W × H N \times W \times H N×W×H的图像,利用不同的卷积核对其多次求卷积,由于每次求卷积之后的输出图像为 1 × W ′ × H ′ 1 \times W' \times H' 1×W×H,若一共求解了 M M M次,即可以将此 M M M次的求解结果按顺序在通道(Channel)这一维度上进行拼接,以此来形成一个规格为 M × W ′ × H ′ M \times W' \times H' M×W×H的图像。

在这里插入图片描述

总结以及课程代码

  1. 每个卷积核的通道数与原通道数一致
  2. 卷积核的数量与输出通道数一致
  3. 卷积核的大小与图像大小无关

上述中所提到的卷积核,是指的多通道的卷积核,而非前文中提到的二维的。
综上所述为了使下图所表征的过程成立,即若需要使得原本为 n × w i d t h i n × h e i g h t i n n \times width_{in} \times height_{in} n×widthin×heightin的图像转变为一个 m × w i d t h o u t × h e i g h t o u t m \times width_{out} \times height_{out} m×widthout×heightout的图像,可以利用 m m m个大小为 n × k e r n e l _ s i z e w i d t h × k e r n e l _ s i z e h e i g h t n \times kernel\_size_{width} \times kernel\_size_{height} n×kernel_sizewidth×kernel_sizeheight的卷积核。

在这里插入图片描述
则在实际操作中,即可抽象为利用一个四维张量作为卷积核,此四维张量的大小为 m × n × k e r n e l _ s i z e w i d t h × k e r n e l _ s i z e h e i g h t m \times n \times kernel\_size_{width} \times kernel\_size_{height} m×n×kernel_sizewidth×kernel_sizeheight

import torch
in_channels, out_channels = 5, 10
width, height = 100, 100

kernel_size = 3 #默认转为3*3,最好用奇数正方形

#在pytorch中的数据处理都是通过batch来实现的
#因此对于C*W*H的三个维度图像,在代码中实际上是一个B(batch)*C*W*H的四个维度的图像
batch_size = 1

#生成一个四维的随机数
input = torch.randn(batch_size, in_channels, width, height)

#Conv2d需要设定,输入输出的通道数以及卷积核尺寸
conv_layer = torch.nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size)

output = conv_layer(input)

print(input.shape)
print(output.shape)
print(conv_layer.weight.shape)

输出结果:
在这里插入图片描述

卷积改进

Padding

若对于一个大小为 N × N N \times N N×N的原图,经过大小为 M × M M \times M M×M的卷积核卷积后,仍然想要得到一个大小为 N × N N \times N N×N的图像,则需要对原图进行Padding,即外围填充。

例如,对于一个 5 × 5 5 \times 5 5×5的原图,若想使用一个 3 × 3 3 \times 3 3×3的卷积核进行卷积,并获得一个同样 5 × 5 5 \times 5 5×5的图像,则需要进行Padding,通常外围填充0

在这里插入图片描述

input = [3,4,6,5,7,
         2,4,6,8,2,
         1,6,7,8,4,
         9,7,4,6,2,
         3,7,5,4,1]

#将输入变为B*C*W*H
input = torch.Tensor(input).view(1, 1, 5, 5)

#偏置量bias置为false
conv_layer = torch.nn.Conv2d(1, 1, kernel_size=3, padding=1, bias=False)

#将卷积核变为CI*CO*W*H
kernel = torch.Tensor([1,2,3,4,5,6,7,8,9]).view(1, 1, 3, 3)

#将做出来的卷积核张量,赋值给卷积运算中的权重(参与卷积计算)
conv_layer.weight.data = kernel.data

output = conv_layer(input)

print(output)

Stride

本质上即是Batch的步长,在Batch进行移动时,每次移动Stride的距离,以此来有效降低图像的宽度与高度。

例如,对于一个 5 × 5 5 \times 5 5×5的原图,若想使用一个 3 × 3 3 \times 3 3×3的卷积核进行卷积,并获得一个 2 × 2 2 \times 2 2×2的图像,则需要进行Stride,且Stride=2

import torch
input = [3,4,6,5,7,
         2,4,6,8,2,
         1,6,7,8,4,
         9,7,4,6,2,
         3,7,5,4,1]

#将输入变为B*C*W*H
input = torch.Tensor(input).view(1, 1, 5, 5)

#偏置量bias置为false
conv_layer = torch.nn.Conv2d(1, 1, kernel_size=3, stride=2, bias=False)

#将卷积核变为CI*CO*W*H
kernel = torch.Tensor([1,2,3,4,5,6,7,8,9]).view(1, 1, 3, 3)

#将做出来的卷积核张量,赋值给卷积运算中的权重(参与卷积计算)
conv_layer.weight.data = kernel.data

output = conv_layer(input)

print(output)

下采样过程

大池化层(Max Pooling)

对于一个 M × M M \times M M×M图像而言,通过最大池化层可以有效降低其宽度和高度上的数据量,例如通过一个 N × N N \times N N×N的最大池化层,即将原图分为若干个 N × N N \times N N×N大小的子图,并在其中选取最大值填充到输出图中,此时输出图的大小为 M N × M N \frac{M}{N} \times \frac{M}{N} NM×NM

在这里插入图片描述

import torch
input = [3,4,6,5,
         2,4,6,8,
         1,6,7,8,
         9,7,4,6]

input = torch.Tensor(input).view(1, 1, 4, 4)

#kernel_size=2 则MaxPooling中的Stride也为2
maxpooling_layer = torch.nn.MaxPool2d(kernel_size=2)

output = maxpooling_layer(input)

print(output)

简单卷积神经网络的实现

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

class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
        self.pooling = torch.nn.MaxPool2d(2)
        self.fc = torch.nn.Linear(320, 10)

    def forward(self, x):
        batch_size = x.size(0)
        x = self.pooling(F.relu(self.conv1(x)))
        x = self.pooling(F.relu(self.conv2(x)))
        x = x.view(batch_size, -1)
        x = self.fc(x)
        return x

课程代码

import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
 
# prepare dataset
 
batch_size = 64
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
 
train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
 
# design model using class
 
class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
        self.pooling = torch.nn.MaxPool2d(2)
        self.fc = torch.nn.Linear(320, 10)
 
 
    def forward(self, x):
        # flatten data from (n,1,28,28) to (n, 784)
        batch_size = x.size(0)
        x = F.relu(self.pooling(self.conv1(x)))
        x = F.relu(self.pooling(self.conv2(x)))
        x = x.view(batch_size, -1) # -1 此处自动算出的是320
        x = self.fc(x)
 
        return x
 
 
model = Net()
 
# construct loss and optimizer
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
 
# training cycle forward, backward, update
 
 
def train(epoch):
    running_loss = 0.0
    for batch_idx, data in enumerate(train_loader, 0):
        inputs, target = data
        optimizer.zero_grad()
 
        outputs = model(inputs)
        loss = criterion(outputs, target)
        loss.backward()
        optimizer.step()
 
        running_loss += loss.item()
        if batch_idx % 300 == 299:
            print('[%d, %5d] loss: %.3f' % (epoch+1, batch_idx+1, running_loss/300))
            running_loss = 0.0
 
 
def test():
    correct = 0
    total = 0
    with torch.no_grad():
        for data in test_loader:
            images, labels = data
            outputs = model(images)
            _, predicted = torch.max(outputs.data, dim=1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    print('accuracy on test set: %d %% ' % (100*correct/total))
 
 
if __name__ == '__main__':
    for epoch in range(10):
        train(epoch)
        test()

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

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

相关文章

LSTM已死,Transformer当立(LSTM is dead. Long Live Transformers! ):上

回想一下在Seq2seq模型中,如何使用Attention。这里简要回顾一下【1】介绍的方法2(并以此为基础展开对Transformer的讨论)。 下图中包含一个encoder(左)和一个decoder(右)。对于decoder来说,给定一个输入,得到输出,如何进一步得到context vector 呢? 我们需要根据和…

网络工程师一定要学会的知识点:OSPF,今天给大家详细介绍

1. OSPF 概念OSPF(Open Shortest Path First 开放式最短路径优先)是一种动态路由协议,属于内部网关协议(Interior Gateway Protocol,简称 IGP),是基于链路状态算法的路由协议。2. OSPF 的运行原理(1)OSPF 的…

后端开发必懂nginx面试40问

什么是Nginx? Nginx是一个 轻量级/高性能的反向代理Web服务器,用于 HTTP、HTTPS、SMTP、POP3 和 IMAP 协议。他实现非常高效的反向代理、负载平衡,他可以处理2-3万并发连接数,官方监测能支持5万并发,现在中国使用ngin…

Flink面试题

一 基础篇Flink的执行图有哪几种?分别有什么作用Flink中的执行图一般是可以分为四类,按照生成顺序分别为:StreamGraph-> JobGraph-> ExecutionGraph->物理执行图。1)StreamGraph顾名思义,这里代表的是我们编写…

RabbitMQ安装及配置

目录1.下载和安装1.1 下载1.2. 安装1.3 测试1.4 卸载管理界面2.1 添加用户2.2 创建Virtual Hosts2.3. 设置权限1.下载和安装 1.1 下载 1.下载Erlang的rpm包 RabbitMQ是Erlang语言编写,所以Erang环境必须要有,注:Erlang环境一定要与RabbitMQ…

每天一道大厂SQL题【Day08】

每天一道大厂SQL题【Day08】 大家好,我是Maynor。相信大家和我一样,都有一个大厂梦,作为一名资深大数据选手,深知SQL重要性,接下来我准备用100天时间,基于大数据岗面试中的经典SQL题,以每日1题…

Learning C++ No.7

引言: 北京时间:20223/2/9/22:20,距离大一下学期开学还有2天,昨天收到好消息,开学不要考试了,我并不是害怕考试,考试在我心里,地位不高,可能只有当我挂了,才能…

自媒体人都在用的免费音效素材网站

视频剪辑、自媒体人必备的剪辑音效素材网站,免费下载,建议收藏! 1、菜鸟图库 音效素材下载_mp3音效大全 - 菜鸟图库 菜鸟图库是一个综合性素材网站,站内涵盖设计、图片、办公、视频、音效等素材。其中音效素材就有上千首&#xf…

数学建模学习笔记(20)典型相关分析

典型相关分析概述:研究两组变量(每组变量都可能有多个指标)之间的相关关系的一种多元统计方法,能够揭示两组变量之间的内在联系。 典型相关分析的思想:把多个变量和多个变量之间的相关化为两个具有代表性的变量之间的…

【沁恒WCH CH32V307V-R1开发板读取板载温度实验】

【沁恒WCH CH32V307V-R1开发板读取板载温度实验】1. 前言2. 软件配置2.1 安装MounRiver Studio3. ADC项目测试3.1 打开ADC工程3.2 编译项目4. 下载验证4.1 接线4.2 演示效果5. 小结1. 前言 ADC 模块包含 2 个 12 位的逐次逼近型的模拟数字转换器,最高 14MHz 的输入时…

pandas——plot()方法可视化

pandas——plot()方法可视化 作者:AOAIYI 创作不易,如果觉得文章不错或能帮助到你学习,记得点赞收藏评论哦 在此,感谢你的阅读 文章目录pandas——plot()方法可视化一、实验目的二、实验原理三、实验环境四、实验内容五、实验步骤…

Python文件的属性获取,重命名,目录的创建,显示和改变

1. 文件的属性获取 os.stat()函数可以获取文件的属性,该函数会返回一个和系统平台有关的stat_result对象, 具备一组可访问的属性,可以通过 stat_result.attribute 这样的格式来访问各个属性的值。 字 段描 述st_modeinode 保护模式st_inoin…

115.Android 简单的多级树结构列表+正常列表结合使用(RecyclerView)

1.第一步 导入需要用到的依赖库: //RecyclerView implementation com.android.support:recyclerview-v7:28.0.0 //RecyclerAdapter implementation com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.28 //刷新控件 implementation com.scwang.smartrefresh:SmartRefre…

python-QGIS环境配置

系统:win10 QGIS的下载及安装 在QGIS的官网下载安装包进行安装 下载得到QGIS-OSGeo4W-3.22.16-1.msi的安装包,除了安装路径,基本下一步就可以安装了安装完成后打开QGIS程序文件夹,在./QGIS xx.xx/bin/目录下有个python-qgis-ltr.b…

SpringBoot 自定义注解实现涉密字段脱敏

关于数据脱敏,网上的文章都是硬编码规则,比如对身份证,手机号,邮件地址等固定写法脱敏。本文在此基础上,拓展动态从数据库查出涉密关键字执行脱敏操作。数据脱敏:把系统里的一些敏感数据进行加密处理后再返…

【prism】路由事件映射到Command命令

在之前的一篇文章中,我介绍了普通的自定义事件: 【wpf】自定义事件总结(Action, EventHandler)_code bean的博客-CSDN博客_wpf action可以说通过Action和EventHandle,自定义事件是相当的方便简单了。https…

winform开发心得

最近一直在从事winform的开发,每次都是需要从网上查找资料才能对应具体风格要求,现在总结一下。 ui方面可以使用CSkin对应的一套ui,使用步骤 1.在窗口界面,工具箱空白处点击右键,弹出菜单有个”选择项“,点…

ISO7320FCQDRQ1数字隔离器LMG1025QDEETQ1半桥GaN驱动器

1、数字隔离器 DGTL ISO 3000VRMS 2CH 8SOIC型号:ISO7320FCQDRQ1批次:新技术:容性耦合类型:通用隔离式电源:无通道数:2输入 - 侧 1/侧 2:2/0通道类型:单向电压 - 隔离:30…

C语言深度剖析 -- 32个关键字(下)

文章目录if else 语句bool 与 0 的比较float 与 0 的比较指针与 0 的比较switch case 语句do while for 关键字goto语句真的没人使用吗?void 关键字void能否定义变量?void定义指针void修饰函数返回值和作为函数参数return关键字const关键字const修饰的只…

《电脑技术-系统篇》

《电脑技术-系统篇》 重装须知 ​ 备份桌面上资料,包括系统盘中其他的个人文件等。 一、重装系统 ​ 重装系统是指对计算机的操作系统进行重新的安装。当用户错误操作或遭受病毒、木马程序的破坏,系统中的重要文件就会受损导致错误,甚至崩…