文章目录
- 简介
- 曲线下降
- 曲面下降
简介
梯度下降是一种优化算法,常用于寻找函数的最小值或最大值。它通过迭代更新参数的方式逐步减小(或增大)目标函数的值,直到达到某个停止条件为止。梯度下降的基本思想是沿着目标函数的负梯度方向进行搜索,以便找到函数的极值点。
梯度下降步骤:
-
初始化参数:选择初始参数值,通常为随机值或者根据问题的特点进行选择。
-
计算梯度:计算目标函数在当前参数值处的梯度。梯度是函数在给定点的导数,它表示函数在该点上升(或下降)最快的方向。
-
更新参数:根据梯度的方向和大小,更新当前参数值。更新规则通常是将当前参数值沿着负梯度方向移动一定步长,以减小目标函数的值。
-
重复步骤2和3:重复计算梯度并更新参数的过程,直到达到停止条件。停止条件可以是达到最大迭代次数、梯度足够小、或者函数值的变化足够小等。
梯度下降算法可以分为多种类型,包括批量梯度下降(Batch Gradient Descent)、随机梯度下降(Stochastic Gradient Descent)、小批量梯度下降(Mini-batch Gradient Descent)等。它们的区别主要在于每次迭代时使用的数据量不同。
-
批量梯度下降(Batch Gradient Descent):在每次迭代时使用全部训练数据计算梯度。
-
随机梯度下降(Stochastic Gradient Descent):在每次迭代时随机选择一个样本计算梯度。这种方法计算速度快,但可能会导致不稳定的更新。
-
小批量梯度下降(Mini-batch Gradient Descent):每次迭代时使用一小部分训练数据计算梯度。这种方法结合了批量梯度下降和随机梯度下降的优点,通常是最常用的方法。
梯度下降算法的性能受到学习率、初始化参数、停止条件等超参数的影响。选择合适的超参数对于算法的收敛速度和最终结果至关重要。通常需要通过实验和调参来确定最佳的超参数值。
曲线下降
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# 定义目标函数和其梯度
def f(x):
return x**2
def grad_f(x):
return 2*x
# Adam优化器参数
alpha = 0.1 # 学习率
epsilon = 1e-6 # 停止条件:梯度接近零
max_iterations = 1000 # 最大迭代次数
# 初始化参数
x = 3.0 # 初始参数值
# 记录每次迭代的参数值和函数值
x_values = [x] # 用于存储每次迭代后的参数值
y_values = [f(x)] # 用于存储每次迭代后的函数值
# 梯度下降迭代
for i in range(max_iterations):
grad = grad_f(x) # 计算当前参数的梯度
x = x - alpha * grad # 更新参数
x_values.append(x) # 记录更新后的参数值
y_values.append(f(x)) # 记录更新后的函数值
if abs(grad) < epsilon: # 如果梯度接近零,停止迭代
break
# 设置绘图
fig, ax = plt.subplots()
x_range = np.linspace(-4, 4, 100)
ax.plot(x_range, f(x_range), label='Function')
point, = ax.plot([], [], 'ro') # 初始化一个红色圆点,用于表示每次迭代后的参数位置
text = ax.text(0.02, 0.95, '', transform=ax.transAxes) # 初始化一个文本标签,用于显示参数和函数值
def init():
"""初始化函数,设置动画开始时的绘图内容"""
point.set_data([], []) # 初始时红色圆点的位置为空
text.set_text('') # 初始时文本内容为空
return point, text
def update(frame):
"""更新函数,逐帧更新动画内容"""
x = x_values[frame] # 获取当前帧对应的参数值
y = y_values[frame] # 获取当前帧对应的函数值
point.set_data(x, f(x)) # 更新红色圆点的位置
text.set_text(f'x = {x:.4f}\nf(x) = {y:.4f}') # 更新文本内容,显示当前参数和函数值
return point, text
# 创建动画
ani = FuncAnimation(fig, update, frames=range(len(x_values)),
init_func=init, blit=True, interval=50, repeat=False)
# 设置图例、标签和标题
ax.legend()
ax.set_xlabel('x')
ax.set_ylabel('f(x)')
ax.set_title('Gradient Descent Visualization on a Simple Function')
# 显示图形
plt.show()
print(f"Minimum point: x = {x_values[-1]}, f(x) = {y_values[-1]}")
曲面下降
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# 定义目标函数
def f(x, y):
return x**2 + y**2
# 定义目标函数的梯度
def grad_f(x, y):
return np.array([2*x, 2*y])
# 定义梯度下降算法
def gradient_descent(starting_point, learning_rate, iterations):
x = starting_point
trajectory = [x]
for _ in range(iterations):
x = x - learning_rate * grad_f(*x)
trajectory.append(x)
return np.array(trajectory)
# 设置参数
starting_point = np.array([3.0, 4.0]) # 初始参数值
learning_rate = 0.1 # 学习率
iterations = 50 # 迭代次数
# 运行梯度下降算法
trajectory = gradient_descent(starting_point, learning_rate, iterations)
# 设置绘图
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('f(x, y)')
ax.set_title('Gradient Descent Visualization')
# 绘制曲面
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8)
# 初始化动画
line, = ax.plot([], [], [], 'r-')
point, = ax.plot([], [], [], 'ro')
def init():
line.set_data([], [])
line.set_3d_properties([])
point.set_data([], [])
point.set_3d_properties([])
return line, point
# 更新动画
def update(frame):
current_point = trajectory[frame]
line.set_data(trajectory[:frame, 0], trajectory[:frame, 1])
line.set_3d_properties(f(*trajectory[:frame].T))
point.set_data(current_point[0], current_point[1])
point.set_3d_properties(f(*current_point))
return line, point
# 创建动画
ani = FuncAnimation(fig, update, frames=iterations, init_func=init, blit=True)
# 显示动画
plt.show()