๊ธฐ์ดˆ/์ธ๊ณต์ง€๋Šฅ

์˜ตํ‹ฐ๋งˆ์ด์ €(Optimizer) (1/2)

James Hwang๐Ÿ˜Ž 2021. 8. 31. 23:32
๐Ÿ’ก 'Deep Learning from Scratch'์™€ 'CS231N'์„ ์ฐธ๊ณ ํ•˜์—ฌ ์ž‘์„ฑ

  ์‹ ๊ฒฝ๋ง(neural network)์˜ ํ•™์Šต ๋ชฉ์ ์€ ์†์‹ค ํ•จ์ˆ˜(loss function)์˜ ๊ฐ’์„ ์ตœ๋Œ€ํ•œ ๋‚ฎ์ถ”๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜(parameter)๋ฅผ ์ฐพ๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ณง ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ตœ์ ๊ฐ’์„ ์ฐพ๋Š” ๋ฌธ์ œ์ด๋ฉฐ, ์ด๋ฅผ ์ตœ์ ํ™” ๋ฌธ์ œ(optimization)๋ผ ํ•ฉ๋‹ˆ๋‹ค.

  ์ตœ์ ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•™์Šต ๋ฐ์ดํ„ฐ๋“ค์„ ์ด์šฉํ•ด ๊ธฐ์šธ๊ธฐ(gradient)์˜ ๊ฐ’์„ ๊ตฌํ•˜๊ณ , ๊ทธ ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ๋‚˜์•„๊ฐˆ ๋ฐฉํ–ฅ์„ ๊ฒฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒˆ ๊ฒŒ์‹œ๋ฌผ์—์„œ๋Š” ์ตœ์ ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ฐพ๋Š” ๋ฐฉ๋ฒ•์ธ ์˜ตํ‹ฐ๋งˆ์ด์ €์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

1. ๊ธฐ์šธ๊ธฐ

  ํ•™์Šต ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ธฐ์šธ๊ธฐ๋ฅผ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ฐ ๋ณ€์ˆ˜๋“ค์— ๋Œ€ํ•œ ํŽธ๋ฏธ๋ถ„์„ ๋™์‹œ์— ๊ณ„์‚ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

$$ f(x_0, x_1) = x_0^2 + x_1^2 $$

  ์œ„์˜ ๊ณต์‹์—์„œ $ x_0 = 3, x_1 = 4 $์ผ ๋•Œ, ($ x_0, x_1 $)์˜ ์–‘์ชฝ์˜ ํŽธ๋ฏธ๋ถ„์„ ๋ฌถ์–ด์„œ ($ \frac{\partial{f}}{\partial{x_0}}, \frac{\partial{f}}{\partial{x_1}} $)๋กœ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ($ \frac{\partial{f}}{\partial{x_0}}, \frac{\partial{f}}{\partial{x_1}} $)์ฒ˜๋Ÿผ ๋ชจ๋“  ๋ณ€์ˆ˜์˜ ํŽธ๋ฏธ๋ถ„์„ ๋ฒกํ„ฐ๋กœ ์ •๋ฆฌํ•œ ๊ฒƒ์„ ๊ธฐ์šธ๊ธฐ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์šธ๊ธฐ๋ฅผ ๊ตฌํ•˜๋Š” ํ•จ์ˆ˜๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

def numerical_gradient_no_batch(f: Callable, x: np.array) -> np.array:
    h = 1e-4
    # x์™€ ๊ฐ™์€ ํ˜•์ƒ์˜ 0์œผ๋กœ ๊ตฌ์„ฑ๋œ ๋ฐฐ์—ด ์ƒ์„ฑ
    grad = np.zeros_like(x)

    for idx in range(x.size):
        tmp_val = x[idx]

        # f(x+h) ๊ณ„์‚ฐ
        x[idx] = float(tmp_val) + h
        fxh1 = f(x)

        # f(x-h) ๊ณ„์‚ฐ
        x[idx] = tmp_val - h
        fxh2 = f(x)

        grad[idx] = (fxh1 - fxh2) / (2 * h)
        x[idx] = tmp_val  # ๊ฐ’ ๋ณต์›
    
    return grad

  ๊ธฐ์šธ๊ธฐ์˜ ๊ฒฐ๊ณผ์— ๋งˆ์ด๋„ˆ์Šค๋ฅผ ๋ถ™์ธ ๋ฒกํ„ฐ๋ฅผ ๊ทธ๋ ค๋ณด๋ฉด, ๊ธฐ์šธ๊ธฐ๊ฐ€ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์„ ๋” ์ž˜ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ๊ทธ๋ฆผ 1์€ ๋ฐฉํ–ฅ์„ ๊ฐ€์ง„ ๋ฒกํ„ฐ(ํ™”์‚ดํ‘œ)๋กœ ๊ทธ๋ ค์กŒ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋งˆ์น˜ ํ•จ์ˆ˜์˜ '๊ฐ€์žฅ ๋‚ฎ์€ ์žฅ์†Œ(์ตœ์†Ÿ๊ฐ’)'๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, '๊ฐ€์žฅ ๋‚ฎ์€ ๊ณณ'์—์„œ ๋ฉ€์–ด์งˆ์ˆ˜๋ก ํ™”์‚ดํ‘œ์˜ ํฌ๊ธฐ๊ฐ€ ์ปค์ง„๋‹ค๋Š” ๊ฒƒ ์—ญ์‹œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆผ 1. $  f(x_0, x_1) = x_0^2 + x_1^2 $์˜ ๊ธฐ์šธ๊ธฐ

  ๊ธฐ์šธ๊ธฐ๋Š” ๊ฐ ์ง€์ ์—์„œ ๋‚ฎ์•„์ง€๋Š” ๋ฐฉํ–ฅ์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. ์ •ํ™•ํžˆ ํ‘œํ˜„ํ•˜๋ฉด, ๊ธฐ์šธ๊ธฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ชฝ์€ ๊ฐ ์žฅ์†Œ์—์„œ ํ•จ์ˆ˜์˜ ์ถœ๋ ฅ ๊ฐ’์„ ๊ฐ€์žฅ ํฌ๊ฒŒ ์ค„์—ฌ์ฃผ๋Š” ๋ฐฉํ–ฅ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


2. ์˜ตํ‹ฐ๋งˆ์ด์ €

2.1 ์˜ตํ‹ฐ๋งˆ์ด์ €๋ž€?

  ์˜ตํ‹ฐ๋งˆ์ด์ €๋Š” '์ตœ์ ์„ ํ–‰ํ•˜๋Š” ์ž'๋ผ๋Š” ๋œป์˜ ๋‹จ์–ด์ž…๋‹ˆ๋‹ค. ๊ธฐ๊ณ„ํ•™์Šต(machine learning)์˜ ํ•™์Šต ๋‹จ๊ณ„์—์„œ ์ตœ์ ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ฐพ์•„๋‚ด๋Š” ๊ฒƒ์ด ์˜ตํ‹ฐ๋งˆ์ด์ €์˜ ์—ญํ• ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ตœ์ ์ด๋ž€, ์†์‹ค ํ•จ์ˆ˜๊ฐ€ ์ตœ์†Ÿ๊ฐ’์ด ๋  ๋•Œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ์˜ ์†์‹ค ํ•จ์ˆ˜๋Š” ๋งค์šฐ ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์ƒํ™ฉ์—์„œ ๊ธฐ์šธ๊ธฐ๋ฅผ ์ž˜ ์ด์šฉํ•˜์—ฌ ํ•จ์ˆ˜์˜ ์ตœ์†Ÿ๊ฐ’์„ ์ฐพ๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ์˜ตํ‹ฐ๋งˆ์ด์ €์ž…๋‹ˆ๋‹ค.

  ์—ฌ๊ธฐ์„œ ์ฃผ์˜ํ•  ์ ์€ ๊ฐ ์ง€์ ์—์„œ ํ•จ์ˆ˜์˜ ๊ฐ’์„ ๋‚ฎ์ถ”๋Š” ๋ฐฉ์•ˆ์„ ์ œ์‹œํ•˜๋Š” ์ง€ํ‘œ๊ฐ€ ๊ธฐ์šธ๊ธฐ๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ณต์žกํ•œ ํ•จ์ˆ˜์—์„œ ๊ธฐ์šธ๊ธฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ณณ์ด ์ •๋ง๋กœ ๋‚˜์•„๊ฐ€์•ผ ํ•  ๋ฐฉํ–ฅ์ธ์ง€๋ฅผ ๋ณด์žฅํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ํ•จ์ˆ˜๊ฐ€ ๋ณต์žกํ• ์ˆ˜๋ก ๊ธฐ์šธ๊ธฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐฉํ–ฅ์— ์ตœ์†Ÿ๊ฐ’์ด ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋Œ€๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์•ˆ์žฅ์ (saddle point)๊ณผ ์ง€์—ญ ์ตœ์ ํ•ด(local minima)๊ฐ€ ๊ทธ ๋Œ€ํ‘œ์ ์ธ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆผ 2. ์•ˆ์žฅ์ ๊ณผ ์ง€์—ญ ์ตœ์ ํ•ด(์ถœ์ฒ˜ : wikipedia)

์•ˆ์žฅ์ 
  ์–ด๋Š ๋ฐฉํ–ฅ์—์„œ ๋ณด๋ฉด ๊ทน๋Œ€๊ฐ’์ด๊ณ  ๋‹ค๋ฅธ ๋ฐฉํ–ฅ์—์„œ ๋ณด๋ฉด ๊ทน์†Ÿ๊ฐ’์ด ๋˜๋Š” ์ .
์ง€์—ญ ์ตœ์ ํ•ด
  ์ฃผ์œ„์˜ ๋ชจ๋“  ์ ์˜ ํ•จ์ˆ˜๊ฐ’๋ณด๋‹ค๋Š” ์ดํ•˜์˜ ๊ฐ’์„ ๊ฐ–๋Š” ์ ์ด์ง€๋งŒ, ๋ชจ๋“  ์‹คํ˜„ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆซ๊ฐ’๋ณด๋‹ค๋Š” ๋” ํด ์ˆ˜ ์žˆ๋Š” ์ .

  ์ด์ฒ˜๋Ÿผ ๊ธฐ์šธ์–ด์ง„ ๋ฐฉํ–ฅ์ด ๊ผญ ์ตœ์†Ÿ๊ฐ’์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ, ๊ทธ ๋ฐฉํ–ฅ์œผ๋กœ ๊ฐ€์•ผ ํ•จ์ˆ˜์˜ ๊ฐ’์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ „์—ญ ์ตœ์†Ÿ๊ฐ’(global minimum)์ด ๋˜๋Š” ์žฅ์†Œ๋ฅผ ์ฐพ๋Š” ๋ฌธ์ œ์—์„œ๋Š” ๊ธฐ์šธ๊ธฐ์˜ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋‚˜์•„๊ฐ€์•ผํ•  ๋ฐฉํ–ฅ์„ ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋“ฑ์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์˜ตํ‹ฐ๋งˆ์ด์ €์˜ ์‹œ์ดˆ์ธ ๊ฒฝ์‚ฌํ•˜๊ฐ•๋ฒ•(gradient descent)์ž…๋‹ˆ๋‹ค.

2.2 Stochastic Gradient Descent (SGD)

  ๊ฒฝ์‚ฌํ•˜๊ฐ•๋ฒ•์€ ํ˜„ ์œ„์น˜์—์„œ ์ตœ์†Ÿ๊ฐ’์„ ํ–ฅํ•ด ์ผ์ • ๊ฑฐ๋ฆฌ๋งŒํผ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด๋™ํ•œ ๊ณณ์—์„œ ๋‹ค์‹œ ๊ธฐ์šธ๊ธฐ๋ฅผ ๊ตฌํ•˜๊ณ  ๋˜ ์ตœ์†Ÿ๊ฐ’์„ ํ–ฅํ•ด ๋‚˜์•„๊ฐ€๊ธฐ๋ฅผ ๋ฐ˜๋ณตํ•ฉ๋‹ˆ๋‹ค. ์ตœ์†Ÿ๊ฐ’ ๋„๋‹ฌ์ด๋ผ๋Š” ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๊ฒฝ์‚ฌํ•˜๊ฐ•๋ฒ•์€ ๊ณ„์†ํ•ด์„œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋‹ˆ๋ฐฐ์น˜(mini-batch)๋กœ ๋žœ๋คํ•˜๊ฒŒ ์„ ์ •ํ•˜๋Š” ๊ฒฝ์‚ฌํ•˜๊ฐ•๋ฒ•์„ SGD๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ์ด๋Š” 'ํ™•๋ฅ ์ (stochastic)์œผ๋กœ ๋ฌด์ž‘์œ„ํ•˜๊ฒŒ ๊ณจ๋ผ๋‚ธ ๋ฐ์ดํ„ฐ'์— ๋Œ€ํ•ด ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์‚ฌํ•˜๊ฐ•๋ฒ•์ด๋ผ๋Š” ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. SGD์˜ ์ˆ˜์‹์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$$ \theta_{t} = \theta_{t-1} - \eta \triangledown J(\theta_{t-1}) $$

  • $ \theta $ : ๋งค๊ฐœ๋ณ€์ˆ˜
  • $ \eta $ : ํ•™์Šต๋ฅ (learning rate)
  • $ \triangledown J(\theta) $ : ์†์‹ค ํ•จ์ˆ˜์˜ ๊ธฐ์šธ๊ธฐ
ํ•™์Šต๋ฅ 
  ๊ฐฑ์‹ ํ•˜๋Š” ์–‘. ํ•œ ๋ฒˆ์˜ ํ•™์Šต์œผ๋กœ ์–ผ๋งˆ๋งŒํผ ํ•™์Šตํ•ด์•ผ ํ• ์ง€, ์ฆ‰ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์„ ์–ผ๋งˆ๋‚˜ ๊ฐฑ์‹ ํ•˜๋Š” ์ง€๋ฅผ ์ •ํ•จ

  ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

class SGD:
    def __init__(self, lr: float=0.01) -> None:
        self.lr = lr
    
    def update(self, params: dict, grads: dict) -> None:
        for key in params.keys():
            params[key] -= self.lr * grads[key]

  SGD๋Š” ๋‹จ์ˆœํ•˜๊ณ  ๊ตฌํ˜„ํ•˜๊ธฐ ์‰ฝ์ง€๋งŒ, ๋ฌธ์ œ์— ๋”ฐ๋ผ์„œ ๋น„ํšจ์œจ์ ์ธ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ์ˆ˜์‹์— SGD๋ฅผ ์ ์šฉํ•˜์—ฌ ์ตœ์†Ÿ๊ฐ’์„ ๊ตฌํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ์ƒ๊ฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$$ f(x,y)=\frac{1}{20}x^2+y^2 $$

  ํƒ์ƒ‰์„ ์‹œ์ž‘ํ•˜๋Š” ์ดˆ๊ธฐ๊ฐ’์„ $ (x, y) = (-8.0, 2.0) $์œผ๋กœ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์‹œ๊ฐํ™”ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆผ 3. SGD์— ์˜ํ•œ ์ตœ์ ํ™” ๊ฐฑ์‹  ๊ฒฝ๋กœ

  SGD๋Š” ๊ทธ๋ฆผ 3๊ณผ ๊ฐ™์ด ์‹ฌํ•˜๊ฒŒ ๊ตฝ์ด์ ธ ๋น„ํšจ์œจ์ ์ธ ์›€์ง์ž„์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. SGD์˜ ๋‹จ์ ์€ ๋น„๋“ฑ๋ฐฉ์„ฑ(anisotropy) ํ•จ์ˆ˜์—์„œ๋Š” ํƒ์ƒ‰ ๊ฒฝ๋กœ๊ฐ€ ๋น„ํšจ์œจ์ ์ด๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. SGD ๊ฐ™์ด ๋ฌด์ž‘์ • ๊ธฐ์šธ์–ด์ง„ ๋ฐฉํ–ฅ์œผ๋กœ ์ง„ํ–‰ํ•˜๋Š” ๋‹จ์ˆœํ•œ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๊ธฐ๋ณด๋‹ค ์ด๋ฅผ ๊ฐœ์„ ํ•  ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋น„๋“ฑ๋ฐฉ์„ฑ ํ•จ์ˆ˜
  ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ ์„ฑ์งˆ(์—ฌ๊ธฐ์„œ๋Š” ๊ธฐ์šธ๊ธฐ)์ด ๋‹ฌ๋ผ์ง€๋Š” ํ•จ์ˆ˜

  ์ด์™ธ์—๋„ SGD๋Š” ์ง€์—ญ ์ตœ์ ํ•ด์™€ ์•ˆ์žฅ์ ์—์„œ ๋ฒ—์–ด๋‚˜์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ๋ชจ๋“  ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ ๋™์ผํ•œ ํ•™์Šต ๋ณดํญ(step size)์ด ์ ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋ณ€ํ•œ ๊ฒฐ๊ณผ๋ฅผ ํ•™์Šต์— ๋ฐ˜์˜ํ•˜์ง€ ๋ชปํ•œ๋‹ค๋Š” ๋ฌธ์ œ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ์ƒˆ๋กœ์šด ์˜ตํ‹ฐ๋งˆ์ด์ €๋“ค์ด ๋“ฑ์žฅํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆผ 4. ์˜ตํ‹ฐ๋งˆ์ด์ €์˜ ๋ฐœ๋‹ฌ ๊ณ„๋ณด [ํ•˜์šฉํ˜ธ, 2017]

2.3 SGD + Momentum

  ๋ชจ๋ฉ˜ํ…€(Momentum)์€ '์šด๋™๋Ÿ‰'์„ ๋œปํ•˜๋Š” ๋‹จ์–ด๋กœ ๋ฌผ๋ฆฌ์™€ ๊ด€๊ณ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. SGD๊ฐ€ ์ง€์—ญ ์ตœ์ ํ•ด์™€ ์•ˆ์žฅ์ ์—์„œ ๋ฒ—์–ด๋‚˜์ง€ ๋ชปํ•˜๋˜ ๋ฌธ์ œ๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด SGD์— ๋ชจ๋ฉ˜ํ…€์˜ ๊ฐœ๋…์„ ์ถ”๊ฐ€ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋ชจ๋ฉ˜ํ…€์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์‹์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$$ v_t = \gamma v_{t-1}-\eta\triangledown J(\theta_{t-1}) $$

$$ \theta_{t} = \theta_{t-1} + v_t $$

  • $ v_t $ : ์†๋„(velocity)

  ์œ„ ๊ณต์‹์—์„œ $ \gamma v_t $๋Š” ๋ฌผ์ฒด๊ฐ€ ์•„๋ฌด๋Ÿฐ ํž˜์„ ๋ฐ›์ง€ ์•Š์„ ๋•Œ ์„œ์„œํžˆ ํ•˜๊ฐ•์‹œํ‚ค๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค($ \gamma $๋Š” 0.9 ๋“ฑ์˜ ๊ฐ’์œผ๋กœ ์„ค์ •). $ \gamma $๋Š” ๋ฌผ๋ฆฌ์—์„œ ์ง€๋ฉด ๋งˆ์ฐฐ์ด๋‚˜ ๊ณต๊ธฐ ์ €ํ•ญ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋ฉ˜ํ…€์˜ ์†๋„ ๊ฐœ๋…์„ ํ†ตํ•ด ์ตœ์†Ÿ๊ฐ’์—์„œ ๋ฐ”๋กœ ๋ฉˆ์ถ”์ง€ ์•Š๊ณ  '์˜ค๋ฒ„์ŠˆํŒ…(Overshooting)'ํ•˜์—ฌ ์ง€์—ญ ์ตœ์ ํ•ด์™€ ์•ˆ์žฅ์ ์„ ํ†ต๊ณผํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋ฉ˜ํ…€์„ ๊ตฌํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

class momentum:
    def __init__(self, lr: float=0.01, momentum: float=0.9) -> None:
        self.lr = lr
        self.m = momentum
        self.v = None
    
    def update(self, params: dict, grads: dict) -> None:
        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.m * self.v[key] - self.lr * grads[key]
            params[key] += self.v[key]

  ์ฝ”๋“œ์—์„œ ๋ณ€์ˆ˜ v๋Š” ๋ฌผ์ฒด์˜ ์†๋„๋ฅผ ๋œปํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์‹œ๊ฐํ™”ํ•˜๋ฉด ์•„๋ž˜ ๊ทธ๋ฆผ 5์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆผ 5. SGD+momentum์— ์˜ํ•œ ์ตœ์ ํ™” ๊ฐฑ์‹  ๊ฒฝ๋กœ

  ๊ทธ๋ฆผ 5์—์„œ ๊ฐฑ์‹  ๊ฒฝ๋กœ๊ฐ€ SGD์— ๋น„ํ•˜์—ฌ ๋ถ€๋“œ๋Ÿฌ์›Œ์ง„ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” $ x $์ถ•์˜ ํž˜์€ ์•„์ฃผ ์ž‘์ง€๋งŒ ๋ฐฉํ–ฅ์€ ๋ณ€ํ•˜์ง€ ์•Š์•„์„œ ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ ์ผ์ •ํ•˜๊ฒŒ ๊ฐ€์†ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ฐ˜๋Œ€๋กœ $ y $์ถ•์˜ ํž˜์€ ํฌ์ง€๋งŒ ์œ„์•„๋ž˜๋กœ ๋ฒˆ๊ฐˆ์•„ ๋ฐ›์•„์„œ ์ƒ์ถฉํ•˜์—ฌ $ y $์ถ• ๋ฐฉํ–ฅ์˜ ์†๋„๋Š” ์•ˆ์ •์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  ๋˜ํ•œ, ๊ทธ๋ฆผ 5์—์„œ ์ „์—ญ ์ตœ์†Ÿ๊ฐ’์—์„œ๋„ ๋ฐ”๋กœ ๋ฉˆ์ถ”๊ฑฐ๋‚˜ ๋Šฆ์ถฐ์ง€์ง€ ์•Š๊ณ  ์ง€๋‚˜์ณ๊ฐ€๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ง€์—ญ ์ตœ์ ํ•ด๋‚˜ ์•ˆ์žฅ์ ์„ ํ†ต๊ณผํ•˜๋Š”๋ฐ๋Š” ์œ ํšจํ•˜์˜€์ง€๋งŒ, ์ „์—ญ ์ตœ์†Ÿ๊ฐ’์—์„œ ๋น ๋ฅด๊ฒŒ ์ˆ˜๋ ดํ•˜์ง€ ์•Š์•„ ํ•™์Šต ์‹œ๊ฐ„์ด ๋Š˜์–ด๋‚œ๋‹ค๋Š” ๋ฌธ์ œ๋กœ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

2.4 Nesterov Accelerated Gradient (NAG)

  ๋ชจ๋ฉ˜ํ…€์€ ๊ฐฑ์‹  ๊ณผ์ •์—์„œ ํ˜„์žฌ์˜ ๊ธฐ์šธ๊ธฐ ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค์Œ ๋‹จ๊ณ„์˜ ๊ฐ’์„ ๋„์ถœํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ด€์„ฑ์— ์˜ํ•ด ์ตœ์ ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง€๋‚˜์น  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ฌธ์ œ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค. NAG์—์„œ๋Š” ๋ชจ๋ฉ˜ํ…€์œผ๋กœ ์ด๋™ํ•œ ์ง€์ ์—์„œ์˜ ๊ธฐ์šธ๊ธฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ฐฑ์‹ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ˆ˜์‹์œผ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

$$ v_t = \gamma v_{t-1}-\eta\triangledown J(\theta_{t-1}-\gamma v_{t-1}) $$

$$ \theta_{t} = \theta_{t-1} + v_t $$

  ๋ชจ๋ฉ˜ํ…€๊ณผ ๋‹ฌ๋ฆฌ $ v_t $๋ฅผ ๊ตฌํ•  ๋•Œ, $ \triangledown J(\theta-\gamma v_{t-1}) $๊ณผ ๊ฐ™์ด ๊ด€์„ฑ์— ์˜ํ•˜์—ฌ ์ด๋™ํ•œ ๊ณณ์˜ ๊ธฐ์šธ๊ธฐ๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ด€์„ฑ์— ์˜ํ•˜์—ฌ ๋น ๋ฅด๊ฒŒ ์ด๋™ํ•˜๋Š” ์ด์ ์„ ์ ์šฉํ•˜๋ฉด์„œ๋„ ์ˆ˜๋ ดํ•ด์•ผ ํ•˜๋Š” ๊ณณ์—์„œ ํšจ๊ณผ์ ์œผ๋กœ ๋ฉˆ์ถ”๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. NAG์™€ ๋ชจ๋ฉ˜ํ…€์˜ ์›€์ง์ž„์„ ๋น„๊ตํ•˜๋ฉด ์•„๋ž˜์˜ ๊ทธ๋ฆผ 6๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆผ 6. ๋ชจ๋ฉ˜ํ…€ ๊ฐฑ์‹ ๊ณผ NAG์˜ ๋ชจ๋ฉ˜ํ…€ ๊ฐฑ์‹  ๋น„๊ต(์ถœ์ฒ˜ : CS231N)

  NAG๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class momentum:
    def __init__(self, lr: float=0.01, momentum: float=0.9,
                 nesterov : bool=False) -> None:
        self.lr = lr
        self.m = momentum
        self.v = None
        self.nesterov = nesterov
    
    def update(self, params: dict, grads: dict) -> None:
        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():
            if self.nesterov:  # NAG
                self.v[key] = self.m * self.v[key] - self.lr * grads[key]
                params[key] += (self.m * self.v[key] - self.lr * grads[key])
            else:  # vanila momentum
                self.v[key] = self.m * self.v[key] - self.lr * grads[key]
                params[key] += self.v[key]

  ๊ธฐ์กด์˜ ๋ชจ๋ฉ˜ํ…€ ํด๋ž˜์Šค์— nesterov ์—ฌ๋ถ€๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์‹œ๊ฐํ™”ํ•œ ๊ฒฐ๊ณผ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆผ 7. NAG์— ์˜ํ•œ ์ตœ์ ํ™” ๊ฐฑ์‹  ๊ฒฝ๋กœ

  ๋ชจ๋ฉ˜ํ…€๊ณผ ๋™์ผํ•˜๊ฒŒ ์˜ค๋ฒ„์ŠˆํŒ…์„ ํ†ตํ•ด ์ „์—ญ ์ตœ์†Ÿ๊ฐ’์„ ์ง€๋‚˜์น˜์ง€๋งŒ, ๋ชจ๋ฉ˜ํ…€์— ๋น„ํ•ด ๋” ๋น ๋ฅด๊ฒŒ ์ˆ˜๋ ดํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  (์Šคํ… ์‚ฌ์ด์ฆˆ๋ฅผ ๊ฐœ์„ ํ•œ ์˜ตํ‹ฐ๋งˆ์ด์ €๋Š” ๋‹ค์Œ ๊ธ€์—์„œ ์ด์–ด์ง‘๋‹ˆ๋‹ค)


์ฐธ๊ณ ์ž๋ฃŒ ์ถœ์ฒ˜

- ํ•˜์šฉํ˜ธ, "์ž์Šตํ•ด๋„ ๋ชจ๋ฅด๊ฒ ๋˜ ๋”ฅ๋Ÿฌ๋‹, ๋จธ๋ฆฌ์†์— ์ธ์Šคํ†จ ์‹œ์ผœ๋“œ๋ฆฝ๋‹ˆ๋‹ค.", https://www.slideshare.net/yongho/ss-79607172, 2017

- CS213N, "Convolutional Neural Networks for Visual Recognition", https://cs231n.github.io/neural-networks-3/, 2021