๋ฐ๋ฐ๋ฅ๋ถํฐ ์์ํ๋ ๋ฅ๋ฌ๋ 3 : https://www.hanbit.co.kr/store/books/look.php?p_code=B6627606922
์์ค์ฝ๋ : https://github.com/WegraLee/deep-learning-from-scratch-3
- ๊ณ ์ฐจ ๋ฏธ๋ถ : ์ด๋ค ํจ์๋ฅผ 2๋ฒ ์ด์ ๋ฏธ๋ถํ ๊ฒ
- ๋ชฉ์ฐจ
- Graphviz : ๊ทธ๋ํ(๋ ธ๋์ ํ์ดํ๋ก ์ด๋ค์ง ๋ฐ์ดํฐ ๊ตฌ์กฐ)๋ฅผ ์๊ฐํํด์ฃผ๋ ๋๊ตฌ
- Graphviz ์ค์นํ๊ธฐ
- Windows์ฉ ๋ค์ด๋ก๋ ๋ฐ ์ค์น
- ํ๊ฒฝ๋ณ์
path
์C:\Program Files\Graphviz\bin
๋ฅผ ์ถ๊ฐํด์ค๋ค. - ์๋์ฝ๋ค ํ๋กฌํํธ์์ graphviz๋ฅผ ์ค์น ํ dot ๋ช
๋ น์ ์คํํด๋ณธ๋ค.
conda install python-graphviz dot -V
- DOT ์ธ์ด : ๊ฐ๋จํ ๋ฌธ๋ฒ์ผ๋ก ๊ทธ๋ํ๋ฅผ ์์ฑํ ์ ์๋ค.
- ๊ธฐ๋ณธ ๊ตฌ์กฐ :
digraph g {...}
- ๊ฐ ๋ ธ๋๋ฅผ ์ค๋ฐ๊ฟ์ผ๋ก ๊ตฌ๋ถ
- ๋ ธ๋ID๋ 0 ์ด์์ ์ ์์ด๋ฉฐ, ๋ค๋ฅธ ๋ ธ๋์ ์ค๋ณต ๋ถ๊ฐ๋ฅ
- ์์ ์ฝ๋ (๊ฒฐ๊ณผ :
x
->Exp
->y
)digraph g{ 1 [label='x', color=orange, style=filled] 2 [label='y', color=orange, style=filled] 3 [label='Exp', color=lightblue, style=filled, shape=box] 1 -> 3 3 -> 2 }
- ์ด๋ฏธ์ง๋ก ๋ณํ :
dot sample.dot -T png -o smaple.png
- ๊ธฐ๋ณธ ๊ตฌ์กฐ :
dezero/utils.py
get_dot_graph
์์๋ง ์ฌ์ฉํ๋ ๋ณด์กฐ ํจ์๋ ์ด๋ฆ ์์ ๋ฐ์ค(_
)์ ๋ถ์๋ค.id()
: ํ์ด์ฌ ๋ด์ฅํจ์๋ก, ์ฃผ์ด์ง ๊ฐ์ฒด์ ID๋ฅผ ๋ฐํํ๋ค. ๊ณ ์ ํ ๋ ธ๋ID๋ก ์ฌ์ฉํ๊ธฐ์ ์ ํฉํ๋ค.get_dot_graph
๋ Variable.backward() ๋ฉ์๋์ ๊ฑฐ์ ๋น์ทํ ํ๋ฆ์ผ๋ก ๊ตฌํํ๋ค.
- ๊ณ์ฐ ๊ทธ๋ํ ์๊ฐํ ์์
- ํ ์ผ๋ฌ ๊ธ์(Taylor Series) : ์ด๋ค ํจ์๋ฅผ ๋คํญ์์ผ๋ก ๊ทผ์ฌํ๋ ๋ฐฉ๋ฒ
- ๋งคํด๋ก๋ฆฐ ์ ๊ฐ(Maclaurin's series) : ์ผ ๋์ ํ ์ผ๋ฌ ๊ธ์
- ํ ์ผ๋ฌ ๊ธ์ ๊ตฌํ ์์
- ์ต์ ํ : ์ด๋ค ํจ์๊ฐ ์ฃผ์ด์ก์ ๋, ๊ทธ ์ต์๊ฐ(ํน์ ์ต๋๊ฐ)์ ๋ฐํํ๋ '์ ๋ ฅ(ํจ์์ ์ธ์)'์ ์ฐพ๋ ์ผ, ์ ๊ฒฝ๋ง ํ์ต์ ๋ชฉํ๋ ์์ค ํจ์์ ์ต์ ํ์ด๋ค.
- ํจ์ ์์
- ๊ธฐ์ธ๊ธฐ(gradient) : ๊ฐ ์ง์ ์์ ํจ์์ ์ถ๋ ฅ์ (์ ์ด๋ ๊ตญ์์ ์ผ๋ก๋) ๊ฐ์ฅ ํฌ๊ฒ(+)/์๊ฒ(-) ํ๋ ๋ฐฉํฅ์ ๊ฐ๋ฆฌํจ๋ค.
- ๊ฒฝ์ฌํ๊ฐ๋ฒ(gradient descent) : ๊ธฐ์ธ๊ธฐ ๋ฐฉํฅ์ ๋ง์ด๋์ค๋ฅผ ๊ณฑํ ๋ฐฉํฅ์ผ๋ก ์ผ์ ๊ฑฐ๋ฆฌ๋งํผ ์ด๋ํ์ฌ ๋ค์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ตฌํ๋ ์์ ์ ๋ฐ๋ณตํ์ฌ ์ํ๋ ์ง์ ์ ์ ๊ทผํ๋ ๋ฐฉ๋ฒ
- ๊ฒฝ์ฌํ๊ฐ๋ฒ ์ต์ ํ ์์
- 2์ฐจ๊น์ง ํ ์ผ๋ฌ ๊ธ์๋ก ๊ทผ์ฌ
- ๋ดํด ๋ฐฉ๋ฒ(Newton's method) : 2์ฐจ ๋ฏธ๋ถ์ ์ด์ฉํ์ฌ ๋ฅผ ์๋์ผ๋ก ์กฐ์ ํ๋ค.
- ๋ดํด ๋ฐฉ๋ฒ ์ต์ ํ ์์
- ๊ณ์ฐ ๊ทธ๋ํ์ ์ฐ๊ฒฐ์ Function ํด๋์ค์
__call__
๋ฉ์๋์์ ์์ ํ๋ฅผ ๊ณ์ฐํ ๋ ๋ง๋ค์ด์ง๋ค. - ์ญ์ ํ๋ฅผ ๊ณ์ฐํ ๋๋ ์ฐ๊ฒฐ์ ๋ง๋ค ์ ์๋ค๋ฉด, ๊ณ ์ฐจ ๋ฏธ๋ถ ๊ตฌํ ๊ฐ๋ฅ
- ๋ฐ๋ผ์ ๋ฏธ๋ถ๊ฐ(๊ธฐ์ธ๊ธฐ)์ Variable ์ธ์คํด์ค๋ก ๋ง๋ค๊ธฐ
- output๋ณ์์ grad๋ฅผ Variable ์ธ์คํด์ค๋ก ๋ง๋ ๋ค.
- Function์ backward์์ ๊ณ์ฐํ๋ ๋ณ์๋ Variable ๊ทธ๋๋ก ์ฌ์ฉํ๋ค.
- ๊ทธ๋ฌ๋ฉด ๋ค์ ์ธ๋์์๋ grad๊ฐ ๊ณ์ Variable ์ธ์คํด์ค๊ฐ ๋๋ค.
- ์ญ์ ํ ํ์ฑ/๋นํ์ฑ ๋ชจ๋(create_graph)
- ์ญ์ ํ ํ์ฑํ
- (Function์
backward
๋ฉ์๋->(๋ค๋ฅธ Function ์ธ์คํด์ค์)__call__
๋ฉ์๋) ๊ณผ์ ์์ ๊ทธ ๋ค์ ์ญ์ ํ๋ฅผ ์ํ ๋ณ์๋ฅผ ์ ์ฅํ๊ณ , ์ฐ๊ฒฐ์ ๋ง๋ ๋ค. - ๋ฐ๋ผ์ ๋ฏธ๋ถ๊ฐ์ ๊ณ์ฐํ๋ ๊ณผ์ ์์์ ๊ณ์ฐ ๊ทธ๋ํ๋ฅผ ๊ทธ๋ฆฐ๋ค. (๊ณ ์ฐจ ๋ฏธ๋ถ ๊ฐ๋ฅ)
y.backward(create_graph=True)
์ผ๋ก ์ฌ์ฉํ๋ค.
- (Function์
- ์ญ์ ํ ๋นํ์ฑํ
- (Function์
backward
๋ฉ์๋->(๋ค๋ฅธ Function ์ธ์คํด์ค์)__call__
๋ฉ์๋) ๊ณผ์ ์์ ๊ทธ ๋ค์ ์ญ์ ํ๋ฅผ ์ํ ๋ณ์๋ ์ ์ฅํ์ง ์๊ณ , ์ฐ๊ฒฐ๋ ๋ง๋ค์ง ์๋๋ค. - ๋ฐ๋ผ์ ๋ฏธ๋ถ๊ฐ์ ๊ณ์ฐํ๋ ๊ณผ์ ์์์ ๊ณ์ฐ ๊ทธ๋ํ๋ฅผ ๊ทธ๋ฆฌ์ง ์๋๋ค. (๊ณ ์ฐจ ๋ฏธ๋ถ ํ์ ์์)
gx.backward()
์ผ๋ก ์ฌ์ฉํ๋ค.
- (Function์
- ์ญ์ ํ ํ์ฑํ
- ๋ฏธ๋ถ๊ฐ ์ฌ์ค์
- ๋ฌธ์ : ๋ฏธ๋ถ๊ฐ ๋์
y.backward(create_graph=True) print(x.grad) # x.grad = dy/dx gx = x.grad gx.backward() print(x.grad) # x.grad = dy/dx + dy/d^2x
- ํด๊ฒฐ : ๋ฏธ๋ถ๊ฐ ์ฌ์ค์
y.backward(create_graph=True) print(x.grad) # x.grad = dy/dx gx = x.grad x.cleargrad() # ๋ฏธ๋ถ๊ฐ ์ฌ์ค์ (x.grad = None) gx.backward() print(x.grad) # x.grad = dy/d^2x
- ๋ฌธ์ : ๋ฏธ๋ถ๊ฐ ๋์
class Variable:
def __init__(self, data, name=None):
if data is not None:
if not isinstance(data, np.ndarray):
raise TypeError('{}์(๋) ์ง์ํ์ง ์์ต๋๋ค.'.format(type(data)))
self.data = data
self.name = name
self.grad = None
self.creator = None
self.generation = 0
def set_creator(self, func):
self.creator = func
self.generation = func.generation + 1
def cleargrad(self):
self.grad = None
def backward(self, retain_grad=False, create_graph=False):
if self.grad is None:
#self.grad = np.ones_like(self.data)
self.grad = Variable(np.ones_like(self.data)) # grad๋ฅผ Variable ์ธ์คํด์ค๋ก ๋ง๋ค๊ธฐ
funcs = []
seen_set = set()
def add_func(f):
if f not in seen_set:
funcs.append(f)
seen_set.add(f)
funcs.sort(key=lambda x : x.generation)
add_func(self.creator)
while funcs:
f = funcs.pop()
gys = [output().grad for output in f.outputs]
with using_config('enable_backprop', create_graph): # ์ญ์ ํ ํ์ฑ/๋นํ์ฑ ๋ชจ๋ ์ ํ
gxs = f.backward(*gys)
if not isinstance(gxs, tuple):
gxs = (gxs,)
for x, gx in zip(f.inputs, gxs):
if x.grad is None:
x.grad = gx
else:
x.grad = x.grad + gx
if x.creater is not None:
add_func(x.creator)
if not retain_grad:
for y in f.outputs:
y().grad = None
# ===========================================================
class Config:
enable_backprop = True
@contextlib.contextmanager
def using_config(name, value):
old_value = getattr(Config, name)
setattr(Config, name, value)
try:
yield
finally:
setattr(Config, name, old_value)
# ===========================================================
def as_array(x):
if np.isscalar(x):
return np.array(x)
return x
def as_variable(obj):
if isinstance(obj, Variable):
return obj
return Variable(obj)
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)
if not isinstance(ys, tuple):
ys = (ys,)
outputs = [Variable(as_array(y)) for y in ys]
if Config.enable_backprop: # ์ญ์ ํ ํ์ฑ/๋นํ์ฑ ๋ชจ๋ ์ ์ด ๋ถ๋ถ
for output in outputs:
output.set_creator(self) # ๊ณ์ฐ ๊ทธ๋ํ ์ฐ๊ฒฐ
self.inputs = inputs
self.outputs = [weakref.ref(output) for output in outputs]
self.generation = max([x.generation for x in inputs])
return outputs if len(outputs) > 1 else outputs[0]
def forward(self, xs):
raise NotImplementedError()
def backward(self, gys):
raise NotImplementedError()
# === ์ฐ์ฐ์ ์ค๋ฒ๋ก๋ =======================================
class Mul(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
x0, x1 = self.inputs # Variable ์ธ์คํด์ค๋ก ๊ณ์ฐํ์ฌ ์ฐ๊ฒฐ ๋ง๋ค๊ธฐ
return gy * x1, gy * x0
dezero/functions.py
- Function์ backward ๋ฉ์๋ ์์ ๋ชจ๋ ๋ณ์๋ Variable ์ธ์คํด์ค์ด๋ค.
- ๋ฐ๋ผ์ backward ๋ฉ์๋ ๊ตฌํ ์ ๋ชจ๋ ๊ณ์ฐ์ ๋ฐ๋์ DeZero ํจ์๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
- ํจ์ ๊ณ ์ฐจ ๋ฏธ๋ถ ์์ / ํจ์ ๊ณ ์ฐจ ๋ฏธ๋ถ ๊ณ์ฐ ๊ทธ๋ํ ์์ / ๊ณ ํด์๋ ์์
- ๋ค๋ณ์ ํจ์์ ๋ดํด ๋ฐฉ๋ฒ (์ฆ, ์ผ ๋, ์ ๋ํ ๋ดํด ๋ฐฉ๋ฒ)
- ํ๊ณ : ๋งค๊ฐ๋ณ์๊ฐ ๋ง์์ง๋ฉด ํค์ธ ํ๋ ฌ์ ์ญํ๋ ฌ ๊ณ์ฐ์ ๋๋ฌด ๋ง์ ์์์ด ์๋ชจ๋๋ค.
- ๋์
- ์ค ๋ดํด ๋ฐฉ๋ฒ(Quasi-Newton Method, QNM) : ๋ดํด ๋ฐฉ๋ฒ ์ค ํค์ธ ํ๋ ฌ์ ์ญํ๋ ฌ์ ๊ทผ์ฌํ์ฌ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ด์นญ
- ex) L-BFGS ๋ฑ
- ๊ธฐ์ธ๊ธฐ๋ง์ ์ฌ์ฉํ ์ต์ ํ
- ex) SGD, Momentum, Adam ๋ฑ
- ์ค ๋ดํด ๋ฐฉ๋ฒ(Quasi-Newton Method, QNM) : ๋ดํด ๋ฐฉ๋ฒ ์ค ํค์ธ ํ๋ ฌ์ ์ญํ๋ ฌ์ ๊ทผ์ฌํ์ฌ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ด์นญ
- double backpropagation : ์ญ์ ํ๋ฅผ ์ํํ ๊ณ์ฐ์ ๋ํด ๋ ๋ค์ ์ญ์ ํํ๋ ๊ฒ
- ์ฉ๋
- ๊ณ ์ฐจ ๋ฏธ๋ถ
-
๋ฏธ๋ถ์ด ํฌํจ๋ ์์์์ ๋ฏธ๋ถ
- ์์ : WGAN-GP์์ ์ต์ ํํ๋ ํจ์ $L$์ ๊ธฐ์ธ๊ธฐ๊ฐ ๋ค์ด์๋ค. ํจ์
$L$ ์ ์ต์ ํํ๊ธฐ ์ํด ๋๋ฒ์งธ ์ญ์ ํ๋ฅผ ํ๋ค.
- ์์ : WGAN-GP์์ ์ต์ ํํ๋ ํจ์ $L$์ ๊ธฐ์ธ๊ธฐ๊ฐ ๋ค์ด์๋ค. ํจ์
- ํค์ธ ํ๋ ฌ๊ณผ ๋ฒกํฐ์ ๊ณฑ(Hessian-vector product)
- ์ค๋ฅธ์ชฝ์ฒ๋ผ, ๋ฒกํฐ์ ๋ด์ ์ ๋จผ์ ๊ตฌํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ก๋ถํฐ ๋ค์ ํ ๋ฒ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ตฌํจ์ผ๋ก์จ, ํด์ธ ํ๋ ฌ์ ๋ง๋ค์ง ์๊ณ ๋ ๊ฐ์ ๊ตฌํ ์ ์๋ค.
- ์์ : TRPO(Trust Region Policy Optimization)์์๋ ํค์ธ ํ๋ ฌ๊ณผ ๋ฒกํฐ์ ๊ณฑ์ ๊ตฌํ ๋ double backprop์ ์ฌ์ฉํ๋ค.