Tim Wong
深思心思
Published in
8 min readAug 12, 2019

--

【ML07】有 hidden layer 的neural network — 六合彩分析

下圖是一般 NN 都有的內容,一個input layout ,一個output layer,而中間有一零個或以上的 hidden layer。當然,都是名稱而已,它們都是有一個或多個neuron 的列,並與下一個layout 有所聯繫,即是weights。

在 ML05 中的 NN,是一個沒有 hidden layer,一層有7個 neurons 的 input layer 及一層只有一個 neuron 的 output layer。太簡單了吧,有些人類總是都喜歡複雜的東西,認為那就代表專業,高深,厲害。那麼我們就把 NN 變為有一層 hidden layer 吧,看看厲害了多少。

import random
import numpy as np
#每一期為個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],
[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]])
#另外告知是否中獎,1=中獎,0=沒中獎
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
random.seed(1)
#random 初始值給weights, 這裡有跟輸入數值一樣多的neuron, 即有7顆:
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(99999):
error_layer2 = 0

for j in range(len(ballNumber)): #每次取用一期攪珠結果來學習。

input = np.array([ballNumber[j]]) #拿到這一期攪珠結果。
true = np.array([win_or_lose_binary[j]]) #拿到這一期是否中獎
pred_0To1 = 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)
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]).dot(weights_layer1).dot(weights_layer2),\
decimals =0)
pred.append(abs(round(x[0],0)))
win_lose = [1,1,0,1,0,0,1,0,0,1,1,1,0,1,0,1,0,0,0,1]result = []
for i, j in zip(pred, win_lose):
result.append(i == j)

print("predict:",pred)
print("true:", win_lose)
print("correct?", result)
countTrue = result.count(True)
print("Accuracy:", round((countTrue)/len(result)*100,0))

youWantToInvestOnTheseNumber = np.array([14,23,44,37,18,9,10])
willItWin = np.round(\
youWantToInvestOnTheseNumber.dot(weights_layer1).dot(weights_layer2)\ ,decimals =0)
#上面的數字組合是判斷為Win.
if willItWin == 1:
print("You may Win!")
else:
print("Properly will Loss...")

上面已是全部code,以下我們都看一下寫了些什麼。

# input(dot)weight 算出第一層 prediction,即存在hidden layer的數值了。
pred_0To1 = input.dot(weights_layer1)
# 用第一層的 prediction(dot)weight_2 算出最後的prediction,即1或0
pred_1To2 = pred_0To1.dot(weights_layer2)

回想一下,gradient descent 的 formula 是weight -= learningRate x delta_weight。當中,delta_weight = Input x (pred — true)。

#我們由output layer做起。先計算 (pred - true)。請理解為output layer的delta。
delta_layer2 = (pred_1To2 - true)
error_layer2 += delta_layer2 ** 2
# 那hidden-layer的delta要如何計算?我們可沒有 hidden layer的true值作比較呀?!
# 理論是這樣的:hidden-layer的delta 加起來就是output-layer的delta; 所以只要把 output-layer的delta,按比例反向分配結hidden-layer就可以了。delta_layer1 = weights_layer2.dot(delta_layer2)

然後就可以更新 weight 了,不過hidden-layer 的weight 是一個matrix,有少少復雜。

weights_layer2 -= (learningRate*delta_layer2*pred_0To1).Tweight_deltas = np.outer(input, delta_layer1)
weights_layer1 -= learningRate * weight_deltas

你只要run 一下這個code, 你就會發現,結果跟ML05的code 得出一個樣的結果,不會更好。為什麼呢?

試這樣想吧,上面的NN 可以寫成:

(Input) x (weight_1) x (weight_2) = (output) ; 那不就可以寫成

(Input) x (weight_1 x weight_2) = (output)

就是說,ML06 的NN 只是把ML05 的NN 由一個weight 拆成兩個連續的weight而已,沒有變得更強呀!

那為何說加多些hidden layer 會使NN 強大?我們慢慢了解吧。

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

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

--

--