今回やりたいこと
最適化をJuliaで扱ってみる。
を参照する。
1. 1変数の最適化
# 1変数関数の最適化 function gradient_method_1dim(f,x_init,eta,maxiter) # 最適化過程のパラメータを格納する配列 x_seq = Array{typeof(x_init),1}(undef, maxiter) # p.63 # 勾配 f_prime(x)= ForwardDiff.derivative(f, x) # 初期値の設定 x_seq[1] = x_init # メインの最適化ループ for i in 2:maxiter x_seq[i] = x_seq[i-1] + eta * f_prime(x_seq[i-1]) end x_seq end #################### ### 最適化の実施 ### #################### # 初期値の設定 x_init = -2.5 # 探索の繰り返し数 maxiter = 200 # ステップサイズ eta = 0.05 # 最適化計算を実施 x_seq = gradient_method_1dim(f, x_init, eta, maxiter) f_seq = f.(x_seq) # 最適化過程の可視化 fig, ax = subplots(figsize = (8,3)) ax.plot(f_seq) ax.set_xlabel("iteration"), ax.set_ylabel("f") ax.grid() fig, axes = subplots(1,2,figsize=(8,3)) # 関数のプロット axes[1].plot(xs, f.(xs), label = "function") # 探索の過程 axes[1].plot(x_seq, f.(x_seq), "bx", label = "sequence") # 最適値 axes[1].plot(x_opt, f(x_opt), "rx", label = "optimal") axes[1].set_xlabel("x"), axes[1].set_ylabel("y") axes[1].grid() axes[1].legend() # 探索の過程をステップごとにプロット axes[2].plot(1:maxiter, x_seq, "bx-", label = "sequence") axes[2].hlines(x_opt, 0, maxiter, ls = "--", label = "x_opt") axes[2].set_xlim([0,maxiter]) axes[2].set_xlabel("iteration"), axes[2].set_ylabel("x") axes[2].grid() axes[2].legend() tight_layout()
2. 多変数の最適化
2.1 2変数関数の定義
# 2変数関数を定義 x_opt = [0.50, 0.25] f_2(x) = -sqrt(0.05 + (x[1] - x_opt[1])^2) - (x[2] - x_opt[2])^2 # 関数を等高線図として可視化 L = 500 xs1 = range(-1, 1, length = L) xs2 = range(-1, 1, length = L) fig, ax = subplots() ax.contour(xs1, xs2, [f_2([x1, x2]) for x1 in xs1, x2 in xs2]') ax.plot(x_opt[1], x_opt[2], color = "r", marker = "x", label = "optimal") ax.set_xlabel("x1"), ax.set_ylabel("x2") ax.grid() ax.legend()
2.2 多変数関数の最適化
########################## ### 多変数関数の勾配法 ### ########################## function gradient_method(f, x_init, eta, maxiter) # 最適化過程のパラメータを格納する配列 x_seq = Array{typeof(x_init[1]),2}(undef, length(x_init), maxiter) # 勾配 grad_f(x) = ForwardDiff.gradient(f, x) # 初期値 x_seq[:,1] = x_init # 主要の最適化ループ for i in 2:maxiter x_seq[:, i] = x_seq[:, i-1] + eta * grad_f(x_seq[:,i-1]) end x_seq end # パラメータの設定 x_init = [-0.75, -0.75] maxiter = 500 eta = 0.01 # 最適化の実施 x_seq = gradient_method(f_2, x_init, eta, maxiter) f_seq = [f_2(x_seq[:,i]) for i in 1:maxiter] # 目的関数の値をステップごとにプロットする fig, ax = subplots(figsize = (8,3)) ax.plot(f_seq) ax.set_xlabel("iteration"), ax.set_ylabel("f") ax.grid() fig, axes = subplots(1, 2, figsize = (8,3)) # 等高線図で関数を可視化 axes[1].contour(xs1, xs2, [f_2([x1, x2]) for x1 in xs1, x2 in xs2]') # 最適化の過程 axes[1].plot(x_seq[1,:], x_seq[2,:], ls = "--", marker = "x", label = "sequence") axes[1].plot(x_opt[1], x_opt[2], color = "r", marker = "x", label = "optimal") axes[1].set_xlabel("x1"), axes[1].set_ylabel("x2") axes[1].grid() axes[1].legend() # ステップごとの最適化の過程 axes[2].plot(1:maxiter, x_seq[1,:], color = "b", marker = "o", label = "x[1]") axes[2].plot(1:maxiter, x_seq[2,:], color = "r", marker = "^", label = "x[2]") axes[2].hlines(x_opt[1], 0 , maxiter, color = "b", ls = "--", label = "x_opt[1]") axes[2].hlines(x_opt[2], 0 , maxiter, color = "r", ls = "-.", label = "x_opt[2]") axes[2].set_xlabel("iteration") axes[2].set_ylabel("x1, x2") axes[2].grid() axes[2].legend() tight_layout()