第五章 误差反向传播法 第六节
Affine层
现将求矩阵于偏置的和的运算用计算图表示出来。将乘积运用“dot”节点表示,则np.daot(x,w)+B的运算可用下图表示,并且在变量上面标记他们的形状。
反向传播的示意图为
图中左上角那两个公式我没有去推到,等需要我了解更加深入一层的时候再推导吧。
各个变量的形状。尤其要注意,X和αL/αX形状相同,W和αL/αW形状相同。从下面的数学式可以很明确地看出X和αL/αX形状相同。
书上说αL/αY形状是(3,),W的形状是(2, 3)时,思考 和WT的乘积,使得αL/αX的形状为(2,)
这样一来,就会自然而然地推导出上上副图左上角的那个公式了。我就是很不明白,只是矩阵形状一样而已,为什么相乘就相等了,迷迷糊糊。
批版本的Affine层
之前Affine层的输入都是以单个数据为对象。现在我们考虑N个数据一起正向传播的的情况。
批版本Affine层的计算图
与之前不同的是输入的X的形状是(N,2),反向传播和单个的时候一样的推导。加上偏置时,需要特别注意。正向传播时,偏置被加到X·W的各个数据上。
class Affine:
def __init__(self,W,b):
self.W = W
self.b = b
self.x = None
self.dW = None
self.db = None
def forward(self,x):
self.x = x
out = np.dot(x,self.W)+self.b
return out
def backward(self,dout):
dx = np.dot(dout,self.W.T)
self.dW = np.dot(self.x.T,dout)
self.db = np.sum(dout,axis=0)
这一小节的代码感觉不难,但是就是这个反向传播这个公式感觉还是不太懂,主要是我道行太浅了。等我再修炼几个月,说不定就晓得是啥子啦。
Softmax-with-Loss
softmax层的输出的示意图
实现代码其实也是套公式就是方向传播的公式书上没有具体推。到时候要用的时候,再细看公式是怎么推的吧
import sys, os
sys.path.append(os.pardir) # 为了导入父目录中的文件而进行的设定
sys.path.append('H:/pythonfile/ch01/')
sys.path.append('H:/pythonfile/ch03/')
import numpy as np
from mini_batch import *
from activeFunction import *
class Relu:
def __init__(self):
self.mask = None
def forward(self,x):
self.mask = (x <= 0)
out = x.copy()
out[self.mask] = 0
return out
def backward(self,dout):
dout[self.mask] = 0
dx = dout
return dx
class sigmiod:
def __init__(self):
self.out = None
def forward(self,x):
out = 1/(1+np.exp(-x))
self.out = out
return out
def backward(self,dout):
dx = dout*(1.0-self.out)*self.out
return
class Affine:
def __init__(self,W,b):
self.W = W
self.b = b
self.x = None
self.dW = None
self.db = None
def forward(self,x):
self.x = x
out = np.dot(x,self.W)+self.b
return out
def backward(self,dout):
dx = np.dot(dout,self.W.T)
self.dW = np.dot(self.x.T,dout)
self.db = np.sum(dout,axis=0)
class SoftmaxWithLoss:
def __init__(self):
self.loss = None # 损失
self.y = None # softmax的输出
self.t = None # 监督数据(one-hot vector)
def forward(self, x, t):
self.t = t
self.y = activeFunction.softmax(x)
self.loss = mini_batch.cross_entropy_error(self.y, self.t)
return self.loss
def backward(self, dout=1):
batch_size = self.t.shape[0]
dx = (self.y - self.t) / batch_size
return dx