BP算法是神经网络的基础,也是最重要的部分。由于误差反向传播的过程中,可能会出现梯度消失或者爆炸,所以需要调整损失函数。在LSTM中,通过sigmoid来实现三个门来解决记忆问题,用tensorflow实现的过程中,需要进行梯度修剪操作,以防止梯度爆炸。RNN的BPTT算法同样存在着这样的问题,所以步数超过5步以后,记忆效果大大下降。LSTM的效果能够支持到30多步数,太长了也不行。如果要求更长的记忆,或者考虑更多的上下文,可以把多个句子的LSTM输出组合起来作为另一个LSTM的输入。下面上传用Python实现的普通DNN的BP算法,激活为sigmoid.

字迹有些潦草,凑合用吧,习惯了手动绘图,个人习惯。后面的代码实现思路是最重要的:每个层有多个节点,层与层之间单向链接(前馈网络),因此数据结构可以设计为单向链表。实现的过程属于典型的递归,递归调用到最后一层后把每一层的back_weights反馈给上一层,直到推导结束。上传代码(未经过优化的代码):

测试代码:

import numpy as np
import NeuralNetWork as nw if __name__ == '__main__':
print("test neural network") data = np.array([[1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 1]]) np.set_printoptions(precision=3, suppress=True) for i in range(10):
network = nw.NeuralNetWork([8, 20, 8])
# 让输入数据与输出数据相等
network.fit(data, data, learning_rate=0.1, epochs=150) print("\n\n", i, "result")
for item in data:
print(item, network.predict(item))
#NeuralNetWork.py
# encoding: utf-8
#NeuralNetWork.py
import numpy as np; def logistic(inX):
return 1 / (1+np.exp(-inX)) def logistic_derivative(x):
return logistic(x) * (1 - logistic(x)) class Neuron:
'''
构建神经元单元,每个单元都有如下属性:1.input;2.output;3.back_weight;4.deltas_item;5.weights.
每个神经元单元更新自己的weights,多个神经元构成layer,形成weights矩阵
'''
def __init__(self,len_input):
#输入的初始参数,随机取很小的值(<0.1)
self.weights = np.random.random(len_input) * 0.1
#当前实例的输入
self.input = np.ones(len_input)
#对下一层的输出值
self.output = 1.0
#误差项
self.deltas_item = 0.0
# 上一次权重增加的量,记录起来方便后面扩展时可考虑增加冲量
self.last_weight_add = 0 def calculate_output(self,x):
#计算输出值
self.input = x;
self.output = logistic(np.dot(self.weights,self.input))
return self.output def get_back_weight(self):
#获取反馈差值
return self.weights * self.deltas_item def update_weight(self,target = 0,back_weight = 0,learning_rate=0.1,layer="OUTPUT"):
#更新权重
if layer == "OUTPUT":
self.deltas_item = (target - self.output) * logistic_derivative(self.input)
elif layer == "HIDDEN":
self.deltas_item = back_weight * logistic_derivative(self.input) delta_weight = self.input * self.deltas_item * learning_rate + 0.9 * self.last_weight_add #添加冲量
self.weights += delta_weight
self.last_weight_add = delta_weight class NetLayer:
'''
网络层封装,管理当前网络层的神经元列表
''' def __init__(self,len_node,in_count):
'''
:param len_node: 当前层的神经元数
:param in_count: 当前层的输入数
'''
# 当前层的神经元列表
self.neurons = [Neuron(in_count) for _ in range(len_node)];
# 记录下一层的引用,方便递归操作
self.next_layer = None def calculate_output(self,inX):
output = np.array([node.calculate_output(inX) for node in self.neurons])
if self.next_layer is not None:
return self.next_layer.calculate_output(output)
return output def get_back_weight(self):
return sum([node.get_back_weight() for node in self.neurons]) def update_weight(self,learning_rate,target):
layer = "OUTPUT"
back_weight = np.zeros(len(self.neurons))
if self.next_layer is not None:
back_weight = self.next_layer.update_weight(learning_rate,target)
layer = "HIDDEN"
for i,node in enumerate(self.neurons):
target_item = 0 if len(target) <= i else target[i]
node.update_weight(target = target_item,back_weight = back_weight[i],learning_rate=learning_rate,layer=layer)
return self.get_back_weight() class NeuralNetWork:
def __init__(self, layers):
self.layers = []
self.construct_network(layers)
pass def construct_network(self, layers):
last_layer = None
for i, layer in enumerate(layers):
if i == 0:
continue
cur_layer = NetLayer(layer, layers[i - 1])
self.layers.append(cur_layer)
if last_layer is not None:
last_layer.next_layer = cur_layer
last_layer = cur_layer def fit(self, x_train, y_train, learning_rate=0.1, epochs=100000, shuffle=False):
'''''
训练网络, 默认按顺序来训练
方法 1:按训练数据顺序来训练
方法 2: 随机选择测试
:param x_train: 输入数据
:param y_train: 输出数据
:param learning_rate: 学习率
:param epochs:权重更新次数
:param shuffle:随机取数据训练
'''
indices = np.arange(len(x_train))
for _ in range(epochs):
if shuffle:
np.random.shuffle(indices)
for i in indices:
self.layers[0].calculate_output(x_train[i])
self.layers[0].update_weight(learning_rate, y_train[i])
pass def predict(self, x):
return self.layers[0].calculate_output(x)
 

DNN的BP算法Python简单实现的更多相关文章

  1. 神经网络(BP)算法Python实现及简单应用

    首先用Python实现简单地神经网络算法: import numpy as np # 定义tanh函数 def tanh(x): return np.tanh(x) # tanh函数的导数 def t ...

  2. 【深度学习】BP反向传播算法Python简单实现

    转载:火烫火烫的 个人觉得BP反向传播是深度学习的一个基础,所以很有必要把反向传播算法好好学一下 得益于一步一步弄懂反向传播的例子这篇文章,给出一个例子来说明反向传播 不过是英文的,如果你感觉不好阅读 ...

  3. 决策树(Decision Tree)算法 python简单实现

    "" """ import numpy as np from math import log import operator import json ...

  4. BP算法从原理到python实现

    BP算法从原理到实践 反向传播算法Backpropagation的python实现 觉得有用的话,欢迎一起讨论相互学习~Follow Me 博主接触深度学习已经一段时间,近期在与别人进行讨论时,发现自 ...

  5. 关于BP算法在DNN中本质问题的几点随笔 [原创 by 白明] 微信号matthew-bai

       随着deep learning的火爆,神经网络(NN)被大家广泛研究使用.但是大部分RD对BP在NN中本质不甚清楚,对于为什这么使用以及国外大牛们是什么原因会想到用dropout/sigmoid ...

  6. 神经网络BP算法C和python代码

    上面只显示代码. 详BP原理和神经网络的相关知识,请参阅:神经网络和反向传播算法推导 首先是前向传播的计算: 输入: 首先为正整数 n.m.p.t,分别代表特征个数.训练样本个数.隐藏层神经元个数.输 ...

  7. 神经网络中 BP 算法的原理与 Python 实现源码解析

    最近这段时间系统性的学习了 BP 算法后写下了这篇学习笔记,因为能力有限,若有明显错误,还请指正. 什么是梯度下降和链式求导法则 假设我们有一个函数 J(w),如下图所示. 梯度下降示意图 现在,我们 ...

  8. BP算法在minist数据集上的简单实现

    BP算法在minist上的简单实现 数据:http://yann.lecun.com/exdb/mnist/ 参考:blog,blog2,blog3,tensorflow 推导:http://www. ...

  9. 基于BP神经网络的简单字符识别算法自小结(C语言版)

    本文均属自己阅读源代码的点滴总结.转账请注明出处谢谢. 欢迎和大家交流.qq:1037701636 email:gzzaigcn2009@163.com 写在前面的闲话: 自我感觉自己应该不是一个非常 ...

随机推荐

  1. 我的第一个netcore2.2 api项目搭建(三)续

    上一章快速陈述了自定义验证功能添加的过程,我的第一个netcore2.2 api项目搭建(三) 但是并没有真正的去实现,这一章将要实现验证功能的添加. 这一章实现目标三:jwt认证授权添加 在netc ...

  2. 【开发笔记】-Ubuntu环境命令初始化

    更新apt-get命令 apt-get update 安装yum命令 首先检测是否安装 build-essential 包 sudo apt-get install build-essential 安 ...

  3. 使用node+vue实现简单的WebSocket聊天功能

    最近学习了一下websocket的即时通信,感觉非常的强大,这里我用node启动了一个服务进行websocket链接,然后再vue的view里面进行了链接,进行通信,废话不多说,直接上代码吧, 首先, ...

  4. npm升级到最新版本、指定版本

    npm 升级到最新版本 //linux下 npm install -g npm npm升级到指定版本 //比如升级到5.6.0 npm install -g npm@5.6.0

  5. jQuery源码学习一: 创建一个jquery实例

    前言: jquery是每个前端都会的基础技能,众所周知,jquery返回的是jquery实例方法,但是我们似乎是直接使用$就可以获取到jquery的方法啦,可以在浏览器中判断一下 window.$ 和 ...

  6. vue动态子组件的实现方式

    让多个组件使用同一个挂载点,并动态切换,这就是动态组件. 通过使用保留的 <component>元素,动态地绑定到它的 is 特性,可以实现动态组件. 方式一:局部注册所需组件 <d ...

  7. Python之路(第四十三篇)线程的生命周期、全局解释器锁

    一.线程的生命周期(新建.就绪.运行.阻塞和死亡) 当线程被创建并启动以后,它既不是一启动就进入执行状态的,也不是一直处于执行状态的,在线程的生命周期中,它要经过新建(new).就绪(Ready).运 ...

  8. Linux基础:时间同步工具Chrony

    在Linux下,默认情况下,系统时间和硬件时间,并不会自动同步.在Linux运行过程中,系统时间和硬件时间以异步的方式运行,互不干扰.硬件时间的运行,是靠Bios电池来维持,而系统时间,是用CPU t ...

  9. prometheus学习系列十一: Prometheus 安全

    prometheus安全 我们这里说的安全主要是基本认证和https2种, 目前这2种安全在prometheus中都没有的, 需要借助第三方软件实现, 这里以nginx为例. 基本认证 配置基本认证 ...

  10. SQLAlchemy的常用数据类型

    SQLAlchemy常用的数据类型 Column 代表数据库表中的一列 是创建对象时数据类型所依赖的对象,通过在Column对象中指明具体的数据类型来实现相应的数据库表中的列的格式自定义. Strin ...