【机器学习】梯度下降的Python实现
作者 | Vagif Aliyev?
編譯 | VK?
來源 | Towards Data Science
梯度下降是數據科學的基礎,無論是深度學習還是機器學習。對梯度下降原理的深入了解一定會對你今后的工作有所幫助。
你將真正了解這些超參數的作用、在背后發生的情況以及如何處理使用此算法可能遇到的問題,而不是玩弄超參數并希望獲得最佳結果。
然而,梯度下降并不局限于一種算法。另外兩種流行的梯度下降(隨機和小批量梯度下降)建立在主要算法的基礎上,你可能會看到比普通批量梯度下降更多的算法。因此,我們也必須對這些算法有一個堅實的了解,因為它們有一些額外的超參數,當我們的算法沒有達到我們期望的性能時,我們需要理解和分析這些超參數。
雖然理論對于深入理解手頭的算法至關重要,但梯度下降的實際編碼及其不同的“變體”可能是一項困難的任務。為了完成這項任務,本文的格式如下:
簡要概述每種算法的作用。
算法的代碼
對規范不明確部分的進一步解釋
我們將使用著名的波士頓住房數據集,它是預先內置在scikit learn中的。我們還將從頭開始構建一個線性模型
好的,首先讓我們做一些基本的導入。我不打算在這里做EDA,因為這不是我們文章的真正目的。不過,我會把一些事情說明白。
import?numpy?as?np import?pandas?as?pd? import?plotly.express?as?px from?sklearn.datasets?import?load_boston from?sklearn.metrics?import?mean_squared_error好的,為了讓我們看到數據是什么樣子,我將把數據轉換成一個數據幀并顯示輸出。
data?=?load_boston()df?=?pd.DataFrame(data['data'],columns=data['feature_names']) df.insert(13,'target',data['target']) df.head(5)好吧,這里沒什么特別的,我敢肯定你之前已經類似實現過了。
現在,我們將定義我們的特征(X)和目標(y)。我們還將定義我們的參數向量,將其命名為thetas,并將它們初始化為零。
X,y?=?df.drop('target',axis=1),df['target']thetas?=?np.zeros(X.shape[1])成本函數
回想一下,成本函數是衡量模型性能的東西,也是梯度下降的目標。我們將使用的代價函數稱為均方誤差。公式如下:
好吧,我們把它寫出來:
def?cost_function(X,Y,B):predictions?=?np.dot(X,B.T)cost?=?(1/len(Y))?*?np.sum((predictions?-?Y)?**?2)return?cost在這里,我們將輸入、標簽和參數作為輸入,并使用線性模型進行預測,得到成本,然后返回。如果第二行讓你困惑,回想一下線性回歸公式:
所以,我們基本上是得到每個特征和它們相應權重之間的點積。如果你還不確定我在說什么,看看這個視頻:https://www.youtube.com/watch?v=kHwlB_j7Hkc
很好,現在讓我們測試一下我們的成本函數,看看它是否真的有效。為了做到這一點,我們將使用scikit learn的均方誤差,得到結果,并將其與我們的算法進行比較。
mean_squared_error(np.dot(X,thetas.T),y)OUT:?592.14691169960474cost_function(X,y,thetas)OUT:?592.14691169960474太棒了,我們的成本函數起作用了!
特征縮放
特征縮放是線性模型(線性回歸、KNN、SVM)的重要預處理技術。本質上,特征被縮小到更小的范圍,并且特征也在一定的范圍內。可以這樣考慮特征縮放:
你有一座很大的建筑物
你希望保持建筑的形狀,但希望將其調整為較小的比例
特征縮放通常用于以下場景:
如果一個算法使用歐幾里德距離,那么由于歐幾里德距離對較大的量值敏感,因此需要對特征進行縮放
特征縮放還可以用于數據標準化
特征縮放還可以提高算法的速度
雖然有許多不同的特征縮放方法,但我們將使用以下公式構建MinMaxScaler的自定義實現:
由于上述原因,我們將使用縮放。
現在,對于python實現:
X_norm?=?(X?-?X.min())?/?(X.max()?-?X.min()) X?=?X_norm這里沒什么特別的,我們只是把公式翻譯成代碼。現在,節目真正開始了:梯度下降!
梯度下降
具體地說,梯度下降是一種優化算法,它通過迭代遍歷數據并獲得偏導數來尋求函數的最小值(在我們的例子中是MSE)。
如果這有點復雜,試著把梯度下降想象成是一個人站在山頂上,他們試著以最快的速度從山上爬下來,沿著山的負方向不斷地“走”,直到到達底部。
現在,梯度下降有不同的版本,但是你會遇到最多的是:
批量梯度下降
隨機梯度下降法
小批量梯度下降
現在我們將按順序討論、實現和分析每一項,所以讓我們開始吧!
批量梯度下降
批量梯度下降可能是你遇到的第一種梯度下降類型。現在,我在這篇文章中并不是很理論化(你可以參考我以前的文章:https://medium.com/@vagifaliyev/gradient-descent-clearly-explained-in-python-part-1-the-troubling-theory-49a7fa2c4c06),但實際上它計算的是整個(批處理)數據集上系數的偏導數。你可能已經猜到這樣做很慢了。
我們的數據集很小,所以我們可以像這樣實現批量梯度下降:
def?batch_gradient_descent(X,Y,theta,alpha,iters):cost_history?=?[0]?*?iters??#?初始化歷史損失列表for?i?in?range(iters):?????????prediction?=?np.dot(X,theta.T)??????????????????theta?=?theta?-?(alpha/len(Y))?*?np.dot(prediction?-?Y,X)???cost_history[i]?=?cost_function(X,Y,theta)???????????????return?theta,cost_history要澄清一些術語:
alpha:這是指學習率。
iters:迭代運行的數量。
太好了,現在讓我們看看結果吧!
batch_theta,batch_history=batch_gradient_descent(X,y,theta,0.05,500)好吧,不是很快,但也不是很慢。讓我們用我們新的和改進的參數來可視化和成本:
cost_function(X,y,batch_theta)OUT:?27.537447130784262哇,從592到27!這只是一個梯度下降的力量的一瞥!讓我們對迭代次數的成本函數進行可視化:
fig?=?px.line(batch_history,x=range(5000),y=batch_history,labels={'x':'no.?of?iterations','y':'cost?function'}) fig.show()好的,看看這個圖表,我們在大約100次迭代之后達到了一個大的下降,從那里開始,它一直在逐漸減少。
所以,批量梯度下降到此結束:
優點
有效且曲線平滑
最準確,最有可能達到全局最低值
缺點
對于大型數據集可能會很慢
計算成本高
隨機梯度下降法
這里,不是計算整個訓練集的偏導數,而是只計算一個隨機樣本(隨機意義上的隨機)。
這是很好的,因為計算只需要在一個訓練示例上進行,而不是在整個訓練集上進行,這使得計算速度更快,而且對于大型數據集來說非常理想。
然而,由于其隨機性,隨機梯度下降并不像批量梯度下降那樣具有平滑的曲線,雖然它可以返回良好的參數,但不能保證達到全局最小值。
學習率調整
解決隨機梯度下降問題的一種方法是學習率調整。
基本上,這會逐漸降低學習率。因此,學習率一開始很大(這有助于避免局部極小值),當學習率接近全局最小值時,學習率逐漸降低。但是,你必須小心:
如果學習速率降低得太快,那么算法可能會陷入局部極小,或者在達到最小值的一半時停滯不前。
如果學習速率降低太慢,可能會在很長一段時間內跳轉到最小值附近,仍然無法得到最佳參數
現在,我們將使用簡易的學習率調整策略實現隨機梯度下降:
t0,t1?=?5,50?#?學習率超參數def?learning_schedule(t):return?t0/(t+t1)def?stochastic_gradient_descent(X,y,thetas,n_epochs=30):c_hist?=?[0]?*?n_epochs?#?歷史成本for?epoch?in?range(n_epochs):for?i?in?range(len(y)):random_index?=?np.random.randint(len(Y))xi?=?X[random_index:random_index+1]yi?=?y[random_index:random_index+1]prediction?=?xi.dot(thetas)gradient?=?2?*?xi.T.dot(prediction-yi)eta?=?learning_schedule(epoch?*?len(Y)?+?i)thetas?=?thetas?-?eta?*?gradientc_hist[epoch]?=?cost_function(xi,yi,thetas)return?thetas,c_hist現在運行函數:
sdg_thetas,sgd_cost_hist?=?stochastic_gradient_descent(X,Y,theta)好吧,太好了,這樣就行了!現在讓我們看看結果:
cost_function(X,y,sdg_thetas)OUT: 29.833230764634493哇!我們從592到29,但是請注意:我們只進行了30次迭代。批量梯度下降,500次迭代后得到27次!這只是對隨機梯度下降的非凡力量的一瞥。
讓我們用一個圖再次將其可視化:
由于這是一個小數據集,批量梯度下降就足夠了,但這只是顯示了隨機梯度下降的力量。
優點:
與批量梯度下降相比更快
更好地處理更大的數據集
缺點:
在某個最小值上很難跳出
并不總是有一個清晰的圖,可以在一個最小值附近反彈,但永遠不會達到最佳的最小值
小批量梯度下降
好了,快到了,還有一個要通過!現在,在小批量梯度下降中,我們不再計算整個訓練集或隨機樣本的偏導數,而是在整個訓練集的小子集上計算。
這給了我們比批量梯度下降更快的速度,因為它不像隨機梯度下降那樣隨機,所以我們更接近于最小值。然而,它很容易陷入局部極小值。
同樣,為了解決陷入局部最小值的問題,我們將在實現中使用簡易的學習率調整。
np.random.seed(42)?#?所以我們得到相同的結果t0,?t1?=?200,?1000 def?learning_schedule(t):return?t0?/?(t?+?t1)def?mini_batch_gradient_descent(X,y,thetas,n_iters=100,batch_size=20):t?=?0c_hist?=?[0]?*?n_itersfor?epoch?in?range(n_iters):shuffled_indices?=?np.random.permutation(len(y))X_shuffled?=?X_scaled[shuffled_indices]y_shuffled?=?y[shuffled_indices]for?i?in?range(0,len(Y),batch_size):t+=1xi?=?X_shuffled[i:i+batch_size]yi?=?y_shuffled[i:i+batch_size]gradient?=?2/batch_size?*?xi.T.dot(xi.dot(thetas)?-?yi)eta?=?learning_schedule(t)thetas?=?thetas?-?eta?*?gradientc_hist[epoch]?=?cost_function(xi,yi,thetas)return?thetas,c_hist讓我們運行并獲得結果:
mini_batch_gd_thetas,mini_batch_gd_cost?=?mini_batch_gradient_descent(X,y,theta)以及新參數下的成本函數:
cost_function(X,Y,mini_batch_gd_thetas)OUT:?27.509689139167012又一次真的很棒。我們運行了1/5的迭代,我們得到了一個更好的分數!
讓我們再畫出函數:
好了,我的梯度下降系列到此結束!感謝閱讀!
往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯獲取本站知識星球優惠券,復制鏈接直接打開:https://t.zsxq.com/qFiUFMV本站qq群704220115。 加入微信群請掃碼:總結
以上是生活随笔為你收集整理的【机器学习】梯度下降的Python实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 现在的计算机专业(比如机器学习)已经沦为
- 下一篇: websocket python爬虫_p