OpenMMLab AI实战营 第一课笔记
OpenMMLab AI实战营 第一课笔记
OpenMMLab AI实战营第一节课由子豪兄讲解,课程主要内容主要围绕计算机视觉和OpenMMLab开源算法体系以及机器学习和神经网络简介进行展开。这里要感谢子豪兄的分享,瑞斯拜。
以下是本节课程的主要内容概要及课后补充介绍。
一、计算机视觉
1.1 计算机视觉是什么
计算机视觉(Computer vision)是一门研究如何使机器“看”的科学,更进一步的说,就是指用摄影机和计算机)代替人眼对目标进行识别、跟踪和测量等机器视觉,并进一步做图像处理,用计算机处理成为更适合人眼观察或传送给仪器检测的图像。
如下图的四个不同任务,即是计算机视觉领域的一系列工作。
- 图中的动物是什么?—— 图像识别
- 哪个位置有狗?——目标定位
- 狗在做什么?——动作识别
- 生成一种狗的图片?——图像生成
更广泛地,例如我们比较常用的微信扫一扫和人脸识别,背后的技术都用到计算机视觉技术与原理。
1.2 计算机视觉应用
-
计算机视觉主要应用领域有哪些?
计算机视觉是使用计算机模仿人类视觉系统的科学,让计算机拥有类似人类提取、处理、理解、分析图像以及图像序列的能力。
大致可以分为这么几类:
- 目标检测、图像分割、图像增强、图像生成、人脸分类识别、姿态估计、立体视觉等。
产业链可分为基础层、技术层和应用层。
- 基础层包括硬件支持、算法支持和数据集;
- 技术层包括视觉技术平台、视频识别、图片识别和模式匹配;
- 应用层包括计算机视觉技术在智慧城市、智慧安防、智慧物流、智慧金融、手机终端和智慧商业等领域的应用。
下面是比较热门且有意思的应用:
- 自动驾驶
- 动漫特效
- 航拍转地图
- 虚拟主播
- 视频理解与自动剪辑
自动驾驶的计算机视觉应用,主要是感知层面,视觉感知与激光雷达感知构成并辅助了车体对环境的感知,结合车辆自身状态,从而可以进行相应的决策、规划与控制。
一些比较有意思的动漫特效,主要应用的关键技术有图像生成、风格迁移和人脸关键点检测。
能够根据无人机航拍图像的 GPS 信息和图像重叠度实现快速建模以及地图构建。
虚拟主播Virtual Youtuber,简称Vtuber,是近几年来兴起的网络直播形式。在这种直播当中,主播选择以一种,往往是动漫的形式的模型扮演,并以此与观众互动。我们称这些扮演者为“中之人”,同时,虚拟主播现象是中之人和模型的统一,而有时候我们往往管单纯的模型叫作虚拟主播
视频内容理解的主要目标是,概括视频中出现的重要概念,打开视频内容的“黑盒”,让机器知道盒子里有什么,为下游应用提供语义信息,以便更好地对视频做管理和分发。根据结果的形式,内容理解可以分为显式和隐式两种。其中,显式是指通过视频分类相关技术,给视频打上人可以理解的文本标签。隐式主要指以向量形式表示的嵌入特征,在推荐、搜索等场景下与模型结合直接面向最终任务建模。可以粗略地理解为,前者主要面向人,后者主要面向机器学习算法。
1.3 计算机视觉的发展
1.3.1 计算机视觉的早期萌芽(1960~1980)
- 1957年春天,美国国家标准局的科学家拉塞尔·基尔希为他的儿子瓦尔登拍了一张照,并将其扫描到了东部标准自动计算机(SEAC)中。为了使图片可以放进SEAC有限的存储空间中,他将图片分割成176176的网格——共30976位二进制,并进行了多次扫描。这张边长5厘米的正方形图片就是历史上第一张数字图像,从某种意义上来讲它甚至是CT扫描、卫星图像和数码摄影的鼻祖。
- 1959年,神经生理学家大卫·休伯尔和托斯坦·维厄瑟尔通过猫的视觉实验,首次发现了视觉初级皮层神经元对于移动边缘刺激敏感,发现了视功能柱结构,为视觉神经研究奠定了基础——促成了计算机视觉技术40年后的突破性发展,奠定了深度学习的核心准则。
- 到了60年代,劳伦斯罗伯茨在《三维固体的机器感知》描述了从二维图片中推导三维信息的过程,成为计算机视觉的前导之一,开创了理解三维场景为目的的计算机视觉研究。这个研究给世界带来了很大启发,并且对边缘、线条、明暗等各种特征建立了各种数据结构和推理规则。
- 1969年秋天,贝尔实验室的两位科学家韦拉德博伊尔和乔治史密斯正忙于电荷耦合器件(CCD)的研发。它是一种将光子转化为电脉冲的器件,很快成为了高质量数字图像采集任务的新宠,逐渐应用于工业相机传感器,标志着计算机视觉走上应用舞台,投入到工业机器视觉中。
1.3.2 统计机器学习与模式识别(1990~2000)
1990年代,机器学习进入了一个新阶段,研究人员开发出了更复杂的算法,比如支持向量机、集成学习、遗传算法等,这些算法可以应用于不同的领域,比如计算机视觉、自然语言处理等。
2000年以后,机器学习进入了一个新的发展阶段,研究人员开发出了更复杂的算法,比如深度学习、强化学习等,这些算法可以应用于更多的领域,比如自动驾驶、自然语言理解等。
模式识别:所谓模式识别的问题就是用计算的方法根据样本的特征将样本划分到一定的类别中去。模式识别就是通过计算机用数学技术方法来研究模式的自动处理和判读,把环境与客体统称为“模式”。随着计算机技术的发展,人类有可能研究复杂的信息处理过程,其过程的一个重要形式是生命体对环境及客体的识别。模式识别以图像处理与计算机视觉、语音语言信息处理、脑网络组、类脑智能等为主要研究方向,研究人类模式识别的机理以及有效的计算方法。
1.3.2.1 视觉特征
颜色特征
描述方法:
- 颜色直方图
- 颜色集
- 颜色矩
- 颜色聚合向量
- 颜色相关图
纹理特征
- 统计方法(共生矩阵)
GLCM(2,1)值为3说明有3对灰度为2和1的像素对角相邻。在共生矩阵基础上,又可以定义多种纹理特征:熵、能量、对比度、均匀度、相关性。- 结构法
- 模型法
- 频谱法
形状特征
- 轮廓特征:针对物体的外边界,常使用游程长度编码方法
- 区域特征:统计整个区域形状,使用区域密度、区域体态比度量
- 局部点特征
角点特征点
- Harris角点
- SIFT
边缘特征
- 灭点、灭线
- 梯度边缘检测
- 非最大抑制边缘检测
- Canny边缘检测
- Robert算子、Prewitt算子、Sobel算子、Laplace 算子、LOG算子边缘检测
1.3.2.2 ImageNet大型数据库
1.3.3 初有成效的视觉系统(~2010)
ImageNet项目是一个用于视觉对象识别软件研究的大型可视化数据库。超过1400万的图像URL被ImageNet手动注释,以指示图片中的对象;在至少一百万个图像中,还提供了边界框。ImageNet包含2万多个类别; [2]一个典型的类别,如“气球”或“草莓”,包含数百个图像。第三方图像URL的注释数据库可以直接从ImageNet免费获得;但是,实际的图像不属于ImageNet。
自2010年以来,ImageNet项目每年举办一次软件比赛,即ImageNet大规模视觉识别挑战赛(ILSVRC),软件程序竞相正确分类检测物体和场景。 ImageNet挑战使用了一个“修剪”的1000个非重叠类的列表。2012年在解决ImageNet挑战方面取得了巨大的突破,被广泛认为是2010年的深度学习革命的开始。
1.3.4 深度学习的时代
2012年,Hinton课题组为了证明深度学习的潜力,首次参加ImageNet图像识别比赛,其通过构建的CNN网络AlexNet一举夺得冠军,且碾压第二名(SVM方法)的分类性能。也正是由于该比赛,CNN吸引到了众多研究者的注意。
AlexNet的创新点在于:
(1)首次采用ReLU激活函数,极大增大收敛速度且从根本上解决了梯度消失问题。
(2)由于ReLU方法可以很好抑制梯度消失问题,AlexNet抛弃了“预训练+微调”的方法,完全采用有监督训练。也正因为如此,DL的主流学习方法也因此变为了纯粹的有监督学习。
(3)扩展了LeNet5结构,添加Dropout层减小过拟合,LRN层增强泛化能力/减小过拟合。
(4)第一次使用GPU加速模型计算。
2013、2014、2015、2016年,通过ImageNet图像识别比赛,DL的网络结构,训练方法,GPU硬件的不断进步,促使其在其他领域也在不断的征服战场。
2016年3月,由谷歌(Google)旗下DeepMind公司开发的AlphaGo(基于深度学习)与围棋世界冠军、职业九段棋手李世石进行围棋人机大战,以4比1的总比分获胜;
2016年末2017年初,该程序在中国棋类网站上以“大师”(Master)为注册帐号与中日韩数十位围棋高手进行快棋对决,连续60局无一败绩;2017年5月,在中国乌镇围棋峰会上,它与排名世界第一的世界围棋冠军柯洁对战,以3比0的总比分获胜。围棋界公认阿尔法围棋的棋力已经超过人类职业围棋顶尖水平。
1.3.5 时至今日
时至今日,人工智能的发展可以处理更多更有意思的事情。例如:
- 文字描述生成图片
- 视觉大模型
- 神经渲染场
- …
1.3.6 开源成为人工智能领域发展引擎
近年来,人工智能领域越来越多的开源、开放,包括人工智能算法和基础平台等,促进了人工智能的高速发展。开源开放、技术创新和产业发展密切相关、互相促进。在三者的共同作用下,可以凝聚全球创新要素,加速技术创新,同时也打造技术生态,赋能产业发展。另一方面,很多标准在开源社区会先形成事实的标准,进而推动技术和产业的协同发展。
二、OpenMMLab开源算法体系
2.1 OpenMMLab总体介绍
OpenMMLab目前基于统一的架构,根据20+的研发方向,开发了将近300+的算法和2000+的预训练模型。
- 提供了统一先进的底层架构
- 覆盖计算机视觉众多方向
- 提供最经典、最前沿的算法支持
- 提供统一的基准和开箱即用的工作
上图可以看到OpenMMLab开源算法体系中的开源历程,可以根据时间线来学习和了解相关的算法库。
2.2 OpenMMLab总体架构概览
OpenMMLab总体架构,主要以Pytorch为训练框架,基于计算基础库MMCV的公用底层模块与抽象训练接口,向上开发了相应的算法框架以及部署框架。
在训练与部署方面,从OpenMMLab算法库到MMDeploy,结合众多硬件厂家,完成了训练-部署的一体化。
随着OpenMMLab的生态开放发展以及产学研一体化,OpenMMLab在全球范围内的影响力也越来越大。
2.3 算法框架介绍
2.3.1 MMDetection
MMDetection 是一个基于 PyTorch 的开源对象检测工具箱。它是OpenMMLab项目的一部分。
简单来说目标检测算法可以按照 3 个维度划分:
- 按照 stage 个数划分,常规是 one-stage 和 two-stage,但是实际上界限不是特别清晰,例如带 refine 阶段的算法 RepPoints,实际上可以认为是1.5 stage 算法,而 Cascade R-CNN 可以认为是多阶段算法,为了简单,上面图示没有划分如此细致
- 按照是否需要预定义 anchor 划分,常规是 anchor-based 和 anchor-free,当然也有些算法是两者混合的
- 按照是否采用了 transformer 结构划分,目前基于 transformer 结构的目标检测算法发展迅速,也引起了极大的关注,所以这里特意增加了这个类别的划分
不管哪种划分方式,其实都可以分成若干固定模块,然后通过模块堆叠来构建整个检测算法体系。
2.3.2 MMDetection3D
MMDetection3D 是一个基于 PyTorch 的开源对象检测工具箱,面向下一代通用 3D 检测平台。它是 MMLab 开发的 OpenMMLab 项目的一部分。
2.3.3 MMClassification
MMClassification 是一个基于 PyTorch 的开源图像分类工具箱。它是OpenMMLab项目的一部分。
2.3.4 MMSegmentation
MMSegmentation 是一个基于 PyTorch 的开源语义分割工具箱。它是OpenMMLab项目的一部分。
master 分支适用于PyTorch 1.5+。
2.3.5 MMPose & MMHuman3D
MMPose 是一个基于 PyTorch 的姿态估计开源工具箱。它是OpenMMLab 项目的一部分。
master 分支适用于PyTorch 1.5+。
MMHuman3D 是一个基于 PyTorch 的开源代码库,用于在计算机视觉和计算机图形学中使用 3D 人体参数模型。它是OpenMMLab项目的一部分。
主要分支适用于PyTorch 1.7+。
2.3.6 MMTracking
https://github.com/open-mmlab/mmtracking
MMTracking 是 PyTorch 开源的视频感知工具箱。它是OpenMMLab项目的一部分。
master 分支适用于PyTorch1.5+。
2.3.7 MMAction2
MMAction2 是一个基于 PyTorch 的视频理解开源工具箱。它是OpenMMLab项目的一部分。
master 分支适用于PyTorch 1.5+。
2.3.8 MMOCR
MMOCR 是一个基于 PyTorch 和 mmdetection 的开源工具箱,用于文本检测、文本识别以及相应的下游任务,包括关键信息提取。它是OpenMMLab项目的一部分。
主要分支适用于PyTorch 1.6+
2.3.9 MMEditing
MMEditing 是一个基于 PyTorch 的开源图像和视频编辑工具箱。它是OpenMMLab项目的一部分。目前MMEditing支持:
master 分支适用于PyTorch 1.5+。
2.4 行业应用案例
OpenMMLab作为算法生态的关键一环,在行业应用案例中与上下游结合,其中对于上游芯片适配了支持,通过算法生态带动国产化软硬件生态链发展。
同时,也不断服务于下游的头部企业用户,加速计算机视觉技术落地,提高行业研发效率,服务国计民生。
上游芯片厂商主要包括:摩尔线程、NVIDIA、Intel、壁仞科技、沐璐集成电路、、燧原科技、GRAPHCORE、寒武纪、华为、中科曙光。
2.5 OpenMMLab2.0整体介绍
下面从以下几个方面来进行介绍:
- 通用:强大的训练器案例、70行训练TIMM模型
- 灵活:可插拔模块、训练流程控制、日志与可视化
- 开放统一:模块抽象、执行入口、训练流程、数据接口
- 迭代计划
2.5.1 整体架构
- 新架构
基于 MMEngine,OpenMMLab 2.0 的核心架构焕然一新,具有通用、统一、灵活三大特点。- 新的架构除了通用、统一、灵活等三大亮点,还针对各个模块进行了精心设计和优化(设计的时间和开发时间五五开),平衡兼顾了简单性、扩展性和效率。在代码可读性和文档方面,我们对 MMEngine 的要求也比以往的各个算法库都要严格,希望大家在阅读 MMEngine 的源码时还能有所收获,也欢迎大家试用 MMEngine。
2.5.2 通用:强大的训练器
通用
OpenMMLab 2.0 中的 20 多个算法任务都基于一个强大且通用的训练器。和 OpenMMLab 1.0 中的训练器相比,新的训练器以统一的方式实现了数据、模型、评测等组件的构造流程供各算法库调用,以更加可拓展的方式支持了不同芯片环境(CPU,GPU,Apple M1,MLU等)下的分布式和非分布式训练,并支持了一些最新的大模型训练技术如 FullyShardedDataParallel。下游的各种算法库都可以直接使用这个训练器,在简化代码的同时,通过依赖最新的 MMEngine 享受最新的训练技术和芯片支持。
同时,这个通用的训练器还支持被 OpenMMLab 体系外的算法库单独使用,它可以做到以少量代码训练不同任务:例如仅使用 80 行代码训练 imagenet(而 pytorch example 需要 400行),100 行代码训练 CLIP(OpenCLIP 中有上千行训练代码) ,还能轻松兼容当前流行的算法库中的模型,例如 TIMM,TorchVision 和 Detectron2。
2.5.3 统一:模块抽象
统一
OpenMMLab 1.0 中的各算法库分别支持了感知、生成、预训练等 30 多个算法方向,每个算法方向中还有各种不同的算法和训练范式,各算法库也因此在接口上存在细微差别,难以兼容,使得支持新芯片和训练技术的开发成本和算法库数量成正比。
统一后的模块抽象:
- 抽象模块数据丰富
- 清理了函数式定义,增加模块或者模块方法
2.5.4 统一:训练流程
统一后的训练流程:
- 统一了20多个算法任务的训练流程
- 支持自监督、半监督、少样本学习
2.5.5 统一:数据接口
在OpenMMLab1.0的时候,一个算法库,定义了一套接口。
这个接口复杂程度是跟算法库的丰富度正相关的。
于是在OpenMMLab2.0的更新中,统一了算法库的数据接口。
在OpenMMLab2.0中,
- N个算法库,统一由一套接口定义。
- 针对多模态、多任务训练统一了数据接口。
- 针对半监督、自监督、少样本学习的统一接口。
2.5.6 灵活:日志与可视化
灵活
在 OpenMMLab 2.0 中,我们对算法训练流程进行了更细粒度的模块化设计,使得整个训练流程中有了更多可定制化的空间,包括在训练器中增加更多抽象模块、更多可自定义的插入点,和组件之间的信息交流渠道 MessageHub 等。上述贴心的设计提供了一个“乐高”式的训练流程 ,用户可以像拼乐高一样,随心所欲地“插拔”各种模块,实现训练流程的定制化,例如:根据迭代数、 loss 和评测结果等动态调整的训练流程、优化策略和数据增强策略,实现 early stopping,ReduceLROnPlateau 等
任意形式的模型权重平均,如 Exponential Momentum Average (EMA) 和 Stochastic Weight Averaging (SWA)
训练过程中针对任意数据和任意节点的灵活可视化和日志控制、逐参数的优化配置、混合精度训练的灵活控制。
2.5.7 迭代计划
三、机器学习和神经网络简介
3.1 机器学习基础
3.1.1 机器学习是什么
3.1.2 为什么要让“机器”去“学习”
关于人脸识别:如何设计算法,基于这几百万个数据计算出这个人是谁?
关于机器翻译:设计算法的难点在于,基于英文序列计算出对应的中文序列,同时保持意思准确、表达通顺。
关于语音识别:处理语音识别的难点在于两个方面:
- 如何准确地识别语音?
- 如何逼真地生成语音?
关于强化学习:强化学习更关心的是怎么设计游戏机制,如何在游戏中获胜?怎么从当下局面推演到下个局面的一个策略,如何奖励智能体的行为?
对于简单的游戏,可以用min-max等非学习方法,但复杂度会随着游戏规模增大指数增长。
3.1.3 机器学习是什么
在传统的算法设计中,处理的方法范式是通过:问题->设计算法->编写程序的方式来求解的。
但是在实际应用场景中,许多和人的认知与智能(如视觉、语言)相关的问题其实是很难通关传统算法设计的方式来求解的。
但是如果从机器学习的角度,我们就可以让计算机从数据中学习去解决问题。
3.1.4 机器学习的典型范式
- 机器学习的用武之地就是哪些难以通过简单算法接近的问题。(这里的简单,指的是在人类可理解范围内,可以手工设计出来的算法。)
例如,通过人脸图像辨别身份;
通过英文句子翻译成中文;
通过语音波形转换文字;- 监督学习
对于监督学习的方式来说,这里主要关注的问题是,数据之间存在某种映射关系,如何基于有限的数据样本推断出这种关系?- 无监督学习
对于无监督学习的方式来说,更关注的是,数据自身是否存在某种“结构”或“规律”?- 强化学习
对于强化学习而言,我们考虑的是,如何和环境交互,以获得最大的收益?
3.2 机器学习中的分类问题
以一个简单的例子为例,试着将垃圾信件进行一个分类处理,这就是一个简单的分类问题。
3.2.1 特征与分类
以信息文本作为处理对象,这里的流程是,输入原始文本,通过特征提取器进行关键词提取、统计,形成词频向量,用词频向量代表一个文本,称为特征。
- 这里的特征,可以看作是向量空间中的点,不同类文本分布在空间中不同的位置上。
这样一来,将空间划分成不同的区域,就可以对邮件进行分类。
3.2.2 线性分类器
线性分类器假设类别和特征之间存在某种线性关系。
换言之,不同类的数据在特征空间中就可以被一条线给分开。两类数据样本分类在一个二维的特征空间中,这条线(分界线)将不同类的数据在特征空间中分开,它的数学表示是:\(h(x_1, x_2) = Ax_1 + Bx_2 + C = 0.\)
针对某个样本\((x_1, x_2)\),计算\(h(x_1, x_2)\)的值:
- 如果\(h(x_1, x_2)<0\),则归类为A类别;
- 如果\(h(x_1,x_2)>0\),则归类为B类别;
在机器学习领域,分类的目标是指将具有相似特征的对象聚集。而一个线性分类器则透过特征的线性组合来做出分类决定,以达到此种目的。对象的特征通常被描述为特征值,而在向量中则描述为特征向量。
3.2.3 如何求解分界面
分数等于0的线就是决策面。
\[w_i^Tx + b_i =0,i=1,\cdots,c \]\(w\)控制着线的方向
\(b\)控制着线的偏移
箭头方向代表分类器的正方向,沿着箭头方向距离决策面越远,分类数就越高。
3.2.4 感知机Perceptron:从数据中学习
感知器(英语:Perceptron)是[兰克·罗森布拉特在1957年就职于康奈尔航空实验室(Cornell Aeronautical Laboratory)时所发明的一种人工神经网络]。它可以被视为一种最简单形式的前馈神经网络],是一种二元线性分类器。
学习算法对于所有的神经元都是一样的,因此下面所有东西都要独立的应用于每个神经元。我们首先定义一些变量:
- \(x(j)\)表示n维输入向量中的第j项
- \(w(j)\)表示权重向量的第j项
- \(f(x)\)表示神经元接受输入\(x\)产生的输出
- \(\alpha\)是一个常数,符合0<\(\alpha\)≤1(接受率)
更进一步,为了简便我们假定偏置量\(b\)等于0。因为一个额外的维\(N+1\)维,可以用\(x(n+1)\)的形式加到输入向量,这样我们就可以用\(w(N+1)\)代替偏置量。
感知器的学习通过对所有训练实例进行多次的迭代进行更新的方式来建模。
令\(D_M = \left\{ (x_1, y_1), \cdots, (x_m, y_m)\right\}\)表示一个有\(m\)个训练实例的训练集。每次迭代权重向量以如下方式更新:
对于每个\(D_M = \left\{ (x_1, y_1), \cdots, (x_m, y_m)\right\}\)中的每个\((x,y)\)对,
\[w(j):= w(j) + \alpha(y-f(x))x(j)(j=1,\cdots,n) \]注意这意味着,仅当针对给定训练实例\((x, y)\)产生的输出值\(f(x)\)与预期的输出值\(y\)不同时,权重向量才会发生改变。
如果存在一个正的常数\(\gamma\)和权重向量\(w\),对所有的\(i\)满足\(Y_i \cdot (<w, x_i> + b) > \gamma\),训练集\(D_m\)就被叫被做线性分隔的。Novikoff(1962)证明如果训练集是线性分隔的,那么感知器算法可以在有限次迭代后收敛,错误的数量由\(\left(\frac{2R}{\gamma} \right)^2\)限定,其中\(R\)为输入向量的最大平均值。
然而,如果训练集不是线性分隔的,那么这个算法则不能确保会收敛。
3.2.5 机器学习的基本流程
更一般地,机器学习工作流(WorkFlow)包含数据预处理(Processing)、模型学习(Learning)、模型评估(Evaluation)、验证预测(Prediction)几个步骤。
- 数据预处理:输入(未处理的数据 + 标签)→处理过程(特征处理+幅度缩放、特征选择、维度约减、采样)→输出(测试集 + 训练集)。
- 模型学习:模型选择、交叉验证、结果评估、超参选择。
- 模型评估:了解模型对于数据集测试的得分。
- 验证预测:预测测试集。
3.3 神经网络的结构
3.3.1 线性分类器与非线性分类器
所谓线性分类器即用一个超平面将正负样本分离开,表达式为\(y=wx\) 。这里是强调的是平面。
而非线性的分类界面没有这个限制,可以是曲面,多个超平面的组合等。
3.3.1.1 异或问题
- 异或(XOR)是一个基本的布尔函数,是线性不可分。
- Perceptrons主要被称为 "线性分类器",只能用于线性分离的用例,而XOR是其中一种逻辑操作,它不是线性分离的,因为数据点会与线性线的数据点重叠,或者不同的类别出现在线性线的单边。
- 简单的感知机是一个线性分类模型只能表示由一条直线分割的空间,与、或、非问题都是线性可分的问题,即存在一个线性超平面能将他们分开。
无法表示用曲线分割的空间,而XOR问题就是个是一个非线性可分问题,单层感知机无法解决XOR问题,或可以说单层感知机无法分离非线性空间。
3.3.1.2 非线性分类器
在非线性分类器中,异或函数可以由一个两层的计算图来实现:
- 第一层由输入\(x\)到隐变量\(h\);
- 第二层由\(h\)到输出\(y\);
3.3.2 神经元
\[y = \sigma(w^Tx + b) \]权重\(weight\):
- 连接线上的值,即图中的\(w_1,w_2,\cdots,w_d\);
- 不同的权值,输出结果不同
偏置值\(bias\):
- 输入\(x_1,x_2,\cdots,x_d\)进行加权求和之后,需要加上一个偏置值\(b\)。
可学习参数\(\sigma\):需要基于数据确定,需要调整这些参数,使得精度最大。
激活函数:
- 给神经网络加入非线性变换,使其能解决非线性分类的问题;
- 不包含可学习参数;
- 常用的激活函数有:Sigmoid、ReLU等。
3.3.3 多层感知器
多层感知器(Multilayer Perceptron,缩写MLP)是一种前向结构的人工神经网络,映射一组输入向量到一组输出向量。 MLP可以被看作是一个有向图,由多个的节点层所组成,每一层都全连接到下一层。 除了输入节点,每个节点都是一个带有非线性激活函数的神经元(或称处理单元)。
3.3.4 多分类任务
神经网络的输出层:
如果是多分类器任务,那么神经网络的输出就有多个(多选一),\(y_1,y_2,y_3\cdots\);
每个输出\(y_i\)介于\(0 \sim 1\)之间,且所有输出的和为1,表示为一个有效的概率分布;
为了满足上述特性,输出层的激活函数使用\(softmax\)。
\[soft = \frac{e^{x_i}}{\sum_{j=1}^ne^{x_j}} \]这里要保证两个条件:
- 保证每个类别输出大于0;
- 计算每个类别输出的占比,保证输出概率和为1;
3.4 神经网络的训练
3.4.1 神经网络训练介绍
让我们来思考一下神经网络的训练的几个问题。
1.假设给定一个神经网络,那么要如何才能找到能让这个神经网络在目标任务上达到最高性能的可学习参数的值呢?
- 答:使用Loss损失函数。
2.假设你得到了一个神经网络模型,要如何去衡量神经网络的性能?
- 错误率越低越好
- 定义连续的损失函数作为媒介
3.在训练过程中,怎么样去找到这个最好的可学习参数\(w\)的值?
- 反向传播+梯度下降+优化器。
3.4.2 损失函数
交叉熵损失Cross-Entropy Loss
对于预测的类别概率\(P \in [0,1]^K\)和类别真值\(y \in [1 , \cdots, K]\),定义交叉熵损失为\[L(P,y) = -logP_y \]
给定数据集\(\mathcal D = \left\{(X_i,y_i) \right\}_{i=1}^N\),模型\(F_w(X)\)和损失函数\(L(P,y)\),模型在数据集上的整体损失,定义为:
\[L(w|\mathcal D) = \frac{1}{N} \sum_{i=1}^{N} L(F_w(X_i),y_i) \]更一般地,对于两个概率向量\(P,Q \in [0,1]^K\),\(P\)相对于\(Q\)的交叉熵,定义为:
\[H(Q,P) = - \sum_{i=1}^K Q_i log P_i \]
3.4.3 梯度下降算法
如何在训练神经网络的过程中,通过调整\(w\),来降低损失函数的值,合适的方案引入梯度下降算法。
对于神经网络来说,我们的训练目标是,找到一组比较好的可学习参数\(w\)的值,从而使得神经网络的性能最好。
抽象成数学问题,那么这里的数学意义是,需要找到一组参数\(w\)的值,使得损失函数\(L\)的值最小。
我们可以基于梯度下降算法来寻找最优参数,进而得到最优(也就是准确率最高)的网络。
3.4.3.1 梯度计算
梯度下降算法思想的三要素:出发点、下降方向、下降步长。
机器学习中常用的权重更新表达式为:\[W = W - \lambda |W|\frac{dW}{|dW|} = W - \lambda dW \]这里的\(\lambda\)就是学习率,梯度方向是\(\frac{dW}{|dW|}\),步长设为常数\(\triangle\),\(W\)即为权重。
如果用在梯度较大的时候,离最优解比较远,\(W\)的更新比较快;然而到了梯度较小的时候,也就是较靠近最优解的时候,\(W\)的更新竟然也保持着跟原来一样的速率,这样会导致\(W\)很容易更新过度反而远离了最优解,进而出现在最优解附近来回震荡。所以,既然在远离最优解的时候梯度大,在靠近最优解的时候梯度小,我们让步长随着这个律动,于是我我们就用\(\lambda|W|\)来代替\(\triangle\),最后得到了我们熟悉的式子。在梯度下降算法中,我们的目标是——寻找损失函数曲面\(L(w)\)的谷点。
需要弄清楚几个概念:
- 凸函数:保证找到最小值点。
- 非凸函数:不能保证找到最小值点,和起始位置、每步的步长有关系。
梯度下降算法的过程,主要可以分为以下几步:
Step1:在损失函数的曲面\(L(w)\)中,随机选取找到一个起始点\(w^{(0)}\);
Step2:寻找下降最快的方向,也即负梯度方向\(\nabla_wL(w^{(0)})\),并前进一步
\[w^{(1)} = w^{(0)} - \eta \nabla_wL(w^{(0)}) \]其中,\(\nabla_w\)为学习率。
Step3:重复Step2,直到不能再下降。
3.4.3.2 反向传播算法
反向传播(英语:Backpropagation,意为误差反向传播,缩写为BP)是对多层人工神经网络进行梯度下降的算法,也就是用链式法则以网络每层的权重为变数计算损失函数的梯度,以更新权重来最小化损失函数。
任何监督式学习算法的目标是找到一个能把一组输入最好地映射到其正确的输出的函数。
例如一个简单的分类任务,其中输入是动物的图像,正确的输出将是动物的名称。一些输入和输出模式可以很容易地通过单层神经网络(如感知器)学习。但是这些单层的感知机只能学习一些比较简单的模式,例如那些非线性可分的模式。
例如,人可以通过识别动物的图像的某些特征进行分类,例如肢的数目,皮肤的纹理(无论是毛皮,羽毛,鳞片等),该动物的体型,以及种种其他特征。但是,单层神经网络必须仅仅使用图像中的像素的强度来学习一个输出一个标签函数。因为它被限制为仅具有一个层,所以没有办法从输入中学习到任何抽象特征。多层的网络克服了这一限制,因为它可以创建内部表示,并在每一层学习不同的特征。|
第一层可能负责从图像的单个像素的输入学习线条的走向。
第二层可能就会结合第一层所学并学习识别简单形状(如圆形)。
每升高一层就学习越来越多的抽象特征,如上文提到的用来图像分类。每一层都是从它下方的层中找到模式,就是这种能力创建了独立于为多层网络提供能量的外界输入的内部表达形式。反向传播算法的发展的目标和动机是找到一种训练的多层神经网络的方法,于是它可以学习合适的内部表达来让它学习任意的输入到输出的映射。
3.4.3.3 梯度下降算法的具体实现
对于神经网络的训练流程来说,主要以下几步:
- 1.计算样本的损失
- 2.计算样本损失的梯度
- 3.根据梯度信息更新参数
那么根据样本的数量的不同,梯度下降算法又有不同的实现方式:
- 标准梯度下降
- 随机梯度下降
- Momentum梯度下降
- 小批量梯度下降
标准梯度下降:
在标准梯度下降中,每步迭代都需要针对所有样本计算梯度,在大数据集上实现就不太现实。\[\nabla_wL(w) = \frac{1}{N} \sum_{i=1}^N \nabla_w L(F_w(X_i),y_i) \]注:通常N有万-百万量级。
随机梯度下降:
随机梯度下降(Stochastic Gradient Descent,SGD):每次迭代随机选取一部分样本\(\mathcal B^{(t)} = \left\{i_1, i_2,\cdots,i_B \right\}\),称为mini batch,计算梯度,作为完整梯度的近似\[\nabla_wL(w) \approx \frac{1}{B}\sum_{i \in \mathcal{B}} \nabla_wL(F_w(X_i),y_i) \]注:通常\(\mathcal B\)取几十到几百。
Batch越大,每下降一步的计算量越大,但是会更稳定。
小批量梯度下降算法:
这种算法,既不是选取全部样本参与计算,也没有只随机选取一个样本,而是选取一小部分样本参与计算。但应用不多。
3.4.3.4 优化器
在讨论梯度下降算法优化问题前,先来简单了解下,几种梯度下降算法的优缺点:
全量梯度下降法(Batch gradient descent)
全量梯度下降法每次学习都使用整个训练集,因此每次更新都会朝着正确的方向进行,最后能够保证收敛于极值点,凸函数收敛于全局极值点,非凸函数可能会收敛于局部极值点,缺陷就是学习时间太长,消耗大量内存。随机梯度下降法(Stochastic Gradient Descent)
SGD一轮迭代只用一条随机选取的数据,尽管SGD的迭代次数比BGD大很多,但一次学习时间非常快。
SGD的缺点在于每次更新可能并不会按照正确的方向进行,参数更新具有高方差,从而导致损失函数剧烈波动。不过,如果目标函数有盆地区域,SGD会使优化的方向从当前的局部极小值点跳到另一个更好的局部极小值点,这样对于非凸函数,可能最终收敛于一个较好的局部极值点,甚至全局极值点。
另一个缺点是,出现损失函数波动,无法判断是否收敛。
小批量梯度下降法(Mini-Batch Gradient Descent)
SGD相比BGD收敛速度快,然而,它也的缺点,那就是收敛时浮动,不稳定,在最优解附近波动,难以判断是否已经收敛。这时折中的算法小批量梯度下降法,MBGD就产生了,道理很简单,SGD太极端,一次一条,为何不多几条?MBGD就是用一次迭代多条数据的方法。
并且如果Batch Size选择合理,不仅收敛速度比SGD更快、更稳定,而且在最优解附近的跳动也不会很大,甚至得到比Batch Gradient Descent 更好的解。这样就综合了SGD和Batch Gradient Descent 的优点,同时弱化了缺点。总之,Mini-Batch比SGD和Batch Gradient Descent都好。
Momentum梯度下降法
SGD、BSGD两种改进方法都存在不同程度的震荡,如何避免震荡?或者说震荡是怎么产生的?震荡,从可视图表现来看,就是频繁更改方向,所以,如果能够把之前下降的方向考量进来,那么将会减少振荡。简单得来看,在损失函数的学习曲线中,参数更新=梯度下降+动量。
动量Momentum SGD:将上一步的移动延续到本步,帮助逃离局部极小值和鞍点,缓解随机梯度下降的波动。
3.4.3.5 自适应梯度算法
对梯度下降算法很难找到一个对每一次迭代都合适的全局学习速率,而一般情况下,我们希望学习速率在开始时比较大,之后随着训练的进行,学习速率能适当调整。于是自适应优化算法就出现了。
自适应梯度算法的基本思路是,不同的参数需要不同的学习率,根据梯度的历史幅度来自动调整学习率。
分为两个方向来进行调整学习率
- X方向,初始梯度小,训练过程中逐渐增大学习率;
- Y方向,初始梯度大,训练过程中逐渐减小学习率;
自适应优化算法主要有以下几种:
- Adagrad
- AdaDelta
- RMSprop
- Adam
3.4.3.6 基于梯度下降训练神经网络的整体流程
这里可以归纳整理下基于梯度下降训练神经网络的整体流程:
整体流程
数据集—(无放回采样)—>Mini Batch—(前传计算)—>损失—(反向计算)—>参数梯度—(梯度下降更新参数)—>可学习参数初始化策略
调整可学习参数,设置默认参数和变量等。
控制外层迭代轮数和内层迭代循环次数。外层循环(epoch)
基于(epoch)迭代模型参数直至收敛;内层训练(iteration)
基于(iteration)迭代模型参数直至采完所有数据。神经网络模型
前向计算+反向计算
优化器和学习率策略
设置模型优化器,调整学习率变化策略。
3.4.4 欠拟合、拟合与过拟合
对于深度学习或机器学习模型而言,我们不仅要求它对训练数据集有很好的拟合(训练误差),同时也希望它可以对未知数据集(测试集)有很好的拟合结果(泛化能力),所产生的测试误差被称为泛化误差。度量泛化能力的好坏,最直观的表现就是模型的过拟合(overfitting)和欠拟合(underfitting)。过拟合和欠拟合是用于描述模型在训练过程中的两种状态。一般来说,训练过程会是如下所示的一个曲线图。
训练刚开始的时候,模型还在学习过程中,处于欠拟合区域。随着训练的进行,训练误差和测试误差都下降。在到达一个临界点之后,训练集的误差下降,测试集的误差上升了,这个时候就进入了过拟合区域——由于训练出来的网络过度拟合了训练集,对训练集以外的数据却不work。
- 欠拟合:欠拟合指的是,模型没有捕捉到训练数据中的规律,不能准确预测未来(测试集)数据,模型过于简单。
- 拟合:拟合指的是,模型可以捕捉到训练数据中的规律,能够准确预测未来(测试集)数据。
- 过拟合:过度拟合到训练数据中的噪声,不能准确预测未来(测试集)数据,模型过于复杂、且数据不够。
如何解决欠拟合?
欠拟合基本上都会发生在训练刚开始的时候,经过不断训练之后欠拟合应该不怎么考虑了。但是如果真的还是存在的话,可以通过增加网络复杂度或者在模型中增加特征,这些都是很好解决欠拟合的方法。如何防止过拟合?
要想解决过拟合问题,就要显著减少测试误差而不过度增加训练误差,从而提高模型的泛化能力。我们可以使用正则化(Regularization)方法。那什么是正则化呢?正则化是指修改学习算法,使其降低泛化误差而非训练误差。常用的正则化方法根据具体的使用策略不同可分为:
- (1)直接提供正则化约束的参数正则化方法,如L1/L2正则化;
- (2)通过工程上的技巧来实现更低泛化误差的方法,如提前终止(Early stopping)和Dropout;
- (3)不直接提供约束的隐式正则化方法,如数据增强等。
3.4.5 早停Early Stopping
将训练数据集划分为训练集和验证集,在训练集上训练,周期性在验证集上测试分类精度。
当验证集的分类精度达到最值时,停止训练,防止过拟合。早停法是一种被广泛使用的方法,在很多案例上都比正则化的方法要好。其基本含义是在训练中计算模型在验证集上的表现,当模型在验证集上的表现开始下降的时候,停止训练,这样就能避免继续训练导致过拟合的问题。
其主要步骤如下:
- 1.将原始的训练数据集划分成训练集和验证集
- 2.只在训练集上进行训练,并每个一个周期计算模型在验证集上的误差,例如,每15次epoch(mini batch训练中的一个周期)
- 3.当模型在验证集上的误差比上一次训练结果差的时候停止训练
- 4.使用上一次迭代结果中的参数作为模型的最终参数
3.5 卷积神经网络
3.5.1 Why CNN?
在 CNN 出现之前,图像对于人工智能来说是一个难题,有2个原因:
- 1.图像需要处理的数据量太大,导致成本很高,效率很低。
- 2.图像在数字化的过程中很难保留原有的特征,导致图像处理的准确率不高
需要处理的数据量太大
图像是由像素构成的,每个像素又是由颜色构成的。
卷积神经网络 – CNN 解决的第一个问题就是“将复杂问题简化”,把大量参数降维成少量参数,再做处理。
更重要的是:我们在大部分场景下,降维并不会影响结果。
比如1000像素的图片缩小成200像素,并不影响肉眼认出来图片中是一只猫还是一只狗,机器也是如此。保留图像特征
所以当我们移动图像中的物体,用传统的方式的得出来的参数会差异很大!这是不符合图像处理的要求的。
而 CNN 解决了这个问题,它用类似视觉的方式保留了图像的特征,当图像做翻转,旋转或者变换位置时,它也能有效的识别出来是类似的图像。
同时,深度神经网络处理图片数据时也存在下面的问题:
- 参数量巨大
- 没有考虑图像本身的二维结构
于是我们考虑卷积神经网络的两个特点,局部连接和共享权重,由此可以大量节约参数,从而有效提取图像特征。
- 局部连接:像素局部相关
- 共享权重:位移不变性
卷积层输入输出的连接仅存在于局部空间,且连接的权重在不同输出单元之间是共享的。
典型的 CNN 由3个部分构成:
- 卷积层
- 池化层
- 全连接层
如果简单来描述的话:
- 卷积层:负责提取图像中的局部特征;
- 池化层:用来大幅降低参数量级(降维);
- 全连接层:类似传统神经网络的部分,用来输出想要的结果。
3.5.2 卷积层Convolutional Layer
灰度图像的卷积:
输入灰度图像——>转换线性矩阵——>卷积核卷积——>输出特征图。
用卷积核扫过整张图像,得到输出\[Y[h,w] = \sum_{i=-1}^{1}\sum_{j=-1}^{1}X[h+i,w+j]K[i,j]. \]
彩色图像的卷积:
输入灰度图像——>转换线性矩阵——>卷积核卷积——>输出特征图。
用卷积核扫过整张图像,得到输出\[Y[h,w] = \sum_{i=-1}^{1}\sum_{j=-1}^{1}\sum_{k=-1}^{3}X[h+i,w+j,k]K[i,j,k]. \]
类似地,我们使用多个卷积核,就能够产生多种特征。
输出特征图的通道数与卷积核的个数相同。
卷积层通过卷积运算,将\(C\)通道的特征图\(X \in \mathbb R^{H \times W \times C}\)变换为\(C^{'}\)通道的特征图\(Y \in \mathbb R^{H^{'} \times W^{'} \times C^{'} }\),计算公式为:
\[Y[h,w,c] = \sum_{i=1}^K \sum_{j=1}^{K} \sum_{k=1}^{C}X[h+i,w+j,k]K_c[i,j,k]+b[c]. \]其中,\(K \in \mathbb R^{C^{'}\times K \times K \times C}\)为\(C^{'}\)个\(C\)通道的卷积核,\(b \in \mathbb R^{C^t}\)为每个输出通道对应的偏置,二者均为可学习的参数。
3.5.2.1卷积的变形
此外,卷积层还可以通过变形,发挥其他的作用。
例如,卷积层可以增加边缘填充(padding)、步长(stride)和空洞(dilation)。\[Y[h,w,c] = \sum_{i=1}^K \sum_{j=1}^{K} \sum_{k=1}^{C}X[h+i,w+j,k]K_c[i,j,k]+b[c]. \]
3.5.4.2 卷积的边缘填充
卷积的边缘填充(padding):
- 边缘填充(padding)在输入特征图的边界处填补\(p\)个像素宽度的0值,以扩大输入和输出特征图的空间尺寸。
- \(H^{'} = H - K + 1 + 2p\).
3.5.2.3 卷积的步长
卷积的步长(padding)
- 步长(padding)降低卷积计算的空间频率,实现空间降采样。
- \(H^{'} = \left[\frac{H-F+2p}{S} + 1\right]\).
- 例:\(F=3,p=1.S=2\)且输入分辨率\(H\)为偶数的时候,输出分辨率恰好为输入的一半。|
- 这一方法在模型中广泛地使用。
3.5.3 激活层Activation Layer
激活层Activation Layer
- 激活层基于一个非线性函数\(\sigma:\mathbb R \rightarrow \mathbb R\)对输入特征图\(X \in \mathbb R^{H \times W \times C}\)进行逐元素的变换:
- \(Y[h, w, c] = \sigma(X[h,w,c])\).
- 激活层通常不包含可学习参数。
- 其中,ReLU(Rectfied Linear Unit)是卷积网络中最常用的非线性激活函数。
3.5.3.1 常用激活函数
3.5.3.2 Sigmoid
数学表达式:
sigmoid 函数是回归模型中使用的非线性函数。它的图形类似于“S”。此函数将其输入转换为介于 0 和 1 之间的概率值。较大的负值将转换为 0,而较大的正值将转换为 1。
这个计算量大的函数没有用在卷积神经网络的隐藏层中。由于它为大于 3 和小于 -3 的值提供低梯度,因此网络无法学习和执行。这称为梯度消失问题。
3.5.3.3 tanh
数学表达式:
tanh 函数最适用于两个不同类别的分类。和 sigmoid 一样,它是非线性的,也形成一个 S 形图。它的取值范围在-1到1之间。本质上是以零为中心的,具有很高的优化速度。对于大的正输入,它给出更接近 1 的输出,而对于更大的负输入,输出更接近 -1。该函数未在输出层中使用。
3.5.3.4 ReLU
数学表达式:
ReLu 是 sigmoid 和 tanh 激活函数的替代方法,是卷积神经网络和深度学习中激活最广泛的函数之一。与 sigmoid 和 tanh 不同,它没有消失的梯度问题。范围介于 0 和 + 无穷大之间。
ReLu 函数执行更快的计算,因为它不使用指数项。然而,缺点是其积极的一面可以走向更高端,从而导致训练阶段的计算问题。
3.5.3.5 SoftMax
数学表达式:
Softmax 是用于处理多个类别的非线性函数。它在 0 和 1 之间调整每个类别的输出,然后将它们除以它们的总和以确定输入值落入特定类别类别的可能性。该函数主要用于输出层,特别适用于需要将输入分类为多个类别的神经网络。
3.5.3.6 Leaky ReLU
数学表达式:
ReLU是将所有的负值都设为零,相反,Leaky ReLU是给所有负值赋予一个非零斜率。Leaky ReLU激活函数是在声学模型(2013)中首次提出的。
3.5.3.7 PReLU
数学表达式:
PReLU可以看作是Leaky ReLU的一个变体。在PReLU中,负值部分的斜率是根据数据来定的,而非预先定义的。作者称,在ImageNet分类(2015,Russakovsky等)上,PReLU是超越人类分类水平的关键所在。
3.5.3.8 ELU
数学表达式:
ELUs 通过正值的身份来缓解梯度消失问题。然而,与具有其他激活函数的单元相比,ELU 具有改进的学习特性。与 ReLU 相比,ELU 具有负值,这使得它们可以像批量归一化一样将平均单位激活推近零,但计算复杂度较低。均值向零偏移通过使正常梯度更接近单位自然梯度来加速学习,因为减少了偏差偏移效应。虽然 LReLU 和 PReLU 也有负值,它们不能确保抗噪停用状态。ELU 在输入较小时饱和为负值,从而减少前向传播的变化和信息。因此,ELU 对输入中特定现象的存在程度进行编码,而它们不会对它们的缺失程度进行定量建模。在实验中,ELU 不仅可以加快学习速度,而且在超过 5 层的网络上的泛化性能也明显优于 ReLU 和 LReLU。
3.5.4 池化层
Pooling layers是CNN中用来减小尺寸,提高运算速度的,同样能减小noise影响,让各特征更具有健壮性
Pooling layers没有卷积运算,仅在滤波器算子滑动区域内取最大值,即max pooling,这是最常用的做法。
池化层在特征图的局部区域内计算最大值或平均值,从而降低特征图分辨率,节省计算量,提高特征的空间鲁棒性。
3.5.5 全连接层
全连接层Fully Connected Layer
全连接层是指每个输入节点都连接到每个输出节点的神经网络。在卷积层中,并非所有节点都是连接的。
神经网络是一组相关的非线性函数。每个单独的功能都由一个神经元(或感知器)组成。在全连接层中,神经元通过权重矩阵对输入向量应用线性变换。然后通过非线性激活函数f对产品应用非线性变换。
全连接层,通过矩阵乘法将输入特征\(X \in \mathbb{R}^N\)映射为输出特征\(Y \in \mathbb{R}^M\)
\(Y = WX + b\)或\(Y = W_{vec}(X) + b\)
全连接层,包含可学习参数\(W \in \mathbb{R}^{M \times N}, b \in \mathbb{R}^{M}\).
在多层感知机中的层就是全连接层。
3.5.6 概率输出层
输出层
与神经网络中的所有层不同,输出层 神经元通常没有激活函数(或者您可以认为它们具有线性身份激活函数)。这是因为最后一个输出层通常用来表示类分数(例如在分类中),它们是任意实数值,或某种实数值目标(例如在回归中)。
- 概率输出层\(S:\mathbb{R}^{K}\rightarrow [0,1]^K\)将网络输出转换为概率向量;
- 二分类,全连接层输出标量\(z \in \mathbb{R}\),通过\(Sigmoid\)函数计算正类的概率
- 多分类,全连接层输出\(K\)维向量\(z \in \mathbb{R}^K\),通过\(Softmax\)函数计算\(K\)类的概率;
- \(P(y=k|x) = \frac{exp(z_k)}{\sum_{i=1}^K exp(z_k)}\).
3.5.4 用特征与分类的角度理解CNN
解析完CNN的各种层,也可以从特征与分类的角度来理解CNN。
- 我们可以将CNN看作是一个黑盒,这个黑盒的作用是一个端到端学习的分类器\(P(y|x) = h(x;w)\).
- 我们把CNN做一个结构的分拆,可以理解为需要实现两个任务,学习一个好图像特征以及通过简单的分类器完成分类。
- 最后,可以分析一下这个视觉任务的核心问题,也就是其本质是,要稳健地表达和描述图像内容,不容像素外观影响。
3.6 Pytorch环境配置与基础使用
3.6.1 Pytorch介绍
PyTorch 是基于Python和 Torch优化的深度学习张量库,主要用于使用 GPU 和 CPU 的应用程序。PyTorch 优于TensorFlow 和 Keras等其他深度学习框架,因为它使用动态计算图并且完全是 Pythonic。它允许科学家、开发人员和神经网络调试人员实时运行和测试部分代码。因此,用户不必等待整个代码被实现来检查代码的一部分是否有效。
PyTorch 的两个主要特点是:
- 具有强大GPU(图形处理单元)加速支持的张量计算(类似于NumPy)
- 用于创建和训练深度神经网络的自动微分
3.6.2 Pytorch环境配置
PyTorch 入门非常简单。推荐的最佳选择是使用 Anaconda Python 包管理器。
使用 Anaconda,可以轻松获取和管理 Python、Jupyter Notebook 以及其他用于科学计算和数据科学的常用软件包,例如 PyTorch!
让我们回顾一下这些步骤:
- 下载并安装 Anaconda(选择最新的 Python 版本)。
- 转到 PyTorch 的站点并找到 本地入门部分。
- 为您的特定环境指定适当的配置选项。
- 在终端中运行提供的命令以安装 PyTorch。
例如,假设我们有以下配置:
Item Value PyTorch Build Stable OS Windows Package Manager Conda Language Python Compute Platform CUDA 10.2 在这种情况下,我们有以下命令:
conda install pytorch torchvision torchaudio cudatoolkit=10.2 -c pytorch
请注意,我们正在安装
PyTorch
和torchvision
。此外,无需单独安装 CUDA。如果在步骤 (3) 中选择了 CUDA 版本,则所需的 CUDA 软件会随 PyTorch 一起安装。如果我们的系统上有支持的 Nvidia GPU,我们需要做的就是选择一个 CUDA 版本。conda list torch # packages in environment at C:\Users\deeplizard\Anaconda3: # # Name Version Build Channel pytorch 1.10 .2 py3 .6 _cuda10 .2 _cudnn7_0 pytorch torchvision 0.11 .3 py36_cu102 pytorch torchaudio 0.10 .2 py36_cu102 pytorch
验证 PyTorch 安装
为验证我们的 PyTorch 安装已全部设置好并且我们已准备好编写代码,我们将在笔记本中执行此操作。为了组织项目的各个部分,我们将创建一个名为 PyTorch 的文件夹,并将所有内容放入该文件夹中。
验证安装的步骤:
- 要使用 PyTorch,我们
import torch
.- 要检查版本,我们使用
torch.__version__
现在,为了验证我们的 GPU 能力,我们使用
torch.cuda.is_available()
并检查 cuda 版本。> torch.cuda.is_available() True
> torch.version.cuda '10.2'
如果您的
torch.cuda.is_available()
调用返回 false,可能是因为您的系统上没有安装受支持的 Nvidia GPU。
3.6.3 Pytorch的基本模块
针对深度学习模型构建与训练,Pytorch提供了以下模块:
- torch:Tensor库
- autograd:自动求导
- nn:神经网络构建
- optim:优化器
- utils.data:数据接口
- nn.Module:通用模型接口
- nn.functional:函数库
3.6.3.1 数值计算库torch
数值计算库torch 库包含多维张量的数据结构,并定义了这些张量的数学运算。此外,它还提供了许多用于高效序列化张量和任意类型的实用程序,以及其他有用的实用程序。
- 多维数组的数据结构Tensor
- 多维数组的运算
- 多计算后端支持
- https://pytorch.org/docs/stable/torch.html
3.6.3.2 自动求导torch.autograd
torch.autograd
提供实现任意标量值函数自动微分的类和函数。它需要对现有代码进行最少的更改——您只需要声明Tensor
应该使用关键字计算梯度的 srequires_grad=True
。截至目前,我们仅支持浮点Tensor
类型(half、float、double 和 bfloat16)和复杂Tensor
类型(cfloat、cdouble)的 autograd。
3.6.3.3 函数库torch.nn.funcitonal
nn.functional
是一个很常用的模块,nn
中的大多数layer在functional
中都有一个与之对应的函数。nn.functional
中的函数与nn.Module()
的区别是:
nn.Module
实现的层(layer)是一个特殊的类,都是由class Layer(nn.Module)
定义,会自动提取可学习的参数
nn.functional
中的函数更像是纯函数,由def functional(input)
定义
torch.nn.functional
提供了构建神经网络所需的计算函数:
线性函数
卷积
池化
非线性激活
3.6.3.4 通用模型封装torch.nn.Module
torch.nn.Module
是所有神经网络模块的基类。
torch.nn.Module定义了神经网络模型的抽象接口。
Module还可以包含其他 Module,允许将它们嵌套在树结构中。您可以将子模块分配为常规属性:import torch.nn as nn import torch.nn.functional as F class Model(nn.Module): def __init__(self): super().__init__() self.conv1 = nn.Conv2d(1, 20, 5) self.conv2 = nn.Conv2d(20, 20, 5) def forward(self, x): x = F.relu(self.conv1(x)) return F.relu(self.conv2(x))
以这种方式分配的子模块将被注册,并且在您调用时也会转换它们的参数
to()
等。
3.6.3.5 优化器torch.optim
torch.optim
是一个实现各种优化算法的包。大多数常用的方法都已经支持,接口也足够通用,以便将来可以轻松集成更复杂的方法。
torch.optim
支持常用的优化算法:
- SGD
- Adam
- RMSprop
以及常用的学习率策略:
步长衰减
指数率减
学习率循环
如何使用优化器
要使用
torch.optim
你必须构建一个优化器对象,它将保持当前状态并根据计算的梯度更新参数。构建它
要构造一个
Optimizer
,你必须给它一个包含要优化的参数(都应该是Variable
s)的可迭代对象。然后,您可以指定特定于优化器的选项,例如学习率、权重衰减等。例子:
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9) optimizer = optim.Adam([var1, var2], lr=0.0001)
3.6.3.6 数据工具torch.utils.data
torch.utils.data
提供了统一方便的数据集模型Dataste以及支持多线程预读的数据加载器DataLoader。PyTorch 数据加载实用程序的核心是类
torch.utils.data.DataLoader
。它代表一个可在数据集上迭代的 Python,支持这些选项由 a 的构造函数参数配置
DataLoader
,具有签名:DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, batch_sampler=None, num_workers=0, collate_fn=None, pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None, *, prefetch_factor=2, persistent_workers=False)
3.6.4 Pytorch神经网络demo演示及讲解
处理数据
PyTorch 有两个原语来处理数据:
torch.utils.data.DataLoader
和torch.utils.data.Dataset
。Dataset
存储样本及其相应的标签,并DataLoader
在Dataset
.import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets from torchvision.transforms import ToTensor
PyTorch 提供特定领域的库,例如TorchText、 TorchVision和TorchAudio,所有这些库都包含数据集。对于本教程,我们将使用 TorchVision 数据集。
该
torchvision.datasets
模块包含Dataset
许多真实世界视觉数据的对象,如 CIFAR、COCO(此处为完整列表)。在本教程中,我们使用 FashionMNIST 数据集。每个 TorchVision 都Dataset
包含两个参数:transform
和target_transform
分别修改样本和标签。# Download training data from open datasets. training_data = datasets.FashionMNIST( root="data", train=True, download=True, transform=ToTensor(), ) # Download test data from open datasets. test_data = datasets.FashionMNIST( root="data", train=False, download=True, transform=ToTensor(), )
我们将
Dataset
作为参数传递给DataLoader
。这在我们的数据集上包装了一个可迭代对象,并支持自动批处理、采样、混洗和多进程数据加载。这里我们定义了一个批大小为 64,即 dataloader 中的每个元素 iterable 将返回一批 64 个特征和标签。batch_size = 64 # Create data loaders. train_dataloader = DataLoader(training_data, batch_size=batch_size) test_dataloader = DataLoader(test_data, batch_size=batch_size) for X, y in test_dataloader: print(f"Shape of X [N, C, H, W]: {X.shape}") print(f"Shape of y: {y.shape} {y.dtype}") break