使用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

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值