《Neural Networks and Deep Learning》读书笔记系列:1.识别手写字

简介: 《Neural Networks and Deep Learning》读书笔记系列:1.识别手写字

深度学习笔记系列之识别手写字


Neural Networks and Deep Learning[1] 是由 Michael Nielsen[2] 编写的开源书籍,这本书主要讲的是如何掌握神经网络的核心概念,包括现代技术的深度学习,为你将来使⽤神经网络和深度学习打下基础,以下是我的读书笔记。


神经网络是一门重要的机器学习技术,它通过模拟人脑的神经网络来实现人工智能的目的,所以其也是深度学习的基础,了解它之后自然会受益颇多,本章主要是以识别手写字这个问题来贯穿整篇,那么,人类的视觉系统和神经网络到底在识别一个目标的时候,主要区别在哪?


  • 人类视觉系统:通过数十亿年不断地进化与学习,最终能够极好地适应理解视觉世界的任务,从而无意识地就可以对目标进行判断识别

  • 神经网络:通过提供的样本来推断出识别某种目标的规则,作为判断标准

本章的主要内容是介绍神经网络的基本概念以及引入一个识别手写数字的例子来加深我们的理解,你将了解到:


  • 两个重要的人工神经元:感知器和 S 型神经元

  • 神经⽹络的架构

  • ⼀个简单的分类⼿写数字的⽹络

  • 标准的神经网络学习算法:随机梯度下降算法

感知器


1943 年,心理学家 McCulloch 和数学家 Pitts 发表了《A logical calculus of the ideas immanent in nervous activity[3]》,其中提出了抽象的神经元模型 MP,但是在这个模型中权重都是要求提前设置好才可以输出目标值,所以很遗憾,它不可以学习,但这不影响此模型给后来者带来的影响,比如感知器:


感知器是 Frank Rosenblatt 提出的一个由两层神经元组成的人工神经网络,它的出现在当时可是引起了轰动,因为感知器是首个可以学习的神经网络


感知器的工作方式如下所示:

13.jpg


分别表示三个不同的二进制输入,output 则是一个二进制输出,对于多种输入,可能有的输入成立有的不成立,在这么多输入的影响下,该如何判断输出 output 呢?Rosenblatt 引入了权重来表示相应输入的重要性。


对于个输入,每个输入都有对应的权重,最后的输出 output 由每个输入与其对应的权重相乘之和与阈值之差来决定,如下:

14.jpg

假设且和对应权重和输⼊的向量,即:


那么感知器的规则可以重写为:

15.jpg

这就是感知器的数学模型,是不是就像一个逻辑回归模型?只要将感知器输出规则替换为(),后面我们会知道这称之为激活函数,其实这种感知器叫做线性单元。


它的出现让我们可以设计学习算法,从而实现自动调整人工神经元的权重和偏置,与此同时 output 也会随之改变,这就是学习!如果你有兴趣可以看我用python写的一个感知器自动学习实现与非门,代码在**nndl_chapter01[4]**。


说句题外话,由于感知器是单层神经网络,它只能实现简单的线性分类任务,所以它无法对异或问题进行分类,异或的真值表如下:




0 0 0
0 1 1
1 0 1
1 1 0

可以看出来,异或问题是线性不可分的,不信你画个坐标轴试试看,那么问题来了?怎么解决,大部分都能很快地想出解决方案,既然感知器可以实现线性分类,也就是说实现与非门是没有问题的,逻辑上来说我们可以实现任何逻辑功能(比如四个与非门实现异或),但前提是为感知器加入一个隐藏层,意思就是多了一个隐藏层的神经网络之后,就可以解决异或问题。

可是在当时是没办法对多层神经网络(包括异或逻辑)进行训练的,因为计算量太大了,Minsky 在 1969 年出版了一本叫《Perceptron》的书详细说明了这个问题。


遇到问题,就解决问题,两层神经网络的作用,是可以对非线性进行分类的,我们的先人并未止步,直到反向传播(Backpropagation,BP)算法的出现解决了计算量太大的问题。


感知器,终于可以多层了。


S 型神经元


前面提到,神经网络可以通过样本的学习来调整人工神经元的权重和偏置,从而使输出的结果更加准确,那么怎样给⼀个神经⽹络设计这样的算法呢?

16.jpg

以数字识别为例,假设⽹络错误地把⼀个9的图像分类为8,我们可以让权重和偏置做些⼩的改动,从而达到我们需要的结果9,这就是学习。对于感知器,我们知道,其返还的结果不是 0 就是 1,很可能出现这样一个情况,我们好不容易将一个目标,比如把9的图像分类为8调整回原来正确的分类,可此时的阈值和偏置会造成其他样本的判断失误,这样的调整不是一个好的方案。


所以,我们需要 S 型神经元,因为 S 型神经元返回的是[0,1]之间的任何实数,这样的话权重和偏置的微⼩改动只会引起输出的微⼩变化,此时的 output 可以表示为,而就是 S 型函数,S 型函数中 S 指的是 Sigmoid 函数,定义如下:


其中表达式为:


那么⼀个具有输⼊,权重为,和偏置 b 的 S 型神经元的输出是:


上面说过,感知器的激活函数只会输出两个值,分别是01,让我们把目光投向 S 型神经元,假设此时是一个很大的正数,那么此时 output 将无限接近于 1,反之,若是一个很大的负数,那么此时 output 将无限接近于 0,从极端情况来看,是不是很像 S 型神经元呢?

S 型神经元的输出是[0,1]之间的任何实数,那么这个分类模型该如何判断分类结果呢?其实很简单,我们可以定义一个数值,比如:


  • 输出 0

  • 输出 1

神经⽹络的架构


看下面一个四层神经网络,这种类型的多层⽹络有时被称为多层感知器或者MLP,如下图:

17.jpg

需要记住以下几个概念:


  • ⽹络中最左边的称为输⼊层,其中的神经元称为输⼊神经元

  • 中间得称之为隐藏层,图中有两个隐藏层

  • 最右边称之为输出层

  • 上⼀层的输出作为下⼀层的输⼊,信息总是向前传播,从不反向回馈:前馈神经网络
  • 有回路,其中反馈环路是可⾏的:递归神经网络

⼀个简单的分类⼿写数字的⽹络


对于这六个数字504192,我们该如何实现一个分类⼿写数字的⽹络呢,可以将其分解为两个小问题:


  • 504192 是连续在一起的图像,首先可以将其分割成 6 个小图像,比如50 ...等

  • 再对分割开的小图像进行分类,比如识别 5 我们将使⽤⼀个三层神经⽹络来识别单个数字:
  • 18.jpg
  • 由于训练数据由的⼿写数字的图像组成,所以:

  • 输入层有 784 个神经元,因为,输⼊像素是灰度级的,值为 0:0 表⽰⽩⾊,值为 1:0 表⽰⿊⾊,中间数值表⽰逐渐暗淡的灰⾊

  • 隐藏层⽤ n 来表⽰神经元的数量,我们将给 n 实验不同的数值。⽰例中⽤⼀个⼩的隐藏层来说明,仅仅包含个神经元

  • ⽹络的输出层包含有 10 个神经元,如果第一个输出神经元被激活,那么数字就是 0,以此类推,从 0 到 9

一个分类⼿写数字的⽹络,大概就可以这样实现。


随机梯度下降算法


分类方案已经确定了,接下来第一步就是获取样本,我们将使⽤MNIST[5]数据集,其包含有数以万计的连带着正确分类器的⼿写数字的扫描图像,下载好建立这样的目录结构,使用jupyter notebook开始吧,如果没有,请自行检索教程安装,代码目录如下:

pylab
└── datasets
    └── MNIST_data
        ├── t10k-images-idx3-ubyte.gz
        ├── t10k-labels-idx1-ubyte.gz
        ├── train-images-idx3-ubyte.gz
        └── train-labels-idx1-ubyte.gz

然后使用TensorFlow来读取数据,看看下载的数据集到底是什么样子,可以在mnist_data.ipynb中添加如下代码:

from matplotlib import pyplot as plt
from tensorflow.examples.tutorials.mnist.input_data import read_data_sets
mnist = read_data_sets("../datasets/MNIST_data/", one_hot=True)

查看一些基本信息:

print("Training data size: %s" % mnist.train.num_examples)
print("Validating data size: %s" % mnist.validation.num_examples)
print("Testing data size: %s" % mnist.test.num_examples)
# 每张图片是长度为784的一维数组
print(len(mnist.train.images[0]))
def display_digit(image):
    image = image.reshape([28,28])
    plt.imshow(image, cmap=plt.get_cmap('gray_r'))
    plt.show()
print("样本真实数字为:%s" % list(mnist.train.labels[1]).index(1))
# 显示图像
display_digit(mnist.train.images[1])
# Output
# Training data size: 55000
# Validating data size: 5000
# Testing data size: 10000
# 784
# 样本真实数字为:3

可以看到显示如下图像:

19.jpg

通过代码,我们知道,每个图像被分割成 784 个值存于一维数组中,看作⼀个维的向量,每个向量就代表图像中单个像素的灰度值,假设我们用表示 output,也就是当我们输入一组样本数据 x,那么 y 就是我们需要的结果,怎么从 x 得到 y 呢,我们需要一个函数。


感知器为什么可以学习,因为它可以调整和来实现 output 的改变,这里,我们同样需要一个算法来让我们找到权重和偏置,从而使得可以拟合样本输入的 x,为了量化我们如何实现这个⽬标,我们定义⼀个代价函数(有时被称为损失或⽬标函数):


  • w 表⽰所有的⽹络中权重的集合

  • b 是所有的偏置

  • n 是训练输⼊数据的个数

  • a 是表⽰当输⼊为 x 时输出的向量,可以理解为 output

训练模型的过程就是优化代价函数的过程,Cost Function(代价函数) 越小,就代表模型拟合的越好,所以我们的目的是找出最⼩化权重和偏置的代价函数,其实这个就是我们平常用来评价回归算法的均方误差,也就是MSE


现在我们的目标很清晰,为了找出合适的权重和偏置值,我们需要让代价函数的值接近于 0,在这个条件下我们就可以找出合适的权重和偏置值,我们将采⽤称为梯度下降的算法来达到这个⽬的。


下面是我的推导过程:

20.jpg

实现数字分类模型


终于,掌握了基本的概念,我们可以通过实战来实现一个数字分类模型,来看看,前面我们掌握的知识是怎么运用于实际的。


书籍作者很贴心地实现了模型代码,仓库见neural-networks-and-deep-learning 官方 git 仓库[6],接下来我们一起来看看具体的实现代码吧。


首先是实现一个Network类,

#!/usr/bin/env python
import random
import numpy as np
class Network(object):
    def __init__(self, sizes):
        """
        初始化
        :param sizes:
            如果想要初始化一个层数为3,里面神经元数量分别为:2,3,1 的神经网络,那么 sizes = [2,3,1]
        """
        self.num_layers = len(sizes)
        self.sizes = sizes
        self.biases = [np.random.randn(y, 1) for y in sizes[1:]]
        self.weights = [np.random.randn(y, x)
                        for x, y in zip(sizes[:-1], sizes[1:])]

前面已经说了 S 型神经元,那么此时激活函数实现如下,更加具体的代码请参考network.py[7]

def sigmoid(z):
    """The sigmoid function."""
    return 1.0/(1.0+np.exp(-z))

代码已经准备就绪,下面可以开始进行模型训练:

import mnist_loader, network
training_data, validation_data, test_data = mnist_loader.load_data_wrapper()
net = network.Network([784, 30, 10])
net.SGD(list(training_data), 30, 10, 3.0, test_data=list(test_data))
# Output
Epoch 0: 9023 / 10000
Epoch 1: 9222 / 10000
Epoch 2: 9312 / 10000
Epoch 3: 9312 / 10000
Epoch 4: 9383 / 10000
Epoch 5: 9421 / 10000
Epoch 6: 9432 / 10000
Epoch 7: 9421 / 10000
Epoch 8: 9454 / 10000
Epoch 9: 9447 / 10000

看结果,十次迭代后,轻轻松松突破 94%

参考


  • 文中涉及代码[8]

  • Neural Networks and Deep Learning[9]

  • Neural Networks and Deep Learning 中文版[10]

  • 神经网络浅讲:从神经元到深度学习[11]

  • neural-networks-and-deep-learning 官方 git 仓库[12]

参考资料


[1]

Neural Networks and Deep Learning: http://neuralnetworksanddeeplearning.com/index.html


[2]

Michael Nielsen: http://michaelnielsen.org/


[3]

A logical calculus of the ideas immanent in nervous activity: http://cns-pc62.bu.edu/cn550/Readings/mcculloch-pitts-43.pdf


[4]

nndl_chapter01: https://github.com/howie6879/pylab/blob/master/pylab/books/nndl/chapter01/chapter01.ipynb


[5]

MNIST: http://yann.lecun.com/exdb/mnist/


[6]

neural-networks-and-deep-learning 官方git仓库: https://github.com/mnielsen/neural-networks-and-deep-learning


[7]

network.py: https://github.com/mnielsen/neural-networks-and-deep-learning/blob/master/src/network.py


[8]

文中涉及代码: https://github.com/howie6879/pylab/blob/master/pylab/books/nndl/chapter01/chapter01.ipynb


[9]

Neural Networks and Deep Learning: http://neuralnetworksanddeeplearning.com/index.html


[10]

Neural Networks and Deep Learning 中文版: https://github.com/zhanggyb/nndl


[11]

神经网络浅讲:从神经元到深度学习: http://www.cnblogs.com/subconscious/p/5058741.html


[12]

neural-networks-and-deep-learning 官方git仓库: https://github.com/mnielsen/neural-networks-and-deep-learning

相关文章
|
4月前
|
机器学习/深度学习 算法
【博士每天一篇文献-综述】A wholistic view of continual learning with deep neural networks Forgotten
本文提出了一个整合持续学习、主动学习(active learning)和开放集识别(open set recognition)的统一框架,基于极端值理论(Extreme Value Theory, EVT)的元识别方法,强调了在深度学习时代经常被忽视的从开放集识别中学习识别未知样本的教训和主动学习中的数据查询策略,通过实证研究展示了这种整合方法在减轻灾难性遗忘、数据查询、任务顺序选择以及开放世界应用中的鲁棒性方面的联合改进。
39 6
|
4月前
|
机器学习/深度学习 存储 人工智能
【博士每天一篇文献-算法】改进的PNN架构Progressive learning A deep learning framework for continual learning
本文提出了一种名为“Progressive learning”的深度学习框架,通过结合课程选择、渐进式模型容量增长和剪枝机制来解决持续学习问题,有效避免了灾难性遗忘并提高了学习效率。
75 4
|
4月前
|
机器学习/深度学习 算法 Go
【博士每天一篇文献-算法】Progressive Neural Networks
本文介绍了渐进式网络(Progressive Neural Networks),一种深度强化学习架构,通过在训练过程中学习预训练模型间的侧向连接实现跨任务知识迁移,有效利用迁移学习优势同时避免灾难性遗忘,并通过强化学习任务验证了架构性能。
49 1
|
4月前
|
机器学习/深度学习 存储 算法
【博士每天一篇文献-综述】Continual lifelong learning with neural networks_ A review
这篇综述论文深入探讨了神经网络在终身学习领域的研究进展,包括生物学启发的概念、终身学习方法的分类与评估,以及未来研究方向,旨在解决神经网络在学习新任务时如何避免灾难性遗忘的问题。
50 2
|
7月前
|
机器学习/深度学习 算法 固态存储
【论文泛读】 Deep Learning 论文合集
【论文泛读】 Deep Learning 论文合集
|
机器学习/深度学习 自然语言处理 算法
【论文泛读】 知识蒸馏:Distilling the knowledge in a neural network
【论文泛读】 知识蒸馏:Distilling the knowledge in a neural network
【论文泛读】 知识蒸馏:Distilling the knowledge in a neural network
|
机器学习/深度学习 人工智能 算法
【Nature论文浅析】基于模型的AlphaGo Zero
【Nature论文浅析】基于模型的AlphaGo Zero
129 0
|
机器学习/深度学习 自然语言处理 算法
周志华《Machine Learning》学习笔记(16)--概率图模型
根据一些已观察到的证据来推断未知,更具哲学性地可以阐述为:未来的发展总是遵循着历史的规律。
137 0
周志华《Machine Learning》学习笔记(16)--概率图模型
|
机器学习/深度学习 算法 数据挖掘
周志华《Machine Learning》学习笔记(15)--半监督学习
监督学习指的是训练样本包含标记信息的学习任务
226 0
周志华《Machine Learning》学习笔记(15)--半监督学习
|
机器学习/深度学习 算法 数据挖掘
周志华《Machine Learning》学习笔记(6)--神经网络
在机器学习中,神经网络一般指的是“神经网络学习”,是机器学习与神经网络两个学科的交叉部分。
106 0
周志华《Machine Learning》学习笔记(6)--神经网络