Мне нравится оптимизировать (минимизировать) следующую заданную функцию (quad_function
) с помощью Optim.jl
с автоматической дифференциацией (autodiff=true
).Julia: Оптимизируйте функцию стоимости с помощью `Optim.jl` и` autodiff` для целых чисел
Мои целевые функции раундовReal
значения целыми числами и поэтому являются ступенчатыми.
Как я использую опцию autodiff
, значения Real
получают dual numbers (ForwardDiff.Dual
). Но, к сожалению, нет функции round
, реализованной для типа ForwardDiff.Dual
. Таким образом, я написал функцию roundtoint64
, которая извлекает реальную часть. Такой подход вызывает проблемы при оптимизации.
using Plots
plotlyjs()
function roundtoint64(x)
if typeof(x) <: ForwardDiff.Dual
roundtoint64(x.value)
else
Int64(round(x))
end
end
function quad_function(xs::Vector)
roundtoint64(xs[1])^2 + roundtoint64(xs[2])^2
end
x, y = linspace(-5, 5, 100), linspace(-5, 5, 100)
z = Surface((x,y)->quad_function([x,y]), x, y)
surface(x,y,z, linealpha = 0.3)
Это как мой quad_function
выглядит следующим образом:
Проблема в том, что optimize
функции сходится сразу и не происходит.
using Optim
res = Optim.optimize(
quad_function,
[5.0,5.0],
Newton(),
OptimizationOptions(
autodiff = true,
# show_trace = true
))
результат:
Results of Optimization Algorithm
* Algorithm: Newton's Method
* Starting Point: [5.0,5.0]
* Minimizer: [5.0,5.0]
* Minimum: 5.000000e+01
* Iterations: 0
* Convergence: true
* |x - x'| < 1.0e-32: false
* |f(x) - f(x')|/|f(x)| < 1.0e-32: false
* |g(x)| < 1.0e-08: true
* Reached Maximum Number of Iterations: false
* Objective Function Calls: 1
* Gradient Calls: 1
optimal_values = Optim.minimizer(res) # [5.0, 5.0]
optimum = Optim.minimum(res) # 50.0
Я также попытался инициализировать optimize
функции с вектором целых [5,5]
, чтобы избежать округления вещей, но это вызывает также проблемы с поиском начального размера шага в:
ERROR: InexactError()
in alphainit(::Int64, ::Array{Int64,1}, ::Array{Int64,1}, ::Int64) at /home/sebastian/.julia/v0.5/Optim/src/linesearch/hz_linesearch.jl:63
in optimize(::Optim.TwiceDifferentiableFunction, ::Array{Int64,1}, ::Optim.Newton, ::Optim.OptimizationOptions{Void}) at /home/sebastian/.julia/v0.5/Optim/src/newton.jl:69
in optimize(::Function, ::Array{Int64,1}, ::Optim.Newton, ::Optim.OptimizationOptions{Void}) at /home/sebastian/.julia/v0.5/Optim/src/optimize.jl:169
Вопрос: Есть ли способ рассказать optimize
только e xplore целое пространство?
Обновление: Я считаю, что проблема с конвертерным подходом к Int64
является то, что я больше не имею ForwardDiff.Dual
с и, таким образом, не могу вычислить любые производные/градиентов. Как могла бы выглядеть лучшая функция round
, в которой раунды также вложенные дуэли и дают двойные дуги?
Алгоритм останавливается, потому что градиент равен нулю. Ваша проблема не подходит для решателя, ожидающего плавной функции. Для вашей функции попробуйте что-то вроде решения MIQP (смешанного целочисленного квадратичного программирования). –
Спасибо @ErwinKalvelagen Я проверю это. Но как вы думаете, есть ли вообще способ, чтобы достичь такого сопоставления, которое я пытаюсь сделать, если только решатель не подходит для него? Потому что это не так уж далеко от гладкой функции в моем persperctive ... – swiesend
Это неглазко, и тогда у вас есть все эти области с нулевыми градиентами, где локальный решатель nlp может решить остановиться. Это действительно неправильная технология для по существу дискретной проблемы. –