728x90
๋ฐ์ํ
5-1) ๊ณ์ฐ ๊ทธ๋ํ
- ๊ณ์ฐ ๊ณผ์ ์ ๊ทธ๋ํ๋ก ๋ํ๋ธ ๊ฒ
- ๋ ธ๋(node)/ ์์ง(edge): ๋ ธ๋ ์ฌ์ด์ ์ง์ ์ ์์ง๋ผ๊ณ ๋ถ๋ฆ

⇒ ์์ ํ๋ผ๊ณ ํจ(์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ์ผ๋ก ์งํ)
๊ตญ์์ ๊ณ์ฐ
- ์ ์ฒด์ ์ผ๋ก ๋ณด๋ฉด ๋ณต์กํ ๊ณ์ฐ์์ด์ง๋ง ํ๊ณ ๋ค๋ฉด ๊ฐ๋จํ ์์์ผ๋ก ์ด๋ฃจ์ด์ ธ ์๋ ⇒ ๊ตญ์์ ๊ณ์ฐ์ด๋ผ๊ณ ํจ.( ์ ์ฒด ์์ ๊ฐ๋ณต์ก but, ์์ผ๋ก ๋ค์ด๊ฐ๋ฉด ๋ง์ ๋บ์ ์ผ๋ก ์ด๋ฃจ์ด์ง)
๊ณ์ฐ ๊ทธ๋ํ์ ์ด์
- ๊ตญ์์ ๊ณ์ฐ
- ์ ์ฒด๊ฐ ๋ณต์กํด๋ ์์์๋ ๊ฐ๋จํ๊ฒ ๋ฌธ์ ๋จ์ํํด์ ํ ์ ์์
- ์ค๊ฐ ์ค๊ฐ์ ๊ณ์ฐ ๊ฒฐ๊ณผ ์ ์ฅ ๊ฐ๋ฅ
- ์ญ์ ํ๋ฅผ ํตํด ‘๋ฏธ๋ถ’์ ํจ์จ์ ์ผ๋ก ๊ณ์ฐ ๊ฐ๋ฅ
5-2) ์ฐ์ ๋ฒ์น
- ํฉ์ฑ ํจ์์ ๋ฏธ๋ถ์ ๋ํ ์ฑ์ง
- ํฉ์ฑ ํจ์์ ๋ฏธ๋ถ: ํฉ์ฑ ํจ์๋ฅผ ๊ตฌ์ฑํ๋ ๊ฐ ํจ์์ ๋ฏธ๋ถ์ ๊ณฑ์ผ๋ก ๋ํ๋ผ ์ ์๋ค
5-3) ์ญ์ ํ
5-4) ๋จ์ ๊ณ์ธต ๊ตฌํ
- ๊ณฑ์ ๊ณ์ธต
class MulLayer: def __init__(self): self.x = None self.y = None def forward(self, x, y): self.x = x self.y = y out = x * y return out def backward(self, dout): dx = dout * self.y # x์ y๋ฅผ ๋ฐ๊พผ๋ค. dy = dout * self.x return dx, dy
from layer_naive import * 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) # 220 # ์ญ์ ํ 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
- ๋ง์ ๊ณ์ธต
class AddLayer: def __init__(self): pass def forward(self, x, y): out = x + y return out def backward(self, dout): dx = dout * 1 dy = dout * 1 return dx, dy
5-5) ํ์ฑํ ํจ์ ๊ณ์ธต ๊ตฌํ(ReLU, Sigmoid)
ReLU ๊ณ์ธต
class Relu: def __init__(self): self.mask = None def forward(self, x): self.mask = (x <= 0) out = x.copy() out[self.mask] = 0 return out def backward(self, dout): dout[self.mask] = 0 dx = dout return dx
- x๊ฐ 0๋ณด๋ค ํฌ๋ฉด ์ญ์ ํ์ ๊ฒฝ์ฐ, ์๋ฅ ๊ฐ์ ํ๋ฅ๋ก ๊ทธ๋๋ก ์ ๋ฌ
- x๊ฐ 0๋ณด๋ค ์์ผ๋ฉด 0์ผ๋ก ์ ๋ฌ
Sigmoid ๊ณ์ธต
- ๊ตฌ์ฒดํ ๋ฒ์ (์)
- ๊ฐ์ํ ๋ฒ์
- ์ญ์ ํ์ ๊ฒฝ์ฐ, ์์ ํ ์ถ๋ ฅ(y)๋ง์ผ๋ก ๊ตฌํ ๊ฐ๋ฅ
class Sigmoid: def __init__(self): self.out = None def forward(self, x): out = sigmoid(x) # ์์ ํ์ ์ถ๋ ฅ์ out์ ๋ณด๊ดํ ํ ์ญ์ ํ ๊ณ์ฐ ๋ ๊ทธ ๊ฐ์ ์ฌ์ฉ self.out = out return out def backward(self, dout): dx = dout * (1.0 - self.out) * self.out return dx
5-6) Affine/Softmax ๊ณ์ธต ๊ตฌํ
Affine ๊ณ์ธต
๋ฐฐ์น์ฉ Affine ๊ณ์ธต
- ๋ฐ์ดํฐ N๊ฐ๋ฅผ ๋ฌถ์ ๊ฒฝ์ฐ

class Affine: def __init__(self, W, b): self.W = W self.b = b self.x = None self.original_x_shape = None # ๊ฐ์ค์น์ ํธํฅ ๋งค๊ฐ๋ณ์์ ๋ฏธ๋ถ self.dW = None self.db = None def forward(self, x): # ํ
์ ๋์ self.original_x_shape = x.shape x = x.reshape(x.shape[0], -1) self.x = x out = np.dot(self.x, self.W) + self.b return out def backward(self, dout): dx = np.dot(dout, self.W.T) self.dW = np.dot(self.x.T, dout) self.db = np.sum(dout, axis=0) dx = dx.reshape(*self.original_x_shape) # ์
๋ ฅ ๋ฐ์ดํฐ ๋ชจ์ ๋ณ๊ฒฝ(ํ
์ ๋์) return dx
- ์์ ํ์ ํธํฅ ๋ง์ : ๊ฐ ๋ฐ์ดํฐ์ ํธํฅ์ด ๋ํด์ง
- ์ญ์ ํ์ ํธํฅ: ๋ฐ์ดํฐ์ ํฉ์ ๊ตฌํ ๋ค ๋ฏธ๋ถ์ผ๋ก ํธํฅ ๊ตฌํจ
Softmax-with-Loss ๊ณ์ธต
- ์ํํธ ๋งฅ์: ์ ๊ทํ, ์ถ๋ ฅ์ธต์์ ์ฌ์ฉ, ์ถ๋ ฅํฉ: 1

- ์ ์๋ฅผ ํ๋ฅ ์ ๋ฒ์๋ก (0~1 ์ฌ์ด๋ก ์ ๊ทํ)
- but ์ถ๋ก ํ ๋๋ ๊ตณ์ด ์ ์ ์ค ๋์ ๊ฐ์ ๊ณ ๋ฅด๋ฉด ๋๊ธฐ์ ํ๋ฅ ๋ก ๋ณํํด์ค ํ์๊ฐ ์์ ⇒ ์ํํธ ๋งฅ์ค ์ฌ์ฉ ์์ (ํ์ต ์์๋ ์ฌ์ฉ)

- ์ถ๋ ฅ๊ฐ-์ ๋ต๊ฐ( softmax ๊ณ์ธต์ ์ถ๋ ฅ๊ณผ ์ ๋ต ๋ ์ด๋ธ์ ์ฐจ๋ถ์ ์๋ฏธ)
- ์ ๊ฒฝ๋ง์ ๋ชฉํ๋ ์ถ๋ ฅ๊ฐ์ด ์ ๋ต๊ณผ ๊ฐ๊น์์ง๋๋ก ๊ฐ์ค์น ๋งค๊ฐ๋ณ์๋ฅผ ์กฐ์ ํ๋ ๊ฒ์.
- (์ถ๋ ฅ-์ ๋ต๊ฐ) ์ด ์ค์ฐจ๊ฐ ์ ๊ณ์ธต์ ์ ๋ฌ๋จ ⇒ ์ค์ฐจ๋ฅผ ํจ์จ์ ์ผ๋ก ์ ๊ณ์ธต์ ์ ๋ฌํด์ผ.
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) self.loss = cross_entropy_error(self.y, self.t) return self.loss def backward(self, dout=1): batch_size = self.t.shape[0] if self.t.size == self.y.size: # ์ ๋ต ๋ ์ด๋ธ์ด ์-ํซ ์ธ์ฝ๋ฉ ํํ์ผ ๋ dx = (self.y - self.t) / batch_size else: dx = self.y.copy() dx[np.arange(batch_size), self.t] -= 1 dx = dx / batch_size return dx
5-7) ์ค์ฐจ์ญ์ ํ๋ฒ ๊ตฌํ
๊ตฌํ ๋จ๊ณ
- ์ ์ : ๊ฐ์ค์น์ ํธํฅ์ ํ๋ จ ๋ฐ์ดํฐ์ ์ ์ํ๋๋ก ์กฐ์ ํ๋ ๊ณผ์ (=ํ์ต)
- 1๋จ๊ณ- ๋ฏธ๋๋ฐฐ์น
- ๋ฌด์์ ๋ฐ์ดํฐ ์ฐ์ถ(๋ฏธ๋๋ฐฐ์น), ๋ฏธ๋๋ฐฐ์น์ ์์ค ํจ์ ๊ฐ์ ์ค์ด๋ ๊ฒ์ด ๋ชฉํ
- 2๋จ๊ณ- ๊ธฐ์ธ๊ธฐ ์ฐ์ถ
- ์์คํจ์ ๊ฐ์ ์ค์ด๊ธฐ ์ํด ๊ฐ ๊ฐ์ค์น ๋งค๊ฐ๋ณ์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ตฌํจ ⇒ ์์คํจ์ ๊ฐ ์๋๋ก ๋ฐฉํฅ ์ ์
- 3๋จ๊ณ- ๋งค๊ฐ๋ณ์ ๊ฐฑ์
- ๊ธฐ์ธ๊ธฐ ๋ฐฉํฅ์ผ๋ก ๊ฐฑ์
- 4๋จ๊ณ- 1~3๋จ๊ณ ๋ฐ๋ณต
์ฝ๋
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() #๊ฐ ์ ์ฅ(์ญ์ ํ ๋ input ๋ฐ๊ฟ์ ๊ณ์ฐํ๊ธฐ ๋๋ฌธ!) 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
๊ธฐ์ธ๊ธฐ ๊ฒ์ฆํ๊ธฐ
- ์์น ๋ฏธ๋ถ vs (ํด์์ ์์)์ค์ฐจ์ญ์ ํ๋ฒ
- ์์น๋ฏธ๋ถ๊ณผ ์ค์ฐจ์ญ์ ํ๋ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋น๊ต ⇒ ์ค์ฐจ์ญ์ ํ๋ฒ์ ์ ๋๋ก ๊ตฌํํ๋๊ฐ์ ๋ํ ๊ฒ์ฆ ⇒ ๊ธฐ์ธ๊ธฐ ํ์ธ
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))
728x90
๋ฐ์ํ