Neural Networks and Deep Learning阅读笔记(1)手写字符识别
刚开始开始学习深度学习,找了一本比较简单的书来看看,顺便记个笔记。我是那种不记笔记估计看完一页忘一页的人╮(╯▽╰)╭嘻嘻嘻
emmm这篇笔记就是我自己的碎碎念啦,不严谨而且中英文随便换着用
第一章手写字符识别,通过这个简单的例子讲了神经网络的一些基本概念,包括神经元、感知器、随机梯度下降等。(好绝望,这些名词都不清楚,慢慢往下看吧)
首先,人辨别手写字符0-9看似容易,其实是一件非常复杂的事情,是我们大脑中的许多地方共同运作的结果,那我们如何使机器也能辨别出这些手写字符呢?有一种方法就是用大量的手写字符当做训练样本training examples
然后用一些神奇的方法让机器自己学会如何辨认这些字符,告诉它们一些辨认规则。【而且training examples越多,机器就对这些字符了解更多,相应的识别的肯定越来越好啦
这里介绍一种只用74行代码的方法,也不用神经网络的库,不过正确率只有96%+,不过下一章会有介绍99%+的更好的方法。
感知器perceptrons
感知器是一种神经元,现在更多的在使用sigmoid神经元而不使用感知器了,但是我们了解一下还是有必要滴~
perceptron接收several binary inputs, x1,x2,x3…然后产生一个single binary output
那具体在这个圈圈里是怎么计算出output的呢?我们给每一个输入乘一个权重weight,w1,w2,w3…weight都是实数,表明每个输入的重要程度,然后我们有一个阈值,如果输入的加权和大于这个阈值,output=1,小于则output=0
其实做决定的时候也不知不觉用了感知器呢,你先列出几个影响决定的指标,然后根据个人喜好决定这些指标的重要程度,根据加权和是否大于自己的心理预期去最终决定。
下面是多个感知器连接起来的网络
第一列的三个呢是first layer,而第二列四个又是在first layer的结果的基础上再一次进行计算,所以第二层比第一层更加的复杂和抽象,第三层就更是啦。所以这样多个感知器连接起来的网络可以进行复杂的decision-making!
每次都写加权和太麻烦啦!所以我们可以把加权和改写成向量点积的形式w·x,并且将threshold移到不等式右边,变成如果w·x+b<=0,output=0,w·x+b>=0,output=1。【懒得打公式╮(╯▽╰)╭
我们把b称作偏置bias。
感知器不仅可以用作decision making,还可以做一些逻辑运算AND, OR, NAND等,比如下图的NAND门运算,这个很简单啦。
将与非门换成感知器
推一推就很容易推出来了。
除去decision making & gate computation,感知器最重要的就是,我们可以设计一些学习算法learning algorithm去根据需要自动调整每一步的权重和偏置。感知器可以自己学习如何解决问题,而不是简单地通过输入得到输出。这种算法让感知器网络与门逻辑运算有了巨大的不同!
Sigmoid neurons
那么如何设计一个学习算法呢?我们上面知道通过改变weights&bias来给output一个非常小的改变
比如有一个手写数字分错了,我们可以尝试改变权重和偏置来使结果正确,这样一次次的改变参数使得我们的感知器表现越来越好。
但问题是,你不清楚如何才能让output有一个很小的改变,有时输出会变动很大。所以我们很难慢慢的调整weights和bias。
为了解决这个问题,我们设计了一个新的神经元——sigmoid neuron。样子嘛 与感知器差不多
与感知器不同的是,output不再只取0和1,而是取0到1之间的任何实数。这个圈圈里不再是简单的计算加权和就直接比较,而是有了一个新的公式——sigmoid function:
所以一个sigmoid neuron的output为:
【幸好我之前接触过一点,不然看到这个式子我就懵了,其实就是把原本的离散输出变成连续的而已,从{0,1}映射到[0,1],这样子权重和偏置的一点点变化才不会导致output直接从0翻到1,而是在实数部分有一个小变化。
那为什么会选取 σ \sigma σ(z)呢?是因为这个函数对于w和b求偏导的结果非常简洁,可以清晰的看出w和b的变化是如何影响 σ \sigma σ的变化的,不过之后还会有其他的函数。
The architecture of neural networks
介绍几个名词~
最左边一列是input layer,在这一层中的神经元是input neurons。最右边就是output layer以及output neurons。中间的层叫做hidden layer,上面的图只有一层hidden layer。
而使用这样简单的神经网络也比较直接,比如想知道一个手写数字是不是“9”,我们把每个像素当做一个输入神经元,灰度当做0到1之间的一个实数输入,通过一些方法加权,而输出神经元则输出这个数是“9”的概率。【当然,根据需要的不同,hidden layer的设计也可以变得十分复杂
如果上一层的输出是下一层的输入的话,我们把这样的网络叫做feedforward神经网络,如果有循环的话(也就是说一层的输出有可能是上层的输入),这样的神经网络被称为recurrent neural networks,这种循环中的神经元可以活跃持续一段时间,并且可以在一段时间之后激励下一层的神经元。
A simple network to classify handwritten digits
为了识别每个手写字符,我们将一串数字分开成单独的数字:
为了识别一个手写字符,我们使用如下三层神经网络:
我们的训练样本是28*28的图片,所以刚开始的input neuron就是784个。输入值是像素灰度值,0.0代表白色,1.0代表黑色。第二列是hidden layer,图中展示了15个神经元。第三层输出层有十个神经元,代表了0~9十个手写字符的概率,比如第一个神经元输出约为1的话,代表了我们认为这个字符是“0”。
不过为什么不仅仅用4个神经元的二进制来代表十个数字呢,这样的效率应该更高啊?为了解决这个问题,需要从原理上理解神经网络到底如何识别手写字符的。
考虑输出层第一个neuron,它决定了这个digit是否是“0”。而这个神经元的输入又是由hidden layer里的每个神经元的输出得到的,考虑hidden layer里面第一个神经元,假设它检测一个image是不是这样的(通过加重这一部分的像素权重而减轻图像其他部分的像素权重):
而第2、3、4个神经元分别检测一个image是不是这样的:
如果这四个神经元都是被激活的,那么我们可以认为,这个字符是“0”: