1.梯度的定義
- 在單變量的函數中,梯度其實就是函數的微分,代表着函數在某個給定點的切線的斜率
- 在多變量函數中,梯度是一個向量,向量有方向,梯度的方向就指出了函數在給定點的上升最快的方向
2.梯度下降算法
迭代尋找下一個點Xi+1,使得f(Xi+1)<=f(Xi),直到 下降的速率為0或者接近零。
3.梯度算法的適用范圍
涉及到函數的的最大值與最小值問題都可以求解。
因此判斷一個問題能否用“梯度”來解決,就是看這個問題能否轉化為“函數最大值和最小值問題求解”
此公示中
- m是數據集中點的個數
- ½是一個常量,這樣是為了在求梯度的時候,二次方乘下來就和這里的½抵消了,自然就沒有多余的常數系數,方便后續的計算,同時對結果不會有影響
- y 是數據集中每個點的真實y坐標的值
-
h 是我們的預測函數,根據每一個輸入x,根據Θ 計算得到預測的y值
所以這個問題就轉化成:求θ,使得J(θ)的最小值。
其中,θ=[θ0,θ1]是一個向量。
我們可以根據代價函數看到,代價函數中的變量有兩個,所以是一個多變量的梯度下降問題,求解出代價函數的梯度,也就是分別對兩個變量進行微分

為了便於計算和編程,我們可以將上述的公式轉化為矩陣的公式,進而可以利用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階單位矩陣