日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

【机器学习基础】使用python实现BP算法

發布時間:2025/3/8 python 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【机器学习基础】使用python实现BP算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

用pytorch跟tensorflow實現神經網絡固然爽。但是想要深入學習神經網絡,光學會調包是不夠的,還是得親自動手去實現一個神經網絡,才能更好去理解。

一、問題介紹

傳說中線性分類器無法解決的異或分類問題。我們就拿它來作為我們神經網絡的迷你訓練數據。把輸入數據拼成一個矩陣X:

import?numpy?as?np#訓練數據:經典的異或分類問題 train_X?=?np.array([[0,0],[0,1],[1,0],[1,1]]) train_y?=?np.array([0,1,1,0])

我們定義一個簡單的2層神經網絡:對應的代碼

linear1?=?LinearLayer(2,3) relu1?=?Relu() linear2?=?LinearLayer(3,1)

我們還需要定義一個損失函數Loss,用來衡量我們的輸出結果與實際結果的誤差。這里用的是均方誤差MSE,表達式如下

二、BP算法 和 計算圖(Computing Graph)模型

里面的線性層,Relu層也得自己動手實現。

實現這些,我們首先需要知道計算圖模型。計算圖模型是所有神經網絡框架的核心理論基礎。

我們依然還是對著這個例子來講解。

上面的神經網絡,用純數學公式表達可以表達。計算圖模型把一個復合運算拆分成為多個子運算,因此,我們需要引入很多中間變量。

定義:根據這些公式,我們就可以用計算圖模型來表示我們的神經網絡,如下:這個計算圖就是上面那一堆公式的可視化表示。

在圖里面,公式里每個出現過的變量都被視為一個節點,變量之間的連線描述了變量之間存在直接的計算的關系。計算圖的表示方法,有什么好處呢?

下面我們基于這個計算圖來用BP算法進行模型的訓練。

對模型進行訓練,就是找到一組模型的參數,使得我們的網絡模型能夠準確預測我們的訓練數據。在我們這個例子里面,需要訓練參數其實只有線性層的矩陣跟bias項:[公式] 。

訓練采用的是BP算法,采用梯度下降法來逐漸迭代去更新參數。

梯度下降法的原理很簡單,每次迭代中,用損失函數關于參數的梯度乘以學習率,來更新參數。關于梯度我要多說幾句。梯度表示Y關于x的變化率,可以理解成x的速度。由于W1是一個2X3的矩陣,那么loss關于W1的梯度可以理解W1的每個元素的瞬時速度。W1的梯度的形狀,必然是嚴格跟參數本身的形狀是一樣的(每個點都有對應的速度)。也就是說損失函數關于W1的梯度也必然是一個2X3的矩陣(不然更新公式里面無法做加減)。

下面開始訓練過程,

首先給定輸入X,初始化 [公式] (記住不能初始為全0)。

正向傳播(forward pass)

BP算法首先在計算圖上面進行正向傳播(forward pass),即從左到右計算所有未知量:嚴格按照順序計算,所有的 [公式] 都能先后求出,右邊的y就是網絡的當前預測結果。

反向傳播(backward pass)

既然我們想要用參數的梯度來更新參數,那么我們需要求出最后的節點輸出loss關于每個參數的梯度,求梯度的方法是反向傳播。

由于我們已經進行過一次正向傳播,因此圖里面所有的節點的值都變成了已知量。我們現在要求的是圖里面標為紅色的這4個梯度,它們距離loss有點兒遠。

但是不急,有了這個計算圖,我們可以慢慢從右往左推出這4個值。

先從最右邊開始,觀察到Loss節點只有一條邊跟y連著,計算loss關于y的導數(這個求導只有一個變量y,怎么求不用我解釋了吧):我們就求得了損失函數關于輸出y的導數,然后繼續往左邊計算。

(已經求出的梯度我們用橙色來標記)y是通過O2計算出來的,我們可以計算y關于O2的梯度:但是我們想要的是loss關于O2的梯度,這里應用到了鏈式求導法則:loss關于y的梯度在之前已經求出來過了,然后就可以求出loss關于O2的梯度。

繼續往左計算梯度:上圖中 a2 關于它每個變量的梯度,可以直接根據 a2 與它左邊3個變量的表達式來算出,如下:這一步我們算出了兩個需要計算的梯度,似乎并沒有遇到困難,繼續往左傳播。

在計算 a1梯度的時候,我們遇到了relu激活函數,relu函數的梯度也很好求:它的梯度就是在輸入X的基礎上,所有大于0的位置導數都是1,其他位置導數都是0,比如:(這括號里的看不懂不要緊,當N維向量對M維向量求導應用鏈式法則時,通用一點兒的結果是一個NM的jacobian矩陣再乘M1向量,但是這里由于1. N=M。2. jacobian矩陣是一個對角方陣。所以可以簡化成兩個向量相乘)

再往左繼續傳,我就不寫每個步驟了。總之可以一直傳到所有梯度都求出來為止。接下來一步就是愉快地進行隨機梯度下降法的更新操作了。

三、模塊化各種Layer

觀察我們的網絡,發現里面的幾個模塊之間其實大部分干的事情都是相似的,無非就是層數不一樣。那么我們就可以復用,我們完全可以把它們抽象成不同的Layer:于是,我們可以把這些類似模塊看成一個小黑盒子,我們的模型等價于下面這個:于是上面那個復雜的網狀結構,被我們簡化成了線性結構。

下面我對照代碼實現每個小黑盒子吧,實現代碼在這個文件里面:Layers.py首先介紹線性全連接層,先看代碼吧:

class?LinearLayer:def?__init__(self,?input_D,?output_D):self._W?=?np.random.normal(0,?0.1,?(input_D,?output_D))?#初始化不能為全0self._b?=?np.random.normal(0,?0.1,?(1,?output_D))self._grad_W?=?np.zeros((input_D,?output_D))self._grad_b?=?np.zeros((1,?output_D))def?forward(self,?X):return?np.matmul(X,?self._W)?+?self._bdef?backward(self,?X,?grad):?self._grad_W?=?np.matmul(?X.T,?grad)self._grad_b?=?np.matmul(grad.T,?np.ones(X.shape[0]))?return?np.matmul(grad,?self._W.T)def?update(self,?learn_rate):self._W?=?self._W?-?self._grad_W?*?learn_rateself._b?=?self._b?-?self._grad_b?*?learn_rate

forward太簡單了,就不講了,看一下backward。

backward里面其實要計算3個值,W, b的梯度算完以后要存起來,前一層的梯度算完以后直接作為返回值傳出去,推導的公式如下:注意矩陣求導應用鏈式法則的時候,順序非常重要。要嚴格按照指定順序來乘,不然形狀對不上。具體什么順序,可以自己想辦法慢慢拼湊出來。

還有一個update函數,調用此函數這一層會按照梯度下降法來更新它的W跟b的值,這個實現也很簡單直接看代碼就明白了。

然后實現Relu層:

class?Relu:def?__init__(self):passdef?forward(self,?X):return?np.where(X?<?0,?0,?X)def?backward(self,?X,?grad):return?np.where(X?>?0,?X,?0)?*?gr

由于這一層沒有需要保存參數,只需要實現以下forward跟backward方法就行了,非常簡單。

接下來開始實現神經網絡訓練。

四、搭建神經網絡

訓練部分的代碼在 nn.py 里面,里面的代碼哪里看不懂可以翻回去看之前的解釋,命名都是跟上面說的一樣的。

#訓練數據:經典的異或分類問題 train_X?=?np.array([[0,0],[0,1],[1,0],[1,1]]) train_y?=?np.array([0,1,1,0])#初始化網絡,總共2層,輸入數據是2維,第一層3個節點,第二層1個節點作為輸出層,激活函數使用Relu linear1?=?LinearLayer(2,3) relu1?=?Relu() linear2?=?LinearLayer(3,1)#訓練網絡 for?i?in?range(10000):#前向傳播Forward,獲取網絡輸出o0?=?train_Xa1?=?linear1.forward(o0)o1?=?relu1.forward(a1)a2?=?linear2.forward(o1)o2?=?a2#獲得網絡當前輸出,計算損失lossy?=?o2.reshape(o2.shape[0])loss?=?MSELoss(train_y,?y)?#?MSE損失函數#反向傳播,獲取梯度grad?=?(y?-?train_y).reshape(result.shape[0],1)grad?=?linear2.backward(o1,?grad)grad?=?relu1.backward(a1,?grad)grad?=?linear1.backward(o0,?grad)learn_rate?=?0.01??#學習率#更新網絡中線性層的參數linear1.update(learn_rate)linear2.update(learn_rate)#判斷學習是否完成if?i?%?200?==?0:print(loss)if?loss?<?0.001:print("訓練完成!?第%d次迭代"?%(i))break

我覺得沒啥好講的,就直接對著我們的計算圖,一步一步來。

注意一下中間過程幾個向量的形狀。列向量跟行向量是不一樣的,一不小心把列向量跟行向量做運算,numpy不會報錯,而是會廣播成一個矩陣。所以運算的之前,記得該轉置得轉置。

#將訓練好的層打包成一個model model?=?[linear1,?relu1,?linear2]#用訓練好的模型去預測 def?predict(model,?X):tmp?=?Xfor?layer?in?model:tmp?=?layer.forward(tmp)return?np.where(tmp?>?0.5,?1,?0)

把模型打包然后用上面的predict函數來預測。也沒啥好說的,就直接往后一直forward就完兒事。

#開始預測 print("-----") X?=?np.array([[0,0],[0,1],[1,0],[1,1]]) result?=?predict(model,?X) print("預測數據1") print(X) print("預測結果1") print(result)

預測訓練完的網絡就能拿去搞預測了,我這里設置學習率為0.01的情況下,在第3315次迭代時候完成訓練。

最后我們成功地預測了訓練數據。

往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯獲取一折本站知識星球優惠券,復制鏈接直接打開:https://t.zsxq.com/662nyZF本站qq群1003271085。加入微信群請掃碼進群(如果是博士或者準備讀博士請說明):

總結

以上是生活随笔為你收集整理的【机器学习基础】使用python实现BP算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。