Оптимизация SciPy для системы с ограниченными возможностями - PullRequest
5 голосов
/ 18 февраля 2012

Мне часто приходится решать нелинейные задачи, в которых количество переменных превышает количество ограничений (или иногда наоборот). Обычно некоторые из ограничений или переменных являются избыточными сложным образом. Есть ли способ решить такие проблемы?

Большинство решающих скептиков, похоже, предполагают, что число ограничений равно числу переменных и что якобиан неособен. leastsq иногда работает, но даже не пытается, когда ограничения меньше числа переменных. Я понимаю, что могу просто запустить fmin на linalg.norm(F), но это гораздо менее эффективно, чем любой метод, использующий якобиан.

Вот пример проблемы, которая демонстрирует то, о чем я говорю. У него, очевидно, есть решение, но leastsq выдает ошибку. Конечно, этот пример легко решить вручную, я просто поместил его здесь, чтобы продемонстрировать проблему.

import numpy as np
import scipy.optimize

mat = np.random.randn(5, 7)

def F(x):
    y = np.dot(mat, x)
    return np.array([ y[0]**2 + y[1]**3 + 12, y[2] + 17 ])

x0 = np.random.randn(7)
scipy.optimize.leastsq(F, x0)

Я получаю сообщение об ошибке:

Traceback (most recent call last):
  File "question.py", line 13, in <module>
    scipy.optimize.leastsq(F, x0)
  File "/home/dstahlke/apps/scipy/lib64/python2.7/site-packages/scipy/optimize/minpack.py", line 278, in leastsq
    raise TypeError('Improper input: N=%s must not exceed M=%s' % (n,m))
TypeError: Improper input: N=7 must not exceed M=2

Я искал сеть для ответа и даже спросил в списке рассылки SciPy, и не получил ответа. На данный момент я взломал источник SciPy, так что решатель newton_krylov использует pinv(), но я не думаю, что это оптимальное решение.

1 Ответ

3 голосов
/ 19 февраля 2012

Как насчет изменения размера возвращаемого массива от F () до количества переменных:

import numpy as np
import scipy.optimize

mat = np.random.randn(5, 7)

def F(x):
    y = np.dot(mat, x)
    return np.resize(np.array([ y[0]**2 + y[1]**3 + 12, y[2] + 17]), 7)

while True:    
    x0 = np.random.randn(7)
    r = scipy.optimize.leastsq(F, x0)
    err = F(r[0])
    norm =  np.dot(err, err)
    if norm < 1e-6:
        break

print err
...