2016-12-14 6 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) 

До сих пор это моя лучшая попытка циклически возможных значений ш, но она не работает должным образом.

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), метод = 'SLSQP', bounds = bnds, constraints = cons). Решение было неверным. –

+0

Это универсальный решатель NLP. Он должен работать с правильно настроенной проблемой, но я бы рекомендовал использовать реальный решатель QP. –

ответ

2

Код SLSQP в scipy может это сделать. Вы можете использовать scipy.optimize.minimize с method='SLSQP, или вы можете использовать функцию fmin_slsqp напрямую. В следующем, я использую fmin_slsqp.

The SciPy решателей, как правило передать одномерный массив к целевой функции, так, чтобы быть последовательным, я изменить W и X1 быть 1-D массивов, и я написать целевую функцию (теперь w_rss1), чтобы ожидать 1-й аргумент w.

Условие, состоящее в том, что все элементы в w должны быть между 0 и 1, задается с использованием аргумента bounds, а условие, что сумма должна быть 1, указывается с использованием аргумента f_eqcons. Функция ограничения возвращает 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.  ]