2016-11-17 6 views
1

Я оптимизации линейной функции с SciPy,AttributeError: «поплавок» объект не имеет атрибута «Градиент» SciPy питона

def func(weights): 
     var = ['x1', 'x2', 'x3', 'x4'] 
     if weights is None: 
      weights = np.ones(len(var))/len(var) 
     return len(set([var[i] for i in range(len(weights)) if weights[i]>0]))/len(var) 

res = minimize(lambda x: func(x), x0=[0.25,0.25,0.25,0.25],method='SLSQP', 
         jac=ad.gh(lambda x: func(x))[0], bounds=((0.,1.),)*4, 
         options = {'disp':True, 'ftol': 1e-20, 'maxiter': 1000}, 
         constraints= {'type': 'eq', 'fun': lambda x: sum(x) - 1.0}) 

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

Traceback (most recent call last): 
    File "D:/applicatio/Sub Applicatio/main.py", line 338, in <module> 
    constraints= {'type': 'eq', 'fun': lambda x: sum(x) - 1.0}) 
    File "C:\Users\hp\Downloads\WinPython-64bit-3.5.1.2\python-3.5.1.amd64\lib\site-packages\scipy\optimize\_minimize.py", line 455, in minimize 
    constraints, callback=callback, **options) 
    File "C:\Users\hp\Downloads\WinPython-64bit-3.5.1.2\python-3.5.1.amd64\lib\site-packages\scipy\optimize\slsqp.py", line 383, in _minimize_slsqp 
    g = append(fprime(x),0.0) 
    File "C:\Users\hp\Downloads\WinPython-64bit-3.5.1.2\python-3.5.1.amd64\lib\site-packages\scipy\optimize\optimize.py", line 289, in function_wrapper 
    return function(*(wrapper_args + args)) 
    File "C:\Users\hp\Downloads\WinPython-64bit-3.5.1.2\python-3.5.1.amd64\lib\site-packages\ad\__init__.py", line 1090, in grad 
    return numpy.array(ans.gradient(list(xa))) 
AttributeError: 'float' object has no attribute 'gradient' 

Как я могу оптимизировать эту простую линейную функцию? Какие-либо предложения ? Благодарю.

+1

Похоже, вы используете SLSQP; не означает, что * требуется, чтобы вы передавали якобиан в ограничениях? – Prune

+1

Ошибка выглядит так: ваше производное определение 1D, тогда как ваша функция 4D. Какой размер 'ad.gh (lambda x: func (x)) [0]'? – aTben0

+1

Из-за связи 'if',' set' и 'len', вы уверены, что производные существуют в определенном пространстве? – aTben0

ответ

2

Что вы делаете func?

def func(weights): 
    .... 
    return len(set())/len(var) 

Вы получаете set объект, а затем его длина, число слагаемых. Что это значит? Это не линейно; он принимает целые прыжки.

In [318]: x0=[0.25,0.25,0.25,0.25] 
In [319]: def func(weights): 
    ...:   var = ['x1', 'x2', 'x3', 'x4'] 
    ...:   if weights is None: 
    ...:   weights = np.ones(len(var))/len(var) 
    ...:   return len(set([var[i] for i in range(len(weights)) if weights 
    ...: [i]>0]))/len(var) 
    ...:  
In [320]: func(x0) 
Out[320]: 1.0 
In [321]: x0=np.array(x0) 
In [322]: func(x0) 
Out[322]: 1.0 
In [323]: func(x0+.1) 
Out[323]: 1.0 
In [324]: func(x0-.1) 
Out[324]: 1.0 
In [325]: func(x0-1) 
Out[325]: 0.0 

На самом деле все это делает сосчитать, сколько из x0 ценностей >0 и разделить на 4 - так он генерирует 0, +0,25, 0,5, 0,75 или 1.

minimize собирается начинайте с x0, и выясните, как func(x0) изменяется с небольшими изменениями в x0.

И ваш jac, что-то на основе этого func, а, jac=ad.gh(lambda x: func(x))[0]

==============

Я не думаю, что вы должны использовать lambda

`lambda x: func(x)` 

Просто дайте func в качестве аргумента. Он принимает правильное количество аргументов (например, начальный x0).

===================

Запуск кода, но без параметра jac (я не знаю, что ad.gh есть):

In [543]: def func(weights): 
    ...:   var = ['x1', 'x2', 'x3', 'x4'] 
    ...:   if weights is None: 
    ...:   weights = np.ones(len(var))/len(var) 
    ...:   return len(set([var[i] for i in range(len(weights)) if weights 
    ...: [i]>0]))/len(var) 
    ...:  
In [544]: optimize.minimize(lambda x: func(x), x0=[0.25,0.25,0.25,0.25],method=' 
    ...: SLSQP',bounds=((0.,1.),)*4,options = {'disp':True, 'ftol': 1e-20, 'max 
    ...: iter': 1000},constraints= {'type': 'eq', 'fun': lambda x: sum(x) - 1.0 
    ...: }) 
Optimization terminated successfully. (Exit mode 0) 
      Current function value: 1.0 
      Iterations: 1 
      Function evaluations: 6 
      Gradient evaluations: 1 
Out[544]: 
    fun: 1.0 
    jac: array([ 0., 0., 0., 0., 0.]) 
message: 'Optimization terminated successfully.' 
    nfev: 6 
    nit: 1 
    njev: 1 
    status: 0 
success: True 
     x: array([ 0.25, 0.25, 0.25, 0.25]) 

Похоже, что он пытается внести небольшие изменения вокруг x0, и обнаруживает, что нет никаких изменений (небольшие изменения не делают какие-либо элементы равными 0). Иными словами, ваш func уже находится на локальном минимуме, плоской области.

+0

@hpaulij На самом деле вы правы. Я фактически подсчитываю количество значений x0, если> 0. На самом деле я выполняю многоцелевую оптимизацию, и у меня есть еще две задачи, которые работают отлично. Я просто не понимал, как свести к минимуму эту функцию. Я пробовал свой путь без лямбда-функции, но потом он бросает «Объект метода TypeError: 'не является индексируемым» – muazfaiz

+0

Ожидаете ли вы, что решение должно быть 3 0 терминов и 1, максимальное число 0, но суммирование до 1?Вы можете удалить параметр 'jac'? – hpaulj

+0

Он работает без параметра 'jac'. – hpaulj