2016-12-14 70 views
0

我试图找到一个向量,使乘法矩阵的残差平方和最小。查找使函数最小化的最佳向量

我知道scipy的优化包(它具有最小化函数)。但是,我的代码有一个额外的限制。 w的所有条目的总和(见下面的函数)必须等于1,并且w的任何条目都不能小于0. 是否有一个包为我做了这个?如果不是,我该怎么做?

试图尽量减少宽:

def w_rss(w,x0,x1): 
    predictions = np.dot(x0,w) 
    errors = x1 - predictions 
    rss = np.dot(errors.transpose(),errors).item(0) 

    return rss 

X0 = np.array([[3,4,5,3], 
       [1,2,2,4], 
       [6,5,3,7], 
       [1,0,5,2]]) 

X1 = np.array([[4], 
       [2], 
       [4], 
       [2]]) 

W = np.array([[.0], 
       [.5], 
       [.5], 
       [.0]]) 

print w_rss(W,X0,X1) 

到目前为止,这是在通过w的可能值循环我最好的尝试,但它不能正常工作。

def get_w(x0,x1): 

J = x0.shape[1] 
W0 = np.matrix([[1.0/J]*J]).transpose() 
rss0 = w_rss(W0,x0,x1) 
loop = range(J) 
for i in loop: 
    W1 = W0 
    rss1 = rss0 
    while rss0 == rss1: 
     den = len(loop)-1 
     W1[i][0] += 0.01 
     for j in loop: 
      if i == j: 
       continue 
      W1[j][0] -= 0.01/den 
      if W1[j][0] <= 0: 
       loop.remove(j) 
     rss1 = w_rss(W1,x0,x1) 
     if rss1 < rss0: 
      #print W1 
      W0 = W1 
      rss0 = rss1 
     print '--' 
     print rss0 
     print W0 

return W0,rss0 
+0

你可以使用任何QP(二次规划)求解器。 –

+0

我试过这个在scipy.optimize:cons =({'type':'eq','fun':lambda x:1 - sum(x)}){{NEW LINE}} bnds = tuple((0,1 )对于x中的W){{NEW LINE}}最小化(w_rss,W1,args =(V,X0,X1),method ='SLSQP',bounds = bnds,constraints = cons)。解决方案不正确。 –

+0

这是一个通用的NLP解算器。它应该能够正确设置问题,但我会建议使用真正的QP解算器。 –

回答

2

scipy中的SLSQP代码可以做到这一点。您可以使用scipy.optimize.minimizemethod='SLSQP,也可以直接使用功能fmin_slsqp。在下面,我使用fmin_slsqp

的SciPy的求解器通常通过一一维阵列到目标函数,所以要一致,我会改变WX1为1-d阵列,以及我会写目标函数(现称为w_rss1)期望1-d变元w

使用bounds自变量指定w中的所有元素必须介于0和1之间的条件,并且使用参数f_eqcons指定总和必须为1的条件。约束函数返回np.sum(w) - 1,所以它是0时,元素之和为1

下面的代码:

import numpy as np 
from scipy.optimize import fmin_slsqp 


def w_rss1(w, x0, x1): 
    predictions = np.dot(x0, w) 
    errors = x1 - predictions 
    rss = (errors**2).sum() 
    return rss 


def sum1constraint(w, x0, x1): 
    return np.sum(w) - 1 


X0 = np.array([[3,4,5,3], 
       [1,2,2,4], 
       [6,5,3,7], 
       [1,0,5,2]]) 

X1 = np.array([4, 2, 4, 2]) 

W = np.array([.0, .5, .5, .0]) 

result = fmin_slsqp(w_rss1, W, f_eqcons=sum1constraint, bounds=[(0.0, 1.0)]*len(W), 
        args=(X0, X1), disp=False, full_output=True) 
Wopt, fW, its, imode, smode = result 

if imode != 0: 
    print("Optimization failed: " + smode) 
else: 
    print(Wopt) 

当我运行此,输出是

[ 0.05172414 0.55172414 0.39655172 0.  ]