对上一文章普通线搜索方法对采用armijo算法进行python代码尝试:python代码如下
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
# 设置matplotlib正常显示中文和负号
matplotlib.rcParams['font.sans-serif']=['SimHei'] # 用黑体显示中文
matplotlib.rcParams['axes.unicode_minus']=False # 正常显示负号
def armijo_line_search(f, gradient, x, alpha=0.1, beta=0.5, max_iter=100):
t = alpha
history = [x.copy()] # 用于记录每个迭代步骤的点
for _ in range(max_iter):
if f(x + t * gradient) <= f(x) + beta * t * np.dot(gradient, gradient):
return t, np.array(history)
t *= beta
history.append((x + t * gradient).copy())
return t, np.array(history)
def example_function(x):
return (x[0] - 3)**2 + (x[1] - 2)**2
def example_gradient(x):
return np.array([2 * (x[0] - 3), 2 * (x[1] - 2)])
# 初始点
initial_point = np.array([1, 2])
# Armijo线搜索
step_size, trajectory = armijo_line_search(example_function, example_gradient(initial_point), initial_point)
# 输出结果
print("选择的步长:", step_size)
# 打印更新后的点
updated_point = initial_point - step_size * example_gradient(initial_point)
print("更新后的点:", updated_point)
# 绘制迭代轨迹和目标函数
x1_vals = np.linspace(0, 4, 100)
x2_vals = np.linspace(0, 4, 100)
X1, X2 = np.meshgrid(x1_vals, x2_vals)
Z = (X1 - 3)**2 + (X2 - 2)**2
plt.contour(X1, X2, Z, levels=20, cmap='viridis')
plt.scatter(trajectory[:, 0], trajectory[:, 1], color='red', label='迭代轨迹')
plt.scatter(updated_point[0], updated_point[1], color='blue', marker='x', label='最小值')
plt.title('Armijo线搜索迭代轨迹和目标函数')
plt.xlabel('x1')
plt.ylabel('x2')
plt.legend()
plt.show()
运行结果:选择的步长: 4.4408920985006264e-17
更新后的点: [1. 2.]
我们记录了每个迭代步骤的点,并绘制了迭代轨迹和目标函数的等高线图。最后一个点(蓝色 "x")表示找到的最小值。不难发现,由于Armijo线搜索方法是一个近似的步长选择方法,它通过比较目标函数的实际改进与预期改进的关系来选择步长。虽然该方法能够找到迭代方向上的足够降低目标函数值的步长,但并不保证在每次迭代都能找到全局最小值。在Armijo线搜索中,初始点和参数的选择也可能影响搜索的结果。故有其他优化算法的产生。