DNN,CNN,RNN的区别在于结构上的差别,产生这种差别主要还是因为要解决的问题不同,其中:
DNN也是人工神经网络(ANN),区别在于层数不同,ANN结构如下:
多层感知机(multilayer perceptron)
同时,每个感知器的结构如下:
每个感知机的输出都是输入加权和的激活。单层网络仅学习线性函数,但不学习复杂关系,所谓的DNN就是层数较多的多层感知机。
DNN和ANN的差别是DNN是层数较多的ANN,对于浅层MLP而言,通常用于解决回归和分类问题,对特征本身没有处理的能力,当隐藏层数加多时,网络甚至能自己去提取特征,而不用再经过特征预处理的阶段。这里的深度指的是层数的深度,其实并没有特定的规模,比如:4层网络能分类语音信号,而用于图像分类的网络通常需要20层才能够满足条件。
在层数较多的情况下, 训练时候很容易出现“梯度消失”现象,如果激活函数是sigmoid函数,使用BP反向传播梯度算法训练,对于幅度为1,的前一层输入,到后一层的时候,会减少为0.25,当层数一多时,低层信号就接受不到有效的训练信号了。
为了克服梯度消失,ReLU、maxout等传输函数代替了sigmoid。这大约DNN的结构
事物的发展是按照时间序列展开的,即前一刻发生的事物会对未来的事情的发展产生影响。,对于MLP结构而言无法捕获处理序列数据所需的输入数据中的顺序信息。样本出现的时间顺序对于自然语言处理、语音识别、手写体识别等应用非常重要,此类问题可以用RNN来处理。
所谓的RNN就是以下结构的感知机网络。
可以看到,每个感知机的输入,会加上上次这个感知机的上次输出结果。但是这种结构也有问题,比如一个时间点的信号,可能过去5轮,这个点的输出就已经消失了,同样也是梯度消失的问题,因此这种结构只对短时的时间序列有效,如果需要长时间记忆,需要采用LSTM模型(长短时记忆单元)。
图中是一个图形识别的CNN模型。可以看出最左边的船的图像就是我们的输入层,计算机理解为输入若干个矩阵,这点和DNN基本相同。
这个是CNN特有的,我们后面专门来讲。卷积层的激活函数使用的是ReLU。我们在DNN中介绍过ReLU的激活函数,它其实很简单,就是ReLU(x)=max(0,x)
单个卷积核的结果。
池化和卷积类似,但是池化是没有激活函数的。
相比卷积层的复杂,池化层则要简单的多,所谓的池化,个人理解就是对输入张量的各个子矩阵进行压缩。假如是2x2的池化,那么就将子矩阵的每2x2个元素变成一个元素,如果是3x3的池化,那么就将子矩阵的每3x3个元素变成一个元素,这样输入矩阵的维度就变小了。
要想将输入子矩阵的每nxn个元素变成一个元素,那么需要一个池化标准。常见的池化标准有2个,MAX或者是Average。即取对应区域的最大值或者平均值作为池化后的元素值。
卷积层+池化层的组合可以在隐藏层出现很多次,上图中出现两次。而实际上这个次数是根据模型的需要而来的。当然我们也可以灵活使用使用卷积层+卷积层,或者卷积层+卷积层+池化层的组合,这些在构建模型的时候没有限制。但是最常见的CNN都是若干卷积层+池化层的组合,如上图中的CNN结构。
在若干卷积层+池化层后面是全连接层(Fully Connected Layer, 简称FC),全连接层其实就是我们前面讲的DNN结构,只是输出层使用了Softmax激活函数来做图像识别的分类,这点我们在DNN中也有讲述。
alexnet
alexnet
fast-rcnn
yolo
本文主要描述了CNN及其派生网络的结构以及应用。
CNN就是卷积神经网络,其网络结构模式如下:
CNN主要由卷积层,池化层,以及后面的传统多层感知机组成,事实上CNN有多个分支:
这些分支其实都由卷积层,池化层和MLP单元组成,只不过组成的结构不同。
图像分类: 和传统的分类任务一样,输出是一个离散的label值。
目标识别: 输出是多个对象的坐标和及其分类。
分为:
传统的MLP的输入是一个列向量,但在CNN将输入看成一个nxm的矩阵,这是利用根据图像结构来提取特征。
卷积的结果在MLP结构下称谓隐藏层,CNN的隐藏层结构也是一个矩阵,计算方法如下:
从上面的计算方法得到:如果输入层是尺寸为28X28的图像,卷积核的大小为5X5,那么得到的第一个隐藏层的大小是24X24。
我们知道单个神经元的输入加权和是:
输出是加权和加上偏移的对于激活函数映射的像。
、
$$f(uk + bias)$$
卷积层的输入是mxn的矩阵,假设卷积核大小lxl,那么输出就是:
$$(m-l)*(n-l)$$
的矩阵作为输出。
单个卷积核只能检测某个特定的特征,当然单个特征不能用于检测一个图片。
因此可能有多个特征,这时候输出就变成了:
$$ ((m-l)(n-l)p) $$
卷积层的个数,一般卷积核要到达6个以上,比如我们认为5个方向的特征就能完整描述一个特征
一个卷积层的结果例子:
经过激活函数后的结果:
池化层(pooling layers) 池化层通常紧随卷积层之后使用,池化分为两种,Max Pooling 最大池化、Average Pooling平均池化。顾名思义,最大池化就是取最大值,平均池化就是取平均值。
其作用是简化卷积层的输出。例如,池化层中的每一个神经元可能将前一层的一个2X2区域内的神经元求和。
而另一个经常使用的max-pooling,该池化单元简单地将一个2X2的输入域中的最大激励输出,如下图所示:
如果卷积层的输出包含24X24个神经元,那么在池化后可得到12X12个神经元。每一个特征映射后分别有一个池化处理,前面所述的卷积层池化后的结构为:
在池化之后,就是接上传统的MLP结构:
由于mlp结构只接受行向量作为输入,因此要将池化层的结果转为行向量,如上图,输入是3x12x12个像素也就是432个输入节点。
训练是对全连接层的进行训练,有BP反向传播算法。
还是老家伙误差函数,每次训练的权值改变为:
其中是训练的步长度。
CNN的优点:
缺点:
应用:
AlexNet一共有8层,网络结构图:
前五层为卷积层:
后三层为全连接层:
AlexNet的特点在于:
AlexNet的最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000个类别预测的值。
AlexNet的每层需要的参数量和计算量:
RCNN MATLAB项目
R-CNN是2014年出现的。它是将CNN用于对象检测的起源,能够基于丰富的特征层次结构进行目标精确检测和语义分割来源,比如:
RCNN 是传统的two-state
算法,包含了候选区回归,和具体的分类两个步骤,候选区回归的会找到一些候选区,但毕竟只是候选,等真正识别出其中的对象以后,还要对候选区进行微调,使之更接近真实的bounding box。这个过程就是边框回归:将候选区bounding box调整到更接近真实的bounding box。
R-CNN的模型如下:
流程如下:
R-CNN等包括YOLO模型在传统CNN网络前端加上一个区域提取阶段,称为区域建议网络,图片中的一小部分作为其输入数据,由于CNN网络的输入图像尺寸必须是固定的某一个大小(否则全连接时没法计算),因此候选框子图必须将图像裁剪缩放到相同尺寸大小,然后对图像中每个区域进行CNN分类,提取特征的坐标也作为输出,因此可以得到目标的坐标和目标的分类,对于最后的分类阶段,一般是用一个SVM分类器,因为这些预编码好的分类肯定是线性可分的。
R-CNN模型速度较慢,因为对于每次的region propersol都需要进行一次CNN计算。
(1)在数据集上训练CNN 。R-CNN论文中使用的CNN网络是AlexNet,数据集为ImageNet 。
(2)在目标检测的数据集上,对训练好的CNN做微调。
(3)用Selective Search搜索候选区域,统一使用微调后的CNN对这些区域提取特征,并将提取到的特征存储起来。
(4)使用存储起来的特征,训练SVM分类器。
Faster R-CNN的计算流程如下:
faster-r-cnn相对于r-cnn的改进如下:
卷积神经网络直接产生region proposal,使用的方法本质上就是滑动窗口。RPN只需在最后的卷积层上滑动一遍,因为anchor机制和边框回归可以得到多尺度、多长宽比的region proposal,3*3滑窗对应的每个特征区域同时预测输入图像3种尺度(128,256,512),3种长宽比(1:1,1:2,2:1)的region proposal,这种映射的机制称为anchor。
faster-r-cnn的网络结构如下,特点就是卷积层针对的是整个图片而不是某个区域
整个Faster RCNN训练过程可分为4步:
YOLO将物体检测作为一个回归问题进行求解,输入图像经过一次inference,便能得到图像中所有物体的位置和其所属类别及相应的置信概率。而rcnn/fast rcnn/faster rcnn将检测结果分为两部分求解:物体类别(分类问题),物体位置即bounding box(回归问题)。
去掉候选区这个步骤以后,YOLO的结构非常简单,就是单纯的卷积、池化最后加了两层全连接。最大的差异是最后输出层用线性函数做激活函数,因为需要预测bounding box的位置(数值型),而不仅仅是对象的概率。YOLO网络结构由24个卷积层与2个全连接层构成,网络入口为448x448(v2为416x416),图片进入网络先经过resize,网络的输出结果为一个张量,维度为:
.
其中,S为划分网格数,B为每个网格负责的边框个数,C为类别个数。每个小格会对应B个边界框,边界框的宽高范围为全图,表示以该小格为中心寻找物体的边界框位置。每个边界框对应一个分值,代表该处是否有物体及定位准确度:,每个小格会对应C个概率值,找出最大概率对应的类别P(Class|object),并认为小格中包含该物体或者该物体的一部分。
实际上,YOLO并没有真正去掉候选区,而是采用了预定义的候选区(准确点说应该是预测区,因为并不是Faster RCNN所采用的Anchor)。比如将图片划分为 77=49 个网格(grid),每个网格允许预测出2个边框(bounding box,包含某个对象的矩形框),总共 492=98 个bounding box。可以理解为98个候选区,它们很粗略的覆盖了图片的整个区域。
输入就是原始图像,唯一的要求是缩放到448448的大小。主要是因为YOLO的网络中,卷积层最后接了两个全连接层,全连接层是要求固定大小的向量作为输入,所以倒推回去也就要求原始图像有固定的尺寸。那么YOLO设计的尺寸就是448448。
输入图像被划分为 77 的网格(grid),输出张量中的 77 就对应着输入图像的 77 网格。或者我们把 77*30 的张量看作49个30维的向量,也就是输入图像中的每个网格对应输出一个30维的向量。参考上图,比如输入图像左上角的网格对应到输出张量中左上角的向量。
要注意的是,并不是说仅仅网格内的信息被映射到一个30维向量。经过神经网络对输入图像信息的提取和变换,网格周边的信息也会被识别和整理,最后编码到那个30维向量中。其中包含了:
YOLO先使用ImageNet数据集对前20层卷积网络进行预训练,然后使用完整的网络,在PASCAL VOC数据集上进行对象识别和定位的训练和预测。YOLO的网络结构如下图所示:</br>
参数是被数据和算法训练出来的。而超参数(比如学习速率)不是被训练出来的,而是人为手工调整的。调整超参数更像是一种艺术,而不是科学,常见的超参数是:
模型的复杂程度本身就是一个超参数。
模型简单,导致偏差变大,称为高偏差,欠拟合。
模型复杂,导致方差变大,称为高方差,过拟合。
也称为过拟合-高方差。
过拟合现象可以总结为:
模型出现过拟合现象的主要原因是:
在模型训练的过程中,需要降低 loss 以达到提高 accuracy 的目的。此时,使用正则化之类的方法直接将权值的大小加入到 loss 里,在训练的时候限制权值变大。训练过程需要降低整体的 loss,这时候,一方面能降低实际输出与样本之间的误差,也能降低权值大小
正则化方法包括 L0 正则、 L1 正则和 L2 正则,而正则一般是在目标函数之后加上对于的范数。但是在机器学习中一般使用 L2 正则:
L2 范数是指向量各元素的平方和然后求平方根。可以使得 W 的每个元素都很小,都接近于0,但不会让它等于0,而是接近于0。 L2 正则项起到使得参数 W 变小加剧的效果,关于它为什么能防止过拟合简答的理解为:更小的参数值 W 意味着模型的复杂度更低,对训练数据的拟合刚刚好,不会过分拟合训练数据,从而使得不会过拟合,以提高模型的泛化能力
这是解决过拟合最有效的方法,只要给足够多的数据,让模型「看见」尽可能多的「例外情况」,它就会不断修正自己,从而得到更好的结果
如何获取更多数据,可以有以下几个方法
在训练时,每次随机(如50%概率)忽略隐层的某些节点;这样,我们相当于随机从 2^n(n个神经元的网络) 个模型中采样选择模型
Early stopping便是一种迭代次数截断的方法来防止过拟合的方法,即在模型对训练数据集迭代收敛之前停止迭代来防止过拟合。
具体做法是,在每一个Epoch结束时计算validation data的accuracy,当accuracy不再提高时,就停止训练。当然我们并不会在accuracy一降低的时候就停止训练,因为可能经过这个Epoch后,accuracy降低了,但是随后的Epoch又让accuracy又上去了,所以不能根据一两次的连续降低就判断不再提高。一般的做法是,在训练的过程中,记录到目前为止最好的validation accuracy,当连续10次Epoch(或者更多次)没达到最佳accuracy时,则可以认为accuracy不再提高了。此时便可以停止迭代了(Early Stopping)。这种策略也称为“No-improvement-in-n”,n即Epoch的次数,可以根据实际情况取,如10、20、30……
欠拟合就是模型没有很好地捕捉到数据特征,不能够很好地拟合数据,例如下面的例子:
欠拟合出现的原因:
欠拟合的情况比较容易克服,常见解决方法有:
过拟合的解决方案:
XGBoost是陈天奇等人开发的一个开源机器学习项目,高效地实现了GBDT算法并进行了算法和工程上的许多改进,被广泛应用在Kaggle竞赛及其他许多机器学习竞赛中并取得了不错的成绩。
说到XGBoost,不得不提GBDT(Gradient Boosting Decision Tree)。因为XGBoost本质上还是一个GBDT,但是力争把速度和效率发挥到极致,所以叫X (Extreme) GBoosted。包括前面说过,两者都是boosting方法。
关于GBDT,这里不再提,可以查看我前一篇的介绍,点此跳转。
先来举个例子,我们要预测一家人对电子游戏的喜好程度,考虑到年轻和年老相比,年轻更可能喜欢电子游戏,以及男性和女性相比,男性更喜欢电子游戏,故先根据年龄大小区分小孩和大人,然后再通过性别区分开是男是女,逐一给各人在电子游戏喜好程度上打分,如下图所示。
就这样,训练出了2棵树tree1和tree2,类似之前gbdt的原理,两棵树的结论累加起来便是最终的结论,所以小孩的预测分数就是两棵树中小孩所落到的结点的分数相加:2 + 0.9 = 2.9。爷爷的预测分数同理:-1 + (-0.9)= -1.9。具体如下图所示:
恩,你可能要拍案而起了,惊呼,这不是跟上文介绍的GBDT乃异曲同工么?
事实上,如果不考虑工程实现、解决问题上的一些差异,XGBoost与GBDT比较大的不同就是目标函数的定义。XGBoost的目标函数如下图所示:
其中:
看到这里可能有些读者会头晕了,这么多公式,我在这里只做一个简要式的讲解,具体的算法细节和公式求解请查看这篇博文,讲得很仔细:通俗理解kaggle比赛大杀器xgboost
XGBoost的核心算法思想不难,基本就是:
显然,我们的目标是要使得树群的预测值尽量接近真实值
,而且有尽量大的泛化能力。类似之前GBDT的套路,XGBoost也是需要将多棵树的得分累加得到最终的预测得分(每一次迭代,都在现有树的基础上,增加一棵树去拟合前面树的预测结果与真实值之间的残差)。
那接下来,我们如何选择每一轮加入什么 f 呢?答案是非常直接的,选取一个 f 来使得我们的目标函数尽量最大地降低。这里 f 可以使用泰勒展开公式近似。
实质是把样本分配到叶子结点会对应一个obj,优化过程就是obj优化。也就是分裂节点到叶子不同的组合,不同的组合对应不同obj,所有的优化围绕这个思想展开。到目前为止我们讨论了目标函数中的第一个部分:训练误差。接下来我们讨论目标函数的第二个部分:正则项,即如何定义树的复杂度。
XGBoost对树的复杂度包含了两个部分:
我们再来看一下XGBoost的目标函数(损失函数揭示训练误差 + 正则化定义复杂度):
正则化公式也就是目标函数的后半部分,对于上式而言,是整个累加模型的输出,正则化项∑kΩ(ft)是则表示树的复杂度的函数,值越小复杂度越低,泛化能力越强。
很有意思的一个事是,我们从头到尾了解了xgboost如何优化、如何计算,但树到底长啥样,我们却一直没看到。很显然,一棵树的生成是由一个节点一分为二,然后不断分裂最终形成为整棵树。那么树怎么分裂的就成为了接下来我们要探讨的关键。对于一个叶子节点如何进行分裂,XGBoost作者在其原始论文中给出了一种分裂节点的方法:枚举所有不同树结构的贪心法
不断地枚举不同树的结构,然后利用打分函数来寻找出一个最优结构的树,接着加入到模型中,不断重复这样的操作。这个寻找的过程使用的就是贪心算法。选择一个feature分裂,计算loss function最小值,然后再选一个feature分裂,又得到一个loss function最小值,你枚举完,找一个效果最好的,把树给分裂,就得到了小树苗。
总而言之,XGBoost使用了和CART回归树一样的想法,利用贪婪算法,遍历所有特征的所有特征划分点,不同的是使用的目标函数不一样。具体做法就是分裂后的目标函数值比单子叶子节点的目标函数的增益,同时为了限制树生长过深,还加了个阈值,只有当增益大于该阈值才进行分裂。从而继续分裂,形成一棵树,再形成一棵树,每次在上一次的预测基础上取最优进一步分裂/建树。
凡是这种循环迭代的方式必定有停止条件,什么时候停止呢?简言之,设置树的最大深度、当样本权重和小于设定阈值时停止生长以防止过拟合。具体而言,则
除了算法上与传统的GBDT有一些不同外,XGBoost还在工程实现上做了大量的优化。总的来说,两者之间的区别和联系可以总结成以下几个方面。
XGBoost使用了一阶和二阶偏导, 二阶导数有利于梯度下降的更快更准. 使用泰勒展开取得函数做自变量的二阶导数形式, 可以在不选定损失函数具体形式的情况下, 仅仅依靠输入数据的值就可以进行叶子分裂优化计算, 本质上也就把损失函数的选取和模型算法优化/参数选择分开了. 这种去耦合增加了XGBoost的适用性, 使得它按需选取损失函数, 可以用于分类, 也可以用于回归。
GitHub:点击进入
作者:@mantchs
概率图模型是用图来表示变量概率依赖关系的理论,结合概率论与图论的知识,利用图来表示与模型有关的变量的联合概率分布。由图灵奖获得者Pearl开发出来。
如果用一个词来形容概率图模型(Probabilistic Graphical Model)的话,那就是“优雅”。对于一个实际问题,我们希望能够挖掘隐含在数据中的知识。概率图模型构建了这样一幅图,用观测结点表示观测到的数据,用隐含结点表示潜在的知识,用边来描述知识与数据的相互关系,最后基于这样的关系图获得一个概率分布,非常“优雅”地解决了问题。
概率图中的节点分为隐含节点和观测节点,边分为有向边和无向边。从概率论的角度,节点对应于随机变量,边对应于随机变量的依赖或相关关系,其中有向边表示单向的依赖,无向边表示相互依赖关系。
概率图模型分为贝叶斯网络(Bayesian Network)和马尔可夫网络(Markov Network)两大类。贝叶斯网络可以用一个有向图结构表示,马尔可夫网络可以表 示成一个无向图的网络结构。更详细地说,概率图模型包括了朴素贝叶斯模型、最大熵模型、隐马尔可夫模型、条件随机场、主题模型等,在机器学习的诸多场景中都有着广泛的应用。
长久以来,人们对一件事情发生或不发生的概率,只有固定的0和1,即要么发生,要么不发生,从来不会去考虑某件事情发生的概率有多大,不发生的概率又是多大。而且概率虽然未知,但最起码是一个确定的值。比如如果问那时的人们一个问题:“有一个袋子,里面装着若干个白球和黑球,请问从袋子中取得白球的概率是多少?”他们会想都不用想,会立马告诉你,取出白球的概率就是1/2,要么取到白球,要么取不到白球,即θ只能有一个值,而且不论你取了多少次,取得白球的概率θ始终都是1/2,即不随观察结果X 的变化而变化。
这种频率派的观点长期统治着人们的观念,直到后来一个名叫Thomas Bayes的人物出现。
托马斯·贝叶斯Thomas Bayes(1702-1763)在世时,并不为当时的人们所熟知,很少发表论文或出版著作,与当时学术界的人沟通交流也很少,用现在的话来说,贝叶斯就是活生生一民间学术“屌丝”,可这个“屌丝”最终发表了一篇名为“An essay towards solving a problem in the doctrine of chances”,翻译过来则是:机遇理论中一个问题的解。你可能觉得我要说:这篇论文的发表随机产生轰动效应,从而奠定贝叶斯在学术史上的地位。
这篇论文可以用上面的例子来说明,“有一个袋子,里面装着若干个白球和黑球,请问从袋子中取得白球的概率θ是多少?”贝叶斯认为取得白球的概率是个不确定的值,因为其中含有机遇的成分。比如,一个朋友创业,你明明知道创业的结果就两种,即要么成功要么失败,但你依然会忍不住去估计他创业成功的几率有多大?你如果对他为人比较了解,而且有方法、思路清晰、有毅力、且能团结周围的人,你会不由自主的估计他创业成功的几率可能在80%以上。这种不同于最开始的“非黑即白、非0即1”的思考方式,便是贝叶斯式的思考方式。
先简单总结下频率派与贝叶斯派各自不同的思考方式:
贝叶斯派既然把看做是一个随机变量,所以要计算的分布,便得事先知道的无条件分布,即在有样本之前(或观察到X之前),有着怎样的分布呢?
比如往台球桌上扔一个球,这个球落会落在何处呢?如果是不偏不倚的把球抛出去,那么此球落在台球桌上的任一位置都有着相同的机会,即球落在台球桌上某一位置的概率服从均匀分布。这种在实验之前定下的属于基本前提性质的分布称为先验分布,或着无条件分布。
其中,先验信息一般来源于经验跟历史资料。比如林丹跟某选手对决,解说一般会根据林丹历次比赛的成绩对此次比赛的胜负做个大致的判断。再比如,某工厂每天都要对产品进行质检,以评估产品的不合格率θ,经过一段时间后便会积累大量的历史资料,这些历史资料便是先验知识,有了这些先验知识,便在决定对一个产品是否需要每天质检时便有了依据,如果以往的历史资料显示,某产品的不合格率只有0.01%,便可视为信得过产品或免检产品,只每月抽检一两次,从而省去大量的人力物力。
而后验分布π(θ|X)一般也认为是在给定样本X的情况下的θ条件分布,而使π(θ|X)达到最大的值θMD称为最大后验估计,类似于经典统计学中的极大似然估计。
综合起来看,则好比是人类刚开始时对大自然只有少得可怜的先验知识,但随着不断观察、实验获得更多的样本、结果,使得人们对自然界的规律摸得越来越透彻。所以,贝叶斯方法既符合人们日常生活的思考方式,也符合人们认识自然的规律,经过不断的发展,最终占据统计学领域的半壁江山,与经典统计学分庭抗礼。
条件概率(又称后验概率)就是事件A在另外一个事件B已经发生条件下的发生概率。条件概率表示为P(A|B),读作“在B条件下A的概率”。
比如上图,在同一个样本空间Ω中的事件或者子集A与B,如果随机从Ω中选出的一个元素属于B,那么这个随机选择的元素还属于A的概率就定义为在B的前提下A的条件概率:
联合概率:
边缘概率(先验概率):P(A)或者P(B)
贝叶斯网络(Bayesian network),又称信念网络(Belief Network),或有向无环图模型(directed acyclic graphical model),是一种概率图模型,于1985年由Judea Pearl首先提出。它是一种模拟人类推理过程中因果关系的不确定性处理模型,其网络拓朴结构是一个有向无环图(DAG)。
贝叶斯网络的有向无环图中的节点表示随机变量
它们可以是可观察到的变量,或隐变量、未知参数等。认为有因果关系(或非条件独立)的变量或命题则用箭头来连接。若两个节点间以一个单箭头连接在一起,表示其中一个节点是“因(parents)”,另一个是“果(children)”,两节点就会产生一个条件概率值。
例如,假设节点E直接影响到节点H,即E→H,则用从E指向H的箭头建立结点E到结点H的有向弧(E,H),权值(即连接强度)用条件概率P(H|E)来表示,如下图所示:
简言之,把某个研究系统中涉及的随机变量,根据是否条件独立绘制在一个有向图中,就形成了贝叶斯网络。其主要用来描述随机变量之间的条件依赖,用圈表示随机变量(random variables),用箭头表示条件依赖(conditional dependencies)。
此外,对于任意的随机变量,其联合概率可由各自的局部条件概率分布相乘而得出:
1. head-to-head
依上图,所以有:P(a,b,c) = P(a)*P(b)*P(c|a,b)成立,即在c未知的条件下,a、b被阻断(blocked),是独立的,称之为head-to-head条件独立。
2. tail-to-tail
考虑c未知,跟c已知这两种情况:
3. head-to-tail
还是分c未知跟c已知这两种情况:
c未知时,有:P(a,b,c)=P(a)*P(c|a)*P(b|c),但无法推出P(a,b) = P(a)P(b),即c未知时,a、b不独立。
c已知时,有:P(a,b|c)=P(a,b,c)/P(c),且根据P(a,c) = P(a)*P(c|a) = P(c)*P(a|c),可化简得到:
所以,在c给定的条件下,a,b被阻断(blocked),是独立的,称之为head-to-tail条件独立。
这个head-to-tail其实就是一个链式网络,如下图所示:
根据之前对head-to-tail的讲解,我们已经知道,在xi给定的条件下,xi+1的分布和x1,x2…xi-1条件独立。意味着啥呢?意味着:xi+1的分布状态只和xi有关,和其他变量条件独立。通俗点说,当前状态只跟上一状态有关,跟上上或上上之前的状态无关。这种顺次演变的随机过程,就叫做马尔科夫链(Markov chain)。对于马尔科夫链我们下一节再细讲。
wikipedia上是这样定义因子图的:将一个具有多变量的全局函数因子分解,得到几个局部函数的乘积,以此为基础得到的一个双向图叫做因子图(Factor Graph)。
通俗来讲,所谓因子图就是对函数进行因子分解得到的一种概率图。一般内含两种节点:变量节点和函数节点。我们知道,一个全局函数通过因式分解能够分解为多个局部函数的乘积,这些局部函数和对应的变量关系就体现在因子图上。
举个例子,现在有一个全局函数,其因式分解方程为:
其中fA,fB,fC,fD,fE为各函数,表示变量之间的关系,可以是条件概率也可以是其他关系。其对应的因子图为:
在概率图中,求某个变量的边缘分布是常见的问题。这问题有很多求解方法,其中之一就是把贝叶斯网络或马尔科夫随机场转换成因子图,然后用sum-product算法求解。换言之,基于因子图可以用sum-product 算法高效的求各个变量的边缘分布。
详细的sum-product算法过程,请查看博文:从贝叶斯方法谈到贝叶斯网络
朴素贝叶斯(Naive Bayesian)是经典的机器学习算法之一,也是为数不多的基于概率论的分类算法。朴素贝叶斯原理简单,也很容易实现,多用于文本分类,比如垃圾邮件过滤。**朴素贝叶斯可以看做是贝叶斯网络的特殊情况:即该网络中无边,各个节点都是独立的。 **
朴素贝叶斯朴素在哪里呢? —— 两个假设:
贝叶斯公式如下:
下面以一个例子来解释朴素贝叶斯,给定数据如下:
现在给我们的问题是,如果一对男女朋友,男生想女生求婚,男生的四个特点分别是不帅,性格不好,身高矮,不上进,请你判断一下女生是嫁还是不嫁?
这是一个典型的分类问题,转为数学问题就是比较p(嫁|(不帅、性格不好、身高矮、不上进))与p(不嫁|(不帅、性格不好、身高矮、不上进))的概率,谁的概率大,我就能给出嫁或者不嫁的答案!这里我们联系到朴素贝叶斯公式:
我们需要求p(嫁|(不帅、性格不好、身高矮、不上进),这是我们不知道的,但是通过朴素贝叶斯公式可以转化为好求的三个量,这三个变量都能通过统计的方法求得。
等等,为什么这个成立呢?学过概率论的同学可能有感觉了,这个等式成立的条件需要特征之间相互独立吧!对的!这也就是为什么朴素贝叶斯分类有朴素一词的来源,朴素贝叶斯算法是假设各个特征之间相互独立,那么这个等式就成立了!
但是为什么需要假设特征之间相互独立呢?
我们这么想,假如没有这个假设,那么我们对右边这些概率的估计其实是不可做的,这么说,我们这个例子有4个特征,其中帅包括{帅,不帅},性格包括{不好,好,爆好},身高包括{高,矮,中},上进包括{不上进,上进},那么四个特征的联合概率分布总共是4维空间,总个数为233*2=36个。
36个,计算机扫描统计还可以,但是现实生活中,往往有非常多的特征,每一个特征的取值也是非常之多,那么通过统计来估计后面概率的值,变得几乎不可做,这也是为什么需要假设特征之间独立的原因。
假如我们没有假设特征之间相互独立,那么我们统计的时候,就需要在整个特征空间中去找,比如统计p(不帅、性格不好、身高矮、不上进|嫁),我们就需要在嫁的条件下,去找四种特征全满足分别是不帅,性格不好,身高矮,不上进的人的个数,这样的话,由于数据的稀疏性,很容易统计到0的情况。 这样是不合适的。
根据上面俩个原因,朴素贝叶斯法对条件概率分布做了条件独立性的假设,由于这是一个较强的假设,朴素贝叶斯也由此得名!这一假设使得朴素贝叶斯法变得简单,但有时会牺牲一定的分类准确率。
朴素贝叶斯优点:
朴素贝叶斯缺点:
理论上,朴素贝叶斯模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为朴素贝叶斯模型假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。
朴素贝叶斯模型(Naive Bayesian Model)的**朴素(Naive)的含义是"很简单很天真"**地假设样本特征彼此独立. 这个假设现实中基本上不存在, 但特征相关性很小的实际情况还是很多的, 所以这个模型仍然能够工作得很好。
判别模型(discriminative model)通过求解条件概率分布P(y|x)或者直接计算y的值来预测y。
线性回归(Linear Regression),逻辑回归(Logistic Regression),支持向量机(SVM), 传统神经网络(Traditional Neural Networks),线性判别分析(Linear Discriminative Analysis),条件随机场(Conditional Random Field)
生成模型(generative model)通过对观测值和标注数据计算联合概率分布P(x,y)来达到判定估算y的目的。
朴素贝叶斯(Naive Bayes), 隐马尔科夫模型(HMM),贝叶斯网络(Bayesian Networks)和隐含狄利克雷分布(Latent Dirichlet Allocation)、混合高斯模型
新闻分类 GitHub:点击进入
作者:@mantchs
循环神经网络(Recurrent Neural Network, RNN)是一类以序列(sequence)数据为输入,在序列的演进方向进行递归(recursion)且所有节点(循环单元)按链式连接的递归神经网络(recursive neural network)
首先先上图,然后再解释:
现在我们考虑输⼊数据存在时间相关性的情况。假设 是序列中时间步t的小批量输⼊,
是该时间步的隐藏变量。那么根据以上结构图当前的隐藏变量的公式如下:
从以上公式我们可以看出,这⾥我们保存上⼀时间步的隐藏变量 ,并引⼊⼀个新的权重参数,该参数⽤来描述在当前时间步如何使⽤上⼀时间步的隐藏变量。具体来说,时间步 t 的隐藏变量的计算由当前时间步的输⼊和上⼀时间步的隐藏变量共同决定。
函数其实就是激活函数。
我们在这⾥添加了 ⼀项。由上式中相邻时间步的隐藏变量 之间的关系可知,这⾥的隐藏变量能够捕捉截⾄当前时间步的序列的历史信息,就像是神经⽹络当前时间步的状态或记忆⼀样。因此,该隐藏变量也称为隐藏状态。由于隐藏状态在当前时间步的定义使⽤了上⼀时间步的隐藏状态,上式的计算是循环的。使⽤循环计算的⽹络即循环神经⽹络(recurrent neural network)。
在时间步t,输出层的输出和多层感知机中的计算类似:
之前介绍的循环神经⽹络模型都是假设当前时间步是由前⾯的较早时间步的序列决定的,因此它 们都将信息通过隐藏状态从前往后传递。有时候,当前时间步也可能由后⾯时间步决定。例如, 当我们写下⼀个句⼦时,可能会根据句⼦后⾯的词来修改句⼦前⾯的⽤词。双向循环神经⽹络通过增加从后往前传递信息的隐藏层来更灵活地处理这类信息。下图演⽰了⼀个含单隐藏层的双向循环神经⽹络的架构。
在双向循环神经⽹络的架构中,设该时间步正向隐藏状态为 (正向隐藏单元个数为h),反向隐藏状态为
(反向隐藏单元个数为h)。我们可以分别
计算正向隐藏状态和反向隐藏状态:
然后我们连结两个⽅向的隐藏状态 来得到隐藏状态
,并将其输⼊到输出层。输出层计算输出
(输出个数为q):
双向循环神经⽹络在每个时间步的隐藏状态同时取决于该时间步之前和之后的⼦序列(包 括当前时间步的输⼊)。
在之前你已经见过对于前向传播(上图蓝色箭头所指方向)怎样在神经网络中从左到右地计算这些激活项,直到输出所有地预测结果。而对于反向传播,我想你已经猜到了,反向传播地计算方向(上图红色箭头所指方向)与前向传播基本上是相反的。
我们先定义一个元素损失函数:
整个序列的损失函数:
在这个计算图中,通过 可以计算对应的损失函数,于是计算出第一个时间步的损失函数,然后计算出第二个时间步的损失函数,然后是第三个时间步,一直到最后一个时间步,最后为了计算出总体损失函数,我们要把它们都加起来,通过等式计算出最后的𝐿,也就是把每个单独时间步的损失函数都加起来。然后你就可以通过导数相关的参数,用梯度下降法来更新参数。
在这个反向传播的过程中,最重要的信息传递或者说最重要的递归运算就是这个从右到左的运算,这也就是为什么这个算法有一个很别致的名字,叫做“通过(穿越)时间反向传播(backpropagation through time)”。取这个名字的原因是对于前向传播,你需要从左到右进行计算,在这个过程中,时刻𝑡不断增加。而对于反向传播,你需要从右到左进行计算,就像时间倒流。“通过时间反向传播”,就像穿越时光,这种说法听起来就像是你需要一台时光机来实现这个算法一样。
One to one:这个可能没有那么重要,这就是一个小型的标准的神经网络,输入𝑥然后得到输出𝑦。
One to many:音乐生成,你的目标是使用一个神经网络输出一些音符。对应于一段音乐,输入𝑥
可以是一个整数,表示你想要的音乐类型或者是你想要的音乐的第一个音符,并且如果你什么都不想输入,𝑥可以是空的输入,可设为 0 向量。
Many to one:句子分类问题,输入文档,输出文档的类型。
Many to many():命名实体识别。
Many to many():机器翻译。
类别 | 特点描述 |
---|---|
相同点 | 1、传统神经网络的扩展。 2、前向计算产生结果,反向计算模型更新。 3、每层神经网络横向可以多个神经元共存,纵向可以有多层神经网络连接。 |
不同点 | 1、CNN空间扩展,神经元与特征卷积;RNN时间扩展,神经元与多个时间输出计算 2、RNN可以用于描述时间上连续状态的输出,有记忆功能,CNN用于静态输出 |
由于RNN特有的memory会影响后期其他的RNN的特点,梯度时大时小,learning rate没法个性化的调整,导致RNN在train的过程中,Loss会震荡起伏,为了解决RNN的这个问题,在训练的时候,可以设置临界值,当梯度大于某个临界值,直接截断,用这个临界值作为梯度的大小,防止大幅震荡。
作者:@mantchs
卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(Feedforward Neural Networks),是深度学习(deep learning)的代表算法之一。
我们先来看卷积神经网络各个层级结构图:
上图中CNN要做的事情是:给定一张图片,是车还是马未知,是什么车也未知,现在需要模型判断这张图片里具体是一个什么东西,总之输出一个结果:如果是车 那是什么车。
这几个部分中,卷积计算层是CNN的核心。
在做输入的时候,需要把图片处理成同样大小的图片才能够进行处理。
常见的处理数据的方式有:
去均值(常用)
**TIPS:**在训练集和测试集上减去训练集的均值。
归一化
幅度归一化到同样的范围。
PCA/白化(很少用)
对图像(不同的数据窗口数据)和滤波矩阵(一组固定的权重:因为每个神经元的多个权重固定,所以又可以看做一个恒定的滤波器filter)做内积(逐个元素相乘再求和)的操作就是所谓的『卷积』操作,也是卷积神经网络的名字来源。
不同的滤波器filter会得到不同的输出数据,比如颜色深浅、轮廓。相当于提取图像的不同特征,模型就能够学习到多种特征。用不同的滤波器filter,提取想要的关于图像的特定信息:颜色深浅或轮廓。如下图所示。
在CNN中,滤波器filter(带着一组固定权重的神经元)对局部输入数据进行卷积计算。每计算完一个数据窗口内的局部数据后,数据窗口不断平移滑动,直到计算完所有数据。这个过程中,有这么几个参数:
参数共享机制
假设每个神经元连接数据窗的权重是固定对的。固定每个神经元连接权重,可以看做模板,每个神经元只关注**一个特性(模板)**,这使得需要估算的权重个数减少:一层中从1亿到3.5万。
一组固定的权重和不同窗口内数据做内积:卷积
作用在于捕捉某一种模式,具体表现为很大的值。
卷积操作的本质特性包括稀疏交互和参数共享。
把卷积层输出结果做非线性映射。
激活函数有:
TIPS:
也叫下采样层,就算通过了卷积层,纬度还是很高 ,需要进行池化层操作。
方式有:Max pooling、average pooling
Max pooling
取出每个部分的最大值作为输出,例如上图左上角的4个黄色方块取最大值为3作为输出,以此类推。
average pooling
每个部分进行计算得到平均值作为输出,例如上图左上角的4个黄色方块取得平均值2作为输出,以此类推。
全连接层的每一个结点都与上一层的所有结点相连,用来把前边提取到的特征综合起来。由于其全连接的特性,一般全连接层的参数也是最多的。
CNN层次结构 | 作用 |
---|---|
输入层 | 卷积网络的原始输入,可以是原始或预处理后的像素矩阵 |
卷积层 | 参数共享、局部连接,利用平移不变性从全局特征图提取局部特征 |
激活层 | 将卷积层的输出结果进行非线性映射 |
池化层 | 进一步筛选特征,可以有效减少后续网络层次所需的参数量 |
全连接层 | 用于把该层之前提取到的特征综合起来。 |
优点:
缺点:
与NLP/Speech共性:
都存在局部与整体的关系,由低层次的特征经过组合,组成高层次的特征,并且得到不同特征之间的空间相关性。
classification:C个类别识别
Localization定位)
Input:Image
Output:物体边界框(x,y,w,h)
Evaluation metric:交并准则(IOU) > 0.5 图中阴影部分所占面积
识别可以看作多分类问题(用softmax),用别人训练好的CNN模型做fine-tune
定位的目标是(x,y,w,h)是连续值,当回归问题解决(mse)
在1的CNN尾部展开(例如把最后一层拿开),接上一个(x,y,w,h)的神经网络,成为classification+regression的模型。
更细致的识别可以提前规定好有k个组成部分,做成k个部分的回归,
例如:框出两只眼睛和两条腿,4元祖*4=16(个连续值)
Regression部分用欧氏距离损失,使用SGD训练。
当图像有很多物体怎么办的?难度可是一下暴增啊。
那任务就变成了:多物体识别+定位多个物体,那把这个任务看做分类问题?
看成分类问题有何不妥?
边缘策略:想办法先找到可能包含内容的图框(候选框),然后进行分类问题的识别。
方法:根据RGB值做区域融合。fast-CNN,共享图窗,从而加速候选框的形成。
R-CNN的简要步骤如下:
SPP:Spatial Pyramid Pooling(空间金字塔池化),SPP-Net是出自2015年发表在IEEE上的论文。
众所周知,CNN一般都含有卷积部分和全连接部分,其中,卷积层不需要固定尺寸的图像,而全连接层是需要固定大小的输入。所以当全连接层面对各种尺寸的输入数据时,就需要对输入数据进行crop(crop就是从一个大图扣出网络输入大小的patch,比如227×227),或warp(把一个边界框bounding box(红框)的内容resize成227×227)等一系列操作以统一图片的尺寸大小,比如224224(ImageNet)、3232(LenNet)、96*96等。
所以才如你在上文中看到的,在R-CNN中,“因为取出的区域大小各自不同,所以需要将每个Region Proposal缩放(warp)成统一的227x227的大小并输入到CNN”。
但warp/crop这种预处理,导致的问题要么被拉伸变形、要么物体不全,限制了识别精确度。没太明白?说句人话就是,一张16:9比例的图片你硬是要Resize成1:1的图片,你说图片失真不?
SPP Net的作者Kaiming He等人逆向思考,既然由于全连接FC层的存在,普通的CNN需要通过固定输入图片的大小来使得全连接层的输入固定。那借鉴卷积层可以适应任何尺寸,为何不能在卷积层的最后加入某种结构,使得后面全连接层得到的输入变成固定的呢?
这个“化腐朽为神奇”的结构就是spatial pyramid pooling layer。
它的特点有两个:
结合空间金字塔方法实现CNNs的多尺度输入。
SPP Net的第一个贡献就是在最后一个卷积层后,接入了金字塔池化层,保证传到下一层全连接层的输入固定。
换句话说,在普通的CNN机构中,输入图像的尺寸往往是固定的(比如224*224像素),输出则是一个固定维数的向量。SPP Net在普通的CNN结构中加入了ROI池化层(ROI Pooling),使得网络的输入图像可以是任意尺寸的,输出则不变,同样是一个固定维数的向量。
简言之,CNN原本只能固定输入、固定输出,CNN加上SSP之后,便能任意输入、固定输出。神奇吧?
只对原图提取一次卷积特征
在R-CNN中,每个候选框先resize到统一大小,然后分别作为CNN的输入,这样是很低效的。
而SPP Net根据这个缺点做了优化:只对原图进行一次卷积计算,便得到整张图的卷积特征feature map,然后找到每个候选框在feature map上的映射patch,将此patch作为每个候选框的卷积特征输入到SPP layer和之后的层,完成特征提取工作。
如此这般,R-CNN要对每个区域计算卷积,而SPPNet只需要计算一次卷积,从而节省了大量的计算时间,比R-CNN有一百倍左右的提速。
SPP Net真是个好方法,R-CNN的进阶版Fast R-CNN就是在R-CNN的基础上采纳了SPP Net方法,对R-CNN作了改进,使得性能进一步提高。
R-CNN有一些相当大的缺点(把这些缺点都改掉了,就成了Fast R-CNN)。
大缺点:由于每一个候选框都要独自经过CNN,这使得花费的时间非常多。
解决:共享卷积层,现在不是每一个候选框都当做输入进入CNN了,而是输入一张完整的图片,在第五个卷积层再得到每个候选框的特征。
原来的方法:许多候选框(比如两千个)-->CNN-->得到每个候选框的特征-->分类+回归
现在的方法:一张完整图片-->CNN-->得到每张候选框的特征-->分类+回归
所以容易看见,Fast R-CNN相对于R-CNN的提速原因就在于:不过不像R-CNN把每个候选区域给深度网络提特征,而是整张图提一次特征,再把候选框映射到conv5上,而SPP只需要计算一次特征,剩下的只需要在conv5层上操作就可以了。
算法步骤:
Fast R-CNN存在的问题:存在瓶颈:选择性搜索,找出所有的候选框,这个也非常耗时。那我们能不能找出一个更加高效的方法来求出这些候选框呢?
解决:加入一个提取边缘的神经网络,也就说找到候选框的工作也交给神经网络来做了。
所以,rgbd在Fast R-CNN中引入Region Proposal Network(RPN)替代Selective Search,同时引入anchor box应对目标形状的变化问题(anchor就是位置和大小固定的box,可以理解成事先设置好的固定的proposal)。这就是Faster R-CNN。
算法步骤:
Faster R-CNN的方法目前是主流的目标检测方法,但是速度上并不能满足实时的要求。YOLO一类的方法慢慢显现出其重要性,这类方法使用了回归的思想,利用整张图作为网络的输入,直接在图像的多个位置上回归出这个位置的目标边框,以及目标所属的类别。
我们直接看上面YOLO的目标检测的流程图:
小结:YOLO将目标检测任务转换成一个回归问题,大大加快了检测的速度,使得YOLO可以每秒处理45张图像。而且由于每个网络预测目标窗口时使用的是全图信息,使得false positive比例大幅降低(充分的上下文信息)。
但是YOLO也存在问题:没有了Region Proposal机制,只使用7*7的网格回归会使得目标不能非常精准的定位,这也导致了YOLO的检测精度并不是很高。
SSD: Single Shot MultiBox Detector。上面分析了YOLO存在的问题,使用整图特征在7*7的粗糙网格内回归对目标的定位并不是很精准。那是不是可以结合region proposal的思想实现精准一些的定位?SSD结合YOLO的回归思想以及Faster R-CNN的anchor机制做到了这点。
上图是SSD的一个框架图,首先SSD获取目标位置和类别的方法跟YOLO一样,都是使用回归,但是YOLO预测某个位置使用的是全图的特征,SSD预测某个位置使用的是这个位置周围的特征(感觉更合理一些)。
那么如何建立某个位置和其特征的对应关系呢?可能你已经想到了,使用Faster R-CNN的anchor机制。如SSD的框架图所示,假如某一层特征图(图b)大小是88,那么就使用33的滑窗提取每个位置的特征,然后这个特征回归得到目标的坐标信息和类别信息(图c)。
不同于Faster R-CNN,这个anchor是在多个feature map上,这样可以利用多层的特征并且自然的达到多尺度(不同层的feature map 3*3滑窗感受野不同)。
小结:SSD结合了YOLO中的回归思想和Faster R-CNN中的anchor机制,使用全图各个位置的多尺度区域特征进行回归,既保持了YOLO速度快的特性,也保证了窗口预测的跟Faster R-CNN一样比较精准。SSD在VOC2007上mAP可以达到72.1%,速度在GPU上达到58帧每秒。
识别图上pixel的类别,用全卷积网络。
作者:@mantchs
机器学习模型在训练数据集和测试数据集上的表现。如果你改变过实验中的模型结构或者超参数,你也许发现了:当模型在训练数据集上更准确时,它在测试数据集上却不⼀定更准确。这是为什么呢?
因为存在着训练误差和泛化误差:
训练误差的期望小于或等于泛化误差。也就是说,⼀般情况下,由训练数据集学到的模型参数会使模型在训练数据集上的表现优于或等于在测试数据集上的表现。由于⽆法从训练误差估计泛化误差,⼀味地降低训练误差并不意味着泛化误差⼀定会降低。
机器学习模型应关注降低泛化误差。
在机器学习中,通常需要评估若⼲候选模型的表现并从中选择模型。这⼀过程称为模型选择(model selection)。可供选择的候选模型可以是有着不同超参数的同类模型。以多层感知机为例,我们可以选择隐藏层的个数,以及每个隐藏层中隐藏单元个数和激活函数。为了得到有效的模型,我们通常要在模型选择上下⼀番功夫。
从严格意义上讲,测试集只能在所有超参数和模型参数选定后使⽤⼀次。不可以使⽤测试数据选择模型,如调参。由于⽆法从训练误差估计泛化误差,因此也不应只依赖训练数据选择模型。鉴于此,我们可以预留⼀部分在训练数据集和测试数据集以外的数据来进⾏模型选择。这部分数据被称为验证数据集,简称验证集(validation set)。例如,我们可以从给定的训练集中随机选取⼀小部分作为验证集,而将剩余部分作为真正的训练集。
可以通过预留这样的验证集来进行模型选择,判断验证集在模型中的表现能力。
由于验证数据集不参与模型训练,当训练数据不够⽤时,预留⼤量的验证数据显得太奢侈。⼀种改善的⽅法是K折交叉验证(K-fold cross-validation)。在K折交叉验证中,我们把原始训练数据集分割成K个不重合的⼦数据集,然后我们做K次模型训练和验证。每⼀次,我们使⽤⼀个⼦数据集验证模型,并使⽤其他K − 1个⼦数据集来训练模型。在这K次训练和验证中,每次⽤来验证模型的⼦数据集都不同。最后,我们对这K次训练误差和验证误差分别求平均。
给定训练数据集,
应对⽋拟合和过拟合的⼀个办法是针对数据集选择合适复杂度的模型。
训练数据集⼤⼩
影响⽋拟合和过拟合的另⼀个重要因素是训练数据集的⼤小。⼀般来说,如果训练数据集中样本数过少,特别是⽐模型参数数量(按元素计)更少时,过拟合更容易发⽣。此外,泛化误差不会随训练数据集⾥样本数量增加而增⼤。因此,在计算资源允许的范围之内,我们通常希望训练数据集⼤⼀些,特别是在模型复杂度较⾼时,例如层数较多的深度学习模型。
正则化
应对过拟合问题的常⽤⽅法:权重衰减(weight decay),权重衰减等价于L2范数正则化(regularization)。正则化通过为模型损失函数添加惩罚项使学出的模型参数值较小,是应对过拟合的常⽤⼿段。
除了上面提到的权重衰减以外,深度学习模型常常使⽤丢弃法(dropout)来应对过拟合问题。丢弃法有⼀些不同的变体。本节中提到的丢弃法特指倒置丢弃法(inverted dropout)。
回忆⼀下,“多层感知机”描述了⼀个单隐藏层的多层感知机。其中输⼊个数为4,隐藏单元个数为5,且隐藏单元hi(i = 1, . . . , 5)的计算表达式为:
这⾥ϕ是激活函数,x1, . . . , x4是输⼊,隐藏单元i的权重参数为w1i, . . . , w4i,偏差参数为bi。当对该隐藏层使⽤丢弃法时,该层的隐藏单元将有⼀定概率被丢弃掉。设丢弃概率为p,那么有p的概率hi会被清零,有1 − p的概率hi会除以1 − p做拉伸。丢弃概率是丢弃法的超参数。具体来说,设随机变量ξi为0和1的概率分别为p和1 − p。使⽤丢弃法时我们计算新的隐藏单元 。
由于E(ξi) = 1 − p,因此:
即丢弃法不改变其输⼊的期望值。让我们对隐藏层使⽤丢弃法,⼀种可能的结果如下图所⽰,其中h2和h5被清零。这时输出值的计算不再依赖h2和h5,在反向传播时,与这两个隐藏单元相关的权重的梯度均为0。由于在训练中隐藏层神经元的丢弃是随机的,即h1, . . . , h5都有可能被清零,输出层的计算⽆法过度依赖h1, . . . , h5中的任⼀个,从而在训练模型时起到正则化的作⽤,并可以⽤来应对过拟合。在测试模型时,我们为了拿到更加确定性的结果,⼀般不使⽤丢弃法。
训练神经网络,尤其是深度神经所面临的一个问题就是梯度消失或梯度爆炸,也就是你训练神经网络的时候,导数或坡度有时会变得非常大,或者非常小,甚至于以指数方式变小,这加大了训练的难度。
本质上,梯度消失和爆炸是一种情况。在深层网络中,由于网络过深,如果初始得到的梯度过小,或者传播途中在某一层上过小,则在之后的层上得到的梯度会越来越小,即产生了梯度消失。梯度爆炸也是同样的。一般地,不合理的初始化以及激活函数,如sigmoid等,都会导致梯度过大或者过小,从而引起消失/爆炸。
解决方案
预训练加微调
其基本思想是每次训练一层隐节点,训练时将上一层隐节点的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,此过程就是逐层“预训练”(pre-training);在预训练完成后,再对整个网络进行“微调”(fine-tunning)。
此方法有一定的好处,但是目前应用的不是很多了。
梯度剪切、正则
梯度剪切这个方案主要是针对梯度爆炸提出的,其思想是设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。
另外一种解决梯度爆炸的手段是采用权重正则化(weithts regularization)比较常见的是L1和L2正则。
ReLu、leakReLu等激活函数
ReLu:其函数的导数在正数部分是恒等于1,这样在深层网络中,在激活函数部分就不存在导致梯度过大或者过小的问题,缓解了梯度消失或者爆炸。同时也方便计算。当然,其也存在存在一些缺点,例如过滤到了负数部分,导致部分信息的丢失,输出的数据分布不在以0为中心,改变了数据分布。
leakrelu:就是为了解决relu的0区间带来的影响,其数学表达为:leakrelu=max(k*x,0)其中k是leak系数,一般选择0.01或者0.02,或者通过学习而来。
Batch Normalization
Batch Normalization是深度学习发展以来提出的最重要的成果之一了,目前已经被广泛的应用到了各大网络中,具有加速网络收敛速度,提升训练稳定性的效果,Batch Normalization本质上是解决反向传播过程中的梯度问题。Batch Normalization,简称BN,即批规范化,通过规范化操作将输出信号x规范化到均值为0,方差为1保证网络的稳定性。
残差结构
残差的方式,能使得深层的网络梯度通过跳级连接路径直接返回到浅层部分,使得网络无论多深都能将梯度进行有效的回传。
LSTM
LSTM全称是长短期记忆网络(long-short term memory networks),是不那么容易发生梯度消失的,主要原因在于LSTM内部复杂的“门”(gates)。在计算时,将过程中的梯度进行了抵消。
你可以把训练集分割为小一点的子集训练,这些子集被取名为 mini-batch,假设每一个子集中只有 1000 个样本,那么把其中的𝑥 (1)到𝑥 (1000)取出来,将其称为第一个子训练集,也叫做 mini-batch,然后你再取出接下来的 1000 个样本,从𝑥 (1001)到𝑥 (2000),然后再取 1000个样本,以此类推。
在训练集上运行 mini-batch 梯度下降法,你运行 for t=1……5000,因为我们有5000个各有 1000 个样本的组,在 for 循环里你要做得基本就是对𝑋 {𝑡}和𝑌 {𝑡}执行一步梯度下降法。
其中1<n<m,m表示整个训练集大小。
优缺点:
首先,如果训练集较小,直接使用 batch 梯度下降法,这里的少是说小于 2000 个样本。一般的 mini-batch 大小为 64 到 512,考虑到电脑内存设置和使用的方式,如果 mini-batch 大小是 2 的𝑛次方,代码会运行地快一些。
在每次迭代中,梯度下降根据⾃变量当前位置,沿着当前位置的梯度更新⾃变量。然而,如果⾃变量的 迭代⽅向仅仅取决于⾃变量当前位置,这可能会带来⼀些问题。
让我们考虑⼀个输⼊和输出分别为⼆维向量x = [x1, x2]⊤和标量的⽬标函数 。,这⾥将
系数从1减小到了0.1。下⾯实现基于这个⽬标函数的梯度下降,并演⽰使⽤学习率为0.4时⾃变量的迭代轨迹。
可以看到,同⼀位置上,⽬标函数在竖直⽅向(x2轴⽅向)⽐在⽔平⽅向(x1轴⽅向)的斜率的绝对值更⼤。因此,给定学习率,梯度下降迭代⾃变量时会使⾃变量在竖直⽅向⽐在⽔平⽅向移动幅度更⼤。那么,我们需要⼀个较小的学习率从而避免⾃变量在竖直⽅向上越过⽬标函数最优解。然而,这会造成⾃变量在⽔平⽅向上朝最优解移动变慢。
动量法的提出是为了解决梯度下降的上述问题。由于小批量随机梯度下降⽐梯度下降更为⼴义,本章后续讨论将沿⽤“小批量随机梯度下降”⼀节中时间步t的小批量随机梯度gt的定义。设时间步t的⾃变量为xt,学习率为ηt。在时间步0,动量法创建速度变量v0,并将其元素初始化成0。在时间步t > 0,动量法对每次迭代的步骤做如下修改:
其中,动量超参数γ满⾜0 ≤ γ < 1。当γ = 0时,动量法等价于小批量随机梯度下降。在梯度下降时候使用动量法后的迭代轨迹:
可以看到使⽤较小的学习率η = 0.4和动量超参数γ = 0.5时,动量法在竖直⽅向上的移动更加平滑,且在⽔平⽅向上更快逼近最优解。
所以,在动量法中,⾃变量在各个⽅向上的移动幅度不仅取决当前梯度,还取决于过去的各个梯度在各个⽅向上是否⼀致。在本节之前⽰例的优化问题中,所有梯度在⽔平⽅向上为正(向右),而在竖直⽅向上时正(向上)时负(向下)。这样,我们就可以使⽤较⼤的学习率,从而使⾃变量向最优解更快移动。
优化算法中,⽬标函数⾃变量的每⼀个元素在相同时间步都使⽤同⼀个学习率来⾃我迭代。在“动量法”⾥我们看到当x1和x2的梯度值有较⼤差别时,需要选择⾜够小的学习率使得⾃变量在梯度值较⼤的维度上不发散。但这样会导致⾃变量在梯度值较小的维度上迭代过慢。动量法依赖指数加权移动平均使得⾃变量的更新⽅向更加⼀致,从而降低发散的可能。本节我们介绍AdaGrad算法,它根据⾃变量在每个维度的梯度值的⼤小来调整各个维度上的学习率,从而避免统⼀的学习率难以适应所有维度的问题。
AdaGrad算法会使⽤⼀个小批量随机梯度gt按元素平⽅的累加变量st。在时间步0,AdaGrad将s0中每个元素初始化为0。在时间步t,⾸先将小批量随机梯度gt按元素平⽅后累加到变量st:
其中⊙是按元素相乘。接着,我们将⽬标函数⾃变量中每个元素的学习率通过按元素运算重新调整⼀下:
其中η是学习率,ϵ是为了维持数值稳定性而添加的常数,如10的-6次方。这⾥开⽅、除法和乘法的运算都是按元素运算的。这些按元素运算使得⽬标函数⾃变量中每个元素都分别拥有⾃⼰的学习率。
需要强调的是,小批量随机梯度按元素平⽅的累加变量st出现在学习率的分⺟项中。因此,
然而,由于st⼀直在累加按元素平⽅的梯度,⾃变量中每个元素的学习率在迭代过程中⼀直在降低(或不变)。所以,当学习率在迭代早期降得较快且当前解依然不佳时,AdaGrad算法在迭代后期由于学习率过小,可能较难找到⼀个有⽤的解。
当学习率在迭代早期降得较快且当前解依然不佳时,AdaGrad算法在迭代后期由于学习率过小,可能较难找到⼀个有⽤的解。为了解决这⼀问题,RMSProp算法对AdaGrad算法做了⼀点小小的修改。
不同于AdaGrad算法⾥状态变量st是截⾄时间步t所有小批量随机梯度gt按元素平⽅和,RMSProp算法将这些梯度按元素平⽅做指数加权移动平均。具体来说,给定超参数0 ≤ γ < 1,RMSProp算法在时间步t > 0计算:
和AdaGrad算法⼀样,RMSProp算法将⽬标函数⾃变量中每个元素的学习率通过按元素运算重新调整,然后更新⾃变量:
其中η是学习率,ϵ是为了维持数值稳定性而添加的常数,如10的-6次方。因为RMSProp算法的状态变量st是对平⽅项gt ⊙ gt的指数加权移动平均,所以可以看作是最近1/(1 − γ)个时间步的小批量随机梯度平⽅项的加权平均。如此⼀来,⾃变量每个元素的学习率在迭代过程中就不再⼀直降低(或不变)。
除了RMSProp算法以外,另⼀个常⽤优化算法AdaDelta算法也针对AdaGrad算法在迭代后期可能较难找到有⽤解的问题做了改进。有意思的是,AdaDelta算法没有学习率这⼀超参数。
AdaDelta算法也像RMSProp算法⼀样,使⽤了小批量随机梯度gt按元素平⽅的指数加权移动平均变量st。在时间步0,它的所有元素被初始化为0。给定超参数0 ≤ ρ < 1(对应RMSProp算法中的γ),在时间步t > 0,同RMSProp算法⼀样计算:
与RMSProp算法不同的是,AdaDelta算法还维护⼀个额外的状态变量∆xt,其元素同样在时间步0时被初始化为0。我们使⽤∆xt−1来计算⾃变量的变化量:
最后,我们使⽤∆xt来记录⾃变量变化量 按元素平⽅的指数加权移动平均:
可以看到,如不考虑ϵ的影响,AdaDelta算法与RMSProp算法的不同之处在于使⽤ 来替代超参数η。
Adam算法在RMSProp算法基础上对小批量随机梯度也做了指数加权移动平均。
Adam算法使⽤了动量变量vt和RMSProp算法中小批量随机梯度按元素平⽅的指数加权移动平均变量st,并在时间步0将它们中每个元素初始化为0。给定超参数0 ≤ β1 < 1(算法作者建议设为0.9),时间步t的动量变量vt即小批量随机梯度gt的指数加权移动平均:
g_t)
和RMSProp算法中⼀样,给定超参数0 ≤ β2 < 1(算法作者建议设为0.999),将小批量随机梯度按元素平⽅后的项gt ⊙ gt做指数加权移动平均得到st:
由于我们将 v0 和 s0 中的元素都初始化为 0,在时间步 t 我们得到 sum_{i=1}^teta_1^{t-i}g_i)。将过去各时间步小批量随机梯度的权值相加,得到 sum_{i=1}^teta_1^{t-i}=1-eta_1^t)。需要注意的是,当 t 较小时,过去各时间步小批量随机梯度权值之和会较小。例如,当β1 = 0.9时,v1 = 0.1g1。为了消除这样的影响,对于任意时间步 t,我们可以将 vt 再除以 ,从而使过去各时间步小批量随机梯度权值之和为1。这也叫作偏差修正。在Adam算法中,我们对变量 vt 和 st 均作偏差修正:


接下来,Adam算法使⽤以上偏差修正后的变量vˆt和sˆt,将模型参数中每个元素的学习率通过按元素运算重新调整:
其中η是学习率,ϵ是为了维持数值稳定性而添加的常数,如10的-8次方。和AdaGrad算法、RMSProp算法以及AdaDelta算法⼀样,⽬标函数⾃变量中每个元素都分别拥有⾃⼰的学习率。最后,使⽤迭代⾃变量:
一个具有高维度空间的函数,如果梯度为 0,那么在每个方向,它可能是凸函数,也可能是凹函数。如果你在 2 万维空间中,那么想要得到局部最优,所有的 2 万个方向都需要是这样,但发生的机率也许很小,也许是2的-20000次方,你更有可能遇到有些方向的曲线会这样向上弯曲,另一些方向曲线向下弯,而不是所有的都向上弯曲,因此在高维度空间,你更可能碰到鞍点。
而不会碰到局部最优。至于为什么会把一个曲面叫做鞍点,你想象一下,就像是放在马背上的马鞍一样,如果这是马,这是马的头,这就是马的眼睛,画得不好请多包涵,然后你就是骑马的人,要坐在马鞍上,因此这里的这个点,导数为 0 的点,这个点叫做鞍点。我想那确实是你坐在马鞍上的那个点,而这里导数为 0。
鞍点中的平稳段是一个问题,这样使得学习十分缓慢,这也是像 Momentum 或是RMSprop,Adam 这样的算法,能够加速学习算法的地方。在这些情况下,更成熟的优化算法,如 Adam 算法,能够加快速度,让你尽早往下走出平稳段。
**数据角度 **
增强数据集。无论是有监督还是无监督学习,数据永远是最重要的驱动力。更多的类型数据对良好的模型能带来更好的稳定性和对未知数据的可预见性。对模型来说,“看到过的总比没看到的更具有判别的信心”。
模型角度
模型的容限能力决定着模型可优化的空间。在数据量充足的前提下,对同类型的模型,增大模型规模来提升容限无疑是最直接和有效的手段。
调参优化角度
如果你知道模型的性能为什么不再提高了,那已经向提升性能跨出了一大步。 超参数调整本身是一个比较大的问题。一般可以包含模型初始化的配置,优化算法的选取、学习率的策略以及如何配置正则和损失函数等等。
训练角度
在越大规模的数据集或者模型上,诚然一个好的优化算法总能加速收敛。但你在未探索到模型的上限之前,永远不知道训练多久算训练完成。所以在改善模型上充分训练永远是最必要的过程。充分训练的含义不仅仅只是增大训练轮数。有效的学习率衰减和正则同样是充分训练中非常必要的手段。
作者:@mantchs
在你阅读这篇文章时候,你都是基于自己已经拥有的对先前所见词的理解来推断当前词的真实含义。我们不会将所有的东西都全部丢弃,然后用空白的大脑进行思考。我们的思想拥有持久性。LSTM就是具备了这一特性。
这篇将介绍另⼀种常⽤的⻔控循环神经⽹络:⻓短期记忆(long short-term memory,LSTM)[1]。它⽐⻔控循环单元的结构稍微复杂⼀点,也是为了解决在RNN网络中梯度衰减的问题,是GRU的一种扩展。
可以先理解GRU的过程,在来理解LSTM会容易许多,链接地址:三步理解--门控循环单元(GRU)
LSTM 中引⼊了3个⻔,即输⼊⻔(input gate)、遗忘⻔(forget gate)和输出⻔(output gate),以及与隐藏状态形状相同的记忆细胞(某些⽂献把记忆细胞当成⼀种特殊的隐藏状态),从而记录额外的信息。
与⻔控循环单元中的重置⻔和更新⻔⼀样,⻓短期记忆的⻔的输⼊均为当前时间步输⼊Xt与上⼀时间步隐藏状态Ht−1,输出由激活函数为sigmoid函数的全连接层计算得到。如此⼀来,这3个⻔元素的值域均为[0, 1]。如下图所示:
具体来说,假设隐藏单元个数为 h,给定时间步 t 的小批量输⼊ (样本数为n,输⼊个数为d)和上⼀时间步隐藏状态
。三个门的公式如下:
输入门:
遗忘问:
输出门:
接下来,⻓短期记忆需要计算候选记忆细胞 。它的计算与上⾯介绍的3个⻔类似,但使⽤了值域在[−1, 1]的tanh函数作为激活函数,如下图所示:
具体来说,时间步t的候选记忆细胞计算如下:
)
我们可以通过元素值域在[0, 1]的输⼊⻔、遗忘⻔和输出⻔来控制隐藏状态中信息的流动,这⼀般也是通过使⽤按元素乘法(符号为⊙)来实现的。当前时间步记忆细胞的计算组合了上⼀时间步记忆细胞和当前时间步候选记忆细胞的信息,并通过遗忘⻔和输⼊⻔来控制信息的流动:

如下图所⽰,遗忘⻔控制上⼀时间步的记忆细胞Ct−1中的信息是否传递到当前时间步,而输⼊⻔则控制当前时间步的输⼊Xt通过候选记忆细胞C˜t如何流⼊当前时间步的记忆细胞。如果遗忘⻔⼀直近似1且输⼊⻔⼀直近似0,过去的记忆细胞将⼀直通过时间保存并传递⾄当前时间步。这个设计可以应对循环神经⽹络中的梯度衰减问题,并更好地捕捉时间序列中时间步距离较⼤的依赖关系。
有了记忆细胞以后,接下来我们还可以通过输出⻔来控制从记忆细胞到隐藏状态Ht的信 息的流动:
这⾥的tanh函数确保隐藏状态元素值在-1到1之间。需要注意的是,当输出⻔近似1时,记忆细胞信息将传递到隐藏状态供输出层使⽤;当输出⻔近似0时,记忆细胞信息只⾃⼰保留。下图展⽰了⻓短期记忆中隐藏状态的全部计算:
LSTM与GRU二者结构十分相似,不同在于:
关于激活函数的选取,在LSTM中,遗忘门、输入门和输出门使用Sigmoid函数作为激活函数;在生成候选记忆时,使用双曲正切函数Tanh作为激活函数。
值得注意的是,这两个激活函数都是饱和的,也就是说在输入达到一定值的情况下,输出就不会发生明显变化了。如果是用非饱和的激活函数,例如ReLU,那么将难以实现门控的效果。
Sigmoid函数的输出在0~1之间,符合门控的物理定义。且当输入较大或较小时,其输出会非常接近1或0,从而保证该门开或关。在生成候选记忆时,使用Tanh函数,是因为其输出在−1~1之间,这与大多数场景下特征分布是0中心的吻合。此外,Tanh函数在输入为0附近相比Sigmoid函数有更大的梯度,通常使模型收敛更快。
激活函数的选择也不是一成不变的,但要选择合理的激活函数。
作者:@mantchs
在循环神经⽹络中的梯度计算⽅法中,我们发现,当时间步数较⼤或者时间步较小时,循环神经⽹络的梯度较容易出现衰减或爆炸。虽然裁剪梯度可以应对梯度爆炸,但⽆法解决梯度衰减的问题。通常由于这个原因,循环神经⽹络在实际中较难捕捉时间序列中时间步距离较⼤的依赖关系。
门控循环神经⽹络(gated recurrent neural network)的提出,正是为了更好地捕捉时间序列中时间步距离较⼤的依赖关系。它通过可以学习的⻔来控制信息的流动。其中,门控循环单元(gatedrecurrent unit,GRU)是⼀种常⽤的门控循环神经⽹络。
GRU它引⼊了重置⻔(reset gate)和更新⻔(update gate)的概念,从而修改了循环神经⽹络中隐藏状态的计算⽅式。
门控循环单元中的重置⻔和更新⻔的输⼊均为当前时间步输⼊ 与上⼀时间步隐藏状态
,输出由激活函数为sigmoid函数的全连接层计算得到。 如下图所示:
具体来说,假设隐藏单元个数为 h,给定时间步 t 的小批量输⼊ (样本数为n,输⼊个数为d)和上⼀时间步隐藏状态
。重置⻔
和更新⻔
的计算如下:
sigmoid函数可以将元素的值变换到0和1之间。因此,重置⻔ 和更新⻔
中每个元素的值域都是[0*,* 1]。
接下来,⻔控循环单元将计算候选隐藏状态来辅助稍后的隐藏状态计算。我们将当前时间步重置⻔的输出与上⼀时间步隐藏状态做按元素乘法(符号为⊙)。如果重置⻔中元素值接近0,那么意味着重置对应隐藏状态元素为0,即丢弃上⼀时间步的隐藏状态。如果元素值接近1,那么表⽰保留上⼀时间步的隐藏状态。然后,将按元素乘法的结果与当前时间步的输⼊连结,再通过含激活函数tanh的全连接层计算出候选隐藏状态,其所有元素的值域为[-1,1]。
具体来说,时间步 t 的候选隐藏状态 的计算为:
W{hh}+b_h))
从上⾯这个公式可以看出,重置⻔控制了上⼀时间步的隐藏状态如何流⼊当前时间步的候选隐藏状态。而上⼀时间步的隐藏状态可能包含了时间序列截⾄上⼀时间步的全部历史信息。因此,重置⻔可以⽤来丢弃与预测⽆关的历史信息。
最后,时间步t的隐藏状态 的计算使⽤当前时间步的更新⻔
来对上⼀时间步的隐藏状态
和当前时间步的候选隐藏状态 做组合:
值得注意的是,更新⻔可以控制隐藏状态应该如何被包含当前时间步信息的候选隐藏状态所更新,如上图所⽰。假设更新⻔在时间步之间⼀直近似1。那么,在时间步
间的输⼊信息⼏乎没有流⼊时间步 t 的隐藏状态
实际上,这可以看作是较早时刻的隐藏状态
直通过时间保存并传递⾄当前时间步 t。这个设计可以应对循环神经⽹络中的梯度衰减问题,并更好地捕捉时间序列中时间步距离较⼤的依赖关系。
我们对⻔控循环单元的设计稍作总结:
作者:@mantchs
Format | export.py --include | Model |
---|---|---|
PyTorch | - | pt |
TorchScript | torchscript | *.torchscript |
ONNX | onnx | *.onnx |
OpenVINO | openvino | *.yolov5s_openvino_model |
TensorRT | engine | *.engine |
CoreML | coreml | *.mlmodel |
TensorFlow SavedModel | saved_model | * |
TensorFlow GraphDef | pb | *.pb |
TensorFlow Lite | tflite | *.tflite |
TensorFlow Edge TPU | edgetpu | *.tflite |
TensorFlow.js | tfjs | * |
常见的模型评价参数,以yolo为例子
关于Ground Truth:ground truth包括图像中物体的类别以及该图像中每个物体的真实边界框。
mAP含义及计算:如何量化呢? 采用IoU(Intersection over Union),IoU是预测框与ground truth的交集和并集的比值。这个量也被称为Jaccard指数,并于20世纪初由Paul Jaccard首次提出。
T或者N代表的是该样本是否被分类分对,P或者N代表的是该样本被分为什么
TP(True Positives)意思我们倒着来翻译就是“被分为正样本,并且分对了”,TN(True Negatives)意思是“被分为负样本,而且分对了”,FP(False Positives)意思是“被分为正样本,但是分错了”,FN(False Negatives)意思是“被分为负样本,但是分错了”。
按下图来解释,左半矩形是正样本,右半矩形是负样本。一个2分类器,在图上画了个圆,分类器认为圆内是正样本,圆外是负样本。那么左半圆分类器认为是正样本,同时它确实是正样本,那么就是“被分为正样本,并且分对了”即TP,左半矩形扣除左半圆的部分就是分类器认为它是负样本,但是它本身却是正样本,就是“被分为负样本,但是分错了”即FN。右半圆分类器认为它是正样本,但是本身却是负样本,那么就是“被分为正样本,但是分错了”即FP。右半矩形扣除右半圆的部分就是分类器认为它是负样本,同时它本身确实是负样本,那么就是“被分为负样本,而且分对了”即TN
有了上面TP TN FP FN的概念,这个Precision和Recall的概念一张图就能说明。
由前面定义,我们可以知道,要计算mAP必须先绘出各类别PR曲线,计算出AP。而如何采样PR曲线,VOC采用过两种不同方法。参见:The PASCAL Visual Object Classes Challenge 2012 (VOC2012) Development Kit
在VOC2010以前,只需要选取当Recall >= 0, 0.1, 0.2, ..., 1共11个点时的Precision最大值,然后AP就是这11个Precision的平均值。
在VOC2010及以后,需要针对每一个不同的Recall值(包括0和1),选取其大于等于这些Recall值时的Precision最大值,然后计算PR曲线下面积作为AP值。
因此,我们有 TP=5 (BB1, BB2, BB5, BB8, BB9), FP=5 (重复检测到的BB1也算FP)。除了表里检测到的5个GT以外,我们还有2个GT没被检测到,因此: FN = 2. 这时我们就可以按照Confidence的顺序给出各处的PR值,如下:
TensorFlow是目前深度学习的主流框架,其主要特性如下所述:
Keras是一个对小白用户非常友好且简单的深度学习框架。如果想快速入门深度学习, Keras将是不错的选择。
Keras是TensorFlow高级集成API,可以非常方便地和TensorFlow进行融合。
Keras在高层可以调用TensorFlow、CNTK、Theano,还有更多优秀的库也在被陆续支持中。
Keras的特点是能够快速搭建模型,是高效地进行科学研究的关键。Keras的基本特性如下:
Studio提供了R与Keras的API接口,RStudio的官网及GitHub上也提供了Keras扩展包的学习资料。
Caffe是由AI科学家贾扬清在加州大学伯克利分校读博期间主导开发的,是以C++/CUDA代码为主的早期深度学习框架之一,比TensorFlow、MXNet、PyTorch等都要早。
Caffe需要进行编译安装,支持命令行、Python和Matlab接口,单机多卡、多机多卡等都可以很方便使用。
Caffe的基本特性如下:
同时,Caffe的缺点也比较明显,主要包括如下几点。
PyTroch主要提供以下两种核心功能:支持GPU加速的张量计算;方便优化模型的自动微分机制。PyTorch的主要优点如下:
CNTK(Microsoft Cognitive Toolkit)是微软开源的深度学习工具包,它通过有向图将神经网络描述为一系列计算步骤。在有向图中,叶节点表示输入值或网络参数,其他节点表示其输入上的矩阵运算。
CNTK允许用户非常轻松地实现和组合流行的模型,包括前馈神经网络(DNN)、卷积神经网络(CNN)和循环神经网络(RNN、LSTM)。与目前大部分框架一样,CNTK实现了自动求导,利用随机梯度下降方法进行优化。
CNTK的基本特性如下。CNTK性能较好,按照其官方的说法,它比其他的开源框架性能都要好。适合做语音任务,CNTK本就是微软语音团队开源的,自然更适合做语音任务,便于在使用RNN等模型以及时空尺度时进行卷积。
MXNet框架允许混合符号和命令式编程,以最大限度地提高效率和生产力。MXNet的核心是一个动态依赖调度程序,可以动态地自动并行化符号和命令操作。
其图形优化层使符号执行更快,内存效率更高。
MXNet的基本特性如下:
通信工程专业毕业,7年开发经验
精通c/c++
精通golang
熟悉常见的脚本,js,lua,python,php
熟悉电路基础,嵌入式,单片机
服务端开发
嵌入式开发
>gin接口代码CURD生成工具
sql ddl to struct and markdown,将sql表自动化生成代码内对应的结构体和markdown表格格式,节省宝贵的时间。
qt .ui文件转css文件
duilib xml 自动生成绑定控件代码
协议调试器
基于lua虚拟机的的协议调试器软件 支持的协议有:
串口
tcp客户端/服务端
udp 组播/udp节点
tcp websocket 客户端/服务端
软件界面
使用例子: 通过脚本来获得接收到的数据并写入文件和展示在界面上
下载地址和源码
webrtc easy demo
webrtc c++ native 库 demo 实现功能:
基于QT
webrtc摄像头/桌面捕获功能
opengl渲染/多播放窗格管理
janus meeting room
下载地址和源码
wifi,蓝牙 - 无线开关
实现功能:
通过wifi/蓝牙实现远程开关电器或者其他电子设备
电路原理图:
实物图:
深度学习验证工具
虚拟示波器
硬件实物图:
实现原理
基本性能
采集频率: 取决于外部adc模块和ebaz4205矿板的以太网接口速率,最高可以达到100M/8 约为12.5MPS
上位机实现功能: 采集,显示波形,存储wave文件。
参数可运行时配置
上位机:
显示缓冲区大小可调
刷新率可调节
触发显示刷新可调节
又一个modbus调试工具
最近混迹物联网企业,发现目前缺少一个简易可用的modbus调试工具,本软件旨在为开发者提供一个简单modbus测试工具。
主打一个代码简单易修改。
特点:
1. 基于QT5
2. 基于libmodbus
3. 三方库完全跨平台,linux/windows。
开源plutosdr 板卡
1. 完全开源
2. 提高固件定制服务
3. 硬件售价450 手焊产量有线
测试数据
内部DDS回环测试
接收测试
外部发送500MHZ FM波形
matlab测试
2TRX版本
大部分plutosdr应用场景都是讲plutosdr板卡作为射频收发器来使用。
实际上plutosdr板卡本身运行linux 操作系统。是具有一定脱机运算的能力。
对于一些微型频谱检测,简单射频信号收发等应用完全可以将应用层直接实现在板卡上
相较于通过网卡或者USB口传输具有更稳定,带宽更高等优点。
本开源板卡由于了SD卡启动,较原版pluto支持了自定义启动应用的功能。
提供了应用层开发SDK(编译器,buildroot文件系统)。
通过usb连接电脑,经过RNDIS驱动可以近似为通过网卡连接
(支持固件的开发定制)。
二次开发例子
```
all:
arm-linux-gnueabihf-gcc -mfloat-abi=hard --sysroot=/root/v0.32_2trx/buildroot/output/staging -std=gnu99 -g -o pluto_stream ad9361-iiostream.c -lpthread -liio -lm -Wall -Wextra -lrt
clean:
rm pluto_stream
版面分析即分析出图片内的具体文件元素,如文档标题,文档内容,文档页码等,本工具基于cnstd模型