DonHurry

step21. μ—°μ‚°μž μ˜€λ²„λ‘œλ“œ(2) λ³Έλ¬Έ

DeZero/πŸ—»μ œ2κ³ μ§€

step21. μ—°μ‚°μž μ˜€λ²„λ‘œλ“œ(2)

_도녁 2023. 1. 22. 01:15

πŸ“’ λ³Έ ν¬μŠ€νŒ…μ€ λ°‘λ°”λ‹₯λΆ€ν„° μ‹œμž‘ν•˜λŠ” λ”₯λŸ¬λ‹3을 기반으둜 μž‘μ„±ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 배운 λ‚΄μš©μ„ κΈ°λ‘ν•˜κ³ , 개인적인 곡뢀λ₯Ό μœ„ν•΄ μž‘μ„±ν•˜λŠ” ν¬μŠ€νŒ…μž…λ‹ˆλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ ꡐ재 ꡬ맀λ₯Ό κ°•λ ₯ μΆ”μ²œλ“œλ¦½λ‹ˆλ‹€.

 

 

이번 λ‹¨κ³„μ—μ„œλ„ μ΄μ–΄μ„œ μ—°μ‚°μž μ˜€λ²„λ‘œλ“œλ₯Ό μ§„ν–‰ν•©λ‹ˆλ‹€. 이전 λ‹¨κ³„μ˜ κ΅¬ν˜„μ„ 톡해 Variable μΈμŠ€ν„΄μŠ€ a와 b의 a + b 같은 연산을 μˆ˜ν–‰ν•  수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ ν˜„μž¬λŠ” a * np.array(3.0)μ΄λ‚˜ 3 + a와 같은 ndarray μΈμŠ€ν„΄μŠ€ λ˜λŠ” 수치 λ°μ΄ν„°μ™€μ˜ 연산은 λΆˆκ°€ν•©λ‹ˆλ‹€. 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•œ λ°©λ²•μœΌλ‘œ λ‹€λ₯Έ 데이터듀을 Variable μΈμŠ€ν„΄μŠ€λ‘œ λ³€ν™˜ν•˜λŠ” μž‘μ—…μ„ μ§„ν–‰ν•©λ‹ˆλ‹€. μš°μ„  variable둜 λ³€κ²½ν•˜κΈ° μœ„ν•œ ν•¨μˆ˜μž…λ‹ˆλ‹€.

def as_variable(obj):
    if isinstance(obj, Variable):
        return obj
    return Variable(obj)

 

이제 Function 클래슀의 __call__ λ©”μ„œλ“œκ°€ as_variable ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜λ„λ‘ λ³€κ²½ν•©λ‹ˆλ‹€.

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)
        ...

 

λ‹€μŒμ€ 파이썬의 float, int λ“±μ˜ κ²½μš°μž…λ‹ˆλ‹€. xκ°€ Variable μΈμŠ€ν„΄μŠ€μΌ λ•Œ x + 2.0 같은 μ½”λ“œλ₯Ό μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄ κΈ°μ‘΄ ν•¨μˆ˜μ— μ½”λ“œλ₯Ό μΆ”κ°€ν•˜κ² μŠ΅λ‹ˆλ‹€. x1이 floatμ΄λ‚˜ int라면, ndarray μΈμŠ€ν„΄μŠ€λ‘œ λ³€ν™˜ ν›„ Function 클래슀 λ‚΄λΆ€μ—μ„œ λ‹€μ‹œ Variable μΈμŠ€ν„΄μŠ€λ‘œ λ³€ν™˜λ©λ‹ˆλ‹€.

def add(x0, x1):
    x1 = as_array(x1)
    return Add()(x0, x1)

 

아직 문제점이 λ‚¨μ•„μžˆμŠ΅λ‹ˆλ‹€. μ—°μ‚°μž μ˜€λ²„λ‘œλ“œμ—μ„œλŠ” x * 2.0κ³Ό 2.0 * xλŠ” λ‹€λ₯Έ λ¬Έμ œμž…λ‹ˆλ‹€. ν˜„μž¬λŠ” 2.0 * xλ₯Ό μˆ˜ν–‰ν•  경우 였λ₯˜κ°€ μƒκΉλ‹ˆλ‹€. μš°μ„  μ‹€ν–‰ν–ˆμ„ λ•Œ 였λ₯˜κ°€ λ°œμƒν•˜λŠ” 과정을 λ³΄κ² μŠ΅λ‹ˆλ‹€.

 

1. μ—°μ‚°μž μ™Όμͺ½μ— μžˆλŠ” 2.0의 __mul__ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ € μ‹œλ„ν•œλ‹€.

2. ν•˜μ§€λ§Œ 2.0은 float νƒ€μž…μ΄λ―€λ‘œ __mul__ λ©”μ„œλ“œλŠ” κ΅¬ν˜„λ˜μ–΄ μžˆμ§€ μ•Šλ‹€.

3. λ‹€μŒμ€ * μ—°μ‚°μž 였λ₯Έμͺ½μ— μžˆλŠ” x의 특수 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ € μ‹œλ„ν•œλ‹€.

4. xκ°€ 였λ₯Έμͺ½μ— 있기 λ•Œλ¬Έμ— (__mul__λŒ€μ‹ ) __rmul__ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ € μ‹œλ„ν•œλ‹€.

5. ν•˜μ§€λ§Œ Variable μΈμŠ€ν„΄μŠ€μ—λŠ” __rmul__ λ©”μ„œλ“œκ°€ κ΅¬ν˜„λ˜μ–΄ μžˆμ§€ μ•Šλ‹€.

 

λ”°λΌμ„œ __rmul__ λ©”μ„œλ“œλ„ ν•¨κ»˜ κ΅¬ν˜„ν•΄μ•Όν•©λ‹ˆλ‹€. μ—°μ‚°μž μ˜€λ²„λ‘œλ“œμ— κ΄€ν•΄ 더 κΆκΈˆν•œ 점은 직접 μ°Ύμ•„λ³΄λŠ” κ±Έ μΆ”μ²œλ“œλ¦½λ‹ˆλ‹€. 특히 C++ 같은 μ–Έμ–΄μ—μ„œ λ‹€λ£¨λŠ” κ²½μš°κ°€ λ§ŽμŠ΅λ‹ˆλ‹€. DeZero의 특수 λ©”μ„œλ“œλŠ” λ‹€μŒκ³Ό 같이 μ„€μ •ν•©λ‹ˆλ‹€.

Variable.__add__ = add
Variable.__radd__ = add
Variable.__mul__ = mul
Variable.__rmul__ = mul

 

λ§ˆμ§€λ§‰μœΌλ‘œ λ‹€μŒκ³Ό 같이 μ’Œν•­μ΄ ndarray μΈμŠ€ν„΄μŠ€κ³  μš°ν•­μ΄ Variable인 κ²½μš°λ„ ν•΄κ²°ν•΄μ•Όν•©λ‹ˆλ‹€. μ’Œν•­μ˜ ndarray μΈμŠ€ν„΄μŠ€μ˜ __add__ λ©”μ„œλ“œκ°€ μ•„λ‹Œ μš°ν•­μ˜ Variable μΈμŠ€ν„΄μŠ€μ˜ __radd__ λ©”μ„œλ“œκ°€ ν˜ΈμΆœλ˜μ–΄μ•Όν•©λ‹ˆλ‹€.

x = Variable(np.array([1.0]))
y = np.array([2.0]) + x

 

μœ„μ™€ 같은 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μ—°μ‚°μž μš°μ„ μˆœμœ„λ₯Ό μ§€μ •ν•˜κ² μŠ΅λ‹ˆλ‹€. Variable μΈμŠ€ν„΄μŠ€ 속성에 __array_priority__λ₯Ό μΆ”κ°€ν•˜κ³  큰 μ •μˆ˜ κ°’μœΌλ‘œ μ„€μ •ν•©λ‹ˆλ‹€.

class Variable:
    __array_priority__ = 200
    ...