機(jī)器學(xué)習(xí)每日一解(梯度下降算法)

無聊的言論

自己其實(shí)聽過挺多課的,之前也會亂七八糟報(bào)一堆課,一直堅(jiān)信著一個(gè)原則,沒有輸出再多的輸入也沒什么卵用,其實(shí)也真的是這樣,輸入再多都不如實(shí)際的輸出一波,希望大家可以認(rèn)真的把老師的每個(gè)例子都能實(shí)踐出來,我也會給大家說怎么實(shí)踐以及如何看到自己的結(jié)果,大綱就是21天入門的大綱,跟著猴哥走起來!
emmm 其實(shí)寫了好多又都刪了,不知道覺得將老師的課本重復(fù)一遍又沒什么太大的用途,我們就從算法開始講起,原理部分就當(dāng)大家都理解啦,就從第一個(gè)算法,梯度下降法,我會把老師講的東西掰開揉碎寫清楚,也許會有些瑣碎,選擇自己需要的看,這篇文章也是我看了好多文章論文寫出來的,希望能有幫助!

梯度下降法快速入門

原理方面請看老師的講解,這里我們主要來學(xué)習(xí)實(shí)際原理以及實(shí)現(xiàn)

前言

梯度下降法(Gradient Descent)是機(jī)器學(xué)習(xí)中最常用的優(yōu)化方法之一,常用來求解目標(biāo)函數(shù)的極值。
其基本原理非常簡單:沿著目標(biāo)函數(shù)梯度下降的方向搜索極小值(也可以沿著梯度上升的方向搜索極大值)。
但是如何調(diào)整搜索的步長(也叫學(xué)習(xí)率,Learning Rate)、如何加快收斂速度以及如何防止搜索時(shí)發(fā)生震蕩卻是一門值得深究的學(xué)問。接下來本文將分析第一個(gè)問題:學(xué)習(xí)率的大小對搜索過程的影響


梯度圖.png

計(jì)算步驟.png

來梳理梯度下降法的原理

梯度下降的相關(guān)概念

在詳細(xì)了解梯度下降的算法之前,我們先看看相關(guān)的一些概念。

1. 步長(Learning rate):步長決定了在梯度下降迭代的過程中,每一步沿梯度負(fù)方向前進(jìn)的長度。用上面下山的例子,步長就是在當(dāng)前這一步所在位置沿著最陡峭最易下山的位置走的那一步的長度。

2.特征(feature):指的是樣本中輸入部分,比如2個(gè)單特征的樣本(x(0),y(0)),(x(1),y(1)),則第一個(gè)樣本特征為x(0),第一個(gè)樣本輸出為y(0)。

3. 假設(shè)函數(shù)(hypothesis function):在監(jiān)督學(xué)習(xí)中,為了擬合輸入樣本,而使用的假設(shè)函數(shù),記為hθ(x)。比如對于單個(gè)特征的m個(gè)樣本(x(i),y(i))(i=1,2,...m),可以采用擬合函數(shù)如下: hθ(x)=θ0+θ1x。

4. 損失函數(shù)(loss function):為了評估模型擬合的好壞,通常用損失函數(shù)來度量擬合的程度。損失函數(shù)極小化,意味著擬合程度最好,對應(yīng)的模型參數(shù)即為最優(yōu)參數(shù)。在線性回歸中,損失函數(shù)通常為樣本輸出和假設(shè)函數(shù)的差取平方。比如對于m個(gè)樣本(xi,yi)(i=1,2,...m),采用線性回歸,損失函數(shù)為:

         J(θ0,θ1)=∑i=1m(hθ(xi)?yi)2

其中xi表示第i個(gè)樣本特征,yi表示第i個(gè)樣本對應(yīng)的輸出,hθ(xi)為假設(shè)函數(shù)。

解決實(shí)際問題

是為了解決最優(yōu)化問題,而最優(yōu)化問題其實(shí)就是我們大學(xué)中,來求極大值以及極小值的問題
初中時(shí)我們就學(xué)會了求解二次函數(shù)的極值(拋物線的頂點(diǎn)),高中時(shí)學(xué)習(xí)了冪函數(shù),指數(shù)函數(shù),對數(shù)函數(shù),三角函數(shù),反三角函數(shù)等各種類型的函數(shù),求函數(shù)極值的題更是頻頻出現(xiàn)。這些方法都采用了各種各樣的技巧,沒有一個(gè)統(tǒng)一的方案。
大學(xué)的時(shí)候我們使用微積分,而這個(gè)就是一個(gè)通用的方案:

找到函數(shù)的導(dǎo)數(shù)等于0的點(diǎn),因?yàn)樵跇O值(請注意極值不一定是全局極值),導(dǎo)數(shù)必然為0.

機(jī)器學(xué)習(xí)中,我們一般將最優(yōu)化問題統(tǒng)一表述為求解函數(shù)的極小值問題:


image.png

其中x稱為優(yōu)化變量,f稱為目標(biāo)函數(shù)。極大值問題可以轉(zhuǎn)換成極小值問題來求解,只需要將目標(biāo)函數(shù)加上負(fù)號即可:


image.png

有些時(shí)候會對優(yōu)化變量x有約束,包括等式約束和不等式約束,它們定義了優(yōu)化變量的可行域,即滿足約束條件的點(diǎn)構(gòu)成的集合。在這里我們先不考慮帶約束條件的問題。

一個(gè)優(yōu)化問題的全局極小值x是指對于可行域里所有的x,有:


image.png

即全局極小值點(diǎn)處的函數(shù)值不大于任意一點(diǎn)處的函數(shù)值。局部極小值x
定義為存在一個(gè)δ鄰域,對于在鄰域內(nèi):


image.png

并且在可行域內(nèi)的所有x,有:


image.png

即局部極小值點(diǎn)處的函數(shù)值比一個(gè)局部返回內(nèi)所有點(diǎn)的函數(shù)值都小。在這里,我們的目標(biāo)是找到全局極小值。不幸的是,有些函數(shù)可能有多個(gè)局部極小值點(diǎn),因此即使找到了導(dǎo)數(shù)等于0的所有點(diǎn),還需要比較這些點(diǎn)處的函數(shù)值。

導(dǎo)數(shù)與梯度

由于實(shí)際應(yīng)用中一般都是多元函數(shù),因此我們跳過一元函數(shù),直接介紹多元函數(shù)的情況。梯度是導(dǎo)數(shù)對多元函數(shù)的推廣,它是多元函數(shù)對各個(gè)自變量偏導(dǎo)數(shù)形成的向量。多元函數(shù)的梯度定義為:

image.png

其中? 稱為梯度算子,它作用于一個(gè)多元函數(shù),得到一個(gè)向量。下面是計(jì)算函數(shù)梯度的一個(gè)例子:


image.png

可導(dǎo)函數(shù)在某一點(diǎn)處取得極值的必要條件是梯度為0,梯度為0的點(diǎn)稱為函數(shù)的駐點(diǎn),這是疑似極值點(diǎn)。需要注意的是,梯度為0只是函數(shù)取極值的必要條件而不是充分條件,即梯度為0的點(diǎn)可能不是極值點(diǎn)。

編寫一個(gè)梯度下降的例子

首先先假設(shè)現(xiàn)在我們需要求解目標(biāo)函數(shù)func(x) = x * x的極小值,由于func是一個(gè)凸函數(shù),因此它唯一的極小值同時(shí)也是它的最小值,其一階導(dǎo)函數(shù) 為dfunc(x) = 2 * x。

import numpy as np

import matplotlib.pyplot as plt

# 目標(biāo)函數(shù):y=x^2

def func(x): return np.square(x)

# 目標(biāo)函數(shù)一階導(dǎo)數(shù):dy/dx=2*x

def dfunc(x): return 2 * x

接下來編寫梯度下降法函數(shù):

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

需要注意的是參數(shù)df是一個(gè)函數(shù)指針,即需要傳進(jìn)我們的目標(biāo)函數(shù)一階導(dǎo)函數(shù)。
測試代碼如下,假設(shè)起始搜索點(diǎn)為-5,迭代周期為5,學(xué)習(xí)率為0.3:

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

  plt.show()
image.png

學(xué)習(xí)率對梯度下降法的影響

在上節(jié)代碼的基礎(chǔ)上編寫新的測試代碼demo1_GD_lr,設(shè)置學(xué)習(xí)率分別為0.1、0.3與0.9:

def demo1_GD_lr():    
  # 函數(shù)圖像   
  line_x = np.linspace(-5, 5, 100)    
  line_y = func(line_x)    
  plt.figure('Gradient Desent: Learning Rate')    
  x_start = -5    
  epochs = 5    
  lr = [0.1, 0.3, 0.9]    
  color = ['r', 'g', 'y']    
  size = np.ones(epochs+1) * 10    
  size[-1] = 70    
  for i in range(len(lr)):        
  x = GD(x_start, dfunc, epochs, lr=lr[i])        
  plt.subplot(1, 3, i+1)        

  plt.plot(line_x, line_y, c='b')        
  plt.plot(x, func(x), c=color[i], label='lr={}'.format(lr[i]))        
  plt.scatter(x, func(x), c=color[i])        
  plt.legend()

  plt.show()

從下圖輸出結(jié)果可以看出兩點(diǎn),在迭代周期不變的情況下:

  • 學(xué)習(xí)率較小時(shí),收斂到正確結(jié)果的速度較慢。
  • 學(xué)習(xí)率較大時(shí),容易在搜索過程中發(fā)生震蕩。


    image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容