使用numpy实现BP神经网络(python代码细节展示)

BP神经网络

算法:后向传播,使用后向传播算法,学习分类或预测的神经网络
输入:
.D: 由训练元祖和其相关联的目标值组成的数据集
L:学习率
输出:训练后的神经网络

本文简单以回归问题进行学习,故输出层的激励函数设置为f(x)=x
bp1

import numpy as np 
class BPNetwork(object):
    def __init__(self, input_nodes, hidden_nodes, output_nodes, learning_rate):
        # 设定输入层、隐藏层、输出层的节点数nodes、学习率
        self.input_nodes = input_nodes
        self.hidden_nodes = hidden_nodes
        self.output_nodes = output_nodes
        self.lr = learning_rate
        # 为了方便理解,在此将输入设置为mnist数据实例,方便理解各个数据的shape
        # 则input_nodes=784,hidden_nodes=32, output_nodes=64
        # 设定权重值
        # w_in2hid.shape=(32,784)
        self.w_in2hid = np.random.normal(0.0, self.hidden_nodes ** -0.5, (self.hidden_nodes, self.input_nodes))
        # w_hid2out.shape=(64,32)
        self.w_hid2out = np.random.normal(0.0, self.output_nodes ** -0.5, (self.output_nodes, self.hidden_nodes))
        # 激活函数(logistic函数)
        self.act_func = (lambda x: 1/(1+np.exp(-x)))

bp2
bp3

    def train(self, inputs_org, groundtruth_org):
        # 将输入转化为2d矩阵,输入向量的shape为[feature_dimension,1]
        # input.shape=(784,1)
        inputs = np.array(inputs_org, ndmin=2).T  
        # groundtruth.shape=(64,1)
        groundtruth = np.array(groundtruth_org, ndmin=2).T  
        # 前向传播
        # hid_ints.shape=(32,1)
        hid_ints = np.dot(self.w_in2hid, inputs)  
        # hid_outs.shape=(32,1)
        hid_outs = self.act_func(hid_ints)  
        # 输出层(激活函数设置为f(x) = x)
        # out_ints.shape=(64,1)
        out_ints = np.dot(self.w_hid2out, hid_outs)  
        # out_outs.shape=(64,1)
        out_outs = out_ints  
        # 反向传播
        # out_error.shape=(64,1)
        out_error = out_outs - groundtruth 
        # hid_error.shape=(1,32)
        hid_error = np.dot(out_error.T, self.w_hid2out) * (hid_outs * (1-hid_outs)).T 
        # 上式中((1,64).(64,32))*((32,1)*(32,1)).T=(1,32)
        # 更新权重
        # 更新w_hid2out
        self.w_hid2out += out_error * hid_outs.T * self.lr # shape=(64,32)
        self.w_in2hid += (inputs * hid_error * self.lr).T  # shape=(32,784)

进行预测

    def run(self, inputs_org):
        inputs = np.array(inputs_org, ndmin=2).T
        # 实现前向传播
        hid_ints = np.dot(self.w_in2hid, inputs)
        hid_outs = self.act_func(hid_ints)
        # 输出层
        out_ints = np.dot(self.w_in2hid, hid_outs)
        out_outs = out_ints

        return out_outs
知识点漏洞总结:
numpy中的中的高斯分布的概率密度函数np.random.normal()

其中,np.random.normal(mean=0.0, stdev=1.0, size=None)
loc表示均值,scale是标准差(scale越大,越矮胖),size表示返回多少个高斯值。
np.array()创建新的数组

网络初始化总结:

以下转载自谷歌工程师:聊一聊深度学习的weightinitialization

可行的几种初始化方式:

(1)pre-training

pre-training是早期训练神经网络的有效初始化方法,一个便于理解的例子是先使用greedy layerwise auto-encoder贪婪的分层自动解码器做unsupervised pre-training,然后再做fine-tuning。
pre-training阶段,将神经网络中的每一层取出,构造一个auto-encoder做训练,使得输入层和输出层保持一致。在这一过程中,参数得以更新,形成初始值
fine-tuning阶段,将pre-train过的每一层放回神经网络,利用pre-train阶段得到的参数初始值和训练数据对模型进行整体调整。在这一过程中,参数进一步被更新,形成最终模型。
随着数据量的增加以及activation function的发展,pre-training的概念已经渐渐发生变化。目前,从零开始训练神经网络时我们也很少采用auto-encoder进行pre-training,而是直奔主题做模型训练。不想从零开始训练神经网络时,我们往往选择一个已经训练好的在任务A上的模型(称为pre-trained model),将其放在任务B上做模型调整(称为fine-tuning)。

(2)random initialization

一旦随机分布选择不当,就会导致网络优化陷入困境

(3)Xavier initialization

该篇博客解释推导的很清楚,参见深度学习——Xavier初始化方法
Xavier initialization可以解决上面的问题!其初始化方式也并不复杂。Xavier初始化的基本思想是保持输入和输出的方差一致,这样就避免了所有输出值都趋向于0
让一个神经元的输入权重的(当反向传播时,就变成输出了)的方差等于:1/输入的个数;这样做的目的就是可以让信息在网络中均匀地分布一下。对于权值的分布:是一个均值为0,方差为1/输入个数的均匀分布
方差
Xavier initialization是在线性函数上推导得出,这说明它对非线性函数并不具有普适性,所以这个例子仅仅说明它对tanh很有效。
He initialization:用来解决Relu初始化的问题。
思想: 在Relu网络中,假定每一层有一半的神经元被激活,另一半为0,为保持variance方差不变,只需要在Xavier的基础上再乘以2.
Var(W) = 2/n
BP参考代码使用的是Xavier initialization,numpy具体实现如下:

# Xavier方差选择,有三种,默认方差是只考虑输入(一般是前向信息的传播更重要一点);只考虑输出;同时考虑输入和输出
# 反向传播过程中,输出变成输入,即self.hidden_nodes,self.output_nodes。由方差,得到偏差
self.w_input2hidden = np.random.normal(0.0, self.hidden_nodes**-0.5, (self.hidden_nodes, self.input_nodes))
self.w_hidden2out = np.random.normal(0.0, self.output_nodes**-0.5, (self.output_nodes, self.hidden_nodes))

参考文献:
[1]https://blog.csdn.net/zhangyang10d/article/details/54804053
[2]https://baijiahao.baidu.com/s?id=1562029585755486&wfr=spider&for=pc
[3]Kaiming He, Xiangyu Zhang, Shaoqing Ren, and Jian Sun. Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification, Technical report, arXiv, Feb. 2015

  • 12
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: numpy是一个常用的Python库,广泛用于科学计算和数据分析。它包含了大量的数学函数和操作,特别适合用于实现神经网络的计算。 要使用numpy实现bp神经网络,首先需要定义网络的结构。例如,输入层有n个神经元,隐含层有m个神经元,输出层有k个神经元。然后,需要初始化神经网络的权重和偏置参数。可以使用numpy的随机函数来生成初始值。 接下来,需要定义神经网络的前向传播函数。它将输入数据传递给网络,经过一系列的权重和偏置计算,最终得到输出结果。在每个神经元中,可以使用numpy的矩阵乘法来实现权重和输入的相乘,然后再加上偏置。经过激活函数的处理,就可以得到每个神经元的输出。 在前向传播之后,需要定义神经网络的反向传播函数。它通过比较网络的输出和实际结果,计算每个神经元的误差,并根据这些误差调整神经网络的参数。计算误差可以使用平方差损失函数。通过计算梯度,可以根据误差大小对权重和偏置进行更新。 最后,需要定义一个训练函数,用于迭代多次进行前向传播和反向传播,不断更新神经网络的参数。在每次迭代中,可以使用随机梯度下降法或者其他优化算法来更新参数。 总结起来,numpy提供了丰富的数学函数和操作,可以方便地实现bp神经网络。通过定义网络结构、初始化参数、实现前向传播和反向传播,以及训练函数的迭代,可以实现一个功能强大的bp神经网络。 ### 回答2: NumPy是一个使用Python语言的开源数值计算库,它可以帮助我们高效地进行数组计算和数据处理。在实现BP神经网络时,我们可以使用NumPy来进行矩阵计算,加速网络的训练和预测过程。 首先,我们需要定义一个神经网络的结构,包括输入层、隐藏层和输出层,每一层都由一组神经元组成。然后,我们需要初始化每个神经元的权重和偏置。 在训练过程中,我们首先将输入数据进行前向传播,即通过计算每一层的加权和和激活函数的输出。然后,我们计算输出层的误差,并通过反向传播算法逐层更新每个神经元的权重和偏置。反向传播的过程可以通过使用NumPy的矩阵乘法和元素级运算来高效地实现。 在预测过程中,我们只需要通过前向传播来计算网络的输出值,并基于输出值进行预测。 使用NumPy实现BP神经网络的主要优势是它提供了高效的矩阵计算能力,减少了迭代的计算次数,提高了训练和预测的速度。另外,NumPy还提供了丰富的数学函数和操作,方便我们对数据进行处理和分析。 总结起来,NumPy是一个非常有用的工具,可以帮助我们实现BP神经网络。它提供了高效的矩阵计算能力,可以加速神经网络的训练和预测过程。同时,它还提供了丰富的数学函数和操作,方便我们对数据进行处理和分析。因此,使用NumPy实现BP神经网络是一个不错的选择。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值