寫在最前:
寫在最前, 我把代碼和整理的檔案放在github上了
https://github.com/Leezhen2014/python_deep_learning
Forward指的是神經網路推理,forward與感知機相比,多了一個激活函式的模塊,因此本章需要實作激活函式,另外也需要重新實作y=w*x+b,本章的順序如下:

3.1 激活函式的實作
在感知機中講到用閾值來切換輸出,這樣的函式稱為“階躍函式”:一旦輸入超出了閾值,就切換輸出,階躍函式也算是一種激勵函式,
需要注意激勵函式應該具有以下數學特性:
第一:由于后期訓練程序中會對激勵函式求導,因此這些函式必須符合數學上的可導,
第二:必須為非線性的函式,這可以用公式推一下:
若激勵函式為線性函式
從本質上看,激活函式等同于原來的輸入的:

即:
![]()
第i層的輸入是第i+1層的k倍,
從表象上看,加深網路層次已經失去了意義;等效于無隱含層的網路,
3.1.1 Sigmoid 函式的實作
Sigmoid函式在(-1,1)區間內變化較大,超出這個范圍以后變化較小,可以很好的影響,

1 def Sigmoid(x): 2 return 1/(np.exp(-x) +1) 3 4 if __name__ == '__main__': 5 x = np.arange(-5.0, 5.0, 0.1) 6 y = Sigmoid(x) 7 8 plt.plot(x,y) 9 plt.ylim(-0.1,1.1) 10 plt.show()

3.1.2 階躍函式

1 def step_func(x): 2 temp = x.copy() 3 temp = np.where(x > 0, temp, 0) 4 temp = np.where(x <= 0, temp, 1) 5 return temp 6 7 8 if __name__ == '__main__': 9 x = np.arange(-5.0, 5.0, 0.1) 10 11 y = step_func(x) 12 13 plt.plot(x,y) 14 plt.ylim(-1.1,1.1) 15 plt.show()

3.1.3 Relu 系列
Relu(Rectified Linear Unit) 函式在輸入值大于0的情況下保持不變,在輸入值小于0的情況下,輸出等于0,
階躍函式和sigmoid函式都屬于非線性的函式,

1 def Relu(x): 2 return np.maximum(0,x) 3 4 if __name__ == '__main__': 5 x = np.arange(-5.0, 5.0, 0.1) 6 7 y = Relu(x) 8 9 plt.plot(x,y) 10 plt.ylim(-1.1,5.1) 11 plt.show()

3.2 forward的流程
主要是介紹y=WX+b的實作,神經網路的forward本質是多維陣列的運算+激勵函式,激活函式已經實作了,因此只要將多維陣列的運算了解清楚,便可以實作forward,forward的流程如下:

p.s.: f即為激活函式
本質上是矩陣的乘法,借助np.dot可以實作;在此不贅述,
3.3 輸出層的設計與實作
目前來看,神經網路在分類的問題上可以大致分為兩類:
1. 分類問題:資料屬于哪個類別,可以使用恒等函式,直接獲取預測結果,
2. 回歸問題:根據輸入,預測一個連續的數值問題,可以使用softmax,
Ps: 分類問題的輸出層也是可以使用softmax的,只不過用softmax以后得到的數值是一個線性的數值,還需要選取閾值才能劃分為類別,
恒等函式是不需要實作了,神經網路的輸出節點就是label的輸出,如下圖所示:

Softmax函式的數學公式如下:

Equation 3 softmax函式
從公式中可以看出,輸出層的各個神經元的輸出都會受到輸入信號的影響,如下圖所示,

Figure 3 softmax 的表達圖
1 def softmax(x): 2 ''' 3 softmax 實作,沒有考慮數值溢位 4 :param x: ndarray 5 :return: y, ndarray 6 ''' 7 a = np.exp(x) 8 sum_exp = np.sum(a) 9 y= a/sum_exp 10 return y
上圖的代碼是按照公式實作的,但是沒有考慮數值溢位的情況;由于是exp是指數函式,當指數特別大的時候,進行除法的時候會的時候會出現數值溢位,為了避免以上情況,將分子和分母同時乘上常量C(必須足夠大)

1 def softmax(x): 2 ''' 3 softmax 實作 4 :param x: ndarray 5 :return: y, ndarray 6 ''' 7 C = np.max(x) 8 exp_a = np.exp(x - C) 9 sum_exp = np.sum(exp_a) 10 y= exp_a / sum_exp 11 return y
3.4測驗神經網路的推理
在經過上述的準備作業后, 我們就可以組裝成一個簡單的推理網路;
假設, 我們的神經網路是簡單的全連接層, 且手里已經有了網路的權重(sample_weight.pkl),
我們要做的是對minst手寫體識別,資料集用load_mnist()方法獲取,
具體代碼可以看github: https://github.com/Leezhen2014/python_deep_learning
1 # -*- coding: utf-8 -*- 2 # @File : day7.py 3 # @Author: lizhen 4 # @Date : 2020/2/4 5 # @Desc : 第二篇的實作: 對檔案的實作 6 7 import sys, os 8 import numpy as np 9 import pickle 10 from src.datasets.mnist import load_mnist 11 from src.common.functions import sigmoid, softmax 12 13 14 def get_data(): 15 (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False) 16 return x_test, t_test 17 18 19 def init_network(): 20 with open("../datasets/sample_weight.pkl", 'rb') as f: 21 network = pickle.load(f) 22 return network 23 24 25 def predict(network, x): 26 W1, W2, W3 = network['W1'], network['W2'], network['W3'] 27 b1, b2, b3 = network['b1'], network['b2'], network['b3'] 28 29 a1 = np.dot(x, W1) + b1 30 z1 = sigmoid(a1) 31 a2 = np.dot(z1, W2) + b2 32 z2 = sigmoid(a2) 33 a3 = np.dot(z2, W3) + b3 34 y = softmax(a3) 35 36 return y 37 38 39 x, t = get_data() 40 network = init_network() 41 accuracy_cnt = 0 42 for i in range(len(x)): 43 y = predict(network, x[i]) 44 p= np.argmax(y) 45 if p == t[i]: 46 accuracy_cnt += 1 47 48 print("Accuracy:" + str(float(accuracy_cnt) / len(x)))
列印輸出正確率:
輸出:
Accuracy: 0.9352
------------------------
好了,今天到此為止,
我心匪石,不可轉也,我心匪席,不可卷也,轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/506553.html
標籤:其他
