使用 Python 的 SPSA(同时扰动随机近似)算法

pythonserver side programmingprogramming

同时扰动随机优化算法 (SPSA) 通过同时扰动目标函数来找到目标函数的最小值。

使用 SPSA,通过评估随机扰动下的少量函数来估计目标函数梯度。当目标函数有噪声、不可微分或具有许多参数时,它特别有用。

此算法已成功实现了各种应用,例如系统识别、控制和机器学习。

使用 SPSA 算法的优势

SPSA 已应用于工程、金融和机器学习等各个领域。与其他优化算法(例如随机梯度下降和梯度下降)相比,它具有多种优势,

其中一些优势是 

  • 减少计算和内存需求

  • 处理非平滑和噪声函数

  • 不需要导数

  • 它能够处理大型参数空间

该算法可用于通过优化权重和偏差来有效地训练深度神经网络。此外,SPSA 还可用于金融领域,例如优化股票、债券和其他金融工具的投资组合。

算法

步骤 1 - 导入 numpy 库并定义任何函数以应用 SPSA 算法来优化/最小化函数

步骤 2  使用一些初始值初始化输入变量(参数)。

步骤 3  选择迭代次数和步骤大小。

步骤 4  使用函数评估之间的差异,估计目标函数的梯度。

步骤 5  使用估计的梯度更新输入变量以最小化目标函数。

步骤 6  返回最佳参数值和对应的损失值。

第 7 步 −  重复第 3 步至第 5 步,直至收敛。

示例

在下面的代码中,我们使用了 Rosenbrock 函数来解释 SPSA 算法的实现。它是优化算法的常用测试函数。它在 (-1, 1) 处具有全局最小值,并且有一个通向最小值的狭窄谷底。

import numpy as np

def rosenbrock(x):
    """
    The Rosenbrock function.
    """
    return (1 - x[0])**2 + 100 * (x[1] - x[0]**2)**2

def SPSA(loss_function, theta, a, c, num_iterations):
    """
    A method for minimizing a loss function via simultaneous perturbation     stochastic approximation (SPSA).
    
    Parameters:
    loss_function (function): Loss function to be minimized.
    theta (numpy array): The initial values of the parameters.
    a (float): Size of the step when updating parameters.
    c (float): The noise parameter for randomly generating perturbations.
    num_iterations (int): Number of iterations in the algorithm.
    
    Returns:
    tuple: A tuple containing the best parameter values found and the 
    corresponding loss value.
    """
    # 初始化最佳参数值和损失
    best_theta = theta
    best_loss = loss_function(theta)
    
    # 初始化迭代计数器
    i = 0
    
    # 重复,直到收敛或达到最大迭代次数
    while i < num_iterations:

        # 生成一个随机扰动向量,其元素为 +1 或 -1
        delta = np.random.choice([-1, 1], size=len(theta))
        
        # 在正和负扰动下评估目标函数
        loss_plus = loss_function(theta + c * delta)
        loss_minus = loss_function(theta - c * delta)
        
        # 使用扰动计算梯度估计
        gradient = (loss_plus - loss_minus) / (2 * c * delta)
        
        # 更新参数值
        theta = theta - a * gradient
        
        # 如果新参数值导致损失较低,则更新最佳值
        new_loss = loss_function(theta)
        if new_loss < best_loss:
            best_theta = theta
            best_loss = new_loss
        
        # 增加迭代计数器
        i += 1

    # 返回最佳参数值和对应的损失值
    return (best_theta, best_loss)

# 设置初始参数值、步长、噪声参数和迭代次数
theta0 = np.array([-1.5, 1.5])
a = 0.1
c = 0.1
num_iterations = 1000

# 在 Rosenbrock 函数上运行 SPSA 算法
best_theta, best_loss = SPSA(rosenbrock, theta0, a, c, num_iterations)

# 打印结果
print("最佳参数值:", best_theta)
print("对应的损失:", best_loss)

我们导入所有必要的库。在 SPSA 函数中,根据给定的 theta 值初始化初始参数值和损失。迭代计数器设置为 0,主循环继续运行,直到达到最大收敛或最大迭代次数。在主循环内部,生成一个随机扰动向量"delta",其元素为 +1 或 -1。

然后通过从 theta 中减去 (c*delta,其中 c 是噪声参数) 来评估损失函数。使用公式 theta = theta - a*gradient 更新参数值。继续执行该过程,直到分配最佳参数值和损失值,然后显示最终结果。

输出

最佳参数值:[-1.5 1.5]
对应损失:62.5

结论

最终,SPSA 是一种能够优化具有许多参数的复杂函数的优化算法。与其他优化算法相比,SPSA 的一个主要优势是它不需要了解函数的导数或曲率,因此适用于广泛的优化问题。

因此,SPSA 对任何数据科学家或机器学习从业者来说都是一个有价值的工具,它的简单性和有效性使其成为许多优化问题的热门选择。


相关文章