이번에 추가될 연산자들을 아래에 표로 만들었습니다.
| 특수 메서드 | 예 | 설명 |
| __neg__(self) | -self | 양수를 음수로 or 음수를 양수로 바꿔주는 부호 연산자, 단항 연산자 |
| __sub__(self, other) | self - other | 뺄셈 연산자, 이항 연산자 |
| __rsub__(self, other) | other - self | 뺄셈 연산자, 이항 연산자 |
| __truediv__(self, other) | self / other | 나눗셈 연산자, 이항 연산자 |
| __rtruediv__(self, other) | other / self | 나눗셈 연산자, 이항 연산자 |
| __pow__(self, other) | self** other | 거듭제곱 연산자, 이항 연산자 |
이러한 연산자를 추가하는 순서는
1. Function 클래스를 상속하여 원하는 함수 클래스를 구현합니다.(예: Mul 클래스)
2. 파이썬 함수로 사용할 수 있도록 합니다.(예: mul 함수)
3. Variable 클래스의 연산자를 오버로드합니다.(Variable.__mul__=mul)
22.1 음수(부호 변환)
음수의 미분은 y = -x일 때 ∂y/∂x = -1입니다.
역전파는 출력 쪽에서 전해지는 미분에 -1을 곱하여 앞단으로 흘려보내주기 때문에
Neg 클래스를 구현한다음 Neg 클래스의 인스턴스를 생성해주는 neg 함수를 구현해주고
특수 메서드인 __neg__에 함수 neg를 대입해주면 됩니다.
class Neg(Function):
def forward(self, x):
return -x
def backward(self, gy):
return -gy
def neg(x):
return Neg()(x)
Variable.__neg__ = neg

22.2 뺄셈
뺄셈의 미분은 y = x0 - x1일때 ∂y/∂x0 = 1, ∂y/∂x1 = -1이 됩니다.
x0의 미분 결과는 출력에서 전해지는 미분값에 1을 곱한 값이되고x1의 미분 결과는 출력에서 전해지는 미분값에 -1을 곱한 값이 됩니다.
class Sub(Function):
def forward(self, x0, x1):
y = x0 - x1
return y
def backward(self, gy):
return gy, -gy
def sub(x0, x1):
x1 = as_array(x1)
return Sub()(x0, x1)
def rsub(x0, x1):
x1 = as_array(x1)
return sub(x1, x0)
Variable.__sub__ = sub
Variable.__rsub__ = rsub
y1 = 2.0 - x
y2 = x - 1.0
print(y1) # variable(0.0)
print(y2) # variable(1.0)

22.3 나눗셈
나눗셈 미분은 y = x0/x1일때 ∂y/∂x0 = 1, ∂y/∂x1 = -x0/(x1)**2입니다.
나눗셈도 좌우항 중 어느 것에 적용할지에 다라 적용된는 함수가 다릅니다.
class Div(Function):
def forward(self, x0, x1):
y = x0 / x1
return y
def backward(self, gy):
x0, x1 = self.inputs[0].data, self.inputs[1].data
gx0 = gy / x1
gx1 = gy * (-x0 / x1 ** 2)
return gx0, gx1
def div(x0, x1):
x1 = as_array(x1)
return Div()(x0, x1)
def rdiv(x0, x1):
x1 = as_array(x1)
return div(x1, x0)
Variable.__sub__ = sub
Variable.__rsub__ = rsub
y = 3.0 / x
print(y) # variable(1.5)

22.4 거듭제곱
거듭제곱은 y = x**c일때 x를 밑이라고하고 c를 지수라합니다.
거듭제곱의 미분공식은 ∂y/∂x = cx**c-1입니다.
class Pow(Function):
def __init__(self, c):
self.c = c
def forward(self, x):
y = x ** self.c
return y
def backward(self, gy):
x = self.inputs[0].data
c = self.c
gx = c * x ** (c - 1) * gy
return gx
def pow(x, c):
return Pow(c)(x)
Variable.__pow__ = pow
y = x ** 3
y.backward()
print(y) # variable(8.0)
코드를 보면 Pow 클래스를 초기화 할 때 지수 c를 제공합니다.
순전파 메서드에서는 x 하나의 항만 받고
특수 메서드 __pow__에서는 함수 pow를 할당합니다.

'Study 공부할레나' 카테고리의 다른 글
| [스터디/밑시딥3] 제 2고지 자연스러운 코드로_24. 복잡한 함수의 미분 (0) | 2023.08.30 |
|---|---|
| [스터디/밑시딥3] 제 2고지 자연스러운 코드로_23. 패키지로 정리 (0) | 2023.08.30 |
| [스터디/밑시딥3] 제 2고지 자연스러운 코드로_21. 연산자 오버로드(2) (0) | 2023.08.27 |
| [스터디/밑시딥3] 제 2고지 자연스러운 코드로_20. 연산자 오버로드(1) (0) | 2023.08.27 |
| [스터디/밑시딥3] 제 2고지 자연스러운 코드로_19. 변수 사용성 개선 (0) | 2023.08.26 |