今回はRで、ある関数を最大化、最小化する値を求めるoptim関数とotimize関数について、その違いや使い方について書いていきます。
optimize関数とoptim関数
この二つは、ある関数の中で値を最大化、最小化するパラメーターを求める時に利用します。簡単な例だと、二次関数を最小化するを求めたり、統計学だと最尤法や最小二乗法に利用されます。 それでは、具体的にやっていきましょう!
optimize関数
optimeze関数は求めたいパラメーターが一つの場合に利用します。今回は、を最小化するを求めてみましょう!
foo <- function(x){(x-3)^2+5}#y = (x-3)^2+5の関数を定義 x <- seq(-1,7,0.1) y <- foo(x) >#グラフ化 plot(x,y,type="o",ylim=c(0,20)) grid(nx = 8 , col = "gray")
グラフにするとこんな感じ!よく見る二次関数のグラフですね。この関数の値を最小にするはもちろん3です。これをoptimize関数を使って求めてみましょう。 optimize関数の引数は(関数, 求めたいの範囲)になります。
> optimise(foo , interval = c(1,6)) $minimum [1] 3 $objective [1] 5
出ました!$minimuは値を最小化するの値、$objectiveはその時の関数の値になります。 最大化したい時は、maximum=TRUEとすると最大化もできます。
optimise(foo , interval = c(1,6),maximum = T) $maximum [1] 5.999922 $objective [1] 13.99953
以上をグラフで視覚化すると...
こんな感じになります。
optimize関数
続いてoptimize関数です。こちらは求めるパラメーターが二つ以上の時に利用します。が最小となる値を求めてみましょう! optim関数には、求めたい値の初期値を適当に与えることに注意しましょう。引数にはoptim(初期値(ベクトルで),関数)となります。
x1 <- x <- seq(-3,3,0.1) x2 <- seq(7,13,0.1) y <- x1^2+(x2-10)^2 #求めたいパラメータはベクトルで与える bar <- function(x){(x[1])^2+(x[2]-10)^2} optim(c(-1,1),bar) $par [1] 0.0004465363 9.9997205855 $value [1] 2.774671e-07 $counts function gradient 89 NA $convergence [1] 0 $message NULL
無事にx1が0、x2が10の時に最小値2.774671e-07(ほほゼロ)になってます!グラフ化するとこんな感じです。(少し見にくいですね^^;)
ちなみにoptimでもパラメータが一つの値を求めることができるみたいです。
> optim(c(1),foo) $par [1] 2.9 $value [1] 5.01 $counts function gradient 14 NA $convergence [1] 0 $message NULL 警告メッセージ: optim(c(1), foo) で: Nelder-Mead 法による一次元最適化は信頼できません: "Brent" 法を用いるか、または optimize() を直接使用してください #警告されるので、警告に従う > optim(c(1),foo,method = "Brent" , lower = 0,upper = 6) $par [1] 3 $value [1] 5 $counts function gradient NA NA $convergence [1] 0 $message NULL >
うまくパラメータ3を求めることができました!
まとめ
最大化、最小化の方法は知っておくと便利なので、ぜひ活用していきましょう!
最後までお読み頂きありがとうございました!
参考
汎用最適化関数 optim | R の optim 関数で準ニュートン法や共役勾配法などによるパラメーター推定
Rの最適化関数optimの目的関数(fr)にpar以外の引数を渡す - Qiita
Rによる最適化、パラメータ推定入門 - yasuhisa's blog
今回のRソースコード
library(rgl)#3Dグラフを描画する #optimize foo <- function(x){(x-3)^2+5} x <- seq(-1,7,0.1) y <- foo(x) optimise(foo , interval = c(1,6))#最小化 optimise(foo , interval = c(1,6),,maximum = T)#最大化 #グラフ化 plot(x,y,type="o",ylim=c(0,20),xlim = c(-1,7),xlab = "",ylab = "") abline(v = 1,col = "red") abline(v = 6,col = "red") points(3,5,col = "red" , cex = 2,pch = 20) text(3,3,"minimum",col = "red") points(6,14,col = "blue" , cex = 2,pch = 20) text(6,12,"maximum",col = "blue") arrows(1,18,6,18) arrows(6,18,1,18) text(3.5,19,"interval") #optim x1 <- x <- seq(-3,3,0.1) x2 <- seq(7,13,0.1) y <- x1^2+(x2-10)^2 bar <- function(x){(x[1])^2+(x[2]-10)^2} optim(c(-1,1),bar) #グラフ化 plot3d(x1,x2,y,size = 5) points3d(0,10,0,col = "red",size = 10) text3d(1,9.5,0,"minimum") #パラメータ一つの場合 optim(c(1),foo,method = "Brent" , lower = 0,upper = 6)