第四章.误差反向传播法
4.1 简单层的实现
本章主要讲述的是加法层(AddLayer)和乘法层(MulLayer)的实现过程。
1.加法层(AddLayer)
从正向传播和反向传播两个层面进行分析。
1).示例:
- 以z=x+y为对象,观察它的传播。z=x+y的导数:
∂z/∂x=1,∂z/∂y=1
2).图像说明:
-
正向传播:(灰色箭头:从左到右进行计算)
①.加法节点“+”,用来计算x和y的和,然后传递给下一个节点z。
-
反向传播:(黑色箭头:从右向左进行计算)
①.从上游传递过来的导数值设置为:
∂L/∂z
,乘以1,然后传递给下游。 -
总结:
①.加法节点的反向传播只乘以1,所以输入的值会原封不动的流到下一个节点
3).代码实现:
class AddLayer:
def __init__(self):
pass
# 正向传播
def forward(self, x, y):
out = x + y
return out
# 反向传播
def backward(self, dout):
dx = dout * 1
dy = dout * 1
return dx, dy
add_layer = AddLayer()
# 正向传播
x, y = 5, 10
sum = add_layer.forward(x, y)
print('正向传播:', sum)
# 反向传播
dsum = 1.3
dx, dy = add_layer.backward(dsum)
print('正向传播:', dx, dy)
4).结果展示:
2.乘法层(MulLayer)
从正向传播和反向传播两个层面进行分析。
1).示例:
- 以z=xy为对象,观察它的传播。z=xy的导数:
∂z/∂x=y,∂z/∂y=x
2).图像说明:
-
正向传播(灰色箭头:从左到右进行计算)
①.乘法节点“x”,用来计算x和y的乘积,然后传递给下一个节点z。
-
反向传播(黑色箭头:从右向左进行计算)
①.从上游传递过来的导数值设置为:
∂L/∂z
,乘以正向传播时输入信号的“翻转值”后传递给下游。 -
总结:
①.乘法节点的反向传播会将上游的值乘以正向传播时的输入信号的“翻转值”后传递给下游。
3).代码实现:
- 示例:太郎在超市买了2个100日元一个的苹果,消费税是10%,计算消费金额:
·代码:
class MulLayer:
def __init__(self):
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):
dx = dout * self.y
dy = dout * self.x
return dx, dy
mul_apple_layer = MulLayer()
mul_tax_layer = MulLayer()
apple = 100
apple_num = 2
tax = 1.1
# 正向传播
apple_price = mul_apple_layer.forward(apple, apple_num)
price = mul_tax_layer.forward(apple_price, tax)
print('price:', price)
# 反向传播
dprice = 1
dapple_price, dtax = mul_tax_layer.backward(dprice)
dapple, dapple_num = mul_apple_layer.backward(dapple_price)
print('apple,apple_num,tax:', str(dapple) + "," + str(dapple_num) + "," + str(dtax))
4).结果展示:
3.链式法则
- 反向传播是基于链式法则的
1).性质:
- 如果某个函数用复合函数表示,则该复合函数的导数可以用构成复合函数的各个函数导数的乘积表示。
2).数学式:
- 比如z=(x+y)2
4.加法层和乘法层的联合使用
1).示例:
- 示例:太郎在超市买了2个苹果,3个橘子,苹果每个100日元,橘子每个150日元,消费税是10%,计算消费金额。
2).代码:
# 乘法层
class MulLayer:
def __init__(self):
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):
dx = dout * self.y
dy = dout * self.x
return dx, dy
# 加法层
class AddLaye:
def __init__(self):
pass
# 正向传播
def forward(self, x, y):
out = x + y
return out
# 反向传播
def backward(self, dout):
dx = dout * 1
dy = dout * 1
return dx, dy
mul_apple_layer = MulLayer()
mul_orange_layer = MulLayer()
mul_tax_layer = MulLayer()
add_layer = AddLaye()
apple = 100
apple_num = 2
orange = 150
orange_num = 3
tax = 1.1
# 正向传播
apple_price = mul_apple_layer.forward(apple, apple_num)
orange_price = mul_orange_layer.forward(orange, orange_num)
apple_orange_price = add_layer.forward(apple_price, orange_price)
price = mul_tax_layer.forward(apple_orange_price, tax)
print('price:', price)
# 反向传播
dprice = 1
dapple_orange_price, dtax = mul_tax_layer.backward(dprice)
dapple, dorange = add_layer.backward(dapple_orange_price)
dapple_price, dapple_num = mul_apple_layer.backward(dapple)
dorange_price, dorange_num = mul_orange_layer.backward(dorange)
print('apple_price,apple_num,tax:', str(dapple_price) + "," + str(dapple_num) + "," + str(dtax))
print('orange_price,orange_num,tax:', str(dorange_price) + "," + str(dorange_num) + "," + str(dtax))