【Python数学建模常用算法代码(二)之BP神经网络】_构建2层前馈神经网络的bp算法python手编代码

100 阅读2分钟

Python数学建模常用算法代码(二)

BP神经网络模型Python代码

import numpy as np
import math
import random
import string
import matplotlib as mpl
import matplotlib.pyplot as plt
 
#random.seed(0)  #当我们设置相同的seed,每次生成的随机数相同。如果不设置seed,则每次会生成不同的随机数
                #参考https://blog.csdn.net/jiangjiang_jian/article/details/79031788
 
#生成区间[a,b]内的随机数
def random\_number(a,b):
    return (b-a)\*random.random()+a
 
#生成一个矩阵,大小为m\*n,并且设置默认零矩阵
def makematrix(m, n, fill=0.0):
    a = []
    for i in range(m):
        a.append([fill]\*n)
    return a
 
#函数sigmoid(),这里采用tanh,因为看起来要比标准的sigmoid函数好看
def sigmoid(x):
    return math.tanh(x)
 
#函数sigmoid的派生函数
def derived\_sigmoid(x):
    return 1.0 - x\*\*2
 
#构造三层BP网络架构
class BPNN:
    def \_\_init\_\_(self, num_in, num_hidden, num_out):
        #输入层,隐藏层,输出层的节点数
        self.num_in = num_in + 1  #增加一个偏置结点
        self.num_hidden = num_hidden + 1   #增加一个偏置结点
        self.num_out = num_out
        
        #激活神经网络的所有节点(向量)
        self.active_in = [1.0]\*self.num_in
        self.active_hidden = [1.0]\*self.num_hidden
        self.active_out = [1.0]\*self.num_out
        
        #创建权重矩阵
        self.wight_in = makematrix(self.num_in, self.num_hidden)
        self.wight_out = makematrix(self.num_hidden, self.num_out)
        
        #对权值矩阵赋初值
        for i in range(self.num_in):
            for j in range(self.num_hidden):
                self.wight_in[i][j] = random\_number(-0.2, 0.2)
        for i in range(self.num_hidden):
            for j in range(self.num_out):
                self.wight_out[i][j] = random\_number(-0.2, 0.2)
    
        #最后建立动量因子(矩阵)
        self.ci = makematrix(self.num_in, self.num_hidden)
        self.co = makematrix(self.num_hidden, self.num_out)        
        
    #信号正向传播
    def update(self, inputs):
        if len(inputs) != self.num_in-1:
            raise ValueError('与输入层节点数不符')
            
        #数据输入输入层
        for i in range(self.num_in - 1):
            #self.active_in[i] = sigmoid(inputs[i])  #或者先在输入层进行数据处理
            self.active_in[i] = inputs[i]  #active_in[]是输入数据的矩阵
            
        #数据在隐藏层的处理
        for i in range(self.num_hidden - 1):
            sum = 0.0
            for j in range(self.num_in):
                sum = sum + self.active_in[i] \* self.wight_in[j][i]
            self.active_hidden[i] = sigmoid(sum)   #active_hidden[]是处理完输入数据之后存储,作为输出层的输入数据
            
        #数据在输出层的处理
        for i in range(self.num_out):
            sum = 0.0
            for j in range(self.num_hidden):
                sum = sum + self.active_hidden[j]\*self.wight_out[j][i]
            self.active_out[i] = sigmoid(sum)   #与上同理
            
        return self.active_out[:]
    
    #误差反向传播
    def errorbackpropagate(self, targets, lr, m):   #lr是学习率, m是动量因子
        if len(targets) != self.num_out:
            raise ValueError('与输出层节点数不符!')
            
        #首先计算输出层的误差
        out_deltas = [0.0]\*self.num_out
        for i in range(self.num_out):
            error = targets[i] - self.active_out[i]
            out_deltas[i] = derived\_sigmoid(self.active_out[i])\*error
        
        #然后计算隐藏层误差
        hidden_deltas = [0.0]\*self.num_hidden
        for i in range(self.num_hidden):
            error = 0.0
            for j in range(self.num_out):
                error = error + out_deltas[j]\* self.wight_out[i][j]
            hidden_deltas[i] = derived\_sigmoid(self.active_hidden[i])\*error
        
        #首先更新输出层权值
        for i in range(self.num_hidden):
            for j in range(self.num_out):
                change = out_deltas[j]\*self.active_hidden[i]
                self.wight_out[i][j] = self.wight_out[i][j] + lr\*change + m\*self.co[i][j]
                self.co[i][j] = change
                
        #然后更新输入层权值
        for i in range(self.num_in):
            for i in range(self.num_hidden):
                change = hidden_deltas[j]\*self.active_in[i]
                self.wight_in[i][j] = self.wight_in[i][j] + lr\*change + m\* self.ci[i][j]
                self.ci[i][j] = change
                
        #计算总误差
        error = 0.0
        for i in range(len(targets)):
            error = error + 0.5\*(targets[i] - self.active_out[i])\*\*2
        return error
 
    #测试
    def test(self, patterns):
        for i in patterns:
            print(i[0], '->', self.update(i[0]))
    #权重
    def weights(self):
        print("输入层权重")
        for i in range(self.num_in):
            print(self.wight_in[i])
        print("输出层权重")
        for i in range(self.num_hidden):
            print(self.wight_out[i])