輕鬆玩轉 Scikit-Learn 系列 —— 梯度下降法

加星標 ,不迷路 !?

接觸過機器學習的小夥伴都應該知道,梯度下降法並不是一個機器學習算法,而是一種基於搜索的最優化方法,在機器學習尤其是深度學習的凸優化中使用尤爲廣泛。給定一個損失函數,如果該函數是凸函數,在學習率合適的情況下,它能夠快速搜索到極小值。類似的還有梯度上升法,只是變換下正負號而已,一個是最大化效用函數,一個是最小化損失函數或者成本函數。在求一個函數的最大值或最小值時,沿其梯度方向進行搜索可能是最有效也是最普遍的方法之一。

我們拿單一變量的凸函數來舉個栗子,如上圖。假如搜索的初始點在極小值的右邊,其梯度(即導數)爲正,則其負梯度方向是從當前位置指向極小值點的方向;假如搜索的初始點在極小值的左邊,則其負梯度方向也是爲從當前的搜索位置指向局部極小值的。由相關數學證明也可推得連續凸函數的負梯度方向總是指向局部極小值點,正梯度方向總是指向其局部極大值點。同時,也必須控制梯度下降的步長,即需要在梯度之前加上一個係數——學習率,否則可能會導致兩個不良後果。

  1. 在搜索極小值的過程中搜索點在極小值點的周圍來回跳動,不斷震盪,但是仍然可以收斂到極小值;
  2. 在搜索過程中,所計算的梯度越來越大,甚至導致計算上溢,搜索失敗。如下圖所示。

所以給梯度下降配上學習率,尤其是選擇合適大小的學習率尤其重要。在深度學習中甚至專門有自適應調整學習率的算法,例如大名鼎鼎的 Adam,還有 AdaGrad 和 RMSProp 等,感興趣的小夥伴去查閱下花書。

因爲搜索初始點的關係,我們搜索到的極小值點可能並非是全局極小值點而只是局部極小值點,這依賴於搜索初始點的位置,廣泛採用的解決方案就是進行多次搜索,每次都隨機的在搜索域產生初始搜索點。重複搜索的次數越多,越有可能找到全局極小值點。

當在學習的過程中如果訓練樣本非常多的話,因爲最終的代價函數是每個樣本代價函數的總和,所以再求梯度的時候每個樣本點都會參與進去,所以以上的梯度下降也叫做批量梯度下降。較大的訓練數據集也意味着較大的計算成本,那我們利用以局部代替整體的思想,從訓練數據集中隨機抽取出一部分樣本點來代替整個數據集,以減小計算開銷,其實這就是深度學習中廣泛採用的隨機梯度下降法。廢話有點多,接下來上代碼。

之後實例化一個對象,訓練模型求其準確率。

結果:

CPU times: user 2 ms, sys: 941 µs, total: 2.94 ms Wall time: 1.38 ms 0.73551631052094557

實例化一個使用隨機梯度下降的線性迴歸模型。

得到結果:

CPU times: user 902 µs, sys: 469 µs, total: 1.37 ms Wall time: 766 µs 0.74803818104616793

一些細心的小夥伴看到我從 scikit-learn 的 linear_model 直接 import SGDRegressor(),實例化後直接拿去訓練而在這過程中並沒有傳入其他的機器學習模型感到奇怪,因爲前面說了梯度下降只是優化算法,而不是機器學習的模型學習算法。

的確是這樣,正如註釋裏所說,scikit-learn 之所以可以這樣做是因爲它在 SGDRegressor() 中集成的是線性迴歸,在學習模型的過程中使用的隨機梯度下降進行優化搜索,使用了隨機梯度下降法的默認模型似乎比沒有使用該算法的模型準確率稍微有所提高,訓練速度也會稍微快了一些。 接下來我們介紹下一些可調整的超參數,並進行調參,順便看下調過參後一些模型的表現。

  • loss:用於選擇損失函數,默認 loss=’squared_loss’,表示損失函數爲預測值與實際值差的平方和,其他還有 ‘huber’, ‘epsilon_insensitive’等;
  • penalty:正則項的懲罰方式,默認 penalty=’l2’, 使用 L2 正則,‘l1’ 和 ‘elasticnet’ ;
  • random_state:shuffle 數據時使用其來種隨機種子;
  • n_iter:對訓練數據集重複訓練的次數,深度學習中常用 Epoch 表示;

更多超參數請小夥伴們自行查閱官方文檔,我就不囉嗦啦!

設置 n_iter 超參如下,得到對應結果 。

CPU times: user 1.7 ms, sys: 659 µs, total: 2.36 ms Wall time: 1.17 ms 0.74863538201180846

與 sgd_reg 相比只能算是略微的提高,那再變大試試。

CPU times: user 6.8 ms, sys: 789 µs, total: 7.59 ms Wall time: 6.14 ms 0.73539011191275572

聰明的讀者有沒有發現這個問題,迭代次數增加,精確度並不一定增加 。爲啥呢?

已知 n_iter 是訓練數據集重複訓練的次數,當 n_iter 過大時,很可能是在訓練數據集上發生了過擬合,導致模型 sgd_reg3 的準確率與前者相比卻有所下降。而且隨着 n_iter 的變大,訓練時間會延長。

沒有免費的午餐定理表明:在所有可能的數據生成分佈上平均之後,每一個分類算法在未事先觀測的點上都有相同的錯誤率。換言之,在某種意義上,沒有一個機器學習算法總是比其他的要好。最先進的算法和簡單地將所有點歸爲同一類的簡單算法有着相同的平均性能。

今天的分享就到這裏了,關於 SGDRegressor 模型還有很多其他超參數的調整,請小夥伴們自己在下面親手操作下,會收穫更多哦。還是那句話,如果你們中有大神路過,還請高擡貴腳,勿踩勿噴。好了,期待與小夥伴們共同進步!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章