繁体   English   中英

仅使用 SciPy 解决 Python 中的这个凸优化问题

[英]Solving this convex optimization problem in Python, using only SciPy

背景

我正在尝试解决中的以下凸优化问题,使用(理想情况下) package。 目标是恢复矩阵 . 矩阵 , , , 和整数 , , , 和是已知的和固定的。

在此处输入图像描述

我得到了一些使用CVXR完成此任务的代码:

J_M = eye(M) - 1/M*ones(M);
J_K = eye(K) - 1/K*ones(K);

S_row = [eye(M) zeros(M, K)];
S_col = [zeros(M, K); eye(K)];

cvx_begin sdp quiet
    cvx_precision low
    cvx_solver sedumi

    variable G(N, N) symmetric;
    variable B(M, K);

    DofG = diag(G)*ones(N, 1)' - 2*G + ones(N, 1)*diag(G)';
    LofG = S_row*DofG*S_col;

    G >= 0;
    G*ones(N, 1) == 0;

    L = cell(M, K);
    for m = 1:M
        for k = 1:K
            L{m, k} = [LofG(m, k) B(m, k); B(m, k) 1];
            L{m, k} >= 0;
        end
    end

    B(:) >= 0;

    minimize square_pos(norm(J_M*(B - T)*J_K, 'fro'))
cvx_end

不幸的是,我对复杂优化技术的了解有限(尽管问题本身原则上相当简单),而且我没有经验。 有些翻译很直截了当,而另一些我很难理解。


试图

我编写了一个(诚然非常稀疏的)框架,试图重新创建代码的一些片段。

from scipy.optimize import minimize
import numpy as np

def loss(...):
    # M and K are given by size of T
    J_M = eye(M) - 1/M * ones(M)
    J_K = eye(K) - 1/K * ones(K)

    DofG = diag(G) @ ones(N, 1) - 2 * G + ones(N, 1) @ diag(G)
    LofG = S_row @ DofG @ S_col

    return np.linalg.norm(J_M @ (B - T) @ J_K, 'fro')**2

res = minimize(loss, ...)


少了什么东西

我不确定G(N, N); symmetric G(N, N); symmetricB(M, K)可以,也不能在代码中复制。 我似乎在CVXR文档中找不到简单的解释。

我也不确定如何复制BG上的约束,我不确定如何复制“迭代约束”:

    for m = 1:M
        for k = 1:K
            L{m, k} = [LofG(m, k) B(m, k); B(m, k) 1];
            L{m, k} >= 0;
        end
    end

这个 Matlab 实现如何翻译成 Python/SciPy

使用 cvxpy 直接翻译

import cvxpy as cp
import numpy as np

def solve(T, verbose=True):
    M,K = T.shape
    N = M + K
    J_M = np.eye(M) - np.ones((M,M))/M
    J_K = np.eye(K) - np.ones((K,K))/K
    S_row = np.eye(M, M+K)
    S_col = np.roll(np.eye(M+K,K), M, axis=0)

    G = cp.Variable((N,N), symmetric=True)
    B = cp.Variable((M,K))

    # Here I am assuming that the product of diag(G)*ones(N,1) is broadcasting
    Gd = cp.reshape(cp.diag(G), (N, 1))
    DofG = Gd + Gd.T - 2*G
    # Imposes N = M + K
    LofG = S_row @ DofG @ S_col
    constraints = [G >> 0, cp.sum(G, axis=1) == 0]
    for m in range(M):
        for k in range(K):
            L = cp.bmat([[LofG[m,k], B[m,k]], [B[m,k],1]])
            constraints.append(L >> 0)
    constraints.append(B >= 0)

    obj = cp.norm(J_M @ (B - T) @ J_K, 'fro')
    prob = cp.Problem(cp.Minimize(obj), constraints)
    prob.solve(verbose=verbose)
    return G.value, B.value, obj.value

如果您熟悉 numpy,上面的代码应该很容易理解。 唯一的区别是,我没有使用 numpy 函数,而是使用可以操作变量的相应 cvxpy 函数。 对象存储变量和它们之间的关系,当prob.solve被调用时,它会将问题转换为标准形式并提交给某个求解器。

solve(np.eye(3, 2) + 1)
(array([[ 0.68113622, -0.22048912, -0.10273289, -0.55665717,  0.19874296],
        [-0.22048912,  0.68113622, -0.10273289,  0.19874296, -0.55665717],
        [-0.10273289, -0.10273289,  0.08445099,  0.0605074 ,  0.0605074 ],
        [-0.55665717,  0.19874296,  0.0605074 ,  0.48298721, -0.1855804 ],
        [ 0.19874296, -0.55665717,  0.0605074 , -0.1855804 ,  0.48298721]]),
 array([[ 1.17174172e+00,  1.71742424e-01],
        [ 1.71742424e-01,  1.17174172e+00],
        [ 1.50334549e-15, -1.47036515e-16]]),
 6.988985781497536e-07)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM