梯度下降法快速教程 | 第一章:Python簡易實現以及對學習率的探討

邀請關注微信公眾號:人工智慧LeadAI(ID:atleadai)

歡迎訪問我們的官方主頁:www.leadai.org

前言

梯度下降法(Gradient Descent)是機器學習中最常用的優化方法之一,常用來求解目標函數的極值。

其基本原理非常簡單:沿著目標函數梯度下降的方向搜索極小值(也可以沿著梯度上升的方向搜索極大值)。

但是如何調整搜索的步長(也叫學習率,Learning Rate)、如何加快收斂速度以及如何防止搜索時發生震蕩卻是一門值得深究的學問。接下來本文將分析第一個問題:學習率的大小對搜索過程的影響。全部源代碼可在本人的GitHub:monitor1379(https://github.com/monitor1379/jianshu_blog/blob/master/scripts/gradient_descent_with_momentum_and_decay.py)中下載。

快速教程

前言啰嗦完了,接下來直接上乾貨:如何編寫梯度下降法。代碼運行環境為Python 2.7.11 + NumPy 1.11.0 + Matplotlib 1.5.1。

首先先假設現在我們需要求解目標函數func(x) = x * x的極小值,由於func是一個凸函數,因此它唯一的極小值同時也是它的最小值,其一階導函數 為dfunc(x) = 2 * x。

import numpy as npnimport matplotlib.pyplot as pltn# 目標函數:y=x^2ndef func(x):nreturn np.square(x)n# 目標函數一階導數:dy/dx=2*xndef dfunc(x):nreturn 2 * xn

接下來編寫梯度下降法函數:

# Gradient Descentdef GD(x_start, df, epochs, lr):n """n 梯度下降法。給定起始點與目標函數的一階導函數,求在epochs次迭代中x的更新值n :param x_start: x的起始點n :param df: 目標函數的一階導函數n :param epochs: 迭代周期n :param lr: 學習率n :return: x在每次迭代後的位置(包括起始點),長度為epochs+1n """n xs = np.zeros(epochs+1)n x = x_startn xs[0] = x for i in range(epochs):n dx = df(x) # v表示x要改變的幅度n v = - dx * lrn x += vn xs[i+1] = x return xsn

需要注意的是參數df是一個函數指針,即需要傳進我們的目標函數一階導函數。

測試代碼如下,假設起始搜索點為-5,迭代周期為5,學習率為0.3:

def demo0_GD(): nx_start = -5 nepochs = 5 nlr = 0.3 nx = GD(x_start, dfunc, epochs, lr=lr) nprint x n# 輸出:[-5. -2. -0.8 -0.32 -0.128 -0.0512]n

繼續修改一下demo0_GD函數以更加直觀地查看梯度下降法的搜索過程:

def demo0_GD(): n"""演示如何使用梯度下降法GD()""" nline_x = np.linspace(-5, 5, 100) n line_y = func(line_x) nx_start = -5 nepochs = 5 nlr = 0.3 nx = GD(x_start, dfunc, epochs, lr=lr) ncolor = r nplt.plot(line_x, line_y, c=b) nplt.plot(x, func(x), c=color, label=lr={}.format(lr)) nplt.scatter(x, func(x), c=color, ) nplt.legend()nplt.show()n

從運行結果來看,當學習率為0.3的時候,迭代5個周期似乎便能得到蠻不錯的結果了。

demo0_GD運行結果

梯度下降法確實是求解非線性方程極值的利器之一,但是如果學習率沒有調整好的話會發生什麼樣的事情呢?

學習率對梯度下降法的影響

在上節代碼的基礎上編寫新的測試代碼demo1_GD_lr,設置學習率分別為0.1、0.3與0.9:

def demo1_GD_lr(): n# 函數圖像 n line_x = np.linspace(-5, 5, 100) nline_y = func(line_x) nplt.figure(Gradient Desent: Learning Rate) nx_start = -5 nepochs = 5 nlr = [0.1, 0.3, 0.9] ncolor = [r, g, y] nsize = np.ones(epochs+1) * 10 nsize[-1] = 70 nfor i in range(len(lr)): nx = GD(x_start, dfunc, epochs, lr=lr[i]) nplt.subplot(1, 3, i+1) nplt.plot(line_x, line_y, c=b) nplt.plot(x, func(x), c=color[i], label=lr={}.format(lr[i])) nplt.scatter(x, func(x), c=color[i]) nplt.legend()nplt.show()n

從下圖輸出結果可以看出兩點,在迭代周期不變的情況下:

  • 學習率較小時,收斂到正確結果的速度較慢。
  • 學習率較大時,容易在搜索過程中發生震蕩。

demo1_GD_lr運行結果

綜上可以發現,學習率大小對梯度下降法的搜索過程起著非常大的影響,為了解決上述的兩個問題,接下來的博客《【梯度下降法】二:衝量(momentum)的原理與Python實現》將講解衝量(momentum)參數是如何在梯度下降法中起到加速收斂與減少震蕩的作用。

原文鏈接:jianshu.com/p/186df2db8

查閱更為簡潔方便的分類文章以及最新的課程、產品信息,請移步至全新呈現的

leadai.org

請關注人工智慧LeadAI公眾號,查看更多專業文章

weixin.qq.com/r/ZDnC2j- (二維碼自動識別)

大家都在看

LSTM模型在問答系統中的應用

基於TensorFlow的神經網路解決用戶流失概覽問題

最全常見演算法工程師面試題目整理(一)

最全常見演算法工程師面試題目整理(二)

TensorFlow從1到2 | 第三章 深度學習革命的開端:卷積神經網路

裝飾器 | Python高級編程

今天不如來複習下Python基礎


推薦閱讀:

visual studio code寫Python無法自動補全?
PyQt5番外篇(2-3):沖頂大會語音答題輔助小工具之解析篇——問題採集
python與numpy使用的一些小tips[6]
從一次CycleGAN實現聊聊TF
轉載好文章「量產型炮灰工程師」

TAG:Python | 梯度下降 |