深度学习入门——卷积神经网络
本章的主题是卷积神经网络(Convolutional Neural Network,CNN)。CNN被用于图像识别、语音识别等各种场合,在图像识别的比赛中,基于深度学习的方法几乎都以CNN为基础。本章将详细介绍CNN的结构,并用Python实现其处理内容。
整体结构
CNN中新出现了卷积层(Convolution 层)和池化层(Pooling 层)。
之前介绍的神经网络中,相邻层的所有神经元之间都有连接,这称为全连接(fully-connected)
在图7-2 的CNN中,靠近输出的层中使用了之前的“Affine - ReLU”组合。此外,最后的输出层中使用了之前的“Affine-Softmax”组合。这些都是一般的CNN中比较常见的结构。
卷积层
全连接层存在的问题
全连接层存在什么问题呢?那就是数据的形状被“忽视”了
图像是3 维形状,这个形状中应该含有重要的空间信息。比如,空间上邻近的像素为相似的值、RBG的各个通道之间分别有密切的关联性、相距较远的像素之间没有什么关联等,3 维形状中可能隐藏有值得提取的本质模式
全连接层会忽视形状,而卷积层可以保持形状不变。
CNN中,有时将卷积层的输入输出数据称为特征图(feature map)。其中,卷积层的输入数据称为输入特征图(input feature map),输出数据称为输出特征图(output feature map)。
卷积运算
卷积运算相当于图像处理中的“滤波器运算”。
有的文献中也会用“核”这个词来表示这里所说的“滤波器”
CNN中,滤波器的参数就对应之前的权重。并且,CNN中也存在偏置
填充
在进行卷积层的处理之前,有时要向输入数据的周围填入固定的数据(比如0 等),这称为填充(padding),是卷积运算中经常会用到的处理
[!IMPORTANT]
使用填充主要是为了调整输出的大小。
如果每次进行卷积运算都会缩小空间,那么在某个时刻输出大小就有可能变为1,导致无法再应用卷积运算。为了避免出现这样的情况,就要使用填充。在刚才的例子中,将填充的幅度设为1,那么相对于输入大小(4, 4),输出大小也保持为原来的(4, 4)。因此,卷积运算就可以在保持空间大小不变的情况下将数据传给下一层。
步幅
应用滤波器的位置间隔称为步幅(stride)
3维数据的卷积运算
图像是3维数据,有高、长、通道方向
通道方向上有多个特征图时,会按通道进行输入数据和滤波器的卷积运算,并将结果相加,从而得到输出。
需要注意的是,在3 维数据的卷积运算中,输入数据和滤波器的通道数要设为相同的值
滤波器大小可以设定为任意值(不过,每个通道的滤波器大小要全部相同)。这个例子中滤波器大小为(3, 3),但也可以设定为(2, 2)、(1, 1)、(5, 5) 等任意值。再强调一下,通道数只能设定为和输入数据的通道数相同的值(本例中为3)。
结合方块思考
在这个例子中,数据输出是1 张特征图。所谓1 张特征图,换句话说,就是通道数为1 的特征图。
作为4 维数据,滤波器的权重数据要按(output_channel, input_channel, height, width) 的顺序书写
不同形状的方块相加时,可以基于NumPy的广播功能轻松实现
批处理
神经网络的处理中进行了将输入数据打包的批处理。
需要将在各层间传递的数据保存为4 维数据。具体地讲,就是按(batch_num, channel, height, width)的顺序保存数据
这里需要注意的是,网络间传递的是4 维数据,对这N个数据进行了卷积运算。也就是说,批处理将N次的处理汇总成了1 次进行。
池化层
池化是缩小高、长方向上的空间的运算
一般来说,池化的窗口大小会和步幅设定成相同的值
[!WARNING]
除了Max 池化之外,还有Average 池化等。相对于Max 池化是从目标区域中取出最大值,Average 池化则是计算目标区域的平均值。在图像识别领域,主要使用Max 池化。因此,本书中说到“池化层”时,指的是Max 池化。
池化层的特征
- 没有要学习的参数
- 通道数不发生变化
- 对微小的位置变化具有鲁棒性(健壮)
卷积层和池化层的实现
4维数组
比如数据的形状是(10, 1, 28, 28),则它对应10 个高为28、长为28、通道为1 的数据
CNN中处理的是4维数据,因此卷积运算的实现看上去会很复杂,但是通过使用下面要介绍的im2col这个技巧,问题就会变得很简单
基于im2col的展开
im2col是一个函数,将输入数据展开以适合滤波器(权重)
对于输入数据,将应用滤波器的区域(3 维方块)横向展开为1 列。im2col会在所有应用滤波器的地方进行这个展开处理。
在滤波器的应用区域重叠的情况下,使用im2col展开后,展开后的元素个数会多于原方块的元素个数。因此,使用im2col的实现存在比普通的实现消耗更多内存的缺点。但是,汇总成一个大的矩阵进行计算,对计算机的计算颇有益处
卷积层的实现
class Convolution:def __init__(self, W, b, stride=1, pad=0):self.W = Wself.b = bself.stride = strideself.pad = paddef forward(self, x):FN, C, FH, FW = self.W.shapeN, C, H, W = x.shapeout_h = int(1 + (H + 2*self.pad - FH) / self.stride)out_w = int(1 + (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.bout = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)return out
池化层的实现
class Pooling:def __init__(self, pool_h, pool_w, stride=1, pad=0):self.pool_h = pool_hself.pool_w = pool_wself.stride = strideself.pad = paddef forward(self, x):N, C, H, W = x.shapeout_h = int(1 + (H - self.pool_h) / self.stride)out_w = int(1 + (W - self.pool_w) / self.stride)# 展开(1)col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)col = col.reshape(-1, self.pool_h*self.pool_w)# 最大值(2)out = np.max(col, axis=1)# 转换(3)out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)return out
池化层的实现按下面3 个阶段进行:
- 展开输入数据。
- 求各行的最大值。
- 转换为合适的输出大小。
CNN的实现
参数
- input_dim―输入数据的维度:(通道,高,长)
- conv_param―卷积层的超参数(字典)。字典的关键字如下:
- filter_num―滤波器的数量
- filter_size―滤波器的大小
- stride―步幅
- pad―填充
- hidden_size―隐藏层(全连接)的神经元数量
- output_size―输出层(全连接)的神经元数量
- weitght_int_std―初始化时权重的标准差
class SimpleConvNet:def __init__(self, input_dim=(1, 28, 28),conv_param={'filter_num':30, 'filter_size':5,'pad':0, 'stride':1},hidden_size=100, output_size=10, weight_init_std=0.01):filter_num = conv_param['filter_num']filter_size = conv_param['filter_size']filter_pad = conv_param['pad']filter_stride = conv_param['stride']input_size = input_dim[1]conv_output_size = (input_size - filter_size + 2*filter_pad) / \filter_stride + 1pool_output_size = int(filter_num * (conv_output_size/2) *(conv_output_size/2))self.params = {}self.params['W1'] = weight_init_std * \np.random.randn(filter_num, input_dim[0],filter_size, filter_size)self.params['b1'] = np.zeros(filter_num)self.params['W2'] = weight_init_std * \np.random.randn(pool_output_size,hidden_size)self.params['b2'] = np.zeros(hidden_size)self.params['W3'] = weight_init_std * \np.random.randn(hidden_size, output_size)self.params['b3'] = np.zeros(output_size)self.layers = OrderedDict()self.layers['Conv1'] = Convolution(self.params['W1'],self.params['b1'],conv_param['stride'],conv_param['pad'])self.layers['Relu1'] = Relu()self.layers['Pool1'] = Pooling(pool_h=2, pool_w=2, stride=2)self.layers['Affine1'] = Affine(self.params['W2'],self.params['b2'])self.layers['Relu2'] = Relu()self.layers['Affine2'] = Affine(self.params['W3'],self.params['b3'])self.last_layer = softmaxwithloss()def predict(self, x):for layer in self.layers.values():x = layer.forward(x)return xdef loss(self, x, t):y = self.predict(x)return self.lastLayer.forward(y, t)def gradient(self, x, t):# forwardself.loss(x, t)# backwarddout = 1dout = self.lastLayer.backward(dout)layers = list(self.layers.values())layers.reverse()for layer in layers:dout = layer.backward(dout)# 设定grads = {}grads['W1'] = self.layers['Conv1'].dWgrads['b1'] = self.layers['Conv1'].dbgrads['W2'] = self.layers['Affine1'].dWgrads['b2'] = self.layers['Affine1'].dbgrads['W3'] = self.layers['Affine2'].dWgrads['b3'] = self.layers['Affine2'].dbreturn grads
CNN的可视化
本节将通过卷积层的可视化,探索CNN中到底进行了什么处理。
第1层权重的可视化
卷积层的滤波器会提取边缘或斑块等原始信息。而刚才实现的CNN会将这些原始信息传递给后面的层。
基于分层结构的信息提取
在堆叠了多层的CNN中,各层中又会提取什么样的信息呢?
根据深度学习的可视化相关的研究,随着层次加深,提取的信息(正确地讲,是反映强烈的神经元)也越来越抽象
图7-26 中展示了进行一般物体识别(车或狗等)的8 层CNN。AlexNet 网络结构堆叠了多层卷积层和池化层,最后经过全连接层输出结果
随着层次加深,神经元从简单的形状向“高级”信息变化
具有代表性的CNN
LeNet
LeNet 在1998 年被提出,是进行手写数字识别的网络
它有连续的卷积层和池化层(正确地讲,是只“抽选元素”的子采样层),最后经全连接层输出结果。
与“现在的CNN”不同点
-
对于激活函数,LeNet 中使用sigmoid 函数,而现在的CNN中主要使用ReLU函数。
-
原始的LeNet 中使用子采样(subsampling)缩小中间数据的大小,而现在的CNN中Max池化是主流。
AlexNet
AlexNet是引发深度学习热潮的导火线
与LeCun不同点
- 激活函数使用ReLU。
- 使用进行局部正规化的LRN(Local Response Normalization)层。
- 使用Dropout(6.4.3 节)。
[!IMPORTANT]
大多数情况下,深度学习(加深了层次的网络)存在大量的参数。因此,学习需要大量的计算,并且需要使那些参数“满意”的大量数据。可以说是GPU和大数据给这些课题带来了希望。
小结
- CNN在此前的全连接层的网络中新增了卷积层和池化层。
- 使用im2col函数可以简单、高效地实现卷积层和池化层。
- 通过CNN的可视化,可知随着层次变深,提取的信息愈加高级。
- LeNet和AlexNet是CNN的代表性网络。
- 在深度学习的发展中,大数据和GPU做出了很大的贡献。
- 激活函数使用ReLU。
- 使用进行局部正规化的LRN(Local Response Normalization)层。
- 使用Dropout(6.4.3 节)。
[!IMPORTANT]
大多数情况下,深度学习(加深了层次的网络)存在大量的参数。因此,学习需要大量的计算,并且需要使那些参数“满意”的大量数据。可以说是GPU和大数据给这些课题带来了希望。
小结
- CNN在此前的全连接层的网络中新增了卷积层和池化层。
- 使用im2col函数可以简单、高效地实现卷积层和池化层。
- 通过CNN的可视化,可知随着层次变深,提取的信息愈加高级。
- LeNet和AlexNet是CNN的代表性网络。
- 在深度学习的发展中,大数据和GPU做出了很大的贡献。
相关文章:
深度学习入门——卷积神经网络
本章的主题是卷积神经网络(Convolutional Neural Network,CNN)。CNN被用于图像识别、语音识别等各种场合,在图像识别的比赛中,基于深度学习的方法几乎都以CNN为基础。本章将详细介绍CNN的结构,并用Python实…...
快团团供货大大团长帮卖团长如何线上结算和支付货款?
一、如何支付结算单? 团长在快团团小程序【我的供货商】—【结算单】—【待支付】中,找到需要支付的结算单,点击【去支付】即可。 当有多笔结算单待支付时,团长可筛选供货商和日期找到需要支付的结算单,点击【去批量…...
vite vue3 Webstorm multiple export width the same name “default“
系统格式不一样,导致代码文件格式冲突导致的,解决方法找到对应的文件,将文件类型切换成LF。...
Transformer预测模型及其Python和MATLAB实现
### 一、背景 在自然语言处理(NLP)领域,传统的序列到序列(Seq2Seq)模型大多依赖于循环神经网络(RNN)和长短期记忆(LSTM)网络。这些模型虽然在许多任务中取得了成功&…...
草的渲染理论
Unity引擎提供了基础的terrain工具,可以制作地形,在上面刷树刷草。对于树,Unity是支持带LOD的Prefab,不同距离显示不同细节的模型,效果还不错。对于草,Unity支持两种方式来刷草,一种是Add Grass…...
Redis:十大数据类型
键(key) 常用命令 1. 字符串(String) 1.1 基本命令 set key value 如下:设置kv键值对,存货时长为30秒 get key mset key value [key value ...]mget key [key ...] 同时设置或者获取多个键值对 getrange…...
bugku-web-source
kali中先用dirsearch工具扫描后台目录,然后用wget -r url/.git命令递归下载后,进入txt文件使用git reflog命令然后只用git show查看作者提交flag日志,用git show 一个一个去尝试,很多假的flag git reflog 是一个 Git 命令&#x…...
一键生成视频并批量上传视频抖音、bilibili、腾讯(已打包)
GenerateAndAutoupload Github地址:https://github.com/cmdch2017/GenerateAndAutoupload 如何下载(找到最新的release) https://github.com/cmdch2017/GenerateAndAutoupload/releases/download/v1.0.1/v1.0.1.zip 启动必知道 conf.py …...
Python WSGI服务器库之gunicorn使用详解
概要 在部署 Python Web 应用程序时,选择合适的 WSGI 服务器是关键的一步。Gunicorn(Green Unicorn)是一个高性能、易于使用的 Python WSGI HTTP 服务器,适用于各种应用部署场景。Gunicorn 设计简洁,支持多种工作模式,能够有效地管理和处理大量并发请求。本文将详细介绍…...
Java编程达人:每日一练,提升自我
目录 题目1.以下哪个单词不是 Java 的关键字?2.boolean 类型的默认值为?3.以下代码输出正确的是?4.以下代码,输出结果为:5.以下代码输出结果为:6.以下代码输出结果为?7.float 变量的默认值为&am…...
(35)远程识别(又称无人机识别)(二)
文章目录 前言 4 ArduRemoteID 5 终端用户数据的设置和使用 6 测试 7 为OEMs添加远程ID到ArduPilot系统的视频教程 前言 在一些国家,远程 ID 正在成为一项法律要求。以下是与 ArduPilot 兼容的设备列表。这里(here)有一个关于远程 ID 的很好解释和常见问题列表…...
提供三方API接口、调用第三方接口API接口、模拟API接口(一)通过signature签名验证,避免参数恶意修改
为什么要设计安全的api接口 运行在外网服务器的接口暴露在整个互联网中,可能会受到各种攻击,例如恶意爬取服务器数据、恶意篡改请求数据等,因此需要一个机制去保证api接口是相对安全的。 本项目api接口安全设计 本项目api接口的安全性主要…...
CDO学习
1.备份instie.mdb文件 2....
奥运会Ⅱ---谁会先抢走你的工作?
Devin AI 与 Microsoft AutoDev,谁会先抢走你的工作? 软件开发领域正处于一场革命的风口浪尖。Devin AI和Microsoft AutoDev 的出现,是人工智能编码领域的两项突破性进步,有望重塑软件构建方式。但是,在如此截然不同的…...
用Python打造精彩动画与视频,4.3 创建动态文本和字幕
第四章:深入MoviePy 4.3 创建动态文本和字幕 在视频编辑中,动态文本和字幕是传达信息、增强观众体验的重要元素。MoviePy 提供了丰富的工具来添加和自定义文本和字幕,包括字体、颜色、动画效果等。本节将介绍如何在视频中添加动态文本和字幕…...
spring boot + vue3 接入钉钉实现扫码登录
1:准备工作 1.1:进入钉钉开放平台创建开发者应用。应用创建和类型介绍,参考下方。 应用类型介绍 - 钉钉开放平台 (dingtalk.com) 应用能力介绍 - 钉钉开放平台 (dingtalk.com) 扫码登录第三方网站 - 钉钉开放平台 (dingtalk.com) 1.2&…...
二叉树构建(从3种遍历中构建)python刷题记录
R3-树与二叉树篇. 目录 从前序与中序遍历序列构造二叉树 算法思路: 灵神套路 从中序与后序遍历序列构造二叉树 算法思路: 灵神套路 从前序和后序遍历序列构造二叉树 算法思路: 灵神套路 从前序与中序遍历序列构造二叉树 算法…...
计算机网络中协议与报文的关系
协议和报文在网络通信中扮演着不同的角色,但它们是紧密相关的。 协议是计算机网络中实现通信的“约定”,它规定了计算机之间如何进行通信,包括数据传输的格式、步骤和规则。协议确保了不同厂商的设备、不同的CPU和操作系统之间的计算机能够相…...
机器学习 第8章-集成学习
机器学习 第8章-集成学习 8.1 个体与集成 集成学习(ensemble learning)通过构建并结合多个学习器来完成学习任务,有时也被称为多分类器系统(multi-classifersystem)、基于委员会的学习(committee-based learning)等。 图8.1显示出集成学习的一般结构:先产生一组“…...
Docker 安装 GitLab教程
本章教程,主要介绍如何在Docker 中安装GitLab。 GitLab 是一个开源的 DevOps 平台,提供了一整套工具,用于软件开发生命周期的各个阶段,从代码管理到 CI/CD(持续集成和持续交付/部署),再到监控和安全分析。 一、拉取镜像 docker pull gitlab/gitlab-ce:latest二、创建 G…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
