BP神经网络思想及其Python实现
神经网络是一种模拟人类大脑工作方式的计算模型。它由神经元组成,这些神经元相互连接形成网络。每个连接都有一个权重,而神经元则通过激活函数处理输入并生成输出。神经网络可以分为输入层、隐藏层和输出层。在训练过程中,神经网络通过调整权重来学习模式和特征,使其能够进行预测或分类任务。这种学习过程通常依赖于反向传播算法,它通过比较网络输出和实际目标来调整权重。深度学习是神经网络的一种特殊形式,其包含多个深度的隐藏层。深度学习在图像识别、语音识别、自然语言处理等领域取得了显著的成就。卷积神经网络(CNN)用于图像处理,循环神经网络(RNN)用于序列数据,而转换器模型(如BERT)在自然语言处理中表现出色。神经网络的发展受益于大数据和强大的计算资源,推动了人工智能领域的快速发展。它被广泛应用于各种领域,如医疗诊断、金融预测和自动驾驶。
神经元 | 神经网络 |
---|---|
![]() |
![]() |
一、神经网络的发展和思想
1.1 神经网络的发展
神经网络的发展经历了几个关键阶段,从最初的概念到如今在各种领域取得巨大成功的深度学习。以下是神经网络发展的主要里程碑:
感知机和早期模型(1943-1960年代): 神经网络的起源可以追溯到上世纪四五十年代,当时Warren McCulloch和Walter Pitts提出了感知机模型,这是一种模拟神经元工作的数学模型。然而,由于感知机存在限制,无法解决一些复杂的问题,神经网络的发展在此时停滞了一段时间。
误差反向传播算法的引入(1970-1980年代): 在这一时期,人们提出了误差反向传播算法,使得神经网络能够更有效地学习和调整权重。这一算法的引入推动了神经网络的再次崛起,但由于当时计算资源有限,神经网络仍然面临训练时间长、性能不佳等问题。
支持向量机和神经网络的衰退(1990-2000年代): 在这段时间内,支持向量机等其他机器学习方法的兴起导致了对神经网络的相对忽视。人们认为神经网络在解决复杂问题上存在限制,因此研究重心转向了其他算法。
深度学习的复兴(2010年至今): 随着大数据的涌现和计算能力的飞速增长,深度学习重新焕发了人们对神经网络的兴趣。深度学习模型,尤其是深度卷积神经网络(CNN)和循环神经网络(RNN),在图像识别、语音识别、自然语言处理等领域取得了巨大成功。此时的神经网络模型变得更加深层,参数更多,能够更好地捕捉和理解复杂的数据模式。
迁移学习、生成对抗网络和注意力机制的兴起(2010年至今): 随着深度学习的发展,一些新的技术和概念被引入,如迁移学习、生成对抗网络(GAN)和注意力机制。这些方法进一步提高了神经网络在各种任务中的性能,使其更加灵活和适用于不同领域。
神经网络的发展不仅推动了人工智能领域的进步,也改变了许多行业的面貌。然而,尽管取得了显著成就,神经网络仍然面临一些挑战,如对大量标注数据的依赖、模型的解释性不足等问题,
1.2 神经网络算法思想
神经网络是一种模拟人脑神经元网络结构的计算模型,其核心思想是通过学习从输入到输出之间的映射关系,以识别模式、进行预测或执行分类任务。以下是神经网络算法的主要思想:
神经元模型: 神经网络的基本组成单元是神经元,它模拟生物神经元的基本功能。每个神经元接收多个输入,通过加权求和后经过激活函数得到输出。这个输出被传递到下一层的神经元,形成网络。
前馈传播: 神经网络通常是分为输入层、隐藏层和输出层。信息从输入层经过隐藏层传递到输出层的过程称为前馈传播。在传播的过程中,每个神经元的输出成为下一层神经元的输入,通过不断传递,网络最终产生输出。
权重调整: 在神经网络中,每个连接都有一个权重,决定了信息在传递过程中的重要性。神经网络的学习过程就是通过调整这些权重,使网络能够对输入数据进行准确的预测。常用的学习算法包括梯度下降和误差反向传播。
激活函数: 激活函数在神经网络中起到引入非线性的作用。常见的激活函数包括Sigmoid、Tanh和ReLU(Rectified Linear Unit)。这些函数帮助神经网络捕捉数据中的非线性关系,使得网络能够更好地适应复杂的模式。
误差反向传播: 在训练神经网络时,通过计算模型输出与实际值之间的误差,利用链式法则将误差从输出层向输入层进行反向传播。这一过程中,根据误差调整权重,使得网络的输出更加接近真实值,从而不断提高网络的性能。
深度学习和深层网络: 随着深度学习的发展,神经网络变得更深、更复杂。深度学习模型包括多个深度的隐藏层,通过多层次的特征提取和抽象,使网络能够学到更加高级和抽象的特征,适用于处理复杂的问题。
优化算法: 为了更有效地训练神经网络,各种优化算法被引入,如随机梯度下降(SGD)、Adam等。这些算法帮助网络更快地收敛到最优解,提高学习效率。
总体而言,神经网络的算法思想在于通过学习数据中的模式和特征,建立输入与输出之间的映射关系,以实现各种任务的自动化处理。这一思想的成功应用推动了人工智能领域的快速发展。
流程图 | 数据集 |
---|---|
![]() |
![]() |
二、BP神经网络算例
2.1 BP神经网络算法
BP神经网络有下面特点:
(i)前馈型网络
各神经元接受前一层的输入,并输出给下一层,没有反馈。结点分为两类,即输入单元和计算单元,每一计算单元可有任意个输入,但只有一个输出(它可耦合到任意多个其它结点作为其输入)。通常前馈网络可分为不同的层,第层的输入只与第层输出相连,输入和输出结点与外界相连,而其它中间层则称为隐层。
(ii)反馈型网络
所有结点都是计算单元,同时也可接受输入,并向外界输出。神经网络的工作过程主要分为两个阶段:第一个阶段是学习期,此时各计算单元状态不变,各连线上的权值可通过学习来修改;第二阶段是工作期,此时各连接权固定,计算单元状态变化,以达到某种稳定状态。从作用效果看,前馈网络主要是函数映射,可用于模式识别和函数逼近。反馈网络按对能量函数的极小点的利用来分类有两种:第一类是能量函数的所有极小点都起作用,这一类主要用作各种联想存储器;第二类只利用全局极小点,它主要用于求解最优化问题。
(iii)向后传播算法(Back-Propagation)
对于反馈型网络所说的各连线上权值的修改,主要运用了向后传播算法(Back-Propagation),这也是三层BP神经网络模型的核心部分。希望对应学习样本的输出非常精确,但实际上是不可能的只能希望实际输出尽可能地接近理想输出。为清楚起见,把对应于样本 的理想输出记为 ,那么
度量了在一组给定的权下,实际输出与理想输出的差异,由此,寻找一组恰当的权的问题,自然地归结为求适当 的值,使 达到极小的问题。
得到隐含层和隐含层到输出层的权值。也就是说,图中所表示的BP神经网络,它的输入层神经元(节点)个数为 ,隐含层神经元(节点)个数为 ,输出层神经元 (节点)个数为l,这种结构称为 结构的三层BP神经网络。(神经网络大多数情况下被用于解决分类问题,使用神经网络训练数据之前,必须确定神经网络的层数,以及每层神经元的个数。在数据集被传入输入层时为了加速神经网络的学习过程通常将数据标准化到0-1之间。输入层神经元数的确定:由数据集数据种类确定,输入层的神经元数量通常等于类别的数量,比如西瓜色泽A可能取三个值乌黑,青绿,浅白,那么就可以设定输入层神经元数为3,如果输入数据为乌黑(A=乌黑),那么代表乌黑色的神经元就取1,其他两个神经元取0;输出层神经元数的确定:对于分类问题,如果是2类,可以用一个输出单元表示(0和1分别代表2类)如果多余2类,每一个类别用一个输出单元表示;隐藏层神经元数的确定:没有明确的规则来设计最好有多少个隐藏层,根据实验测试和误差,以及准确度来实验并改进)
- 步骤 1: 网络初始化。根据输入 和期望输出 来确定网络输入层、隐含层和输出层神经元 (节点) 个数,初始化各层神经元之间的连接权值 ,初始化隐含层阈值 ,输出层阈值 ,给定学习速率和神经元传递函数。
- 步骤 2: 隐含层输出计算。根据输入向量 ,输入层和隐含层间连接权值 以及隐含层阈值 ,计算隐含层输出。
即
式中, 为隐含层节点数(可用估计,为0-10之间的常数); 为隐含层传递函数。这里我们采用传递函数为
- 步骤 3: 输出层输出计算。根据隐含层输出 ,连接权值 和阈值 ,计算 神经网络的实际输出 。
- 步骤 4: 误差计算。根据网络实际输出 与期望输出 ,计算网络总体误差 。
- 步骤 5: 权值更新。根据网络总体误差 ,按照以下公式更新网络连接权值 。
令
由步骤4误差公式可知,网络误差是各层权值的函数,因此调整权值可以改变误差。显然,调整权值的原则是使错误不断的减小,因此应使权值的调整量与误差的梯度的下降成正比,即:
式子中,负号表示梯度下降,常数 表示比例系数,在训练中反映了学习速率。可以看出,BP算法属于 学习规则类,这类算法常被称为误差的梯度下降算法。就得
其中 ,式中 为学习速率。
- 步骤6: 判断算法迭代是否结束 (可用网络总误差是否达到精度要求等方式来判断),若没有结束,返回步骤2。
BP网络的核心步骤如下图,实线表示正向传播,虚线表示反向传播。
2.2 BP算例
BP算法总共分为两个部分,第一个部分是FP(前馈计算计算误差)过程,我们用来计算误差;第二个部分是BP(反馈计算更新权重),我们用来更新权重。
神经网络实例 | 激活函数 |
---|---|
![]() |
![]() |
神经网络结构见上图,其中是这个神经网络的输入层,是这里的隐藏层,是我这个神经网络的输出层,其中表示权重,表示偏置项(可以理解为一次函数中的中的常数项,在这里我们取,其实我们可以取任意值,在此不影响结论),激活函数为。为了方便更直观的解释,我们来设定一下权重值和偏置项的初始值:
权值 | 权值 | 权值 | 权值 | 权值 | 权值 |
---|---|---|---|---|---|
FP(前馈计算计算误差)过程:
下面我们就来进行前馈计算:首先我们以为例:隐层神经元有2个输入,总输入记作net(h1),net(h1)经过sigmoid函数激活之后,可以得到Out(h1)这就是我们隐藏层的一个输出结果。下面我们来进行计算h1的总输入:
(你可以发现, h1是由w1和w2 连接而成的),然后经过sigmoid函数激活之后我们可以得到。同理可得:
有了这三个数值,我们可以算出输出层o1,o2的总输入:
经过sigmoid函数激活之后,我们可以得到:
同理,可得:
然后,我们可以得到总误差,这里我们记作Etotal(这里我们将Out(h1), Out(h2) 简称为 o1,o2):
上面的是为了后面反馈计算方便而添加的。到此为止,我们已经完成了前馈计算,并且算出了总误差值。
BP(反馈计算更新权重):
- 更新(hidden layer ----- Output layer)
这里的BP过程,我们是用来更新的值,使预测结果更加精确。在此,我们以为例,这里我们需要用到高等数学里的链式法则,与下列因素相关:
根据涟式法则。我们可得:
其中, 等式右边第一项等于:
第二项等于:
第三项等于:
所以,我们可以得到总式:
最后,我们求得 的更新结果:
同理,我们可得:
- 更新(Input layer ----hidden layer)
这里我们以为例:这里还是应用高等数学里的链式法则,与下列因素有关:
所以,我们得到求导公式:
这里以对的求导为例:
同理可得EO2对Outh1的求导公式:
所以我们求得更新后的 的值:
同理可得 (w1-w6):
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
w = [0, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65]
b = [0, 0.35, 0.65]
l = [0, 5, 10]
def sigmoid(z):
return 1.0 / (1 + np.exp(-z))
def bp(w, b, l):
# 1. 前向传播计算预测值与误差
h1 = sigmoid(w[1] * l[1] + w[2] * l[2] + b[1])
h2 = sigmoid(w[3] * l[1] + w[4] * l[2] + b[1])
h3 = sigmoid(w[5] * l[1] + w[6] * l[2] + b[1])
o1 = sigmoid(w[7] * h1 + w[9] * h2 + w[11] * h3 + b[2])
o2 = sigmoid(w[8] * h1 + w[10] * h2 + w[12] * h3 + b[2])
e = np.square(0.01 - o1) / 2.0 + np.square(0.99 - o2) / 2.0
# 2. 后向传播, 更新权重 W
t1 = -(0.01 - o1) * o1 * (1 - o1)
t2 = -(0.01 - o2) * o2 * (1 - o2)
w[7] = w[7] - 0.5 * (t1 * h1)
w[9] = w[9] - 0.5 * (t1 * h2)
w[11] = w[11] - 0.5 * (t1 * h3)
w[8] = w[8] - 0.5 * (t2 * h1)
w[10] = w[10] - 0.5 * (t2 * h2)
w[12] = w[12] - 0.5 * (t2 * h3)
w[1] = w[1] - 0.5 * (t1 * w[7] + t2 * w[8]) * h1 * (1 - h1) * l[1]
w[2] = w[2] - 0.5 * (t1 * w[7] + t2 * w[8]) * h1 * (1 - h1) * l[2]
w[3] = w[3] - 0.5 * (t1 * w[9] + t2 * w[10]) * h2 * (1 - h2) * l[1]
w[4] = w[4] - 0.5 * (t1 * w[9] + t2 * w[10]) * h2 * (1 - h2) * l[2]
w[5] = w[5] - 0.5 * (t1 * w[11] + t2 * w[12]) * h3 * (1 - h3) * l[1]
w[6] = w[6] - 0.5 * (t1 * w[11] + t2 * w[12]) * h3 * (1 - h3) * l[2]
return o1, o2, w, e
for i in range(101):
o1, o2, w, e = bp(w, b, l)
print('第 {} 次迭代: 预测值: ({}, {}),总误差: {},权重系数: {}'.format(i, o1, o2, e, w))
三、Python实现
# -*- coding: UTF-8 -*-
# 1-导入包库
from sklearn import datasets
import numpy as np
import matplotlib.pyplot as plt # Correct import statement for Matplotlib
import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import SGD
# 2-导入数据
X = datasets.load_iris().data # 特征
y = datasets.load_iris().target # 标签
# 3-数据乱序
np.random.seed(116)
np.random.shuffle(X)
np.random.seed(116)
np.random.shuffle(y)
tf.random.set_seed(116)
# 4-切分数据
X_train = X[:-30]
y_train = y[:-30]
X_test = X[-30:] # 最后30条数据
y_test = y[-30:]
# 5-数据类型转换
X_train = tf.cast(X_train, tf.float32)
X_test = tf.cast(X_test, tf.float32)
# 6-建立模型
model = Sequential([
Dense(5, activation='relu', input_shape=(4,)), # Hidden layer with 5 neurons
Dense(3, activation='softmax') # Output layer with 3 neurons (for 3 classes)
])
# 7-编译模型
lr = 0.1
model.compile(optimizer=SGD(learning_rate=lr),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 8-训练模型
epoch = 300
history = model.fit(X_train, y_train, epochs=epoch, batch_size=32)
# 9-可视化
plt.title('Loss Function Curve') # 图片标题
plt.xlabel('Epoch') # x轴变量名称
plt.ylabel('Loss') # y轴变量名称
plt.plot(history.history['loss'], label="Loss")
plt.legend() # 画出曲线图标
plt.show() # 画出图像
# 10-评估模型
test_loss, test_acc = model.evaluate(X_test, y_test)
print("Test Loss:", test_loss)
print("Test Accuracy:", test_acc)
# 11-混淆矩阵
y_pred = np.argmax(model.predict(X_test), axis=1)
conf_mat = tf.math.confusion_matrix(labels=y_test, predictions=y_pred)
conf_mat = conf_mat.numpy()
# 显示混淆矩阵
print("Confusion Matrix:")
for i in range(conf_mat.shape[0]):
for j in range(conf_mat.shape[1]):
print(conf_mat[i, j], end='\t')
print()
损失函数曲线 | 混淆矩阵 |
---|---|
![]() |
![]() |
四、算法评价
神经网络是一种强大的机器学习模型,广泛应用于图像识别、自然语言处理和其他领域。在评价神经网络的计算结果时,接收操作特征曲线(Receiver Operating Characteristic Curve,ROC曲线)是一种常用的工具。接收操作特征曲线(Receiver Operating Characteristic Curve,ROC曲线)是一种用于评估分类模型性能的强大工具,尤其在神经网络应用中备受关注。这条曲线通过显示在不同阈值下真正例率(True Positive Rate,TPR,又称敏感性)与假正例率(False Positive Rate,FPR)之间的关系,为深入了解和评价模型的性能提供了全面的视角。ROC曲线的构建涉及复杂的统计计算,以下是关键的计算公式和解释。
- 真正例率(True Positive Rate,TPR,敏感性): ,其中,TP是真正例的数量,FN是假负例的数量。TPR度量了模型对真正例的识别能力。在计算过程中,真正例率的增加意味着模型更有效地捕获了实际正例。
- 假正例率(False Positive Rate,FPR): ,其中,FP是假正例的数量,TN是真负例的数量。FPR衡量了模型将负例错误分类为正例的程度。较低的FPR表示模型在负例上的性能更好。
- 阈值变化: ROC曲线的生成基于模型输出的连续值,并通过改变分类阈值来计算不同阈值下的TPR和FPR。通过调整阈值,可以实现对模型性能的定制化评估,平衡灵敏性和特异性。
- 曲线下面积(AUC): ,ROC曲线下的面积(AUC)是一个综合性的度量,用于评估模型在所有可能阈值下的性能。AUC值越接近1,表示模型性能越优越。
- 随机分类线: ROC曲线的随机分类线为对角线,代表模型没有区分能力。因此,AUC值为0.5时表示模型性能等同于随机猜测,而AUC越大则说明模型性能越好。
综合而言,ROC曲线和相关的计算指标为评价神经网络等机器学习模型提供了直观、可解释的性能评估方式。通过分析不同阈值下的TPR和FPR,以及AUC值,我们能够更深入地理解模型的分类能力,为模型的改进和优化提供有力支持。这种全面的性能评估方法在各个应用领域都具有广泛的实用性。
总结
神经网络是一种受到生物神经系统启发的计算模型,用于机器学习和人工智能领域。它由多个神经元组成的层次结构构成,分为输入层、隐藏层和输出层。神经网络通过学习数据的模式和特征来执行各种任务。在神经网络中,每个神经元都与下一层的神经元连接,并具有权重,这些权重在学习过程中进行调整。神经网络的学习是通过反向传播算法实现的,该算法根据预测结果的误差调整权重,从而不断提高网络性能。
神经网络在图像识别、语音识别、自然语言处理等领域取得显著成果。深度学习是神经网络的一个分支,通过多个深层次的隐藏层进行复杂特征的学习,提高了网络的表达能力。然而,神经网络也面临一些挑战,如需要大量标记数据、计算资源消耗大等问题。研究者们不断提出新的结构和算法来改进神经网络的性能,促使其在更多领域取得成功。神经网络作为人工智能的核心技术之一,对未来科技发展具有深远影响,将继续在各个领域发挥重要作用。
参考文献
权值更新推导过程
对于输入层,有:
对于输出层,有:
对于隐层,有:
上述两式中,激活函数 均为单极性Sigmoid函数:
具有连续、可导的特点,且有:
当网络输出与期望输出不等时,存在输出误差,定义如下:
将以上误差定义式展开至隐层,有:
进一步展开至输出层,有:
由上式可知,网络误差是各层权值的函数,因此调整权值可以改变误差。显然,调整权值的原则是使错误不断的减小,因此应使权值的调整量与误差的梯度的下降成正比,即:
式子中,负号表示梯度下降,常数 表示比例系数,在训练中反映了学习速率。可以看出,BP算法属于 学习规则类,这类算法常被称为误差的梯度下降算法。
1986年,认知心理学家McClelland和Rumelhart在神经网络训练中引入了 规则,该规则也可以称为连续感知器学习规则。 学习规则是一种利用梯度下降法的一般性的学习规则。
以二次损失函数为例:
误差 是权向量 的函数,我们可以使用梯度下降法来最小化 的值:
BP算法推导
公式(1)仅是对权值调整思路的数学表达,而不是具体的权值调整的计算式。下面推导三层BP算法权值调整的计算式。事先约定,在全部推导过程中,对输出层均有 ; 对隐层均有
对于输出层,公式(1)可写成
对隐层,公式(1)可以写成
对输出层和隐层各定义一个误差信号,令:
综合将公式(2)的权值调整公式改写为:
综合将公式(3)的权值调整公式改写为:
可以看出,只要计算出误差信号,权值调整量的计算推导即可完成
对于输出层, 可以展开为:
对于隐层, 可以展开为
下面求式子(4)和(5)中网络误差对各层输出的偏导。
对于输出层,基于输出误差,可得
对于隐层,利用输出误差,可得
将结果带入到公式(4)和公式(5)中,得
至此,两个误差信号的推导已经完成,得到三层感知器的BP学习算法权值调整计算公式为
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!