最终实现代码仓库链接
https://github.com/VitaminyW/numpy_basied_DeepLearning/tree/main
基础知识
目前主流的深度学习是基于Hinton在1986年所提的反向传播算法(back-propagating,BP)[1]和机器学习中的神经网络算法,通过加深神经网络的层数,从而能够在增加少量参数(相比于浅层网络)的前提下,提高网络对函数的拟合能力。PS:事实上,当参数量足够大时,浅层网络可以拟合任意函数[2]。
本文所需数学知识
- 矩阵求导法则
- 微积分求导方法以及链式法则
- 最优化理论基础
问题建模
假设现实中存在某一函数,我们通过采样得到其数据集,于是我们想要获取,值得注意的是,在实际情况中,采样过程是存在噪声的,即,但这里为了简化问题,我们噪声为0。
如果我们了解 的特性,即如果它是线性函数,其中,则我们可以在线性函数集中寻找一个最优的去代替它,即求解最优化表达式,
(1)
如果可以证明集合是凸集,则可以使用牛顿法,共轭梯度算法等求解该问题。
而事实上,我们所想求的经常是非线性函数,通过我们在基础知识所讲的,神经网络可以用于逼近任意函数,则设神经网络的运算为,其中为网络参数,则问题可以转变为,求解下面最优化表达式
(2)
其中,K为参数数量。
模型细节
为了求解未知的非线性函数,我们使用了神经网络这一工具制作我们的函数集,通过将问题转为求解,我们便可以得到所求解的模型(定义:模型指的是其参数以及其结构)。
为了简化公式,我们定义这里的模型为一个两层的神经网络,则其函数可以表示为:
(3)
其中,,是非线性函数。
则模型参数
由此,我们可以将问题转化为求解
BP算法
在微积分中,我们了解到当位于函数定义域的某一点时,我们沿着函数在该点的梯度以一个固定的小的步长(步长可以用某些准则求出,为了避免冗余,这里不阐述)行走时,能够最快地得到的增量,但在深度学习中,我们往往想让损失函数(如公式(1),(2))下降,则我们应该沿着负梯度更新,下面给出一个简单的公式阐述:
目的:我们想得到一个,使得
即,
由二阶泰勒展开可得,
所以,当取时,原式可以写为
当步长满足一定条件,我们可以忽略无穷小量,即使得
注:我们通常不会直接取作为更新步长,而会在其之上乘以一个学习率, 该学习率是模型的超参数,其与函数的高阶导有关,但由于神经网络产生函数是变化的,我们通常会调参这个学习率,而不是推导。
BP算法用于神经网络
值得注意的是,上一节中的是神经网络的参数,而不是我们前面所提的数据集中的元素,在本节开始前,要明确数据集是不变的,即它在我们求解的最优化公式中可以被视为常量,而我们所要更新的是。则将上节中的,用代替,则更新算法可以表示为:
于是问题转为各个参数的梯度如何求导,这里便引入了链式求导法则:
最终,
由此,我们可以看出不同函数的运算可以在更新过程中独立开来,即每个函数只要能够计算前向传播与后向梯度求导(由后面的梯度算出本步计算的梯度)即可完成模型参数更新。
我们只需要知道,便可以训练模型。而在深度学习中,常见的非线性函数为Relu,Sigmoid等,若网络重复使用这些非线性函数,只需要定义一次如何进行反向便可。
参考文献
[1]Rumelhart D E, Hinton G E, Williams R J. Learning representations by back-propagating errors[J]. nature, 1986, 323(6088): 533-536.
[2]Hornik K, Stinchcombe M, White H. Multilayer feedforward networks are universal approximators[J]. Neural networks, 1989, 2(5): 359-366.