BP

关于反向传播

反向传播(英语:Backpropagation,缩写为BP)是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。该方法对网络中所有权重计算损失函数的梯度。这个梯度会反馈给最优化方法,用来更新权值以最小化损失函数。
反向传播要求有对每个输入值想得到的已知输出,来计算损失函数梯度。因此,它通常被认为是一种监督式学习方法,虽然它也用在一些无监督网络(如自动编码器)中。它是多层前馈网络的Delta规则的推广,可以用链式法则对每层迭代计算梯度。反向传播要求人工神经元(或“节点”)的激励函数可微。。

首先我们要初始化网络
每个神经元都有一组需要维持的权重。每个输入连接一个权重和偏置的额外权重。 我们需要在训练期间为神经元存储额外的属性,因此我们将使用字典来表示每个神经元并通过诸如权重的“weights”之类的名称来存储属性。
网络按层组织。 输入层实际上只是我们训练数据集的一行。 第一个真实图层是隐藏图层。接下来是输出层,每个类值都有一个神经元。
我们将层组织为字典数组,并将整个网络视为一个层数组。
最好将网络权重初始化为小的随机数。我们将使用0到1范围内的随机数。
下面是一个名为initialize_network()的函数,它创建了一个可供训练的新神经网络。它接收三个参数,分别是输入数量,隐藏层中的神经元数量和输出数量。
在这里插入图片描述
可以看到,对于隐藏层,我们创建了n_hidden个神经元,隐藏层中的每个神经元都有n_inputs + 1个权重,一个用于数据集中的每个输入列,另一个用于偏差。
我们还可以看到连接到隐藏层的输出层具有n_outputs个神经元,每个神经元具有n_hidden + 1个权重。这意味着输出层中的每个神经元都连接到隐藏层中每个神经元。
完整代码:
BP_第1张图片
运行后可以看到代码逐个打印出每个层。 可以看到隐藏层有一个具有2个输入权重和偏差的神经元。 输出层有2个神经元,每个神经元有1个权重加上偏差。

在这里插入图片描述

第二步是前项传播
我们可以通过在每层传播输入信号直到输出层输出其值来计算神经网络的输出,将此过程称为前向传播。
我们可以将传播分解为三个部分:
神经元激活。
神经元转移。
前向传播。
神经元激活:
第一步是计算给定输入的一个神经元的激活。
输入可以是我们的训练数据集中的一行,如隐藏层的情况。 在输出层的情况下,它也可以是隐藏层中每个神经元的输出。
神经元激活作为输入的加权和进行计算。
activation = sum(weight_i * input_i) + bias
当权重是网络权重时,input是输入,i是权重或输入的索引,bias是没有输入与之相乘的特殊权重
下面是一个名为activate()的函数的实现。 该函数假定偏差是权重列表中的最后一个权重。
在这里插入图片描述

神经元转移:
一旦神经元被激活,我们需要转移以查看神经元输出实际是什么。

可以使用不同的传递函数。 传统上使用sigmoid激活函数,但也可以使用tanh(双曲正切)函数来传输输出。
S形激活函数看起来像S形,它也称为逻辑函数。它可以取任何输入值并在S曲线上产生0到1之间的数字,它也是一个函数,我们可以很容易地计算出反向传播误差后我们将需要的导数(斜率)。
我们可以使用sigmoid函数传递激活函数,如下所示:
output = 1 / (1 + e^(-activation))
其中e是自然对数的基数
下面是一个名为transfer()的函数,它实现了sigmoid方程。
在这里插入图片描述

前项传播
向前传播一个输入很简单。
我们通过网络的每一层计算每个神经元的输出。来自一层的所有输出都成为下一层神经元的输入。
下面是一个名为forward_propagate()的函数,它使用我们的神经网络实现数据集中一行数据的前向传播。
可以看到神经元的输出值存储在神经元中,名称为“output”。还可以看到我们收集名为new_inputs的数组中的图层的输出,该数组成为名为Inputs的数组,并用作后续图层的输入。
该函数返回最后一层的输出,也称为输出层。
BP_第2张图片
完整的代码如下
BP_第3张图片
运行后会传播输入模式[1,0]并生成打印的输出值。因为输出层有两个神经元,所以我们得到两个数字的列表作为输出。
在这里插入图片描述
到目前为止实际输出值无意义,但接下来,我们将开始学习如何使神经元中的权重更有用。

第三步是反向传播
反向传播算法以训练权重的方式命名。
在预期输出和从网络传播的输出之间计算误差。然后,这些错误通过网络从输出层向后传播到隐藏层,为错误分配责任并随时更新权重。
反向传播误差的数学基础是微积分.

给定神经元的输出值,我们需要计算它的斜率。我们使用sigmoid传递函数,其导数可以计算如下:
derivative = output * (1.0 - output)
这个方程写在下面的函数了
在这里插入图片描述

误差反向传播的第一步是计算每个输出神经元的误差,这将使我们的误差信号(输入)通过网络向后传播。给定神经元的误差可以如下计算:
error = (expected - output) * transfer_derivative(output)
上式中expected是神经元的预期输出值,output是神经元的输出值,transfer_derivative()计算神经元输出值的斜率
隐藏层中神经元的误差信号被计算为输出层中每个神经元的加权误差。想象一下错误沿输出层的权重返回到隐藏层中的神经元。
累积反向传播的误差信号,然后用于确定隐藏层中神经元的误差,如下所示:
error = (weight_k * error_j) * transfer_derivative(output)
上式中error_j是来自输出层中第j个神经元的误差信号,weight_k是将第k个神经元连接到当前神经元的权重,output是当前神经元的输出。
下面是一个名为backward_propagate_error()的函数,它实现了这个过程。
可以看到delta存储着每个神经元计算的误差信号,网络层以相反的顺序迭代,从输出开始并向后工作。
我们还可以看到隐藏层中神经元的误差信号是从输出层中的神经元累积的,其中隐藏神经元数j也是输出层neuron[‘weights’] [j]中神经元权重的指数。
BP_第4张图片
完整的代码如下:
BP_第5张图片
运行后会在误差反向传播完成后打印网络。我们可以看到错误值被计算并存储在输出图层和隐藏图层的神经元中。
在这里插入图片描述

第四步是训练网络.
我们使用随机梯度下降训练网络。
这涉及将训练数据集暴露给网络以及向前传播输入的每行数据的多次迭代,反向传播错误并更新网络权重。
这部分分为两步:
更新权重。
训练网络。
首先是更新权重
一旦通过上述反向传播方法计算网络中每个神经元的误差,就可以使用它们来更新权重。
网络权重更新如下:
weight = weight + learning_rate * error * input
上式中weight是给定权重,learning_rate是指定的参数,error是由神经元的反向传播过程计算的误差,input是导致误差的输入值。
下面名为update_weights()的函数,它在给定输入数据行,learning rate的情况下更新网络的权重,并假设已经执行了前向和后向传播。
BP_第6张图片

接下来我们训练网络
我们使用随机梯度下降来更新网络。
下面的函数利用给定的训练数据集,learning rate,固定的epoch数目和期望的输出值数来实现已经初始化的神经网络的训练。
BP_第7张图片
完整的代码在4.py,代码中, 我们将在隐藏层中使用2个神经元。 这是一个二元分类问题(2个类),因此输出层中将有两个神经元。 该网络将被训练20个epoch,learning rate为0.5
给出数据进行测试
BP_第8张图片
结果如下
BP_第9张图片
运行后首先打印每个训练epoch的总和平方误差。我们可以看到这个误差的趋势随着每个epoch而减少。
一旦经过训练,就会打印网络,显示权重。 网络中还有输出和delta值,这些可以忽略。

第五步是预测
使用训练有素的神经网络进行预测很容易。
我们已经看到了如何向前传播输入模式以获得输出 这就是我们做出预测所需要做的。将此输出转换为清晰的预测可能更有用。我们可以通过选择具有更大概率的类值来做到这一点。
下面是一个名为predict()的函数,它实现了这个过程,返回网络输出中具有最大概率的索引。它假定类值已经转换为整数。
在这里插入图片描述
我们将它与上面的代码一起用于前向传播输入,并使用数据集来测试使用已经训练过的网络进行预测。
完整的代码在5.py
给出数据集
BP_第10张图片
运行结果中可以看到,打印了训练数据集中每条记录的预期输出然后是网络进行预测值。
结果表明网络在这个小数据集上达到了100%的准确率。
BP_第11张图片

反向传播算法的步骤已经结束了,接下里我们用反向传播处理实际问题.
数据集名为seeds_daatset.csv.数据集涉及从不同品种的小麦给出测量种子的物种的预测。共有201条记录和7个数字输入变量。这是一个有3个输出类的分类问题。每个数字输入值的比例不同,因此可能需要一些数据标准化以用于加权输入的算法,如反向传播算法。
第一步是加载数据集并将加载的数据转换为我们可以在神经网络中使用的数字。 为此,我们将使用辅助函数load_csv()来加载文件,使用str_column_to_float()将字符串数转换为浮点数,使用str_column_to_int()将类列转换为整数值。
BP_第12张图片
因为输入值的比例不同,所以需要归一化到0和1的范围。通常的做法是将输入值标准化为所选传递函数的范围,在这种情况下,输出0到1之间的值的sigmoid函数 datat_minmax()和normalize_dataset()辅助函数用于规范化输入值。
BP_第13张图片
我们将使用5倍折交叉验证来评估算法。 这意味着每个折中将有201/5 = 40.2或40个记录。我们将使用evaluate_algorithm()来使用交叉验证评估算法
BP_第14张图片
使用accuracy_metric()计算预测的准确性。
BP_第15张图片
back_propagation()首先初始化网络,在训练数据集上训练它,然后使用训练好的网络对测试数据集进行预测。
BP_第16张图片
完整代码在BP.py中
在代码中, 构建了隐藏层中有5个神经元,输出层中有3个神经元的网络。 该网络训练了500个epoch,learning rate为0.3。运行结果如下
在这里插入图片描述
打印了5个折各自的平均分类准确度以及所有折叠的平均性能。您可以看到实现了大约95%的平均分类精度

参考:
1.<机器学习实战>
2https://zh.wikipedia.org/wiki/%E5%8F%8D%E5%90%91%E4%BC%A0%E6%92%AD%E7%AE%97%E6%B3%95
3.<机器学习>(周志华的西瓜书)
4. https://machinelearningmastery.com/category/algorithms-from-scratch/

你可能感兴趣的:(AI)