当前位置:   article > 正文

人工智能初级算法——误差反向传播算法(BP)_误差反向传播算法 单个神经元

误差反向传播算法 单个神经元

误差反向传播算法(BP)

一、神经网络基本概念

二、神经元模型

神经元细胞示意图
在这里插入图片描述
在这里插入图片描述

1. 单个神经元

1> 感知器模型

在这里插入图片描述

2> 输入与输出
3> 激活函数

S i g m o i d ( x ) = 1 1 + e − x Sigmoid(x) = \frac{1}{1+e^{-x}} Sigmoid(x)=1+ex1
在这里插入图片描述
S i g m o i d ′ ( x ) = S i g m o i d ( x ) ∗ ( 1 − S i g m o i d ( x ) ) Sigmoid'(x) = Sigmoid(x) * (1 - Sigmoid(x)) Sigmoid(x)=Sigmoid(x)(1Sigmoid(x))

2. 单个神经元的学习

1> 识别

在这里插入图片描述

3. 多层神经元模型

在这里插入图片描述

三、误差反向传播算法(BP)

1. 算法的推导

在这里插入图片描述

符号说明:

  • X: 输入向量
  • Y t r u e Y_{true} Ytrue: 输入向量 X 对应的真实结果
  • Y p r e d Y_{pred} Ypred: 根据输入向量 X 预测的结果
  • Yi: 向量的某个分量
  • h_in: 隐藏层输入
  • h_out: 隐藏层输出(经过激活函数处理)
  • h_w: 隐藏层权重矩阵
  • output_in: 输出层输入
  • output_out: 输出层输出(经过激活函数处理)
  • output_w: 输出层权重矩阵
1> 输出层权重偏导

已知对于某个训练样例 d 的误差函数:
E r r o r = 1 2 ∗ ∑ i ∈ o u t p u t ( Y i t r u e − Y i p r e d ) 2 Error = \frac{1}{2} * \sum_{i \in output}(Yi_{true}-Yi_{pred})^2 Error=21ioutput(YitrueYipred)2
可得,总误差函数对输出层权重 w 35 w_{35} w35 的偏导数:
∂ E ∂ w 35 = ∂ E ∂ o u t p u t 5 _ o u t ∗ ∂ o u t p u t 5 _ o u t ∂ o u t p u t 5 _ i n ∗ ∂ o u t p u t 5 _ i n ∂ w 35 \frac{\partial{E}}{\partial{w_{35}}} = \frac{\partial{E}}{\partial{output5\_out}} * \frac{\partial{output5\_out}}{\partial{output5\_in}} * \frac{\partial{output5\_in}}{\partial{w_{35}}} w35E=output5_outEoutput5_inoutput5_outw35output5_in
各项展开得:
∂ E ∂ o u t p u t 5 _ o u t = − ( Y 5 t r u e − o u t p u t 5 _ o u t ) \frac{\partial{E}}{\partial{output5\_out}} = -(Y5_{true} - output5\_out) output5_outE=(Y5trueoutput5_out)
∂ o u t p u t 5 _ o u t ∂ o u t p u t 5 _ i n = S i g m o i d ( o u t p u t 5 _ i n ) ∗ ( 1 − S i g m o i d ( o u t p u t 5 _ i n ) ) \frac{\partial{output5\_out}}{\partial{output5\_in}} = Sigmoid(output5\_in)*(1-Sigmoid(output5\_in)) output5_inoutput5_out=Sigmoid(output5_in)(1Sigmoid(output5_in))
output5_in = h3_out * w_{35} + h4_out * w_{45}
∂ o u t p u t _ i n ∂ w 35 = h 3 _ o u t \frac{\partial{output\_in}}{\partial{w_{35}}} = h3\_out w35output_in=h3_out

最终偏导为:
∂ E ∂ w 35 = − ( Y 5 t r u e − o u t p u t 5 _ o u t ) ∗ S i g m o i d ( o u t p u t 5 _ i n ) ∗ ( 1 − S i g m o i d ( o u t p u t 5 _ i n ) ) ∗ h 3 _ o u t \frac{\partial{E}}{\partial{w35}} = -(Y5_{true} - output5\_out) * Sigmoid(output5\_in)*(1-Sigmoid(output5\_in)) * h3\_out w35E=(Y5trueoutput5_out)Sigmoid(output5_in)(1Sigmoid(output5_in))h3_out

2> 隐藏层权重偏导

总体上,隐藏层权重偏导公式如下:
∂ E ∂ w 13 = ∂ E ∂ h 3 _ o u t ∗ ∂ h 3 _ o u t ∂ h 3 _ i n ∗ ∂ h 3 _ i n ∂ w 13 \frac{\partial{E}}{\partial{w_{13}}} = \frac{\partial{E}}{\partial{h3\_out}} * \frac{\partial{h3\_out}}{\partial{h3\_in}} * \frac{\partial{h3\_in}}{\partial{w_{13}}} w13E=h3_outEh3_inh3_outw13h3_in
展开,得:
∂ E ∂ w 13 = ∂ E ∂ h 3 _ o u t ∗ S i g m o i d ( h 3 _ i n ) ∗ ( 1 − S i g m o i d ( h 3 _ i n ) ) ∗ x 1 \frac{\partial{E}}{\partial{w_{13}}} = \frac{\partial{E}}{\partial{h3\_out}} * Sigmoid(h3\_in) * (1 - Sigmoid(h3\_in))* x_1 w13E=h3_outESigmoid(h3_in)(1Sigmoid(h3_in))x1
仔细分析,我们只需对权重 w 13 w_{13} w13 直接影响的节点求导即可:
∂ E ∂ h 3 _ o u t = ∑ i ∈ D o w n s t r e a m ( h 3 ) ∂ E ∂ o u t p u t i _ o u t ∗ ∂ o u t p u t i _ o u t ∂ o u t p u t i _ i n ∗ ∂ o u t p u t i _ i n ∂ h 3 _ o u t \frac{\partial{E}}{\partial{h3\_out}} = \sum_{i \in Downstream(h3)} \frac{\partial{E}}{\partial{outputi\_out}} * \frac{\partial{outputi\_out}}{\partial{outputi\_in}} * \frac{\partial{outputi\_in}}{\partial{h3\_out}} h3_outE=iDownstream(h3)outputi_outEoutputi_inoutputi_outh3_outoutputi_in
各项展开得:
∂ E ∂ h 3 _ o u t = ∑ i ∈ D o w n s t r e a m ( h 3 ) − ( Y i t r u e − o u t p u t i _ o u t ) ∗ S i g m o i d ( o u t p u t i _ i n ) ∗ ( 1 − S i g m o i d ( o u t p u t i _ i n ) ) ∗ w 3 i \frac{\partial{E}}{\partial{h3\_out}} = \sum_{i \in Downstream(h3)} -(Yi_{true} - outputi\_out) * Sigmoid(outputi\_in) * (1 - Sigmoid(outputi\_in)) * w_{3i} h3_outE=iDownstream(h3)(Yitrueoutputi_out)Sigmoid(outputi_in)(1Sigmoid(outputi_in))w3i

3. 训练

1> 调整单个权重 w。我们追求误差减小,故,有以下公式:

w 35 = w 35 − Δ w 35 w_{35} = w_{35} - \Delta w_{35} w35=w35Δw35
定义学习速率: r r r
w 35 = w 35 − r ∗ ∂ E ∂ w 35 w_{35} = w_{35} - r * \frac{\partial{E}}{\partial{w_{35}}} w35=w35rw35E
输出层权重调整:
w 35 = w 35 + r ∗ ( Y 5 t r u e − o u t p u t 5 _ o u t ) ∗ S i g m o i d ( o u t p u t 5 _ i n ) ∗ ( 1 − S i g m o i d ( o u t p u t 5 _ i n ) ) ∗ h 3 _ o u t w_{35} = w_{35} + r * (Y5_{true} - output5\_out) * Sigmoid(output5\_in)*(1-Sigmoid(output5\_in)) * h3\_out w35=w35+r(Y5trueoutput5_out)Sigmoid(output5_in)(1Sigmoid(output5_in))h3_out
w 45 = w 45 + r ∗ ( Y 5 t r u e − o u t p u t 5 _ o u t ) ∗ S i g m o i d ( o u t p u t 5 _ i n ) ∗ ( 1 − S i g m o i d ( o u t p u t 5 _ i n ) ) ∗ h 4 _ o u t w_{45} = w_{45} + r * (Y5_{true} - output5\_out) * Sigmoid(output5\_in)*(1-Sigmoid(output5\_in)) * h4\_out w45=w45+r(Y5trueoutput5_out)Sigmoid(output5_in)(1Sigmoid(output5_in))h4_out
w 36 = w 36 + r ∗ ( Y 6 t r u e − o u t p u t 6 _ o u t ) ∗ S i g m o i d ( o u t p u t 6 _ i n ) ∗ ( 1 − S i g m o i d ( o u t p u t 6 _ i n ) ) ∗ h 3 _ o u t w_{36} = w_{36} + r * (Y6_{true} - output6\_out) * Sigmoid(output6\_in)*(1-Sigmoid(output6\_in)) * h3\_out w36=w36+r(Y6trueoutput6_out)Sigmoid(output6_in)(1Sigmoid(output6_in))h3_out
w 46 = w 46 + r ∗ ( Y 6 t r u e − o u t p u t 6 _ o u t ) ∗ S i g m o i d ( o u t p u t 6 _ i n ) ∗ ( 1 − S i g m o i d ( o u t p u t 6 _ i n ) ) ∗ h 4 _ o u t w_{46} = w_{46} + r * (Y6_{true} - output6\_out) * Sigmoid(output6\_in)*(1-Sigmoid(output6\_in)) * h4\_out w46=w46+r(Y6trueoutput6_out)Sigmoid(output6_in)(1Sigmoid(output6_in))h4_out
利用矩阵运算简化
o w + = r ∗ ( Y 5 t r u e − Y 5 p r e d Y 6 t r u e − Y 6 p r e d ) ⋅ S i g m o i d ′ ( o u t p u t 5 _ i n o u t p u t 6 _ i n ) × ( h 3 _ o u t h 4 _ o u t ) ow += r * \left(

Y5trueY5predY6trueY6pred
\right) \cdot Sigmoid'\left(
output5_inoutput6_in
\right) \times \left(
h3_outh4_out
\right) ow+=r(Y5trueY5predY6trueY6pred)Sigmoid(output5_inoutput6_in)×(h3_outh4_out)
继续化简(默认向量为列向量):
o w + = r ∗ ( Y t r u e − Y p r e d ) ⋅ S i g m o i d ′ ( o u t p u t _ i n ) × h _ o u t . T ow += r * (Y_{true} - Y_{pred}) \cdot Sigmoid'(output\_in) \times h\_out.T ow+=r(YtrueYpred)Sigmoid(output_in)×h_out.T
令:
o u t p u t _ e r r o r s = ( Y t r u e − Y p r e d ) output\_errors = (Y_{true} - Y_{pred}) output_errors=(YtrueYpred)
则:
h w + = r ∗ ( o u t p u t _ e r r o r s ⋅ S i g m o i d ′ ( o u t p u t _ i n ) ) × h _ o u t . T hw += r * (output\_errors \cdot Sigmoid'(output\_in)) \times h\_out.T hw+=r(output_errorsSigmoid(output_in))×h_out.T

隐藏层权重调整:
w 13 = w 13 + r ∗ S i g m o i d ′ ( h 3 _ i n ) ∗ x 1 ∗ ∑ i ∈ D o w n s t r e a m ( h 3 ) ( Y i t r u e − o u t p u t i _ o u t ) ∗ S i g m o i d ′ ( o u t p u t i _ i n ) ∗ w 3 i w_{13} = w_{13} + r * Sigmoid'(h3\_in) * x_1 * \sum_{i \in Downstream(h3)} (Yi_{true} - outputi\_out) * Sigmoid'(outputi\_in) * w_{3i} w13=w13+rSigmoid(h3_in)x1iDownstream(h3)(Yitrueoutputi_out)Sigmoid(outputi_in)w3i

w 23 = w 23 + r ∗ S i g m o i d ′ ( h 3 _ i n ) ∗ x 2 ∗ ∑ i ∈ D o w n s t r e a m ( h 3 ) ( Y i t r u e − o u t p u t i _ o u t ) ∗ S i g m o i d ′ ( o u t p u t i _ i n ) ∗ w 3 i w_{23} = w_{23} + r * Sigmoid'(h3\_in) * x_2 * \sum_{i \in Downstream(h3)} (Yi_{true} - outputi\_out) * Sigmoid'(outputi\_in) * w_{3i} w23=w23+rSigmoid(h3_in)x2iDownstream(h3)(Yitrueoutputi_out)Sigmoid(outputi_in)w3i

w 14 = w 14 + r ∗ S i g m o i d ′ ( h 4 _ i n ) ∗ x 1 ∗ ∑ i ∈ D o w n s t r e a m ( h 4 ) ( Y i t r u e − o u t p u t i _ o u t ) ∗ S i g m o i d ′ ( o u t p u t i _ i n ) ∗ w 4 i w_{14} = w_{14} + r * Sigmoid'(h4\_in) * x_1 * \sum_{i \in Downstream(h4)} (Yi_{true} - outputi\_out) * Sigmoid'(outputi\_in) * w_{4i} w14=w14+rSigmoid(h4_in)x1iDownstream(h4)(Yitrueoutputi_out)Sigmoid(outputi_in)w4i

w 24 = w 24 + r ∗ S i g m o i d ′ ( h 4 _ i n ) ∗ x 2 ∗ ∑ i ∈ D o w n s t r e a m ( h 4 ) ( Y i t r u e − o u t p u t i _ o u t ) ∗ S i g m o i d ′ ( o u t p u t i _ i n ) ∗ w 4 i w_{24} = w_{24} + r * Sigmoid'(h4\_in) * x_2 * \sum_{i \in Downstream(h4)} (Yi_{true} - outputi\_out) * Sigmoid'(outputi\_in) * w_{4i} w24=w24+rSigmoid(h4_in)x2iDownstream(h4)(Yitrueoutputi_out)Sigmoid(outputi_in)w4i
利用矩阵简化:
h w i j + = r ∗ S i g m o i d ′ ( h j _ i n h j _ i n ) ⋅ ( x 1 x 2 ) × ∑ k ∈ D o w n s t r e a m ( h j ) ( Y k t r u e − Y k p r e d ) ⋅ S i g m o i d ′ ( o u t p u t k _ i n ) × w j k hw_{ij} += r * Sigmoid'\left(

hj_inhj_in
\right) \cdot \left(
x1x2
\right) \times \sum_{k \in Downstream(h_j)} ( Yk_{true} - Yk_{pred} ) \cdot Sigmoid'( outputk\_{in} ) \times w_{jk} hwij+=rSigmoid(hj_inhj_in)(x1x2)×kDownstream(hj)(YktrueYkpred)Sigmoid(outputk_in)×wjk
令(默认向量为列向量):
h i d d e n _ e r r o r s = o u t p u t _ w . T × ( ( Y k t r u e − Y k p r e d ) ⋅ S i g m o i d ′ ( o u t p u t _ i n ) ) hidden\_errors = output\_w.T \times ((Yk_{true} - Yk_{pred} ) \cdot Sigmoid'( output\_{in}) ) hidden_errors=output_w.T×((YktrueYkpred)Sigmoid(output_in))
带入得(默认向量为列向量):
h w + = r ∗ ( h i d d e n _ e r r o r s ⋅ S i g m o i d ′ ( h _ i n ) ) × X . T hw += r * (hidden\_errors \cdot Sigmoid'(h\_in)) \times X.T hw+=r(hidden_errorsSigmoid(h_in))×X.T

2> 随机梯度下降
  1. 对训练样本中的每一个数据,进行一次训练
  2. 对整个样本进行多次(例如:100次)训练

4. 编码

#_author :NineSun
#data: 2019-10-12

import  numpy as np

def activate(x):
    return 1/(1+np.exp(-x))
def activate_de(x):
    return activate(x)*(1-activate(x))
class NeutualNetWork:
    # 构造方法,用于构造神经网络
    def __init__(self):
        # 隐藏层权重矩阵
        self.hw=np.random.normal(np.zeros((2,2)))
        # 输出层权重矩阵
        self.ow=np.random.normal(np.zeros((2,2)))
        # 学习速率
        self.r=0.1
        # 训练遍数
        self.epoch=100

    # 预测函数,根据输入数据预测结果
    # x:输入向量
    def prdict(self,x):
        # 将输入向量转化为列向量
        x=np.array(x,ndmin=2).T
        # 计算隐藏层输入
        h_in=np.dot(self.hw,x)
        # 计算隐藏层输出
        h_out = activate(h_in)
        # 计算输出层输入 output_in
        output_in=np.dot(self.ow,h_out)
        # 计算输出层输出
        output_out=activate(output_in)
        return output_out

    # 训练神经网络
    # x_data:输入数据集
    # ytrue_data:输出数据集
    def train(self,x_data,ytrue_data):
        # 训练epoch遍
        for i in range(self.epoch):
            # 针对每一个样本训练一遍
            for data in zip(x_data,ytrue_data):
                self.train_once(data[0],data[1])


    # 针对一个样本(x,ytrue)进行训练
    def train_once(self,x,ytrue):
        '''
        :param x: 输入行向量
        :param ytrue: 输出行向量
        :return:
        '''
        # 将输入输出向量转化为列向量
        x = np.array(x, ndmin=2).T
        ytrue = np.array(ytrue, ndmin=2).T


        # 根据输入计算 Ypred,output_out
        h_in=np.dot(self.hw,x)
        h_out=activate(h_in)
        output_in=np.dot(self.ow,h_out)
        output_out=activate(output_in)

        # 计算输出误差
        output_errors=ytrue-output_out
        cal_tmp=output_errors*activate_de(output_in)
        # 更新输出层权重
        self.ow+=self.r*np.dot(cal_tmp,h_out.T)

        # 计算隐藏层误差
        hidden_errors=np.dot(self.ow.T,cal_tmp)

        # 更新隐藏层权重
        self.hw+=self.r*np.dot(hidden_errors*activate_de(h_in),x.T)

    # 1.准备数据
in_data = [
        [165, 55],
        [160, 53],
        [175, 55],
        [163, 55],
        [173, 49],
        [163, 56],
        [180, 77],
        [155, 54],
        [176, 79],
        [161, 49],
        [180, 60],
        [168, 57],
        [172, 69],
        [166, 50],
        [172, 90],
        [163, 51],
        [175, 70],
        [164, 53],
        [160, 45],
        [160, 56],
        [182, 70],
        [180, 74],
        [185, 73],
        [165, 55],
        [185, 75]
    ]
out_data = [
            [1,0],
            [0,1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1],
            [1, 0],
            [0, 1]
    ]
    # 测试数据
in_test=[
        [165, 55],
        [160, 53],
        [175, 55],
        [163, 55],
        [173, 49]
    ]
out_test=[
        [0,1],
        [0, 1],
        [1, 0],
        [0, 1],
        [1, 0],
    ]

nn = NeutualNetWork()
    # 3.训练
nn.train(in_data,out_data)
    # 4.预测
for test in zip(in_test,out_test):
        ypred=nn.prdict(test[0])
        print("in:",test[0],"yture:",test[1])
        print("predit:",ypred)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161

这串代码可以直接运行

五、 算法优化

1. 指定网络结构

可随意指定:输入层,隐藏层,输出层的神经元个数

2. 存储当前神经网络的训练数据

将神经网络结构,包括:学习速率,训练次数和所有权重矩阵存成文件,以便以后可以不必训练,加载数据后可直接进行预测。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/477576
推荐阅读
相关标签
  

闽ICP备14008679号