FPGA開発日記

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

ゼロから作るDeep Learning ③ のDezeroをRubyで作り直してみる(ステップ37/ステップ38)

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

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

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

ゼロから作るDeep Learning ③のDezero実装、勉強のためRubyでの再実装に挑戦している。今回はステップ37とステップ38。

  • ステップ37:テンソルを扱うための確認。これまでは変数Variableはスカラの値のみを使用していたが、これをテンソルに拡張する。
begin
  x = Variable.new(np.array([[1, 2, 3], [4, 5, 6]]))
  y = sin(x)
  puts (y)
end


begin
  x = Variable.new(np.array([[1, 2, 3], [4, 5, 6]]))
  c = Variable.new(np.array([[10, 20, 30], [40, 50, 60]]))
  y = x + c
  puts (y)
end
variable([[ 0.84147098  0.90929743  0.14112001]
 [-0.7568025  -0.95892427 -0.2794155 ]])
variable([[11 22 33]
 [44 55 66]])

Numpyを使っているので、テンソルの状態でも計算できる。テンソルを使った場合のバックプロパゲーションについては何だか小難しくて理解が及ばないので省略。必要ならばまた戻ってくる。

  • ステップ38:形状変える関数としてreshapetransposeを実装する。
class Reshape < Function
  def initialize(shape)
    @shape = shape
  end

  def forward(x)
    @x_shape = x.shape
    y = x.reshape(@shape)
    return y
  end

  def backward(gy)
    return reshape(gy, @x_shape)
  end
end

def reshape(x, shape)
  if x.shape == shape
    return as_variable(x)
  end
  return Reshape.new(shape).call(x)
end

forward()はあらかじめ指定した形状@shapeに形を変更する。backward()forward()で形状を変更する前の形に戻す。

begin
  x = Variable.new(np.array([[1, 2, 3], [4, 5, 6]]))
  y = reshape(x, [6])
  puts y.to_s
  y.backward()
  puts x.grad.to_s
end


begin
  x = Variable.new(np.random.randn(1, 2, 3))
  puts x.reshape([2, 3])
  puts x.reshape(2, 3)
end
variable([1 2 3 4 5 6])
variable([[1 1 1]
 [1 1 1]])

続いてtranspose()の実装となる。transpose()は行列の形状を逆転させる。

class Transpose < Function
  def forward(x)
    np = Numpy
    y = np.transpose(x)
    return y
  end

  def backward(gy)
    gx = transpose(gy)
    return gx
  end
end

def transpose(x)
  return Transpose.new().call(x)
end
begin
  x = Variable.new(np.array([[1, 2, 3], [4, 5, 6]]))
  y = transpose(x)
  y.backward()
  puts x.grad.to_s
end


begin
  x = Variable.new(np.random.rand(2, 3))
  puts x.transpose()
  puts x.T()
end
variable([[0.02191114 0.20123865]
 [0.14901781 0.9142529 ]
 [0.57729125 0.52181901]])
variable([[0.02191114 0.20123865]
 [0.14901781 0.9142529 ]
 [0.57729125 0.52181901]])

想定通りに動作することが確認できた。