【凸优化】交替方向乘子法的PyTorch实现

【凸优化】交替方向乘子法的PyTorch实现

本实验使用Python作为编程语言,PyTorch作为机器学习库,实现了交替方向乘子法

基本步骤

算法基本步骤

优化目标

本次实验的优化目标如下:
m i n i m i z e f ( x ) = 3 2 x 1 2 + 1 2 x 2 2 − x 1 x 2 − 2 x 1 g ( z ) = 1 2 z 1 2 + 2 z 2 2 + z 1 z 2 + z 1 + z 2 A = ( 1 , 1 )   B = ( 1 , 1 )   C = 1 minimize f(x)=\frac{3}{2} x_1^2+\frac{1}{2} x_2^2-x_1 x_2-2 x_1 \\ g(z)=\frac{1}{2} z_1^2+2 z_2^2+z_1 z_2+z_1+z_2 \\ A=(1,1) \ B=(1,1) \ C=1 minimizef(x)=23x12+21x22x1x22x1g(z)=21z12+2z22+z1z2+z1+z2A=(1,1) B=(1,1) C=1

代码

import torch
import numpy as np
import matplotlib.pyplot as plt
from math import sqrt, log

x = torch.tensor([1., 1.], requires_grad=True).reshape(2, 1)
z = torch.tensor([1., 1.], requires_grad=True).reshape(2, 1)

rho = 2
epsilon = 0.01
u = torch.tensor([0.])
c = 1
A_ = torch.tensor([1., 1.])
B_ = torch.tensor([1., 1.])

A = torch.tensor([[3., -1], [-1, 1]])
b1 = torch.tensor([2., 0])


# 定义初始函数
def f(x, z, u):
    return 1 / 2 * x.t() @ A @ x - b1.t() @ x + 1 / 2 * rho * torch.norm(
        x @ torch.tensor([1., 1.]).reshape(1, 2) + z @ torch.tensor([1., 1.]).reshape(1, 2) - 1 + u)


B = torch.tensor([[1., 4.], [1., 1.]])
b2 = torch.tensor([1., 1.])


def g(x, z, u):
    return 1 / 2 * z.t() @ B @ z + b2.t() @ z + 1 / 2 * rho * torch.norm(
        x @ torch.tensor([1., 1.]).reshape(1, 2) + z @ torch.tensor([1., 1.]).reshape(1, 2) - 1 + u)


def argmin_f(x, z, u):
    def f_grad(x, z, u):  # 计算梯度
        y = f(x, z, u)
        grad = torch.autograd.grad(y, x, retain_graph=True, create_graph=True)[0]
        return grad

    alpha = torch.tensor([0.25])
    beta = torch.tensor([0.5])
    eta = 0.1
    while torch.norm(f_grad(x, z, u)) > eta:
        delta_x = - f_grad(x, z, u)
        t = torch.tensor([1.])
        while f(x + t.mul(delta_x), z, u) > (f(x, z, u) + alpha.mul(t).mul((f_grad(x, z, u).t()) @ delta_x)):
            t = beta.mul(t)
        x = x + t.mul(delta_x)
    return x


def argmin_g(x, z, u):
    def g_grad(x, z, u):  # 计算梯度
        y = g(x, z, u)
        grad = torch.autograd.grad(y, z, retain_graph=True, create_graph=True)[0]
        return grad

    alpha = torch.tensor([0.25])
    beta = torch.tensor([0.5])
    eta = 0.1
    while torch.norm(g_grad(x, z, u)) > eta:
        delta_z = - g_grad(x, z, u)
        t = torch.tensor([1.])
        while g(x, z + t.mul(delta_z), u) > (g(x, z, u) + alpha.mul(t).mul((g_grad(x, z, u).t()) @ delta_z)):
            t = beta.mul(t)
        z = z + t.mul(delta_z)
    return z


def admm(x, z, u):
    while torch.norm(A_@x+B@z-c) > epsilon or torch.norm(rho*A_.t()@B@(z_last-z)) > epsilon:
        x = argmin_f(x, z, u)
        z_last = z
        z = argmin_g(x, z, u)
        u = u + (torch.tensor([1., 1.]).reshape(1, 2)@x - torch.tensor([1., 1.]).reshape(1, 2)@z)
        opt = 1/2*x.t()@A@x - b1.t()@x + 1/2*z.t()@B@z + b2.t()@z_last
        print('Function value is: ' + str(opt.tolist()))
    opt = 1/2*x.t()@A@x - b1.t()@x + 1/2*z.t()@B@z + b2.t()@z
    print('Optimal solution is: ' + str(opt.tolist()))
   
if __name__ == '__main__':
	admm(x, z, u)

运行结果

代码输出
注意:此代码仅为初始的实现版本,所得结果与真实值存在差距,如果你有更好的版本,欢迎提交PR到我的邮箱。

如果我的博客对你有帮助,欢迎点赞收藏
欢迎转载,转载请注明出处

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 交替方向乘子法(Alternating Direction Method of Multipliers,简称ADMM)是一种用于求解带有约束条件的凸优化问题的迭代算法。其基本思想是将带约束条件的优化问题转化为无约束条件的优化问题,然后通过加入拉格朗日乘子项和对偶变量,将原问题分解为两个子问题,分别对原变量和对偶变量进行交替优化,最终可以得到原问题的最优解。以下是使用 PyTorch 实现 ADMM 算法对 IRIS 数据集进行训练和测试的代码: ``` import torch from sklearn.datasets import load_iris # 加载数据集 iris = load_iris() X = torch.tensor(iris.data, dtype=torch.float32) y = torch.tensor(iris.target, dtype=torch.long) # 定义 ADMM 模型 class ADMM(torch.nn.Module): def __init__(self): super(ADMM, self).__init__() self.linear = torch.nn.Linear(4, 3) self.rho = 1.0 self.u = torch.tensor(0.0) def forward(self, x): return self.linear(x) def update_u(self, x, z): self.u += self.rho * (x - z) def prox(self, x): return torch.nn.functional.relu(x - 1) + torch.nn.functional.relu(-x - 1) # 定义损失函数和优化器 model = ADMM() criterion = torch.nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # 训练模型 for epoch in range(100): z = model(X) loss = criterion(z, y) optimizer.zero_grad() loss.backward() optimizer.step() with torch.no_grad(): model.update_u(X, z) model.linear.weight.data = model.prox(model.linear.weight.data + model.u / model.rho) # 测试模型 with torch.no_grad(): z = model(X) _, predicted = torch.max(z, 1) accuracy = (predicted == y).sum().item() / y.size(0) print('Accuracy:', accuracy) ``` 2. 交替迭代二乘法(Alternating Iterative Method,简称AIM)也是一种用于求解带有约束条件的优化问题的迭代算法。其基本思想是将原问题分解为两个子问题,分别对原变量和辅助变量进行交替优化,最终可以得到原问题的最优解。以下是使用 PyTorch 实现 AIM 算法对 IRIS 数据集进行训练和测试的代码: ``` import torch from sklearn.datasets import load_iris # 加载数据集 iris = load_iris() X = torch.tensor(iris.data, dtype=torch.float32) y = torch.tensor(iris.target, dtype=torch.long) # 定义 AIM 模型 class AIM(torch.nn.Module): def __init__(self): super(AIM, self).__init__() self.linear1 = torch.nn.Linear(4, 3) self.linear2 = torch.nn.Linear(4, 3) self.u = torch.tensor(0.0) def forward(self, x): return self.linear1(x) def update_u(self, z): self.u += z - self.linear2.weight.data def prox(self, x): return torch.nn.functional.relu(x - 1) + torch.nn.functional.relu(-x - 1) # 定义损失函数和优化器 model = AIM() criterion = torch.nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # 训练模型 for epoch in range(100): z = model.linear2.weight.data model.update_u(z) for i in range(10): w = model.linear1.weight.data model.linear1.weight.data = model.prox(w + (z - model.linear2.weight.data) / 2) optimizer.zero_grad() z = model(X) loss = criterion(z, y) loss.backward() optimizer.step() # 测试模型 with torch.no_grad(): z = model(X) _, predicted = torch.max(z, 1) accuracy = (predicted == y).sum().item() / y.size(0) print('Accuracy:', accuracy) ``` 3. ADMM 算法适用于带有约束条件的凸优化问题,而 AIM 算法适用于非凸优化问题。具体来说,ADMM 算法通常用于线性规划、凸优化、稀疏编码等问题,而 AIM 算法通常用于非凸优化问题,例如矩阵分解、多任务学习等。在实际应用中,需要根据具体问题的性质和约束条件选择合适的算法。 4. 在矩阵变量的优化问题中,ADMM 和 AIM 算法都有广泛的应用。一般来说,ADMM 算法适用于稀疏矩阵的优化问题,而 AIM 算法适用于低秩矩阵的优化问题。在实际应用中,需要根据具体问题的性质和约束条件选择合适的算法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值