DonHurry

step13. κ°€λ³€ 길이 인수(μ—­μ „νŒŒ 편) λ³Έλ¬Έ

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

step13. κ°€λ³€ 길이 인수(μ—­μ „νŒŒ 편)

_도녁 2023. 1. 14. 01:25

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

 

 

이전 λ‹¨κ³„κΉŒμ§€λŠ” ν•¨μˆ˜κ°€ μ—¬λŸ¬ 개의 λ³€μˆ˜λ₯Ό μž…λ ₯λ°›κ³  λ°˜ν™˜ν•  수 μžˆλ„λ‘ ν•˜κ³ , μˆœμ „νŒŒμ—κΉŒμ§€ λ°˜μ˜ν–ˆμŠ΅λ‹ˆλ‹€. μ΄λ²ˆμ—λŠ” μ—­μ „νŒŒμž…λ‹ˆλ‹€.

 

μ•„λž˜ λ§μ…ˆ 계산 κ·Έλž˜ν”„μ—μ„œ μ—­μ „νŒŒλŠ” μž…λ ₯이 1개, 좜λ ₯이 2κ°œμž…λ‹ˆλ‹€. μ΄λ•Œ $y=x0+x1$μ—μ„œ $x0$κ³Ό $x1$ 각각에 λŒ€ν•΄ νŽΈλ―ΈλΆ„μ„ μ§„ν–‰ν•˜λ©΄ 각각 1, 1이 λ‚˜μ˜΅λ‹ˆλ‹€. λ§μ…ˆμ˜ μ—­μ „νŒŒλŠ” 좜λ ₯ μͺ½μ—μ„œ μ „ν•΄μ§€λŠ” 미뢄값에 1을 κ³±ν•œ 값이 μž…λ ₯ λ³€μˆ˜ (x0, x1)의 λ―ΈλΆ„μž…λ‹ˆλ‹€. 즉, 상λ₯˜μ—μ„œ ν˜λŸ¬μ˜€λŠ” 미뢄값을 κ·ΈλŒ€λ‘œ ν˜λ €λ³΄λ‚΄λŠ” 것이 λ§μ…ˆμ˜ μ—­μ „νŒŒμž…λ‹ˆλ‹€.

 

μœ„ λ‚΄μš©λ“€μ„ λ°˜μ˜ν•˜μ—¬ Add 클래슀λ₯Ό λ‹€μŒκ³Ό 같이 κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ•„λž˜μ˜ μ½”λ“œκ°€ λ™μž‘ν•˜λ €λ©΄ Variable ν΄λž˜μŠ€λ„ μˆ˜μ •ν•˜μ—¬μ•Ό ν•©λ‹ˆλ‹€.

class Add(Function):
    def forward(self, x0, x1):
        y = x0 + x1
        return y

    def backward(self, gy):
        return gy, gy

 

κΈ°μ‘΄ μ½”λ“œμ—μ„œ 총 λ„€ ꡰ데λ₯Ό μˆ˜μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€. 1λ²ˆμ—μ„œ 좜λ ₯ λ³€μˆ˜μΈ outputs에 담겨 μžˆλŠ” 미뢄값듀을 λ¦¬μŠ€νŠΈμ— μ €μž₯ν•©λ‹ˆλ‹€. 2λ²ˆμ—μ„œλŠ” μ—­μ „νŒŒλ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€. 3λ²ˆμ—μ„œλŠ” gxsκ°€ νŠœν”Œμ΄ μ•„λ‹Œ 경우λ₯Ό κ³ λ €ν•΄μ€λ‹ˆλ‹€. λ§ˆμ§€λ§‰μœΌλ‘œ 4λ²ˆμ—μ„œλŠ” μ—­μ „νŒŒλ‘œ μ „νŒŒλ˜λŠ” 미뢄값을 Variable μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μΈ grad에 μ €μž₯ν•©λ‹ˆλ‹€.

class Variable:
    ...
    
    def backward(self):
        if self.grad is None:
            self.grad = np.ones_like(self.data)
        
        funcs = [self.creator]
        while funcs:
            f = funcs.pop()
            gys = [output.grad for output in f.outputs]  # 1
            gxs = f.backward(*gys)  # 2
            if not isinstance(gxs, tuple):  # 3
                gxs = (gxs, )
            
            for x, gx in zip(f.inputs, gxs):  # 4
                x.grad = gx

                if x.creator is not None:
                    funcs.append(x.creator)

 

 

κ°œμ„ λœ 클래슀λ₯Ό λ°”νƒ•μœΌλ‘œ Square ν΄λž˜μŠ€λ„ μˆ˜μ •ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€. self.inputs.data λΆ€λΆ„λ§Œ λ³€κ²½ν•΄μ£Όλ©΄ λ©λ‹ˆλ‹€.

class Square(Function):
    def forward(self, x):
        y = x ** 2
        return y

    def backward(self, gy):
        x = self.inputs[0].data  # μˆ˜μ •
        gx = 2 * x * gy
        return gx

 

λ§ˆμ§€λ§‰μœΌλ‘œ add ν•¨μˆ˜μ™€ square ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄λ΄…μ‹œλ‹€. $z=x^2+y^2$λ₯Ό κ³„μ‚°ν•˜λŠ” μ½”λ“œμž…λ‹ˆλ‹€. μ΄μƒμœΌλ‘œ 볡수 μž…μΆœλ ₯에 λŒ€μ‘ν•˜μ—¬ μžλ™ λ―ΈλΆ„ ꡬ쑰λ₯Ό μ™„μ„±ν–ˆμŠ΅λ‹ˆλ‹€. λ‹€λ§Œ, μ§€κΈˆμ˜ DeZeroλŠ” λͺ‡ κ°€μ§€ λ¬Έμ œκ°€ μˆ¨μ–΄ μžˆμ–΄, λ‹€μŒ 단계에선 이 λ¬Έμ œλ“€μ„ ν•΄κ²°ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

x = Variable(np.array(2.0))
y = Variable(np.array(3.0))

z = add(square(x), square(y))
z.backward()
print(z.data)  # 13.0
print(x.grad)  # 4.0
print(y.grad)  # 6.0