当前位置:   article > 正文

机器学习-神经网络_机器学习神经网络

机器学习神经网络

1、神经网络

1.1、神经元模型

        神经网络中最基本的成分是神经元(neuron)模型, 即上述定义中的“简单单元”. 在生物神经网络中, 每个神经元与其他神经元相连,当它“兴奋”时, 就会向相连的神经元发送化学物质,从而改变这些神经元内的电位; 如果某神经元的电位超过了一个“阅值”(threshold), 那么它就会被激活,即"兴奋"起来, 向其他神经元发送化学物质.

        1943 年,[McCulloch and Pitts,1943] 将上述情形抽象为图 5.1所示的简单模型,这就是一直沿用至今的 “M-P 神经元模型”. 在这个模型中, 神经元接收到来自n个其他神经元传递过来的输入信号, 这些输入信号通过带权重的连接(connection)进行传递, 神经元接收到的总输入值将与神经元的阙值进行比较,然后通过“激活函数”(activation function)处理以产生神经元的输出.

        理想中的激活函数是图 5.2(a) 所示的阶跃函数,它将输入值映射为输出值“0”或“1”, 显然“1”对应于神经元兴奋,“0”对应于神经元抑制. 然而,阶跃函数具有不连续、不光滑等不太好的性质,因此实际常用 Sigmoid函数作为激活函数. 典型的 Sigmoid 函数如图 5.2(b)所示, 它把可能在较大范围内变化的输入值挤压到(0, 1) 输出值范围内, 因此有时也称为“挤压函数”(squashing function).

        把许多个这样的神经元按一定的层次结构连接起来, 就得到了神经网络.

        事实上, 从计算机科学的角度看, 我们可以先不考虑神经网络是否真的模拟了生物神经网络, 只需将一个神经网络视为包含了许多参数的数学模型, 这个模型是若干个函数, 例如y_{j}=f( \sum_{i}w_{i}x_{i}-\theta_{j} ) 相互(嵌套)代入而得. 有效的神经网络学习算法大多以数学证明为支撑.

1.2、感知机与多层网络

        感知机(Perceptron)由两层神经元组成,如图 5.3 所示,输入层接收外界输入信号后传递给输出层, 输出层是 M-P 神经元,亦称“阈值逻辑单元”(threshold logic unit).

         感知机能容易地实现逻辑与、或、非运算. 注意到 y_{j}=f( \sum_{i}w_{i}x_{i}-\theta_{j} ), 假定​是图 5.2中的阶跃函数, 有

  • “与” (x_{1} \wedge x_{2}): 令w_{1}=w_{2}=1, \theta = 2, 则 y=f(1\cdot x_{1}+1\cdot x_{2}-2), 仅在x_{1}=x_{2}=1时, y=1
  • “或” (x_{1} \vee x_{2}): 令w_{1}=w_{2}=1, \theta = 0.5, 则y=f(1\cdot x_{1}+1\cdot x_{2}-0.5), 仅在 x_{1}=1x_{2}=1时, y=1;
  • “非” (\lnot x_{1}): 令 w_{1}=-0.6, w_{2}=0, \theta = -0.5, 则 y=f(-0.6\cdot x_{1}+0\cdot x_{2}+0.5), 仅在 x_{1}=1y=0, 当 x_{1}=0时, y=1.

        更一般地, 给定训练数据集, 权重 w_{i}(i = 1,2,...,n)以及阈值 \theta可通过学习得到. 阈值 \theta可看作一个固定输入为-1.0的“哑结点”(dummy node) 所对应的连接权重 w_{n+1}, 这样, 权重和阈值的学习就可统一为权重的学习. 感知机学习规则非常简单, 对训练样例 (x,y), 若当前感知机的输出为 \hat{y}, 则感知机权重将这样调整:

w_{i}\leftarrow w_{i}+\bigtriangleup w_{i}        (5.1)

\bigtriangleup w_{i}=\eta (y-\hat{y})x_{i}        (5.2)

x_{i}x对应于第i个输入神经元的分量.

\eta通常设置为一个小正数, 例如0.1.

        其中 \eta \in (0,1)称为学习率(learning rate). 从式(5.1)可看出,若感知机对训练样例(x, y)预测正确,即 \hat{y}=y, 则感知不发变化,否则将根据错误的程度进行权重调整。

        需注意的是,感知机只有输出层神经元进行激活函数处理,即只拥有一层功能神经元(functional neuron), 其学习能力非常有限. 事实上,上述与、或非问题都是线性可分(ineary separable)的问题. 可以证明[Minsky and Papert.1969], 若两类模式是线性可分的, 即存在一个线性超平面能将它们分开, 如图5.4(a)-(c)所示, 则感知机的学习过程一定会收敛(converge) 而求得适当的权向量w=(w_l;w_2;...;w_{n+1}); 否则感知机学习过程将会发生振荡(uctuation), ​w难以稳定下来, 不能求得合适解, 例如感知机甚至不能解决如图 5.4(d) 所示的异或这样简单的非线性可分问题.

        要解决非线性可分问题,需考虑使用多层功能神经元. 例如图 5.5 中这个简单的两层感知机就能解决异或问题. 在图 5.5(a)中, 输出层与输入层之间的一层神经元, 被称为隐层或隐含层(hidden layer), 隐含层和输出层神经元都是拥有激活函数的功能神经元.

        更一般的, 常见的神经网络是形如图 5. 6所示的层级结构, 每层神经元与下一层神经元全互连,神经元之间不存在同层连接, 也不存在跨层连接. 这样的神经网络结构通常称为“多层前馈神经网络”(multi-layer feedforward neural networks), 其中输入层神经元接收外界输入, 隐层与输出层神经元对信号进行加工,最终结果由输出层神经元输出; 换言之,输入层神经元仅是接受输入,不进行函数处理,隐层与输出层包含功能神经元. 因此,图5.6(a)通常被称为“两层网络”,为避免歧义, 本书称其为“单隐层网络”. 只需包含隐层, 即可称为多层网络. 神经网络的学习过程, 就是根据训练数据来调整神经元之间的“连接权”(connection weight)以及每个功能神经元的阈值; 换言之,神经网络“学”到的东西, 蕴涵在连接权与阈值中.

1.3、误差逆传播算法

        多层网络的学习能力比单层感知机强得多. 欲训练多层网络, 式(5.1)的简单感知机学习规则显然不够了,需要更强大的学习算法. 误差逆传播(extrorBackPropagation, 简称 BP)算法就是其中最杰出的代表, 它是迄今最成功的神经网络学习算法. 现实任务中使用神经网络时, 大多是在使用 BP 算法进行训练. 值得指出的是, BP 算法不仅可用于多层前馈神经网络, 还可用于其他类型的神经网络,例如训练递归神经网络[Pienda, 1987]. 但通常说“BP 网络”时, 一般是指用 BP算法训练的多层前馈神经网络.

        下面我们来看看 BP 算法究竟是什么样. 给定训练集D=\left\{ (x_{1},y_{1}),(x_{2},y_{2}),...,(x_{m},y_{m}) \right\}, x_{i} \in \mathbb{R}^{d},y_{i} \in \mathbb{R}^{l}, 即输入示例由 d个属性描述, 输出l维实值向量. 为便于讨论, 图5.7给出了一个拥有 d个输入神经元、 l个输出神经元、 q 个隐层神经元的多层前馈网络结构, 其中输出层第 j个神经元的阈值用 \theta_{j}表示, 隐层第 h个神经元的阈值用 \gamma _{h}表示. 输入层第 i个神经元与隐层第 h个神经元之间的连接权为 v_{ih}, 隐层第 h个神经元与输出层第 j个神经元之间的连接权为 w_{hj}. 记隐层第 h个神经元接收到的输入为 \alpha_{h}=\sum_{i=1}^{d}v_{ih}x_{i}, 输出层第 j个神经元接收到的输入为 \beta_{j}=\sum_{h=1}^{q}w_{hj}b_{h}, 其中 b_{h}为隐层第 h个神经元的输出. 假设隐层和输出层神经元都使用图 5.2(b)中的Sigmoid 函数.

 对训练例 (x_{k},y_{k}),假定神经网络的输出为 \hat{y}_{k}=(\hat{y}_{1}^{k},\hat{y}_{2}^{k},...,\hat{y}_{l}^{k}),即

\hat{y}_{j}^{k}=f(\beta_{j}-\theta_{j})        (5.3)

则网络在 (x_{k},y_{k})上的均方误差为

E_{k}=\frac{1}{2}\sum_{j=1}^{l}(\hat{y}_{j}^{k}-{y}_{j}^{k})^{2}        (5.4)

        图 5.7 的网络中有 (d+l+1)q +l个参数需确定: 输入层到隐层的 d\times q个权值、隐层到输出层的 q\times l个权值、 q个隐层神经元的阈值、 l个输出层神经元的阅值. BP是一个迭代学习算法, 在迭代的每一轮中采用广义的感知机学习规则对参数进行更新估计, 即与式(5.1)类似, 任意参数v的更新估计式为

v\leftarrow v+ \Delta v        (5.5)

下面我们以图 5.7 中隐层到输出层的连接权 w_{hj}为例来进行推导.

        BP算法基于梯度下降(gradient descent)策略,以目标的负梯度方向对参数进行调整. 对式(5.4)的误差 E_{k}, 给定学习率 \eta, 有

\Delta w_{hj}=-\eta \frac{\partial E_{k}}{\partial w_{hj}}        (5.6)

注意到 w_{hj}先影响到第 j个输出层神经元的输入值 \beta _{j}, 再影响到其输出值 \hat{y}_{j}^{k}, 然后影响到 E_{k}, 有

\frac{\partial E_{k}}{\partial w_{hj}}= \frac{\partial E_{k}}{\partial \hat{y}_{j}^{k}} \cdot \frac{\partial \hat{y}_{j}^{k}}{\partial \beta_{j}} \cdot \frac{\partial \beta_{j}}{\partial w_{hj}}        (5.7)

根据 \beta_{j}的定义,显然有

\frac{\partial \beta_{j}}{\partial w_{hj}}=b_{h}        (5.8)

图5.2中的Sigmoid 函数有一个很好的性质:

{f}'(x)=f(x)(1-f(x))        (5.9)

于是根据式(5.4)和(5.3),有

\begin{aligned} g_{j}&=-\frac{\partial E_{k}}{\partial \hat{y}_{j}^{k}} \cdot \frac{\partial \hat{y}_{j}^{k}}{\partial \beta_{j}} \\ &=-(\hat{y}_{j}^{k}-{y}_{j}^{k}){f}'(\beta_{j}-\theta_{j}) \\ &=\hat{y}_{j}^{k}(1-\hat{y}_{j}^{k})({y}_{j}^{k} - \hat{y}_{j}^{k}) \end{aligned}        (5.10)

        将式(5.10)和(5.8)代入式(5.7), 再代入式(5.6), 就得到了BP 算法中关于 w_{hj}的更新公式

\Delta w_{hj}=\eta g_{j}b_{h}        (5.11)

类似可得

\Delta \theta_{j}=-\eta g_{j}        (5.12)

\Delta v_{ih}=\eta e_{h}x_{i}        (5.13)

\Delta \gamma _{h}=-\eta e_{h}        (5.14)

式(5.13)和(5.14)中

\begin{aligned} e_{h}&=-\frac{\partial E_{k}}{\partial b_{h}} \cdot \frac{\partial b_{h}}{\partial \alpha_{h}} \\ &=-\sum_{j=1}^{l}\frac{\partial E_{k}}{\partial \beta_{j}} \cdot \frac{\partial E_{k}}{\partial b_{h}} {f}'(\alpha_{h}-\gamma_{h}) \\ &=\sum_{j=1}^{l} w_{hj} g_{j} {f}'(\alpha_{h}-\gamma_{h}) \\ &=b_{h}(1-b_{h})\sum_{j=1}^{l} w_{hj} g_{j} \end{aligned}        (5.15)

        学习率 \eta \in (0,1), 常设置\eta =0.1控制着算法每一轮选代中的更新步长, 若太大则容易振荡, 太小则收敛速度又会过慢. 有时为了做精细调节, 可令式(5.11) 与(5.12)使用 \eta_{1}, 式(5.13)与(5.14)使用 \eta_{2}, 两者未必必等.

        图5.8给出了BP算法的工作流程. 对每个训练样例, BP算法执行以下操作: 先将输入示例提供给输入层神经元,然后逐层将信号前传, 直到产生输出层的结果; 然后计算输出层的误差(第 4-5 行)再将误差逆向传播至隐层神经元(第 6行), 最后根据隐层神经元的误差来对连接权和阈值进行调整(第7行). 该迭代过程循环进行, 直到达到某些停止条件为止(停止条件与缓解 BP 过拟合的策略有关), 例如训练误差已达到一个很小的值. 图 5.9 给出了在2个属性、5个样本的西瓜数据上, 随着训练轮数的增加, 网络参数和分类边界的变化情况.

        需注意的是, BP 算法的目标是要最小化训练集 D上的累积误差

E=\frac{1}{m} \sum_{k=1}^{m}E_{k}        (5.16)

但我们上面介绍的“标准 BP 算法”每次仅针对一个训练样例更新连接权和阈值, 也就是说, 图 5.8 中算法的更新规则是基于单个的 E_{k}推导而得. 如果类似地推导出基于累积误差最小化的更新规则,就得到了累积误差逆传播(accumulated error backpropagation)算法. 累积BP算法与标准BP算法都很常用. 一般来说, 标准 BP 算法每次更新只针对单个样例, 参数更新得非常频繁, 而且对不同样例进行更新的效果可能出现“抵消”现象. 因此,为了达到同样的累积误差极小点, 标准BP 算法往往需进行更多次数的迭代, 累积BP算法直接针对累积误差最小化, 它在读取整个训练集D一遍后才对参数进行更新, 其参数更新的频率低得多. 但在很多任务中, 累积误差下降到一定程度之后, 进一步下降会非常缓慢, 这时标准 BP 往往会更快获得较好的解, 尤其是在训练集 D非常大时更明显.

        这里标准 BP 算法和累积 BP算法的区别类似于随机梯度下降(stochastic gradientdescent简称SGD)与标准梯度下降之间的区别.

        [Hornik et al,1989] 证明, 只需一个包含足够多神经元的隐层, 多层前馈网络就能以任意精度逼近任意复杂度的连续函数. 然而, 如何设置隐层神经元的个数仍是个未决问题, 实际应用中通常靠“试错法”(trial-by-error)调整.

        正是由于其强大的表示能力, BP 神经网络经常遭遇过拟合, 其训练误差持续降低, 但测试误差却可能上升. 有两种策略常用来缓解BP网络的过拟合. 第一种策略是“早停”(early stopping): 将数据分成训练集和验证集, 训练集用来计算梯度、更新连接权和阈值, 验证集用来估计误差, 若训练集误差降低但验证集误差升高, 则停止训练, 同时返回具有最小验证集误差的连接权和阈值. 第二种策略是“正则化”(regularization)[Barron,1991; Girosi et al, 1995], 其基本思想是在误差目标函数中增加一个用于描述网络复杂度的部分, 例如连接权与阈值的平方和. 仍令 E_{k}表示第k个训练样例上的误差, w_{i}表示连接权和阈值, 则误差目标函数(5.16)改变为

E=\lambda \frac{1}{m} \sum_{k=1}^{m}E_{k}+(1-\lambda) \sum_{i}w_{i}^{2}        (5.17)

其中 \lambda \in (0,1)用于对经验误差与网络复杂度这两项进行折中, 常通过交叉验证法来估计. 增加连接权与阈值平方和这一项后, 训练过程将会偏好比较小的连接权和阈值, 使网络输出更加“光滑”, 从而对过拟合有所缓解.

2、代码实现

使用Scikit-learn库

官网地址:API Reference — scikit-learn 1.3.0 documentation

2.1、使用MLPClassifier

详细的参数信息:sklearn.neural_network.MLPClassifier — scikit-learn 1.3.0 documentation

sklearn.neural_network.MLPClassifier 是使用神经网络做分类。

  1. from sklearn import datasets
  2. from sklearn import model_selection
  3. from sklearn import neural_network
  4. # 加载鸢尾花数据集
  5. X, y = datasets.load_iris(return_X_y=True)
  6. # 拆分 训练集 和 测试集
  7. X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, random_state=0)
  8. # 创建 多层感知器分类器
  9. mlp_cls = neural_network.MLPClassifier(hidden_layer_sizes=(100,), random_state=0, alpha=0.0001, max_iter=1000)
  10. # 训练数据
  11. mlp_cls.fit(X_train, y_train)
  12. # 评估模型得分 (准确率)
  13. print(mlp_cls.score(X_train, y_train)) # 训练集得分: 0.9821428571428571
  14. print(mlp_cls.score(X_test, y_test)) # 测试集得分: 0.9736842105263158

2.2、使用MLPRegressor

详细的参数信息:sklearn.neural_network.MLPRegressor — scikit-learn 1.3.0 documentation

sklearn.neural_network.MLPRegressor 是使用神经网络做回归。

  1. from sklearn import datasets
  2. from sklearn import model_selection
  3. from sklearn import neural_network
  4. # 加载/获取 加利福尼亚住房 数据集
  5. X, y = datasets.fetch_california_housing(return_X_y=True)
  6. # 把数据集拆分为 训练集 和 测试集
  7. X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, random_state=0)
  8. # 创建 多层感知器回归器
  9. mlp_reg = neural_network.MLPRegressor(hidden_layer_sizes=(100,), random_state=0, alpha=0.0001, max_iter=1000)
  10. # 训练模型
  11. mlp_reg.fit(X_train, y_train)
  12. # 评估模型 R方
  13. print(mlp_reg.score(X_train, y_train)) # 在训练集上的得分: 0.5041034703903609
  14. print(mlp_reg.score(X_test, y_test)) # 在测试集上的得分: 0.46688586880740435

3、想法

        了解神经网络的一些概念,后面才方便学习深度学习的一些算法。主要了解一些原理和公式,才能在调用现有的机器学习库的时候选取参数和调参。

        最后,觉得有帮助或者有点收获的话,帮忙点个赞吧!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/990454
推荐阅读
相关标签
  

闽ICP备14008679号