RNN

宏观理解 我们在CNN和R-CNN中学到了怎么来处理一张图片,但是我们默认的是图片和图片之间是没有任何联系的,但是递归神经网络(RNN)来处理的无论文字信息还是图像我们都默认为其间是存在关联的,这种关联的体现就是时间的顺序。比如我给你一张清晨的图片让你来预测再过几小时是什么样子,RNN就能知道按顺序的话输出就应该是中午1点半的图片。文字也是一样。曾经在github上见到一种可以自动填充代码的code,它做的就是根据你目前为止的输入,我推断你接下来应该会写些什么。当然还有我们大家应该都听过的技术叫做时间序列分析,股票预测,用的就是每天收盘的信息来预测这只股票未来走势如何。比如著名的RNN家族里的LSTM模型。 我们在计算机视觉的图片识别上机器已经超过了人类的能力,但是在机器翻译上或者说NLP中机器离人类还有一段距离,这段距离就是人们还没能很好的用机器来做到时间顺序的拟合。因为我们说过神经网络处理图片的时候是根据的人体生物学得到的启发,模拟的人类视觉接收图片到处理图片识别图片。但是RNN目前在生物学中没有找到很好的切合点,到目前为止的RNN设计思路是由1995年被证实和图灵机在数学意义上等价来的,所以RNN未来的发展势必有很大空间。 微观分析 我们先来看看RNN长什么样子:          绿色的箭头是我们的输入值,红色的箭头是我们的输出值。RNN很有意思,它有不止一次的输入也可以有不止一次的输出。我们可以把每次的输入对应到股票预测中的每天的收盘价,中间的灰色区域就是RNN网络,这个里面是一个神经网络就像我们以前见过的一样,下标(t-1)就是指的前一天,今天,和明天。中间的蓝色箭头代表神经网络之间的信息传递,既然时间顺序,那么第N天的神经网络就也一定要有第一天的输出结果。 右图中是我们把左边的网络折叠起来,这就说明了整个网络的RNN的共享权重的,在反向传播中也是照样往回传的。下面我们来推公式,假设我们有一个这样的RNN: 跟之前的展开和折叠的图像含义一样。我们假设有了这些参数U, W, V,一个输入值Xt和两个输出值St, Ot。 U, W, V是三个参数矩阵,也就是一开始我们先把输入值Xt和U点乘,然后加上前一个的输出值St-1和W点乘的和,过一个激活函数比如说f: 对于Ot,我们只需要用St点乘V然后过一个激活函数比如说g: 除了我们见过的这种结构的网络,还有很多的衍生品: 这些网络由于输入值和输出值的不同(输出值-to-输出值)可以针对不同的问题进行训练: one-to-one:我们管这种网络叫Vanilla Neural Networks,算是递归神经网络的基础型。 one-to-many:我们可以输入一张图片,然后生成描述这个图片的一句话一个自然段甚至是一篇文章,这叫Image Captioning many-to-one:我们可以输入一段话,输出关于这段话的评价比如说积极的还是消极的,这叫Sentiment Classification many-to-many:我们可以输入中文句子,输出英文的翻译,这叫Machine Translation many-to-many:另一种many-to-many的结构也可以做视频中每帧的分类,比如这一帧包不包含暴力情节,也可以针对一个1小时的视频来过滤无关的帧,精简到10分钟的内容。 我更觉得RNN是一种思想,基于这种思想我们有了很多的模型比如做机器翻译的NMT,比如可以时序分析的LSTM等等。当然还有大量的未被发掘的应用等待着我们。 希望结合代码的同学可以看这里  

Conv Network (2)

Case Study 我们这里主要介绍几种常见常听说的模型,既是对之前讲的概念进行更深的理解,也是在以后我们可以有思路怎么搭建自己的模型更好。这里主要是讲 LeNet-5 AlexNet ZFNet VGGNet googLeNet ResNet 我们在分别讲5个模型之前先看一下他们的丰功伟绩,这些模型都出自ILSVRC竞赛。为了更好的膜拜这些模型,我一定要说人类识别这些图片的错误率在5%左右,可见最后的ResNet已经达到了超过人类的识别能力。 Year Ranking Top 5 error rate LeNet-5 1998 1st 18.2% AlexNet 2012 1st 15.4% ZFNet 2013 1st 14.8% VGGNet 2014 2nd 11.2% googLeNet 2014 1st 6.7% ResNet 2015 1st 3.6% LeNet-5 这是Yann LeCun在1998年ILSVRC构建的卷积网络,名列第一,也是convnet投入重点研究的开端。它的架构如下图所示: 输入一张32*32的图片,经过C1卷积层得到28*28*6的feature map。feature map就是在输入经过卷积后的结果。我们可以推算出来他的kernel用的是5*5*6并且步长为1。然后一个S2下采样的池化层把纬度降到14*14*6,也可以推算出来pooling用的2*2并且步长为2。接着就又是一层卷积C3和一层池化S4。最后连着两层的全连接层把纬度降到120和84,最后用高斯连接输出10个分类概率。 所以总结起来就是CONV-POOL-CONV-POOL-FC-FC-GAUSSIAN AlexNet Alex Krizhevsky, Ilya Sutskever and Geoff Hinton在2012年参加ILSVRC竞赛的冠军模型,其实很像LeNet但是比它更深更大一些,这也是随着硬件的发展的必然趋势。 …

Conv Network (1)

宏观理解 卷积神经网络我们主要用在图片的处理上,它是在神经网络的思想基础上,把神经网络的weight组合成了一层过滤网,把原图一遍遍的过滤来提取出来最主要的特征。现在的图片分类几乎都是在用卷积网络来做,神经网络更多的还是在一些像年龄、价格、所属层级的一些分类和回归问题上。 下图左边就是我们说过的神经网络的架构,右边是卷积神经网络的架构。能看出来还是有很大区别的,但是这种区别在掌握了神经网络之后就很好理解了。 微观分析 卷积网络主要是由几种不同操作的layer组成,他们是convolutional layer(卷积层),pooling layer(池化层)和fully connection layer(全连接层)组成。 下面对这几种layer分别介绍一下。 convolutional layer 卷积层是卷积网络最核心的提取信息的layer,他的作用是在已有的输入后,把和输入具有信息等价的输出传给下一层。可以理解为卷积层做了一个信息的重构。 对输入信息进行卷积操作的是一个叫filter或者kernel的矩阵。我们以后就统一叫kernel。kernel中的值就是这个卷积网络的参数,在反向传播中我们会不断优化这些值,一开始我们可以随机初始化这些值。   第一张图中左边为输入矩阵,比如说rgb色道中的一个,然后中间的就是卷积核kernel,右边为输出。kernel会一步一步的扫一遍输入,每次到达一个位置时计算这两个3*3矩阵的乘积加和,给到输出。所以每次计算后的输出都是一个值。下面是一个动图更好的理解一下kernel是怎么扫的输入矩阵。 在动图中四周的白色边框叫padding,因为我们可以看出来当kernel进行卷积操作的时候,输出会比输入的矩阵小。如果我有一个上百层的卷积网络,那么矩阵会缩小的很快。在第一张图中输入为5*5,经过3*3的kernel后输出就是3*3 。但是在卷积层我们并不想损失任何信息,我们还想得到相同大小的输出。这时候就像动图中的我们可以在原图上pad一圈0,这样长和宽都扩大了2,最后输出的矩阵大小就和我们输入矩阵大小相同了。关于padding其实有也有很多方法,可以pad 0,也可以pad相邻的数字。但是为了让padding更小的对输出产生影响,一般默认都是pad 0 。 那么我们在pad的时候怎么知道要pad几圈呢?有一个公式可以计算出来:padding = (kernel_size – 1)/ 2  。比如第一张图中,kernel_size等于3,那么我们就需要(3 – 1)/ 2 = 1圈的padding。 除了padding算是一个超参数以外,还有步长(stride)。顾名思义,就是kernel在扫描input的时候是每次往右或者下走一步还是更多。比如在下图中,步长stride就不再是1了而是等于2,所以横竖都只能扫描3次,得到3*3的output。 以上介绍的都是二维矩阵,但是我们知道在处理图片的时候都是rgb三个色道来表示一张图。所以我们接下来让input和kernel变得更复杂一点。 上图就是标准的3色道输入size = 7*7*3,然后两个kernel size = 2*3*3*3,输出是一个3*3*2三维矩阵,步长stride = 2 。输入矩阵先用第一个kernel相乘,得到一层output,再和第二个kernel相乘得到第二层output。因为我们可以看出来input的第一层和kernel的第一层相乘,input的第二层和kernel的第二层相乘,input的第三层和kernel的第三层相乘,所以我们在初始化kernel的时候要遵守的就是input和kernel深度相同。 我们有公式可以计算出来output的大小:size = (input_size – kernel_size)/ stride + 1 。例如上图中size = (7 …

Neural network(2)

接着之前的神经网络第一篇。 这篇文章我们来了解一下更多更专业的细节,来帮助我们更好的训练出神经网络。 Data preprocessing 对于神经网络来说,一般的分类回归问题和普通机器学习模型的数据预处理基本相同。但是对于图像特征的处理,就是重点了。 我们知道一个图像分RGB三个色道,每一个像素值都是0-255。那么我们对图像数据的预处理可以做mean subtraction,比如像AlexNet对每个像素值减去整张图的像素值mean;也可以像VGGNet一样减去每个色道的mean。 归一化也是预处理很重要的一步,目的是把所有的特征点都归一到同一个scale里。一般我们有两种方法,第一种是把整个数据集除以它自己的标准差,第二种就是min-max归一化。流程见下图: 左图是我们拿到的raw data,经过减去整个数据集的mean值,我们可以得到原点对称的数据,就是中间的图。最后再经过归一化得到右图。当然如果像图片的输入,就已经是0-255,就不再需要归一化处理了。 PCA和whitening白化也是我们预处理的方法,因为我们拿到的数据大部分都是特征之间相关性很高,所以自带很多冗余信息,这样会加大训练的难度。经过PCA降维之后,我们可以找到一个新的特征矩阵,这个新矩阵满足1. 特征之间独立。2. 新矩阵和原矩阵的方差一样。也就是说,我们在不损失信息的前提下,降低了数据维度,让数据特征之间增强了独立性。PCA不细说了前面有文章讲过。所谓的白化就是在PCA得到的新矩阵上进行归一化处理。这个过程见下图: 在PCA处理后我们根据所选取的top 144个新特征向量组成新的数据集,也就是图3,然后在新的数据集中进行归一化。最终得到的白化结果如图4。 weight / bias 初始化 权重的初始化也对神经网络的性能产生一定影响,如果倒霉初始化的不好,会发现怎么优化都得不到好的结果。 有的教科书中在讲解神经网络的时候用的都是把权重全部初始化成0,首先肯定是不能用0来初始化的,因为一旦所有的weight都设置成一个权重,在反向传播的过程中所有权重的更新值也都会一样,毫无意义。 我们一般会用的初始化有高斯分布随机初始化,还有Xavier初始化(w = np.random.randn(in, out) / np.sqrt(in)),in和out是前一层和下一层的node数量。还有如果你想用ReLU作为激活函数的时候,需要在Xavier初始化中改变一下分母(w = np.random.randn(in, out) / np.sqrt(in/2.0))。 对于bias我们可以初始化为0或者一个很小的数值比如0.01用于ReLU作为激活函数的时候。 Batch Normalization 这是一个近几年才刚发的论文提到的方法。由于我们的反向传播过程中改变weight改变激活函数输出值,我们一开始标准化完的数据集可能会产生偏移,会导致训练越来越慢。Batch Normalization做的就是在神经网络中添加一些层,在这些层中,我们把传过来的神经元强行拉回到高斯分布的状态。 在我们从前一层得到输出之后,输出值会传给下一层做,然后a = g(z)做非线性激活。我们的Batch Normalization就卡在得到了z之后在激活函数运算之前进行。变换方法也很简单,就是把一个输入值标准化到高斯分布一样: 经过这个还不算完,因为强行的标准化,会导致表达能力下降,所以论文作者也提出了一种防止办法,那就是在得到新的x后,对x进行一个转化,这个转化过程叫scale and shift:。所以总结一下,整个Batch Normalization的过程就是先计算mean和variance用来标准化,然后把标准化的x值进行转化: Regularization 正则化 正则化不多说了,为了防止过拟合增大数据variance。用的多的不过L1和L2。 在神经网络中,还有一种防止过拟合的方法叫dropout。简单易懂易实行,就是强行的扔掉一些神经元,强行让神经网络丧失一些信息。一般dropout都是随机drop20%左右的神经元,下图中打叉的神经元就是被drop掉的。 loss function 损失函数 我们之前介绍反向传播的时候一直说求出loss对于一些值的偏导,还没介绍过神经网络的损失函数。 对于分类问题来说,我们知道最后一层经常用的softmax层,所以损失函数就用cross-entropy loss: …

Neural network(1)

宏观理解 神经网络感觉人人都知道的感觉。它是个仿生学的模型,仿的就是我们的大脑神经网。我们的大脑神经是由一个一个神经元组成的,一旦有冲动神经元之间就会传递这种冲动, 从起点传输到终点然后我们会接收到信号,做出相应的反射动作。人工神经网络就是模仿了这一种信号传递的过程,就好比我们眼前看到的是一个木板四条腿没有脑袋没有嘴,通过视觉神经传输到大脑皮层的神经网,最后成像告诉大脑哦这货看到一张桌子。过程就像这张图: 我们也可以让人工神经网络接收一些东西比如一个特征矩阵,一张图片,一段声波,一连串单词,最后来告诉我这是个啥?这项技术其实从19世纪就有了,后来因为技术不成熟被人遗忘,但是从90年代开始突飞猛进一下超过了很多别的机器学习模型,又在2012年因为ImageNet竞赛秒杀所有模型掀起神经网络的热潮。 直到今天很多衍生物比如CNN, RNN的诞生更是加剧了人们对神经网络的兴趣。一个人类还摸不到底的模型,不多说了看细节吧。 微观分析 我们先说2层的神经网络,一般说几层,指的是有多少层包含权重,两层的神经网络就是这样的: 仅有隐含层(hidden layer)和输出层(output layer)有权重,所以我们叫它两层神经网络。输入层的每个x1,x2,x3是我们的features输入,通过中间隐含层的去线性化,然后通过两层权重(weight,即图中w)最后得到答案。如果是二分类问题,输出层可能只有一个node用来表示y = 1的概率,如果我们用sigmoid激活函数就是这样。多分类问题就比其他模型简单了,最后一层的激活函数换成softmax就好,比如上图我们想像成一个2分类的softmax函数。 激活函数的目的就是去线性化,我们知道逻辑回归是一个广义线性模型,如果我们的神经网络用的都是sigmoid当激活函数就好比把很多逻辑回归拼凑一起,它反而不是线性的了。 我们知道输入层就是我们所有的features,输出层就是每个分类的概率,那么中间的隐含层做了什么呢? 现在我们只看隐含层其中一个node。我们一样有很多的input features,比如年龄身高体重是否结婚。然后我们把左右的input feature x和我们到下一层的权重weight相乘再sum,注意我们sum node上面还有个bias b,这个叫偏置,他的作用是用来拟合更多的情况,想想我们的逻辑回归是不是就是有一个偏置b来让函数可以不止是通过原点来拟合,这里也一样。我们用z来代表这个过程就是。因为是矩阵点乘所以w要transpose一下。接着我们有了z的值,就是要过一个激活函数(activation function)了。试想如果没有激活函数是不是就是线性回归?那就丧失了神经网络的巨大潜能。比如这里我们用sigmoid( σ)函数当作激活函数,通过激活函数我们得到a = σ(z),那么这个a就是我们的y,也就是预测结果。 所以在每个hidden node中,包含的都是两部分,先找到z,也就是上一层的输入乘以这一层的权重再加上偏置b。再把z通过激活函数去线性化,得到预测值y。多层的神经网络无非就是反复这个过程。 现在我们说一下每个参数的维度,这是一个在神经网络中一不小心就会犯的错误。下面是一个3层神经网络: input layer我们有3个node,第一层隐含层有4个node,第二层也一样,最后输出层有一个node输出。我们把每层中node个数记作n。用 “l” 来表示第几层,比如input是第0层,hidden layer 1是第1层依此类推。一个神经网络一共包含的参数有:权重w,偏置b,前一层输出a,和当前层输出σ(z)的z。所以每层神经网络做的事情就是计算。如果我们向量化的考虑大小,应该是这样的: 用文字表达:    dW,db,dZ,dA是反向传播时候的导数,只是求偏导,大小不变。 比如说我们的hidden layer 1,l = 1,那么w1维度是当前层的node个数*前一层的node个数也就是4*3; b1的维度是当前层个数*1也就是4*1;z和a一样都是4*feature的个数3也就是4*3。 Forward propagation 前向传播的过程就像冲动从接受信号往大脑皮层传播的过程。也就是从有了features的输入一直到有一个prediction y。基本过程就跟之前讲的一样。a就是前一层的输出,σ(z)就是这一层的输出,然后把σ(z)当作前一层输出a再传播给下一层。直到我们有了一个预测值y。这就是一整个前向传播过程。 Backward propagation 反向传播的过程就是从原路返回,我们已经有了一个y,那就从y开始求偏导数一直求到input。反向传播是学习神经网络的重点也是难点,所以我会介绍的尽可能详细。 讲反向传播之前我们先看一个简单的例子:             …