๋ฐ์ํ
์ด๋ฒ๊ธ์์๋ ๋จ์ํ Layer ๋ถํฐ ํ๋ฒ ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค.
- ์์ ๊ธ์์๋ณธ ๊ณ์ฐ ๊ทธ๋ํ์ ๊ณฑ์ ๋ ธ๋๋ฅผ 'MultiLayer', ๋ง์ ๋ ธ๋๋ฅผ 'AddLayer'๋ผ๋ ์ด๋ฆ์ผ๋ก ๊ตฌํํฉ๋๋ค.
๊ณฑ์ ๊ณ์ธต
- ๋ชจ๋ ๊ณ์ธต์ forward()์ backward()๋ผ๋ ๊ณตํต์ Method(์ธํฐํ์ด์ค)๋ฅผ ๊ฐ๋๋ก ๊ตฌํํฉ๋๋ค.
- forward()๋ Forward Propagation(์์ ํ), backward()๋ Back propagation(์ญ์ ํ)๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
- ํ๋ฒ ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค.
# coding: utf-8
class MulLayer:
def __init__(self):
self.x = None
self.y = None
# x์ y๋ฅผ ์ธ์๋ผ ๋ฐ๊ณ ๋ ๊ฐ์ ๊ณฑํด์ ๋ฐํ
def forward(self, x, y):
self.x = x
self.y = y
out = x * y
return out
# ์๋ฅ์์ ๋์ด์จ ๋ฏธ๋ถ(dout)์ ์์ ํ ๋์ ๊ฐ์
# ์๋ก ๋ฐ๊ฟ ๊ณฑํ ํ ํ๋ฅ๋ก ํ๋ ค์ค
def backward(self, dout):
dx = dout * self.y # x์ y๋ฅผ ๋ฐ๊พผ๋ค.
dy = dout * self.x
return dx, dy
- ์ธ์คํด์ค ๋ณ์์ธ x,y๋ฅผ ์ด๊ธฐํ ํฉ๋๋ค. ์ด ๋ ๋ณ์๋ Forward PropagatIon(์์ ํ)์ ์ ๋ ฅ ๊ฐ์ ์ ์งํ๊ธฐ ์ํด์ ์ฌ์ฉํฉ๋๋ค.
- forward()์์๋ x, y๋ฅผ ์ธ์๋ก ๋ฐ๊ณ ๋ ๊ฐ์ ๊ณฑํด์ ๋ฐํ ํฉ๋๋ค.
- ๋ฐ๋ฉด backward()์์๋ ์๋ฅ์์ ๋์ด์จ ๋ฏธ๋ถ(dout)์ Forward PropagatIon(์์ ํ) ๋์ ๊ฐ์ '์๋ก ๋ด๊ฟ' ๊ณฑํ ํ ํ๋ฅ๋ก ํ๋ฆฝ๋๋ค.
- MulLayer๋ฅผ ์ฌ์ฉํ์ฌ ์์ ํ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํํ ์ ์์ต๋๋ค.
# coding: utf-8
from layer_naive import *
apple = 100
apple_num = 2
tax = 1.1
mul_apple_layer = MulLayer()
mul_tax_layer = MulLayer()
# forward
apple_price = mul_apple_layer.forward(apple, apple_num)
price = mul_tax_layer.forward(apple_price, tax)
print(price) # 200
- ๊ฐ ๋ณ์์ ๋ํ ๋ฏธ๋ถ์ backward() ์์ ๊ตฌํ ์ ์์ต๋๋ค.
# backward (์ญ์ ํ)
dprice = 1
dapple_price, dtax = mul_tax_layer.backward(dprice)
dapple, dapple_num = mul_apple_layer.backward(dapple_price)
print(dapple, dapple_num, dtax) # 2.2 110 200
- backward() ์ญ์ ํ์ ํธ์ถ ์์๋ forward() ์์ ํ ๋์๋ ๋ฐ๋์ ๋๋ค.
- ๋, backward()๊ฐ ๋ฐ๋ ์ธ์๋ '์์ ํ์ ์ถ๋ ฅ์ ๋ํ ๋ฏธ๋ถ'์์ ์ฃผ์ํฉ๋๋ค.
๋ง์ ๊ณ์ธต
class AddLayer:
def __init__(self):
pass
# ์
๋ ฅ๋ฐ์ ๋ ์ธ์ x, y๋ฅผ ๋ํด์ ๋ฐํ
def forward(self, x, y):
out = x + y
return out
# ์๋ฅ์์ ๋ด๋ ค์จ ๋ฏธ๋ถ(dout)์ ๊ทธ๋๋ก ํ๋ฅ๋ก ํ๋ ค์ค
def backward(self, dout):
dx = dout * 1
dy = dout * 1
return dx, dy
- ๋ง์
๊ณ์ธต์์๋ ์ด๊ธฐํ๊ฐ ํ์ ์๊ธฐ ๋๋ฌธ์ _init_()์์๋ ์๋ฌด ์ผ๋ ํ์ง ์์ต๋๋ค.
- ์ฆ, pass๋ ์๋ฌด๊ฒ๋ ํ์ง ๋ง๋ผ๋ ๋ช ๋ น์ ๋๋ค.
- ๋ง์ ๊ณ์ธต์ forward()์์๋ ์ ๋ ฅ๋ฐ์ ๋ ์ธ์ x, y๋ฅผ ๋ํด์ ๋ฐํํฉ๋๋ค.
- backward()์์๋ ์๋ฅ์์ ๋ด๋ ค์จ ๋ฏธ๋ถ(dout)์ ๊ทธ๋๋ก ํ๋ฅ๋ก ํ๋ฆด ๋ฟ์ ๋๋ค.
๊ทธ๋ฌ๋ฉด ๋ง์ , ๊ณฑ์ ๊ณ์ธต์ ์ฌ์ฉํ์ฌ ์ฌ๊ณผ 2๊ฐ์ ๊ทค 3๊ฐ๋ฅผ ์ฌ๋ ์ํฉ์ ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค.
# coding: utf-8
from layer_naive import *
apple = 100
apple_num = 2
orange = 150
orange_num = 3
tax = 1.1
# layer
mul_apple_layer = MulLayer()
mul_orange_layer = MulLayer()
add_apple_orange_layer = AddLayer()
mul_tax_layer = MulLayer()
# forward
apple_price = mul_apple_layer.forward(apple, apple_num) # (1)
orange_price = mul_orange_layer.forward(orange, orange_num) # (2)
all_price = add_apple_orange_layer.forward(apple_price, orange_price) # (3)
price = mul_tax_layer.forward(all_price, tax) # (4)
# backward
dprice = 1
dall_price, dtax = mul_tax_layer.backward(dprice) # (4)
dapple_price, dorange_price = add_apple_orange_layer.backward(dall_price) # (3)
dorange, dorange_num = mul_orange_layer.backward(dorange_price) # (2)
dapple, dapple_num = mul_apple_layer.backward(dapple_price) # (1)
print("price:", int(price))
print("dApple:", dapple)
print("dApple_num:", int(dapple_num))
print("dOrange:", dorange)
print("dOrange_num:", int(dorange_num))
print("dTax:", dtax)
- ํ๋ํ๋์ ๋ช ๋ น์ ๋จ์ํฉ๋๋ค. ํ์ํ ๊ณ์ธต์ ๋ง๋ค์ด์ Forward Propagation(์์ ํ) Method์ธ forward()๋ฅผ ์ ์ ํ ์์๋ก ํธ์ถํฉ๋๋ค.
- ๊ทธ๋ฐ ๋ค์ Forward Propagation(์์ ํ)์ ๋ฐ๋ ์์๋ก Back Propagation(์ญ์ ํ) Method์ธ Backward()๋ฅผ ํธ์ถํ๋ฉด ์ํ๋ ๋ฏธ๋ถ์ด ๋์ต๋๋ค.
Model Code (by Python)
# ๊ณฑ์
๊ณ์ธต ์ ์
class MulLayer:
def __init__(self):
self.x = None # ์์ ํ ์
๋ ฅ๊ฐ ์ ์ง๋ฅผ ์ํด์ ์ด๊ธฐํ
self.y = None # ์์ ํ ์
๋ ฅ๊ฐ ์ ์ง๋ฅผ ์ํด์ ์ด๊ธฐํ
def forward(self, x, y):
self.x = x # ์์ ํ ์ ์
๋ ฅ๋ x๊ฐ ์ ์ฅ
self.y = y # ์์ ํ ์ ์
๋ ฅ๋ y๊ฐ ์ ์ฅ
out = x * y # ์
๋ ฅ๋ ๋ ๊ฐ์ ๊ณฑ ๋ฐํ
return out
# ์๋ฅ์์ ๋์ด์จ ๋ฏธ๋ถ(dout)์์ ์์ ํ ๋์ ๊ฐ์ ์๋ก ๋ด๊ฟ ๊ณฑํ ํ ํ๋ฅ๋ก ํ๋ฆผ
def backward(self, dout):
dx = dout * self.y # x์ ๋ํ ๋ฏธ๋ถ๊ฐ ๊ณ์ฐ
dy = dout * self.x # y์ ๋ํ ๋ฏธ๋ถ๊ฐ ๊ณ์ฐ
return dx, dy # ๋ฏธ๋ถ ๊ฒฐ๊ณผ ๋ฐํ
# ๋ง์
๊ณ์ธต ์ ์
class AddLayer:
def __init__(self):
pass # ๋ง์
๊ณ์ธต์ ๋ณ๋์ ์ด๊ธฐํ ์์
์ด ํ์ ์์
def forward(self, x, y):
out = x + y # ์
๋ ฅ๋ ๋ ๊ฐ์ ํฉ ๋ฐํ
return out
# ์๋ฅ์์ ๋์ด์จ ๋ฏธ๋ถ(dout)์์ ์์ ํ ๋์ ๊ฐ์ ์๋ก ๋ด๊ฟ ๊ณฑํ ํ ํ๋ฅ๋ก ํ๋ฆผ
def backward(self, dout):
dx = dout * 1 # x์ ๋ํ ๋ฏธ๋ถ๊ฐ ๊ณ์ฐ
dy = dout * 1 # y์ ๋ํ ๋ฏธ๋ถ๊ฐ ๊ณ์ฐ
return dx, dy # ๋ฏธ๋ถ ๊ฒฐ๊ณผ ๋ฐํ
if __name__ == '__main__':
# ๋ฌธ์ 1: ์ฌ๊ณผ ๊ฐ๊ฒฉ ๊ณ์ฐ ์์
apple = 100 # ์ฌ๊ณผ ํ ๊ฐ ๊ฐ๊ฒฉ
apple_num = 2 # ์ฌ๊ณผ ๊ฐ์
tax = 1.1 # ์ธ๊ธ
# ๊ณ์ธต ์์ฑ
mul_apple_layer = MulLayer() # ์ฌ๊ณผ ๊ฐ๊ฒฉ ๊ณ์ฐ์ ์ํ ๊ณฑ์
๊ณ์ธต
mul_tax_layer = MulLayer() # ์ธ๊ธ ๊ณ์ฐ์ ์ํ ๊ณฑ์
๊ณ์ธต
# ์์ ํ
apple_price = mul_apple_layer.forward(apple, apple_num) # ์ฌ๊ณผ ๊ฐ๊ฒฉ ๊ณ์ฐ
price = mul_tax_layer.forward(apple_price, tax) # ์ต์ข
๊ฐ๊ฒฉ ๊ณ์ฐ
print(price) # ์ต์ข
๊ฐ๊ฒฉ ์ถ๋ ฅ
# ์ญ์ ํ
dprice = 1 # ๊ฐ๊ฒฉ์ ๋ํ ๋ฏธ๋ถ๊ฐ ์ด๊ธฐํ
dapple_price, dtax = mul_tax_layer.backward(dprice) # ์ธ๊ธ ๊ณ์ฐ ์ญ์ ํ
dapple, dapple_num = mul_apple_layer.backward(dapple_price) # ์ฌ๊ณผ ๊ฐ๊ฒฉ ๊ณ์ฐ ์ญ์ ํ
print(dapple, dapple_num, dtax) # ๋ฏธ๋ถ ๊ฒฐ๊ณผ ์ถ๋ ฅ
# ๋ฌธ์ 2: ์ฌ๊ณผ์ ์ค๋ ์ง ๊ฐ๊ฒฉ ๊ณ์ฐ ์์
orange = 150 # ์ค๋ ์ง ํ ๊ฐ ๊ฐ๊ฒฉ
orange_num = 3 # ์ค๋ ์ง ๊ฐ์
# ๊ณ์ธต ์ฌ์ฌ์ฉ ๋ฐ ์๋ก์ด ๊ณ์ธต ์์ฑ
mul_apple_layer = MulLayer() # ์ฌ๊ณผ ๊ฐ๊ฒฉ ๊ณ์ฐ์ ์ํ ๊ณฑ์
๊ณ์ธต (์ฌ์ฌ์ฉ)
mul_orange_layer = MulLayer() # ์ค๋ ์ง ๊ฐ๊ฒฉ ๊ณ์ฐ์ ์ํ ๊ณฑ์
๊ณ์ธต
add_apple_orange_layer = AddLayer() # ์ฌ๊ณผ์ ์ค๋ ์ง ๊ฐ๊ฒฉ ํฉ์ฐ์ ์ํ ๋ง์
๊ณ์ธต
mul_tax_layer = MulLayer() # ์ธ๊ธ ๊ณ์ฐ์ ์ํ ๊ณฑ์
๊ณ์ธต (์ฌ์ฌ์ฉ)
# ์์ ํ
apple_price = mul_apple_layer.forward(apple, apple_num) # ์ฌ๊ณผ ๊ฐ๊ฒฉ ๊ณ์ฐ
orange_price = mul_orange_layer.forward(orange, orange_num) # ์ค๋ ์ง ๊ฐ๊ฒฉ ๊ณ์ฐ
all_price = add_apple_orange_layer.forward(apple_price,
Activation Function Layer (ํ์ฑํ ํจ์ ๊ณ์ธต) ๊ตฌํํ๊ธฐ
๊ณ์ฐ ๊ทธ๋ํ๋ฅผ ์ ๊ฒฝ๋ง์ ์ ์ฉํด ๋ณด๊ฒ ์ต๋๋ค. ์ ๊ฒฝ๋ง์ ๊ตฌ์ฑํ๋ Layer(๊ณ์ธต)์ ๊ฐ๊ฐ์ ํด๋์ค ํ๋๋ก ๊ตฌํํฉ๋๋ค.
ReLU ๊ณ์ธต
- ํ์ฑํ ํจ์๋ก ์ฌ์ฉ๋๋ ReLU์ ์์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- x์ ๋ํ y์ ๋ฏธ๋ถ์ ์๋์ ์์ฒ๋ผ ๊ตฌํฉ๋๋ค.
- ์์ ์์๊ณผ ๊ฐ์ด, Forward Propagation(์์ ํ) ๋์ ์ ๋ ฅ์ธ x๊ฐ 0๋ณด๋ค ํฌ๋ฉด Back Propagation(์ญ์ ํ)๋ ์๋ฅ์ ๊ฐ์ ๊ทธ๋๋ก ํ๋ฅ๋ก ํ๋ฆฝ๋๋ค.
- ๋ค๋ง, Forward Propagation(์์ ํ) ๋ x๊ฐ 0 ์ดํ๋ฉด Back Propagation(์ญ์ ํ) ๋๋ ํ๋ฅ๋ก ์ ํธ๋ฅผ ๋ณด๋ด์ง ์์ต๋๋ค. (0์ ๋ณด๋ ๋๋ค.) ๊ณ์ฐ ๊ทธ๋ํ๋ก๋ ์๋์ ๊ทธ๋ฆผ์ฒ๋ผ ๊ทธ๋ฆฝ๋๋ค.
- ์ด์ ํ๋ฒ ReLU ๊ณ์ธจ์ ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค.
class Relu:
def __init__(self):
self.mask = None # ์
๋ ฅ๊ฐ์ด 0 ์ดํ์ธ์ง ์ฌ๋ถ๋ฅผ ์ ์ฅํ๊ธฐ ์ํ ๋ณ์๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
def forward(self, x):
self.mask = (x <= 0) # x์ ๊ฐ์ด 0 ์ดํ์ธ ์์๋ True, ๊ทธ ์ธ๋ False๋ก ํ๋ ๋ฐฐ์ด์ ์์ฑํฉ๋๋ค.
out = x.copy() # ์
๋ ฅ๊ฐ x์ ๋ณต์ฌ๋ณธ์ ์์ฑํฉ๋๋ค.
out[self.mask] = 0 # mask๊ฐ True์ธ ์์น, ์ฆ x์ ๊ฐ์ด 0 ์ดํ์ธ ์์น์ ์์๋ฅผ 0์ผ๋ก ์ค์ ํฉ๋๋ค.
return out # ํ์ฑํ ํจ์๋ฅผ ์ ์ฉํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
def backward(self, dout):
dout[self.mask] = 0 # ์์ ํ ๋ 0 ์ดํ์๋ ์์์ ๋์ํ๋ ์ญ์ ํ ๊ฐ์ 0์ผ๋ก ์ค์ ํฉ๋๋ค.
dx = dout # ๋๋จธ์ง ์์๋ ๊ทธ๋๋ก dout์ ๋ฐํํฉ๋๋ค.
return dx # ์
๋ ฅ๊ฐ์ ๋ํ ๋ฏธ๋ถ๊ฐ์ ๋ฐํํฉ๋๋ค.
- ReLU ํด๋์ค๋ mask๋ผ๋ ์ธ์คํด์ค ๋ณ์๋ฅผ ๊ฐ์ง๋๋ค.
- mask๋ True/False๋ก ๊ตฌ์ฑ๋ Numpy Array(๋ฐฐ์ด)๋ก, Forward Propagation(์์ ํ)์ ์ ๋ ฅ์ธ x์ ์์ ๊ฐ์ด 0์ดํ์ธ index๋ True, ๊ทธ ์ธ(0๋ณด๋ค ํฐ ์์)๋ False๋ก ์ ์งํฉ๋๋ค.
- ์์ปจ๋ mask ๋ณ์๋ True/False๋ก ๊ตฌ์ฑ๋ Numpy ๋ฐฐ์ด์ ์ ์งํฉ๋๋ค.
Sigmoid ๊ณ์ธต
- Sigmoid ํจ์๋ ๋ค์ ์์ ์๋ฏธํฉ๋๋ค.
- ์์ ์์ ๊ณ์ฐ ๊ทธ๋ํ๋ก ๊ทธ๋ฆฌ๋ฉด ์๋์ ๊ทธ๋ฆผ์ฒ๋ผ ๋ฉ๋๋ค.
- 'x'์ '+' ๋ ธ๋๋ง๊ณ ๋, 'exp' ,'/' ๋ ธ๋๊ฐ ์๋๋ฐ, 'exp' ๋ ธ๋๋ y = exp(x) ๊ณ์ฐ์ ์ํํ๊ณ '/' ๋ ธ๋๋ y = 1/x ๊ณ์ฐ์ ์ํํฉ๋๋ค.
- ๊ณ์ฐ์ '๊ตญ์์ ๊ณ์ฐ'์ ์ ํ๋ก ์ด๋ค์ง๋๋ค. ์ด์ ์์ ๊ณ์ฐ ๊ทธ๋ํ์ Back Propagation(์ญ์ ํ)์ ํ๋ฆ์ ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ์ผ๋ก ํ ๋จ๊ณ์ฉ ์ถ์ด๋ณด๊ฒ ์ต๋๋ค.
1๋จ๊ณ
- '/' ๋ ธ๋, y = 1/x ์ ๋ฏธ๋ถํ๋ฉด ๋ค์ ์์ด ๋ฉ๋๋ค.
- Back Propagation(์ญ์ ํ) ๋๋ ์๋ฅ์์ ํ๋ฌ์จ ๊ฐ์ -y**2 (์์ ํ์ ์ถ๋ ฅ์ ์ ๊ณฑํ ํ ๋ง์ด๋์ค๋ฅผ ๋ถ์ธ ๊ฐ)์ ๊ณฑํด์ ํ๋ฅ๋ก ์ ๋ฌํฉ๋๋ค.
- ๊ณ์ฐ ๊ทธ๋ํ์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
2๋จ๊ณ
- '+'๋ ธ๋๋ ์๋ฅ์ ๊ฐ์ ์ฌ๊ณผ ์์ด ํ๋ฅ๋ก ๋ด๋ณด๋ด์ง๋๊ฒ ๋ค์ ๋๋ค.
3๋จ๊ณ
- 'exp' ๋ ธ๋๋ y = exp(x) ์ฐ์ฐ์ ์ํํ๋ฉฐ, ๊ทธ ๋ฏธ๋ถ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ๊ณ์ฐ ๊ทธ๋ํ์์๋ ์๋ฅ์ ๊ฐ์ Forward Propagation(์์ ํ) ๋์ ์ถ๋ต(์ด ์์์๋ exp(-x))์ ๊ณฑํด ํ๋ฅ๋ก ์ ํํฉ๋๋ค.
4๋จ๊ณ
- 'x'๋ ธ๋๋ Forward Propagation(์์ ํ) ๋์ ๊ฐ์ '์๋ก ๋ด๊ฟ' ๊ณฑํฉ๋๋ค. ์ฌ๊ธฐ์๋ -1๋ฅผ ๊ณฑํฉ๋๋ค.
- ์์ ๊ณ์ฐ ๊ทธ๋ํ๋ฅผ ๋ณด๋ฉด, Sigmoid ๊ณ์ธต์ Back Propagation(์ญ์ ํ)๋ฅผ ๊ณ์ฐ ๊ทธ๋ํ๋ฅผ ์์ฑํ์ต๋๋ค.
- ์ด๋ฌํ ๊ณ์ฐ ๊ทธ๋ํ์ ์ค๊ฐ ๊ณผ์ ์ ๋ชจ๋ ๋ฌถ์ด ๋จ์ํ 'Sigmoid' ๋ ธ๋ ํ๋๋ก ๋์ฒดํ ์ ์์ต๋๋ค.
- ๊ณ์ฐ ๊ทธ๋ํ์, ๊ฐ์ํ ๊ทธ๋ํ์ ๊ฐ์ํ ๋ฒ์ ์ ๊ฒฐ๊ณผ๋ ๊ฐ์ต๋๋ค.
- ๊ทธ๋ ์ง๋ง, ๊ฐ์ํ ๋ฒ์ ์ Back Propagation(์ญ์ ํ) ๊ณผ์ ์ ์ค๊ฐ ๊ณผ์ ์ ์๋ตํ์ฌ ๋ ํจ์จ์ ์ธ ๊ณ์ฐ์ด๋ผ๊ณ ํ ์ ์์ต๋๋ค.
- ๋ํ Node๋ฅผ ๊ทธ๋ฃนํ ํ์ฌ Sigmoid ๊ณ์ธต์ ์ธ์ธํ ๋ด์ฉ์ ๋ ธ์ถํ์ง ์๊ณ ์ ๋ ฅ, ์ถ๋ ฅ์๋ง ์ง์ค ํ ์ ์๋ค๋ ๊ฒ๋ ์ข์ ํฌ์ธํธ ์ ๋๋ค.
- ์ด์ฒ๋ผ Sigmoid ๊ณ์ธต์ Back Propagation(์ญ์ ํ)๋ Forward Progagation(์์ ํ)์ ์ถ๋ ฅ(y)๋ง์ผ๋ก ๊ณ์ฐํ ์ ์์ต๋๋ค.
- ๊ทธ๋ฌ๋ฉด ํ๋ฒ Sigmoid ๊ณ์ธต์ Python์ผ๋ก ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค.
- ์ฌ๊ธฐ์๋ Forward Progagation(์์ ํ)์ ์ถ๋ ฅ์ ์ธ์คํด์ค ๋ณ์ out์ ๋ณด๊ดํ๋ค๊ฐ, Back Propagation(์ญ์ ํ)๋ ๊ทธ ๊ฐ์ ์ฌ์ฉํฉ๋๋ค.
class Sigmoid:
def __init__(self):
self.out = None # ์์ ํ์ ์ถ๋ ฅ๊ฐ์ ์ ์ฅํ๊ธฐ ์ํ ๋ณ์๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
def forward(self, x):
out = 1 / (1 + np.exp(-x)) # ์๊ทธ๋ชจ์ด๋ ํจ์๋ฅผ ์ ์ฉํฉ๋๋ค.
self.out = out # ์์ ํ์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํฉ๋๋ค. ์ด ๊ฐ์ ์ญ์ ํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
return out # ํ์ฑํ ํจ์๋ฅผ ์ ์ฉํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
def backward(self, dout):
dx = dout * (1.0 - self.out) * self.out # ์๊ทธ๋ชจ์ด๋ ํจ์์ ๋ฏธ๋ถ์ ์ ์ฉํฉ๋๋ค.
return dx # ์
๋ ฅ๊ฐ์ ๋ํ ๋ฏธ๋ถ๊ฐ์ ๋ฐํํฉ๋๋ค.
# dout์ ์๋ฅ(๋ค์ ๊ณ์ธต)์์ ๋์ด์จ ๋ฏธ๋ถ๊ฐ์
๋๋ค.
# ์๊ทธ๋ชจ์ด๋ ํจ์์ ๋ฏธ๋ถ์ y(1-y)์ด๋ฉฐ, ์ฌ๊ธฐ์ y๋ ์๊ทธ๋ชจ์ด๋ ํจ์์ ์ถ๋ ฅ๊ฐ์
๋๋ค.
# ๋ฐ๋ผ์, self.out์ด y์ ํด๋นํ๊ณ , (1.0 - self.out) * self.out์ด y(1-y)์ ํด๋นํฉ๋๋ค.
# ์ด๋ฅผ ์๋ฅ์์ ๋์ด์จ ๋ฏธ๋ถ๊ฐ๊ณผ ๊ณฑํ์ฌ ์ด ๊ณ์ธต์ ํต๊ณผํ ๋์ ๋ฏธ๋ถ๊ฐ์ ๊ตฌํฉ๋๋ค.
Affine ๊ณ์ธต
์ ๊ฒฝ๋ง์ Forward Propagation(์์ ํ)์์๋ Weight(๊ฐ์ค์น) ์ ํธ์ ์ดํฉ์ ๊ณ์ฐํ๊ธฐ ๋๋ฌธ์ ํ๋ ฌ์ ๊ณฑ(Numpy์์๋ np.dot())์ ์ฌ์ฉํ์ต๋๋ค.
- Neuron(๋ด๋ฐ)์ Weight(๊ฐ์ค์น) ํฉ์ Y = np.dot(X, W) + B์ฒ๋ผ ๊ณ์ฐํฉ๋๋ค.
- ๊ทธ๋ฆฌ๊ณ ์ด Y๋ฅผ Activation Function(ํ์ฑํ ํจ์)๋ก ๋ณํํด ๋ค์ Layer(์ธต)์ผ๋ก ์ ํํ๋ ๊ฒ์ด ์ ๊ฒฝ๋ง Forward Propagation(์์ ํ)์ ํ๋ฆ์ด์์ต๋๋ค.
- ํ๋ ฌ์ ๊ณฑ ๊ณ์ฐ์ ๋์ํ๋ Dimension(์ฐจ์)์ ์์ ์๋ฅผ ์ผ์น์ํค๋๊ฒ ํต์ฌ์ ๋๋ค. ํ๋ ฌ์ ํ์์ (2, 3)์ฒ๋ผ ๊ดํธ๋ก ํ๊ธฐํ๋ ์ด๋ด๋ Numpy shapeํจ์์ Output(์ถ๋ ฅ) & ํํ๋ฅผ ํต์ผํ๊ธฐ ์ํด์ ์ ๋๋ค.
์ ๊ฒฝ๋ง์ Forward Propagation(์์ ํ) ๋ ์ํํ๋ ํ๋ ฌ์ ๊ณฑ์ ๊ธฐํํ์์ Affine Transformation(์ดํ์ธ ๋ณํ)์ด๋ผ๊ณ ํฉ๋๋ค.
- ๊ทธ๋ฌ๋ฉด ํ๋ ฌ์ ๊ณฑ๊ณผ Bias(ํธํฅ)์ ํฉ์ ๊ณ์ฐ ๊ทธ๋ํ๋ก ํ๋ฒ ๊ทธ๋ ค๋ณด๊ฒ ์ต๋๋ค.
- ๊ณฑ์ ๊ณ์ฐํ๋ ๋ ธ๋๋ฅผ 'dot'์ด๋ผ ํ๋ฉด np.dot(X, W) + B ๊ณ์ฐ์ ์๋์ ๊ทธ๋ํ์ฒ๋ผ ๊ทธ๋ ค์ง๋๋ค.
- ์ฐธ๊ณ ๋ก ์ง๊ธ๊น์ง์ ๊ณ์ฐ ๊ทธ๋ํ๋ ๋ ธ๋ ์ฌ์ด์ '์ค์นผ๋ผ ๊ฐ'์ด ํ๋ ๋๋ฐ ๋ฐํด, ์ด ์์์๋ 'ํ๋ ฌ'์ด ํ๋ฅด๊ณ ์์ต๋๋ค.
- ๊ทธ๋ฌ๋ฉด ์ด๋ฒ์๋ Back propagation(์ญ์ ํ)์ ๋ํด ์๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
- ํ๋ ฌ์ ์ฌ์ฉํ Back propagation(์ญ์ ํ)๋ ํ๋ ฌ์ ์์๋ง๋ค ์ ๊ฐํด๋ณด๋ฉด ์ค์นผ๋ผ ๊ฐ์ ์ฌ์ฉํ ์ง๊ธ๊น์ง์ ๊ณ์ฐ ๊ทธ๋ํ์ ๊ฐ์ ์์๋ก ์๊ฐํ ์ ์์ต๋๋ค.
- WT์ T๋ ์ ์นํ๋ ฌ์ ๋ปํ๋ฉฐ, W์ (i, j) ์์น์ ์์๋ฅผ (j,i) ์์น๋ก ๋ด๊พผ๊ฒ์ ๋งํฉ๋๋ค.
- ๊ณ์ฐ๊ทธ๋ํ์์ ๊ฐ ๋ณ์์ ํ์์ ์ฃผ์ํด์ ์ดํด ๋ด์ผ ํฉ๋๋ค.
- ํนํ X์ δL/δX์ ๊ฐ์ ํ์์ด๊ณ , W์ δL/δW๋ ๊ฐ์ ํ์์ด๋ผ๋ ๊ฒ์ ๊ธฐ์ตํ์ธ์.
- ๊ทผ๋ฐ, ์ฌ๊ธฐ์ ์๋ฌธ์ด ๋๋๊ฒ ์์ต๋๋ค. ์ ํ๋ ฌ์ ํ์์ ์ฃผ์๋ฅผ ํด์ผ ํ ๊น์?
- ํ๋ ฌ์ ๊ณฑ์์ ๋์ํ๋ ์ฐจ์์ ์์ ์๋ฅผ ์ผ์น์์ผ์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋ฐฐ์น์ฉ Affine ๊ณ์ธต
- Affine ๊ณ์ธต์ ์ ๋ ฅ ๋ฐ์ดํฐ๋ก X ํ๋๋ง์ ๊ณ ๋ คํ ๊ฒ์ด์์ต๋๋ค.
- ์ด๋ฒ ์ ์์๋ ๋ฐ์ดํฐ N๊ฐ๋ฅผ ๋ฌถ์ด Forward Propagation(์์ ํ)ํ๋ ๊ฒฝ์ฐ, ์ฆ, ๋ฐฐ์น์ฉ Affine ๊ณ์ธต์ ์๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
- ์ฌ๊ธฐ์ ๋ฌถ์ ๋ฐ์ดํฐ๋ฅผ '๋ฐฐ์น'๋ผ๊ณ ๋ถ๋ฆ ๋๋ค.
- ๊ธฐ์กด๊ณผ ๋ค๋ฅธ ๋ถ๋ถ์ input(์ ๋ ฅ)์ธ X์ ํ์์ด (N, 2)๊ฐ ๋ ๊ฒ ๋ฟ์ ๋๋ค. ๊ทธ ๋ค๋ก๋ ์ง๊ธ๊น์ง์ ๊ฐ์ด ๊ณ์ฐ ๊ทธ๋ํ์ ์์๋ฅผ ๋ฐ๋ผ ์์ํ ํ๋ ฌ ๊ณ์ฐ์ ํฉ๋๋ค.
- ๋ํ Back propagation(์ญ์ ํ) ๋๋ ํ๋ ฌ์ ํ์์ ์ฃผ์ํ๋ฉด δL/δX๊ณผ δL/δW์ ์ด์ ๊ณผ ๊ฐ์ด ๋์ถํ ์ ์์ต๋๋ค.
- ํธํญ์ ๋ํ ๋๋ ์ฃผ์ํด์ผ ํฉ๋๋ค. Forward Propagation(์์ ํ)์ Bias(ํธํฅ) ๋ง์ ์ X, W์ ๋ํ Bias(ํธํฅ)์ด ๊ฐ๊ฐ์ ๋ฐ์ดํฐ์ ๋ํด์ง๋๋ค.
- ๊ทธ๋์ Back propagation(์ญ์ ํ) ๋๋ ๊ฐ ๋ฐ์ดํฐ์ Back propagation(์ญ์ ํ)๊ฐ์ด Bias(ํธํฅ)์ ์์์ ๋ชจ์ฌ์ผ ํฉ๋๋ค.
- ์ด๋ ๊ฒ Affine ๊ณ์ธต์ ์ด๋ ๊ฒ ๊ตฌํ ํ ์ ์์ต๋๋ค.
class Affine:
def __init__(self, W, b):
self.W = W # ๊ฐ์ค์น(weight)๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
self.b = b # ํธํฅ(bias)์ ์ด๊ธฐํํฉ๋๋ค.
self.x = None # ์
๋ ฅ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ ์ํ ๋ณ์๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
self.dW = None # ๊ฐ์ค์น์ ๊ธฐ์ธ๊ธฐ๋ฅผ ์ ์ฅํ๊ธฐ ์ํ ๋ณ์๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
self.db = None # ํธํฅ์ ๊ธฐ์ธ๊ธฐ๋ฅผ ์ ์ฅํ๊ธฐ ์ํ ๋ณ์๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
def forward(self, x):
self.x = x # ์
๋ ฅ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํฉ๋๋ค.
out = np.dot(x, self.W) + self.b # ์
๋ ฅ ๋ฐ์ดํฐ์ ๊ฐ์ค์น์ ๋ด์ ์ ๊ณ์ฐํ๊ณ ํธํฅ์ ๋ํฉ๋๋ค.
return out # ๊ณ์ฐ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
def backward(self, dout):
dx = np.dot(dout, self.W.T) # ์๋ฅ์์ ๋์ด์จ ๋ฏธ๋ถ๊ฐ์ ๊ฐ์ค์น์ ์ ์น๋ฅผ ๊ณฑํ์ฌ ์
๋ ฅ ๋ฐ์ดํฐ์ ๋ํ ๋ฏธ๋ถ๊ฐ์ ๊ณ์ฐํฉ๋๋ค. (์คํ ์์ : np.dout -> np.dot, xelf.W.T -> self.W.T)
self.dW = np.dot(self.x.T, dout) # ์
๋ ฅ ๋ฐ์ดํฐ์ ์ ์น์ ์๋ฅ์์ ๋์ด์จ ๋ฏธ๋ถ๊ฐ์ ๊ณฑํ์ฌ ๊ฐ์ค์น์ ๋ํ ๋ฏธ๋ถ๊ฐ์ ๊ณ์ฐํฉ๋๋ค.
self.db = np.sum(dout, axis=0) # ์๋ฅ์์ ๋์ด์จ ๋ฏธ๋ถ๊ฐ์ ์ถ(axis) 0์ ๋ฐ๋ผ ํฉ์ฐํ์ฌ ํธํฅ์ ๋ํ ๋ฏธ๋ถ๊ฐ์ ๊ณ์ฐํฉ๋๋ค.
return dx # ์
๋ ฅ ๋ฐ์ดํฐ์ ๋ํ ๋ฏธ๋ถ๊ฐ์ ๋ฐํํฉ๋๋ค.
Softmax-with-Loss ๊ณ์ธต
์ถ๋ ฅ์ธต์์ ์ฌ์ฉํ๋ Softmax ํจ์์ ๊ดํด ์ค๋ช ํ๊ฒ ์ต๋๋ค.
- Softmax ํจ์๋ ์
๋ ฅ ๊ฐ์ ์ ๊ทํํ์ฌ ์ถ๋ ฅํฉ๋๋ค. ์๋ฅผ ๋ค์ด์ Mnist ๋ฐ์ดํฐ์
์ ํ์ฉํ ์๊ธ์จ ์ซ์ ์ธ์์์์ Softmax ๊ณ์ธต์ ์ถ๋ ฅ์ ์๋์ ๊ทธ๋ฆผ์ฒ๋ผ ๋ฉ๋๋ค.
- Input Image๊ฐ Affine ๊ณ์ธต, ReLU ๊ณ์ธต์ ํต๊ณผํ์ฌ ๋ณํ๋๊ณ , ๋ง์ง๋ง Softmax ๊ณ์ธต์ ์ํด์ 10๊ฐ์ ์ ๋ ฅ์ด ์ ๊ทํ ๋ฉ๋๋ค.
- ์ด ๊ทธ๋ฆผ์์๋ ์ซ์ '0'์ ์ ์๋ 5.3์ด๋ฉฐ, ์ด๊ฒ์ด Softmax ๊ณ์ธต์ ์ํด์ 0.008(0.8%)๋ก ๋ณํ๋ฉ๋๋ค.
- ๋ํ '2'์ ์ ์๋ 10.1์์ 0.991(99.1%)๋ก ๋ณํ๋ฉ๋๋ค.
- Softmax ๊ณ์ธต์ ์ ๋ ฅ ๊ฐ์ ์ ๊ทํ(์ถ๋ ฅ์ ํฉ์ด 1์ด ๋๋ก๋ก ๋ณํ)ํ์ฌ ์ถ๋ ฅํฉ๋๋ค.
- ๊ทธ๋ฆฌ๊ณ ์๊ธ์จ ์ซ์๋ 10๊ฐ(Class 10๊ฐ๋ก ๋ถ๋ฅ)์ด๋ฏ๋ก Softmax ๊ณ์ธต์ ์ ๋ ฅ์ 10๊ฐ๊ฐ ๋ฉ๋๋ค.
์ ๊ฒฝ๋ง์์ ์ํํ๋ ์์ ์ ํ์ต, ์ถ๋ก 2๊ฐ์ง ์ธ๋ฐ, ์ถ๋ก ํ ๋์ ์ผ๋ฐ์ ์ผ๋ก Softmax ๊ณ์ธต์ ์ฌ์ฉํ์ง ์์ต๋๋ค.
์ ๊ฒฝ๋ง์ ์ถ๋ก ํ ๋ ๋ง์ง๋ง Affine ๊ณ์ธต์ ์ถ๋ ฅ์ ์ธ์ ๊ฒฐ๊ณผ๋ก ์ด์ฉํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ ๊ฒฝ๋ง์์ ์ ๊ทํ ํ์ง ์๋ ์ถ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ Score(์ ์)๋ผ๊ณ ํฉ๋๋ค.
์ฆ, ์ ๊ฒฝ๋ง ์ถ๋ก ์์ ๋ต์ ํ๋๋ง ๋ด๋ ๊ฒฝ์ฐ์๋ ๊ฐ์ฅ ๋์ Score(์ ์)๋ง ์๋ฉด ๋๋, Softmax ๊ณ์ธต์ด ํ์ ์์ต๋๋ค.
๋ค๋ง, ์ ๊ฒฝ๋ง์ ํ์ตํ ๋์๋ Softmax ๊ณ์ธต์ด ํ์ํฉ๋๋ค.
- ๊ทธ๋ฌ๋ฉด ์ด์ Softmax ๊ณ์ธต์ ํ๋ฒ ๋ณด๊ฒ ์ต๋๋ค. Loss Function(์์ค ํจ์)์ธ Cross-Entropy Error(๊ต์ฒด ์ํธ๋กํผ ์ค์ฐจ)๋ ํฌํจํ์ฌ, 'Softmax-with-Loss ๊ณ์ธต'์ด๋ผ๋ ์ด๋ฆ์ผ๋ก ๊ตฌํํฉ๋๋ค.
- ๋ณด์๋ค ์ํผ, Softmax-with-Loss ๊ณ์ธต์ ๋ณต์กํฉ๋๋ค. ์ฌ๊ธฐ์๋ ๊ฒฐ๊ณผ๋ง ํ๋ฒ ๋ณด๊ฒ ์ต๋๋ค.
- ์์ ๊ณ์ฐ ๊ทธ๋ํ์์ ์ํํธ๋งฅ์ ํจ์๋ 'Softmax" ๊ณ์ธต์ผ๋ก, Cross-Entropy Error'๊ณ์ธต์ผ๋ก ํ๊ธฐํ์ต๋๋ค.
- ์ฌ๊ธฐ์ 3๊ฐ์ ํด๋์ค ๋ถ๋ฅ๋ฅผ ๊ฐ์ ํ๊ณ ์ด์ Layer(๊ณ์ธต)์์ 3๊ฐ์ ์ ๋ ฅ(Score)๋ฅผ ๋ฐ์ต๋๋ค.
- ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด Softmax ๊ณ์ธต์ ์ ๋ ฅ (a1, a2, a3)๋ฅผ ์ ๊ทํํ์ฌ (y1, y2, y3)๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
- Cross-Entropy Error ๊ณ์ธต์ Softmax ๊ณ์ธต์ ์ถ๋ ฅ (y1, y2, y3)์ ์ ๋ต ๋ ์ด๋ธ (t1, t2, t3)๋ฅผ ๋ฐ๊ณ , ์ด ๋ฐ์ดํฐ๋ก๋ถํฐ Loss(์์ค) L์ ์ถ๋ ฅํฉ๋๋ค.
- ๊ฐ์ํ๋ Softmax-with-Loss ๊ณ์ธต์ ๊ณ์ฐ ๊ทธ๋ํ์์ ์ฃผ๋ชฉํ ๊ฑด Back propagation(์ญ์ ํ)์ ๊ฒฐ๊ณผ์ ๋๋ค.
- Softmax ๊ณ์ธต์ Back propagation(์ญ์ ํ)๋ (y1 - t1, y2- t2, y3 - t3)๋ผ๋ '๋ง๋ํ' ๊ฒฐ๊ณผ๋ฅผ ๋ด๋๊ณ ์์ต๋๋ค.
- (y1 ~ y3)๋ Softmax ๊ณ์ธต์ ์ถ๋ ฅ์ด๊ณ , (t1 ~ t3)๋ ์ ๋ต ๋ ์ด๋ธ ์ด๋ฏ๋ก, (y1 - t1, y2- t2, y3 - t3)๋ Softmax ๊ณ์ธต์ ์ถ๋ ฅ๊ณผ ์ ๋ต ๋ ์ด๋ธ์ ์ฐจ๋ถ์ธ๊ฒ์ ๋๋ค.
- ์ ๊ฒฝ๋ง์ Back propagation(์ญ์ ํ)๋ ์ด ์ฐจ์ด์ธ ์ค์ฐจ๊ฐ ์ ๊ณ์ธต์ ์ ํด์ง๋ ๊ฒ์ ๋๋ค.
- ์ด๊ฒ์ด ์ ๊ฒฝ๋ง ํ์ต์ ์ค์ํ ์ฑ์ง์ ๋๋ค.
- ๊ทธ๋ฌ๋ฉด Softmax-with-Loss ๊ณ์ธต์ ๊ตฌํํ ์ฝ๋๋ฅผ ๋ณด๊ฒ ์ต๋๋ค.
Softmax-with-Loss Example Code (by Python)
class SoftmaxWithLoss:
def __init__(self):
self.loss = None # ์์ค
self.y = None # softmax์ ์ถ๋ ฅ
self.t = None # ์ ๋ต ๋ ์ด๋ธ(์-ํซ ๋ฒกํฐ)
def forward(self, x, t):
self.t = t
self.y = softmax(x) # ์
๋ ฅ x์ ๋ํด softmax ํจ์๋ฅผ ์ ์ฉํฉ๋๋ค.
self.loss = cross_entropy_error(self.y, self.t
# softmax์ ์ถ๋ ฅ๊ณผ ์ ๋ต ๋ ์ด๋ธ์ ์ด์ฉํด ํฌ๋ก์ค ์ํธ๋กํผ ์ค์ฐจ๋ฅผ ๊ณ์ฐํฉ๋๋ค.
return self.loss # ๊ณ์ฐ๋ ์์ค์ ๋ฐํํฉ๋๋ค.
def backward(self, dout=1):
batch_size = self.t.shape[0] # ๋ฐฐ์น ํฌ๊ธฐ๋ฅผ ๊ตฌํฉ๋๋ค.
dx = (self.y - self.t) / batch_size
# ์์ค ํจ์์ ๋ฏธ๋ถ์ ๊ณ์ฐํฉ๋๋ค. ์ฌ๊ธฐ์ dout=1์ ์์ค ํจ์์ ๋ฏธ๋ถ๊ฐ์ด 1์ด๋ผ๊ณ ๊ฐ์ ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
return dx # ์
๋ ฅ๊ฐ์ ๋ํ ๋ฏธ๋ถ๊ฐ์ ๋ฐํํฉ๋๋ค.
- ์ฃผ์ํด์ผ ํ๋์ ์ Back propagation(์ญ์ ํ) ๋๋ ์ ํํ๋ ๊ฐ์ Batch_size๋ก ๋๋ ์ ๋ฐ์ดํฐ 1๊ฐ๋น ์ค์ฐจ๋ฅผ ์ Layer(๊ณ์ธต)์ผ๋ก ์ ํํฉ๋๋ค.
Backprogagation(์ค์ฐจ์ญ์ ํ)๋ฒ ๊ตฌํํ๊ธฐ
์ ๊ฒฝ๋ง ํ์ต์ ์ ์ฒด์ ์ธ Flow
๋ค์ ํ๋ฒ ์ ๊ฒฝ๋ง ํ์ต์ ์์๋ฅผ ํ๋ฒ ๋ณด๊ฒ ์ต๋๋ค.
์ ์
- ์ ๊ฒฝ๋ง์๋ ์ ์ ๊ฐ๋ฅํ Weight(๊ฐ์ค์น)์ Bias(ํธํฅ)์ด ์๊ณ , ์ด Weight(๊ฐ์ค์น)์ Bias(ํธํฅ)์ Training Data(ํ๋ จ ๋ฐ์ดํฐ)์ ์ ์ํ๋๋ก ์กฐ์ ํ๋ ๊ณผ์ ์ Training(ํ์ต)์ด๋ผ๊ณ ํฉ๋๋ค.
- ๊ทธ๋ฆฌ๊ณ Neural Network Training(์ ๊ฒฝ๋ง ํ์ต)์ 4๋จ๊ณ๋ก ์ํํ ์ ์์ต๋๋ค.
1๋จ๊ณ - Mini-Batch
- ํ๋ จ ๋ฐ์ดํฐ ์ค ์ผ๋ถ๋ฅผ ๋ฌด์์๋ก ๊ฐ์ ธ์ต๋๋ค. ์ด๋ ๊ฒ ์ ๋ณํ ๋ฐ์ดํฐ๋ฅผ Mini-Batch(๋ฏธ๋๋ฐฐ์น) ๋ผ๊ณ ํฉ๋๋ค.
- ๊ทธ๋ฆฌ๊ณ ๊ทธ Mini-Batch(๋ฏธ๋๋ฐฐ์น)์ Loss Function Value(์์ค ํจ์ ๊ฐ)์ ์ค์ด๋ ๊ฒ์ด ๋ชฉํ์ ๋๋ค.
2๋จ๊ณ - Gradient(๊ธฐ์ธ๊ธฐ) ์ฐ์ถ
- Mini-Batch์ Loss Function ๊ฐ์ ์ค์ด๊ธฐ ์ํด์ ๊ฐ Weight Paraemter(๊ฐ์ค์น ๋งค๊ฐ๋ณ์)์ Gradient(๊ธฐ์ธ๊ธฐ)๋ฅผ ๊ตฌํฉ๋๋ค.
- Gradient(๊ธฐ์ธ๊ธฐ)๋ Loss Function Value(์์ค ํจ์ ๊ฐ)์ ๊ฐ์ฅ ์๊ฒ ํ๋ ๋ฐฉํฅ์ ์ ์ํฉ๋๋ค.
3๋จ๊ณ - Parameter(๋งค๊ฐ๋ณ์) ๊ฐฑ์
- Weight Paraemter(๊ฐ์ค์น ๋งค๊ฐ๋ณ์)๋ฅผ Gradient(๊ธฐ์ธ๊ธฐ) ๋ฐฉํฅ์ผ๋ก ์์ฃผ ์กฐ๊ธ ๊ฐฑ์ ํฉ๋๋ค.
4๋จ๊ณ - ๋ฐ๋ณต
- 1~3๋จ๊ณ๋ฅผ ๋ฐ๋ณตํฉ๋๋ค.
- ์ฌ๊ธฐ์ ์ค์ฐจ์ญ์ ํ๋ฒ์ด ๋ฑ์ฅํ๋ ๋จ๊ณ๋ 2๋จ๊ณ์ธ 'Gradient(๊ธฐ์ธ๊ธฐ)์ฐ์ถ' ์ ๋๋ค.
- ์์์๋ ์ด Gradient(๊ธฐ์ธ๊ธฐ)๋ฅผ ๊ตฌํ๊ธฐ ์ํด์ ์์น ๋ฏธ๋ถ์ ์ฌ์ฉํ์ง๋ง, ์ค์ฐจ์ญ์ ํ๋ฒ์ ์ด์ฉํ๋ฉด Gradient(๊ธฐ์ธ๊ธฐ)๋ฅผ ํจ์จ์ , ๋น ๋ฅด๊ฒ ๊ตฌํ ์ ์์ต๋๋ค.
์ค์ฐจ์ญ์ ํ๋ฒ์ ์ด์ฉํ ์ ๊ฒฝ๋ง ๊ตฌํํ๊ธฐ
์ฌ๊ธฐ์ 2์ธต ์ ๊ฒฝ๋ง์ TwoLayerNet ํด๋์ค๋ก ๊ตฌํํฉ๋๋ค. ํ๋ฒ ํด๋์ค & ์ธ์คํด์ค ๋ณ์ ๋ฐ Method๋ฅผ ์ ์ํ ํ๋ค์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
- ์์์ผ ํ ์ ์, Layer(๊ณ์ธต)์ ์ฌ์ฉํ๋ค๋ ์ ์ ๋๋ค.
- Layer(๊ณ์ธต)์ ์ฌ์ฉํจ์ผ๋ก์จ ์ธ์ ๊ฒฐ๊ณผ๋ฅผ ์ป๋ ์ฒ๋ฆฌ(predict())์ Gradient(๊ธฐ์ธ๊ธฐ)๋ฅผ ๊ตฌํ๋ ์ฒ๋ฆฌ (gradient()) ๊ณ์ธต์ ์ ํ๋ง์ผ๋ก ๋์์ด ์ด๋ฃจ์ด ์ง๋๋ค.
# coding: utf-8
import sys, os
sys.path.append(os.pardir) # ๋ถ๋ชจ ๋๋ ํฐ๋ฆฌ์ ํ์ผ์ ๊ฐ์ ธ์ฌ ์ ์๋๋ก ์ค์
import numpy as np
from common.layers import *
from common.gradient import numerical_gradient
from collections import OrderedDict
class TwoLayerNet:
def __init__(self, input_size, hidden_size, output_size, weight_init_std = 0.01):
# ๊ฐ์ค์น ์ด๊ธฐํ
self.params = {}
self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
self.params['b1'] = np.zeros(hidden_size)
self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
self.params['b2'] = np.zeros(output_size)
# ๊ณ์ธต ์์ฑ
self.layers = OrderedDict()
self.layers['Affine1'] = Affine(self.params['W1'], self.params['b1'])
self.layers['Relu1'] = Relu()
self.layers['Affine2'] = Affine(self.params['W2'], self.params['b2'])
self.lastLayer = SoftmaxWithLoss()
def predict(self, x):
for layer in self.layers.values():
x = layer.forward(x)
return x
# x : ์
๋ ฅ ๋ฐ์ดํฐ, t : ์ ๋ต ๋ ์ด๋ธ
def loss(self, x, t):
y = self.predict(x)
return self.lastLayer.forward(y, t)
def accuracy(self, x, t):
y = self.predict(x)
y = np.argmax(y, axis=1)
if t.ndim != 1 : t = np.argmax(t, axis=1)
accuracy = np.sum(y == t) / float(x.shape[0])
return accuracy
# x : ์
๋ ฅ ๋ฐ์ดํฐ, t : ์ ๋ต ๋ ์ด๋ธ
def numerical_gradient(self, x, t):
loss_W = lambda W: self.loss(x, t)
grads = {}
grads['W1'] = numerical_gradient(loss_W, self.params['W1'])
grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
grads['W2'] = numerical_gradient(loss_W, self.params['W2'])
grads['b2'] = numerical_gradient(loss_W, self.params['b2'])
return grads
def gradient(self, x, t):
# forward
self.loss(x, t)
# backward
dout = 1
dout = self.lastLayer.backward(dout)
layers = list(self.layers.values())
layers.reverse()
for layer in layers:
dout = layer.backward(dout)
# ๊ฒฐ๊ณผ ์ ์ฅ
grads = {}
grads['W1'], grads['b1'] = self.layers['Affine1'].dW, self.layers['Affine1'].db
grads['W2'], grads['b2'] = self.layers['Affine2'].dW, self.layers['Affine2'].db
return grads
- ์ธ์๋ ์ฐจ๋ก๋๋ก ์ ๋ ฅ์ธต ๋ด๋ฐ ์, ์๋์ธต ๋ด๋ฐ ์, ์ถ๋ ฅ์ธต ๋ด๋ฐ ์, ๊ฐ์ค์น ์ด๊ธฐํ ์ ์ ๊ท๋ถํฌ์ ์ค์ผ์ผ์ ๋๋ค.
- OrderedDict๋ ์์๊ฐ ์๋ ๋์ ๋๋ฌ ์ ๋๋ค. '์์๊ฐ ์๋' ๋์ ๋๋ฆฌ์ ์ถ๊ฐํ ์์๋ฅผ ๊ธฐ์ตํ๋ค๋ ๊ฒ์ ๋๋ค.
- ๊ทธ๋์ Forward Propagation(์์ ํ) ๋๋ ์ถ๊ฐํ ์์๋๋ก ๊ฐ Layer(๊ณ์ธต)์ forward() Method๋ฅผ ํธ์ถํ๋ฉด ์ฒ๋ฆฌ๊ฐ ๋ฉ๋๋ค.
- Back Propagation(์ญ์ ํ)๋์๋ Layer(๊ณ์ธต)์ ๋ฐ๋ ์์๋ก ํธ์ถ ํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
- Affine, ReLU ๊ณ์ธต์ด ๊ฐ์์ ๋ด๋ถ์์ Forward Propagation(์์ ํ), Back Propagation(์ญ์ ํ)๋ฅผ ์ฒ๋ฆฌํ๊ณ ์์ผ๋๊น, ๊ทธ๋ฅ ๊ณ์ธต์ ์ฌ๋ฐ๋ฅธ ์์๋ก ์ฐ๊ฒฐํ ํ ํธ์ถํด์ฃผ๋ฉด ๋์ ๋๋ค.
Gradient(๊ธฐ์ธ๊ธฐ) ๊ฒ์ฆํ๊ธฐ
- ํฌ๊ฒ 2๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
- ์์น ๋ฏธ๋ถ์ ์จ์ Gradient(๊ธฐ์ธ๊ธฐ)๋ฅผ ๊ตฌํ๋ ๋ฐฉ๋ฒ, ํด์์ ์ผ๋ก ์์์ ํ์ด์ Gradient(๊ธฐ์ธ๊ธฐ)๋ฅผ ๊ตฌํ๋ ๋ฐฉ๋ฒ 2๊ฐ์ง๊ฐ ์์ต๋๋ค.
- ์์์ ํ์ด์ ๊ตฌํ๋ ๋ฐฉ๋ฒ์ ์ค์ฐจ์ญ์ ํ๋ฒ์ ์ฌ์ฉํด์ ๋งค๊ฐ๋ณ์๊ฐ ๋ง์๋ ํจ์จ์ ์ผ๋ก ๊ณ์ฐ์ด ๊ฐ๋ฅํฉ๋๋ค.
- ์ฌ๊ธฐ์ ์์น ๋ฏธ๋ถ์ ์ค์ฐจ์ญ์ ํ๋ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋น๊ตํ์ฌ ์ ๋๋ก ๊ตฌํํ๋์ง ๊ฒ์ฆํ๋ ๊ณผ์ ์ ๊ฑฐ์นฉ๋๋ค.
- ์ด ๊ฒ์ฆํ๋ ์์ ์ '๊ธฐ์ธ๊ธฐ ํ์ธ(Gradient Check)'๋ผ๊ณ ํฉ๋๋ค.
# coding: utf-8
import sys, os
sys.path.append(os.pardir) # ๋ถ๋ชจ ๋๋ ํฐ๋ฆฌ์ ํ์ผ์ ๊ฐ์ ธ์ฌ ์ ์๋๋ก ์ค์
import numpy as np
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet
# ๋ฐ์ดํฐ ์ฝ๊ธฐ
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)
x_batch = x_train[:3]
t_batch = t_train[:3]
grad_numerical = network.numerical_gradient(x_batch, t_batch)
grad_backprop = network.gradient(x_batch, t_batch)
# ๊ฐ ๊ฐ์ค์น์ ์ฐจ์ด์ ์ ๋๊ฐ์ ๊ตฌํ ํ, ๊ทธ ์ ๋๊ฐ๋ค์ ํ๊ท ์ ๋ธ๋ค.
for key in grad_numerical.keys():
diff = np.average( np.abs(grad_backprop[key] - grad_numerical[key]) )
print(key + ":" + str(diff))
# Result
W2:9.71260696544e-13
b2:1.20570232964e-10
W1:2.86152966578e-13
b1:1.19419626098e-12
์์น ๋ฏธ๋ถ๊ณผ ์ค์ฐจ์ญ์ ํ๋ฒ์ผ๋ก ๊ตฌํ ๊ธฐ์ธ๊ธฐ์ ์ฐจ์ด๊ฐ ๋งค์ฐ ์๋ค.
์ค์ ์์ด ๊ตฌํ๋์์ ํ๋ฅ ์ด ๋๋ค.
์ ๋ฐ๋๊ฐ ์ ํํ๊ธฐ ๋๋ฌธ์ ์ค์ฐจ๊ฐ 0์ด ๋์ง๋ ์๋๋ค.
์ค์ฐจ์ญ์ ํ๋ฒ์ ์ด์ฉํ ํ์ต ๊ตฌํํ๊ธฐ
์ง๊ธ๊น์ง์ ๋ค๋ฅธ ๋ถ๋ถ์ Grdient(๊ธฐ์ธ๊ธฐ)๋ฅผ ์ค์ฐจ์ญ์ ํ๋ฒ์ผ๋ก ๊ตฌํ๋ค๋ ์ ๋ฟ์ ๋๋ค.
# coding: utf-8
import sys, os
sys.path.append(os.pardir)
import numpy as np
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet
# ๋ฐ์ดํฐ ์ฝ๊ธฐ
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)
# hyperparameter
iters_num = 10000 # ๋ฐ๋ณตํ์
train_size = x_train.shape[0]
batch_size = 100 # ๋ฏธ๋๋ฐฐ์น ํฌ๊ธฐ
learning_rate = 0.1
train_loss_list = []
train_acc_list = []
test_acc_list = []
# 1 epoch๋น ๋ฐ๋ณตํ๋ ํ์
iter_per_epoch = max(train_size / batch_size, 1)
for i in range(iters_num):
# ๋ฏธ๋๋ฐฐ์น ํ๋
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
# ์ค์ฐจ์ญ์ ํ๋ฒ์ผ๋ก ๊ธฐ์ธ๊ธฐ ๊ณ์ฐ (๋ณ๊ฒฝํ ๋ถ๋ถ)
#grad = network.numerical_gradient(x_batch, t_batch) # ์์น ๋ฏธ๋ถ ๋ฐฉ์
grad = network.gradient(x_batch, t_batch) # ์ค์ฐจ์ญ์ ํ๋ฒ ๋ฐฉ์(ํจ์ฌ ๋น ๋ฅด๋ค)
# ๋งค๊ฐ๋ณ์ ๊ฐฑ์
for key in ('W1', 'b1', 'W2', 'b2'):
network.params[key] -= learning_rate * grad[key]
# ํ์ต ๊ฒฝ๊ณผ ๊ธฐ๋ก
loss = network.loss(x_batch, t_batch)
train_loss_list.append(loss)
# 1epoch ๋น accuray ๊ณ์ฐ
if i % iter_per_epoch == 0:
train_acc = network.accuracy(x_train, t_train)
test_acc = network.accuracy(x_test, t_test)
train_acc_list.append(train_acc)
test_acc_list.append(test_acc)
print(train_acc, test_acc)
# Result
"""
train acc, test acc | 0.0992833333333, 0.1032
train acc, test acc | 0.898, 0.9026
train acc, test acc | 0.92135, 0.9216
train acc, test acc | 0.936016666667, 0.9337
train acc, test acc | 0.945316666667, 0.9431
train acc, test acc | 0.94675, 0.9427
train acc, test acc | 0.954766666667, 0.9521
train acc, test acc | 0.9602, 0.9551
train acc, test acc | 0.9634, 0.9581
train acc, test acc | 0.9656, 0.9597
train acc, test acc | 0.9683, 0.9615
train acc, test acc | 0.970516666667, 0.9629
train acc, test acc | 0.97305, 0.9649
train acc, test acc | 0.9731, 0.9661
train acc, test acc | 0.975916666667, 0.9659
train acc, test acc | 0.976383333333, 0.9666
train acc, test acc | 0.977916666667, 0.969
[Finished in 45.5s]
"""
Summary
- ๊ณ์ฐ ๊ทธ๋ํ๋ฅผ ์ด์ฉํ๋ฉด ๊ณ์ฐ ๊ณผ์ ์ ์๊ฐ์ ์ผ๋ก ํ์ ํ ์ ์์ต๋๋ค.
- ๊ณ์ฐ ๊ทธ๋ํ์ ๋ ธ๋๋ ๊ตญ์์ ๊ณ์ฐ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ๊ตญ์์ ๊ณ์ฐ์ ์กฐํฉํด ์ ์ฒด ๊ณ์ฐ์ ๊ตฌ์ฑํฉ๋๋ค.
- ๊ณ์ฐ ๊ทธ๋ํ์ ์์ ํ๋ ํต์์ ๊ณ์ฐ์ ์ํํฉ๋๋ค. ํํธ, ๊ณ์ฐ ๊ทธ๋ํ์ ์ญ์ ํ๋ก๋ ๊ฐ ๋ ธ๋์ ๋ฏธ๋ถ์ ๊ตฌํ ์ ์์ต๋๋ค.
- ์ ๊ฒฝ๋ง์ ๊ตฌ์ฑ ์์๋ฅผ ๊ณ์ธต์ผ๋ก ๊ตฌํํ์ฌ ๊ธฐ์ธ๊ธฐ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ณ์ฐํ ์ ์์ต๋๋ค(์ค์ฐจ์ญ์ ํ๋ฒ).
- ์์น ๋ฏธ๋ถ๊ณผ ์ค์ฐจ์ญ์ ํ๋ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋น๊ตํ๋ฉด ์ค์ฐจ์ญ์ ํ๋ฒ์ ๊ตฌํ์ ์๋ชป์ด ์๋์ง ํ์ธํ ์ ์์ต๋๋ค(๊ธฐ์ธ๊ธฐ ํ์ธ).
๋ฐ์ํ
'๐ฅ๏ธ Deep Learning' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[DL] Activation Function - ํ์ฑํ ํจ์ (0) | 2024.04.29 |
---|---|
[DL] Feed-forward Network (ํผ๋-ํฌ์๋ ๋คํธ์ํฌ) (0) | 2024.04.18 |
[DL] Backpropagation (์ค์ฐจ์ญ์ ํ๋ฒ) (0) | 2024.03.27 |
[DL] Gradient (๊ธฐ์ธ๊ธฐ), Training Algorithm(ํ์ต ์๊ณ ๋ฆฌ์ฆ) (0) | 2024.03.23 |
[DL] Neural Network Training (์ ๊ฒฝ๋ง ํ์ต) (0) | 2024.03.21 |