๋งค๊ฐ๋ณ์ ๊ฐฑ์
ํ๋ฅ ์ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ(SGD)
์ ๊ฒฝ๋ง ํ์ต์ ๋ชฉ์ ์ ์์ค ํจ์์ ๊ฐ์ ๊ฐ๋ฅํ ํ ๋ฎ์ถ๋ ๋งค๊ฐ๋ณ์๋ฅผ ์ฐพ๋ ๊ฒ์ผ๋ก ์ด๋ ๊ณง ๋งค๊ฐ๋ณ์์ ์ต์ ๊ฐ์ ์ฐพ๋ ๋ฌธ์ ์ด๋ฉฐ, ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํธ๋ ๊ฒ์ `์ต์ ํ(optimization)`์ด๋ผ๊ณ ํ๋ค. ์ต์ ์ ๋งค๊ฐ๋ณ์ ๊ฐ์ ์ฐพ๊ธฐ ์ํ ๋จ์๋ก ๋งค๊ฐ๋ณ์์ ๊ธฐ์ธ๊ธฐ(๋ฏธ๋ถ)๋ฅผ ์ด์ฉํ๋๋ฐ, ๋งค๊ฐ๋ณ์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ตฌํด ๊ธฐ์ธ์ด์ง ๋ฐฉํฅ์ผ๋ก ๋งค๊ฐ๋ณ์ ๊ฐ์ ๊ฐฑ์ ํ๋ ์ผ์ ๋ฐ๋ณตํด์ ์ต์ ์ ๊ฐ์ ํฅํด ๋ค๊ฐ๊ฐ๋ ๊ฒ์ด `ํ๋ฅ ์ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ(SGD)`์ด๋ค. SGD๋ ๋ค์๊ณผ ๊ฐ์ ์์์ผ๋ก ํํ์ด ๊ฐ๋ฅํ๋ค. ๊ฒฐ๊ตญ SGD๋ ๊ธฐ์ธ์ด์ง ๋ฐฉํฅ์ผ๋ก ์ผ์ ๊ฑฐ๋ฆฌ๋ง ๊ฐ๊ฒ ๋ค๋ ๋จ์ํ ๋ฐฉ๋ฒ์ด๋ค.
SGD๋ฅผ ํ์ด์ฌ ์ฝ๋๋ก ๊ตฌํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
class SGD:
def __init__(self, lr=0.01):
self.lr = lr
def update(self, params, grads):
for key in params.key():
params[key] -= self.lr * grads[key]
์ด๊ธฐํ ๋์ ์ธ์์ธ lr์ `ํ์ต๋ฅ (learning rate)`์ ์๋ฏธํ๋ค. ํ์ต๋ฅ ์ ์ธ์คํด์ค ๋ณ์๋ก ์ ์งํ๋ค. update(params, grads) ๋ฉ์๋๋ SGD ๊ณผ์ ์์ ๋ฐ๋ณตํด์ ๋ถ๋ฆฐ๋ค. ์ธ์์ธ params์ grads๋ ๋์ ๋๋ฆฌ ๋ณ์์ด๋ฉฐ ๊ฐ๊ฐ ๊ฐ์ค์น ๋งค๊ฐ๋ณ์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ์ ์ฅํ๋ค. ์ด๋ฌํ SGD์ ๋จ์ ์ `๋น๋ฑ๋ฐฉ์ฑ(anisotropy)` ํจ์, ์ฆ ๋ฐฉํฅ์ ๋ฐ๋ผ ์ฑ์ง(๊ธฐ์ธ๊ธฐ)์ด ๋ฌ๋ผ์ง๋ ํจ์์์๋ ํ์ ๊ฒฝ๋ก๊ฐ ์ง๊ทธ์ฌ๊ทธ๋ก ๋นํจ์จ์ ์ด๋ผ๋ ๊ฒ์ด๋ค.
๋ชจ๋ฉํ
`๋ชจ๋ฉํ (momentum)`์ ์ด๋๋์ ๋ปํ๋ ๋จ์ด๋ก, ๋ฌผ๋ฆฌ์ ๊ด๊ณ๊ฐ ์๋ค. ๋ชจ๋ฉํ ๊ธฐ๋ฒ์ ์์์ผ๋ก ๋ํ๋ด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค. ๋ชจ๋ฉํ ์ ๊ฐฑ์ ๊ฒฝ๋ก๋ ๊ณต์ด ๊ทธ๋ฆ ๋ฐ๋ฅ์ ๊ตฌ๋ฅด๋ฏ ์์ง์ฌ SGD์ ๋น๊ตํ์ ๋ ์ง๊ทธ์ฌ๊ทธ ์ ๋๊ฐ ๋ํ๋ค.
๋ชจ๋ฉํ ์ ํ์ด์ฌ ์ฝ๋๋ก ๊ตฌํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
class Momentum:
def __init__(self, lr=0.01, momentum=0.9):
self.lr = lr
self.momentum = momentum
self.v = None
def update(self, params, grads):
if self.v is None:
self.v = {}
for key, val in params.items():
self.v[key] = np.zeros_like(val)
for key in params.keys():
self.v[key] = self.momentum * self.v[key] - self.lr * grads[key]
params[key] += self.v[key]
์ธ์คํด์ค ๋ณ์ v๊ฐ ๋ฌผ์ฒด์ ์๋์ด๋ค. v๋ ์ด๊ธฐํ ๋๋ ์๋ฌด๊ฒ๋ ์๋ค๊ฐ update()๊ฐ ์ฒ์ ํธ์ถ๋ ๋ ๋งค๊ฐ๋ณ์์ ๊ฐ์ ๊ตฌ์กฐ์ ๋ฐ์ดํฐ๋ฅผ ๋์ ๋๋ฆฌ ๋ณ์๋ก ์ ์ฅํ๋ค.
AdaGrad
์ ๊ฒฝ๋ง ํ์ต์์ ํ์ต๋ฅ ๊ฐ์ด ๋๋ฌด ์์ผ๋ฉด ํ์ต ์๊ฐ์ด ๋๋ฌด ๊ธธ์ด์ง๊ณ , ๋๋ฌด ํฌ๋ฉด ๋ฐ์ฐํ์ฌ ํ์ต์ด ์ ๋๋ก ์ด๋ฃจ์ด์ง์ง ์์ ์ ์๋ค. ์ด ํ์ต๋ฅ ์ ์ ํ๋ ํจ๊ณผ์ ์ธ ๊ธฐ์ ๋ก `ํ์ต๋ฅ ๊ฐ์(learning rate decay)`๊ฐ ์๋ค. ์ด๋ ์ฒ์์๋ ํฌ๊ฒ ํ์ตํ๋ค๊ฐ ํ์ต์ ์งํํ๋ฉด์ ํ์ต๋ฅ ์ ์ ์ฐจ ์ค์ฌ๊ฐ๋ ๋ฐฉ๋ฒ์ด๋ค. ํ์ต๋ฅ ์ ์์ํ ๋ฎ์ถ๋ ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ์ ์ฒด์ ํ์ต๋ฅ ๊ฐ์ ์ผ๊ด์ ์ผ๋ก ๋ฎ์ถ๋ ๊ฒ์ผ๋ก, AdaGrad๋ ์ด๋ฅผ ๋ฐ์ ์์ผ ๊ฐ๊ฐ์ ๋งค๊ฐ๋ณ์์ ๋ง์ถคํ ๊ฐ์ ๋ง๋ค์ด์ค๋ค. AdaGrad๋ ๊ฐ๋ณ ๋งค๊ฐ๋ณ์์ ์ ์์ ์ผ๋ก ํ์ต๋ฅ ์ ์กฐ์ ํ๋ฉด์ ํ์ต์ ์งํํ๋ค.
AdaGrad์์ ์๋ก์ด h๋ผ๋ ๋ณ์๊ฐ ๋ฑ์ฅํ๋ค. h๋ ๊ธฐ์กด ๊ธฐ์ธ๊ธฐ ๊ฐ์ ์ ๊ณฑํ์ฌ ๊ณ์ ๋ํด์ค๋ค. ๋ํ ๋งค๊ฐ๋ณ์๋ฅผ ๊ฐฑ์ ํ ๋ ํ์ต๋ฅ ์ ์กฐ์ ํ๋ค. ๋งค๊ฐ๋ณ์์ ์์ ์ค ํฌ๊ฒ ๊ฐฑ์ ๋ ์์๋ ํ์ต๋ฅ ์ด ๋ฎ์์ง๋ ๊ฒ์ผ๋ก ์ด๋ ํ์ต๋ฅ ๊ฐ์๊ฐ ๋งค๊ฐ๋ณ์์ ์์๋ง๋ค ๋ค๋ฅด๊ฒ ์ ์ฉ๋จ์ ์๋ฏธํ๋ค. AdaGrad๋ฅผ ํ์ด์ฌ ์ฝ๋๋ก ๊ตฌํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
class AdaGrad:
def __init__(self, lr=0.01):
self.lr = lr
self.h = None
def update(self, params, grads):
if self.h is None:
self.h = {}
for key, val in params.items():
self.h[key] = np.zeros_like(val)
for key in params.keys():
self.h[key] += grads[key] * grads[key]
params[key] -= self.lr * grads[key] / np.sqrt(self.h[key] + 1e-7)
๊ทธ๋ฌ๋ AdaGrad๋ ๊ณผ๊ฑฐ์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ ์ ๊ณฑํ์ฌ ๋ํด๋๊ฐ ํ์ต์ ์งํํ ์๋ก ๊ฐฑ์ ์ ๋๊ฐ ์ฝํด์ง๋ค. ์ด๋ฅผ ๋ฌดํํ ํ์ตํ๊ฒ ๋๋ฉด ์ด๋ ์๊ฐ ๊ฐฑ์ ๋์ด 0์ด ๋์ด ์ ํ ๊ฐฑ์ ํ์ง ์๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค. ์ด๋ฅผ ๊ฐ์ ํ ๊ธฐ๋ฒ์ผ๋ก `RMSProp`์ด ์๋ค. RMSProp๋ ๊ณผ๊ฑฐ์ ๋ชจ๋ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ท ์ผํ๊ฒ ๋ํด๋๊ฐ๋ ๊ฒ์ด ์๋๋ผ, ๋จผ ๊ณผ๊ฑฐ์ ๊ธฐ์ธ๊ธฐ๋ ์์ํ ์๊ณ ์๋ก์ด ๊ธฐ์ธ๊ธฐ ์ ๋ณด๋ฅผ ํฌ๊ฒ ๋ฐ์ํ๋ค. ์ด๋ฅผ `์ง์์ด๋ํ๊ท (Exponential Moving Average · EMA)๋ผ๊ณ ํ๋ฉฐ ๊ณผ๊ฑฐ ๊ธฐ์ธ๊ธฐ์ ๋ฐ์ ๊ท๋ชจ๋ฅผ ๊ธฐํ๊ธ์์ ์ผ๋ก ๊ฐ์์ํจ๋ค.
Adam
Adam์ ๋ชจ๋ฉํ ๊ณผ AdaGrad๋ฅผ ์ตํฉํ ๋ฏํ ๋ฐฉ๋ฒ์ด๋ค. Adam์ 3๊ฐ์ง์ ํ์ดํผํ๋ผ๋ฏธํฐ๋ฅผ ์ค์ ํ๋ค. ํ๋๋ ํ์ต๋ฅ , ๋๋จธ์ง ๋๊ฐ๋ ์ผ์ฐจ ๋ชจ๋ฉํ ์ฉ ๊ณ์์ ์ด์ฐจ ๋ชจ๋ฉํ ์ฉ ๊ณ์์ด๋ค. ์ด๋ค์ ๊ธฐ๋ณธ๊ฐ์ ๊ฐ๊ฐ 0.9, 0.999์ด๋ค. ๋ํ ํ์ดํผํ๋ผ๋ฏธํฐ์ ํธํฅ ๋ณด์ ์ด ์งํ๋๋ค๋ ์ ๋ Adam์ ํน์ง์ด๋ค. ์ด๋ฅผ ํ์ด์ฌ ์ฝ๋๋ก ๊ตฌํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
class Adam:
def __init__(self, lr=0.001, beta1=0.9, beta2=0.999):
self.lr = lr
self.beta1 = beta1
self.beta2 = beta2
self.iter = 0
self.m = None
self.v = None
def update(self, params, grads):
if self.m is None:
self.m, self.v = {}, {}
for key, val in params.items():
self.m[key] = np.zeros_like(val)
self.v[key] = np.zeros_like(val)
self.iter += 1
lr_t = self.lr * np.sqrt(1.0 - self.beta2**self.iter) / (1.0 - self.beta1**self.iter)
for key in params.keys():
self.m[key] += (1 - self.beta1) * (grads[key] - self.m[key])
self.v[key] += (1 - self.beta2) * (grads[key]**2 - self.v[key])
params[key] -= lr_t * self.m[key] / (np.sqrt(self.v[key]) + 1e-7)
๊ฐ์ค์น์ ์ด๊น๊ฐ
์ด๊น๊ฐ์ 0์ผ๋ก ํ๋ฉด?
`๊ฐ์ค์น ๊ฐ์(weight decay)`๋ ๊ฐ์ค์น ๋งค๊ฐ๋ณ์์ ๊ฐ์ด ์์์ง๋๋ก ํ์ตํ๋ ๋ฐฉ๋ฒ์ผ๋ก, ์ค๋ฒํผํ ์ ์ต์ ํด ๋ฒ์ฉ ์ฑ๋ฅ์ ๋์ด๋ ๊ธฐ๋ฒ์ด๋ค. ๊ฐ์ค์น๋ฅผ ์๊ฒ ํ๊ธฐ ์ํด์ ์ด๊น๊ฐ๋ ์ต๋ํ ์์ ๊ฐ์์ ์์ํ๋ ๊ฒ์ด ์ข๋ค. ๊ทธ๋ฌ๋ ์ด๊น๊ฐ์ 0์ผ๋ก ์ค์ ํ๋ค๋ฉด, ์ฆ ๊ฐ์ค์น๋ฅผ ๊ท ์ผํ ๊ฐ์ผ๋ก ์ค์ ํ๋ฉด ํ์ต์ด ์ฌ๋ฐ๋ฅด๊ฒ ์ด๋ฃจ์ด์ง์ง ์๋๋ค. ์ด๋ ์ญ์ ํ ๊ณผ์ ์์ ๋ชจ๋ ๊ฐ์ค์น์ ๊ฐ์ด ๋๊ฐ์ด ๊ฐฑ์ ๋๊ธฐ ๋๋ฌธ์ด๋ค.
์๋ฅผ ๋ค์ด 2์ธต ์ ๊ฒฝ๋ง์์ ์ฒซ ๋ฒ์งธ ์ธต๊ณผ ๋ ๋ฒ์งธ ์ธต์ ๊ฐ์ค์น๊ฐ ๋ชจ๋ 0์ด๋ผ๊ณ ๊ฐ์ ํด๋ณด๋ฉด, ์์ ํ ๋๋ ์ ๋ ฅ์ธต์ ๊ฐ์ค์น๊ฐ 0์ด๊ธฐ ๋๋ฌธ์ ๋ ๋ฒ์งธ ์ธต์ ๋ด๋ฐ์ ๋ชจ๋ ๊ฐ์ ๊ฐ์ด ์ ๋ฌ๋๋ค. ์ด๋ ์ญ์ ํ ๊ณผ์ ์์ ๋ ๋ฒ์งธ ์ธต์ ๊ฐ์ค์น๊ฐ ๋ชจ๋ ๋๊ฐ์ด ๊ฐฑ์ ๋๋ค๋ ์๋ฏธ์ด๋ค. ๋ฐ๋ผ์ ๊ฐ์ค์น๋ค์ ๊ฐ์ ์ด๊น๊ฐ์์ ์์ํ๊ณ ๊ฐฑ์ ์ ๊ฑฐ์ณ๋ ์ฌ์ ํ ๊ฐ์ ๊ฐ์ ์ ์งํ๊ฒ ๋๋ค. ์ด๋ฅผ ๋ง๊ธฐ ์ํด์ ์ด๊น๊ฐ์ ๋ฌด์์๋ก ์ค์ ํด์ผ ํ๋ค.
์๋์ธต์ ํ์ฑํ๊ฐ ๋ถํฌ
๊ฐ์ค์น์ ์ด๊น๊ฐ์ ๋ฐ๋ผ ์๋์ธต์ ํ์ฑํ๊ฐ, ์ฆ ํ์ฑํ ํจ์์ ์ถ๋ ฅ ๋ฐ์ดํฐ๊ฐ ์ด๋ป๊ฒ ๋ณํํ๋์ง ํ์ธํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
x = np.random.randn(1000, 100) # 1000๊ฐ์ ๋ฐ์ดํฐ
node_num = 100 # ๊ฐ ์๋์ธต์ ๋ด๋ฐ ์ 100๊ฐ
hidden_layer_size = 5 # ์๋์ธต์ด 5๊ฐ
activations = {} # ํ์ฑํ ํจ์ ๊ฒฐ๊ณผ๊ฐ์ ์ ์ฅ
for i in range(hidden_layer_size):
if i != 0:
x = activations[i-1]
w = np.random.randn(node_num, node_num) * 1 # ๊ฐ์ค์น์ ๋ถํฌ๊ฐ ํ์คํธ์ฐจ๊ฐ 1์ธ ์ ๊ท๋ถํฌ
a = np.dot(x, w)
z = sigmoid(a)
activations[i] = z
์ธต์ ์ด 5๊ฐ์ด๋ฉฐ ๊ฐ ์ธต์ ๋ด๋ฐ์ 100๊ฐ์ฉ ๊ตฌ์ฑ๋์ด ์๋ค. ์ ๋ ฅ ๋ฐ์ดํฐ๋ 1,000๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ท๋ถํฌ๋ก ๋ฌด์์๋ก ์์ฑํ์๋ค. ํ์ฑํ ํจ์๋ก๋ ์๊ทธ๋ชจ์ด๋ ํจ์๋ฅผ ์ด์ฉํ์์ผ๋ฉฐ ๊ฐ ์ธต์ ํ์ฑํ ๊ฒฐ๊ณผ๋ฅผ activations ๋ณ์์ ์ ์ฅํ๋ค. ๊ฐ์ค์น๋ ํ์คํธ์ฐจ๊ฐ 1์ธ ์ ๊ท๋ถํฌ๋ฅผ ์ด์ฉํ๋ค. ์ด activations ๋ณ์์ ์ ์ฅ๋ ๊ฐ ์ธต์ ํ์ฑํ๊ฐ์ ํ์คํ ๊ทธ๋จ์ผ๋ก ๋ํ๋๋ค.
์ด๋ฅผ ๋ณด๋ฉด ๊ฐ ์ธต์ ํ์ฑํ๊ฐ๋ค์ด 0๊ณผ 1์ ์น์ฐ์ณ ๋ถํฌํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ์๊ทธ๋ชจ์ด๋ ํจ์๋ ์ถ๋ ฅ์ด 0 ๋๋ 1์ ๊ฐ๊น์์ง๋ฉด ๋ฏธ๋ถ ๊ฐ์ 0์ ๊ฐ๊น์์ง๋ฉฐ ์ด๋ฅผ ํตํด ์ญ์ ํ์ ๊ธฐ์ธ๊ธฐ ๊ฐ์ด ์ ์ ์์์ง๋ค๊ฐ ์ฌ๋ผ์ง๋ค. ์ด๋ ๊ฒฐ๊ตญ `๊ธฐ์ธ๊ธฐ ์์ค(gradient vanishing)`๋ก ์ด์ด์ง๋ฉฐ ์ธต์ ๊น๊ฒ ํ๋ ๋ฅ๋ฌ๋์์๋ ๊ธฐ์ธ๊ธฐ ์์ค์ ์ฌ๊ฐํ ๋ฌธ์ ๊ฐ ๋ ์ ์๋ค.
๋ค์์ผ๋ก ๊ฐ์ค์น์ ํ์คํธ์ฐจ๋ฅผ 0.01๋ก ๋ฐ๊ฟ ๊ฐ์ ์คํ์ ๋ฐ๋ณตํ๋ค. ์์ ์ฝ๋์์ ๊ฐ์ค์น ์ด๊น๊ฐ ์ค์ ๋ง ๋ณํ์ํจ๋ค.
for i in range(hidden_layer_size):
if i != 0:
x = activations[i-1]
w = np.random.randn(node_num, node_num) * 0.01 # ๊ฐ์ค์น์ ๋ถํฌ๊ฐ ํ์คํธ์ฐจ๊ฐ 0.01์ธ ์ ๊ท๋ถํฌ
a = np.dot(x, w)
z = sigmoid(a)
activations[i] = z
์ด ๋ํ activations ๋ณ์์ ์ ์ฅ๋ ๊ฐ ์ธต์ ํ์ฑํ๊ฐ ๋ฐ์ดํฐ๋ฅผ ํ์คํ ๊ทธ๋จ์ผ๋ก ๋ํ๋ด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
์ด๋ฒ์๋ ๊ฐ ์ธต์ ํ์ฑํ๊ฐ์ด 0.5 ๋ถ๊ทผ์ ์ง์ค๋์๋ค. ์ด๋ ๊ธฐ์ธ๊ธฐ ์์ค์ ๋ฐ์ํ์ง ์์ง๋ง ํ์ฑํ๊ฐ๋ค์ด ์น์ฐ์ณค๋ค๋ ๊ฒ์ ๊ฒฐ๊ตญ ํํ๋ ฅ์ ์ ํํ๋ค๋ ๊ด์ ์์ ๋ฌธ์ ๊ฐ ๋๋ค. ์ฆ, ๋ด๋ฐ์ด 1๊ฐ ์์ผ๋ 100๊ฐ ์์ผ๋ ๋์ผํ ๊ฒฐ๊ณผ๊ฐ ๋์ ๋ด๋ฐ์ ์ฌ๋ฌ ๊ฐ ๋ ์๋ฏธ๊ฐ ์์ด์ง๋ค๋ ๊ฒ์ด๋ค. ๋ฐ๋ผ์ ๊ฐ ์ธต์ ํ์ฑํ๊ฐ์ ์ ๋นํ ๊ณ ๋ฃจ ๋ถํฌ๋์ด์ผ ํ๋ค. ์ธต๊ณผ ์ธต ์ฌ์ด์ ์ ๋นํ๊ฒ ๋ค์ํ ๋ฐ์ดํฐ๊ฐ ํ๋ฌ์ผ ํจ์จ์ ์ธ ์ ๊ฒฝ๋ง ํ์ต์ด ์ด๋ฃจ์ด์ง๋ฉฐ, ๋ฐ๋๋ก ์น์ฐ์น ๋ฐ์ดํฐ๊ฐ ํ๋ฅด๋ฉด ๊ธฐ์ธ๊ธฐ ์์ค ํน์ ํํ๋ ฅ ์ ํ ๋ฌธ์ ์ ๋น ์ ธ ํ์ต์ด ์ ์ด๋ฃจ์ด์ง์ง ์๋๋ค.
์ด์ด์ ์ผ๋ฐ์ ์ธ ๋ฅ๋ฌ๋ ํ๋ ์์ํฌ๋ค์ด ํ์ค์ ์ผ๋ก ์ด์ฉํ๋ `Xavier ์ด๊น๊ฐ`์ ํ์ธํ๋ค. ์ด๋ ๊ฐ ์ธต์ ํ์ฑํ๊ฐ๋ค์ ๊ด๋ฒ์ํ๊ฒ ๋ถํฌ์ํค๊ธฐ ์ํ ๊ฐ์ค์น์ ์ ์ ํ ๋ถํฌ๋ฅผ ์ฐพ๋๋ค. Xavier ์ด๊น๊ฐ์ ์ฌ์ฉํ๋ฉด ์ ์ธต์ ๋ ธ๋๊ฐ ๋ง์์๋ก ๋์ ๋ ธ๋์ ์ด๊น๊ฐ์ผ๋ก ์ค์ ํ๋ ๊ฐ์ค์น๊ฐ ์ข๊ฒ ํผ์ง๋ ๊ตฌ์กฐ์ด๋ค.
์์ ํ์ธํ ์คํ์ ์ด๋ฒ์ Xavier ์ด๊น๊ฐ์ ์ฌ์ฉํ๋ค.
for i in range(hidden_layer_size):
if i != 0:
x = activations[i-1]
w = np.random.randn(node_num, node_num) / np.sqrt(node_num) # Xavier ์ด๊น๊ฐ
a = np.dot(x, w)
z = sigmoid(a)
activations[i] = z
์ด ๋ํ activation ๋ณ์์ ์ ์ฅ๋ ๊ฐ ์ธต์ ํ์ฑํ๊ฐ ๋ฐ์ดํฐ๋ฅผ ํ์คํ ๊ทธ๋จ์ผ๋ก ๋ํ๋ด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
Xavier ์ด๊น๊ฐ์ ์ฌ์ฉํ ๊ฒฐ๊ณผ ์ธต์ด ๊น์ด์ง๋ฉด์ ํํ๊ฐ ๋ค์ ์ผ๊ทธ๋ฌ์ง์ง๋ง ์์ ๋ณธ ๋ถํฌ๋ณด๋ค ํจ์ฌ ๋๊ฒ ๋ถํฌ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ์ด๋ ๊ฐ ์ธต์ ํ๋ฅด๋ ๋ฐ์ดํฐ๊ฐ ์ ๋นํ ํผ์ ธ ์์ผ๋ฏ๋ก, ์๊ทธ๋ชจ์ด๋ ํจ์์ ํํ๋ ฅ๋ ์ ํ๋ฐ์ง ์๊ณ ํ์ต์ด ํจ์จ์ ์ผ๋ก ์ด๋ฃจ์ด์ง ๊ฒ์ ๊ธฐ๋ํ ์ ์๋ค.
ReLU๋ฅผ ์ฌ์ฉํ ๋์ ๊ฐ์ค์น ์ด๊น๊ฐ
Xavier ์ด๊น๊ฐ์ ํ์ฑํ ํจ์๊ฐ ์ ํ์ธ ๊ฒ์ ์ ์ ๋ก ํ๋ค. sigmoid ํจ์์ tanh ํจ์๋ ์ข์ฐ ๋์นญ์ด๊ธฐ ๋๋ฌธ์ ์ค์ ๋ถ๊ทผ์ด ์ ํ์ธ ํจ์๋ก ๋ณผ ์ ์๊ธฐ ๋๋ฌธ์ Xavier ์ด๊น๊ฐ์ด ์ ์ ํ ์ ํ์ด ๋ ์ ์๋ค. ๊ทธ๋ฌ๋ `ReLU`๋ฅผ ํ์ฑํ ํจ์๋ก ์ฌ์ฉํ ๋๋ ์ด์ ํนํ๋ ์ด๊น๊ฐ์ ์ฌ์ฉํ๋๋ฐ, ์ด๋ฅผ `He ์ด๊น๊ฐ`์ด๋ผ๊ณ ํ๋ค. He ์ด๊น๊ฐ์ ๋ค์๊ณผ ๊ฐ๋ค. ์ด๋ ReLU์ ์์ ์์ญ์ด 0์ด๋ผ์ ๋ ๋๊ฒ ๋ถํฌ์ํค๊ธฐ ์ํด 2๋ฐฐ์ ๊ณ์๊ฐ ํ์ํ ๊ฒ์ผ๋ก ์ง๊ด์ ์ผ๋ก ํด์ํ ์ ์๋ค. ๊ฒฐ๋ก ์ ์ผ๋ก ํ์ฑํ ํจ์๋ก ReLU๋ฅผ ์ฌ์ฉํ ๋๋ He ์ด๊น๊ฐ์, sigmoid๋ tanh ๋ฑ์ S์ ๋ชจ์ ๊ณก์ ์ผ ๋๋ Xavier ์ด๊น๊ฐ์ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ค.
๋ฐฐ์น ์ ๊ทํ(Batch Normalization)
์์ ๊ฐ์ค์น์ ์ด๊น๊ฐ์ ์ ์ ํ ์ค์ ํ๋ฉด ๊ฐ ์ธต์ ํ์ฑํ๊ฐ ๋ถํฌ๊ฐ ์ ๋นํ ํผ์ง๋ฉด์ ํ์ต์ด ์ํํ๊ฒ ์ํ๋จ์ ํ์ธํ๋ค. ์ฌ๊ธฐ์ ๊ฐ ์ธต์ด ํ์ฑํ๋ฅผ ์ ๋นํ ํผ๋จ๋ฆฌ๋๋ก ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ์ด ๋ฐ๋ก `๋ฐฐ์น ์ ๊ทํ(Batch Normalization)`์ด๋ค. ๋ฐฐ์น ์ ๊ทํ๋ฅผ ์ํํจ์ผ๋ก์จ ์ป์ ์ ์๋ ํจ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- ํ์ต์ ๋นจ๋ฆฌ ์งํํ์ฌ ํ์ต ์๋๋ฅผ ๊ฐ์
- ์ด๊น๊ฐ์ ํฌ๊ฒ ์์กด x
- ์ค๋ฒํผํ ์ ์ต์ (๋๋กญ์์ ๋ฑ์ ํ์์ฑ ๊ฐ์)
๋ฐฐ์น ์ ๊ทํ์ ๊ธฐ๋ณธ ์์ด๋์ด๋ ์์์ ์ค๋ช ํ๋ฏ์ด ๊ฐ ์ธต์์์ ํ์ฑํ๊ฐ์ด ์ ๋นํ ๋ถํฌ๋๋๋ก ์กฐ์ ํ๋ ๊ฒ์ด๋ค. ๋ฐฐ์น ์ ๊ทํ๋ฅผ ์ฌ์ฉํ๋ ์ ๊ฒฝ๋ง์ ์์๋ ๋ค์๊ณผ ๊ฐ๋ค. ์ด๋ฌํ ๋ฐฐ์น ์ ๊ทํ์ ์ฒ๋ฆฌ๋ฅผ ํ์ฑํ ํจ์์ ์ ํน์ ๋ค์ ์ฝ์ ํจ์ผ๋ก์จ ๋ฐ์ดํฐ ๋ถํฌ๊ฐ ๋ ์น์ฐ์น๊ฒ ํ ์ ์๋ค.
๋ฐฐ์น ์ ๊ทํ๋ ํ์ต ์ ๋ฏธ๋๋ฐฐ์น๋ฅผ ๋จ์๋ก ๋ฐ์ดํฐ ๋ถํฌ๊ฐ ํ๊ท ์ด 0, ๋ถ์ฐ์ด 1์ด ๋๋๋ก ์ ๊ทํ๋ฅผ ์ํํ๋ค. ์์์ ๋ค์๊ณผ ๊ฐ๋ค. ๋ํ ์ถ๊ฐ์ ์ผ๋ก ๋ฐฐ์น ์ ๊ทํ ๊ณ์ธต๋ง๋ค ์ ๊ทํ๋ ๋ฐ์ดํฐ์ ๊ณ ์ ํ `ํ๋(scale)`์ `์ด๋(shift)` ๋ณํ์ ์ํํ๋ค.
์ด ํฌ์คํ ์ "๋ฐ๋ฐ๋ฅ๋ถํฐ ์์ํ๋ ๋ฅ๋ฌ๋" ๊ต์ฌ๋ฅผ ๊ณต๋ถํ๋ฉฐ ์์ฑํ ๊ธ์ ๋๋ค.