最初,我想使用YALL1 package来使L1最小化,但是它是用matlab编写的。经过一番研究,我在Python中找不到basis pursuit求解器,但是那里有吗?另外,我可以使用哪些现有库来解决此最小化问题?
这是原始问题(BP +):
答案 0 :(得分:2)
我认为您可以使用二次圆锥编程(quick reference)进行基础追踪。
在python中,您可以使用cvxopt to solve quadratic cone programs
编辑:甚至是one of their examples。
答案 1 :(得分:1)
如关于基础追踪 (BP) 的原始论文 Atomic Decomposition by Basis Pursuit 所述,BP 可以等效地重新表述为线性规划 (LP) 问题,并且 LP 开发了非常有效的求解器。
在 this se.math site 中有一个讨论和一个公式,用于给定 BP 问题的 LP 问题的标准形式。回想一下,在 BP 中,您正在寻找形状为 x
的 (x_dim, )
,使得 A@x=y
和 x
对 L1 范数而言是最小的。因此,您只需要一个脚本,它采用形状为 A
的数组 (y_dim, x_dim)
、形状为 y
的 (y_dim, )
并返回标准形式。
这是采用 BP 问题并使用 LP 的标准形式返回最优 x
的函数(我以这种方式编写它以使其适合 that tutorial 中使用的术语)。该脚本使用 scipy.optimize.linprog
作为 LP 的后端。
import numpy as np
from scipy.optimize import linprog
def get_optimal_x_for_bp(A, y):
x_dim, y_dim = A.shape[1], y.shape[0]
eye = np.eye(x_dim)
obj = np.concatenate([np.zeros(x_dim), np.ones(x_dim)])
lhs_ineq = np.concatenate([np.concatenate([eye, -eye], axis=1), np.concatenate([-eye, -eye], axis=1)], axis=0)
rhs_ineq = np.zeros(2 * x_dim)
lhs_eq = np.concatenate([A, np.zeros((y_dim, x_dim))], axis=1)
rhs_eq = y
bnd = [*((None, None) for _ in range(x_dim)), *((0, None) for _ in range(x_dim))]
res = linprog(c=obj, A_ub=lhs_ineq, b_ub=rhs_ineq, A_eq=lhs_eq, b_eq=rhs_eq, bounds=bnd, method="revised simplex")
return res.x[:x_dim]
您可以在示例 2x_1-x_2=2
上检查它是否正常工作:
if __name__ == '__main__':
A = np.array([[2, -1]])
y = np.array([2])
x = get_optimal_x_for_bp(A, y)
print(x)
Output: [1. 0.]
输出表明 x_1=1, x_2=0
是最优的 x
。从下图可以看出这是真的:
您还可以将其应用于一些更复杂的问题:
if __name__ == '__main__':
x_dim, y_dim = 6, 4
A = np.random.rand(y_dim, x_dim)
y = np.random.rand(y_dim)
x = get_optimal_x_for_bp(A, y)
print(x)
Output: [ 0. 1.55953519 0.50597071 0. 0.1724968 -1.86814744]
请记住,正如在关于 BP 的原始论文中所写的那样,系统 A@x=y
应该是过完备的。