笔记101:OSQP求解器的底层算法 -- ADMM算法

前言1:这篇博客仅限于介绍拉格朗日乘子法,KKT条件,ALM算法,ADMM算法等最优化方法的使用以及简版代码实现,但不会涉及具体的数学推导;不过在下面我会给出具体数学推导的相关文章和截图,供学有余力的同志参考; 

前言2:从OSQP求解器的官方网站可以得知,OSQP求解器使用的最优化方法即ADMM算法;


a

a

a

a

a

a

1. 拉格朗日乘子法与KKT条件

注:这一章节不从数学推导上,而是从实际数学意义上,直观的讲解拉格朗日乘子法和KKT条件是如何推导得来的;


1.1 无约束的优化问题 -- 梯度下降法

首先从无约束的优化问题讲起,一般就是要使表达式 minf(x) 取到最小值;对于这类问题在高中就学过怎么做,只要对它的每一个变量求导,然后让偏导为零,解方程组就行了;

在极值点处一定满足 \frac{df(x)}{dx}=0 (只是必要条件),然后对它进行求解,再代入验证是否真的是极值点就行了;

但是有很多问题通过直接求导是解不出来的,或者很难解,所以就需要梯度下降法、牛顿法、坐标下降法之类的数值迭代算法;对于这些迭代算法就像下面这张图一样,我们希望找到其中的最小值,一个比较直观的想法是先找一个起点,然后不断向最低点靠近。就先把一个小球放到一个碗里一样;

一开始要找一个起始点,然后确定走的方向和距离,最后还要知道什么时候停止;这三步中最难的是确定走的方向,走的慢点还可以接受,要是方向错了就找不到最小值了;

  • 走的距离可以简单的设为一个比较小的值;
  • 起始点可以随机选一个 (x_0,y_0) ;
  • 关键是方向,可以选择 (x_0,y_0) 处的梯度的反方向,这是函数在这个点下降最快的方向;
  • 最终的停止条件是梯度的大小很接近于 0(在极值点处的梯度大小就是 0);

这种方法依靠梯度确定下降方向的方法叫做梯度下降法;

 对 f(x) 求极小值的流程:

  1. 随机选定起点 x_0
  2. 得到函数在 x_0 的梯度,然后从 x_0 向前走一步( x_0^{new}=x_0^{old}-\alpha \bigtriangledown f(x) )
  3. 重复第2步,直到梯度接近于0(小于一个事先设定的小值),或到达指定的迭代次数上限


1.2 有约束优化问题 -- 拉格朗日乘子法和KKT条件

摘自文章:

  • https://www.cnblogs.com/xinchen1111/p/8804858.html
  • 什么是仿射函数?-CSDN博客
  • https://www.cnblogs.com/fuleying/p/4481334.html

a

a

1.2.1 单个等式约束

我们可能要在满足一定约束条件的情况下最小化目标函数,比如有一个等式约束:

  • minf(x)
  • h(x)=0

如图,其中的圆圈是目标函数 𝑓(𝑥,𝑦) 投影在平面上的等值线,黑线是约束条件 ℎ(𝑥)=0 的函数图像;等值线与函数图像相交的点其实就是所有满足约束的点;

那么极值点只有可能在等值线与函数图像相切的地方取到,因为如果在相交的地方取到,那么沿着 ℎ(𝑥) 的图像往前走或者往后走,一定还有其它的等值线与它相交,也就是 𝑓(𝑥,𝑦) 的值还能变大和变小,所以交点不是极值点,只有相切的时候才有可能是极值点(不可能同时变大和变小,往前后两个方向走只能同时变大/变小,这才是极值点);

在相切的地方 ℎ(𝑥) 的梯度和 𝑓(𝑥,𝑦) 的梯度应该是在同一条直线上的(在切点处两个函数的梯度都与切平面垂直,所以在一条直线上);

所以满足条件的极值点一定满足:∇𝑓(𝑥,𝑦)=𝜆∇ℎ(𝑥,𝑦)  和 ℎ(𝑥,𝑦)=0

那么只要解出这个方程组,就可以得到问题的解析解了;当然也存在解不出来的情况,就需要用罚函数法之类的方法求数值解了;

为了方便和好记,就把原来的优化问题写成 𝑓(𝑥,𝑦)+𝜆ℎ(𝑥,𝑦) 的形式,然后分别对 𝜆,𝑥,𝑦 求偏导,并且令偏导为 0 就行了(对 x,y 的偏导为0可以得到式子 ∇𝑓(𝑥,𝑦)-𝜆∇ℎ(𝑥,𝑦)=0 )( 对 𝜆 的偏导为0可以得到式子 ℎ(𝑥,𝑦)=0 ),和之前得到的方程组是一样的;这种方法叫拉格朗日乘数法;

a

a

1.2.2 多个等式约束

将拉格朗日乘子法扩展到含有多个等式约束的情况:

这里的平面和球面分别代表了两个约束 ℎ1(𝑥) 和 ℎ2(𝑥),那么这个问题的可行域就是它们相交的那个圆;这里蓝色箭头表示平面的梯度,黑色箭头表示球面的梯度,那么相交的圆的梯度就是它们的线性组合,所以在极值点处目标函数的梯度和约束的梯度的线性组合在一条直线上,所以满足:

为了好记,将原来的约束的问题写成 L(x,\lambda )=f(x)+\sum_{i=1}^{n}[\lambda _i\bigtriangledown h_i(x)] 的形式,然后对 𝑥、𝜆 求偏导,让它们为 0;结果像上面一样直接列方程组是一样的,这可以看做是一种简记,或者是对偶问题,这个函数叫做拉格朗日函数;

a

a

1.2.3 同时含有等式约束和不等式约束

如果问题中既有等式约束,又有不等式约束怎么办呢?对于:

当然也同样约定不等式是 ≤,如果是 ≥ 只要取反就行了;

对于这个问题先不看等式约束,对于不等式约束和目标函数的图:

阴影部分就是可行域,也就是说可行域从原来的一条线变成了一块区域;那么能取到极值点的地方可能有两种情况:

  1. 还是在 ℎ(𝑥) 和 等值线相切的地方
  2. 𝑓(𝑥) 的极值点本身就在可行域里面

因为如果不是相切,那么同样的,对任意一个在可行域中的点,如果在它附近往里走或者往外走,𝑓(𝑥) 一般都会变大或者变小,所以绝大部分点都不会是极值点;除非这个点刚好在交界处,且和等值线相切;或者这个点在可行域内部,但是本身就是 f(x)𝑓(𝑥) 的极值点;

 对于第一种情况,不等式约束就变成等式约束了,对 𝑓(𝑥)+𝜆ℎ(𝑥)+𝜇𝑔(𝑥) 用拉格朗日乘子法:

对于第二种情况,不等式约束就相当于没有,对 𝑓(𝑥)+𝜆ℎ(𝑥) 用拉格朗日乘子法:

把两种情况用同一组方程表示出来,对比一下两个问题:

  • 第一种情况中有 𝜇≥0 且 𝑔(𝑥)=0
  • 第二种情况 𝜇=0 且 𝑔(𝑥)≤0

综合两种情况,可以写成 𝜇𝑔(𝑥)=0 且 𝜇≥0 且 𝑔(𝑥)≤0:

这个就是 KKT 条件;它的含义是这个优化问题的极值点一定满足这组方程组(不是极值点也可能会满足,但是不会存在某个极值点不满足的情况);它也是原来的优化问题取得极值的必要条件,解出来了极值点之后还是要代入验证的,但是因为约束比较多,情况比较复杂,KKT 条件并不是对于任何情况都是满足的;

要满足 KKT 条件需要有一些规范性条件(Regularity conditions),就是要求约束条件的质量不能太差,常见的比如:

  1. LCQ:如果 ℎ(𝑥) 和 𝑔(𝑥) 都是形如 𝐴𝑥+𝑏 的仿射函数,那么极值一定满足 KKT 条件;
  2. LICQ:起作用的 𝑔(𝑥) 函数(即 𝑔(𝑥) 相当于等式约束的情况)和 ℎ(𝑥) 函数在极值点处的梯度要线性无关,那么极值一定满足 KKT 条件;
  3. Slater 条件:如果优化问题是个凸优化问题,且至少存在一个点满足 ℎ(𝑥)=0 和 𝑔(𝑥)=0,极值一定满足 KKT 条件,并且满足强对偶性质;

a

a

a

a

a

a

2. ALM 算法

注1:ALM(Augmented Lagrange Multiplier)算法,即增广型拉格朗日乘子法

注2:ALM 算法常用于线性规划问题( f(x) 不能有高阶项/根号项,也不能有两个变量之间的交乘积项);

注3:ALM 算法的推导过程 -- http://faculty.bicmr.pku.edu.cn/~wenzw/optbook/lect/16-lect-alm.pdf


2.1 ALM 算法介绍

只考虑含有等式约束的问题:

minf(x)

Ax-b=0

x\geq 0

a

a

注:含有不等式约束问题的 ALM 算法,见文章 -- http://faculty.bicmr.pku.edu.cn/~wenzw/optbook/lect/16-lect-alm.pdf

构造增广拉格朗日函数:

L(x,\lambda )=f(x)+\lambda (Ax-b)+\frac{\alpha }{2}\left \| Ax-b \right \|_2^2

  • \lambda:拉格朗日乘子(矩阵)
  • \alpha:惩罚项权重(标量)

a

a

注意:增广拉格朗日乘子法就是在拉格朗日乘子法获得的函数后面,加上针对所有等式约束的惩罚项;

a

a

优点:

  • 原拉格朗日函数的收敛性不太好,抖动很大不稳定;
  • 加上了惩罚项可以增加原拉格朗日函数的凸性,使得我们可以通过更简单的方法,如梯度下降法去求解这个函数的最优解;
  • 加强了等式约束的限制作用(针对等式约束增加了惩罚项),使得在迭代的过程中迭代点一直是在约束附近的区域进行梯度下降,不会跑太远,从而加快了求解速度;

ALM 算法的求解过程:梯度下降

  • 先对变量 x 进行梯度下降:x_{k+1}=x_{k}-\eta \bigtriangledown _{x}L
  • 再对拉格朗日乘子 \lambda 进行梯度下降:\lambda _{k+1}=\lambda _{k}+\alpha (Ax_{k+1}-b)
  • 上述两步为一次迭代,不断这样迭代下去,直至收敛或者到达指定迭代次数;

2.2 ALM 算法代码示例

举例:只含等式约束

minf(x)=C^Tx

Ax-b=0

x\geq 0

a

使用 Scipy 中的函数 linprog 求解线性规划问题,将求解得到的结果作为参考答案:

函数 linprog:scipy.optimize.linprog函数参数最全详解_optimize的linprog-CSDN博客

"""
solve the following problem with scipy
min f(x) = -3x[0] - 5x[1]
s.t. x[0] + x[2] = 42x[1] + x[3] = 123x[0] + 2x[1] + x[4] = 18x[0], x[1], x[2], x[3], x[4] >= 0optimal solution:
fun: -36.0
x: [ 2.000e+00  6.000e+00  2.000e+00  0.000e+00  0.000e+00]
"""from scipy.optimize import linprog
import torchc = torch.tensor([-3, -5, 0, 0, 0], dtype=torch.float32)
A = torch.tensor([[1, 0, 1, 0, 0], [0, 2, 0, 1, 0], [3, 2, 0, 0, 1]], dtype=torch.float32)
b = torch.tensor([4, 12, 18], dtype=torch.float32)res = linprog(c, A_eq=A, b_eq=b, bounds=(0, None))
print(res)

a

ALM 算法示例:

"""
solve the following problem with Augmented Lagrange Multiplier method
min f(x) = -3x[0] - 5x[1]
s.t. x[0] + x[2] = 42x[1] + x[3] = 123x[0] + 2x[1] + x[4] = 18x[0], x[1], x[2], x[3], x[4] >= 0问题形式:
min f(x) = c^T x
s.t. Ax = b
x >= 0
"""import torchdef lagrangian_function(x, lambda_):return f(x) + lambda_ @ (A @ x - b) + alpha / 2 * ((A @ x - b)**2).sum()def f(x):return c @ xdef update_x(x, lambda_):""" update x with gradient descent """lagrangian_function(x, lambda_).backward()new_x = x - eta * x.gradx.data = new_x.clamp(min=0)x.grad.zero_()def update_lambda(lambda_):new_lambda = lambda_ + alpha * (A @ x - b)lambda_.data = new_lambdadef pprint(i, x, lambda_):print(f'\n{i+1}th iter, L:{lagrangian_function(x, lambda_):.2f}, f: {f(x):.2f}')print(f'x: {x}')print(f'lambda: {lambda_}')print("constraints violation: ")print(A @ x - b)def solve(x, lambda_):for i in range(500):pprint(i, x, lambda_)       # 更新 xupdate_x(x, lambda_)        # 更新拉格朗日乘子update_lambda(lambda_)      # 打印信息if __name__ == '__main__':eta = 0.03  # 学习率alpha = 1   # 惩罚权重c = torch.tensor([-3, -5, 0, 0, 0], dtype=torch.float32)A = torch.tensor([[1, 0, 1, 0, 0], [0, 2, 0, 1, 0], [3, 2, 0, 0, 1]], dtype=torch.float32)b = torch.tensor([4, 12, 18], dtype=torch.float32)lambda_ = torch.tensor([0, 0, 0], dtype=torch.float32)x = torch.tensor([2, 0, 2, 0, 0], dtype=torch.float32, requires_grad=True)solve(x, lambda_)

a

a

a

a

a

a

3. ADMM 算法

注1:ADMM(Alternating Direction Method of Multipliers)算法,即交替方向乘子法

注2:关于详细的数学推导 -- 一文详解从拉格朗日乘子法、KKT条件、对偶上升法到罚函数与增广Lagrangian乘子法再到ADMM算法(交替方向乘子法)_拉格朗日乘子 二次惩罚系数-CSDN博客


3.1 ADMM 算法介绍

 只考虑含有等式约束的问题:

minf(x,y)

Ax+By-b=0

x,y\geq 0

a

a

和ALM算法的不同点在于:将所有的变量分成几部分(假设为两部分,一部分是向量 x,一部分是向量 y),然后分别进行梯度下降,而不是一次性将所有的变量全部都进行梯度下降;

构造增广拉格朗日函数:

L(x,y,\lambda )=f(x,y)+\lambda (Ax+By-b)+\frac{\alpha }{2}\left \| Ax+By-b \right \|_2^2

  • \lambda:拉格朗日乘子(矩阵)
  • \alpha:惩罚项权重(标量)

ADMM 算法的求解过程:

  • 先对变量 x 进行梯度下降:x_{k+1}=x_{k}-\eta \bigtriangledown _{x}L(x_k,y_k,\lambda _k)
  • 再对变量 y 进行梯度下降:y_{k+1}=y_{k}-\eta \bigtriangledown _{y}L(x_{k+1},y_k,\lambda _k)
  • 再对变量 \lambda 进行梯度下降:\lambda_{k+1}=\lambda_{k}+\alpha (Ax_{k+1}+By_{k+1}-b)
  • 上述三步为一次迭代,不断这样迭代下去,直至收敛或者到达指定迭代次数;

3.2 ADMM 算法代码示例

"""
solve the following problem with Alternating Direction Multiplier Method
min f(x) = -3x[0] - 5x[1]
s.t. x[0] + x[2] = 42x[1] + x[3] = 123x[0] + 2x[1] + x[4] = 18x[0], x[1], x[2], x[3], x[4] >= 0问题形式:
min f(x) = c^T x
s.t. Ax = b
x >= 0
"""import torchdef lagrangian_function(x, lambda_):return f(x) + lambda_ @ (A @ x - b) + alpha / 2 * ((A @ x - b)**2).sum()def f(x):return c @ xdef update_x(x, lambda_):""" update x with gradient descent """for i in range(len(x)):# not the best way to calculate gradient# 这里直接将所有的变量拆成了5份,这并不是最好的求解方式lagrangian_function(x, lambda_).backward()x_i = x[i] - eta * x.grad[i]x.data[i] = max(0, x_i)x.grad.zero_()def update_lambda(lambda_):new_lambda = lambda_ + alpha * (A @ x - b)lambda_.data = new_lambdadef pprint(i, x, lambda_):print(f'\n{i+1}th iter, L:{lagrangian_function(x, lambda_):.2f}, f: {f(x):.2f}')print(f'x: {x}')print(f'lambda: {lambda_}')print("constraints violation: ")print(A @ x - b)def solve(x, lambda_):for i in range(500):pprint(i, x, lambda_)update_x(x, lambda_)update_lambda(lambda_)if __name__ == '__main__':eta = 0.03  # 学习率alpha = 1   # 惩罚权重c = torch.tensor([-3, -5, 0, 0, 0], dtype=torch.float32)A = torch.tensor([[1, 0, 1, 0, 0], [0, 2, 0, 1, 0], [3, 2, 0, 0, 1]], dtype=torch.float32)b = torch.tensor([4, 12, 18], dtype=torch.float32)lambda_ = torch.tensor([0, 0, 0], dtype=torch.float32)x = torch.tensor([2, 0, 2, 0, 0], dtype=torch.float32, requires_grad=True)solve(x, lambda_)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/366435.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pytest+Allure+Yaml+PyMsql+Jenkins+Gitlab接口自动化(四)Jenkins配置

一、背景 Jenkins(本地宿主机搭建) 拉取GitLab(服务器)代码到在Jenkins工作空间本地运行并生成Allure测试报告 二、框架改动点 框架主运行程序需要先注释掉运行代码(可不改,如果运行报allure找不到就直接注释掉) …

CCAA:认证通用基础 10(审核的概念、审核有关的术语、审核的特征、审核原则)

10.审核的概念、审核有关的术语、审核的特征、审核原则 10.1审核的基本概念 第一章 审核基础知识 第一节 概述 1.什么是审核 审核是认证过程中最基本的活动,是审核方案的重要组成部分,其实施效果直接影响到审核方案的意图和审核目标的达成。 在认证…

葡萄串目标检测YoloV8——从Pytorch模型训练到C++部署

文章目录 软硬件准备数据准备数据处理脚本模型训练模型部署数据分享软硬件准备 训练端 PytorchultralyticsNvidia 3080Ti部署端 fastdeployonnxruntime数据准备 用labelimg进行数据标注 数据处理脚本 xml2yolo import os import glob import xml.etree.ElementTree as ETxm…

DSPy:变革式大模型应用开发

大模型相关目录 大模型,包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步,扬帆起航。 大模型应用向开发路径:AI代理工作流大模型应用开发实用开源项目汇总大模…

ADS1220IRVAR 模数转换器(ADC) TI德州仪器 封装 国产替代

ADS1220IRVAR 模数转换器(ADC) TI德州仪器 封装 国产替代

docker 多网卡指定网卡出网

前言 宿主机中有多个网卡 ens160 192.168.4.23/20 内网通信用 ens192 10.31.116.128/24 出公网访问-1 ens193 10.31.116.128/24 出公网访问-2 现在需要不同容器中不同出网访问,举例 容器1 192.168.0.1/20 网段走宿主机 ens160网卡,否则全部走ens192 网…

vue根据文字长短展示跑马灯效果

介绍 为大家介绍一个我编写的vue组件 auto-marquee ,他可以根据要展示文本是否超出展示区域,来判断是否使用跑马灯效果,效果图如下所示 假设要展示区域的宽度为500px,当要展示文本的长度小于500px时,只会展示文本&…

1077 韩信点兵

这是一个中国剩余定理的问题。中国剩余定理是数论中的一个定理,它给出了一组同余方程的解的存在性和唯一性。在这个问题中,我们需要找到一个数,使得它对给定的每个质数取余的结果等于给定的余数。 以下是一个使用C实现的解决方案&#xff1a…

【每日一练】Python遍历循环

1. 情节描述:上公交车(10个座位),并且有座位就可以坐下 要求:输入公交卡当前的余额,只要超过2元,就可以上公交车;如果车上有空座位,才可以上。 seat 10 while seat > 0:money int(input(…

CentOS修复OpenSSH漏洞升级到openssh 9.7 RPM更新包

在做政府和学校单位网站时,经常需要服务器扫描检测,经常被OpenSSH Server远程代码执行漏洞(CVE-2024-6387)安全风险通告,出了报告需要升级OpenSSH。 使用yum update openssh是无法更新到最新的,因为系统里的…

JsonCpp:更简洁的序列化及反序列化

简介 jsoncpp 提供了一组简单易用的 API&#xff0c;使得在 C 程序中处理 JSON 数据变得更加方便和高效。 安装 linux环境下安装jsoncpp sudo apt-get update sudo apt-get install --reinstall libjsoncpp-dev建立软链接确保编译器找到头文件 #include <json/json.h>…

Vue原生写全选反选框

效果 场景&#xff1a;Vue全选框在头部&#xff0c;子框在v-for循环内部。 实现&#xff1a;点击全选框&#xff0c;所有子项选中&#xff0c;再次点击取消&#xff1b;子项全选中&#xff0c;全选框自动勾选&#xff0c;子项并未全选&#xff0c;全选框不勾选&#xff1b;已选…

LVM核心概念

1. LVM简介 LVM是逻辑盘卷管理&#xff08;Logical Volume Manager&#xff09;的简称&#xff0c;它是Linux环境下对磁盘分区进行管理的一种机制&#xff0c;LVM是建立在硬盘和分区之上的一个逻辑层&#xff0c;来提高磁盘分区管理的灵活性。 优点&#xff1a; 可以灵活分配…

大数据学习之Clickhouse

Clickhouse-23.2.1.2537 学习 一、Clickhouse概述 clickhouse 官网网址&#xff1a;https://clickhouse.com/ ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。 OLTP(联机事务处理系统)例如mysql等关系型数据库&#xff0c;在对于存储小数据量的时候&#xff…

Langchain-Chatchat本地部署记录,三分钟学会!

1.前言&#xff1a; 最近AI爆发式的火&#xff0c;忆往昔尤记得16,17那会移动互联网是特别火热的&#xff0c;也造富了一批公司和个人&#xff0c;出来了很多精妙的app应用。现在轮到AI发力了&#xff0c;想想自己也应该参与到这场时代的浪潮之中&#xff0c;所以就找了开源的…

【TB作品】atmega16 计算器,ATMEGA16单片机,Proteus仿真

实验报告&#xff1a;基于ATmega16单片机的简易计算器设计 1. 实验背景 计算器是日常生活和工作中不可或缺的工具&#xff0c;通过按键输入即可实现基本的四则运算。通过本实验&#xff0c;我们将利用ATmega16单片机、矩阵键盘和LCD1602显示屏&#xff0c;设计并实现一个简易…

一招解决 | IP地址访问怎么实现https

没有域名的情况下&#xff0c;使用IP地址实现HTTPS访问是可以的&#xff0c;但相比使用域名会有些许限制&#xff0c;需要通过部署专用于IP地址的SSL/TLS证书来实现。 IP地址实现HTTPS访问的过程与使用域名类似&#xff0c;但有几个关键的区别。以下是使用IP地址实现HTTPS访问…

Win10 电脑屏幕保护怎么设置?学会了你也能轻松设置屏保

在 Windows 10 操作系统中&#xff0c;屏幕保护程序不仅能够为您的电脑增添个性化色彩&#xff0c;还能在长时间不操作电脑时保护屏幕免受烧屏影响。下面是一份详细指南&#xff0c;简鹿办公编辑教您如何通过 Windows 搜索框设置屏幕保护程序&#xff0c;并调整相关参数&#x…

uniapp——上传图片获取到file对象而非临时地址——基础积累

最近在看uniapp的代码&#xff0c;遇到一个需求&#xff0c;就是要实现上传图片的功能 uniapp 官网地址&#xff1a;https://uniapp.dcloud.net.cn/ 上传图片有对应的API&#xff1a; uni.chooseImage方法&#xff1a;https://uniapp.dcloud.net.cn/api/media/image.html#choo…

使用uniapp编写微信小程序

使用uniapp编写微信小程序 文章目录 使用uniapp编写微信小程序前言一、项目搭建1.1 创建项目方式1.1.1 HBuilderX工具创建1.1.2 命令行下载1.1.3 直接Gitee下载 1.2 项目文件解构1.2.1 安装依赖1.2.2 项目启动1.2.3 文件结构释义 1.2 引入uni-ui介绍 二、拓展2.1 uni-app使用uc…