深度学习入门(基于python实现)--第五章 误差反向传播 01

# _*_ coding:UTF-8 _*_
# 文件名:Error_BackPropagation_01.py
# 开发工具:PyCharm
"""
下面介绍一种高效的计算权重方法,误差反向传播
计算图
用图的形式来表示数据的求解过程
比如表示买两个苹果,并且要交10%的税
一个苹果100元

          100         200                 220
一个苹果-------→ ×2 -------→ 交税 ×1.1 --------→ 总支出220

上面这个计算图从左到右是正向传播,也就是从出发点到结束点
反之便是反向传播,即从结束点到出发点

计算图有个特性:局部计算,也就是对于某个计算,只关心自己那部分计算,其他部分计算对其没有影响
打个比方,比如你要买2个苹果,3个梨,4个西瓜,对于苹果来说,只要把苹果价格乘2即可,而另外西瓜和梨的计算过程和结果对
苹果没有影响,苹果也不需要关心这个过程。也可以看做工厂流水线上工人,只要做好自己部分工作即可。

正向传播可以计算数值,反向传播总不能倒着再把数值算出来吧?所以反向传播需要干点不同的东西,即算出节点导数值。
还是上面那个买苹果
            *2.2        *1.1               *1
一个苹果 ←------- ×2 ←------- 交税 ×1.1 ←------- 总支出220

什么意思呢,就是一个苹果涨价x元, 那么最终总支出会增加2.2x元

ok,那么如何来计算呢?大致方法和求导数没啥太大区别,对于加减节点,传过来的导数值不变,对于乘除节点,对应乘上节点的导数值
以上面这个苹果为例
            *3.3            *1.1
一个西瓜-----------x3 --------- 交税 *1.1    *1
                                            ↖
              *2.2        *1.1              ↙ +结点   ------ 总支出220
一个苹果 ←------- ×2 ←------- 交税 ×1.1 ↙ *1             *1

假设我现在还要要买3个西瓜,对于+节点,只是简单的加上所耗费的钱财,所以从右边传过来的导数值依旧传到下游
对于交税节点,假设左边传过来值为 x ,向右边传出的值为y  可得 y = 1.1x ,节点导数值为1.1,那么当右边导数值传来
的时候,就要乘上这个1.1,变成1.1,继续向左边传去。
和导数的链式法则很像

在这里,我们把乘法节点称作“乘法层”,加法节点称作“加法层”
"""


class MulLayer(object):
    """乘法层的实现"""

    def __init__(self):
        """保存正向传播时x和y的值"""
        self.x = None
        self.y = None

    def forward(self, x, y):
        """正向传播"""
        self.x = x
        self.y = y
        out = x * y
        return out

    def backward(self, dout):
        """反向传播,将上游传过来的导数值dout乘以该节点的导数值"""
        dx = dout * self.y
        dy = dout * self.x

        return dx, dy


apple = 100
apple_num = 2
tax = 1.1

# layer
mul_apple_layer = MulLayer()  # 买两个苹果
mul_tax_layer = MulLayer()  # 交税

# forward
apple_price = mul_apple_layer.forward(apple, apple_num)
price = mul_tax_layer.forward(apple_price, tax)

print(price)

# backward
dprice = 1  # 初始导数值
dapple_price, dtax = mul_tax_layer.backward(dprice)
dapple, dapple_num = mul_apple_layer.backward(dapple_price)
print(dapple, dapple_num, dtax)


# 加法层实现
class AddLayer(object):
    """加法层的实现"""

    def __init__(self):
        pass

    def forward(self, x, y):
        """正向传播"""
        out = x + y
        return out

    def backward(self, dout):
        """反向传播,将上游传过来的导数值dout乘以该节点的导数值"""
        dx = dout * 1
        dy = dout * 1

        return dx, dy


# ok,下面来试着进行买两个苹果和三个橘子的反向传播

apple = 100
apple_num = 2
orange = 150
orange_num = 3
tax = 1.1

# layer
mul_apple_layer = MulLayer()
mul_orange_layer = MulLayer()
add_apple_orange_layer = AddLayer()
mul_tax_layer = MulLayer()

# forward
apple_price = mul_apple_layer.forward(apple, apple_num)  # (1)
orange_price = mul_orange_layer.forward(orange, orange_num)  # (2)
all_price = add_apple_orange_layer.forward(apple_price, orange_price)  # (3)  加法层
price = mul_tax_layer.forward(all_price, tax)  # (4)  算税率

# backward
dprice = 1
dall_price, dtax = mul_tax_layer.backward(dprice)  # (4)  
dapple_price, dorange_price = add_apple_orange_layer.backward(dall_price)  # (3)  加法层直接返回
dorange, dorange_num = mul_orange_layer.backward(dorange_price)  # (2)
dapple, dapple_num = mul_apple_layer.backward(dapple_price)  # (1)

print("price:", int(price))
print("dApple:", dapple)
print("dApple_num:", int(dapple_num))
print("dOrange:", dorange)
print("dOrange_num:", int(dorange_num))
print("dTax:", dtax)


你可能感兴趣的:(深度学习,人工智能,深度学习,python)