基于cvxopt在python中进行半定嵌入

时间:2012-11-23 09:55:02

标签: python optimization machine-learning convex-optimization

我正在尝试在python中基于 cvxopt 包实现半定嵌入算法(参见here)来解决半定规划。我在将半定程序的定义映射到cvxopt的接口时遇到了一些问题(参见this)。

这是我目前的实施:

from numpy import array, eye
from numpy.linalg import norm
from numpy.random import multivariate_normal
from sklearn.neighbors import NearestNeighbors
from cvxopt import matrix, spmatrix, solvers

n = 10 # The number of data points

#### Generate data and determine nearest neighbor structure ####
# Sample data
X = multivariate_normal([0, 0], [[10, -10], [2, -1]] ,n)

# Determine 5-nearest neighbors graph
N = NearestNeighbors(n_neighbors=5).fit(X).kneighbors_graph(X).todense()
N = array(N)

# Generate set of index-pairs, where each pair corresponds to a eighbor pair
neighs = set(zip(*N.nonzero()))
neighs.union(set(zip(*(N.T.dot(N)).nonzero())))

# Plot data points and nearest neighbor graph
#import pylab
#for i, j in neighs:
    #pylab.plot([X[i, 0], X[j, 0]], [X[i, 1], X[j, 1]], 'k')
#pylab.plot(X[:, 0], X[:, 1], 'ro')
#pylab.show()

#### Create kernel using semidefinite programming ####
# We want to maximize the trace, i.e. minimize the negative of the trace
c = matrix(-1 * eye(n).reshape(n**2, 1))

## x must be positive semidefinite
# Note -Gs*x should be the n*n matrix representation of x (which is n**2, 1)
Gs = [spmatrix([-1.0]*n**2, range(n**2), range(n**2), (n**2, n**2))]
hs = [spmatrix([], [], [], (n, n))]  #  Zero matrix

## Equality constraints
# Kernel must be centered, i.e. sum of all kernel elements needs to be 0
A = [[1] * (n**2)]
b = [[0.0]]

# Add one row to A and b for each neighbor distance-preserving constraint
for i, j in neighs:
    if i > j and (j, i) in neighs: 
        continue # skip since this neighbor-relatonship is symmetric
    i = int(i)
    j = int(j)
    # TODO: Use sparse matrix for A_
    #spmatrix([1.0, -2.0, 1.0], [0, 0, 0], [i*(n + 1), i*n + j, j*(n + 1)], 
    #        (1, n**2))
    A_ = [0.0 for k in range(n**2)]
    A_[i*n + i] = +1 # K_ii
    A_[i*n + j] = -2 # K_ij
    A_[j*n + j] = +1 # K_jj
    b_ = [norm(X[i] - X[j])**2] # squared distance between points with index i and j
    A.append(A_)
    b.append(b_)

# Solve positive semidefinite program
A = matrix(array(A, dtype=float))
b = matrix(array(b, dtype=float))

sol = solvers.sdp(c=c, Gs=Gs, hs=hs, A=A, b=b)

执行程序抛出ValueError(Rank(A)< p或Rank([G; A])< n)。有什么提示这里出了什么问题?

2 个答案:

答案 0 :(得分:0)

此错误来自对A提出排名要求的解算器。当A太稀疏时,我对cvxopt的所有解算器都遇到了这个问题。在某些情况下,我通过采用等式约束A*x=y成功获得结果,并在其中附加了相同等式的嘈杂版本Ap*x=y,其中A的零填充低电平噪声。人们可以通过设置

来做到这一点
A1 = matrix([A,Ap])
y1 = matrix([y,y])  

并传递那些用于等式约束。您可能会发现此链接很有用:minimizing nuclear norm with cvxopt

答案 1 :(得分:0)

这是一个旧线程,但这可能会帮助人们在将来寻找MVU的python实现:

https://github.com/buquicchiol/MaximumVarianceUnfolding