Tim Wong
深思心思
Published in
10 min readAug 17, 2019

--

【ML09】Activation Function 是什麼?

NN 的 neurons ,除了input node及output node 外,一般除了保存中途的計算結果(SUM) 之外還會有Activation Function 的計算(ACT)。它有什麼用?它有什麼形式?如何選擇呢?

簡而言之,Activation Function,就是把計算好了的輸入值standardize 好,規範它的「輸出數值之範圍」,「輸出數值的相互關係」。之前的blog 有說過pre-processing raw data, 對不?其實,Activation Function 做的就是差不多的東西了。

Activation Function 故名思義,就是一個輸入x 得出y 的算式,不要想得太復雜,它其實很簡單。

上圖示意,每個node, 當SUM 部份完成了之後 = X ,然後 X 就掉入Activation Function 來做一次transform才離開node 的。以下是常見的Activation Function。

〖 幾種常用的Activation Function 〗

1.ReLU (Rectified Linear Units) 是最簡單又最常用的,它是把負數先轉為零,正數就什麼都不做直接離開node。用意係把負值關係排除掉。

例如據說,跑步x 跟做Gym y 是相輔相承的,你不可以只專注做其中一種的。如用neuron 來判定健康與否,就要先自你x+y 是不是由於bias (b) 了。(請把biase 當作是一個判別門檻)。那就是說,x, y 不是獨立的,它們互相影響。Neuron 就用ReLu來判定x, y 是否大於biase。是的話就有一個優點,否則是零,即沒有缺點更不會發生在NN 後段因缺點底消了優點的擔憂。

但當然,這neuron 就不會處理負數了!! 這是不是你的數據想要的呢? 要判的東西只有正數? 另外,這個ReLu 不要以為它是linear,其實它在(0,0) 轉了個彎,它是 non-linear 的。

用在我們的六合彩code 時,是加兩個functions 及改兩個位置。

你會發覺prediction 差了,但error 是大幅下降的。(Error: 2.7 降至1.9)

#加這個functions.
def relu(x):
return (x>0) * x
def relu2deriv(x):
return x>0
#每一期為個array, 例如第一期是:[12,23,14,15,36,17,18]
ballNumber = np.array([[12,23,14,15,36,17,18],
[12,33,44,25,26,19,30],
[21,13,15,17,12,24,18],
[36,13,12,11,14,15,40],
[19,17,13,32,14,21,13],
..........
pred_0To1 = relu(input.dot(weights_layer1)) #改這句
pred_1To2 = pred_0To1.dot(weights_layer2)
delta_layer2 = (pred_1To2 - true)
error_layer2 += delta_layer2 ** 2
delta_layer1 = (\ #改這句
weights_layer2*relu2deriv(\
pred_0To1.T)).dot(delta_layer2)

上面最後一句是說,「唔,結果delta_layer2 的delta 要反向分給各位layer1 的兄弟了! 什麼?你的輸出是0 ? 你想說你沒有頁獻這次的delta? OKOK,如果是零的,就不會分到delta 了,放心 。」

2.Leaky ReLU 就是不想放棄那些負數,只是負數的影響力小一點。例如把負數乘0.1 或乘 0.01。

3.ELU 是進一步把Leaky ReLU 跟 ReLU 的硬朗線條改smooth 一點。

4.Sigmoid 又是一個常用的 Activation Function。它會處理負數output 的, 不是把負數歸零,而是把負數時的輸出但規範在0~0.5 之間,而正數時的輸出規範在0.5~1。即所有x+y-b 都會規範在0~1之間。

首先是0~1 這個normalize 了的規範就已包含了之前說normalization 了好處;而負正分界於0.5,更使其在NN 界中用作二元判斷的好工具(判斷那些非黑即白,非對即錯的從二選一情況)。而它的output數 ,例如0.75 就可以當成是prediction 的概率,75%。

下次我們用在classification 吧!

5.有如ReLu 跟Leaky ReLU 的關係一樣,Sigmoid 跟 tanh 有同樣的關係。前者不處理負數,它總會在有很多負數輸入值的應用上遇到麻煩,包搭NN 跑不動。那當然會有人跑出來發明差不多但又可處理負數的Function。

tanh 會輸出由-1 至1 的sigmoid 呀!

6. Maxout 是比較復雜的方法,是在相鄰兩個neurons 先算好 x+y-b ,再比較它們並使用當中較大的數作為Activation Function 的結果。就是說,Maxout 根本沒有什麼運算過東西,而只是簡單比較兩個數,找出較大者。

好處是它常常有較大的slop /derivative 給NN 要它學習,不好處是多了一層類似hidden layer 的東西,code 比較煩。

以下是我們的六合彩code,用了ReLu Activation Function,還用了前15個samples 作training ,後5個samples 作testing。

結果係,不用ReLu 時: Error:2.73 ; 20% 準確。

用了ReLu 時: Error:2.76 ; 60% 準確。

對!! Error 少不一定好呀 ~ (再講)

import numpy as npdef relu(x):
return (x>0) * x
def relu2deriv(x):
return x>0
ballNumber = np.array([[12,23,14,15,36,17,18],
[12,33,44,25,26,19,30],
[21,13,15,17,12,24,18],
[36,13,12,11,14,15,40],
[19,17,13,32,14,21,13],
[11,11,22,13,24,25,17],
[22,17,14,19,38,21,44],
[38,17,18,33,34,15,16],
[11,42,13,14,15,16,17],
[14,33,44,35,16,11,12],
[22,33,24,37,18,13,14],
[16,31,20,13,24,15,36],
[17,32,21,14,25,16,37],
[14,33,42,31,12,15,12],
[13,24,21,12,25,14,11],
[22,23,24,25,26,27,28],
[31,32,33,34,35,36,37],
[23,24,25,26,27,28,29],
[25,26,27,28,29,30,31],
[12,13,14,41,22,23,34]])
win_or_lose_binary = np.array([[1,1,0,1,0,0,1,0,0,1,1,1,0,1,0,1,0,0,0,1]]).T
learningRate = 0.0001
numberOfInputNodes = len(ballNumber[0])
numberOfHiddenLayerNodes = numberOfInputNodes
numberOfOutputNodes = 1
np.random.seed(0)
weights_layer1 = 2*np.round(np.random.random(\
(numberOfInputNodes,numberOfHiddenLayerNodes)),\
decimals =2)-1
np.random.seed(0)
weights_layer2 = 2*np.round(np.random.random(\
(numberOfHiddenLayerNodes,numberOfOutputNodes)),\
decimals = 2)-1
for iter in range(9999):
error_layer2 = 0

for j in range(len(ballNumber)-5):
input = np.array([ballNumber[j]])/47
true = np.array([win_or_lose_binary[j]])
#pred_0To1 = input.dot(weights_layer1)
pred_0To1 = relu(input.dot(weights_layer1)) #改這句

pred_1To2 = pred_0To1.dot(weights_layer2)
delta_layer2 = (pred_1To2 - true)
error_layer2 += delta_layer2 ** 2

#delta_layer1 = (weights_layer2).dot(delta_layer2) #改這句
delta_layer1 = (weights_layer2*relu2deriv(pred_0To1.T)\
).dot(delta_layer2)
weights_layer2 -= (learningRate*delta_layer2*pred_0To1).T
weight_deltas = np.outer(input, delta_layer1)
weights_layer1 -= learningRate * weight_deltas

print("Error:", error_layer2)
pred = []
for i in range(len(ballNumber)):
x = np.round(\
np.array((ballNumber[i])/47).dot(weights_layer1\
).dot(weights_layer2),decimals =0)
pred.append(abs(round(x[0],0)))
win_lose = [1,0,0,0,1]
result = []
for i, j in zip(pred[-5:], win_lose):
result.append(i == j)
print("correct?", result)
countTrue = result.count(True)
print(countTrue)
print("Accuracy:", round((countTrue)/len(result)*100,0))

全力衝刺中的男人(2019-Aug-15)

我是阿Tim | timwong.ai@gmail.com

P.S. 還有很多Activation Functions 呀~

--

--