(入門というよりは用語の整理)
関数 \(f: D \to \mathbb{R} \ (D\subseteq \mathbb{R}^n)\) が与えられたときに
\(f(x)\)を最小にする\(x\)を求めたい場面は色々ある
以降では非線形連続最適化を扱います
非線形連続最適化に使えるアルゴリズムの例
解きたい問題
Newton法
収束は早いが初期値依存性が強い
最急降下法
初期値依存性が弱いが局所最適解に陥る
焼き鈍し法
多峰性を考慮できるが、計算量が多い
(Desmos力が足りず、デモが不十分…)
微分の計算が不要で収束が早くハイパラの工夫が不要なアルゴリズムが欲しい!
(∵ \(f\)がブラックボックスなら微分が取れない)
3点\((x_1, f(x_1)), (x_2, f(x_2)), (x_3, f(x_3))\)が与えられれば
これらを通る放物線\(\tilde{f}\)が一意に定まる (Lagrange補間)
\begin{align} \scriptsize \tilde{f}(x) = f(x_1)\frac{(x-x_2)(x-x_3)}{(x_1-x_2)(x_1-x_3)} + f(x_2)\frac{(x-x_1)(x-x_3)}{(x_2-x_1)(x_2-x_3)} + f(x_3)\frac{(x-x_1)(x-x_2)}{(x_3-x_1)(x_3-x_2)} \end{align}
この係数を整理して次の探索点が計算できる
この記法を広めたい!!
以下の式で探索を繰り返す! \(\newcommand\iter[2]{\underset{#1}{\underline{#2}}} \newcommand\Pare[1]{\left(#1\right)}\)
\begin{align} \small \iter{n}{x} = \frac{1}{2} \cdot \frac{\iter{n-1}{f(x)}(\iter{n-2}{x^2}-\iter{n-3}{x^2}) + \iter{n-2}{f(x)}(\iter{n-3}{x^2}-\iter{n-1}{x^2}) + \iter{n-3}{f(x)}(\iter{n-1}{x^2}-\iter{n-2}{x^2})}{\iter{n-1}{f(x)}(\iter{n-2}{x}-\iter{n-3}{x}) + \iter{n-2}{f(x)}(\iter{n-3}{x}-\iter{n-1}{x}) + \iter{n-3}{f(x)}(\iter{n-1}{x}-\iter{n-2}{x})} \end{align}
function rec1D(x₁, x₂, x₃)
a₁ = f(x₁)*(x₂-x₃)
a₂ = f(x₂)*(x₃-x₁)
a₃ = f(x₃)*(x₁-x₂)
return (a₁*(x₂+x₃)+a₂*(x₃+x₁)+a₃*(x₁+x₂))/2(a₁+a₂+a₃)
end
f(x) = sin(x) + x^2/10
xs_init = [1.2, 0.1, -2.2]
xs = copy(xs_init)
for _ in 1:100
push!(xs, rec1D(xs[end], xs[end-1], xs[end-2]))
end
using Plots
plot(f; xlims=(-5,5), color=:red3, label="objective")
plot!(xs, f.(xs); color=:blue3, label="iteration")
scatter!(xs_init, f.(xs_init); color=:blue3, label="initial points")
目的関数に対して単調減少に探索できてるか確認
plot(f.(xs); label="objectve")
logスケールで確認
→探索が進むにつれて放物線近似の数値誤差が拡大
plot(f.(xs).-minimum(f.(xs)).+eps(Float64); label="objectve", yscale=:log10)
やり方は同じ
using LinearAlgebra
function rec2D(xs, ys)
zs = f.(xs,ys)
A = hcat([[x^2, x*y, y^2, x, y, 1] for (x,y) in zip(xs, ys)]...)'
a,b,c,d,e,_ = pinv(A)*zs
p,q = -[2a b;b 2c]\[d;e]
return p,q
end
\begin{align} f\left(x,y\right)=x^{2}+\sin\left(x\right)+1.5y^{2}+\sinh\left(y\right)-\frac{xy}{5} \end{align}
using Random
Random.seed!(42)
f(x,y) = x^2 + sin(x) + 1.5y^2 + sinh(y) - x*y/5
xs_init = rand(6)
ys_init = rand(6)
xs = copy(xs_init)
ys = copy(ys_init)
for _ in 1:100
x, y = rec2D(xs[end-5:end], ys[end-5:end])
push!(xs,x)
push!(ys,y)
end
xs_plot = -3:0.1:3
ys_plot = -5:0.1:3
zs_plot = f.(xs_plot', ys_plot)
plot(xs_plot, ys_plot, zs_plot; levels=-40:40, label="objective")
plot!(xs, ys; color=:blue2, label="iteration")
scatter!(xs_init, ys_init, label="initial points")
plot(f.(xs, ys); label="objective")
plot(f.(xs, ys) .- minimum(f.(xs, ys)) .+ eps(Float64); label="objective", yscale=:log10)
見つかった英語文献 (ちゃんと読んでない)