페이지

2022년 8월 26일 금요일

20.1 Mul 클래스 구현

 곰셈의 미분은 y = x0 * x1 일때 dy/dx0 = x1, dy/dx1 = x0가 됩니다. 따라서 역전파는 [그림 20-1]처럼 이루어집니다.


[그림 20-1]에서 보듯 역전파는 최종 출력인 l의 미분을, 정확하게는 l의 각 변수에 대한 미분을 전파합니다. 이때 변수 x0와 x1에 대한 미분은 각각 dl/dx0 = x1*dl/dy 과 dl/dx1 = x0*dl/dy입니다.


우리는 스칼라를 출력하는 합성 함수에 관임이 있습니다. 그래서 [그림 20-1]에서는 마지막에 L이라는 스칼라를 출려하는 합성 함수를 가정했습니다. 여기서 L은 오차, 다른 말로 손실(loss)을 뜻합니다.

그럼 Mul클래스의 코드부터 보죠, [그림 20-1]를 참고하여 다음과 같이 구현할 수 있습니다.

class Mul(Function):
  def forward(selfx0x1):
    y = x0 * x1

    return y
  
  def backward(selfgy):
    x0, x1 = self.inputs[0].data, self.inputs[1].data
    return gy * x1, gy * x0

이어서 Mul클래스를 파이썬 함수로 사용할 수 있도록 해줍니다. 코드는 다음과 같습니다.

def mul(x0x1):
  return Mul()(x0, x1)

이제 mul함수를 사용하여 '곱셈'을 할 수 있습니다. 옐르 들어 다음과 같은 코드를 작성할 수 있습니다.

a = Variable(np.array(3.0))
b = Variable(np.array(2.0))
c = Variable(np.array(1.0))

y = add(mul(a, b), c)
y.backward()

print(y)
print(a.grad)
print(b.grad)



variable(7.0) 2.0 3.0

이와 같이 add 함수와 mul 함수를 함께 사용할 수 있게 됐습니다. 이때 미분도 자동으로 이루어집니다. 다만 매번 y = add(mul(a, b), c)처럼 코딩하기는 번거로울 것 같군요, 지금 보다는 y = a * b + c 형태가 훨씬 깔끔하겠죠? 그래서 + 와 * 연산자를 사용할 수 있도록 Variable을 확장하려 합니다. 이를 위해 연사자 오버로드operator.overload를 이용할 것입니다.


연산자를 오버로드하면 + 와 * 같은 연산자 사용 시 사용자가 설정한 함수가 호출됩니다. 파이썬에서는 __add__와 __mul__ 같은 특수 메서드를 정의함으로써 사용자 지정함수가 호출되도록 합니다.






댓글 없음: