原文出处:Build Your Own Neural Network Framework 原作者:Microsoft · 许可证:MIT License 中文译本由诸葛AI学院整理,仅供学习参考,版权归原作者与微软所有。
神经网络入门:多层感知机
上一节我们认识了最简单的神经网络模型:单层感知机(perceptron),一个线性的两类分类模型。
这一节要把模型推广到一个更灵活的框架,让我们能够:
- 除两类之外,还能做多类分类(multi-class classification)
- 除分类之外,还能解回归问题(regression)
- 分开那些线性不可分的类别
我们还会用 Python 开发一套自己的模块化框架,用它来搭建不同的神经网络结构。
课前小测
机器学习的形式化
先把机器学习问题形式化。假设我们有训练数据集 X 和标签 Y,需要构造一个模型 f,让它的预测尽可能准确。预测质量用损失函数(loss function) L 来衡量。常用的损失函数有这几种:
- 回归问题要预测一个数,可以用绝对误差(absolute error) ∑ᵢ|f(x⁽ⁱ⁾)-y⁽ⁱ⁾|,或者平方误差(squared error) ∑ᵢ(f(x⁽ⁱ⁾)-y⁽ⁱ⁾)²
- 分类问题用 0-1 损失(本质上和模型的准确率是一回事),或者逻辑损失(logistic loss)
对单层感知机来说,函数 f 定义为一个线性函数 f(x)=wx+b(这里 w 是权重矩阵,x 是输入特征向量,b 是偏置向量)。放到不同的神经网络结构里,这个函数可以复杂得多。
做分类时,我们往往希望网络输出的是各个类别对应的概率。要把任意数字变成概率(也就是对输出做归一化),常用 softmax 函数 σ,于是函数 f 变成 f(x)=σ(wx+b)。
在上面 f 的定义里,w 和 b 叫参数(parameter) θ=⟨w,b⟩。给定数据集 ⟨X,Y⟩,我们可以把整个数据集上的总误差写成参数 θ 的函数。
训练神经网络的目标,就是通过调整参数 θ 把误差压到最小。
梯度下降优化
函数优化有一个众所周知的方法:梯度下降(gradient descent)。思路是算出损失函数对参数的导数(多维情况下叫梯度,gradient),然后朝误差下降的方向调参数。形式化写出来:
- 用随机值初始化参数 w⁽⁰⁾、b⁽⁰⁾
- 反复执行下面这一步很多次:
- w⁽ⁱ⁺¹⁾ = w⁽ⁱ⁾ - η∂L/∂w
- b⁽ⁱ⁺¹⁾ = b⁽ⁱ⁾ - η∂L/∂b
按定义,损失是对全部训练样本求和得到的,所以训练时的优化步骤本该在整个数据集上计算。现实里我们只取数据集的小块,叫小批量(minibatch),在一部分数据上算梯度。因为每次取的都是随机子集,这个方法叫随机梯度下降(stochastic gradient descent,SGD)。
多层感知机与反向传播
前面看过,单层网络只能分类线性可分的类别。想构建表达能力更强的模型,可以把网络的几层组合起来。数学上意味着函数 f 的形式更复杂,要分几步算:
- z₁ = w₁x + b₁
- z₂ = w₂α(z₁) + b₂
- f = σ(z₂)
这里 α 是非线性激活函数(non-linear activation function),σ 是 softmax 函数,参数 θ=⟨w₁,b₁,w₂,b₂⟩。
梯度下降算法本身不变,只是梯度更难算了。有了链式求导法则(chain differentiation rule),导数可以这样拆:
- ∂L/∂w₂ = (∂L/∂σ)(∂σ/∂z₂)(∂z₂/∂w₂)
- ∂L/∂w₁ = (∂L/∂σ)(∂σ/∂z₂)(∂z₂/∂α)(∂α/∂z₁)(∂z₁/∂w₁)
链式求导法则就是用来算损失函数对参数的导数的。
注意所有表达式最左边那一项都相同,于是我们可以从损失函数出发,沿着计算图"往回"逐项算导数。训练多层感知机的这个方法,因此叫反向传播(backpropagation),简称 backprop。
原文此处有一张计算图(compute graph),画的是梯度沿网络逐层回传的过程,纯文字版已删去;原文另留有一条待补的图片出处说明(TODO),一并略过。
反向传播会在配套的笔记本示例里详细展开。
小结
这一课我们自己动手搭了一个神经网络库,并用它完成了一个简单的二维分类任务。
挑战
在配套的笔记本里,你将亲手实现一个构建和训练多层感知机的框架,看清现代神经网络的具体运转方式。
去打开 OwnFramework 笔记本,把它做完。
课后小测
复习与自学
反向传播是 AI 和 ML 里的通用算法,值得更深入地研究。
作业
这次实验要求你用本课搭好的框架,解决 MNIST 手写数字分类问题。