skopt: Как динамически изменять границы при оптимизации?

Я только начал использовать skopt, поэтому перенаправляйте меня к любому базовому руководству, которое я мог пропустить. Во всяком случае, вот оно:

У меня есть проблема оптимизации, когда я вычисляю спектр с двумя пиками с помощью сложной физической модели, а затем извлекаю его лоренцевский профиль (т.е. 6 параметров, по 3 на пик). Затем я настроил функцию стоимости, которая вычисляет квадрат разницы между рассчитанными параметрами и экспериментальным, так что я получаю f(x), которая принимает массив и возвращает скаляр (если я правильно понял, это то, что требует gp_minimize).

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

dim1=Real(name="A1", low=1, high=100)dim2=Real(name="A2", low=1, high=200)

размеры = [dim1, dim2,...], но в моей конкретной системе A2 ограничен 2*A1. Есть ли способ использовать это в ограничениях, подобных показанным выше, чтобы избежать поиска во множестве «нефизических» пространств параметров? В моем конкретном случае оценка модели занимает очень много времени, поэтому было бы очень полезно избежать ненужных вычислений :)

Заранее спасибо за вашу помощь!

Бест, Крис

1 ответ

Решение

На данный момент не представляется возможным указать этот тип зависимости между размерами пространства поиска. Однако вы можете включить ограничение в цель, передаваемую оптимизатору.

В приведенном ниже примере «истинная» (и дорогостоящая) цель оценивается только при соблюдении ограничения. В противном случае немедленно возвращается высокое значение.

На рисунке все слева от пунктирной линии нарушает a2 <= 2*a1. Красный крест - истинный минимум цели f, а черные точки - объективные оценки. Из-за высоких объективных значений слева от строки фокус поиска находится в допустимой части области поиска. Конечно, также могут быть оценки в недопустимом подпространстве (во время первоначальной случайной выборки или при «изучении» вместо «эксплуатации»), но они не будут включать оценку дорогостоящей цели. f.

      import numpy as np
from matplotlib import pyplot as plt

from skopt import gp_minimize
from skopt.space import Real
from skopt.utils import use_named_args

# search space
dimensions = [Real(name='a1', low=1, high=10),
              Real(name='a2', low=1, high=10)]


# expensive target function to minimize
def f(a1, a2):
    x1 = a1 - 4.5
    x2 = a2 - 7
    return 1.5*x1**2 + x2**2 - 0.9*x1*x2


# objective function passed to optimizer incorporates constraint
@use_named_args(dimensions)
def objective(a1, a2):

    # if constraint violated quickly return a high value ...
    if a2 > 2*a1:
        return 1e4

    # ... otherwise expensive target can be evaluated
    else:
        return f(a1, a2)


# run optimization
res = gp_minimize(objective, dimensions, n_calls=50, n_initial_points=20, random_state=92)

# evaluate f on regular grid for plotting
a1_grid = np.linspace(0, 10, 50)
a2_grid = np.linspace(0, 10, 50)
f_grid = np.array([f(i, j) for j in a2_grid for i in a1_grid]).reshape(
    len(a1_grid), len(a2_grid))

# visualize results
fig, ax = plt.subplots()
ax.set_xlabel('a1')
ax.set_ylabel('a2')

# contours of f
ax.contourf(a1_grid, a2_grid, f_grid, 20)

# true minimum
ax.plot(4.5, 7, 'rx')

# constraint
ax.plot([0, 5], [0, 10], 'k--')

# evaluations
for x in res.x_iters:
    ax.plot(x[0], x[1], 'k.')
Другие вопросы по тегам