Как включить ограничение на решение функции Scipy NNLS, чтобы оно суммировалось до 1

У меня есть следующий код для решения неотрицательного наименьшего квадрата. Использование scipy.nnls.

import numpy as np from scipy.optimize import nnls A = np.array([[60, 90, 120], [30, 120, 90]]) b = np.array([67.5, 60]) x, rnorm = nnls(A,b) print x #[ 0. 0.17857143 0.42857143] # Now need to have this array sum to 1. 

То, что я хочу сделать, это применить ограничение на решение x так, чтобы оно суммировалось с 1. Как я могу это сделать?

One Solution collect form web for “Как включить ограничение на решение функции Scipy NNLS, чтобы оно суммировалось до 1”

Я не думаю, что вы можете использовать nnls напрямую, поскольку код Fortran, который он вызывает, не позволяет создавать дополнительные ограничения. Однако ограничение, которое уравнение суммирует на единицу, может быть введено как третье уравнение, поэтому ваша примерная система имеет форму,

 60 x1 + 90 x2 + 120 x3 = 67.5 30 x1 + 120 x2 + 90 x3 = 60 x1 + x2 + x3 = 1 

Поскольку это теперь набор линейных уравнений, точное решение можно получить из x=np.dot(np.linalg.inv(A),b) так что x=[0.6875, 0.3750, -0.0625] . Для этого требуется, чтобы x3 был отрицательным. Поэтому нет точного решения, когда x положительно относится к этой задаче.

Для приближенного решения, где x ограничено положительным, это можно получить, используя,

 import numpy as np from scipy.optimize import nnls #Define minimisation function def fn(x, A, b): return np.sum(A*x,1) - b #Define problem A = np.array([[60., 90., 120.], [30., 120., 90.], [1., 1., 1. ]]) b = np.array([67.5, 60., 1.]) x, rnorm = nnls(A,b) print(x,x.sum(),fn(x,A,b)) 

что дает x=[0.60003332, 0.34998889, 0.] с x.sum()=0.95 .

Я думаю, что если вы хотите получить более общее решение, включая ограничения сумм, вам нужно будет использовать минимизацию с явными ограничениями / ограничениями в следующей форме,

 import numpy as np from scipy.optimize import minimize from scipy.optimize import nnls #Define problem A = np.array([[60, 90, 120], [30, 120, 90]]) b = np.array([67.5, 60]) #Use nnls to get initial guess x0, rnorm = nnls(A,b) #Define minimisation function def fn(x, A, b): return np.linalg.norm(A.dot(x) - b) #Define constraints and bounds cons = {'type': 'eq', 'fun': lambda x: np.sum(x)-1} bounds = [[0., None],[0., None],[0., None]] #Call minimisation subject to these values minout = minimize(fn, x0, args=(A, b), method='SLSQP',bounds=bounds,constraints=cons) x = minout.x print(x,x.sum(),fn(x,A,b)) 

который дает x=[0.674999366, 0.325000634, 0.] и x.sum()=1 . Из минимума сумма правильная, но значение x не совсем np.dot(A,x)=[ 69.75001902, 59.25005706] с np.dot(A,x)=[ 69.75001902, 59.25005706] .

  • Определение логнормального распределения с использованием Scipy vs Matlab
  • Должен ли я использовать scipy.pi, numpy.pi или math.pi?
  • fsolve - несоответствие между входом и выходом
  • Заполните пропущенные значения с ближайшим соседом в масках в масках в макете Python?
  • numpy cov (ковариация), что именно он вычисляет?
  • Python MemoryError в Scipy Radial Basis Function (scipy.interpolate.rbf)
  • В чем разница между numpy.linalg.lstsq и scipy.linalg.lstsq?
  • Постройте цветовое колесо (полярное) на основе цветовой карты с использованием Python / Matplotlib
  • Python - лучший язык программирования в мире.