这篇文章中,我将简单介绍下与神经网络有关的东西,包括它的基本模型,典型的算法以及与深度学习的联系等内容。

一、神经元

神经网络是由许多个神经元组成的,在生物的神经网络中,就是神经元间相互连接,传递信号,改变其的电位;并且在某神经元的电位超过一个“阈值”后就会被激活,也就是会“兴奋”起来,而再向其他神经元发送化学物质。而对于生物神经网络进行抽象就会得到“M-P神经元模型”。如下图,就可以说是一个神经元模型:

其中,input表示输入,weight表示权重,就是神经元接收信号时的权重,而bias则是一个偏置项,用来调整拟合程度。

在神经网络中,大部分神经元总是存在一个激活函数,它可以控制输出范围,不同激活函数有不同的输出范围,就像sigmoid函数,它就可以将输出结果控制在0到1间,此外,激活函数还可以影响梯度计算、以及可以引入非线性因素等,从而可以影响权重的计算方式以及使得神经网络可以逼近任意复杂度的函数计算等。

二、感知机

1.1 感知机

如果用两层神经元进行组合,就可以等到“感知机”。它能容易地实现与、或、非操作。不过,我们要知道这些与、或、非操作都是线性可分的,如果是非线性可分的话,则要考虑多层功能神经元了。如下图,就是一个简单的用graphviz画的感知机模型:

其中,x1,x2所在层就是输入层,它们指向的就是输出层。

画出它的代码如下:

from graphviz import Digraph
from imageio import imread
import matplotlib.pyplot as plt


ax = plt.gca()
mygraph = Digraph(node_attr={'shape':'circle'},edge_attr={'labeldistance':'10.5'},format="png")
mygraph.node("0","x1")
mygraph.node("1","x2")
mygraph.node("2"," ")
mygraph.node('output'," ", color='none', style='filled', fillcolor='none')
mygraph.edge("0","2",label="w1")
mygraph.edge("1","2",label="w2")
mygraph.edge("2","output", label="y")
mygraph.render("tmp")
ax.imshow(imread("tmp.png"))
ax.set_axis_off()
plt.show()

在这个感知机中,当前的输出可以看为\hat{y},而对于训练样例(x,y)中,则可以发生这样一个调整:

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

其中的η可以被称为“学习率”。从中,我们可以发现,如果对于样例的预测正确,那么感知机就不会发生变化,反之则将会对于错误的程度将感知机的权重进行调整。

1.2 多层前馈神经网络

如果我们在感知机的基础上加入了一层或多层的隐藏层,那么这个神经网络模型就会变为“多层前馈神经网络”。其中,输入层神经元会接收外界的输入,隐藏层则会对信号进行加工,最终输出层进行输出.

三、BP算法

BP算法也叫误差逆传播算法,它是指先由前到后正常地传播一次,然后计算误差得到损失函数,然后再向后传播,并将神经元的权重进行更新,如此这样迭代到目标次数,或是某一值的最低标准。

在如图的一个神经网络模型中,x层为输入层,b层的隐藏层,y层为输出层。

那么在图中的第h个隐藏神经元的输入就是:\alpha _{h}=\sum_{i=1}^{d}v_{ih}x_{i},在第j个输出神经元的输入为:\beta _{j}=\sum_{h=1}^{q}w_{hj}b_{h}。网络在(x_{k},y_{k})上就会存在一个均方误差:E_{k}=\frac{1}{2}\sum_{j=1}^{l}(\hat{y}_{j}^{k}-y_{j}^{k})^2

BP算法的目标是要最小化训练集D上的累计误差,所有可以有:E=\frac{1}{m}\sum_{k=1}^{m}E_{k}。在标准BP算法中,更新的规则是基于单个的E_{k}推导而来的,如果推导出这样的累计误差,那么就得到了累计误差逆传递算法。标准BP算法与累计BP算法都会经常用到,但标准算法只针对单个的样例,所以参数会更新的很频繁,而导致出现“抵消”现象,所以为此标准算法就需要更多的迭代次数。

我们回到刚才的神经网络模型中,我们在知道了E_{k}后就可以算得\bigtriangleup w_{hj},可以说它由两部分组成,一部分是学习率η,另一部分是\frac{\partial E_{k}}{\partial w_{hj}},不过与这整体的是反比的关系就是说要在它俩组合后的式子前加上负号。对于它的第二部分,即\frac{\partial E_{k}}{\partial w_{hj}},我们可以将之分解,具体的可以参考西瓜书P103的公式,在分解后又可以分为两部分,一部分因为sigmoid的特殊性质,即其导数等于原函数与1减原函数的积而可变形为:-g_{i}=\hat{y}_{j}^{k}(1-\hat{y}_{j}^{k})(y_{j}^{k}-\hat{y}_{j}^{k}),而另一部分则变为b_{n},如此考虑之前的学习率部分,整体就会是这样:

\bigtriangleup w_{hj}=\eta g_{i}b_{h}

同样的,我们可以陆续得到:\bigtriangleup\theta _{j}\bigtriangleup v_{ih}

BP算法有着强大的表示能力,但也因此时常发生过拟合的问题,所以为了解决这个问题,有两个策略,一是“早停”,二是“正则化”,在早停策略中,是将数据集分为训练集与验证集,其中的验证集用来估计误差,如果训练集的误差降低,但验证集的误差反而上升时,那么就要停止训练了,并返回最小验证集误差的连接权与阈值;而正则化则是对于误差目标函数进行改造,往其中增加一个用于描述网络复杂程度的部分。

四、全局最小与局部最小

用E来表示神经网络上的误差时,神经网络的训练过程就可以看作是一个参数寻优过程,去寻找一个最优参数使得E最小。但此时,在训练中会遇到局部最小,而局部最小不一定是全局最小,我们要找的则是全局最小,所以此时可能就会寻找错误,为此我们有一些算法来帮助我们跳出这个局部最小来,这些算法分别是模拟退火算法、遗传算法、随机梯度下降算法以及以多组不同参数值来初始多个神经网络并从结果中寻找答案。

五、其他神经网络

除了上述的神经网络模型外,还有以下这些神经网络:

5.1 RBF网络

RBF网络也叫径向基函数,它是一种单隐层前馈神经网络,广泛应用于模式识别、函数逼近和分类问题中。RBF网络利用径向基函数作为隐藏层的激活函数,这些函数通常是对称的,如高斯函数。其中高斯函数的形式如下:

5.2 ART网络

ART网络也叫自适应谐振理论网络,它是竞争型学习的重要代表,它由比较层、识别层、识别阈值和重置模块这四部分组成。其中关于竞争型学习,其核心思想是让网络中的神经元为一个给定的输入样本“竞争”,以决定哪个神经元应该被激活。在这一过程中,最接近输入样本的神经元(通常称为获胜神经元)会得到强化,而其他神经元则不会更新或更新程度较小。

5.3 SOM网络

SOM网络也叫自组织映射网络,也是一种竞争型学习的无监督神经网络,它能将高维输入数据映射到低维空间中,并同时保持输入数据在高维空间的拓扑结构。

5.4 级联相关网络

级联相关网络是一种人工神经网络架构。它的设计目的是克服传统多层感知器(MLP)在训练过程中遇到的一些问题,如容易陷入局部极小值、训练速度慢等。级联相关网络的特点在于它可以动态地增加隐藏单元,并且保证每次增加单元后,网络性能都有所提升。

也就是说,在寻常的神经网络中,其网络模型结构通常是固定的,而在这个网络中,网络结构也会是学习的目标之一,所以在学习的过程中,该网络会增加一些隐藏节点,因此,它无需设置网络层数、隐藏神经数目,且训练速度也较快,但相对的,它在数据较小时容易发生过拟合。

5.5 Elman网络

如果我们在前馈神经网络的基础上增加了递归的部分,那么就诞生了“递归神经网络”。而Elman网络就是最常见的递归神经网络之一。其结构如图:

六、深度学习

深度学习是神经网络的一个子领域,专注于构建和训练深层神经网络(具有多个隐藏层的神经网络)。深度学习的目标是通过大量的数据和计算资源来学习复杂的特征表示,从而实现更高级别的任务。

深度学习继承了传统神经网络的基本架构和训练方法,并在此基础上进行了扩展和改进。可以说深度学习就是具有更多隐藏层的神经网络。

七、python代码

最后,我们还是用神经网络算法在iris数据集上直接引用aklearn函数库来实践下,代码如下:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, classification_report

# 加载数据并分割
iris = load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=42)

# 数据预处理
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# 构建神经网络
mlp = MLPClassifier(hidden_layer_sizes=(10, 10), max_iter=1000)
mlp.fit(X_train,y_train)

# 预测与评估
y_pre = mlp.predict(X_test)
accuracy = accuracy_score(y_test,y_pre)
report = classification_report(y_test,y_pre)
print("The accuracy is: {}".format(accuracy))
print("The report is: {}".format(report))

其结果如下:

The accuracy is: 1.0
The report is:               precision    recall  f1-score   support

           0       1.00      1.00      1.00        15
           1       1.00      1.00      1.00        11
           2       1.00      1.00      1.00        12

    accuracy                           1.00        38
   macro avg       1.00      1.00      1.00        38
weighted avg       1.00      1.00      1.00        38

(补充:在这篇文章中,整体的结构与介绍都与西瓜书的无异,因为这篇就是根据我这几日自学西瓜书时所作的笔记来写的,所以有些不同的地方是我自己的想法,故而可能会有差错,希望见到的人能告知于我)

此上

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐