首先给出梯度下降法的python源码:
# conding:utf-8
import numpy as np
import matplotlib.pyplot as plt
# 原函数
def function_1(x):
# 二元二次函数,这里最小值点为(0,0)
return x[0] ** 2 + x[1] ** 2
def numerical_gradient(f, x):
"""采用中心差分计算数值微分
:param f: 原函数
:param x: 当前位置(x1,x2)
:return: 返回当前位置梯度
"""
h = 1e-4 # 0.0001,定义间隔
grad = np.zeros_like(x) # 初始化梯度grad=(0,0)
for idx in range(x.size): # 分别计算每个元素位的微分
tmp_val = x[idx]
x[idx] = float(tmp_val) + h
fxh1 = f(x) # 如对以一个元素f([x1+h,x2])
x[idx] = float(tmp_val) - h
fxh2 = f(x) # f(x-h)
grad[idx] = (fxh1 - fxh2) / (2 * h) # 如对第一个元素grad(new_x1,0)
x[idx] = tmp_val # 还原值
return grad
def gradient_descent(f, init_x, l_rate=0.01, step_num=100): # 默认学习率和迭代函数
"""迭代计算梯度
:param f: 原函数
:param init_x: 给定初始位置
:param l_rate: 学习率
:param step_num: 迭代次数
:return: 返回函数值更新结果,以及函数值的变化用于画图
"""
x = init_x # 初始值点
x_history = [] # 纪录函数值变化轨迹
for i in range(step_num): # 迭代次数
x_history.append(x.copy()) # 添加纪录函数值变化轨迹
# print("x_history: " + str(x_history))
grad = numerical_gradient(f, x) # 计算当前位置的梯度
x -= l_rate * grad # 沿着梯度方向更新函数值
print("step_num: " + str(i+1) + " grad:" + str(grad) + " x:" + str(x))
return x, np.array(x_history)
init_x = np.array([-3.0, 4.0]) # 初值点
l_rate = 0.1 # 学习率
step_num = 10 # 迭代次数
# 返回所计算的最小值,以及函数值变化轨迹
x, x_history = gradient_descent(function_1, init_x, l_rate=l_rate, step_num=step_num)
plt.plot([-10, 10], [0, 0], '--b') # 坐标
plt.plot([0, 0], [-10, 10], '--b')
plt.plot(x_history[:, 0], x_history[:, 1], 'rx') # x_history=(10, 2)
plt.xlim(-4, 4)
plt.ylim(-5, 5)
plt.xlabel('x0')
plt.ylabel('x1')
plt.show()
展示20次迭代结果:
step_num: 1 grad:[-6. 8.] x:[-2.4 3.2]
step_num: 2 grad:[-4.8 6.4] x:[-1.92 2.56]
step_num: 3 grad:[-3.84 5.12] x:[-1.536 2.048]
step_num: 4 grad:[-3.072 4.096] x:[-1.2288 1.6384]
step_num: 5 grad:[-2.4576 3.2768] x:[-0.98304 1.31072]
step_num: 6 grad:[-1.96608 2.62144] x:[-0.786432 1.048576]
step_num: 7 grad:[-1.572864 2.097152] x:[-0.6291456 0.8388608]
step_num: 8 grad:[-1.2582912 1.6777216] x:[-0.50331648 0.67108864]
step_num: 9 grad:[-1.00663296 1.34217728] x:[-0.40265318 0.53687091]
step_num: 10 grad:[-0.80530637 1.07374182] x:[-0.32212255 0.42949673]
step_num: 11 grad:[-0.64424509 0.85899346] x:[-0.25769804 0.34359738]
step_num: 12 grad:[-0.51539608 0.68719477] x:[-0.20615843 0.27487791]
step_num: 13 grad:[-0.41231686 0.54975581] x:[-0.16492674 0.21990233]
step_num: 14 grad:[-0.32985349 0.43980465] x:[-0.1319414 0.17592186]
step_num: 15 grad:[-0.26388279 0.35184372] x:[-0.10555312 0.14073749]
step_num: 16 grad:[-0.21110623 0.28147498] x:[-0.08444249 0.11258999]
step_num: 17 grad:[-0.16888499 0.22517998] x:[-0.06755399 0.09007199]
step_num: 18 grad:[-0.13510799 0.18014399] x:[-0.0540432 0.07205759]
step_num: 19 grad:[-0.10808639 0.14411519] x:[-0.04323456 0.05764608]
step_num: 20 grad:[-0.08646911 0.11529215] x:[-0.03458765 0.04611686]
函数值变化曲线:
