Подтвердить что ты не робот

Как отобразить ход функции scipy.optimize?

Я использую scipy.optimize, чтобы свести к минимуму функцию из 12 аргументов.

Я начал оптимизацию некоторое время назад и все еще жду результатов.

Есть ли способ заставить scipy.optimize отобразить его прогресс (например, сколько уже сделано, какова лучшая лучшая точка)?

4b9b3361

Ответ 1

Как было предложено в mg007, некоторые из подпрограмм scipy.optimize позволяют использовать функцию обратного вызова (к сожалению, lesssq на данный момент не разрешает). Ниже приведен пример, использующий процедуру "fmin_bfgs", где я использую функцию обратного вызова для отображения текущего значения аргументов и значения целевой функции на каждой итерации.

import numpy as np
from scipy.optimize import fmin_bfgs

Nfeval = 1

def rosen(X): #Rosenbrock function
    return (1.0 - X[0])**2 + 100.0 * (X[1] - X[0]**2)**2 + \
           (1.0 - X[1])**2 + 100.0 * (X[2] - X[1]**2)**2

def callbackF(Xi):
    global Nfeval
    print '{0:4d}   {1: 3.6f}   {2: 3.6f}   {3: 3.6f}   {4: 3.6f}'.format(Nfeval, Xi[0], Xi[1], Xi[2], rosen(Xi))
    Nfeval += 1

print  '{0:4s}   {1:9s}   {2:9s}   {3:9s}   {4:9s}'.format('Iter', ' X1', ' X2', ' X3', 'f(X)')   
x0 = np.array([1.1, 1.1, 1.1], dtype=np.double)
[xopt, fopt, gopt, Bopt, func_calls, grad_calls, warnflg] = \
    fmin_bfgs(rosen, 
              x0, 
              callback=callbackF, 
              maxiter=2000, 
              full_output=True, 
              retall=False)

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

Iter    X1          X2          X3         f(X)      
   1    1.031582    1.062553    1.130971    0.005550
   2    1.031100    1.063194    1.130732    0.004973
   3    1.027805    1.055917    1.114717    0.003927
   4    1.020343    1.040319    1.081299    0.002193
   5    1.005098    1.009236    1.016252    0.000739
   6    1.004867    1.009274    1.017836    0.000197
   7    1.001201    1.002372    1.004708    0.000007
   8    1.000124    1.000249    1.000483    0.000000
   9    0.999999    0.999999    0.999998    0.000000
  10    0.999997    0.999995    0.999989    0.000000
  11    0.999997    0.999995    0.999989    0.000000
Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 11
         Function evaluations: 85
         Gradient evaluations: 17

По крайней мере, таким образом вы можете наблюдать, как оптимизатор отслеживает минимальный

Ответ 2

Какую функцию минимизации вы используете точно?

Большинство функций имеют встроенный отчет о ходе выполнения, включая несколько уровней отчетов, показывающих точно нужные вам данные, с использованием флага disp (например, см. scipy.optimize.fmin_l_bfgs_b).

Ответ 3

Следуя примеру @joel, существует аккуратный и эффективный способ сделать аналогичную вещь. В следующем примере показано, как мы можем избавиться от переменных global, call_back и повторной оценки целевой функции несколько раз.

import numpy as np
from scipy.optimize import fmin_bfgs

def rosen(X, info): #Rosenbrock function
    res = (1.0 - X[0])**2 + 100.0 * (X[1] - X[0]**2)**2 + \
           (1.0 - X[1])**2 + 100.0 * (X[2] - X[1]**2)**2


    # display information
    if info['Nfeval']%100 == 0:
        print '{0:4d}   {1: 3.6f}   {2: 3.6f}   {3: 3.6f}   {4: 3.6f}'.format(info['Nfeval'], X[0], X[1], X[2], res)
    info['Nfeval'] += 1
    return res

print  '{0:4s}   {1:9s}   {2:9s}   {3:9s}   {4:9s}'.format('Iter', ' X1', ' X2', ' X3', 'f(X)')   
x0 = np.array([1.1, 1.1, 1.1], dtype=np.double)
[xopt, fopt, gopt, Bopt, func_calls, grad_calls, warnflg] = \
    fmin_bfgs(rosen, 
              x0, 
              args=({'Nfeval':0},), 
              maxiter=1000, 
              full_output=True, 
              retall=False,
              )

Это будет генерировать вывод, например

Iter    X1          X2          X3         f(X)     
   0    1.100000    1.100000    1.100000    2.440000
 100    1.000000    0.999999    0.999998    0.000000
 200    1.000000    0.999999    0.999998    0.000000
 300    1.000000    0.999999    0.999998    0.000000
 400    1.000000    0.999999    0.999998    0.000000
 500    1.000000    0.999999    0.999998    0.000000
Warning: Desired error not necessarily achieved due to precision loss.
         Current function value: 0.000000
         Iterations: 12
         Function evaluations: 502
         Gradient evaluations: 98

Однако без бесплатного запуска здесь я использовал function evaluation times вместо algorithmic iteration times в качестве счетчика. Некоторые алгоритмы могут оценивать целевую функцию несколько раз за одну итерацию.

Ответ 4

Попробуйте использовать:

options={'disp': True} 

чтобы заставить scipy.optimize.minimize печатать промежуточные результаты.