深度学习笔记:卷积神经网络(1)

news2024/10/2 10:25:30

1 卷积神经网络整体结构

卷积神经网络(CNN)相比全连接网络多了卷积层和池化层。对于全连接网络,所有相邻层的神经元都用Affine层进行连接,如图中即为Affine-ReLU的连接组合。
在这里插入图片描述
卷积神经网络则包含卷积层和池化层与激活函数相连,其结构如下:
在这里插入图片描述

2 全连接层对图象识别的局限性

我们之前一直使用全连接网络识别mnist数据集,但这其实是一个低效的方法。对于28 X 28的图片信息,我们必须将其拉长成1 X 784的数据再传入网络。这一操作不但需要大量神经元作为输入层,而且当我们将二维图片拉伸为一维后,会丢失原图中部分特征信息,如邻近像素值的关系。

CNN可以保留原图二维的形状同时识别图像,从而保留原图中的各类特征。CNN卷积层输入输出数据被称为特征图

3 卷积运算

在这里插入图片描述
如图,卷积运算中我们用一个矩阵(被称为卷积核),在图片矩阵中“滑动”,并和图片矩阵重合部分进行内积运算(即将对应位置元素相乘在加和)。最终将各个部分内积结果汇总成一个新的矩阵作为输出特征图

填充(paddling):通过在原图片矩阵周围拓展0以增大原矩阵形状,这一操作用于控制输出特征图的形状和大小。
在这里插入图片描述
如图,使用1的填充,可以使得输出特征图大小和原矩阵一样为4 X 4,这样防止了深度学习中由于不断卷积导致矩阵被不断缩小。

步幅(stride):步幅为每一次卷积核在图片上移动的步长,步长会对提取到的特征和输出特征图形状有影响

对于一个形状(w,h)的输入图,步幅为S,填充为P,卷积核(cw, ch),输出特征图形状为((w + 2P - cw) / s + 1, (h + 2P - ch) / 2 + 1)

三维数据卷积运算

对于有多通道的图片(如RGB图片),需要使用和通道数一致的卷积核数量,其得到的特征图通道数恒为1.可以使用多个卷积核分别和图片做卷积运算,将每一个运算得到的特征图累积成一个多通道特征图

在这里插入图片描述
在这里插入图片描述
如图,对于形状为(C,H,W)的输入图,使用FN个形状为(C,FH,FW)的卷积核,得到形状为(FN,OH,OW)的输出特征图

4 批处理

和全连接网络的批处理类似,卷积神经网络批处理数据为4维数据,按照(batch_num, channel, height, width)的顺序保存数据

池化层

池化层会缩小特征图长宽方向上大小,其作用为将一片区域内的元素缩为一个元素。如Max池化取该区域内最大值,而Average池化取区域所有元素平均值。(在图像识别中我们一般使用max池化)

一般来说,我们池化窗口的大小和卷积核步幅设为相同值,如下图中池化层窗口为2 X 2,同时卷积核步幅也为2
在这里插入图片描述
池化层不存在参数,因此不需要进行学习。另外池化层不会改变输入输出的通道数。对输入特征图的每一个通道池化层会单独处理

python实现卷积层和池化层

实现卷积层可以使用im2col函数,该函数将批处理的4维数据转换为2维矩阵以适合滤波器(权重)。如对于通道为3的7X7数据。im2col展开结果为

im2col的参数
在这里插入图片描述

def im2col(input_data, filter_h, filter_w, stride=1, pad=0):
    """

    Parameters
    ----------
    input_data : 由(数据量, 通道, 高, 长)的4维数组构成的输入数据
    filter_h : 滤波器的高
    filter_w : 滤波器的长
    stride : 步幅
    pad : 填充

    Returns
    -------
    col : 2维数组
    """
    N, C, H, W = input_data.shape
    out_h = (H + 2*pad - filter_h)//stride + 1
    out_w = (W + 2*pad - filter_w)//stride + 1

    img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')
    col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))

    for y in range(filter_h):
        y_max = y + stride*out_h
        for x in range(filter_w):
            x_max = x + stride*out_w
            col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]

    col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)
    return col

该程序将输入img批处理中每一个特征图展开为一个一维数组col,其中数组长度为通道数 X 图片矩阵长 X 图片矩阵宽。

卷积层的实现

class Convolution:
    def __init__(self, W, b, stride=1, pad=0):
        self.W = W
        self.b = b
        self.stride = stride
        self.pad = pad
        
        # 中间数据(backward时使用)
        self.x = None   
        self.col = None
        self.col_W = None
        
        # 权重和偏置参数的梯度
        self.dW = None
        self.db = None

    def forward(self, x):
        FN, C, FH, FW = self.W.shape
        N, C, H, W = x.shape
        out_h = 1 + int((H + 2*self.pad - FH) / self.stride)
        out_w = 1 + int((W + 2*self.pad - FW) / self.stride)

        col = im2col(x, FH, FW, self.stride, self.pad)
        col_W = self.W.reshape(FN, -1).T

        out = np.dot(col, col_W) + self.b
        out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)

        self.x = x
        self.col = col
        self.col_W = col_W

        return out

    def backward(self, dout):
        FN, C, FH, FW = self.W.shape
        dout = dout.transpose(0,2,3,1).reshape(-1, FN)

        self.db = np.sum(dout, axis=0)
        self.dW = np.dot(self.col.T, dout)
        self.dW = self.dW.transpose(1, 0).reshape(FN, C, FH, FW)

        dcol = np.dot(dout, self.col_W.T)
        dx = col2im(dcol, self.x.shape, FH, FW, self.stride, self.pad)

        return dx

在正向传播中,我们使用im2col将输入数据展开,和经过reshape的卷积核进行点乘得到输出值(如图示)
在这里插入图片描述
对于反向传播,我们的实现方法和Affline层完全一致(因为本质上都是矩阵乘法反向传播)。只是这里要在最后将输出的col再转换回图片形状(使用方法col2im)

池化层python实现

class Pooling:
    def __init__(self, pool_h, pool_w, stride=1, pad=0):
        self.pool_h = pool_h
        self.pool_w = pool_w
        self.stride = stride
        self.pad = pad
        
        self.x = None
        self.arg_max = None

    def forward(self, x):
        N, C, H, W = x.shape
        out_h = int(1 + (H - self.pool_h) / self.stride)
        out_w = int(1 + (W - self.pool_w) / self.stride)

        col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)
        col = col.reshape(-1, self.pool_h*self.pool_w)

        arg_max = np.argmax(col, axis=1)
        out = np.max(col, axis=1)
        out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)

        self.x = x
        self.arg_max = arg_max

        return out

    def backward(self, dout):
        dout = dout.transpose(0, 2, 3, 1)
        
        pool_size = self.pool_h * self.pool_w
        dmax = np.zeros((dout.size, pool_size))
        dmax[np.arange(self.arg_max.size), self.arg_max.flatten()] = dout.flatten()
        dmax = dmax.reshape(dout.shape + (pool_size,)) 
        
        dcol = dmax.reshape(dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1)
        dx = col2im(dcol, self.x.shape, self.pool_h, self.pool_w, self.stride, self.pad)
        
        return dx

这里我们还是先使用im2col将批处理数据转化为矩阵。在一个维度上(即batch中每一个特征图)取各个数组中最大值汇总为输出。

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

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

相关文章

后端Java随机比大小游戏实战讲解

## - 利用print打印输出提示用户 ## - 利用Scanner函数抓取数据 ## - 利用Math方法实现随机数 #### 1.首先用到的是print函数,对用户进行提醒进一步的操作 通过System.out.print();提示用户进行选择买大买小。 #### 2.然后利用Scanner函数,对用户输出…

Spring Bean生命周期七大阶段-Java八股面试(七)

系列文章目录 第一章 ArrayList-Java八股面试(一) 第二章 HashMap-Java八股面试(二) 第三章 单例模式-Java八股面试(三) 第四章 线程池和Volatile关键字-Java八股面试(四) 第五章 ConcurrentHashMap-Java八股面试(五) 第六章 spring之refresh流程-Java八股面试(六) 提示&…

HTTPS是怎么加密数据的?

HTTPS是怎么加密数据的?对安全或密码学基础有了解的同学,应该知道常见的加密手段。一般来说,加密分为对称加密、非对称加密(也叫公开密钥加密)对称加密对称加密的意思就是,加密数据用的密钥,跟解…

儿童反复感染,是体质差还是免疫缺陷?

原发性免疫缺陷病(PIDs)它是一组由遗传因素或先天性免疫系统发育不良引起的免疫系统功能障碍综合征,可涉及固有免疫或适应性免疫。在中国,PID的中位发病率为6个月,男孩的发病率通常高于女孩。▼分类目前,国…

LearnOpenGL-光照-2.基础光照

本人刚学OpenGL不久且自学,文中定有代码、术语等错误,欢迎指正 我写的项目地址:https://github.com/liujianjie/LearnOpenGLProject 文章目录基础光照环境光照漫反射光照法向量计算漫反射光照最后一件事镜面光照基础光照 简介 现实世界的光照…

JavaEE初阶---初始进程

系统分配资源的最小单元--进程啥是进程看看进程操作系统如何管理进程PCB中的一些属性pid(进程id)内存指针文件描述符表进程调度并行和并发:进程调度的特性状态:优先级:记账信息:上下文:虚拟地址空间进程间交互我们日常使用计算机,大致可以抽象成如下形式:自上向下依次是 各种软…

易优cms switch 条件判断标签使用方法

【基础用法】 标签:switch 描述:简单条件判断,比if判断标签少些不等于相同功能,视个人习惯而用。 用法: {eyou:switch name$eyou.field.has_children} {eyou:case value1}当前栏目列表的栏目ID有1个下级栏目{/eyo…

跨境电商卖家如何应对拒付、盗卡

跨境电商主要是通过电子商务平台进行交易,在平台上完成支付结算,并通过国际物流将商品送达买方,从而实现跨国零售交易。与传统贸易相比,跨境电商存在交易链条更短、回款周期更快、数据及时透明等优势。商务部数据显示,…

sumifs的交叉 表的例子

比如这样,那么冰箱绿山店的栏位中,SUMIFS($D$3:$D$10,$B$3:$B$10,$F3,$C$3:$C$10,G$2)就是把求和范围,条件1设置为固定列的复合引用,条件2设置为固定行的复合引用即可。

LeetCode 1653. Minimum Deletions to Make String Balanced【字符串,动态规划,枚举】中等

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…

shell基本知识

为什么学习和使用Shell编程 什么是Shell shell的起源 shell的功能 shell的分类 如何查看当前系统支持的shell? 如何查看当前系统默认shell? 驼峰语句 shell脚本的基本元素 shell脚本编写规范 shell脚本的执行方式 shell脚本的退出状态 &#xf…

数位dp-- 数字游戏

题目 思路 也是一道比较典型的数位dp的问题,关键的思想跟我上一篇博客很像, 首先把区间值变成[1,Y]-[1,X-1]的值,然后单独计算得到结果。 总的来说就是把这个数的每一位都单独拿出来,然后根据选0-an-1和选**an**两种方案单独计算&…

LeetCode 热题 C++ 538. 把二叉搜索树转换为累加树 543. 二叉树的直径 560. 和为 K 的子数组

538. 把二叉搜索树转换为累加树 给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提醒一下,二…

Java基础算法题

目录 练习一 : 优化代码 扩展 : CRTL Alt M 自动抽取方法 练习二: 方法1: 方法2: 方法3: Math : 顾名思义,Math类就是用来进行数学计算的,它提供了大量的静态方法来便于我们实现数学计算: 练习三 : 练习四 : 练习五: 练习…

【GO】K8s 管理系统项目34[Docker方式–应用部署]

K8s 管理系统项目[Docker方式–应用部署] 1. 数据库 1.1 创建数据库目录 mkdir -p /data/mysql5.7/1.2 创建容器 docker run --name mysql -itd -h mysql-server -e MYSQL_ROOT_PASSWORDroot -v /data/mysql5.7:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD123456 …

layui框架实战案例(19):layui-table模块表格综合应用(筛选查询、导入导出、群发短信、一键审核、照片展示、隐私加密)

系列文章目录 layui动态表格翻页和搜索的代码分析layui框架实战案例(3):layui上传错误请求上传接口出现异常解决方案layui框架实战案例(9):layPage 静态数据分页组件layui框架实战案例(10):短信验证码60秒倒计时layui框架实战案例(11)&#…

《实践论》笔记及当下反思(二)

目录 笔记 1、马克思主义所说的绝对真理是什么? 2、客观现实世界的变化运动永远没有完结,人们在实践中对于真理的认识也就永远没有完结 3、改造客观世界,也改造自己的主观世界-——改造自己的认识能力 4、实践、认识、再实践、再认识&…

ARP报文内容详细分析

ARP报文格式如图: 字段1:ARP请求的目的以太网地址,全1时,代表广播地址。 字段2:发送ARP请求的以太网地址。 字段3:以太网帧类型表示后面的数据类型,ARP请求和ARP应答此字段为:0x0806…

SourceTree 重置提交、合并、撤销、回滚

SourceTree重置当前分支到此次提交使用场景:已提交未推送的修改撤销、想把某一次的错误修改全部撤销当前发布代码有bug需要切到上次提交发布版本Git中的HEAD解释# 使用最新一次提交重制暂存区git reset HEAD -- filename# 使用最新一次提交重制暂存区和工作区git re…

SpringBoot——统一功能处理

处理登陆拦截 上一片博客中讲到SpringAOP可以对页面进行拦截,我们可以用SpringAOP实现对登陆的拦截 但是由于拦截需要HttpSession对象,并且之后还需要页面重定向,因此在实际应用中,并不用SpringAOP进行登陆拦截,而是…