首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >人工智能数学基础(八)—— 最优化理论

人工智能数学基础(八)—— 最优化理论

作者头像
啊阿狸不会拉杆
发布2026-01-21 10:33:29
发布2026-01-21 10:33:29
1600
举报

   最优化理论在人工智能领域占据着举足轻重的地位,无论是训练机器学习模型,还是让机器人规划最优路径,亦或是解决复杂的工程设计问题,都离不开最优化方法的有力支持。今天,我将带大家深入浅出地探索最优化理论的奇妙世界。资源绑定附上完整资源供读者参考学习!

8.1 最优化理论的基础知识

8.1.1 最优化示例

    你有没有想过,怎么让一个函数的输出值尽可能的小(或者尽可能的大)?或者说,在有限的资源下,怎样分配才能让收益最大化?这些都可以归结为最优化问题。比如,企业生产中,要在成本有限的情况下让利润最大化,这就是一个典型的最优化问题。

8.1.2 最优化的基本概念

   最优化问题一般可以描述为:在给定的约束条件下,找到一个变量的值,使得某个目标函数达到最小值(或者最大值)。这里的变量可以是一个数值、一个向量,甚至是一个函数。

8.1.3 求最优化问题的一般步骤

  1. 明确目标函数:也就是你要优化的那个东西,比如成本、利润、误差等。
  2. 确定变量和约束条件:变量是你可以调整的那些因素,约束条件则是变量需要满足的一些限制。
  3. 选择合适的方法求解:根据问题的特点,选择合适的最优化算法,比如梯度下降法、牛顿法等。
  4. 验证结果:检查得到的结果是否满足约束条件,是否真的让目标函数达到了最优。

8.1.4 最优化问题的几何解释

   可以想象一下三维空间中的一个曲面,这个曲面代表了目标函数的值。最优化问题就像是在这个曲面上寻找最低点或者最高点。约束条件则像是在这个空间中围起的一个区域,解必须在这个区域内找到。

8.1.5 最优化问题的基本解法

穷举法

   如果变量的取值范围是有限的,我们可以尝试所有可能的值,然后找到使目标函数最优的那个。但是,这种方法在变量很多或者取值范围很大的时候就不实用了。

解析法

   通过对目标函数求导,找到导数为零的点,这些点可能是极值点。然后进一步判断这些点是否是最优解。但是,很多复杂函数的导数很难求,甚至求不出来。

迭代法

  从一个初始猜测值开始,不断调整变量的值,逐步逼近最优解。梯度下降法和牛顿法都是迭代法。

示例(解析法求解简单最优化问题)
代码语言:javascript
复制
import numpy as np
# 定义目标函数
def f(x):
    return x**2 + 2*x + 1
# 求导函数
def df(x):
    return 2*x + 2
# 解方程 df(x)=0
x_optimal = -2 / 2  # 解为 x = -1
print("最优解为 x =", x_optimal)

8.2 线性规划

8.2.1 线性规划问题及其数学模型

   线性规划问题的目标函数和约束条件都是线性的。一个标准的线性规划问题可以表示为:

minimize(cTx)

subject toA x≤b,x≥0

其中,x 是决策变量,c 是目标函数的系数向量,A 是约束条件的系数矩阵,b 是约束条件的右侧向量。

8.2.2 线性规划问题的几何意义

   在线性规划中,每一个不等式约束条件都定义了一个半空间,而所有约束条件的交集形成了一个凸多面体,称为可行域。目标函数则可以看作是一个超平面,随着目标函数值的变化,这个超平面会平移。最优解一定在这个可行域的顶点上。

8.2.3 单纯形法

   单纯形法是一种求解线性规划问题的经典算法。它的基本思想是:从可行域的一个顶点出发,沿着使目标函数值改进的方向移动到相邻的顶点,直到找到最优解。

示例(用单纯形法求解线性规划问题)
代码语言:javascript
复制
from scipy.optimize import linprog
# 目标函数系数(注意这里是求最小值,所以直接用)
c = [-1, 4]
# 不等式约束条件的系数矩阵和右侧向量
A = [[-3, 1], [1, 2]]
b = [6, 4]
# 变量的下界
x0_bounds = (0, None)
x1_bounds = (0, None)
# 求解线性规划问题
res = linprog(c, A_ub=A, b_ub=b, bounds=[x0_bounds, x1_bounds], method='highs')
print('结果:', res)

8.3 非线性规划

8.3.1 非线性规划的基本概念

   如果目标函数或者约束条件中包含非线性函数,那么这个问题就是一个非线性规划问题。非线性规划问题比线性规划问题要复杂得多,也更难以求解。

8.3.2 无约束条件下的单变量函数最优化方法

对于单变量无约束的最优化问题,常用的方法有:

  • 黄金分割法:通过不断缩小包含极小点的区间来寻找最优解。这种方法不需要计算导数,适用于不可导的函数。
示例(黄金分割法求解单变量无约束最优化问题)
代码语言:javascript
复制
import numpy as np
def golden_section_search(func, a, b, tol=1e-5, max_iter=100):
    """
    使用黄金分割法求解单变量无约束最优化问题
    参数:
    func -- 目标函数
    a, b -- 初始区间端点
    tol -- 容忍误差
    max_iter -- 最大迭代次数
    返回:
    x_opt -- 近似最优解
    """
    gr = (5 ** 0.5 + 1) / 2  # 黄金比例
    for i in range(max_iter):
        c = b - (b - a) / gr
        d = a + (b - a) / gr
        if func(c) < func(d):
            b = d
        else:
            a = c
        if abs(b - a) < tol:
            break
    x_opt = (a + b) / 2
    return x_opt
# 定义目标函数
def f(x):
    return x ** 2 + 2 * x + 1
# 使用黄金分割法求解
x_opt = golden_section_search(f, -5, 5)
print("最优解为 x =", x_opt)

8.3.3 无约束条件下的多变量函数最优化方法

对于多变量无约束的最优化问题,常用的方法有:

  • 梯度下降法:利用目标函数的梯度信息,沿着梯度的反方向更新变量的值,逐步逼近最优解。
示例(梯度下降法求解多变量无约束最优化问题)
代码语言:javascript
复制
import numpy as np
def gradient_descent(func, grad_func, x0, learning_rate=0.1, tol=1e-5, max_iter=1000):
    """
    使用梯度下降法求解多变量无约束最优化问题
    参数:
    func -- 目标函数
    grad_func -- 目标函数的梯度函数
    x0 -- 初始点
    learning_rate -- 学习率
    tol -- 容忍误差
    max_iter -- 最大迭代次数
    返回:
    x_opt -- 近似最优解
    """
    x = x0.copy()
    for i in range(max_iter):
        grad = grad_func(x)
        x_prev = x.copy()
        x = x - learning_rate * grad
        if np.linalg.norm(x - x_prev) < tol:
            break
    return x
# 定义目标函数和梯度函数
def f(x):
    return x[0] ** 2 + x[1] ** 2 + 2 * x[0] + 4 * x[1] + 1
def grad_f(x):
    return np.array([2 * x[0] + 2, 2 * x[1] + 4])
# 使用梯度下降法求解
x0 = np.array([5, 5])
x_opt = gradient_descent(f, grad_f, x0, learning_rate=0.1)
print("最优解为 x =", x_opt)

8.4 实验:用梯度下降法求 Rosenbrock 函数的最小值

8.4.1 实验目的

   掌握梯度下降法的基本原理和实现方法,学会使用梯度下降法求解非线性规划问题。

8.4.2 实验要求

   用梯度下降法求 Rosenbrock 函数的最小值,并绘制迭代过程。

8.4.3 实验原理

   Rosenbrock 函数是一个经典的测试函数,用于验证优化算法的性能。其定义为:

f(x,y)=(a−x)2+b(y−x2)2

   其中,a 和 b 是常数,通常取 a=1,b=100。这个函数的最小值在 (x,y)=(1,1) 处,最小值为 0。Rosenbrock 函数的形状像一个香蕉谷,使得许多优化算法在寻找最小值时容易陷入困境。

梯度下降法是一种迭代的优化算法,它利用目标函数的梯度信息来更新变量的值,逐步逼近最优解。在每次迭代中,变量的更新方向是梯度的反方向,因为梯度的方向是函数值增长最快的方向。

8.4.4 实验步骤

  1. 定义 Rosenbrock 函数及其梯度函数:根据 Rosenbrock 函数的定义,编写相应的 Python 函数,并计算其梯度。
  2. 初始化参数:设置初始点、学习率、最大迭代次数和容忍误差等参数。
  3. 梯度下降迭代:从初始点出发,沿着梯度的反方向更新变量的值,直到满足停止条件。
  4. 记录迭代过程:在每次迭代中,记录变量的值和目标函数值,用于后续分析和绘图。
  5. 绘制迭代过程:将迭代过程中变量的值和目标函数值绘制出来,观察梯度下降法的收敛过程。

8.4.5 实验结果

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def rosenbrock(x):
    """
    Rosenbrock 函数
    参数:
    x -- 输入变量,形状为 (2,) 的 NumPy 数组
    返回:
    函数值
    """
    a = 1
    b = 100
    return (a - x[0]) ** 2 + b * (x[1] - x[0] ** 2) ** 2
def grad_rosenbrock(x):
    """
    Rosenbrock 函数的梯度
    参数:
    x -- 输入变量,形状为 (2,) 的 NumPy 数组
    返回:
    梯度向量
    """
    a = 1
    b = 100
    grad_x0 = 2 * (x[0] - a) + 4 * b * x[0] * (x[0] ** 2 - x[1])
    grad_x1 = 2 * b * (x[1] - x[0] ** 2)
    return np.array([grad_x0, grad_x1])
def gradient_descent(rosenbrock, grad_rosenbrock, x0, learning_rate=0.001, tol=1e-5, max_iter=1000):
    """
    使用梯度下降法求解 Rosenbrock 函数的最小值
    参数:
    rosenbrock -- Rosenbrock 函数
    grad_rosenbrock -- Rosenbrock 函数的梯度函数
    x0 -- 初始点,形状为 (2,) 的 NumPy 数组
    learning_rate -- 学习率,默认为 0.001
    tol -- 容忍误差,默认为 1e-5
    max_iter -- 最大迭代次数,默认为 1000

    返回:
    x_opt -- 近似最优解,形状为 (2,) 的 NumPy 数组
    f_values -- 每次迭代的目标函数值,形状为 (num_iter,) 的 NumPy 数组
    x_values -- 每次迭代的变量值,形状为 (num_iter, 2) 的 NumPy 数组
    """
    x = x0.copy()
    f_values = []
    x_values = []
    for i in range(max_iter):
        # 记录当前函数值和变量值
        f_values.append(rosenbrock(x))
        x_values.append(x.copy())

        # 计算梯度
        grad = grad_rosenbrock(x)

        # 更新变量
        x_prev = x.copy()
        x = x - learning_rate * grad

        # 检查是否收敛
        if np.linalg.norm(x - x_prev) < tol:
            break

    # 将列表转换为 NumPy 数组
    f_values = np.array(f_values)
    x_values = np.array(x_values)

    return x, f_values, x_values


# 初始化参数
x0 = np.array([-2, 2])
learning_rate = 0.001
tol = 1e-5
max_iter = 10000

# 梯度下降
x_opt, f_values, x_values = gradient_descent(rosenbrock, grad_rosenbrock, x0, learning_rate, tol, max_iter)

# 绘制迭代过程
plt.figure(figsize=(12, 5))

# 绘制函数值变化
plt.subplot(1, 2, 1)
plt.plot(f_values,color='r')
plt.xlabel('迭代次数')
plt.ylabel('目标函数值')
plt.title('目标函数值变化')

# 绘制变量值变化
plt.subplot(1, 2, 2)
plt.plot(x_values[:, 0], x_values[:, 1])
plt.xlabel('x')
plt.ylabel('y')
plt.title('变量值变化')

plt.tight_layout()
plt.show()

print("最优解为 x =", x_opt)
print("最小值为 f(x) =", rosenbrock(x_opt))

   上图左图展示了梯度下降法在优化 Rosenbrock 函数过程中的目标函数值变化情况,随着迭代次数的增加,目标函数值逐渐减小并趋于稳定。右图展示了变量值在迭代过程中的变化轨迹,可以看到变量值逐步逼近最优解 (1, 1)。最终,算法成功找到了近似最优解,验证了梯度下降法在求解非线性规划问题中的有效性。

    这一实验不仅加深了我对梯度下降法的理解,也让我对 Rosenbrock 函数的特性有了更直观的认识。通过实践操作,我更加熟练地掌握了如何运用优化算法解决实际问题,为今后在人工智能领域深入探索奠定了坚实基础。资源绑定附上完整资源供读者参考学习!

牛顿法示例:

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 定义目标函数
def f(x):
    x1, x2 = x[0], x[1]
    return x1 ** 2 + x1 * x2 + x2 ** 2 + 3 * x1


# 定义梯度函数(手动计算偏导数)
def gradient(x):
    x1, x2 = x[0], x[1]
    # 对 x1 的偏导数
    df_dx1 = 2 * x1 + x2 + 3
    # 对 x2 的偏导数
    df_dx2 = x1 + 2 * x2
    return np.array([df_dx1, df_dx2])


# 定义Hessian矩阵(手动计算二阶偏导数)
def hessian(x):
    # Hessian矩阵的元素
    d2f_dx1x1 = 2  # 对x1的二阶偏导数
    d2f_dx1x2 = 1  # 对x1和x2的混合偏导数
    d2f_dx2x2 = 2  # 对x2的二阶偏导数
    return np.array([[d2f_dx1x1, d2f_dx1x2], [d2f_dx1x2, d2f_dx2x2]])


# 牛顿法(仅迭代一次)
def newton_method(initial_point):
    x = initial_point.copy()

    # 计算梯度
    grad = gradient(x)

    # 计算Hessian矩阵
    hess = hessian(x)

    # 计算牛顿步长(梯度的负方向乘以Hessian矩阵的逆)
    # 牛顿步长:-H^{-1} * g
    newton_step = -np.linalg.solve(hess, grad)

    # 更新 x
    x_new = x + newton_step

    return x_new


# 参数设置
initial_point = np.array([1.0, 1.0])  # 初始点

# 执行牛顿法(仅迭代一次)
new_point = newton_method(initial_point)


# 绘制收敛轨迹
def plot_convergence_path(initial_point, new_point):
    # 创建网格
    x1 = np.linspace(-5, 5, 100)
    x2 = np.linspace(-5, 5, 100)
    X1, X2 = np.meshgrid(x1, x2)
    Z = X1 ** 2 + X1 * X2 + X2 ** 2 + 3 * X1

    # 绘制等高线图
    plt.figure(figsize=(10, 8))
    plt.contourf(X1, X2, Z, levels=30, alpha=0.5, cmap='viridis')
    plt.colorbar(label='f(x1, x2)')
    plt.contour(X1, X2, Z, levels=30, colors='k', alpha=0.3)

    # 绘制初始点和新点
    plt.scatter(initial_point[0], initial_point[1], color='r', s=100, label='初始点')
    plt.scatter(new_point[0], new_point[1], color='g', s=100, label='新点')

    # 绘制箭头表示移动方向
    plt.arrow(initial_point[0], initial_point[1],
              new_point[0] - initial_point[0], new_point[1] - initial_point[1],
              head_width=0.2, head_length=0.3, fc='b', ec='b', label='牛顿步长')

    plt.xlabel('x1')
    plt.ylabel('x2')
    plt.title('牛顿法收敛路径',font='SimHei',fontsize=20)
    plt.legend()
    plt.grid(True)
    plt.show()


# 绘制收敛轨迹
plot_convergence_path(initial_point, new_point)

# 输出结果
print(f"初始点: x = {initial_point}")
print(f"经过一次牛顿法迭代后的点: x = {new_point}")
print(f"初始点的目标函数值: f(x) = {f(initial_point)}")
print(f"新点的目标函数值: f(x) = {f(new_point)}")

梯度下降法:

代码语言:javascript
复制
import numpy as np
# 可视化迭代过程(可选)
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 定义目标函数
def f(x):
    x1, x2 = x[0], x[1]
    return x1 ** 2 - 2 * x1 * x2 + 4 * x2 ** 2 + x1 - 3 * x2


# 定义梯度函数(手动计算偏导数)
def gradient(x):
    x1, x2 = x[0], x[1]
    # 对 x1 的偏导数
    df_dx1 = 2 * x1 - 2 * x2 + 1
    # 对 x2 的偏导数
    df_dx2 = -2 * x1 + 8 * x2 - 3
    return np.array([df_dx1, df_dx2])


# 梯度下降法
def gradient_descent(initial_point, learning_rate, max_iterations, tolerance=1e-6):
    x = initial_point.copy()
    history = [x.copy()]  # 记录每次迭代的点
    for iteration in range(max_iterations):
        grad = gradient(x)  # 计算梯度
        x_prev = x.copy()
        x = x - learning_rate * grad  # 更新 x
        history.append(x.copy())

        # 检查收敛条件(梯度的模长是否小于容忍度)
        if np.linalg.norm(grad) < tolerance:
            print(f"Converged after {iteration + 1} iterations.")
            break

    return x, history


# 参数设置
initial_point = np.array([1.0, 1.0])  # 初始点
learning_rate = 0.01  # 学习率
max_iterations = 1000  # 最大迭代次数

# 执行梯度下降
optimal_point, history = gradient_descent(initial_point, learning_rate, max_iterations)

# 输出结果
print(f"最优解: x = {optimal_point}")
print(f"函数f(x)最小值: {f(optimal_point)}")

# 绘制函数等高线
x1 = np.linspace(-2, 2, 100)
x2 = np.linspace(-2, 2, 100)
X1, X2 = np.meshgrid(x1, x2)
Z = X1 ** 2 - 2 * X1 * X2 + 4 * X2 ** 2 + X1 - 3 * X2

plt.contourf(X1, X2, Z, levels=30, alpha=0.5)
plt.colorbar(label='f(x1, x2)')

# 绘制迭代路径
history = np.array(history)
plt.plot(history[:, 0], history[:, 1], 'ro-', markersize=5)
plt.scatter(history[0, 0], history[0, 1], color='b', s=100, label='起始点')
plt.scatter(history[-1, 0], history[-1, 1], color='g', s=100, label='最优解')
plt.xlabel('x1')
plt.ylabel('x2')
plt.title('梯度下降路径')
plt.legend()
plt.show()

   以上就是本期关于最优化理论的全部内容啦!如果你在学习过程中有任何疑问或者想法,欢迎在评论区留言,大家一起交流探讨呀!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-05-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 8.1 最优化理论的基础知识
    • 8.1.1 最优化示例
    • 8.1.2 最优化的基本概念
    • 8.1.3 求最优化问题的一般步骤
    • 8.1.4 最优化问题的几何解释
    • 8.1.5 最优化问题的基本解法
      • 示例(解析法求解简单最优化问题)
  • 8.2 线性规划
    • 8.2.1 线性规划问题及其数学模型
    • 8.2.2 线性规划问题的几何意义
    • 8.2.3 单纯形法
      • 示例(用单纯形法求解线性规划问题)
  • 8.3 非线性规划
    • 8.3.1 非线性规划的基本概念
    • 8.3.2 无约束条件下的单变量函数最优化方法
      • 示例(黄金分割法求解单变量无约束最优化问题)
    • 8.3.3 无约束条件下的多变量函数最优化方法
      • 示例(梯度下降法求解多变量无约束最优化问题)
  • 8.4 实验:用梯度下降法求 Rosenbrock 函数的最小值
    • 8.4.1 实验目的
    • 8.4.2 实验要求
    • 8.4.3 实验原理
    • 8.4.4 实验步骤
    • 8.4.5 实验结果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档