python语言原理_梯度下降算法的原理用Python语言实现,易于理解,python,更
梯度下降
要找到某個函數的最小值,就是沿著該函數的梯度的負方向尋找。若尋找某函數最大值,則沿著梯度方向找。
那么梯度下降數學表示:
:步長或叫學習率,
:是函數關于w的導數
梯度上升數學表示:
上述某函數可以理解成最小二乘問題(線性回歸和非線性)的損失函數,均方誤差損失表示為:
對于凸函數可以使用最小二乘法求解最優點,過程是求關于w的導數,使導數等于0即可
對于梯度下降法則需要迭代N次,每次將wi帶入上式中求得wi值下的導數,然后求得wi+1的值
看圖理解
上圖是梯度下降求解過程,假設求解一個線性回歸問題,目標函數是均方誤差最小,數學公式表示為:
用矩陣表示為:
,其中X已知,y已知,w是求要的參數,圓心視為最優點也是誤差最小點,那么對w求導
則梯度的負方向尋找最小點,p0是開始位置,w0可以使初始值1的矩陣,則將w0帶入導數方程求得w0導數,那么根據梯度下降法
,根據此方法一直迭代的圓心點附近,求得的wi使得均方誤差最小。
實例
首先生成隨機樣本:
x = np.arange(0, 100, 1)
y = x * 11.8 - np.random.standard_normal(100) * 100
使用梯度下降法求解結果如下圖
第一張圖表示樣本分布,第二張(右上)表示使用梯度下降法求解擬合直線,第三張(左下)表示隨著迭代次數增加模型損失逐漸下降直至平穩,第四張圖表示參數的學習效果,隨著迭代次數增加參數學習逐漸穩定。
迭代 1 損失:18659840.76439424,weight參數:[[1.0539232487566108, 4.578364388994817]]
迭代 2 損失:9004152.836684883,weight參數:[[1.0901282014628215, 6.981505910781841]]
迭代 3 損失:4649307.430631565,weight參數:[[1.1144339831409158, 8.5953966993742]]
迭代 4 損失:2685213.4523903765,weight參數:[[1.13074857483731, 9.679246133912951]]
迭代 5 損失:1799380.5932514765,weight參數:[[1.1416964803735679, 10.407132849392006]]
迭代 6 損失:1399858.0328088128,weight參數:[[1.1490402518776508, 10.89596376971111]]
迭代 7 損失:1219667.972099556,weight參數:[[1.1539635759490037, 11.22425070567449]]
迭代 8 損失:1138399.8251730944,weight參數:[[1.157261387354931, 11.44472025576014]]
迭代 9 損失:1101746.7947403109,weight參數:[[1.1594675447067935, 11.59278230490871]]
迭代 10 損失:1085215.783217484,weight參數:[[1.1609405742996355, 11.692217259740454]]
迭代10輪,直線方程可以表達為y =??11.692217259740454* x +1.1609405742996355和樣本生成方程即(y = x * 11.8 - np.random.standard_normal(100) * 100)比較接近了
python實現代碼如下
# @Time : 2020/6/16 19:42
# @Author : 大太陽小白
# @Software: PyCharm
"""
通過程序理解如何使用梯度下降求解
1、首先程序定義一個樣本集,用來代替真實數據的分布
2、計算模型誤差,使用均方誤差
3、利用均方誤差求導,解出關于待定參數w的導數
4、目標函數是誤差最小,則關于w的方程求w下降最快方向使目標函數下降最快
5、定義w初始位置,帶入導數方程,求得關于初始位置w的導數
6、w根據w位置導數移動lamda倍步長,得到新的w1點,帶入導數方程求w1導數,如此迭代
7、當滿足一定迭代限制或是誤差限制時停止迭代,求得w值
"""
import numpy as np
import matplotlib.pyplot as plt
def create_sample_set():
"""
生成樣本數據集
:return:
"""
x = np.arange(0, 100, 1)
y = x * 11.8 - np.random.standard_normal(100) * 100
return x, y
def loss(weight, x, y):
"""
損失函數使用均方誤差
:param weight:權重
:param x:
:param y:
:return:
"""
return (x * weight - y).T * (x * weight - y)
def gradient(weight, x, y):
"""
基于損失函數求關于w的導數
:param weight:
:param x:
:param y:
:return:
"""
return x.T * (x * weight - y)
def gradient_descent(x, y, max_iter=10, learning_rate=0.001):
"""
梯度下降求解
:param x:
:param y:
:param max_iter:
:param learning_rate:
:return:
"""
m, n = np.shape(x)
weight = np.mat(np.ones((n, 1)))
loss_arr = []
weight_arr = np.zeros((max_iter,n))
for i in range(max_iter):
g = gradient(weight, x, y)
weight = weight - learning_rate * g
error = loss(weight, x, y).T.tolist()[0][0]
loss_arr.append(error)
weight_arr[i, :] = weight.T
print("迭代 {} 損失:{},weight參數:{}".format(i + 1, error, weight.T.tolist()))
return weight,loss_arr,weight_arr
if __name__ == '__main__':
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用來正常顯示中文標簽
features, labels = create_sample_set()
X = np.ones((2, 100))
X[1] = np.mat(features)
X = X.T
Y = labels.reshape(100, 1)
weights,loss_array,weights_array = gradient_descent(X, Y, learning_rate=0.000001)
# 繪制曲線
fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 1)
ax1.set_title("樣本數據分布" )
ax1.scatter(features, labels)
ax2 = fig.add_subplot(2, 2, 2)
ax2.set_title("梯度下降擬合效果" )
ax2.scatter(features, labels)
ax2.plot(features, (X * weights).T.tolist()[0])
ax3 = fig.add_subplot(2, 2, 3)
ax3.set_title("隨著迭代次數增加loss走勢")
ax3.plot(range(len(loss_array)), loss_array)
ax4 = fig.add_subplot(2, 2, 4)
ax4.set_title("隨著迭代數增加學習的參數逐漸穩定")
ax4.plot(np.array(weights_array))
plt.show()
模型使用的學習率很小,可以嘗試加大學習率(會出現問題),這個時候可以考慮對樣本數據進行標準化。
總結
以上是生活随笔為你收集整理的python语言原理_梯度下降算法的原理用Python语言实现,易于理解,python,更的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 汇编OFFSET,SEG,LEA
- 下一篇: python 接收邮件服务器地址_pyt