В рамках многостартовой оптимизации я использую дифференциальную эволюцию (DE), выходные данные которой я использую в качестве начальных значений для scipy минимизации с помощью SLSQP (мне нужны ограничения).

Я тестирую, тестирую процедуру на функции Экли. Даже в ситуациях, когда DE возвращает оптимум (нули), разумная минимизация отклоняется от оптимального начального значения и возвращает значение, превышающее оптимальное.

Знаете ли вы, как сделать scipy минимизацию отдачи оптимальной? Я заметил, что это помогает указать допуск для scipy минимизации, но полностью решает проблему. Масштабирование целевой функции ухудшает ситуацию. Проблема отсутствует для решателя COBYLA.

Вот шаги по оптимизации:

# Set up
x0min = -20
x0max = 20
xdim = 4
fun = ackley
bounds = [(x0min,x0max)] * xdim
tol = 1e-12


# Get a DE solution
result = differential_evolution(fun, bounds, 
                                maxiter=10000,
                                tol=tol,
                                workers = 1, 
                                init='latinhypercube')

# Initialize at DE output
x0 = result.x

# Estimate the model
r = minimize(fun, x0, method='SLSQP', tol=1e-18)

Что в моем случае дает

result.fun = -4.440892098500626e-16
r.fun = 1.0008238682246429e-09

result.x = array([0., 0., 0., 0.])
r.x = array([-1.77227927e-10, -1.77062108e-10,  4.33179228e-10, -2.73031830e-12])

Вот реализация функции Экли:

def ackley(x):
    # Computes the value of Ackley benchmark function.
    # ACKLEY accepts a matrix of size (dim,N) and returns a vetor
    # FVALS of size (N,)

    # Parameters
    # ----------
    # x : 1-D array size (dim,) or a 2-D array size (dim,N)
    #     Each row of the matrix represents one dimension. 
    #     Columns have therefore the interpretation of different points at which
    #     the function is evaluated.  N is number of points to be evaluated.
 
    # Returns
    # -------
    # fvals : a scalar if x is a 1-D array or 
    #         a 1-D array size (N,) if x is a 2-D array size (dim,N)
    #         in which each row contains the function value for each column of X.

    n = x.shape[0]
    ninverse = 1 / n
    sum1 = np.sum(x**2, axis=0)
    sum2 = np.sum(np.cos(2 * np.pi * x), axis=0)
    
    fvals = (20 + np.exp(1) - (20 * np.exp(-0.2 * np.sqrt( ninverse * sum1))) 
             - np.exp( ninverse * sum2))
    return fvals
1
user64150 10 Дек 2020 в 14:47

1 ответ

Лучший ответ

Уменьшение «размера шага, используемого для численного приближения якобиана» в параметрах SLSQP решило проблему для меня.

0
user64150 11 Дек 2020 в 08:57