三层BP神经网络的python实现

简介:

这是一个非常漂亮的三层反向传播神经网络的python实现,下一步我准备试着将其修改为多层BP神经网络。

 

下面是运行演示函数的截图,你会发现预测的结果很惊人!

 

 

 

 

提示:运行演示函数的时候,可以尝试改变隐藏层的节点数,看节点数增加了,预测的精度会否提升

 

复制代码
  1 import math
  2 import random
  3 import string
  4 
  5 random.seed(0)
  6 
  7 # 生成区间[a, b)内的随机数
  8 def rand(a, b):
  9     return (b-a)*random.random() + a
 10 
 11 # 生成大小 I*J 的矩阵,默认零矩阵 (当然,亦可用 NumPy 提速)
 12 def makeMatrix(I, J, fill=0.0):
 13     m = []
 14     for i in range(I):
 15         m.append([fill]*J)
 16     return m
 17 
 18 # 函数 sigmoid,这里采用 tanh,因为看起来要比标准的 1/(1+e^-x) 漂亮些
 19 def sigmoid(x):
 20     return math.tanh(x)
 21 
 22 # 函数 sigmoid 的派生函数, 为了得到输出 (即:y)
 23 def dsigmoid(y):
 24     return 1.0 - y**2
 25 
 26 class NN:
 27     ''' 三层反向传播神经网络 '''
 28     def __init__(self, ni, nh, no):
 29         # 输入层、隐藏层、输出层的节点(数)
 30         self.ni = ni + 1 # 增加一个偏差节点
 31         self.nh = nh
 32         self.no = no
 33 
 34         # 激活神经网络的所有节点(向量)
 35         self.ai = [1.0]*self.ni
 36         self.ah = [1.0]*self.nh
 37         self.ao = [1.0]*self.no
 38         
 39         # 建立权重(矩阵)
 40         self.wi = makeMatrix(self.ni, self.nh)
 41         self.wo = makeMatrix(self.nh, self.no)
 42         # 设为随机值
 43         for i in range(self.ni):
 44             for j in range(self.nh):
 45                 self.wi[i][j] = rand(-0.2, 0.2)
 46         for j in range(self.nh):
 47             for k in range(self.no):
 48                 self.wo[j][k] = rand(-2.0, 2.0)
 49 
 50         # 最后建立动量因子(矩阵)
 51         self.ci = makeMatrix(self.ni, self.nh)
 52         self.co = makeMatrix(self.nh, self.no)
 53 
 54     def update(self, inputs):
 55         if len(inputs) != self.ni-1:
 56             raise ValueError('与输入层节点数不符!')
 57 
 58         # 激活输入层
 59         for i in range(self.ni-1):
 60             #self.ai[i] = sigmoid(inputs[i])
 61             self.ai[i] = inputs[i]
 62 
 63         # 激活隐藏层
 64         for j in range(self.nh):
 65             sum = 0.0
 66             for i in range(self.ni):
 67                 sum = sum + self.ai[i] * self.wi[i][j]
 68             self.ah[j] = sigmoid(sum)
 69 
 70         # 激活输出层
 71         for k in range(self.no):
 72             sum = 0.0
 73             for j in range(self.nh):
 74                 sum = sum + self.ah[j] * self.wo[j][k]
 75             self.ao[k] = sigmoid(sum)
 76 
 77         return self.ao[:]
 78 
 79     def backPropagate(self, targets, N, M):
 80         ''' 反向传播 '''
 81         if len(targets) != self.no:
 82             raise ValueError('与输出层节点数不符!')
 83 
 84         # 计算输出层的误差
 85         output_deltas = [0.0] * self.no
 86         for k in range(self.no):
 87             error = targets[k]-self.ao[k]
 88             output_deltas[k] = dsigmoid(self.ao[k]) * error
 89 
 90         # 计算隐藏层的误差
 91         hidden_deltas = [0.0] * self.nh
 92         for j in range(self.nh):
 93             error = 0.0
 94             for k in range(self.no):
 95                 error = error + output_deltas[k]*self.wo[j][k]
 96             hidden_deltas[j] = dsigmoid(self.ah[j]) * error
 97 
 98         # 更新输出层权重
 99         for j in range(self.nh):
100             for k in range(self.no):
101                 change = output_deltas[k]*self.ah[j]
102                 self.wo[j][k] = self.wo[j][k] + N*change + M*self.co[j][k]
103                 self.co[j][k] = change
104                 #print(N*change, M*self.co[j][k])
105 
106         # 更新输入层权重
107         for i in range(self.ni):
108             for j in range(self.nh):
109                 change = hidden_deltas[j]*self.ai[i]
110                 self.wi[i][j] = self.wi[i][j] + N*change + M*self.ci[i][j]
111                 self.ci[i][j] = change
112 
113         # 计算误差
114         error = 0.0
115         for k in range(len(targets)):
116             error = error + 0.5*(targets[k]-self.ao[k])**2
117         return error
118 
119     def test(self, patterns):
120         for p in patterns:
121             print(p[0], '->', self.update(p[0]))
122 
123     def weights(self):
124         print('输入层权重:')
125         for i in range(self.ni):
126             print(self.wi[i])
127         print()
128         print('输出层权重:')
129         for j in range(self.nh):
130             print(self.wo[j])
131 
132     def train(self, patterns, iterations=1000, N=0.5, M=0.1):
133         # N: 学习速率(learning rate)
134         # M: 动量因子(momentum factor)
135         for i in range(iterations):
136             error = 0.0
137             for p in patterns:
138                 inputs = p[0]
139                 targets = p[1]
140                 self.update(inputs)
141                 error = error + self.backPropagate(targets, N, M)
142             if i % 100 == 0:
143                 print('误差 %-.5f' % error)
144 
145 
146 def demo():
147     # 一个演示:教神经网络学习逻辑异或(XOR)------------可以换成你自己的数据试试
148     pat = [
149         [[0,0], [0]],
150         [[0,1], [1]],
151         [[1,0], [1]],
152         [[1,1], [0]]
153     ]
154 
155     # 创建一个神经网络:输入层有两个节点、隐藏层有两个节点、输出层有一个节点
156     n = NN(2, 2, 1)
157     # 用一些模式训练它
158     n.train(pat)
159     # 测试训练的成果(不要吃惊哦)
160     n.test(pat)
161     # 看看训练好的权重(当然可以考虑把训练好的权重持久化)
162     #n.weights()
163     
164     
165 if __name__ == '__main__':
166     demo()
复制代码

 

本文转自罗兵博客园博客,原文链接:http://www.cnblogs.com/hhh5460/p/4304628.html ,如需转载请自行联系原作者
相关文章
|
2天前
|
网络协议 开发者 Python
网络编程小白秒变大咖!Python Socket基础与进阶教程,轻松上手无压力!
【7月更文挑战第25天】在网络技术快速发展的背景下, Python因其简洁的语法和强大的库支持成为学习网络编程的理想选择。
19 5
|
3天前
|
Unix API Python
python提供了两个级别访问的网络服务
【7月更文挑战第23天】python提供了两个级别访问的网络服务
19 7
|
2天前
|
网络协议 开发者 Python
深度探索Python Socket编程:从理论到实践,进阶篇带你领略网络编程的魅力!
【7月更文挑战第25天】在网络编程中, Python Socket编程因灵活性强而广受青睐。本文采用问答形式深入探讨其进阶技巧。**问题一**: Socket编程基于TCP/IP,通过创建Socket对象实现通信,支持客户端和服务器间的数据交换。**问题二**: 提升并发处理能力的方法包括多线程(适用于I/O密集型任务)、多进程(绕过GIL限制)和异步IO(asyncio)。**问题三**: 提供了一个使用asyncio库实现的异步Socket服务器示例,展示如何接收及响应客户端消息。通过这些内容,希望能激发读者对网络编程的兴趣并引导进一步探索。
11 4
|
1天前
|
网络协议 Python
网络世界的建筑师:Python Socket编程基础与进阶,构建你的网络帝国!
【7月更文挑战第26天】在网络的数字宇宙中,Python Socket编程是开启网络世界大门的钥匙。本指南将引领你从基础到实战,成为网络世界的建筑师。
6 2
|
2天前
|
开发者 Python
Python Socket编程:不只是基础,更有进阶秘籍,让你的网络应用飞起来!
【7月更文挑战第25天】在网络应用蓬勃发展的数字时代,Python凭借其简洁的语法和强大的库支持成为开发高效应用的首选。本文通过实时聊天室案例,介绍了Python Socket编程的基础与进阶技巧,包括服务器与客户端的建立、数据交换等基础篇内容,以及使用多线程和异步IO提升性能的进阶篇。基础示例展示了服务器端监听连接请求、接收转发消息,客户端连接服务器并收发消息的过程。进阶部分讨论了如何利用Python的`threading`模块和`asyncio`库来处理多客户端连接,提高应用的并发处理能力和响应速度。掌握这些技能,能使开发者在网络编程领域更加游刃有余,构建出高性能的应用程序。
10 3
|
1天前
|
消息中间件 网络协议 网络安全
Python Socket编程:打造你的专属网络通道,基础篇与进阶篇一网打尽!
【7月更文挑战第26天】在网络编程领域,Python以简洁语法和强大库支持成为构建应用的首选。Socket编程为核心,实现计算机间的数据交换。
8 1
|
13天前
|
网络协议 安全 Shell
`nmap`是一个开源的网络扫描工具,用于发现网络上的设备和服务。Python的`python-nmap`库允许我们在Python脚本中直接使用`nmap`的功能。
`nmap`是一个开源的网络扫描工具,用于发现网络上的设备和服务。Python的`python-nmap`库允许我们在Python脚本中直接使用`nmap`的功能。
|
11天前
|
机器学习/深度学习 数据采集 前端开发
网络爬虫开发:JavaScript与Python特性的小差异
我们以前写JavaScript的代码时,在遇到了发送请求时,都是需要去await的。 但是为什么Python代码不需要这样做呢? 这就是因为JavaScript是异步的,Python是同步的。 JavaScript就需要使用关键词await将异步代码块变为同步代码。
|
1天前
|
消息中间件 网络协议 网络安全
解锁Python Socket新姿势,进阶篇带你玩转高级网络通信技巧!
【7月更文挑战第26天】掌握Python Socket后,探索网络通信高级技巧。本指南深化Socket编程理解,包括非阻塞I/O以提升并发性能(示例使用`select`),SSL/TLS加密确保数据安全,以及介绍高级网络协议库如HTTP、WebSocket和ZeroMQ,简化复杂应用开发。持续学习,成为网络通信专家!
3 0