您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

简单网络的反向传播代码这么写就对了:分解步骤+完整实现

时间:2020-09-09 10:47:36  来源:  作者:

本文建立在理论推导之上,推导部分我通过一系列视频呈现,感兴趣请去我的主页找『戴森与你聊:神经网络小知识』这个合集即可,根据前面所做的推导,本文就通过代码来实现一个简单的三层全连接网络。

#技术技能超级玩家#

简单网络的反向传播代码这么写就对了:分解步骤+完整实现

本文将要实现的一个三层全连接简单网络

0.必要的库

我们代码基于Python环境,大家可以把下面的代码写入到一个jupyter notebook中,分节运行并调试。实现神经网络的基本算法,需要用到一些库,我们先把它们导入进来:

import numpy as np
import matplotlib.pyplot as plot

接下来进入正题!

1.给定输入和输出

X = np.array([[1,0,0,0],[1,0,1,1],[0,1,0,1],[1,1,1,0],[1,0,0,1]])
print('nInput shape:n',X.shape)
y = np.array([[1],[1],[0],[1],[0]])
print('nGround truth shape:n',y.shape)

注意: 在之前的推导中(视频中)我们假设一个输入是一个列向量,而这里使用的是矩阵,代表什么呢?在上面(3,4)所表示的输入信号维度中,第一个3是指的样本数目,而第二个4指的是每个样本中的feature的数目。因此,这里的(3,4)意思就是,输入是三个样本,每个样本用一个 1x4 的向量来表达。一定注意二者区别,这决定了后面所有矩阵运算时角标的顺序(也就是矩阵相乘时候的顺序)。 还要提醒各位注意观察,样本数目的多少,和后面的权重没有关系!权重的数目只取决于每个样本自身的维度。这其中有什么原因吗?

2. 定义网络结构和参数

假定使用以下结构的简单全连接网络,输入层有4个单元,隐藏层3个单元,输出层一个单元

简单网络的反向传播代码这么写就对了:分解步骤+完整实现

 

numInputNeurons = X.shape[1]
numHiddenNeurons = 3
numOutputNeurons = 1

3. 初始化权重和偏置参数

注意: 权重编号规则,与推导过程中使用的下标编号规则不一致,比如对于权重矩阵,之前推导中我们约定的是先写目标单元,再写起始单元的顺序,这里反过来了,大家可以考虑下为什么?

weightsInputHidden = np.random.uniform(size=(numInputNeurons,numHiddenNeurons))
print('nThe shape of weight matrix between the input layer and hidden layer is: ',weightsInputHidden.shape)
weightsHiddenOutput = np.random.uniform(size=(numHiddenNeurons,numOutputNeurons))
print('nThe shape of weight matrix between the hidden layer and output layer is: ',weightsHiddenOutput.shape)
biasHidden = np.random.uniform(size=(1,numHiddenNeurons))
print('nThe shape of bias matrix of hidden layer: ',biasHidden.shape)
biasOutput = np.random.uniform(size=(1,numOutputNeurons))
print('nThe shape of bias matrix of output layer is: ',biasOutput.shape)

4. 定义激活函数及其导数函数

前向和反向传播都会用到Sigmoid函数以及它的导数,先定义它们:

def sigmoid(x):
    return 1/(1 + np.exp(-x))
# Detailed definition of the derivative of sigmoid function
def derivative_sigmoid(x, original = False):
    return x * (1 - x)
    if(original == True):
        return sigmoid(x) * (1 - sigmoid(x))
简单网络的反向传播代码这么写就对了:分解步骤+完整实现

 

5. 正向传播 Forward Propagation¶

5.1 InputLayer --> HiddenLayer

hiddenIn = np.dot(X, weightsInputHidden) + biasHidden
hiddenActivation = sigmoid(hiddenIn)

注意: 这里涉及到矩阵运算的顺序,仔细分析一下。主要就是盯着维度的匹配!

  • 如果输入单元是行向量(本例中就是如此)且有j个元素,输入层的维度就是 1xj,然后后面的矩阵计算就一定要也得到一个维度匹配的行向量;
  • 如果输入单元是列向量(前面推导中的情形),那么输入层的维度就是jx1,后面的矩阵计算就要匹配列向量的维度

5.2 HiddenLayer --> OutputLayer

outputIn = np.dot(hiddenActivation, weightsHiddenOutput) + biasOutput
outputActivation = sigmoid(outputIn)print('nPrediction is: ', outputActivation)

6. 反向传播 Back Propagation

误差反传是最重要的一步,分为以下几个关键步骤:

6.1 成本函数和成本函数的导数

简单网络的反向传播代码这么写就对了:分解步骤+完整实现

 

Error = np.square(y - outputActivation)/2
E = outputActivation - y

6.2 BP四个基本方程之:输出层神经元误差

简单网络的反向传播代码这么写就对了:分解步骤+完整实现

 

derivativeHidden = derivative_sigmoid(hiddenActivation)
derivativeHidden.shapedeltaHidden = np.dot(deltaOutput, weightsHiddenOutput.T) * derivativeHiddendeltaHidden.sha# Learning rate
lr = 0.01n

6.3 BP四个基本方程之:中间层神经元误差

简单网络的反向传播代码这么写就对了:分解步骤+完整实现

 

derivativeHidden = derivative_sigmoid(hiddenActivation)
derivativeHidden.shapedeltaHidden = np.dot(deltaOutput, weightsHiddenOutput.T) * derivativeHiddendeltaHidden.shapedeltaHidden

6.4 BP四个基本方程之:权重和偏置的更新

简单网络的反向传播代码这么写就对了:分解步骤+完整实现

 

# Learning rate
lr = 0.01
weightsHiddenOutput -= np.dot(hiddenActivation.T, deltaOutput) * lr         # 3xN x Nx1 = 3x1
weightsInputHidden -= np.dot(X.T, deltaHidden) * lr        # 4xN x Nx3 = 4x3
biasOutput -= np.sum(deltaOutput, axis=0) * lr
biasHidden -= np.sum(deltaHidden, axis=0) * lr

注意: 上面注意维度的匹配!网络本身的参数维度和样本数均无关,比如权重和偏置的维度,都不可能与样本数有关系!这是检验我们有没有做对的一个很有用的标准。

到这为止,对这个神经网络的一次完整的前向传播+反向传播的流程算是进行完了!这是分解动作,也是完成了一次『训练』,但是一个神经网络必须经过多次训练,才能够较好的调整参数并完成任务,因此我们需要把这个训练过程写入一个循环中,反复进行!


上述过程的完整实现+训练神经网络

# Define Structure Parameters
numInputNeurons = X.shape[1]
numHiddenNeurons = 3
numOutputNeurons = 1
# Initialize weights and biases with random numbers
weightsInputHidden = np.random.uniform(size=(numInputNeurons,numHiddenNeurons))print('nThe shape of weight matrix between the input layer and hidden layer is: ',weightsInputHidden.shape)
weightsHiddenOutput = np.random.uniform(size=(numHiddenNeurons,numOutputNeurons))print('nThe shape of weight matrix between the hidden layer and output layer is: ',weightsHiddenOutput.shape)
biasHidden = np.random.uniform(size=(1,numHiddenNeurons))
print('nThe shape of bias matrix of hidden layer: ',biasHidden.shape)
biasOutput = np.random.uniform(size=(1,numOutputNeurons))
print('nThe shape of bias matrix of output layer is: ',biasOutput.shape)
# Define useful functionsdef sigmoid(x):    return 1/(1 + np.exp(-x))
# Definition of the derivative of sigmoid function with switch between original and efficient
def derivative_sigmoid(x, original = False):
    return x * (1 - x)
    if(original == True):
        return sigmoid(x) * (1 - sigmoid(x))
# Define training parameters
epochs = 8000
lr = 1
# Start training
for epoch in range(epochs):
    # Forward Propagation
    hiddenIn = np.dot(X, weightsInputHidden) + biasHidden    # Nx4 x 4x3 + Nx3 = Nx3
    hiddenActivation = sigmoid(hiddenIn)                     # Nx3
    
    outputIn = np.dot(hiddenActivation, weightsHiddenOutput) + biasOutput  # Nx3 x 3x1 + Nx1
    outputActivation = sigmoid(outputIn)                     # Nx1
    
    # Error
    Error = np.square(y - outputActivation)/2                # Nx1
    print('n Error in epoch ', epoch,' is: ', np.mean(Error))
    
    # Back Propagation 
    E = outputActivation - y                                # Nx1
    derivativeOutput = derivative_sigmoid(outputActivation) # Nx1
    #Output --> Hidden
    deltaOutput = E * derivativeOutput                      # Nx1 Hadamard Nx1 = Nx1
    # Hidden --> Input
    derivativeHidden = derivative_sigmoid(hiddenActivation)                      # Nx3
    deltaHidden = np.dot(deltaOutput, weightsHiddenOutput.T) * derivativeHidden  # Nx1 x 1x3 Hadamard Nx3
    # Update weights
    weightsHiddenOutput -= np.dot(hiddenActivation.T, deltaOutput) * lr         # 3xN x Nx1 = 3x1
    weightsInputHidden -= np.dot(X.T, deltaHidden) * lr        # 4xN x Nx3 = 4x3
    # Update biases
    biasOutput -= np.sum(deltaOutput, axis=0) * lr
    biasHidden -= np.sum(deltaHidden, axis=0) * lr
    
print('nTraining Accomplished!n', outputActivation)


Tags:反向传播   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
反向传播是训练神经网络的最常用方法之一。Rumelhart、Hinton和Williams(1986)引入了反向传播,该方法到今天仍然很流行。程序员经常使用反向传播训练深层神经网络,因为在图形处...【详细内容】
2021-03-25  Tags: 反向传播  点击:(290)  评论:(0)  加入收藏
本文建立在理论推导之上,推导部分我通过一系列视频呈现,感兴趣请去我的主页找『戴森与你聊:神经网络小知识』这个合集即可,根据前面所做的推导,本文就通过代码来实现一个简单的三...【详细内容】
2020-09-09  Tags: 反向传播  点击:(135)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的  程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条