1. 程式人生 > >一種更簡單的求最小平方均值函式(MSE)的方法 -- 梯度下降法。

一種更簡單的求最小平方均值函式(MSE)的方法 -- 梯度下降法。

  1. 在上一篇部落格中我們通過解析解法算出來了

    這裡寫圖片描述
    但是上面公式中的對稱陣是N維乘以N維的,複雜度為O(n*n*n),雖然很精準但是很慢。

    此我們引入梯度下降法

我們首先大致畫出MSE的影象,MSE是一個開口向下,有最小值的凸函式,它的影象如下圖。

這裡寫圖片描述
其中θ為模型w0~wn,縱軸為MSE的值。
由圖可知,該影象上點的梯度會隨著位置變化,當在θ ̂(MSE最小)時,梯度為零。

由圖可知,在圖中我們初始了一個θ,將這個θ代入梯度下降法公式,我們便可以求出下一個時刻的θ
其中梯度下降法的公式為:
這裡寫圖片描述

其中:α為計算機的學習率(不變,由人工設定),g為(θ=θt)時的梯度
為此,要讓我們計算機用梯度下降法求最小MSE只需執行以下4個步驟即可;
1:求初始化θ,設定學習率α
2:求梯度g
3:代入公式,判斷g是否等於0
4:當g等於0時,停止

接下來我們對MSE函式求導,找到g的關係。
這裡寫圖片描述
這裡寫圖片描述

為此,在日常的演算法中,我們結合兩種方法,一般我們採用小批量的隨機梯度下降法

接下來,我們用程式碼分別實現批量梯度下降法和隨機梯度下降法。

批量梯度下降法:

import  numpy as np
import matplotlib.pyplot as plt

#模擬資料
#模擬100行1列X的資料
X = 2* np.random.rand(100,1)
y = 4+3*X +np.random.randn(100,1)

#將X於1列100行連線
X_b = np.c_[np.ones((100,1)),X]

# print(X_b)
#學習率阿爾法的設定
learning_rate = 0.01 #設定迭代次數 n_interations= 10000 m= 100 #第一步:初始化 theta = np.random.randn(2,1) count = 0 #第二步;代入公式 for interation in range(n_interations): count +=1 #求梯度 index = np.random.randint(m) #切片 Xi = X_b[index:index+1] yi = y[index:index+1] gradients = Xi.T.dot(Xi.dot(theta)-yi) #隨機梯度下降法只要把求梯度改成
#帶入梯度下降公式 theta = theta- learning_rate*gradients print(count) print(theta) #繪圖 X_new = np.array([[0],[2]]) X_new_b = np.c_[(np.ones((2,1))),X_new] print(X_new_b) y_predict = X_new_b.dot(theta) # print(y_predict) #繪圖模組 plt.plot(X_new,y_predict,'r-') plt.plot(X,y,'b.') plt.axis([0,2,0,15]) plt.show()

執行結果:這裡寫圖片描述

批量梯度下降法:

import  numpy as np
import matplotlib.pyplot as plt

#模擬資料
#模擬100行1列X的資料
X = 2* np.random.rand(100,1)
y = 4+3*X +np.random.randn(100,1)

#將X於1列100行連線
X_b = np.c_[np.ones((100,1)),X]

# print(X_b)
#學習率阿爾法的設定
learning_rate = 0.01
#設定迭代次數
n_interations= 1000000
m= 100

#第一步:初始化
theta  = np.random.randn(2,1)
count = 0

#第二步;代入公式

for interation in range(n_interations):
    count +=1
    #求梯度
    gradients = 1/m *X_b.T.dot(X_b.dot(theta)-y)


print(count)
print(theta)


#繪圖
X_new = np.array([[0],[2]])

X_new_b = np.c_[(np.ones((2,1))),X_new]

print(X_new_b)

y_predict = X_new_b.dot(theta)

# print(y_predict)
#繪圖模組
plt.plot(X_new,y_predict,'r-')
plt.plot(X,y,'b.')
plt.axis([0,2,0,15])
plt.show()

執行結果:
這裡寫圖片描述

最後介紹一種學習率調參的方法,其實梯度下降法就正如我們找山下的地雷一般,而學習率的大小正如你步子的大小一樣,如果你的步子太大,可能一下子就跨過了地雷,無法將地雷找出來,若是你的學習率的太小,則所用的時間會很長很長,我們正確的方法應該是步子大小隨著下山步子數的增多而變小,為此我介紹一種學習率調參的方法;
“`
import numpy as np

模擬資料

模擬100行1列X的資料

X = 2* np.random.rand(100,1)
y = 4+3*X +np.random.randn(100,1)
X_b = np.c_[np.ones((100,1)),X]

n_epochs = 1000#倫次,把已有的資料學更多的次數
t0,t1 = 5,500#超引數

m = 100#100行

學習率

定義調參方法

def learning_schedule(t):
return t0/(t+t1)

初始化

theta = np.random .randn(2,1)

for epoch in range(n_epochs):
for i in range(m):
random_index = np.random.randint(m)
xi = X_b[random_index:random_index+1]
yi = y[random_index:random_index+1]
gradients = 2*xi.T.dot(xi.dot(theta)-yi)
learning_rate = learning_schedule(epoch*m+i)
theta = theta - learning_rate*gradients

print(theta)

繪圖

X_new = np.array([[0],[2]])

X_new_b = np.c_[(np.ones((2,1))),X_new]

print(X_new_b)

y_predict = X_new_b.dot(theta)

print(y_predict)

繪圖模組

plt.plot(X_new,y_predict,’r-‘)
plt.plot(X,y,’b.’)
plt.axis([0,2,0,15])
plt.show()

總結:這種方法相比解析式求θ法來說更好理解,但用解析式求的更精確,但這種方法更偏向於猜,因為我還沒有學到如何使用抽取部分資料的批量梯度下降法,等學到了也會分享給大家。
本人人工智慧小白,歡迎各位指正我的這篇文章,與我討論其中的問題。
這裡寫圖片描述