FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

ゼロから作るDeep Learning ③ のPython実装をRubyで作り直してみる(ステップ5/ステップ6)

ゼロから作るDeep Learning ❸ ―フレームワーク編

ゼロから作るDeep Learning ❸ ―フレームワーク編

  • 作者:斎藤 康毅
  • 発売日: 2020/04/20
  • メディア: 単行本(ソフトカバー)

ゼロから作るDeep Learning ③を買った。DezeroのPython実装をRubyに移植する形で独自に勉強している。次はステップ5とステップ6。

この章は理論的な部分なので実装は省略。理論の部分は説明をしっかり読むこと。

ステップ5のバックプロパゲーションを実装する。Rubyでの実装に置き換える。まずgradメンバ変数を作ってそこに勾配を確認する。

  • step06.rb
class Variable
  def initialize(data)
    @data = data
    @grad = nil
  end

  attr_accessor :data, :grad
end

SquareExpバックプロパゲーションの機能を実装していく。 y = \text{Square}(x) = x^{2}y = \text{Exp}(x) = e^{x}微分を実装するので、  \dfrac{dy}{dx} = \dfrac{d\text{Square}(x)}{dx} = 2x,  \dfrac{dy}{dx} = \dfrac{d\text{Exp}(x)}{dx} = e^{x} となる。backward()は以下のような実装となった。

class Square < Function
...
  def backward(gy)
    x = @input.data
    gx = x.zip(gy).map{|i0, i1| i0 * i1 * 2.0}
    return gx
  end
class Exp < Function
...
  def backward(gy)
    x = @input.data
    gx = x.zip(gy).map{|i0, i1| Math.exp(i0) * i1}
    return gx
  end

これにより順方向の伝搬を行った後の逆伝搬は以下のようにテストできる。

A = Square.new()
B = Exp.new()
C = Square.new()

x = Variable.new([0.5])
a = A.call(x)
b = B.call(a)
y = C.call(b)

puts(y.data)

y.grad = [1.0]
b.grad = C.backward(y.grad)
a.grad = B.backward(b.grad)
x.grad = A.backward(a.grad)

puts(x.grad)
1.648721270700128
3.297442541400256

ステップ4のnumerical_diff()と同様の結果が得られた。