[ConvNet]卷积神经网络概念解析

news2025/7/18 21:51:57

在初步接触了深度学习以后,我们把目光投向对于一些图像的识别。

其实在d2l这本书中,我们接触过用深度神经网络去识别一个图像,并且对其进行一个分类操作,核心原理是将图像展开成一维tensor,然后作为特征进行检测。

其实理论是这个思路和方式都没有问题,怀就坏在这个图片的大小可能是不固定的,如果是288×288×3的图片,展开成张量然后拿去训练,那么特征值的数目就会很恐怖,对构建神经网络产生了一个巨大的开销。

为了避免这种开销,有效地缩小构建网络,训练模型的开销(也就是少点参数),我们使用卷积神经网络

1.什么是卷积层

卷积层的这个卷积,在计算机图形学中的应用同样很广泛,而且概念上也是一样的.

其实严格来说,我们这个操作并不能称之为卷积操作,因为数学论文中的卷积操作需要额外的一个步骤就是倒转卷积核,在这里我们仅仅是对固定的层数和区域做运算而已.

在大一的时候,我们接触过滑动窗口算法,用来进行平滑的操作,,或者就像是我们在ps中进行图像处理的时候,所用到的污点修复工具, 也是一种卷积.

这其实就是卷积神经网络中的一部分,只不过严格来说这个操作被称之为pooling(池化)

首先我们要介绍一下卷积核 / 过滤器  / convolution kernel / filtering

就是一个小型矩阵,深度和被卷积对象匹配(为什么这里说被卷积对象而不是输入,这个和我们后面的一个叫做分离卷积的东西有关,当然这个是后话了)

过滤器是怎么样工作的,或者说卷积的数学原理是什么,差不多就这样,那个小的过滤矩阵被称之为核

然后类似滑动窗口的操作,只不过这次窗口被严格限制在了原本张量范围内,窗口的每个计算,对应着目标中一个数字的输出

比如这张图上,这个核起到的作用就是:垂直边缘检测,可以看一下效果

很好地展现了一个垂直的边缘检测器,这个检测器也是我们常用的类型了

还有一些其他的核

但是迄今为止,我们说到的东西仅仅止步于数学和图形学,神经网络呢???

别急,核心的数目很多,种类很多,能达到的效果都不一样,如果能检测到更适合我们手中样本的数据,就是训练呗.

比如这样一个9*9大小的卷积核心,我们可以设置参数w1--w9, 后面如果有需要还可以使用bias还有激活函数之类的东西进行处理,紧接着根据参数开始训练,这就是我们的一个核心思路.

2.卷积层的相关参数

这里我们展示一个比较完整的卷积神经网路的图像.

我们可以看到,现在我们的卷积是在三维上进行处理的,每个核的卷积结果都是一个二维矩阵.

如图所示

而具体的计算方法可以是这样子的

在这种比较正常的卷积操作中,我们设置一些相关的参数,并且将他们的名称作为约定俗成

有关参数

n:输入的长宽度

f:卷积核的长宽

s;卷积运算的移动步长

p:填充的长度(注意这个填充长度,不同的材料中表示的含义不太一样)

num:卷积核的数目,卷积核的数目在一般情况下决定了输出的三维张量的频道数量(频道是深度的另一种称呼)

这是一张纯三维的展示图像,途中我们可以看到这里又不止一个卷积核,每个卷积核都能得到一个结果.这里其实存在一个物理意义,每个卷积核都是提取自己需要的特征,比如A获取的是垂直边缘,B获取的是水平边缘.叠加起来就是我们需要的东西(比如轮廓图)

填充和步长

在进行卷积的时候,可以注意到一个问题,随着卷积的增加,虽然特征提取了,但是输出的长宽是肉眼可见的不断变小的.并且步长也会直接影响输出的因素.

而且,卷积也会导致对于边缘部分的采集不充分,所以对于这种情况,我们的处理方法是在原本的输入基础上,在四周填充长度为p的部分,使得卷积出来的结果大小发生一些变化

如图所示:

步长

其实在这里我们可以看到一个计算公式

size=\left ( \frac{n+2*p-f}{s}+1 \right )

这个公式即可得到卷积层输出的结果长度,如果是想要完成一些保持操作,可以选择让其size=n

3.池化层pool

池化层其实个人感觉和卷积没有本质上的区别,都是对局部特征进行提取,然后够获取特征部分,压缩输入,节约计算.或者一些其他的奇奇怪怪的功能.

但是真说计算上的区别,那么就是池化层不需要任何训练参数,比较常用的两个池化核心是最大池化和平均池化.

举个例子,这就是average pooling

4.CNN的简单展示

下面是一段代码,用来展示一个简单的卷积操作的底层原理

import torch
from torch import nn
from d2l import torch as d2l

#cross-correlation,这个被称之为卷积的东西其实不能算是卷积运算
#一个纯粹的数学方法,默认卷积步长为1
def corr2d(X, K):  #@save
    """计算二维互相关运算"""
    h, w = K.shape
    Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            Y[i, j] = (X[i:i + h, j:j + w] * K).sum()
    return Y


X = torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])
K = torch.tensor([[0.0, 1.0], [2.0, 3.0]])

print('进行一下测试',corr2d(X, K))


#定义一个卷基层:这个卷及层只有一个核。。。而且只能对一个二维进行卷积
class Conv2D(nn.Module):
    def __init__(self, kernel_size):
        super().__init__()
        self.weight = nn.Parameter(torch.rand(kernel_size)) #还随机生成是吧。。。。
        self.bias = nn.Parameter(torch.zeros(1))            #广播机制计算?

    def forward(self, x):
        return corr2d(x, self.weight) + self.bias           #除了这个乘法的计算结果不一样,其他的还行
    
#创造一个用来边缘检测的图
X = torch.ones((6, 8))
X[:, 2:6] = 0
print('展示一下这个张良边缘\n',X)

#设置一个竖直边缘检测核心
K = torch.tensor([[1.0, -1.0]])
Y = corr2d(X, K)
print('展示一下这个检测结果\n',X)

#----------------------卷积层的训练--------------------------#

# 构造一个二维卷积层,它具有1个输出通道和形状为(1,2)的卷积核
conv2d = nn.Conv2d(1,1, kernel_size=(1, 2), bias=False)
#参数分别为:输入通道数目,输出通道数目(卷积核数目),卷积核是个啥,是否需要bias

# 这个二维卷积层使用四维输入和输出格式(批量大小、通道、高度、宽度),
# 其中批量大小和通道数都为1
X = X.reshape((1, 1, 6, 8))
Y = Y.reshape((1, 1, 6, 7))
lr = 3e-2  # 学习率

for i in range(10):
    Y_hat = conv2d(X)     #先算一下
    l = (Y_hat - Y) ** 2  #计算损失
    conv2d.zero_grad()    #清空梯度
    l.sum().backward()    #反响传播计算梯度
    conv2d.weight.data[:] -= lr * conv2d.weight.grad   # 迭代卷积核,具体的迭代计算。。。。
    if (i + 1) % 2 == 0:
        print(f'epoch {i+1}, loss {l.sum():.3f}')



5.ResNet

一般来说,我们正常去训练一些数据差不多都是这个样子的,这就是我们平时所谓的'前向传播'

但是我们之前就知道,神经网络的深度够深,或者是出现一些不适应情况的时候,会产生'梯度爆炸'/'梯度消失'两种情况,并且在卷积中,我们渴望去减少计算量,所以出现了残差网络

 所以在某些步骤可以选择跳过:,在向前传递的时候,直接把输出交给后面的层

这样每一个跳过的部分我们都称之为一个residual block,这种跳跃向前传递我们称之为: skip connection

假设我们条约了i个步骤,从 n层输出到 n+i 层输出

a[n+i] = ReLU( z[n+i] + a[i] ) = ReLU 这里要把条约之前的输入一起加上

,这是一个关键步骤.....

6.inception

初始网路块

同时完成卷积层还有池化层的操作,并且将他们的结果拼接在一起,这个东西叫做inception层已经肥肠勉强了,直接叫模块算了...

初始化网络

初始网络的模块就是一次可以提供多个计算并且合并为一个输出\

有点类似我们之前在博客上写的神经网络块

7.mobileNet

1*1的卷积有很多的用途

用来降低通道大小(深度)就是其中最重要的一个用途

使用瓶颈的思路,将大规模的乘法运算改变为两个使用瓶颈缩减一些计算量

mobileNet(移动卷积网络)

(目标:计算损耗更小)

计算损失 = 核的单位数目*输出结果的单位数目,前面适当加上一些中间的1*1卷积层可以用来处理一些简单的深度降低操作,介于一部分的计算

可分离深度卷积:先进行逐层卷积,然后进行逐个卷积,将两个计算拆分开,形成一个

逐层卷积:

卷积层:卷积层的每个卷积核都是二维,而且每个卷积只负责对应输入的一个层.

输出:输出的每一层都是输入的每一层对应的二维卷积结果,

意思就是这种:

计算成本为:卷积核面积*输出二维面积*层数

逐点卷积:

接下来就是沿着第三维度的方向,然后进行1*1的卷积核,计算出最终的卷积产物

计算成本=卷积核体积*输出的体积

将这个部分封装成一个块

8.基于keras的简单应用:数字图像识别

import numpy as np
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Dense, Flatten
from keras.utils import to_categorical
import tensorflow._api.v2.compat.v1 as tf
tf.disable_v2_behavior()

#get dataSet
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

train_images = (train_images / 255) - 0.5
test_images = (test_images / 255) - 0.5

train_images=train_images.reshape(-1, 28, 28, 1)
test_images=test_images.reshape(-1, 28, 28, 1)


num_filters = 8
filter_size = 2
pool_size = 4
# Build the model.
model = Sequential([ 
    Conv2D(num_filters, filter_size, input_shape=(28, 28, 1), activation='relu'),
    MaxPooling2D(pool_size=pool_size),
    Flatten(),                        #展开层
    Dense(10, activation='softmax'),  #密集层,使用softmax进行输出
])

model.compile( 'adam', loss='categorical_crossentropy', metrics=['accuracy'])

model.fit(
train_images,                        #训练
to_categorical(train_labels),
epochs=5,
validation_data=(test_images,        #测试
to_categorical(test_labels)),
)

# Save the model to disk.
model.save_weights('cnn.mnist')
                   
# Load the model from disk later using:
model.load_weights('cnn.mnist')


# Predict on the test dataset
predictions = model.predict(test_images)

# Get the predicted labels
predicted_labels = np.argmax(predictions[:8], axis=1)

# Print the predicted labels
print('Predicted labels:', predicted_labels[:8])

# Print the real labels
print('Real labels:', test_labels[:8])

9.迁移学习以及数据增强

迁移学习:

(又回来了真的是...之前的说法.把一个神经网络的计算结果迁移到另一个神经网络的输入)

再深度学习/计算机视觉的应用中,其实更贴切的一种说法是借用其他人已经训练好的一部分层和参数

比如极端一点的,我们获取到一个作者已经训练好的深度学习网络,获取架构以及参数

前面前几层的参数我们都不做处理,只有最后一层改成我们自己需要的softmax层输出(举例)

然后根据我们自己的数据集合,只训练自己的一层即可,前面几层可以视为别人帮我准备好的特征提取器

(根据我们自己数据集合的大小,多少参数被冻结也是按照我们自己的想法来,如果数据足够大,我们就可以自己训练所有的参数)

数据增强:

:????:这不就数据生成:

对于图像来说:裁剪,变色,滤镜,失真,扭曲,生成相关目标的新数据

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

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

相关文章

JAVA基础(JAVA SE)学习笔记(二)变量与运算符

前言 1. 学习视频: 尚硅谷Java零基础全套视频教程(宋红康2023版,java入门自学必备)_哔哩哔哩_bilibili 2023最新Java学习路线 - 哔哩哔哩 正文 第一阶段:Java基本语法 1. Java 语言概述 JAVA基础(JAVA SE)学习…

源码解析flink文件连接源TextInputFormat

背景: kafka的文件系统数据源可以支持精准一次的一致性,本文就从源码看下如何TextInputFormat如何支持状态的精准一致性 TextInputFormat源码解析 首先flink会把输入的文件进行切分,分成多个数据块的形式,每个数据源算子任务会被分配以读取…

【面试经典150 | 区间】插入区间

文章目录 Tag题目解读题目来源解题思路方法一:合并区间方法二:模拟 其他语言python3 写在最后 Tag 【模拟】【数组】 题目解读 给定一个含有多个无重叠区间的数组,并且数组已经按照区间开始值升序排序。在列表中插入一个新的区间&#xff0…

unity动画_UI动画案例 c#

首先我们打开一个项目 在这个初始界面我们需要做一些准备工作 创建基础通用包 在场景上创建一个Cube 选中Cube 在Window下点击Animation拖拽至运行窗口 点击创建 保存后 这个操作是给Cube添加了一个组件 对Cube_添加一个Position动画 设置几个帧位置的坐标(x,y,z)值 点击运行测…

PHP 如何查看php函数源码

一、在git找到php对应的版本 找到对应的分支版本可以下载也可以在线直接查看 通过这个地址 https://github.com/php/php-src 二、下面已shuffle函数举例,版本为7.4 找到对应的版本进入 点击ext,这个文件夹里面是存放函数的目录 在文件夹里搜不到stu…

Linux使用rpm包安装mysql5.7

以前安装过mysql 前言:检查以前是否装有mysql rpm -qa|grep -i mysql安装了会显示:   bt-mysql57-5.7.31-1.el7.x86_64 停止mysql服务和删除之前安装的mysql rpm -e bt-mysql57-5.7.31-1.el7.x86_64查找并删除mysql相关目录 find / -name mysql/va…

react+ts手写cron表达式转换组件

前言 最近在写的一个分布式调度系统,后端同学需要让我传入cron表达式,给调度接口传参。我去了学习了解了cron表达式的用法,发现有3个通用的表达式刚好符合我们的需求: 需求 每天 xx 的时间: 0 11 20 * * ? 上面是…

jQuery+AJAX请求的统一封装

记录一下使用jQueryAJAX对http请求的统一封装 很久都没有使用jquery和ajax的组合了,这里记录一下jquery和ajax的组合简单封装 将来或许有机会重新启用这个组合 新建jquery.request.js;demo目录结构如下 const baseURL http://127.0.0.1:8116;// con…

4K壁纸小程序源码 全内容自动采集

全内容自动采集 4K壁纸小程序源码,带流量主。用的都是一个接口,不过这个不知是谁改的,成了LSP版,是真色啊,专搜小姐姐。 4K壁纸,静态壁纸,头像等都有保留,界面广告位很多&#xff0c…

List小练习,实现添加图书,并且有序遍历

SuppressWarnings({"all"})public static void main(String[] args) {List list new LinkedList(); // List list new Vector(); // List list new ArrayList();list.add(new Book1("红楼小梦",35.5,"曹雪芹"));list.add(new B…

算法-堆/归并排序-排序链表

算法-堆/归并排序-排序链表 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/sort-list/description/?envTypestudy-plan-v2&envIdtop-interview-150 1.2 题目描述 2 优先级队列构建大顶堆 2.1 思路 优先级队列构建小顶堆链表所有元素放入小顶堆依次取出堆顶…

【Java 进阶篇】JavaScript BOM History 详解

当用户浏览网页时,可以使用JavaScript的BOM (Browser Object Model)中的History对象来访问浏览器的历史记录。这个对象允许您在不更改页面的情况下导航到不同的历史记录项,或者查看有关用户访问过的页面的信息。 在本篇博客中,我们将围绕Jav…

IIS7.0解析漏洞

IIS7.0解析漏洞 实验环境 windows server 2008 r2(x64) IIS 7 phpStudyIIS 2016版本 漏洞条件 1. php.ini里的cgi.cgi_pathinfo1 2. IIS7在Fast-CGI运行模式下 漏洞复现 先搭建IIS7 出现如下界面安装成功 安装phpstudy ,使用较老的版…

通过核密度分析工具建模,基于arcgis js api 4.27 加载gp服务

一、通过arcmap10.2建模,其中包含三个参数 注意input属性,选择数据类型为要素类: 二、建模之后,加载数据,执行模型,无错误的话,找到执行结果,进行发布gp服务 注意,发布g…

Vue3语法-双向绑定

点击加入精英计划可以加入 点击名字可以删除 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><!-- vue.js --><script src"https://unpkg.com/vue3/dist/vue.glob…

Nested loop(PostgreSQL 14 Internals翻译版)

连接类型和方法 连接是SQL语言的一个关键特性;它们是其力量和灵活性的基础。行集(要么直接从表中检索&#xff0c;要么作为某些其他操作的结果接收)总是成对连接。 有几种类型的连接&#xff1a; 内连接。 内连接(指定为“INNER JOIN”或简称为“JOIN”)由满足特定连接条件的…

单一职责模式

三、单一职责模式 单一职责模式概念1、装饰着模式&#xff08;Decorator&#xff09;动机&#xff08;Motivation)模式定义代码具体实现要点总结 2、桥模式&#xff08;Bridge&#xff09;动机 &#xff08;Motivation)模式定义代码具体实现要点总结 单一职责模式概念 在软件组…

MTK APP实现动态修改logo和开机动画

MTK APP实现动态修改logo和开机动画 前言一、修改对新分区的权限1.修改开机动画对新分区的权限2.修改系统APP对新分区的权限3.修改SE权限,不然编译会报错4.修改开机动画文件&#xff0c;让其加载新分区中的文件 二、系统APP代码使用1.系统app修改开机logo2.系统app修改开机动画…

设计模式:工厂方法模式(C#、JAVA、JavaScript、C++、Python、Go、PHP):

本节主要介绍设计模式中的工厂方法模式。 简介&#xff1a; 工厂方法模式&#xff0c;它是对简单工厂模式的进一步抽象化&#xff0c;其好处是可以使系统在不修改原来代码的情况下引进新的产品&#xff0c;即满足开闭原则。 它定义了一个用于创建对象的工厂接口&#xff0c;让…

Nginx正向代理,反向代理,负载均衡

Nginx正向代理&#xff0c;反向代理&#xff0c;负载均衡 Nginx当中有两种代理方式&#xff1a; 七层代理&#xff08;http协议&#xff09; 四层代理&#xff08;tcp/udp流量转发&#xff09; 七层代理&#xff1a;七层代理&#xff0c;代理的是http的请求和响应 客户端请求…