LoginSignup
0
2

More than 1 year has passed since last update.

pytorchにおける最適化手法の観察

Last updated at Posted at 2022-12-25

はじめに

ディープラーニングによく使われている最適化手法がどのような動作をするのか気になったので、ライトコードさんの記事を参考に試してみました。

環境
WSL
ubuntu 22.04
python3.10.6
jupyter

コード

%matplotlib inline
%matplotlib widget
from torch import optim
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np
import torch

#各データの格納リスト
classes = ['SGD', 'Momentum', 'Adagrad', 'RMSprop', 'Adadelta', 'Adam']
x_list = {}
f_list = {}
optimizers = {}
 
#各種optimizer毎に関数の最適化を行う
for key in classes:
  x_list[key] = np.empty((0, 2))
  f_list[key] = np.empty((0))
  #更新パラメータ(x, y)の初期値
  init = [-3., -2.]
  x = torch.tensor(init, requires_grad=True)
  params = [x]
  
  #学習率
  lr = 1
  #各optimizerの定義
  optimizers['SGD'] = optim.SGD(params, lr=0.001)
  optimizers['Momentum'] = optim.SGD(params, lr=0.001, momentum=0.5)
  optimizers['Adagrad'] = optim.Adagrad(params, lr)
  optimizers['RMSprop'] = optim.RMSprop(params, lr=0.01)
  optimizers['Adadelta'] = optim.Adadelta(params, lr)
  optimizers['Adam'] = optim.Adam(params, lr)

  #関数定義(ビール関数)
  f  = lambda x: (1.5 - x[0] + x[0]*x[1])**2 + (2.25 - x[0] + x[0]*x[1]**2)**2 + (2.625 - x[0] + x[0]*x[1]**3)**2
  
 #関数の出力に対して勾配を求め、optimizerで更新を繰り返す
  for i in range(1000):
    optimizers[key].zero_grad()
    out = f(x)
    out.backward()
    optimizers[key].step()
    x_list[key] = np.vstack([x_list[key],np.array([x.detach().numpy()])])
    f_list[key] = np.append(f_list[key],np.array([out.detach().numpy()]), axis = 0)

#グリッドの計算
xmin, xmax= -5, 5
ymin, ymax= -5, 5
xstep = (xmax - xmin)/50
ystep = (ymax - ymin)/50
x_grid, y_grid = np.meshgrid(np.arange(xmin, xmax + xstep, xstep), np.arange(ymin, ymax + ystep, ystep))
z = f([x_grid,y_grid])

#グラフの出力
fig = plt.figure(figsize=(10, 7))
i = 1
for key in classes:
  ax = fig.add_subplot(2, int(len(classes)/2), i, projection='3d')
  ax.set_title(key, fontsize=8)
  ax.set_xlabel('x', fontsize=8)
  ax.set_ylabel('y', fontsize=8)
  ax.set_xlim(xmin, xmax)
  ax.set_ylim(ymin, ymax)
  ax.view_init(elev=50, azim=-10)

  ax.plot(init[0], init[1], 'x') #初期位置
  ax.plot(3, 0.5, '+') #ゴール(ビール関数)
)
  ax.plot(x_list[key][:,0],x_list[key][:,1],f_list[key][:],"ro-", ms=1)
  ax.plot_surface(x_grid, y_grid, z, cmap='jet',norm=LogNorm(), alpha = 0.5)

  i += 1

結果

Figure 5.png

検証に最適化のテスト関数であるBeale関数を使用しました。
xマークが初期値、
+マークがゴールになります。
関数のハイパーパラメータによって結果は変わるので、
各手法にどんな傾向があるのか観察することができました。

ほかにも様々な最適化手法があるので、試してみるのも面白いです。

参考文献

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2