2
1

More than 3 years have passed since last update.

敢えてRubyで学ぶ「ゼロから作るDeep Learning」第4章 数値微分/勾配

Last updated at Posted at 2020-02-12

Rubyだとちょっと数値微分に一工夫必要。

Pythonだと

def numerical_diff(f,x):
  h = 1e-4
  return (f(x+h) - f(x-h)) / (2*h)

と引数に関数を渡せてしまうが、Rubyで同じことはできない。
Proc(lambda)オブジェクトを定義し、ブロック化して関数を渡すことで実行可能。

数値微分

numerical_diff.rb
def numerical_diff(f,x)
  h = 1e-4
  return (f.call(x+h) - f.call(x-h)) / (2*h)
end

def function_1(x)
  0.01*x**2 + 0.1*x
end

# 実行
f = lambda {|arg| function_1(arg)}
numerical_diff(f,5) # => 0.1999999999990898
numerical_diff(f,10) # => 0.2999999999986347

勾配

require 'numo/narray'

def numerical_gradient(f, x)
  h = 1e-4
  grad = Numo::DFloat.zeros(x.shape)
  # 各xで偏微分
  x.length.times do |idx|
    tmp_val = x[idx]
    # 要素に差分を入れて、中心差分を取る
    x[idx] = tmp_val + h
    fxh1 = f.call(x)
    x[idx] = tmp_val - h
    fxh2 = f.call(x)
    grad[idx] = (fxh1 - fxh2) / (2*h)
    # 元のxに戻す
    x[idx] = tmp_val
  end

  grad
end

def function_2(x)
  return x[0]**2 + x[1]**2
end

x = Numo::DFloat[3.0, 4.0]
f = lambda{|arg| function_2(arg)}
numerical_gradient(f, x) # =>Numo::DFloat#shape=[2] [6, 8]
x = Numo::DFloat[0.0, 2.0] 
numerical_gradient(f, x) # => Numo::DFloat#shape=[2] [0, 4]
x = Numo::DFloat[3.0, 0.0] 
numerical_gradient(f, x) # => Numo::DFloat#shape=[2] [6, 0]

勾配法

def gradient_descent(f, init_x, lr=0.01, step_num=10)
  x = init_x

  step_num.times do |i|
    grad = numerical_gradient(f, x)
    x -= lr * grad
  end
  return x
end

init_x = Numo::DFloat[-3.0, 4.0]
f = lambda{|arg| function_2(arg)}
# 良い例
gradient_descent(f, init_x, lr=0.1, step_num=100) => Numo::DFloat#shape=[2][-6.11111e-10, 8.14814e-10]
# 悪い例 : 学習率が大きすぎる例
gradient_descent(f, init_x, lr=10, step_num=100) => Numo::DFloat#shape=[2][-2.58984e+13, -1.29525e+12]
# 悪い例 : 学習率が小さすぎる例
gradient_descent(f, init_x, lr=-10, step_num=100) => Numo::DFloat#shape=[2][-2.4204e+12, 3.0874e+12]
2
1
10

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
2
1