# _*_ 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实现)--第五章 误差反向传播 01
最新推荐文章于 2024-07-08 11:38:25 发布