Элемент-мудрый ограничений составляющей.оптимизировать.минимизировать


Я использую метод COBYLA scipy.optimize.minimize, чтобы найти матрицу параметров для категориального распределения. Мне нужно наложить ограничение, что каждый параметр больше нуля, и что сумма строк матрицы параметров является столбцом единиц.

Мне не ясно, как реализовать это в scipy.minimize, потому что ограничения проверяются на неотрицательность, а не на истинность. Минимизация вызывает исключение, если я просто передаю массивы в качестве ограничения.

Есть ли кто-нибудь знаете, как реализовать такого рода ограничения?

2 4

2 ответа:

Первое ограничение x > 0 может быть выражено очень просто:

{'type':'ineq', 'fun': lambda x: x}

Второе ограничение-это ограничение равенства, которое COBYLA изначально не поддерживает. Однако вместо этого вы можете выразить его в виде двух отдельных ограничений неравенства:

{'type':'ineq', 'fun': lambda x: np.sum(x, 0) - 1}  # row sum >= 1
{'type':'ineq', 'fun': lambda x: 1 - np.sum(x, 0)}  # row sum <= 1

В противном случае вы можете попробовать SLSQP, который поддерживает ограничения равенства.

Вам нужны ограничения равенства, которые обеспечивают np.sum(x, 1) == 1 и ограничения неравенства для x >= 0.

Однако метод COBYLA может обрабатывать только ограничения неравенства, как описано в документации minimize (смотрите раздел, который объясняет Аргумент constraints). Вместо этого можно использовать последовательное Программирование наименьших квадратов (SLSQP), которое поддерживает оба типа ограничений. Функция minimize должна автоматически выбрать правильный решатель для вас, основываясь на ограничениях, которые вы указывать.

Необходимые ограничения могут быть реализованы следующим образом:

def ineq_constraint(x):
    """constrain all elements of x to be >= 0"""
    return x

def eq_constraint(x):
    """constrain the sum of all rows to be equal to 1"""
    return np.sum(x, 1) - 1


constraints = [{'type': 'ineq', 'fun': ineq_constraint},
               {'type': 'eq', 'fun': eq_constraint}]

result = minimize(objective_function, x0, constraints=constraints)