TensorFlow(四)反向传播算法(BP)

通过前面几篇建立的神经网络以上一层的输出作为下一层的输入。这种⽹络被称为前馈神经网络。这意味着网络中是没有回路的 —— 信息总是向前传播,从不反向回馈。如果确实有回路,我们最终会有这样的情况:σ 函数的输⼊依赖于输出。这将难于理解,所以我们不允许这样的环路。(前馈 指的是拓扑学上的向前单向传播)

BP神经网络是一种多层的前馈神经网络,其主要的特点是:信号是前向传播的,而误差是反向传播的。BP神经网络的过程主要分为两个阶段,第一阶段是信号的前向传播,从输入层经过隐含层,最后到达输出层;第二阶段是误差的反向传播,从输出层到隐含层,最后到输入层,依次调节隐含层到输出层的权重和偏置,输入层到隐含层的权重和偏置

 

呢么怎样修正权值呢?

这需要将误差逐层向前传递优化整个神经网络的每一个神经元 

                                

                                

                                

                                

                               

由此,我们得到权重更新公式

下面我们来完成一个BP神经网络: 


import numpy as np
import math
import random

def rand(a , b):
    return (b - a) * random.random() + a #random.random()返回随机生成的一个实数,它在[0,1)范围内

#生成一个m * n的矩阵
def make_matrix(m , n , fill = 0.0):
    mat = []
    for i in range(m):
        mat.append([fill] * n)
    return mat

#定义sigmoid函数
def sigmoid(x):
    return 1.0 / (1.0 + math.exp(-x))

#定义sigmoid导函数 sigmoid具有f'(x) = f(x)(1 - f(x))的性质
def sigmoid_derivate(x):
    return x * (1 - x)

class BPNeuralNetwork:
    
    def __init__(self):
        self.input_n = 0
        self.hidden_n = 0
        self.output_n = 0
        self.input_cells = []
        self.hidden_cells = []
        self.output_cells = []
        self.input_weights = []
        self.output_weights = []
        
    def setup(self , ni , nh , no):
        self.input_n = ni + 1
        self.hidden_n = nh
        self.output_n = no
        
        self.input_cells = [1.0] * self.input_n
        self.hidden_cells = [1.0] * self.hidden_n
        self.output_cells = [1.0] * self.output_n
        
        self.input_weights = make_matrix(self.input_n , self.hidden_n)
        self.output_weights = make_matrix(self.hidden_n , self.output_n)
        
        # 生成随机权值
        for i in range(self.input_n):
            for h in range(self.hidden_n):
                self.input_weights[i][h] = rand(-0.2 , 0.2)
        for h in range(self.hidden_n):
            for o in range(self.output_n):
                self.output_weights[h][o] = rand(-2.0 , 2.0)
    
    #完成前向计算          
    def predict(self , inputs):
        
        for i in range(self.input_n - 1):
            self.input_cells[i] = inputs[i]
            
        for j in range(self.hidden_n):
            total = 0.0
            #完成矩阵的乘法
            for i in range(self.input_n):
                total += self.input_cells[i] * self.input_weights[i][j]
            self.hidden_cells[j] = sigmoid(total)
            
        for k in range(self.output_n):
            total = 0.0
            for j in range(self.hidden_n):
                total += self.hidden_cells[j] * self.output_weights[j][k]
            self.output_cells[k] = sigmoid(total)

        return self.output_cells[:]
    
    def back_propagate(self , case , label , learn):
        
        #输入 得到 运算结果
        self.predict(case)
        
        #计算输出层的误差
        output_deltas = [0.0] * self.output_n
        for k in range(self.output_n):
            error = label[k] - self.output_cells[k]
            output_deltas[k] = sigmoid_derivate(self.output_cells[k]) * error
          
        #计算隐藏层误差    
        hidden_deltas = [0.0] * self.hidden_n
        for j in range(self.hidden_n):
            error = 0.0
            for k in range(self.output_n):
                error += output_deltas[k] * self.output_weights[j][k]
            hidden_deltas[j] = sigmoid_derivate(self.hidden_cells[k]) * error
            
        #更新输出层权重
        for j in range(self.hidden_n):
            for k in range(self.output_n):
                self.output_weights[j][k] += learn * output_deltas[k] * self.hidden_cells[j]
                
        #更新隐藏层权重
        for i in range(self.input_n):
            for j in range(self.hidden_n):
                self.input_weights[i][j] += learn * hidden_deltas[j] * self.input_cells[i]
                
        error = 0
        for o in range(len(label)):
            error += 0.5 * (label[o] - self.output_cells[o]) ** 2
            
        return error
    
    #使用前馈训练模型
    def train(self , cases , labels , limit = 100 , learn = 0.05):
        for i in range(limit):
            error = 0
            for i in range(len(cases)):
                label = labels[i]
                case = cases[i]
                error += self.back_propagate(case , label , learn)
        pass
        
    def test(self):
        #训练BP神经网络
        #输入
        cases = [
            [0 , 0],
            [0 , 1],
            [1 , 0],
            [1 , 1],
        ]
        #正确输出
        labels = [[0] , [0.5] , [0.5] , [1]]
        self.setup(2 , 5 , 1)
        self.train(cases , labels , 10000 , 0.05)
        #将测试集输入测试
        for case in cases:
            print(self.predict(case))

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

输出为:

可以看到与测试的label接近 可以说说明这个神经网络是有效的

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值