4

我使用scipy.optimize.minimize的COBYLA方法来查找分类分布的参数矩阵。我需要强加每个参数大于零的约束,并且参数矩阵的行总和是一列。scipy.optimize.minimize中的元素限制

我不清楚如何在中实现这一点,因为约束检查的是非否定性而非真实性。如果我只是传递数组作为约束,最小化会引发异常。

有谁知道如何去执行这些约束?

+1

我的实验室的一名成员建议一招,其中的参数,最后一列固定为一个,并且参数被输出的SOFTMAX给出。这消除了我提到的限制的需要。不过,我认为这个问题的答案对其他人有用。 –

回答

5

第一个约束x > 0可以很简单地表示:

{'type':'ineq', 'fun': lambda x: x} 

第二个条件是相等的约束,这COBYLA本身并不支持。但是,你可以将它表示为两个独立的不等式约束改为:

{'type':'ineq', 'fun': lambda x: np.sum(x, 0) - 1} # row sum >= 1 
{'type':'ineq', 'fun': lambda x: 1 - np.sum(x, 0)} # row sum <= 1 

否则,你可以尝试SLSQP代替,这不支持等式约束。

+0

这个作品,谢谢!我有单独的不平等约束,所以我会坚持与COBYLA。我发现上/下限技巧工作得很好。 –

+0

只限制最小的元素而不是所有元素都非常聪明。我必须记住这一点。 – kazemakase

+1

这很聪明,但实际上会导致模型更难解决,因为它引入了不连续性。即一般来说这不是一个好主意。像瘟疫一样避免像min和max这样的函数。 –

6

您需要实施np.sum(x, 1) == 1的平等约束和x >= 0的不等式约束。

但是,COBYLA方法只能处理不等式约束,如文档minimize(参见解释constraints参数的部分)中所述。相反,您可以使用支持这两种约束的Sequential Least SQuares Programming(SLSQP)。根据您指定的约束,minimize函数应该自动为您选择正确的求解器。

您所需要的约束可以这样实现:

def ineq_constraint(x): 
    """constrain all elements of x to be >= 0""" 
    return x 

def eq_constraint(x): 
    """constrain the sum of all rows to be equal to 1""" 
    return np.sum(x, 1) - 1 


constraints = [{'type': 'ineq', 'fun': ineq_constraint}, 
       {'type': 'eq', 'fun': eq_constraint}] 

result = minimize(objective_function, x0, constraints=constraints)