机器学习入门(12)— 激活函数层 ReLU、Sigmoid 层的实现
1. ReLU 函數(shù)層
激活函數(shù) ReLU(Rectified Linear Unit)由下式(5.7)表示。
通過式(5.7),可以求出 y 關(guān)于 x 的導(dǎo)數(shù),如式(5.8)所示。
在式(5.8)中,如果正向傳播時(shí)的輸入 x 大于0,則反向傳播會將上游的值原封不動地傳給下游。反過來,如果正向傳播時(shí)的 x 小于等于0,則反向傳播中傳給下游的信號將停在此處。用計(jì)算圖表示的話,如圖5-18 所示。
在神經(jīng)網(wǎng)絡(luò)的層的實(shí)現(xiàn)中,一般假定 forward() 和 backward() 的參數(shù)是 NumPy 數(shù)組。如下代碼所示:
class Relu:def __init__(self):self.mask = Nonedef forward(self, x):self.mask = (x <= 0)out = x.copy()out[self.mask] = 0return outdef backward(self, dout):dout[self.mask] = 0dx = doutreturn dx
Relu 類有實(shí)例變量 mask 。這個(gè)變量 mask 是由 True / False 構(gòu)成的 NumPy 數(shù)組,它會把正向傳播時(shí)的輸入 x 的元素中小于等于 0 的地方保存為 True ,其他地方(大于0 的元素)保存為 False 。
如下例所示,mask 變量保存了由 True / False 構(gòu)成的 NumPy 數(shù)組。
In [3]: x = np.array( [[1.0, -0.5], [-2.0, 3.0]] )In [4]: x
Out[4]:
array([[ 1. , -0.5],[-2. , 3. ]])In [5]: mask = (x<=0)In [6]: mask
Out[6]:
array([[False, True],[ True, False]])In [7]:
如圖 5-18 所示,如果正向傳播時(shí)的輸入值小于等于 0,則反向傳播的值為 0。因此,反向傳播中會使用正向傳播時(shí)保存的 mask ,將從上游傳來的 dout 的mask 中的元素為 True 的地方設(shè)為0。
2. Sigmoid 層
sigmoid 函數(shù)由式(5.9)表示:
用計(jì)算圖表示式(5.9)的話,則如圖5-19 所示。
exp節(jié)點(diǎn)會進(jìn)行y = exp(x)的計(jì)算;/節(jié)點(diǎn)會進(jìn)行 y=1xy=\frac{1}{x}y=x1? 的計(jì)算;
反向傳播流程:
/節(jié)點(diǎn)表示 y=1xy=\frac{1}{x}y=x1?,它的導(dǎo)數(shù)可以解析性地表示為下式。
根據(jù)式(5.10),反向傳播時(shí),會將上游的值乘以?y2(正向傳播的輸出的平方乘以?1后的值)后,再傳給下游。計(jì)算圖如下所示。
+節(jié)點(diǎn)將上游的值原封不動地傳給下游。計(jì)算圖如下所示。
exp節(jié)點(diǎn)表示y = exp(x),它的導(dǎo)數(shù)由下式表示。
計(jì)算圖中,上游的值乘以正向傳播時(shí)的輸出(這個(gè)例子中是exp(?x))后,再傳給下游。
×節(jié)點(diǎn)將正向傳播時(shí)的值翻轉(zhuǎn)后做乘法運(yùn)算。因此,這里要乘以 ?1。
根據(jù)上述內(nèi)容,圖5-20的計(jì)算圖可以進(jìn)行Sigmoid層的反向傳播。從圖 5-20 的結(jié)果可知,反向傳播的輸出為 ?L?yy2exp(?x)\frac{\partial L}{\partial y} y^2exp(-x)?y?L?y2exp(?x),這個(gè)值會傳播給下游的節(jié)點(diǎn)。
這里要注意, 這個(gè)值 ?L?yy2exp(?x)\frac{\partial L}{\partial y} y^2exp(-x)?y?L?y2exp(?x) 只根據(jù)正向傳播時(shí)的輸入x和輸出y就可以算出來。
因此,圖5-20的計(jì)算圖可以畫成圖5-21的集約化的sigmoid節(jié)點(diǎn)。
圖5-20 的計(jì)算圖和簡潔版的圖5-21 的計(jì)算圖的計(jì)算結(jié)果是相同的,但是,簡潔版的計(jì)算圖可以省略反向傳播中的計(jì)算過程,因此計(jì)算效率更高。此外,通過對節(jié)點(diǎn)進(jìn)行集約化,可以不用在意 Sigmoid 層中瑣碎的細(xì)節(jié),而只需要專注它的輸入和輸出,這一點(diǎn)也很重要。
另外, ?L?yy2exp(?x)\frac{\partial L}{\partial y} y^2exp(-x)?y?L?y2exp(?x) 可以進(jìn)一步整理如下。
因此,圖5-21 所表示的 Sigmoid 層的反向傳播,只根據(jù)正向傳播的輸出就能計(jì)算出來。
用代碼實(shí)現(xiàn)結(jié)果如下:
class Sigmoid:def __init__(self):self.out = Nonedef forward(self, x):out = sigmoid(x)self.out = outreturn outdef backward(self, dout):dx = dout * (1.0 - self.out) * self.outreturn dx
這個(gè)實(shí)現(xiàn)中,正向傳播時(shí)將輸出保存在了實(shí)例變量 out 中。然后,反向傳播時(shí),使用該變量 out 進(jìn)行計(jì)算。
參考:《深度學(xué)習(xí)入門:基于Python的理論與實(shí)現(xiàn)》
總結(jié)
以上是生活随笔為你收集整理的机器学习入门(12)— 激活函数层 ReLU、Sigmoid 层的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习入门(11)— 反向传播的加法节
- 下一篇: 男生精子畸形怎么治疗