# 梯度下降 == 导数值下降
import matplotlib.pyplot as plt
import numpy as np
#引入3D绘图
from mpl_toolkits.mplot3d import Axes3D
# f(x) = (x+y)**2, 目标函数
# f'(x) = 2*x +2*y
# f'(y) =2*y + 2*x 梯度函数:2阶导数函数
def targetFunc(W):
x,y = W
return x**2 + y**2 + 2*x*y
pass
def gradientFunc(W):
x,y = W
xs = 2*x + 2*y
ys = 2*x + 2*y
return np.array([xs,ys])
pass
listx = [] #存放每一次计算点的值
def gradientCal(targetFunc, gradientFunc,init_W, rating=0.1, tolent=0.000000001, times = 500000):
'''
:param initX: 猜测的点
:param targetFunc: 目标函数
:param gradientFunc: 梯度函数
:param rating: 步进系数
:param tolent: 收敛条件
:return: 返回极值点x值
'''
W=init_W
result = targetFunc(W) # 计算出initX这个点的实际值
# gradientResult = gradientFunc(W) # 计算出initX这个点的导数,也是斜率,梯度
listx.append(W)
new_W= W - rating*gradientFunc(W) #计算新的极值点
newResult = targetFunc(W) #计算新的函数值
reResult = np.abs(result - newResult)
t = 0 #初始化循环次数
while reResult > tolent and t < times: #判断循环条件
t += 1
W = new_W #从新赋值
result = newResult
listx.append(W) #将新的值存入列表
new_W = W - rating * gradientFunc(W)
newResult = targetFunc(W)
reResult = np.abs(result - newResult)
pass
return new_W,reResult
if __name__ == "__main__": #函数入口
np.random.seed(0) #确保随机数值一定
init_W = np.array([np.random.random(),np.random.random()])# 创建随机数x点,y点
gradientCal(targetFunc,gradientFunc,init_W) #调用函数计算
xs, ys = np.meshgrid(np.linspace(-50, 50,100), np.linspace(-50, 50, 100))
print(xs)
print(xs.shape)
print(ys.shape)
z = targetFunc([xs, ys])
print(z)
result = []
for row1, row2 in zip(xs, ys):
row = []
for x1, x2 in zip(row1, row2):
row.append(gradientFunc([x1, x2]))
pass
result.append(row)
pass
print(np.array(result))
# 画图
ax = plt.figure().add_subplot(111, projection='3d')
ax.plot_surface(xs, ys, z)
ax.scatter(np.array(listx), np.array(listx), s=20)
plt.show()
效果图