【机器学习】--神经网络(NN)
生活随笔
收集整理的這篇文章主要介紹了
【机器学习】--神经网络(NN)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
簡單介紹:
神經網絡主要是默認人類腦結構進行的一種代碼程序結構的表現,同時是RNN,CNN,DNN的基礎。結構上大體上分為三個部分(輸入,含隱,輸出),各層都有個的講究,其中,輸入層主要是特征處理后的入口,含隱層用來訓練相應函數,節點越多,訓練出的函數就越復雜,輸出層輸出相應的預測結果,比較常見的就是多分類了。算法特點:
1、神經網絡屬于有監督學習的一種; 2、計算復雜度比較高,因為增加了相應的激活函數,所以等于復合函數嵌套復合函數; 3、含隱層的神經元越多,計算函數便越復雜,但帶來的好處是,不用過度考慮特征方程,較其它機器學習入門算法而言,省卻了特征適配; 4、BP后向傳播其實就是誤差函數反推參數求導過程,不知道為什么網絡上的很多博客都沒有人點出來,可能是使用BP后向傳播算法,讓別人聽起來更厲害一些吧; 5、需要考慮過擬合問題; 6、數學不好別看了,看前五條就行了。學習神經網絡的基本流程:
1、了解基礎知識(簡單的神經網絡構造,激活函數,誤差函數); 2、推導 3、完成代碼 4、畫圖看效果基礎知識:
神經網絡
上圖建立具有一個輸入層、一個隱藏層、一個輸出層的三層神經網絡。輸入層的結點數由數據維度決定,這里是2維。類似地,輸出層的結點數由類別數決定,也是2。(因為我們只有兩類輸出,實際中我們會避免只使用一個輸出結點預測0和1,而是使用兩個輸出結點以使網絡以后能很容易地擴展到更多類別)。每一個神經元都可以理解成一個函數,這個函數,也可以叫做激活函數,例如,輸入神經元理解為Fin(x),含隱神經元理解為Fhn(x),輸出神經元理解為Fou(x),每一層之間都是具有一個權重參數w(或者叫θ),每一層的輸出乘上權重參數,都是下一層的輸入,例如,Fin( input1 ) * w1 就是含隱層的輸入,Fhn( Fin( input1 ) * w1 ) *w2 就是輸出層的輸入,Fou( Fhn( Fin(input1 ) * w1 ) * w2 )計算出最后的輸出值。
常見的激活函數:
1、Sigmoid函數(也叫logistics函數) 2、Tanh函數(雙曲函數) 3、sgn函數(階躍函數) 4、ReLU函數 5、softmax函數 6、Linear函數誤差函數:
參考我寫的機器學習--邏輯回歸這篇文章吧,里面有提到,這里我們使用的是對數似然損失。這里特別說明一下,需要注意,交叉熵和對數似然很像,需要注意區別。本次神經網絡的三層形式:
輸入層:特征,用x表示 輸入層和含隱層之間的權重:使用w1表示 含隱層:tanh() 含隱層和輸出層之間的權重:使用w2表示 輸出層:softmax() 輸出結果:Y表示(帶上角標的那個我打不出來。。。)softmax的函數如下:
其中,Yi表示第i類的輸出,xi表示第i類的輸入,底部的是所有輸入的求和。
softmax的求導:
需要先行注意的是,底部xk的累加和是包含n個未知參數的,但在求導過程中,除了對其求到的那個未知參數外,其它參數,都視為常數項; f(xi)對xi求導:f(xi)對xa求導:
推導:
正向傳播(也就是預測過程,即開始輸入到最后輸出的過程,求y):
y = softmax (?tanh ( x * w1 ) * w2 )后向傳播(求w2,w1):
后向傳播就是倒著推,先推輸出層到含隱層之間的權重w2,那么假設我們的真實值用大Y表示,我們的預測值用小y表示,那么他們之間的誤差是Loss = ( Y - y) ,但由于我們softmax函數是指數形式,且本身是概率性問題,我們使用最大似然損失函數(也叫對數似然損失函數),Loss = -ln ( y ) ,(注,在書上見到的log其實就是ln,表示以e為底,表示的含義是,y是當前樣本下預測模型得到的概率) 那么損失函數Loss =- ln ( y ) ,也就是說,要在損失最小的情況下求參數w2, 求參數求參數還要損失最小,梯度下降就可以了,已知梯度下降公式: w = w - α(?Loss /?w); 那么令 結果 a = tanh(x*w1)* w2 求取過程如下:? ? ?各項如下:
所以:w2 = w2 -?α ?* [? ( yi - 1) * tanh( xi * w1 ) ]
同理,對b2進行求導:
同理,進行對誤差函數中的w1求導: 所以:w1 = w1 -?α ?* [? (? yi - 1 ) * [ 1 - (tanh( w1 * xi ))^2 ] * w2 * xi ] ? ? 同理,對b1求導:
這樣,后向傳播也推導完了。
開始部署程序,程序分為以下幾步:
1、獲取數據進行處理 2、softmax公式構建 2.5、參數初始化(主要是權重) 3、前向傳播(就是預測函數)構建 4、后向傳播構建 5、誤差函數構建 5.5、組合函數進行訓練 6、訓練結果評估 7、畫圖本程序使用以下庫,并使用以下全局變量: import numpy as np from sklearn.datasets import make_moons import matplotlib.pyplot as plt #學習速率 learning_rate = 0.01#正則化參數 reg_lambda = 0.01#特征數據 data_x = []#data_y對應結果,mat_data_y結果的表示矩陣形式 data_y = [] mat_data_y = []#權重參數 weights1 = [] weights2 = [] b1 = [] b2 = []#誤差 loss = []
第一步,數據獲取:
def get_data():global data_x,data_ynp.random.seed(0)data_x, data_y = make_moons(200, noise=0.20)max_y = max(data_y)m = len(data_x)
第二步,數學公式構建(我們只需要構建最后的分類函數softmax):
#定義softmax函數 def softmax(x):return np.exp(x)/(np.sum( np.exp(x) ,axis=1,keepdims=True))
第二點五步,參數初始化(主要是權重):
#input_layout_num是輸入層層數,hide_layout_num是含隱層層數,output_layout_num是輸出層層數 def set_params(hide_layout_num = 3 ):global weights1, weights2 ,b1 ,b2input_layout_num = len(data_x[0])output_layout_num = len(mat_data_y[0])# weights1 = np.ones((input_layout_num, hide_layout_num))# weights2 = np.ones((hide_layout_num, output_layout_num))weights1 = np.random.randn(input_layout_num, hide_layout_num)/ np.sqrt(input_layout_num)weights2 = np.random.randn(hide_layout_num, output_layout_num)/np.sqrt(hide_layout_num)# print(weights1)# weights1 = np.ones((input_layout_num, hide_layout_num))b1 = np.zeros((1,hide_layout_num))b2 = np.zeros((1,output_layout_num)) ? 第三步,前向傳播(就是預測函數)構建: #前向傳播計算 def forward_propagation():input_hide_calc_pe = np.dot(data_x ,weights1) + b1 #input_hide_calc_pe為輸入層和含隱層之間的參數方程計算值hide_activation_val = np.tanh(input_hide_calc_pe)#hide_activation_val是含隱層激活函數值hide_output_calc_pe = np.dot(hide_activation_val, weights2) + b2#hide_output_calc_pe是含隱層和輸出層之間的參數方程計算值output_proba = softmax(hide_output_calc_pe)#out_proba是最后選擇softmax函數計算出的概率,也就是預測值return hide_activation_val,output_proba#預測函數 def predict(x):input_hide_calc_pe = np.dot(x ,weights1) + b1 #input_hide_calc_pe為輸入層和含隱層之間的參數方程計算值hide_activation_val = np.tanh(input_hide_calc_pe)#hide_activation_val是含隱層激活函數值hide_output_calc_pe = np.dot(hide_activation_val, weights2) + b2#hide_output_calc_pe是含隱層和輸出層之間的參數方程計算值output_proba = softmax(hide_output_calc_pe)#out_proba是最后選擇softmax函數計算出的概率,也就是預測值result = np.max(output_proba,axis=1)kind = np.argmax(output_proba,axis=1)print(output_proba)print("預測結果為第:" + str( kind) + "類\n"+"預測系數為:" + str(result) )return kind#返回每一組中最大數值對應位置的索引 之所以寫兩個是因為后面的那個畫圖和單點預測需要使用
第四步,后向傳播構建: #后向傳播計算,output_proba輸出層計算出的概率 def back_propagation( hide_activation_val, output_proba):global weights2,weights1,b1,b2feature_x_len,feature_x0_len = np.shape(data_x)delta_w2_1 = output_proba#(yi - 1 )for i in range(feature_x_len):delta_w2_1[i][data_y[i]] = delta_w2_1[i][data_y[i]] - 1# (yi - 1 ) * tanh(w1 * xi)delta_w2 = np.dot(hide_activation_val.T, delta_w2_1)#b2 = yi - 1delta_b2 = np.sum(delta_w2_1,axis=0,keepdims=True)#[ ( yi - 1 ) * [ 1 - (tanh( w1 * xi ))^2 ] * w2 * xi ]#1 - (tanh( w1 * xi ))^2delta_w1_2 = (1 - hide_activation_val**2)delta_w1_1 = np.dot(delta_w2_1 ,weights2.T)delta_w1_3 = delta_w1_1 * delta_w1_2delta_w1 = np.dot(data_x.T,delta_w1_3)delta_b1 = np.sum(delta_w1_3,axis=0,keepdims=True)delta_w2 = delta_w2 + reg_lambda * weights2delta_w1 = delta_w1 + reg_lambda * weights1weights1 = weights1 - learning_rate * delta_w1b1 = b1 - learning_rate * delta_b1weights2 = weights2 - learning_rate * delta_w2b2 = b2 - learning_rate * delta_b2
第五步,誤差函數構建: #誤差函數 def loss_func():global loss#Loss = - ln p(y|x) = - ln yiloss_sum = 0.0hide_activation_val, output_proba = forward_propagation()for i in range(len(data_x)):loss_sum = loss_sum + -1 * np.log( output_proba[i][data_y[i]] )loss.append(1/len(data_x) * loss_sum)
第五點五步,訓練: def train(iter_num = 1,hide_layout_num = 3):set_params(hide_layout_num)for i in range(iter_num):hide_activation_val,output_proba = forward_propagation()back_propagation(hide_activation_val,output_proba)loss_func()
第六步,訓練結果評估: #評估訓練結果 def train_result_evaluate():hide_activation_val, output_proba = forward_propagation()output_result = np.argmax(output_proba,axis=1) #返回每一組中最大數值對應位置的索引x_num = len(output_result)real_num = 0.0for i in range(x_num):if output_result[i] == data_y[i]:real_num += 1.0score = real_num / x_numprint("本次樣本數共:" + str(x_num) + "個\n"+"訓練后預測正確數量:"+ str(real_num) + "個\n"+"正確率為:" + str(score * 100 ) + r'%' )
第七步,畫圖: #畫決策邊界 def show_decision_pic():# Set min and max values and give it some paddingx_max = max(data_x[:,0]) + 0.5x_min = min(data_x[:,0]) - 0.5y_max = max(data_x[:,1]) + 0.5y_min = min(data_x[:,1]) - 0.5range_space = 0.01# Generate a grid of points with distance h between themfeature_x1 = np.arange(x_min, x_max, range_space) #其橫向特征最大最小生成的范圍值feature_x2 = np.arange(y_min, y_max, range_space) #其縱向特征最大最小生成的范圍值x1, x2 = np.meshgrid(feature_x1, feature_x2) #將特征變化成行列相等的矩陣# Predict the function value for the whole gidfeature = np.c_[x1.ravel(), x2.ravel()] #拼接成二維矩陣print(np.shape(feature))Z = predict(feature)print(Z)Z = Z.reshape(x1.shape)# Plot the contour and training examplesplt.contour(feature_x1, feature_x2, Z)plt.scatter(data_x[:, 0], data_x[:, 1], c=data_y, cmap=plt.cm.Spectral)plt.show()def show_loss_pic():plt.figure(2)plt.plot(loss)plt.show()
運行程序:
if __name__ == "__main__":get_data()train(iter_num=20000,hide_layout_num=3)print("初始loss:" + str(loss[0]))print("最終loss:" + str(loss[-1]))train_result_evaluate()show_decision_pic()show_loss_pic()#這里進行一個單點預測predict(data_x[-5])
看一下結果:
決策邊界如下:誤差損失逐漸收斂:
誤差值:
評估結果:
最后的單點預測(因為兩類分別是用0和1表示的,所以第一類是第[0]類,第二類是第[1]類):
關于關于程序中權重初始化的說明(對應在set_param函數): 關于程序中,權重為什么是這樣設置,還不是像基礎的機器學習方法,設置全0或全1矩陣,原因就是因為,如果設置相同矩陣,那么所有神經元計算出來的結果是一樣的,反向傳播時,計算的梯度就一樣了,參數就會一樣,具體說明,請參考引用【4】.
寫在最后,可以看出來,神經網絡的計算比之前基礎機器學習稍稍復雜一些,但套路還是一樣的,就是多了一點,但好處也可以從圖中看出來,尤其是和之前的邏輯回歸比較后更容易得出鮮明結論,神經網絡省去了找尋復雜特征方程的選擇,神經元的多少就會決定自己處理的特征的復雜度。 比如使用30層含隱層,迭代2w次,看下效果 但這樣的情況,就過擬合了,并不平滑,這樣做出來的權重和函數,就不是預測了,無法體現我們做出來的東西的是具有通用適配性的。
圖文知識及引用參考:
【1】softmax的推導:http://blog.csdn.net/behamcheung/article/details/71911133 【2】看了這篇文章,開始嘗試寫神經網絡:http://python.jobbole.com/82208/ 【3】實際上,【2】是翻譯的github上的一篇文章( 打開ipynb格式):https://github.com/dennybritz/nn-from-scratch 【4】權重初始化的選擇原因:http://blog.csdn.net/bixiwen_liu/article/details/52956727 【5】python繪圖的函數說明:https://www.cnblogs.com/shuhanrainbow/p/6282452.html 【6】如何畫等高線:https://zhidao.baidu.com/question/922394146083399819.html
總結
以上是生活随笔為你收集整理的【机器学习】--神经网络(NN)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实现生产者消费者的三种方式
- 下一篇: Xilinx 7系列原语使用(时钟相关)