scipy最小化不等式约束函数

时间:2017-02-17 16:35:09

标签: python optimization scipy constraints

我需要限制我的损失,以便预测总是积极的。 所以我有:

x = [1.0,0.64,0.36,0.3,0.2]
y = [1.0,0.5,0.4,-0.1,-0.2]
alpha = 0

def loss(w, x, y, alpha):
    loss = 0.0
    for y_i,x_i in zip(y,x):
        loss += ((y_i - np.dot(w,x_i)) ** 2)
    return loss + alpha * math.sqrt(np.dot(w,w))

res = minimize(loss_new_scipy, 0.0, args=(x, y, alpha))

现在我想添加约束,但我发现x主要在约束之间的约束,而不是np.dot(w,x)>= 0 这样的约束会是什么样的?

编辑: 我想在scipy.optimize.minimize函数中使用constraints参数,所以我认为它应该看起来像这样:

def con(w,x):
    loss = 0.0
    for i_x in x:
         loss += (np.dot(w, i_x))
    return loss


cons = ({'type': 'ineq', 'fun': con})
res = minimize(loss_new_scipy, 0.0, args=(x, y, alpha), constraints=cons)

我也为了简单而删除了第二个约束

EDIT2: 我将我的问题更改为以下内容:约束是w * x必须大于1,并且还将目标更改为所有底片。我也改变了args,所以它现在运行:

x = np.array([1.0,0.64,0.36,0.3,0.2])
y = [-1.0,-0.5,-0.4,-0.1,-0.2]
alpha = 0

def con(w,x,y,alpha):
    print np.array(w*x)
    return np.array((w*x)-1).sum()


cons = ({'type': 'ineq', 'fun': con,'args':(x,y,alpha)})

def loss_new_scipy(w, x, y, alpha):
    loss = 0.0
    for y_i,x_i in zip(y,x):
        loss += ((y_i - np.dot(w,x_i)) ** 2)
    return loss + alpha * math.sqrt(np.dot(w,w))

res = minimize(loss_new_scipy, np.array([1.0]), args=(x, y, alpha),constraints=cons)
print res

但不幸的是,w的结果是2.0,这确实是正的并且看起来像约束有帮助,因为它远远不能使函数适应目标,但是预测w * x并不都高于1.0

EDIT3: 我刚刚意识到我的预测总和 - 1现在等于0,但我希望每个预测都大于1.0 所以w = 2.0,

w*x = [ 2.00000001  1.28000001  0.72        0.6         0.4       ] 

(w*x) - 1 = [ 1.00000001  0.28000001 -0.28       -0.4        -0.6       ]

哪个总和等于0.0,但我希望所有预测w*x都大于1.0,因此w*x中的所有5个值应至少为1.0

1 个答案:

答案 0 :(得分:1)

如果我正确理解您的EDIT2,您尝试将|y - w*x|^2作为真实参数w(其中xy是向量)的函数最小化约束w*x所有组件都大于1。

现在,表达式|y - w*x|^2w中是二次的,因此它具有明确定义的全局最小值(w^2前面的因子为正)。但是,对w*x的组件的约束实际上强制了w的最小允许值(因为x是固定的),在这种情况下是5。由于二次(无约束)函数|y - w*x|^2的全局最小值适用于np.dot(y,x)/np.dot(x,x)=-0.919左右的特定情况,因此w>=5的函数单调递增,因此5的值表示受约束的最低限度......

要使用您的代码获得此答案,必须修复约束。在您的情况下,您将w*x的所有分量相加1.这里可能会发生一个特定组件远大于1的情况,因此它对总和的贡献可能会掩盖其他只是轻微的组件小于1(例如,如果x=[2, 0.25]w=2,则w*x-1=[3,-0.5],因此即使违反约束,总和也是正数)。为了纠正这个问题,我们可以只加总w*x-1的负数,即那些违反约束的成分:

def con(w,x,y,alpha):
    return np.minimum(w*x - 1, 0).sum()