Как включить ограничение на решение функции 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] .

  • диагональная матрица матрицы с numpy и scipy
  • Python: изменение тональности аудиофайла
  • Быстрое взвешенное эвклидовое расстояние между точками в массивах
  • Как узнать собственные векторы, соответствующие конкретному собственному значению матрицы?
  • Эрозия изображения и расширение с помощью Scipy
  • Ошибка репликации случайного леса Python Scikit
  • Эффективный метод расчета плотности нерегулярно разнесенных точек
  • Получение квантилей SciPy для соответствия функции Stata xtile
  • Python - лучший язык программирования в мире.