<- function(x, y, a = 1, b = 100) {
rosenbrock - x)^2 + b * (y - x^2)^2
(a }
12 機械学習
PyTorchは広く使われている機械学習フレームワークです。 Torch for RはRからPyTorchのほとんどの機能が利用できます。
パッケージの名前はtorch
です。 install.packages("torch")
インストールしましょう。
12.1 数値最適化
Torch for Rを解説した Keydana (2023) のFunction minimization with L-BFGSに従って、数値最適化をしてみましょう。
最適化のベンチマーク函数Rosenbrock函数は \[ f(x, y) = (1-x)^2 + 100(y-x^2)^2 \] と書けます。\(x\)の4次函数となっており、歪んだ溝の中に最小値があります。 そのため、最急降下法や共軛勾配法では、多くのステップ数を必要とします。 ニュートン法やガウス・ニュートン法では、少ない回数で最小に到達することが知られています(Enomoto and Nakashita 2024)。
上記テキストでは、右辺第2項の係数が5になっていて、線型探索なしで2回、ありで1回で最適値に至るとしていますが、ここでは標準的な係数100を使います。
ここでは、torch for Rを使って、Rosenbrock函数を最適化します。 最適化手法には、L-BFGS、線型探索には強ウルフ条件を使います。 制御変数をtorchのテンソルとして定義し、初期位置を与えるとともに、 勾配を自動微分で求めるためにrequries_grad=TRUE
を指定します。
library(torch)
<- torch_tensor(c(-1, -1), requires_grad = TRUE)
x
<- optim_lbfgs(x, line_search_fn = "strong_wolfe") optimizer
損失を計算する函数を定義します。勾配を0に初期化して、損失とその勾配を計算します。 最適化の進捗を確認するため、損失を表示しています。 この函数は最適化手法の1ステップoptimizer$step()
に渡します。
<- function() {
calc_loss $zero_grad()
optimizer
<- rosenbrock(x[1], x[2])
value cat("value is:", as.numeric(value), "\n")
$backward()
value
value }
3ステップ数まで進み、損失をxhist
に格納し、write()
でテキストファイルに保存します。 ファイルに格納せずに、直接描画しても構いません。
<- 3
num_iterations <- as.numeric(x)
xhist for (i in 1:num_iterations) {
cat("\n", "iteration:", i, "\n")
$step(calc_loss)
optimizercat("x=", as.numeric(x), "\n")
<- rbind(xhist, as.numeric(x))
xhist }
iteration: 1
value is: 404
value is: 62.32629
value is: 30.0694
value is: 2.630802
value is: 1.178554
value is: 1.15742
value is: 1.132393
value is: 1.00142
value is: 1.091282
value is: 0.6181912
value is: 0.8905501
value is: 0.6098283
value is: 0.5655912
value is: 0.3922533
value is: 0.2774411
value is: 1.417702
value is: 0.2190705
value is: 0.1747326
value is: 0.1380794
value is: 0.08087045
value is: 0.05257415
value is: 0.1490689
value is: 0.0400695
value is: 0.02954894
value is: 0.01238139
x= 0.9039377 0.8114879
iteration: 2
value is: 0.01238139
value is: 0.006821597
value is: 0.002873288
value is: 0.001204705
value is: 0.0006028978
value is: 4.76946e-05
value is: 2.687239e-06
value is: 5.929914e-08
value is: 1.555293e-09
value is: 3.588241e-13
x= 0.9999999 0.9999998
iteration: 3
value is: 3.588241e-13
x= 0.9999999 0.9999998
write(xhist, file = "hist.txt")
2回で最小に至りました。 テキストファイルに保存した最適化の履歴を読み、Rosenbrockの等値線に重ねて描画します。
<- matrix(scan("hist.txt"), ncol = 2)
xhist
<- seq(-1, 2, 0.01)
x.axis <- seq(-1, 2, 0.01)
y.axis <- outer(x.axis, y.axis, rosenbrock)
z
contour(x.axis, y.axis, z, levels=4^(0:10), main="R torch L-BFGS",
asp=1, xlim=c(-1,2))
points(xhist[,1], xhist[,2], pch=16)
lines(xhist[,1], xhist[,2], lwd=3)