DonHurry

step47. ์†Œํ”„ํŠธ๋งฅ์Šค ํ•จ์ˆ˜์™€ ๊ต์ฐจ ์—”ํŠธ๋กœํ”ผ ์˜ค์ฐจ ๋ณธ๋ฌธ

DeZero/๐Ÿ—ป์ œ4๊ณ ์ง€

step47. ์†Œํ”„ํŠธ๋งฅ์Šค ํ•จ์ˆ˜์™€ ๊ต์ฐจ ์—”ํŠธ๋กœํ”ผ ์˜ค์ฐจ

_๋„๋… 2023. 2. 27. 19:13

๐Ÿ“ข ๋ณธ ํฌ์ŠคํŒ…์€ ๋ฐ‘๋ฐ”๋‹ฅ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ๋”ฅ๋Ÿฌ๋‹3์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋ฐฐ์šด ๋‚ด์šฉ์„ ๊ธฐ๋กํ•˜๊ณ , ๊ฐœ์ธ์ ์ธ ๊ณต๋ถ€๋ฅผ ์œ„ํ•ด ์ž‘์„ฑํ•˜๋Š” ํฌ์ŠคํŒ…์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ต์žฌ ๊ตฌ๋งค๋ฅผ ๊ฐ•๋ ฅ ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

 

 

์ด์ „ ๋‹จ๊ณ„๊นŒ์ง€๋Š” ์‹ ๊ฒฝ๋ง์„ ํ™œ์šฉํ•˜์—ฌ ํšŒ๊ท€ ๋ฌธ์ œ๋ฅผ ํ’€์—ˆ์Šต๋‹ˆ๋‹ค. ์•ž์œผ๋กœ๋Š” DeZero๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ƒˆ๋กœ์šด ์œ ํ˜•์˜ ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ค์ค‘ ํด๋ž˜์Šค ๋ถ„๋ฅ˜(multi-class classification) ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ์šฐ์„  ์ด๋ฒˆ ๋‹จ๊ณ„์—์„œ๋Š” ์‚ฌ์ „ ์ค€๋น„๋ฅผ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋จผ์ € get_item์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Variable์˜ ๋‹ค์ฐจ์› ๋ฐฐ์—ด ์ค‘์—์„œ ์ผ๋ถ€๋ฅผ ์Šฌ๋ผ์ด์Šคํ•˜์—ฌ ๋ฝ‘์•„์ฃผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. DeZero ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์—ญ์ „ํŒŒ๋„ ์ˆ˜ํ–‰ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

import numpy as np
from dezero import Variable
import dezero.functions as F

x = Variable(np.array([[1, 2, 3], [4, 5, 6]])
y = F.get_item(x, 1)
print(y)  # variable([4 5 6])

 

์Šฌ๋ผ์ด์Šค๋กœ ์ธํ•œ ๊ณ„์‚ฐ์€ ๋‹ค์ฐจ์› ๋ฐฐ์—ด์˜ ๋ฐ์ดํ„ฐ ์ผ๋ถ€๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์—ญ์ „ํŒŒ๋Š” ๊ธฐ์กด ๋‹ค์ฐจ์› ๋ฐฐ์—ด์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ถ”์ถœ๋œ ์œ„์น˜์— ํ•ด๋‹น ๊ธฐ์šธ๊ธฐ๋ฅผ ์„ค์ •ํ•˜๊ณ , ๋‚˜๋จธ์ง€๋Š” 0์œผ๋กœ ์ฑ„์›๋‹ˆ๋‹ค.

 

 

Variable.__getitem__ = F.get_item ๊ณผ ๊ฐ™์ด Variable์˜ ๋ฉ”์„œ๋“œ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ ์ด ํŠน์ˆ˜ ๋ฉ”์„œ๋“œ๋Š” dezero์˜ core.py์˜ setup_variable์—์„œ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ์จ Variable ์ธ์Šคํ„ด์Šค๋ฅผ ์›ํ•˜๋Š”๋Œ€๋กœ ์Šฌ๋ผ์ด์Šคํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค get_item ํ•จ์ˆ˜์˜ ์‹ค์ œ ๊ตฌํ˜„๊ณผ ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์„ค๋ช…์ด ๋ถ€๋ก์œผ๋กœ ์ถ”๊ฐ€๋˜์–ด์žˆ๋Š”๋ฐ, ๋ฉ”์ธ ๊ณผ์ •์€ ์•„๋‹ˆ๋ฏ€๋กœ ๋ณธ ์ฃผ์ œ๋กœ ๋„˜์–ด๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์šฐ์„  ์†Œํ”„ํŠธ๋งฅ์Šค ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์†Œํ”„ํŠธ ๋งฅ์Šค ํ•จ์ˆ˜๋Š” ์ˆ˜์น˜๋กœ ๋‚˜์˜ค๋Š” ์‹ ๊ฒฝ๋ง์˜ ์ถœ๋ ฅ์„ ํ™•๋ฅ ๋กœ ๋ณ€ํ™˜ํ•ด์ค๋‹ˆ๋‹ค. ํ•จ์ˆ˜์˜ ์ž…๋ ฅ $yk$๊ฐ€ ์ด n๊ฐœ(ํด๋ž˜์Šค ์ˆ˜)๋ผ๊ณ  ๊ฐ€์ •ํ•˜๊ณ , k๋ฒˆ์งธ ์ถœ๋ ฅ $pk$๋ฅผ ๊ตฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ๋ถ„์ž๋Š” ์ž…๋ ฅ $yk$์˜ ์ง€์ˆ˜ ํ•จ์ˆ˜๊ณ , ๋ถ„๋ชจ๋Š” ๋ชจ๋“  ์ž…๋ ฅ์˜ ์ง€์ˆ˜ ํ•จ์ˆ˜์˜ ์ดํ•ฉ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ $0 <= pi <= 1$์ด๊ณ , ๋ชจ๋“  p๊ฐ’์˜ ํ•ฉ์ด 1์ด ๋ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ์›์†Œ ๊ฐ๊ฐ(p1, p2, ..., pn)์„ ํ™•๋ฅ ๋กœ ํ•ด์„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

 

์ด์ œ DeZero์˜ ์†Œํ”„ํŠธ๋งฅ์Šค ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ •ํ™•ํ•œ ๊ตฌํ˜„์€ ๊นƒํ—ˆ๋ธŒ์— ์žˆ๊ณ , ์—ฌ๊ธฐ์„œ๋Š” ๊ฐ„๋‹จํ•œ ๋ฒ„์ „์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

from dezero import Variable, as_variable
import dezero.functions as F


def softmax1d(x):
    x = as_variable(x)
    y = F.exp(x)
    sum_y = F.sum(y)
    return y / sum_y


model = MLP((10, 3))

x = np.array([[0.2, -0.4]])
y = model(x)
p = softmax1d(y)
print(y)
print(p)

variable([[0.72107507 0.46316368 0.21703336]])
variable([[0.42074299 0.32509283 0.25416418]])

 

๋งŒ์•ฝ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•˜๋‚˜์ธ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐฐ์น˜ ๋ฐ์ดํ„ฐ์—๋„ ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ํ™•์žฅํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋งŒ์œผ๋กœ ์˜ฌ๋ฐ”๋ฅธ ๊ฒฐ๊ณผ๊ฐ€ ๋„์ถœ๋˜๊ธฐ๋Š” ํ•˜์ง€๋งŒ, ๊ฐœ์„ ์„ ์œ„ํ•ด์„œ๋Š” Function ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜์—ฌ Softmax ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์€ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค. (dezero/functions.py์— ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.)

def softmax_simple(x, axis=1):
    x = as_variable(x)
    y = exp(x)
    sum_y = sum(y, axis=axis, keepdims=True)
    return y / sum_y

 

๋‹ค์Œ์€ ๊ต์ฐจ ์—”ํŠธ๋กœํ”ผ ์˜ค์ฐจ์ž…๋‹ˆ๋‹ค. ์„ ํ˜• ํšŒ๊ท€ ๋ฌธ์ œ์—์„œ๋Š” ํ‰๊ท  ์ œ๊ณฑ ์˜ค์ฐจ๋ฅผ ์ด์šฉํ–ˆ์ง€๋งŒ, ๋‹ค์ค‘ ํด๋ž˜์Šค ๋ถ„๋ฅ˜์—๋Š” ๊ต์ฐจ ์—”ํŠธ๋กœํ”ผ ์˜ค์ฐจ๊ฐ€ ๋” ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์‹์˜ ์ •์˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

 

$tk$๋Š” ์ •๋‹ต ๋ฐ์ดํ„ฐ์˜ k์ฐจ์›์งธ ๊ฐ’์„ ๋‚˜ํƒ€๋‚ด๋Š”๋ฐ, ์ •๋‹ต ๋ฐ์ดํ„ฐ ์›์†Œ๋Š” ์ •๋‹ต์ด๋ฉด 1, ์•„๋‹Œ ๊ฒฝ์šฐ์—๋Š” 0์œผ๋กœ ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ •๋‹ต์„ ์ œ์™ธํ•œ ํ™•๋ฅ ๋“ค์€ ๋Œ€์ž…ํ•˜๋ฉด 0์ด ๋˜๋ฏ€๋กœ, ์ •๋‹ต ํด๋ž˜์Šค์— ํ•ด๋‹นํ•˜๋Š” ํ™•๋ฅ  p๋งŒ ์ถ”์ถœํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค.

 

 

์ง€๊ธˆ๊นŒ์ง€์˜ ์„ค๋ช…์€ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•˜๋‚˜์ธ ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ คํ–ˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋ฐ์ดํ„ฐ๊ฐ€ N๊ฐœ, ์ฆ‰ ์—ฌ๋Ÿฌ๊ฐœ๋ผ๋ฉด ๊ฐ ๋ฐ์ดํ„ฐ์—์„œ ์˜ค์ฐจ๋ฅผ ๊ตฌํ•˜๊ณ , ์ „์ฒด๋ฅผ ๋”ํ•œ ๋‹ค์Œ N์œผ๋กœ ๋‚˜๋ˆ„์–ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ‰๊ท  ๊ต์ฐจ ์—”ํŠธ๋กœํ”ผ ์˜ค์ฐจ๋ฅผ ๊ตฌํ•œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

 

์ด์ œ ์‹ค์ œ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์œ„์—์„œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์—ฌ๊ธฐ์„œ๋Š” ๊ฐ„๋‹จํ•œ ๋ฒ„์ „์˜ ๊ตฌํ˜„์„ ๋‹ค๋ฃจ๋ฏ€๋กœ, ์‹ค์ œ ๊ตฌํ˜„์€ ๊นƒํ—ˆ๋ธŒ๋ฅผ ์ฐธ๊ณ ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

 

์•„๋ž˜ ํ•จ์ˆ˜์—์„œ x๋Š” ์†Œํ”„ํŠธ๋งฅ์Šค ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•˜๊ธฐ ์ „์˜ ์ถœ๋ ฅ์ด๊ณ , t๋Š” ์ •๋‹ต ๋ฐ์ดํ„ฐ์ž…๋‹ˆ๋‹ค. p = softmax(x)์—์„œ ์ถœ๋ ฅ์€ 0 ์ด์ƒ 1 ์ดํ•˜์˜ ์ˆ˜์ธ๋ฐ, ์ด์–ด์ง€๋Š” ๋กœ๊ทธ ๊ณ„์‚ฐ์—์„œ log ํ•จ์ˆ˜์— 0์„ ์ž…๋ ฅํ•˜๋ฉด ๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฏ€๋กœ ์ด์— ๋Œ€ํ•œ ๋Œ€์ฒ˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. clip์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ, 0์ธ ๊ฒฝ์šฐ์— ์ž‘์€ ๊ฐ’์ด 1e-15๋กœ ๋Œ€์ฒดํ•ด์ค๋‹ˆ๋‹ค.

def softmax_cross_entropy_simple(x, t):
    x, t = as_variable(x), as_variable(t)
    N = x.shape[0]
    p = softmax(x)  # softmax_simple(x)
    p = clip(p, 1e-15, 1.0)  # to avoid log(0)
    log_p = log(p)  # log๋Š” DeZero ํ•จ์ˆ˜
    tlog_p = log_p[np.arange(N), t.data]
    y = -1 * sum(tlog_p) / N
    return y

 

์ด์ œ ์ž…๋ ฅ ๋ฐ์ดํ„ฐ x์™€ ์ •๋‹ต ๋ฐ์ดํ„ฐ t๋ฅผ ์ค€๋น„ํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ •์ƒ์ ์œผ๋กœ ์ง„ํ–‰๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ๋‹ค์ค‘ ํด๋ž˜์Šค ๋ถ„๋ฅ˜๋ฅผ ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

x = np.array([[0.2, -0.4], [0.3, 0.5], [1.3, -3.2], [2.1, 0.3]])
t = np.array([2, 0, 1, 0])

y = model(x)
p = F.softmax(y)

loss = F.softmax_cross_entropy(y, t)
loss.backward()
print(loss)

variable(1.001130001089163)