# 构建两层以上BP神经网络（python代码）

self.setup(2, [2,2,2], 1)	#入药实现四层可改成[2,2,2,2]


# -*- coding: utf-8 -*-
"""
Created on Tue May 15 16:39:55 2018
"""

import math
import random
import numpy
import matplotlib.pyplot as plt
import pandas
from sklearn.preprocessing import MinMaxScaler

random.seed(0)  # 使random函数每一次生成的随机数值都相等

def rand(a, b):
return (b - a) * random.random() + a  # 生成a到b的随机数

def make_matrix(m, n, fill=0.0):  # 创建一个指定大小的矩阵
mat = []
for i in range(m):
mat.append([fill] * n)
return mat

# 定义tanh函数和它的导数
def tanh(x):
return numpy.tanh(x)

def tanh_derivate(x):
return 1 - numpy.tanh(x) * numpy.tanh(x)  # tanh函数的导数

class BPNeuralNetwork:
def __init__(self):  # 初始化变量
self.output_n = 0
self.output_n = 0
self.input_n = 0
self.input_cells = []
self.output_cells = []
self.input_weights = []
self.output_weights = []
self.input_correction = []
self.output_correction = []

def setup(self, ni, nh, no):
self.hidden_layers = len(nh)
self.hidden_n = [0] * self.hidden_layers  # 也就是需要初始化多少
self.hidden_cells = [None] * self.hidden_layers
self.hidden_weights = [None] * (self.hidden_layers - 1)
self.hidden_correction = [None] * (self.hidden_layers - 1)
self.input_n = ni + 1  # 输入层+偏置项
self.hidden_n = nh  # 一个列表
self.h_b = [None] * self.hidden_layers
for i in range(self.hidden_layers):
self.hidden_n[i] += 1
self.output_n = no  # 输出层

# 初始化神经元
self.input_cells = [1.0] * self.input_n
for i in range(self.hidden_layers):  # 也就是使用
self.hidden_cells[i] = [1.0] * self.hidden_n[i]  # 也就是进行
self.output_cells = [1.0] * self.output_n  #

# 初始化连接边的边权
self.input_weights = make_matrix(self.input_n, self.hidden_n[0])  # 邻接矩阵存边权：输入层->隐藏层
for i in range(self.hidden_layers - 1):
self.hidden_weights[i] = make_matrix(self.hidden_n[i], self.hidden_n[i + 1])

self.output_weights = make_matrix(self.hidden_n[-1], self.output_n)  # 邻接矩阵存边权：隐藏层->输出层
# 初始化bias

for i in range(self.hidden_layers):  #
self.h_b[i] = make_matrix(self.hidden_n[i], 1)  # 也就是使用
self.o_b = make_matrix(self.output_n, 1)  #
# 随机初始化边权：为了反向传导做准备--->随机初始化的目的是使对称失效
for i in range(self.input_n):
for h in range(self.hidden_n[0]):
self.input_weights[i][h] = rand(-1, 1)  # 由输入层第i个元素到隐藏层1第j个元素的边权为随机值
for k in range(self.hidden_layers - 1):
for i in range(self.hidden_n[k]):  # 也就是使用了
for h in range(self.hidden_n[k + 1]):
self.hidden_weights[k][i][h] = rand(-1, 1)  # 由隐藏层1第i个元素到隐藏层2第j个元素的边权为随机值
print(self.hidden_weights[k][i][h])
for h in range(self.hidden_n[self.hidden_layers - 1]):
for o in range(self.output_n):
self.output_weights[h][o] = rand(-1, 1)  # 由隐藏层2第i个元素到输出层第j个元素的边权为随机值
# 随机初始化bias
for k in range(self.hidden_layers):
for i in range(self.hidden_n[k]):  # 也就是进行
self.h_b[k][i] = rand(-1, 1)  # dui
for i in range(self.output_n):
self.o_b[i] = rand(-1, 1)
# 保存校正矩阵，为了以后误差做调整
self.input_correction = make_matrix(self.input_n, self.hidden_n[0])
for i in range(self.hidden_layers - 1):  # 就是会长生多个
self.hidden_correction[i] = make_matrix(self.hidden_n[i], self.hidden_n[i + 1])
self.output_correction = make_matrix(self.hidden_n[-1], self.output_n)

# 输出预测值

def predict(self, inputs):
# 对输入层进行操作转化样本
for i in range(self.input_n - 1):
self.input_cells[i] = inputs[i]  # n个样本从0~n-1
# 计算隐藏层的输出，每个节点最终的输出值就是权值*节点值的加权和
for j in range(self.hidden_n[0]):  # 使用了
total = 0.0
for i in range(self.input_n):
total += self.input_cells[i] * self.input_weights[i][j]
# 此处为何是先i再j，以隐含层节点做大循环，输入样本为小循环，是为了每一个隐藏节点计算一个输出值，传输到下一层
self.hidden_cells[0][j] = tanh(total - self.h_b[0][j])  # 此节点的输出是前一层所有输入点和到该点之间的权值加权和
for k in range(self.hidden_layers - 1):
for m in range(self.hidden_n[k + 1]):
total = 0.0
for i in range(self.hidden_n[k]):
total += self.hidden_cells[k][i] * self.hidden_weights[k][i][m]  # 使用了一个新的东西
self.hidden_cells[k + 1][m] = tanh(total - self.h_b[k + 1][m])  # 此节点的输出是前一层所有输入点和到该点之间的权值加权和
for k in range(self.output_n):
total = 0.0
for j in range(self.hidden_n[-1]):
total += self.hidden_cells[-1][j] * self.output_weights[j][k]
self.output_cells[k] = tanh(total - self.o_b[k])  # 获取输出层每个元素的值
return self.output_cells[:]  # 最后输出层的结果返回

# 反向传播算法
def back_propagate(self, case, label, learn, correct):
self.predict(case)  # 对实例进行预测
output_deltas = [0.0] * self.output_n  # 初始化矩阵
for o in range(self.output_n):
error = label[o] - self.output_cells[o]  # 正确结果和预测结果的误差：0,1，-1
output_deltas[o] = tanh_derivate(self.output_cells[o]) * error  # 误差稳定在0~1内
# 隐含层误差
hidden_deltas = [None] * self.hidden_layers
for i in range(self.hidden_layers):
hidden_deltas[i] = [0.0] * self.hidden_n[i]

for h in range(self.hidden_n[-1]):  # 也就是
error = 0.0
for o in range(self.output_n):
error += output_deltas[o] * self.output_weights[h][o]
hidden_deltas[-1][h] = tanh_derivate(self.hidden_cells[-1][h]) * error
# 反向传播算法求W
# 更新隐藏层->输出权重
for h2 in range(self.hidden_n[-1]):
for o in range(self.output_n):
change = output_deltas[o] * self.hidden_cells[-1][h2]  #
# 调整权重：上一层每个节点的权重学习*变化+矫正率
self.output_weights[h2][o] += learn * change + correct * self.output_correction[h2][o]
self.output_correction[h2][o] = change
# 更新隐藏1层->隐藏2权重
for k in range(self.hidden_layers - 2, -1, -1):  # 得到了隐藏层是多少层
for h1 in range(self.hidden_n[k]):
for o in range(self.hidden_n[k + 1]):
change = hidden_deltas[k + 1][o] * self.hidden_cells[k][h1]
# 调整权重：上一层每个节点的权重学习*变化+矫正率
self.hidden_weights[k][h1][o] += learn * change + correct * self.hidden_correction[k][h1][o]
self.hidden_correction[k][h1][o] = change
# 更新输入->隐藏层的权重
for i in range(self.input_n):  # 使用了一个东西
for h in range(self.hidden_n[0]):
change = hidden_deltas[0][h] * self.input_cells[i]
self.input_weights[i][h] += learn * change + correct * self.input_correction[i][h]
self.input_correction[i][h] = change
# 更新bias
for o in range(self.output_n):
self.o_b[o] = self.o_b[o] - learn * output_deltas[o]
for k in range(self.hidden_layers):
for h1 in range(self.hidden_n[k]):
self.h_b[k][h1] = self.h_b[k][h1] - learn * hidden_deltas[k][h1]

error = 0.0
for o in range(len(label)):  # 逐渐yuce
error = 0.5 * (label[o] - self.output_cells[o]) ** 2  # 平方误差函数
return error

def train(self, cases, labels, limit=10000, learn=0.05, correct=0.1):
for i in range(limit):  # 设置迭代次数
error = 0.0
for j in range(len(cases)):  # 对输入层进行访问
label = labels[j]
case = cases[j]
error += self.back_propagate(case, label, learn, correct)  # 样例，标签，学习率，正确阈值
print(error)

def test(self):  # 学习正弦函数
cases = [
[0, 0],
[0, 1],
[1, 0],
[1, 1],
]
labels = [[0], [1], [1], [0]]
self.setup(2, [2, 2], 1)  #
self.train(cases, labels, 10000, 0.05, 0.1)
for case in cases:
print(self.predict(case))

if __name__ == '__main__':
nn = BPNeuralNetwork()
nn.test()


• 点赞 1
• 评论
• 分享
x

海报分享

扫一扫，分享海报

• 收藏
• 打赏

打赏

半成品文艺青年

你的鼓励将是我创作的最大动力

C币 余额
2C币 4C币 6C币 10C币 20C币 50C币
• 举报
• 一键三连

点赞Mark关注该博主, 随时了解TA的最新博文

04-20 86

02-23 1万+
04-29 9819
08-13 1598
07-28 3万+
01-06 724
01-16 612
05-20
09-18
09-28