前提・実現したいこと
ゼロから作るdeep Learningフレームワーク編という本をみて、PytorchやChainerなどのフレームワークの勉強をしています。
dy/dx=(dy/dy)(dy/db)(db/da)(da/dx)として
逆伝搬でdy/dy(=1)からdy/dxを導き出すところを学んでいるところです。
コードを書くときに毎回dy/dyについての記述
Python
1y.grad = np.array(1.0)
をすると関数を使うユーザーとしては使い勝手が悪いため、backward関数に
Python
1 if self.grad is None: 2 self.grad = np.ones_like(self.data)
と記述すればいいらしいのですが、理由がよくわからないので教えてください。
本には「Variableのdataとgradのデータ型を同じにするためで、例えばdataの型が32ビットの浮動小数点であれば、gradの型も浮動小数点になります」と書いています。型が同じになるのはわかりましたが、
該当のソースコード
import numpy as np class Variable: def __init__(self, data): self.data = data self.grad = None self.creator = None def set_creator(self, func): self.creator = func def backward(self): ''' このコードをこの位置に入れればy.grad = np.array(1.0)を省くことができる。 if self.grad is None: self.grad = np.ones_like(self.data) ''' funcs = [self.creator] while funcs: f = funcs.pop() # 1. Get a function x, y = f.input, f.output # 2. Get the function's input/output x.grad = f.backward(y.grad) # 3. Call the function's backward if x.creator is not None: funcs.append(x.creator) class Function: def __call__(self, input): x = input.data y = self.forward(x) output = Variable(y) output.set_creator(self) self.input = input self.output = output return output def forward(self, x): raise NotImplementedError() def backward(self, gy): raise NotImplementedError() class Square(Function): def forward(self, x): y = x ** 2 return y def backward(self, gy): x = self.input.data gx = 2 * x * gy return gx class Exp(Function): def forward(self, x): y = np.exp(x) return y def backward(self, gy): x = self.input.data gx = np.exp(x) * gy return gx A = Square() B = Exp() C = Square() x = Variable(np.array(0.5)) a = A(x) b = B(a) y = C(b) # backward y.grad = np.array(1.0)#←毎回これを記述する手間を省きたい y.backward() print(x.grad)
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/07 12:19