“神经网络是具有适应性的简单单元组成的广泛,并行互连的网络,能够模拟生物神经系统对真实世界物体所作出的交互反应。”

神经网络的发展

1943年,神经网络模型最早是由心理学家和数理逻辑学家在提出的MP模型,它揭示了“大脑活动是靠脑细胞的组合连接实现的。”

1949年,心理学家Hebb提出 “脑细胞间某种通路在参与某种活动时被加强。” 用现在的观点来看这一说法,即我们可以通过调整网络参数(权重),来改善网络的性能。

1956年,达特茅斯会议上,明斯基,麦卡锡,西蒙等人首次提供人工智能的概念,使得人工智能在成为计算机科学的一个分支。

1962年,感知机模型正式提出,它具有输入层,输出层和中间层。

1969年,明斯基的《percetion》一书出版,指出感知机不能解决高阶谓词问题,人工智能发展陷入低谷。

1982年,hopfield向美国科学院提出了关于神经网络的报告,引起美国军方的注意,引起了神经网络的第二次高潮。在这次高潮中,hopfield网络,boltzmann机以及BP算法得到提出。

2006年之后,hiton提出深度学习,引起了神经网络的第三次浪潮。

神经网络模型

1943年提出的“M-P神经元模型”如下:

输入乘以权重之后,减去一个偏置$\theta$ ,然后通过激活函数,得到这个神经元的输出。在早期,使用的激活函数为sigmoid函数:


$$
\sigma(z)=\frac{1}{1+\mathrm{e}^{-z}}
$$
sigmoid函数如图:

sigmoid 的导数形式如下:
$$
\sigma(z)’=\frac{\mathrm{e}^{-z}}{(1+\mathrm{e}^{-z})^{2}} = \frac{1+\mathrm{e}^{-z}-1}{(1+\mathrm{e}^{-z})^{2}} = \sigma(z)*(1 - \sigma(z))
$$
由于sigmoid的导数函数形式简单,取值变化范围在(0,1)之间。神经网络就是有无数个像这样的神经元结构组合而成的一个包含许多参数的数学模型。

激励函数

激励函数的作用是将无限域的变换指定到有限范围内进行输出。同时增加网络的非线性建模能力,复杂程度。

Bengio对激活函数有如下的定义:

激活函数是映射h:R->R,且几乎处处可导。

具有软饱和函数的性质:$\lim_{s->\inf} f’(s) = 0$ ,软饱和性质只当x趋向去正无穷或负无穷的时候,函数的导数为0。硬饱和指存在一个区域c,当x接近c边缘时,导数值变为0.

ReLu激活函数:该激活函数能够在一定程度上克服梯度消失的问题。

relu在$x<0$部分为硬饱和,导数为0。在$x>0$部分,导数为1,能够保持网络梯度不衰减,缓解梯度消失问题。 当部分输入落入饱和区时,将导致网络的稀疏性,同时导致对应的权重无法更新(神经元死亡)。relu的输出同时具有偏移现象,即输出的值均值大于0,偏移与神经元死亡是其主要弊病。

误差反向传播

BP算法沿着负梯度方向减小误差,利用链式法则对每一个梯度求一个$\Delta$ 值,用于更新网络的参数。当网络陷入一个极小点时,在该点处不存在负梯度方向,因此参数无法进行更新。此时网络可能陷入局部极小点或全局最小点。

如果网络陷入局部极小点,我们希望在网络的训练过程中,函数能够跳出该极小点。可以使用的方法有 模拟退火法,即在每一步迭代,以一定的概率接受次优解,可以一定程度上避免陷入局部极小。 随机梯度下降法,每次选择部分数据进行梯度的计算,因此该梯度方向不一定是全局的下降方向,随着函数的迭代,网络误差可以慢慢降到一个可以接受的水平。

深度学习

深度学习模型是深层次的神经网络,通过增加网络的层次,提高网络的容量,使得它能学到更加复杂的问题。但是多层神经网络难以用传统的BP算法进行训练,因此后来的学者们也提出了许多其他的算法。

神经网络的实现

pytorch中的torch.nn包

pytorch中关于网络结构的函数在torch.nn这个包里头,此外torch.nn.functional中也有于torch.nn对应的相关函数。他们的区别在于torch.nn中的参数是可训练的,可变的。torch.nn.functional中的函数是不可训练的,进行一些数学运算,类似于tensor于Variable的区别。因此搭建网络结构的时候使用torch.nn,激活函数则使用torch.nn.functional。

贴一个解释很清楚的文章:https://blog.csdn.net/hawkcici160/article/details/80140059

pytorch中的torch.autograd包

autograd.Variable是包的中央类,包含一个张量,并支持几乎所有定义的操作,在完成计算后,调用.backward()并自动计算所有梯度。可以通过.data属性访问原始张量,而将此变量的梯度累加到.grad

Variable类中比tensor类多了几个其他的属性:data,grad_fn,grad,variable变量可以用来计算梯度。

下面这个文章有有详细介绍:https://www.jianshu.com/p/cbce2dd60120

可以用variable来定义网络的参数。