全球名校课程作业分享系列(6)--斯坦福计算机视觉与深度学习CS231n之神经网络细解与优化尝试

课程作业原地址:CS231n Assignment 1
作业及整理:编写:@土豆 && @郭承坤 && @寒小阳
时间:2018年2月。
出处:http://blog.csdn.net/han_xiaoyang/article/details/79278882

  • To-Do:

  • [x] 统一所有的数学符号和代码符号

  • [x] 统一所有的术语名称

  • [x] 术语的英文词汇对应

  • [x] 线性模型的名字是?perceptron?

  • [x] 损失函数的计算公式和符号是否严格和合适?

  • [x] denominator layout?

  • [ ] BN梯度的证明
  • [x] ​ bn_param[‘running_mean’] = running_mean
    ​ bn_param[‘running_var’] = running_var

(我是盗图大仙,所有图片资源全部来源于网络,若侵权望告知~)

本文是什么?

本文以CS231n的Assignment2中的Q1-Q3部分代码作为例子,目标是由浅入深得搞清楚神经网络,同时以图片分类识别任务作为我们一步一步构建神经网路的目标。

本文既适合仅看得懂一点Python代码、懂得矩阵的基本运算、听说过神经网络算法这个词的朋友,也适合准备学习和正在完成CS231n课程作业的朋友。

本文内容涉及:很细节的Python代码解析 + 神经网络中矩阵运算的图像化解释 + 模块化Python代码的流程图解析

本文是从Python编程代码的实现角度理解,一层一层拨开神经网络的面纱,以搞清楚数据在其中究竟是怎么运动和处理的。希望可以为小白,尤其是为正在学习CS231n课程的朋友,提供一个既浅显又快捷的观点,用最直接的方式弄清楚并构建一个神经网络出来。所以,此文不适合章节跳跃式阅读。

本文不是什么?

不涉及艰深的算法原理,忽略绝大多数数学细节,也尽量不扯任何生涩的专业术语,也不会对算法和优化处理技术做任何横向对比。

CS231n课程讲师Andrej Karpathy在他的博客上写过一篇文章Hacker’s guide to Neural Networks,其中的精神是我最欣赏的一种教程写作方式:“My exposition will center around code and physical intuitions instead of mathematical derivations. Basically, I will strive to present the algorithms in a way that I wish I had come across when I was starting out.”

“…everything became much clearer when I started writing code.”

废话不多说,找个板凳坐好,慢慢听故事~

待折腾的数据集

俗话说得好:皮裤套棉裤,里边有缘故;不是棉裤薄,就是皮裤没有毛!

我们的神经网络是要用来解决某特定问题的,不是家里闲置的花瓶摆设,模型的构建都有着它的动机。所以,首先让我们简单了解下要摆弄的数据集(CIFAR-10),最终的目标是要完成一个图片样本数据源的分类问题。

图像分类数据集:CIFAR-10。
这是一个非常流行的图像分类数据集是CIFAR-10。这个数据集包含了60000张 32×32 32 × 32 的小图像,单个像素的数值范围都在0-255之间。每张图像都对应于是10种分类标签(label)中的一种。此外,这60000张图像被分为包含带有标签的50000张图像的训练集和包含不带有标签的10000张图像的测试集。


img

上图是图片样本数据源CIFAR-10中训练集的一部分样本图像,从中你可以预览10个标签类别下的10张随机图片。


小结:

在我们的故事中,只需要记得这个训练集是一堆 32×32 32 × 32 的RGB彩色图像作为训练目标,一个样本图像共有 32×32×3 32 × 32 × 3 个数据,每个数据的取值范围0~255,一般用x来标记。每个图还配有一个标签值,总共10个标签,以后我们都用y来标记。(悄悄告诉你的是:每个像素点的3个数据维度是有序的,分别对应红绿蓝(RGB))

关于神经网络,你起码应该知道的!

下图是将神经网络算法以神经元的形式绘制的两个图例,想必同志们早已见怪不怪了。

但是,你起码应该知道的是其中各种约定和定义:


img

左边是一个2层神经网络,一个隐藏层(蓝色层)有4个神经元(也可称为单元(unit))组成,输出层(绿色)由2个神经元组成,输入层(红色)是3个”神经元”。右边是一个3层神经网络,两个隐藏层,每层分别含4个神经元。注意:层与层之间的神经元是全连接的,但是层内的神经元不连接(如此就是所谓全连接层神经网络)。

这里有个小坑:输入层的每个圈圈代表的可不是每一张图片,其实也不是神经元。应该说整个纵向排列的输入层包含了一张样本图片的所有信息,也就是说,每个圈圈代表的是某样本图片对应位置的像素数值。可见对于CIFAR-10数据集来说,输入层的维数就是 32×32×3 32 × 32 × 3 ,共3072个圈圈呢!至于输出层的神经元数也是依赖数据集的,就CIFAR-10数据集来说,输出层维数必然是10,即对应数据集的10个标签。至于中间的隐藏层可以有多少层,以及每层的神经元个数就都可以任意啦!你说牛不牛?!


在接下来我们的故事中,要从代码实现的角度慢慢剖析,先从一个神经元的角度出发,再搞清楚一层神经元们是如何干活的,然后逐渐的弄清楚一个含有任意神经元个数隐藏层的神经网络究竟是怎么玩的,在故事的最后将会以CIFAR-10数据集的分类问题为目标一试身手,看看我们构造的神经网络究竟是如何工作运转的。

所谓的前向传播

一个神经元的本事

我们先仅前向传播而言,来谈谈一个神经元究竟是做了什么事情。

前向传播,这名字起的也是神乎其神的,说白了就是将样本图片的数据信息,沿着箭头正向传给一个带参数的神经网络层中咀嚼一番,然后再吐出来一堆数据再喂给后面的一层吃(如此而已,居然就叫做了前向/正向传播了,让人忍不住吐槽一番)。那么,对于一个全连接层(fully-connected layer) 1

的前向传播来说,所谓的“带参数的神经网络层”一般就是指对输入数据源(此后用”数据源”这个词来表示输入层所有输入样本图片数据总体)先进行一个矩阵乘法,然后加上偏置,得到数字再运用激活函数”修饰”,最后再反复迭代罢了(后文都默认使用此线性模型)。

是不是晕了?别着急,我们进一步嚼碎了来看看一个神经元(处于第一隐藏层)究竟是如何处理输入层传来的一张样本图片(带有猫咪标签)的?

上面提到过,输入数据源是一张尺寸为 32×32 32 × 32 的RGB彩色图像,我们假定输入数据 xi x i 的个数是 D D 的话(即 i 是有 D D 个),那这个 D = 32 × 32 × 3 = 3072 。为了普遍意义,下文继续用大写字母 D D 来表示一张图片作为数据源的维数个数(如果该神经元位于隐藏层,则大写字母 D 表示本隐藏层神经元的神经元个数,下一节还会提到)。

显然,一张图片中的 D D 个数据 x i 包含了判断该图片是一支猫的所有特征信息,那么我们就需要”充分利用”这些信息来给这张样本图片”打个分”,来评价一下这张图像究竟有多像猫。

不能空口套白狼,一张美图说明问题:


左图不用看,这个一般是用来装X用的,并不是真的要严格类比。虽然最初的神经网络算法确实是受生物神经系统的启发,但是现在早已与之分道扬镳,成为一个工程问题。关键我们是要看右图的数学模型(严格地说,这就是传说中的感知器perceptron)。


如右图中的数学模型所示,我们为每一个喂进来的数据 xi x i 都对应的”许配”一个”权重”参数 wi w i ,再加上一个偏置 b b ,然后一股脑的把他们都加起来得到一个数(scalar):

i w i x i + b = w 0 x 0 + w 1 x 1 + + w D 1 x D 1 + b

上面的代数表达式看上去很繁杂,不容易推广,所以我们把它改写成

[iwixi+b]1×1=[xi]1×DwiD×1+[b]1×1 [ ∑ i w i x i + b ] ⏟ 1 × 1 = [ ⋯ x i ⋯ ] ⏟ 1 × D ⋅ [ ⋮ w i ⋮ ] ⏟ D × 1 + [ b ] ⏟ 1 × 1

上面等式左侧这样算出的一个数字,表示为对于输入进来的 D D 个数据 x i ,在当前选定的参数 (wi,b) ( w i , b ) 下,这个神经元能够正确评价其所对应的”猫咪”标签的程度。所以,这个得分越高,越能说明其对应的在某种 (wi,b) ( w i , b ) D+1 D + 1 个参数的评价下,该神经元正确判断的能力越好,准确率越高。

换句话说,相当于是有一个神经元坐在某选秀的评委席里,戴着一款度数为 (wi,b) ( w i , b ) 雷朋眼镜,给某一位台上模仿猫咪的样本图片 xi x i 打了一个分(评价分数)。显然,得分的高低是不仅依赖于台上的主角 xi x i 的表现,还严重依赖于神经元评委戴着的有色眼镜(参数 wi,b w i , b )。当然,我们已经假定评委的智商(线性模型)是合乎统一要求的。

现如今,参加选秀的人可谓趋之若鹜,一个神经元评委该如何同时的批量化打分,提高效率嗯?

也就是说,一个神经元面对 N N 张图片该如何给每一张图片打分的问题。这就是矩阵表达式的优势了,我们只需要很自然地把上述矩阵表达式纵向延展下即可,如下所示:

[ i w i x i + b ] N × 1 = [ x i ] N × D [ w i ] D × 1 + [ b ] N × 1

上面矩阵表达式中,等号左侧的得分矩阵中每一行运算都是独立并行的,并且其每一行分别代表 N N 张样本图片的数据经过一个神经元后的得分数值。到此,我们就明白了一个神经元是如何面对一个shape为(N, D)的输入样本图片数据矩阵,并给出得分的。

然而,关于一个神经元的故事还没完。

你可能注意到了,上面例子中的美图中有个函数f,我们把图放大仔细看清楚:

在神经元对每张图片算得的“得分”送给下一个神经元之前都要经过一个函数f的考验。这就暗示我们,选秀节目的导演对神经元评委给出的得分还并不满意,为了(未来模型训练的)快捷方便,导演要求对每一个得分需要做进一步的“激活”处理(即上图中的函数 f ),于是这个叫激活函数(activation)的家伙会对结果做进一步的处理、比如大家这些年都在用的ReLU就是临门一脚,要求把得分小于零的都阉割掉,一律给0分(都得负分的了还选什么秀啊?给0分滚蛋):

f(x)=max(0,x) f ( x ) = max ( 0 , x )

所以,总结下来,一个神经元干的活就是如下所示的公式:

out=f(iwixi+b)=max(0,iwixi+b) out = f ( ∑ i w i x i + b ) = max ( 0 , ∑ i w i x i + b )

如果这个数学看得让人心烦意乱,不要怕,一层神经元的故事之后就是万众期待的Python代码实现了,相信看后会让你不禁感慨:“小样!不过如此嘛~”

小备注:

这里最后再多一句嘴:一个神经元在前向传播中输出的只是一个数字,另外,神经网络的训练过程,训练的是上述提到的模型参数 (wi,b) ( w i , b )

再多一句嘴,通常我们在整个神经网络结构中只使用一种激活函数。并且值得你注意的是,全连接层的最后一层就是输出层,除了这个最后一层,其它的全连接层神经元都要包含激活函数。

最最后说再一句,神经网络的激活函数是非线性的,所以神经网络是一个非线性分类器。

强大的层状神经元

在正式开始谈一层神经元之前,我们继续来探讨下神经元面对一张图片还可以做什么?

对于一张标签是猫咪的样本图片,我们光能评价有多么的像猫咪还不能满足,我们还需要神经元评价一下其他9个标签才行,然后才好比较评判得出最终结论。于是,光用 (wi,b) ( w i , b ) D+1 D + 1 个参数就不够用了,应该要有 10×(D+1) 10 × ( D + 1 ) 个参数才行。还是用那个恶搞的例子说明的话,就是说一个神经元评委可不够用哦,要10个戴着不同有色眼镜的神经元评委分头去考察10个不同标签,这样就可以对每个样本图片给出10个对应不同类别的得分。

所以,我们可以在最初的矩阵表达式 iwixi+b ∑ i w i x i + b 的基础上横向延展成如下矩阵表达式:

[iwixi+b]1×10=[xi]1×DwiD×10+[b]1×10Broadcasting [ ∑ i w i x i + b ⋯ ] ⏟ 1 × 10 = [ ⋯ x i ⋯ ] ⏟ 1 × D ⋅ [ ⋮ w i ⋯ ⋯ ⋮ ] ⏟ D × 10 + [ b ⋯
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值