一、拉格朗日乘子法
1.1 拉格朗日乘子法定义
假设需要求极值的目标函数 (objective function) 为 f(x,y) ,约束条件为 φ(x,y)=M 设
g(x,y)=M-φ(x,y) ,定义一个新函数F(x,y,λ)=f(x,y)+λg(x,y) ,则用偏导数方法列出方程: ∂F/∂x=0
∂F/∂y=0 ∂F/∂λ=0 求出 x,y,λ 的值,代入即可得到目标函数的极值
1.2 KKT条件定义
对于含有不等式约束的优化问题,如何求取最优值呢?常用的方法是KKT条件,同样地,把所有的不等式约束、等式约束和目标函数全部写为一个式子L(a,b, x)= f(x) + ag(x)+bh(x),KKT条件是说最优值必须满足以下条件:
1.L(a, b, x)对x求导为零;
2.h(x) =;
3.a*g(x) = 0;
求取这三个等式之后就能得到候选最优值。其中第三个式子非常有趣,因为g(x)<=0,如果要满足这个等式,必须a=0或者g(x)=0.
这是SVM的很多重要性质的来源,如支持向量的概念。
1.3 拉格朗日乘子法手工推导例题
二、Python编程
2.1 Python代码
#拉格朗日乘子法python代码
from sympy import *
x1,x2,k = symbols('x1,x2,k')
f = 60-10*x1-4*x2+(x1)**2+(x2)**2-x1*x2
g = x1+x2-8
#构造拉格朗日等式
L=f-k*g
#求导,构造KKT条件
dx1 = diff(L, x1) # 对x1求偏导
#print("dx1=",dx1)
dx2 = diff(L,x2) #对x2求偏导
#print("dx2=",dx2)
dk = diff(L,k) #对k求偏导
#print("dk=",dk)
#dx1= -k + 2*x1 - x2 - 10
#dx2= -k - x1 + 2*x2 - 4
#dk= -x1 - x2 + 8
#求出个变量解
m= solve([dx1,dx2,dk],[x1,x2,k])
#print(m)
#{x1: 5, x2: 3, k: -3}
#给变量重新赋值
x1=m[x1]
x2=m[x2]
k=m[k]
#计算方程的值
f = 60-10*x1-4*x2+(x1)**2+(x2)**2-x1*x2
print("方程的极小值为:",f)
三、Python包编程
```cpp
#导入sympy包,用于求导,方程组求解等等
from sympy import *
#设置变量
x1 = symbols("x1")
x2 = symbols("x2")
alpha = symbols("alpha")
#beta = symbols("beta")
#构造拉格朗日等式
L = 60 - 10*x1 - 4*x2 + x1*x1 + x2*x2 - x1*x2 - alpha * (x1 + x2 - 8)
#求导,构造KKT条件
difyL_x1 = diff(L, x1) #对变量x1求导
difyL_x2 = diff(L, x2) #对变量x2求导
difyL_alpha = diff(L, alpha) #对alpha求导
#求解KKT等式
aa = solve([difyL_x1, difyL_x2, difyL_alpha], [x1, x2, alpha])
print(aa)
x1=aa.get(x1)
x2=aa.get(x2)
alpha=aa.get(alpha)
print("最优解为:",60 - 10*x1 - 4*x2 + x1*x1 + x2*x2 - x1*x2 - alpha * (x1 + x2 - 8))