0

自動微分 ( )quad_functionを使用して、次の特定の関数 ( ) を最適化 (最小化) するのが好きです。Optim.jlautodiff=true

私の目的関数は値を整数に丸めるため、階段状になります。 Real

autodiffこのオプションを使用すると、Real値が2 つの数値( ForwardDiff.Duals) になります。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のように見える方法です: 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整数空間のみを探索するように指示する方法はありますか?

更新: への変換アプローチの問題は、 sInt64がなくなったForwardDiff.Dualため、導関数/勾配を計算できないことだと思います。roundネストされたデュアルも丸め、デュアルを返すより良い関数はどのように見えるでしょうか?

4

2 に答える 2

2

Erwin Kalvelagen が元の質問で私を打ち負かしたので、私はあなたの更新に、より二重の数字中心の回答で返信します。

実際、元の投稿で言及した動作を持つround関数が実装されForwardDiff.Dualています-偏導関数コンポーネントを切り捨てround、実コンポーネントにのみ適用されます。roundの導関数はほぼどこでもゼロであり、ステップが発生する場所 (つまり の間隔) では定義されていないため、これはほぼ正しい定義です0.5

この定義は、導関数が定義されていないポイントで s を伝播するか、エラーを発生させることによって「より正確」にすることができますがNaN、実用的な AD の観点からは、その戦略にはあまり利点がありません。メソッドは不連続のround場合に「サイドを選択」するので、導関数を取得するときに手を振って「サイドを選択」することは理にかなっています。roundの場合、不連続性の両側の導関数がゼロであるため、これは簡単です。

現在定義されているメソッドを上書きすることで、任意の定義を使用できますが、指摘したようにround、中間の部分導関数を ing すると、誤った全体的な導関数が生成される可能性があります。これは本質的に、同じ目的関数をもはや微分していないという事実によるものです。

于 2016-11-25T20:04:37.560 に答える