Python實現梯度下降法的示例代碼
1.首先讀取數據集
導包并讀取數據,數據自行任意準備,只要有兩列,可以分為自變量x和因變量y即可即可。
import numpy as np
import matplotlib.pyplot as plt
data = np.loadtxt("data.csv", delimiter=",")
x_data = data[:, 0]
y_data = data[:, 1]
2.初始化相關參數
# 初始化 學習率 即每次梯度下降時的步長 這里設置為0.0001 learning_rate = 0.0001 # 初始化 截距b 與 斜率k b = 0 k = 0 # 初始化最大迭代的次數 以50次為例 n_iterables = 50
3.定義計算代價函數–>MSE
使用均方誤差 MSE (Mean Square Error)來作為性能度量標準
假設共有m個樣本數據,則均方誤差:

將該公式定義為代價函數,此外為例后續(xù)求導方便,則使結果在原mse的基礎上,再乘以1/2。
def compute_mse(b, k, x_data, y_data):
total_error = 0
for i in range(len(x_data)):
total_error += (y_data[i] - (k * x_data[i] + b)) ** 2
# 為方便求導:乘以1/2
mse_ = total_error / len(x_data) / 2
return mse_
4.梯度下降
分別對上述的MSE表達式(乘以1/2后)中的k,b求偏導,

更新b和k時,使用原來的b,k值分別減去關于b、k的偏導數與學習率的乘積即可。至于為什么使用減號,可以這么理解:以斜率k為例,當其導數大于零的時候,則表示均方誤差隨著斜率的增大而增大,為了使均方誤差減小,則不應該使斜率繼續(xù)增大,所以需要使其減小,反之當偏導大于零的時候也是同理。其次,因為這個導數衡量的是均方誤差的變化,而不是斜率和截距的變化,所以這里需要引入一個學習率,使得其與偏導數的乘積能夠在一定程度上起到控制截距和斜率變化的作用。
def gradient_descent(x_data, y_data, b, k, learning_rate, n_iterables):
m = len(x_data)
# 迭代
for i in range(n_iterables):
# 初始化b、k的偏導
b_grad = 0
k_grad = 0
# 遍歷m次
for j in range(m):
# 對b,k求偏導
b_grad += (1 / m) * ((k * x_data[j] + b) - y_data[j])
k_grad += (1 / m) * ((k * x_data[j] + b) - y_data[j]) * x_data[j]
# 更新 b 和 k 減去偏導乘以學習率
b = b - (learning_rate * b_grad)
k = k - (learning_rate * k_grad)
# 每迭代 5 次 輸出一次圖形
if i % 5 == 0:
print(f"當前第{i}次迭代")
print("b_gard:", b_grad, "k_gard:", k_grad)
print("b:", b, "k:", k)
plt.scatter(x_data, y_data, color="maroon", marker="x")
plt.plot(x_data, k * x_data + b)
plt.show()
return b, k
5.執(zhí)行
print(f"開始:截距b=,斜率k={k},損失={compute_mse(b,k,x_data,y_data)}")
print("開始迭代")
b, k = gradient_descent(x_data, y_data, b, k, learning_rate, n_iterables)
print(f"迭代{n_iterables}次后:截距b=,斜率k={k},損失={compute_mse(b,k,x_data,y_data)}")
代碼執(zhí)行過程產生了一系列的圖像,部分圖像如下圖所示,隨著迭代次數的增加,代價函數越來越小,最終達到預期效果,如下圖所示:
第5次迭代:

第10次迭代:

第50次迭代:

執(zhí)行過程的輸出結果如下圖所示:

可以看到,隨著偏導數越來越小,斜率與截距的變化也越來越細微。
到此這篇關于Python實現梯度下降法的示例代碼的文章就介紹到這了,更多相關Python梯度下降法內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

