一、计算机视觉历史回顾与介绍
- 边缘定义了形状,大脑对视觉信息的的处理是基于边缘与形状的。
- 视觉处理从一些简单的形状开始,而不是一个整体;视觉是分层的。
- Convolutional Neural Network (CNN) has become an important tool for object recognition
- Convolutional Neural Network (CNN) is not invented overnight
- The quest for visual intelligence goes far beyond object recognition…
- 图像分类关注图的整体是什么,物体检测表示图像中某个物体在什么地方
- 计算机视觉应用于人体动作捕捉,医疗卫生,无人驾驶,人脸识别,机器人导航,机器人抓取等方面,深海探测。
二、数据驱动的图像分类
- 挑战:照射角度、光照强度、物体形变、部分遮挡、背景混入、同类演变,需要算法具有一定的鲁棒性。
- 图像分类的尝试算法:由物体的部分到整体。
- 近邻算法
例如有500图像,10个类别的训练集,100张图像作为测试集。图像的大小是32*32,通道数目为3。
训练:
将所有的图像拉直(32*32*3=3072),则训练集形成了一个500×3072的矩阵。训练集的标签为500*1的矩阵。
测试:
测试集的每一个图片遍历,图片此时是1*3072大小,将其与训练集形成500*3072矩阵的每一行进行减法求绝对值然后相加的运算(距离度量方法L1范数),在500个计算结果中选择最小的行号作为结果。该结果作为训练集标签矩阵的索引值就可以得到测试结果的类别。
因此,很明显,这种分类算法的速度取决于训练数据的大小。 - k近邻算法
近邻算法通过选择最小的距离度量(例如,L2范数)作为分类结果,但是这种距离度量方式仅仅取决于不同图像对应位置像素值的相似性,具有很大的错误可能。一种改进的方式称为K近邻,选择度量方式中比较小的k个结果,然后通过投票的方式从K个结果中选择出最终的类别判定,对于回归任务,则对k个结果取平均或者其他操作。可以对近邻算法做出一些优化。这就是k近邻算法。
Attention!
不能使用测试集调试参数,否则会导致算法的泛化性能差,过拟合。
可以选择使用交叉验证的方式选择最佳的K值。 - 存在的问题
从效果上看:
基于像素比较的相似和感官上以及语义上的相似是不同的。
这种方式图像的相似度更多的是以背景为主导而不是图片语义本身。
从实际应用中看:
需要将训练集数据(一般都会很大)被保存在内存空间中,占用了太多的资源。
一般情况下,我们认为系统的训练时间长一些,当实际使用的时候,时间短一些,不会影响系统的运行,但对于KNN来说,训练时间就是把图像读入存储,时间很短,测试的时候却需要把每一副测试图像和每一个训练集数据进行对比,时间很长。
Read more: https://zhuanlan.zhihu.com/p/20894041?refer=intelligentunit
三、线性分类器、损失函数、优化问题、反向传播
- 假设有10个类别的图像,现在要测试一副图像或者其他经过一个函数或者多个函数后哪个类别的得分值最高。这个函数叫分类器,也叫得分函数。
线性分类器
模型:f(W,x)=Wx+b(W权重矩阵:n个类别×每个类别的参数,x输入矩阵,b偏置)
xi是图片拉伸后的结果,W的每一行代表一种类别的参数。
使用过程中,为了方便处理,常常把b添加到w当中,把x增加一个大小为1的维度。
一种思考:线性分类器只是在模仿K近邻,不同的是它仅仅是使用的是一种学习到的模板。Read more: https://zhuanlan.zhihu.com/p/20918580?refer=intelligentunit
损失函数
在得到每一个类别的得分值以后,如何判断该分类器是否达到了理想的效果呢?
我们使用损失函数、损失值来表示,损失函数更重要的作用是为了后面的用于调整参数W,需要说明的是损失值越大,得到的结果与真实结果相差越大(通过输入图像的标签来判断),这里使用两类损失函数一类是多类别SVM损失(Multiclass SVM loss),一类是交叉熵损失。- 多类别SVM损失
Li表示后面内容的累加和:是错误类别的得分值(Sj)减去正确类别的得分值(Syi)加上一个安全系数(这里为1),然后选择其结果与0中的较大值。
理解一下:
1、先不考虑安全系数,如果错误类别的得分值都小于正确类别,公式的结果为0,说明分对了。反之,得分值大于0,说明分错了。
2、如果错误类别的得分值远远大于正确类别的得分值,则结果也将变得很大。表示分类效果不好
3、增加了安全系数表明,即使分对了,但是错误类别的得分值只是比正确类别的得分值低一点(小于安全系数)。我们也认为这次分类是不准确的,因为它没有将错误类别与正确类别很好的留出一定的安全距离。
4、上述这个损失方式也叫hinge loss。可以通过加平方项扩大损失值。
这种损失值的计算方式关注了每次进行分类的得分值,但是像素的权重对于得分值的大小没有影响,考虑下面一种情况是:
参数w1和w2相比,虽然得到的结果相同,但是w2使用了所有的像素值,而w1的有效数据其实只有一个,而使用更少的原始数据可能意味着过拟合。
通过引入正则化惩罚项可以使得w1和w2的损失值不一样,使得w值(像素的权重值)尽可能的分散.
这里引入一种L2惩罚项:
损失函数的最终版本是:
Read more:https://zhuanlan.zhihu.com/p/20945670?refer=intelligentunit
5.交叉熵损失(cross-entry loss)(也叫softmax分类器)
交叉熵损失的公式:
根据公式的一个例子:
1、第一步是将得分值取e为底的指数函数,这样做可以增大得分值之间的差距。
2、归一化此时将得分值转变成为了概率分布,表示经过测试后的数据为其他每一个类别的概率。
3、最后使用log函数进行求损失值,-log自变量的取值范围在0到1之间,函数值的取值范围在0到+无穷大之间,则归一化正确分类的数值越小,损失值也就越大。
4、在svm的损失函数中,假设一种情况是如果所有的类别都分对了,并且类别的得分值差距大于安全距离,则损失值为0。现在错误类别的得分值改变了(仍然满足上述条件),但是损失值依然为0,不管错误类别的得分值是多么接近正确类别或者是远离正确类别,损失值都不改变,这种情况是不好的。而使用交叉熵损失则可以改变这种情况。
read more:https://zhuanlan.zhihu.com/p/21102293?refer=intelligentunit
5、优化问题
优化问题是什么样的W可以使得系统的损失值最小。
1、随机搜索策略:在程序中使用产生随机数的程序,随机产生所需要的参数W,每次生成参数后计算损失值并与前一次的损失值比较,如果优于前一次,则保留,否则就舍弃,这就是随机搜索策略。
2、本地随机搜索策略:这个方式与随机搜索策略大致相同,不同的是每一次随机生成一组W后,需要乘上一个学习率,然后将这个结果加到上一次的W中,然后比较损失值是否减小,不减小的话就丢弃掉,否则更新新的W。Wnew=Wold+step×Wrandom。这里相当于在寻找下降的梯度。
3、跟随策略:实际上下降的梯度并不需要寻找,可以通过计算得到,这个就是下降的梯度,代替2中每次生成的新的W值。
read more:https://zhuanlan.zhihu.com/p/21360434?refer=intelligentunit
4、梯度下降的计算方式
* 有限差值计算梯度:这里就是使用3中的梯度计算方法,给w增加一个h,然后计算损失值f(x+h)。这样最终得到了梯度的方向,用df表示。
使用:Wnew=Wold-step×df,step表示步长,也叫学习率learning rate(步长过大?步长过小?)。更新参数W。这里为什么使用的是减号?
当计算梯度大于0的时候,这个时候表示上山,函数递增,我们想往损失值更小的地方去,就需要反方向行走,因此需要加个负号。
* 微分计算梯度,偏微分就是梯度,因此可以通过偏微分的方式计算梯度,在线性回归中,就是直接通过偏微分直接计算梯度的。
5、梯度下降是对神经网络的损失函数最优化中最常用的方法。
保留一些疑问:多个训练图像如何的梯度是如何确定的?随机梯度下降的方式?
Read more:https://zhuanlan.zhihu.com/p/21387326?refer=intelligentunit
6、该部分的流程
四、反向传播
反向传播是使用链式求导法则从最终输出端往回分段求导,最终得到输入对输出的梯度的过程。这里所说的梯度就是倒数。其实反向传播就是求导过程,我们知道:对于复杂函数的求导过程可以使用链式求导法则去求。
得到的梯度反应了输入对于输出的影响,相当于某一个输入的参数每增加“一份”,输出结果增加“梯度份”的过程。
反向传播中有加法门操作,乘法门操作,其实就是加法和乘法。还有一种是MAX门操作,这种操作是取输入中较大的梯度为1,较小的梯度为0。
Read more:https://zhuanlan.zhihu.com/p/21407711?refer=intelligentunit
五、神经网络基础
神经网络系统理解:数学上,神经网络中的每一个神经元就是一个线性单元(f=Wx+b)加上一个激活函数,这个激活函数是一个非线性系统。线性系统在高维空间中线性划分区间,而神经网络由于引入了非线性环节,因此可以使用曲线划分空间。除此之外,神经网络多层神经元的引入增加了拟合函数的复杂度,因此,应该具有更好的拟合效果。如果从生物神经系统上进行解释,神经元通过自己的许多树突获取信号(线性单元),如果信号达到一定强度,则神经元兴奋或者抑制(激活函数),通过轴突向下一个神经元传递信号(单个神经元连接到下一个神经元)。
1、下图是用数学方法表示,max(0,-)是一种激活函数
2、神经网络的架构,隐层中每一个圆圈都是一个神经元。
3、每一个神经元的构造模型
4、单个神经元模型
+ 使用sigmoid函数作为激活函数,单个神经元就是一个逻辑回归,实现二分类问题。
+ 使用多类别SVM损失,其正则化项使用折叶损失,则单个神经元就是一个二分类的SVM。正则化项是需要优化的函数。
5、几种类型的激活函数
sigmoid激活函数:以前的神经网络算法经常使用,但是有三个缺点:
(1)由于在接近0和1的地方,梯度为0,在进行反向传播的过程中,根据链式法则,其他较大的梯度与激活函数处的梯度相乘,得到的梯度也会很小,会导致梯度消失现象,而使得该部分的参数无法进行优化。为了防止饱和,对初始参数的设定尤为注意,其实这也是神经网络中所需要注意的。
(2) sigmoid函数不是零中心输出的(不是很理解课程中所说的权重的Z字型下降是什么意思),零中心输出会使得收敛速度更快。
(3)exp运算需要更大的计算量,但是最大的计算量在于卷积和点乘,而不是在这里。Tanh函数,零中心对称,数据拉伸到(-1,1)之间,但是和sigmoid一样具有(1)(3)中的缺点。
- Relu函数(Rectified Linear Unit),f(x)=max(0,-)。优点如下:
(1)在大于0的地方一直增长,具有非饱和性,不会出现梯度消失现象
(2)简单的比较大小,计算效率高了很多
(3)在实践中显示收敛速度更快,这个与计算效率不是一个概念。
缺点:
(1)也不是关于中心对称的
(2)非激活的输入值(小于0)无法进行反向传播,因此,权值也不会跟新。
(3)有时候Relu函数不会被激活,包括初始化参数不合适,以及学习率过高(question) - Leaky Relu函数
f(x)=max(0.01x,x);
该函数的出现是为了解决Relu函数的输入值小于0而不被激活的问题,尽管有研究表明,这个函数确实比Relu函数效果好一些,但是它可能不总是这样的。实际上0.01是一个参数(alpha),可以对每一个神经元进行设置。 - ELU(exponential linear units)
几种Relu相关函数的曲线图
Elu继承了Relu的优点,更加接近0均值输出(不知道是否有更好的效果),但是计算需要exp。 - Maxout函数
是对Relu函数和Leaky Relu的一般性归纳,其表达形式是Max(W1*X+B1,W2*X+B2),这里有之前的f=WX+B的神经元组成形式不同,它需要有两组参数。当W1X+B1=0的时候,它就是RElu函数。
6、激活函数总结
- 虽然有很多中激活函数,但是最为常用的还是Relu函数
- RElu函数注意学习率的设计
- 可以Leaky ReLU / Maxout / ELU函数
- 尝试tanh函数,但是不要期望太高
- 不要使用sigmoid函数
read more:https://zhuanlan.zhihu.com/p/21462488?refer=intelligentunit
六、神经网络的组织结构
写的真的很好
> read more:https://zhuanlan.zhihu.com/p/21513367?refer=intelligentunit
七、神经网络的使用步骤
1、数据预处理
不同数据的散乱分布会影响最终的分析结果,因此,需要对其进行零归一化处理;除此之外,由于不同的评价指标具有不同的量纲和单位,会导致在训练过程中,数据较大的特征对结果影响更大,为了消除这种影响,最好进行数据归一化。
零中心化(Zero-centered或者Mean-subtraction)和归一化(标准化Standardization或Normalization),零中心化是将数据变成均值为0的数据,在图像上相当于平移,在操作上,是将所有的数据减去均值。归一化将数据变成均值为0,标准差为1的数据。在操作上X*=(X-均值)/标准差。在图像处理过程中,更多的使用第一种方式,因为像素之间不存在量纲不同的问题。
在实际使用过程中,也会看到PCA和Whitening of the data的处理方式。
2、权重初始化
不能使用零初始化?
:全0初始化会使得每一个神经元的输出相同,在反向传播过程中,所有的梯度都相同,最终每一个神经元的参数也相同。
一般通过产生一个较小的随机数去初始化参数?
:使用W = 0.01 * np.random.randn(D,H)产生一个零均值和标准差的高斯分布。
对于层数很少的情况,上面这种方法有效,然而初始权重较小意味着反向传播梯度较小,当层数很多的时候,根据链式法则,会得到一个较小的梯度。除此之外,当数据量较大的时候,还会导致初始神经元的输出数据的方差变大。
使用1/sqrt(n)校准方差
:w = np.random.randn(n) / sqrt(n)可以保证所有神经元的起始时有近似同样的输出分布。实验表明,可以提高收敛速度。
当使用Relu作为激活函数的时候,推荐使用:w = np.random.randn(n) * sqrt(2.0/n)进行初始化。
3、正则化方法
L1正则化
L2正则化
最大范式约束
随机失活
Read More:https://zhuanlan.zhihu.com/p/21560667?refer=intelligentunit
Read More:https://zhuanlan.zhihu.com/p/21741716?refer=intelligentunit
Read More:https://zhuanlan.zhihu.com/p/21798784?refer=intelligentunit