2015-01-26 4 views
1

Я использую optimize.fmin_l_bfgs_b для оптимизации функции, написанной в Fortran. Код нечто похожее на:Неверная конвергенция с использованием optimize.fmin_l_bfgs_b

def f(m, *args): 
    # Optmization values 
    Opt1 = m[0] 
    Opt2 = m[1] 
    # Rest of arguments: 
    Var1 = args[0] 
    Var2 = args[1] 
    # Fortran Function 
    r1, r2 = FortranFunction(Opt1, Opt2) 
    # Evaluation of the result 
    evaluation = sqrt((r1-Var1)**2 + (r2-Var2)**2) 
    return evaluation 

initial_values = numpy.array([1.09, 0.0025]) 
mybounds = [(1, 1.2), (0, 0.1)] 
m = optimize.fmin_l_bfgs_b(f, x0 = initial_values, args=(x, file_vars), approx_grad = True, bounds = mybounds) 

Fortran функция возвращает 2 значения, которые используются для оценки функции с помощью двух желаемых результатов (var1 и var2). Проблема в том, что алгоритм не оптимизирует первую переменную. Если напечатать его в каждой итерации, это то, что я получаю:

1.09 
1.09 
1.09000001 
1.09 
1.09 
1.09 
1.09000001 
1.09 
1.09 
1.09 
1.09000001 
1.09 
1.09 
1.09 
1.09000001 
... 

Кажется, только оценка функции разности между 1,09 и 1.09000001, который является слишком низким, чтобы получить другое значение в Fortran функции (что может быть причиной того, что он не оптимизирован). Вторая переменная не представляет этой проблемы. Это нормальное поведение? Есть ли возможность сделать алгоритм более высоким шагом?

+0

Что он делает, когда вы вводите разные стартовые значения? – senderle

+0

Точно так же. Функция Fortran не очень чувствительна к таким низким изменениям для первой переменной. – wuampa

+0

Вы посмотрели на приближение градиента оптимизированного решения? – cel

ответ

1

В зависимости от того, что именно делает функция Fortran, существует множество возможных исправлений. Я вижу из вашей сигнатуры вызова, что у вас минималистская оценка градиента численно. Вы можете рассчитать градиент напрямую? Если да, попробуйте написать функцию, которая делает это, передайте ее как fprime и установите approx_grad на номер False. Есть хороший шанс, что правильная функция градиента даст лучшие результаты.

Другой возможностью было бы попробовать разные значения epsilon, которые управляют размером шага для приближения численного градиента. Но мне кажется, что fmin_l_bfgs_b принимает только одно значение с плавающей запятой для epsilon, что означает, что вы не можете использовать разные размеры шагов для разных измерений. Это не проблема. если большой эпсилон дает лучшую оценку градиента для первого измерения и не отменяет оценки для второго измерения, тогда ваша проблема может быть исправлена. Вы также можете попробовать передать массив с величиной epsilon для каждого измерения - это возможно работа. И, наконец, вы могли бы сделать что-то немного неуклюже, как оптимизировать одно измерение, затем настроить epsilon, а затем оптимизировать другое измерение. Я сделаю несколько экспериментов позже, если у меня будет время.

Окончательный подход может заключаться в использовании другой функции минимизации. Вы пробовали, например, fmin_cg? Я обнаружил, что он справляется с большинством проблем, которые я бросаю на него довольно хорошо. Но я никогда не использовал его без функции кодированного градиента раньше. Вы также можете попробовать другие функции на this list - особенно такие, как Powell и Anneal, которые предназначены для работы без использования какой-либо информации о градиенте.

Какой из этих подходов работает, если таковые имеются, будет в значительной степени зависеть от специфики функции, которую вы пытаетесь свести к минимуму. Возможно, вам придется провести какое-то экспериментирование!

+0

Изменение размера шага с помощью значения epsilon устранило проблему с первым измерением. Однако, как было предложено в ваших подробных комментариях, я буду экспериментировать с другими вариантами. Конечно, я попробую с другими функциями минимизации, но также разработаю новую функцию градиента. Не уверен, как это делается сейчас. Большое спасибо за этот полезный ответ. – wuampa

Смежные вопросы