Read the handwritten BP neural network of this blog, after using feel good, and then want to achieve more than two layers of BP network, so they will rewrite part of the function, as long as this line of function to change the number of numbers in the list can achieve training

self.setup(2[2.2.2].1)	# four layers can be changed to [2,2,2,2]
Copy the code

If you need to see the principle of the blog can be tuned to the above, some redundant code hope forgive me

# -*- 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)  # Make the random function generate the same random value every time


def rand(a, b) :
    return (b - a) * random.random() + a  # Generate random numbers from a to B


def make_matrix(m, n, fill=0.0) :  # Create a matrix of the specified size
    mat = []
    for i in range(m):
        mat.append([fill] * n)
    return mat


Define the tanh function and its derivative
def tanh(x) :
    return numpy.tanh(x)


def tanh_derivate(x) :
    return 1 - numpy.tanh(x) * numpy.tanh(x)  The derivative of tanh


class BPNeuralNetwork:
    def __init__(self) :  # Initialize variables
        self.output_n = 0
        self.output_n = 0
        self.input_n = 0self.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  # is how much you need to initialize
        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  # Input layer + offset term
        self.hidden_n = nh  # A list
        self.h_b = [None] * self.hidden_layers
        for i in range(self.hidden_layers):
            self.hidden_n[i] += 1
        self.output_n = no  # output layer

        # Initialize the neuron
        self.input_cells = [1.0] * self.input_n
        for i in range(self.hidden_layers):  # is to use
            self.hidden_cells[i] = [1.0] * self.hidden_n[i]  # is to carry on
        self.output_cells = [1.0] * self.output_n  #

        # Initialize the edge weight of the join edge
        self.input_weights = make_matrix(self.input_n, self.hidden_n[0])  Adjacent matrix edge weight: input layer -> hidden layer
        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)  Adjacent matrix edge weight: hidden layer -> output layer
        Initialize BIAS

        for i in range(self.hidden_layers):  #
            self.h_b[i] = make_matrix(self.hidden_n[i], 1)  # is to use
        self.o_b = make_matrix(self.output_n, 1)  #
        # Random initialization edge weights: in preparation for reverse conduction --> The purpose of random initialization is to disable symmetry
        for i in range(self.input_n):
            for h in range(self.hidden_n[0]):
                self.input_weights[i][h] = rand(-1.1)  # The edge weight of the ith element in the input layer to the JTH element in the hidden layer 1 is random
        for k in range(self.hidden_layers - 1) :for i in range(self.hidden_n[k]):  # is used
                for h in range(self.hidden_n[k + 1]):
                    self.hidden_weights[k][i][h] = rand(-1.1)  # The edge weight of the ith element from hidden layer 1 to the JTH element from hidden layer 2 is a random value
                    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)  # The edge weight from the ith element of the hidden layer 2 to the JTH element of the output layer is a random value
        # Randomly initialize BIAS
        for k in range(self.hidden_layers):
            for i in range(self.hidden_n[k]):  # is to carry on
                self.h_b[k][i] = rand(-1.1)  # dui
        for i in range(self.output_n):
            self.o_b[i] = rand(-1.1)
        Save the correction matrix to adjust for future errors
        self.input_correction = make_matrix(self.input_n, self.hidden_n[0])
        for i in range(self.hidden_layers - 1) :# is to grow more
            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)

        # Output the predicted value

    def predict(self, inputs) :
        # Convert the sample to the input layer
        for i in range(self.input_n - 1):
            self.input_cells[i] = inputs[i]  # n samples from 0 to n-1
        # Calculate the output of the hidden layer. The final output value of each node is the weighted sum of the weight * node values
        for j in range(self.hidden_n[0) :# using the
            total = 0.0
            for i in range(self.input_n):
                total += self.input_cells[i] * self.input_weights[i][j]
                # Here, why do I first and then J, make a large loop with hidden layer nodes, and the input sample is a small loop, in order to calculate an output value for each hidden node and transmit it to the next layer
            self.hidden_cells[0][j] = tanh(total - self.h_b[0][j])  # The output of this node is the weighted sum of all the input points of the previous layer and the weights up to that point
        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]  # uses a new thing
                self.hidden_cells[k + 1][m] = tanh(total - self.h_b[k + 1][m])  # The output of this node is the weighted sum of all the input points of the previous layer and the weights up to that point
        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])  Get the value of each element in the output layer
        return self.output_cells[:]  The final output layer results are returned

    # Back propagation algorithm
    def back_propagate(self, case, label, learn, correct) :
        self.predict(case)  # Predict the example
        output_deltas = [0.0] * self.output_n  Initialize the matrix
        for o in range(self.output_n):
            error = label[o] - self.output_cells[o]  Error between correct and predicted results: 0,1, -1
            output_deltas[o] = tanh_derivate(self.output_cells[o]) * error  # The error is stable within 0~1
        # Hidden layer error
        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) :#, that is,
            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
            # Back propagation algorithm for W
        # Update hidden layer -> Output weights
        for h2 in range(self.hidden_n[-1) :for o in range(self.output_n):
                change = output_deltas[o] * self.hidden_cells[-1][h2]  #
                Adjust weight: the weight of each node at the upper layer is learned * change + correction rate
                self.output_weights[h2][o] += learn * change + correct * self.output_correction[h2][o]
                self.output_correction[h2][o] = change
        # Update hide 1 layer -> Hide 2 weights
        for k in range(self.hidden_layers - 2, -1, -1) :# Get the number of hidden layers
            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]
                    Adjust weight: the weight of each node at the upper layer is learned * change + correction rate
                    self.hidden_weights[k][h1][o] += learn * change + correct * self.hidden_correction[k][h1][o]
                    self.hidden_correction[k][h1][o] = change
        Update input -> hide layer weights
        for i in range(self.input_n):  # use a thing
            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
        # update 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 gradually
            error = 0.5 * (label[o] - self.output_cells[o]) ** 2  # Squared error function
        return error

    def train(self, cases, labels, limit=10000, learn=0.05, correct=0.1) :
        for i in range(limit):  # Set number of iterations
            error = 0.0
            for j in range(len(cases)):  # Access the input layer
                label = labels[j]
                case = cases[j]
                error += self.back_propagate(case, label, learn, correct)  # sample, tag, learn rate, correct threshold
            print(error)

    def test(self) :  # Learn the sine function
        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()

Copy the code