构建两层以上BP神经网络(python代码)

看了这篇博客的手写bp神经网络,使用了之后觉得不错,然后想实现两层以上的bp网络,于是自己将部分函数改写,只要这行函数中更改列表中数字的个数就可以实现训练

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

如果需要看原理的可以调至上述博客,代码有些冗余希望见谅

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

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()

已标记关键词 清除标记
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质? 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹?   那么C++就是你个人能力提升,职业之路进阶的不二之选。 【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。 【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署; 2.吊打一切关于C++的笔试面试题; 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块 基础篇 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 进阶篇 本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 提升篇: 本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页