728x90
반응형
확인1 : Variable 인스턴스 변수
class Variable:
__array_priority__ = 200
def __init__(self, data, name=None):
if data is not None:
if not isinstance(data, np.ndarray):
raise TypeError('{} is not supported'.format(type(data)))
self.data = data
self.name = name
self.grad = None
self.creator = None
self.generation = 0
- data와 grad는 각각 순전파, 역전파 계산 시 사용
- data와 grad 모두 ndarray 인스턴스를 저장한다.
확인2 : Function 클래스
class Function:
def __call__(self, *inputs):
inputs = [as_variable(x) for x in inputs]
# 순전파 계산(메인 처리)
xs = [x.data for x in inputs]
ys = self.forward(*xs)
if not isinstance(ys, tuple):
ys = (ys,)
outputs = [Variable(as_array(y)) for y in ys]
if Config.enable_backprop:
self.generation = max([x.generation for x in inputs])
# '연결'을 만듦
for output in outputs:
output.set_creator(self)
self.inputs = inputs
self.outputs = [weakref.ref(output) for output in outputs]
return outputs if len(outputs) > 1 else outputs[0]
- Dezero 함수는 모두 Function 클래스를 상속한다.
- 구체적인 계산은 상속된 클래스에서 forward 메서드에 구현한다.
확인3 : Variable 클래스의 역전파
class Variable:
def backward(self, retain_grad=False):
if self.grad is None:
self.grad = np.ones_like(self.data)
funcs = []
seen_set = set()
def add_func(f):
if f not in seen_set:
funcs.append(f)
seen_set.add(f)
funcs.sort(key=lambda x: x.generation)
add_func(self.creator)
while funcs:
f = funcs.pop()
# 역전파 계산(메인 처리)
gys = [output().grad for output in f.outputs] # output is weakref #1
gxs = f.backward(*gys) #2
if not isinstance(gxs, tuple):
gxs = (gxs,)
for x, gx in zip(f.inputs, gxs): #3
if x.grad is None:
x.grad = gx
else:
x.grad = x.grad + gx
if x.creator is not None:
add_func(x.creator)
if not retain_grad:
for y in f.outputs:
y().grad = None # y is weakref
- Variable의 인스턴스 변수인 grad를 리스트로 모으고, 인스턴스 변수 grad는 ndarray 인스턴스를 참조하고 있다.
- backward 메서드에는 ndarray 인스턴스가 담긴 리스트 가 전달된다.
- 출력 쪽에서 저파하는 미분값 (gxs)을 함수의 입력 변수(f.inputs)의 grad로 설정
출처 : http://www.yes24.com/Product/Goods/95343845?OzSrank=2
728x90
반응형
최근댓글