——简单易懂梯度下降算法
梯度下降
什么是梯度下降呢?
梯度下降是迭代法的一种,可以用于求解最小二乘问题(线性和非线性都可以)。在求解机器学习算法的模型参数,即无约束优化问题时,梯度下降(Gradient Descent)是最常采用的方法之一,另一种常用的方法是最小二乘法。在求解损失函数的最小值时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数和模型参数值。反过来,如果我们需要求解损失函数的最大值,这时就需要用梯度上升法来迭代了。在机器学习中,基于基本的梯度下降法发展了两种梯度下降方法,分别为随机梯度下降法和批量梯度下降法。
话不多说 上代码!
一个变量
# 梯度 下降 == 导数下降
import matplotlib.pyplot as plt
import numpy as np
# f(x) = x**2 # 目标函数
# f`(x) = 2*x # 梯度函数:一阶导数函数
# 梯度下降算法是一个方法,是帮助我们找极值点的方法cost
def targetFunc(x):
return (x)**2
pass
def gradientFunc(x):
return 2*x
pass
# 猜测的过程
listx = []
def gradientCal(initX, targetFunc, gradientFunc, rating=0.1, tolent=0.00000001):
'''
:param initX: 猜测的点
:param targetFunc: 目标函数
:param gradientFunc: 梯度函数
:param rating: 不进系数
:param tolent: 收敛条件
:return: 返回极值点x值
'''
result = targetFunc(initX) # 计算出initX这个点的实际值
gradientResult = gradientFunc(initX) # 计算出initX这个点的导数,也是斜率,梯度
newX = initX - rating * gradientFunc(initX)
newResult = targetFunc(newX)
reResult = np.abs(result-newResult)
while reResult > tolent:
initX = newX
result = newResult
listx.append(initX)
newX = newX - rating * gradientFunc(newX)
newResult = targetFunc(newX)
reResult = np.abs(result-newResult)
pass
return initX
pass
if __name__ == "__main__":
print(gradientCal(10, targetFunc, gradientFunc))
x = np.arange(-10, 10+1, 1)
y = (x)**2
plt.plot(x, y)
plt.grid(linestyle='--')
plt.scatter(listx, (np.array(listx))**2, s=20)
plt.show()
print(listx)
pass
多个变量
# 梯度 下降 == 导数下降
import matplotlib.pyplot as plt
import numpy as np
# f(a, b) = a^2 + b^2 # 目标函数
# f`(a, b) = 2*a + 2*b # 梯度函数:一阶导数函数
# 梯度下降算法是一个方法,是帮助我们找极值点的方法cost
def targetFunc(a, b):
return a**2 + b**2
pass
def gradientFunc(a, b):
return 2*a + 2*b
pass
def gradientFunc2(a, b):
return 2*b + 2*a
# 猜测的过程
listx = []
def gradientCal(inita, initb, targetFunc, gradientFunc, gradientFunc2, rating=0.1, tolent=0.00000001, times=500):
'''
:param initX: 猜测的点
:param targetFunc: 目标函数
:param gradientFunc: 梯度函数
:param rating: 不进系数
:param tolent: 收敛条件
:return: 返回极值点x值
'''
result = targetFunc(inita, initb) # 计算出initX这个点的实际值
gradientResult = gradientFunc(inita, initb) # 计算出initX这个点的导数,也是斜率,梯度
newa = inita - rating * gradientFunc(inita, initb)
newb = initb - rating * gradientFunc2(inita, initb)
newResult = targetFunc(newa, newb)
reResult = np.abs(result-newResult)
count = 0
while reResult > tolent and count < times:
count += 1
inita = newa
initb = newb
result = newResult
listx.append((inita, initb))
newa = newa - rating * gradientFunc(newa, newb)
newb = newb - rating * gradientFunc2(newb, newa)
newResult = targetFunc(newa, newb)
reResult = np.abs(result-newResult)
pass
return inita, initb
pass
if __name__ == "__main__":
print(gradientCal(10, 10, targetFunc, gradientFunc, gradientFunc2))
a = np.arange(-10, 10, 1)
b = np.arange(-10, 10, 1)
y = a**2 + b**2
plt.plot(a, b, y)
plt.grid(linestyle='--')
plt.scatter(np.array(listx), (np.array(listx))**2, s=20)
plt.show()
print(listx)
pass