梯度下降算法詳解及案例


1.梯度的定義

  • 在單變量的函數中,梯度其實就是函數的微分,代表着函數在某個給定點的切線的斜率
  • 在多變量函數中,梯度是一個向量,向量有方向,梯度的方向就指出了函數在給定點的上升最快的方向

2.梯度下降算法

  迭代尋找下一個點Xi+1,使得f(Xi+1)<=f(Xi),直到 下降的速率為0或者接近零。

3.梯度算法的適用范圍

 

  涉及到函數的的最大值與最小值問題都可以求解。

因此判斷一個問題能否用“梯度”來解決,就是看這個問題能否轉化為“函數最大值和最小值問題求解

4.梯度下降算法的實現(Python)

問題:用梯度下降算法擬合一條直線

分析:擬合點集合的本質就是使這些點盡可能的在這條直線上或者盡可能靠近這些直線,所以評判一條擬合線是否合格,可以通過“均方誤差代價函數”來評判,即,該擬合線上的點與該點的真實值要

的差要最小。可以用下面的 公式來解釋:

 

此公示中

  • m是數據集中點的個數
  • ½是一個常量,這樣是為了在求梯度的時候,二次方乘下來就和這里的½抵消了,自然就沒有多余的常數系數,方便后續的計算,同時對結果不會有影響
  • y 是數據集中每個點的真實y坐標的值
  • h 是我們的預測函數,根據每一個輸入x,根據Θ 計算得到預測的y值

所以這個問題就轉化成:求θ,使得J(θ)的最小值。

其中,θ=[θ01]是一個向量。

我們可以根據代價函數看到,代價函數中的變量有兩個,所以是一個多變量的梯度下降問題,求解出代價函數的梯度,也就是分別對兩個變量進行微分

 

 
為了便於計算和編程,我們可以將上述的公式轉化為矩陣的公式,進而可以利用numpy包進行編程和運算

 

其中:X是一個m行2列的矩陣,表示每個數據點,每個點由兩個元素(維度)表示,其第一列都為1,第二列為點的橫坐標。

   Y:點的橫坐標值所構成的向量

代碼部分:

import numpy as np
from matplotlib import pyplot as plt
def error_function(theta,X,Y):
    '''
    代價函數的實現
    Parameters:
        theda - 擬合曲線的參數
        X - m行n列的矩陣,m個樣本點,每個點由n維元素表示。代價函數自變量
        Y - m行1列的矩陣,代價函數值
    Returns:
        返回代價函數值
    '''
    diff=np.dot(X,theta)-Y
    return (1./2*m)*np.dot(np.transpose(diff),diff)

def gradient_function(theta,X,Y):
    '''
    Parameters:
        theda - 擬合曲線的參數
        X - m行n列的矩陣,m個樣本點,每個點由n維元素表示。代價函數自變量
        Y - m行1列的矩陣,函數的真實值
    Returns:
        返回梯度值
    '''
    diff = np.dot(X, theta)-Y
    return (1./m)*np.dot(np.transpose(X),diff)
def gradient_descent(X,Y,alpha):
    '''
    Parameters:
        X - m行n列的矩陣,m個樣本點,每個點由n維元素表示。代價函數自變量
        Y - m行1列的矩陣,函數的真實值
        alpha - 學習率
    Returns:
        返回theda值
    '''
    theda=np.array([1,1]).reshape(2,1)
    gradient = gradient_function(theda,X,Y)

    while not (np.all(np.absolute(gradient) <= 1e-5 )):
        theda=theda-alpha*gradient
        gradient = gradient_function(theda, X, Y)
    return theda


#測試代碼
#定義點的個數
m=20
#定義X矩陣
x0=np.ones((m,1))
x1=np.arange(1,m+1).reshape(m,1)
X=np.hstack((x0,x1))
#定義Y矩陣
Y = np.array([3, 4, 5, 5, 2, 4, 7, 8, 11, 8, 12,11, 13, 13, 16, 17, 18, 17, 19, 21]).reshape(m, 1)
#給定學習率
alpha=0.01

theda_result=gradient_descent(X,Y,alpha)
print("theta的值是:", theda_result)
print("代價函數值是:", error_function(theda_result,X,Y))

#做出擬合圖像
Xa=np.linspace(1,20,20)
Ya=theda_result[0]+theda_result[1]*Xa
plt.plot(Xa,Ya)
plt.plot(Xa,Y,'ro')
plt.show()

 

最后的擬合結果為:

總結

多樣本點的問題,要學會使用矩陣的這個工具。若能轉化為矩陣問題,則用numpy能大大地簡化代碼,和提高運算速度。

問題的轉化。

 關於上面程序中所用到的numpy知識點

  • np.hstack(x,y)   將x和y向量左往右拼接。
  • 生成ndarray的方式  
1.np.array([1,2,3])  #將列表轉化為數組
2.np.arange(start,stop,[step])    start~stop-1
3.np.zeros([m,n])    np.ones([m,n])  np.eye(m)   #生成m階單位矩陣

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM