λ°λ°λ₯λΆν° μμνλ λ₯λ¬λ 3 : https://www.hanbit.co.kr/store/books/look.php?p_code=B6627606922
μμ€μ½λ : https://github.com/WegraLee/deep-learning-from-scratch-3
- λͺ©μ°¨
- ν
μ μ¬μ© μμ μμ ν
- λνμ΄μ λΈλ‘λμΊμ€νΈ(broadcast) : νΌμ°μ°μμ νμμ΄ λ€λ₯΄λ©΄ μλμΌλ‘ λ°μ΄ν°λ₯Ό 볡μ¬νμ¬ κ°μ νμμ ν μλ‘ λ³νν΄μ£Όλ κΈ°λ₯
- ν μ μ¬μ© μμ μμ ν
β» μ£Όμ : Functionμ backward λ΄μμ λͺ¨λ Variable μΈμ€ν΄μ€λ₯Ό μ¬μ©νλ―λ‘ κ΅¬νν λ DeZero ν¨μλ₯Ό μ¬μ©ν΄μΌ νλ€.
-
νμ λ³ν ν¨μ
reshape
: ν μμ νμμ λ°κΎΈλ ν¨μ - [FunctionμΌλ‘ ꡬν | Variable ν΄λμ€μ μΆκ°]- μμ ν :
numpyμ reshape
ν¨μ μ¬μ© - μμ ν : κΈ°μΈκΈ°μ νμμ΄ μ λ ₯μ νμκ³Ό κ°μμ§λλ‘ λ³ν
- μμ ν :
transpose
: νλ ¬μ μ μΉν΄μ£Όλ ν¨μ - [FunctionμΌλ‘ ꡬν | Variable ν΄λμ€μ μΆκ°]- μμ ν :
numpyμ transpose
ν¨μ μ¬μ© - μμ ν : μΆλ ₯ μͺ½μμ μ ν΄μ§λ κΈ°μΈκΈ°μ νμμ μμ ν λμ λ°λ ννλ‘ λ³κ²½
- μμ ν :
-
ν©κ³ ν¨μ
sum
: μμκ° 2κ° μ΄μμΈ λ²‘ν°μ ν© - [FunctionμΌλ‘ ꡬν | Variable ν΄λμ€μ μΆκ°]- μμ ν :
numpyμ sum
ν¨μ μ¬μ© - μμ ν : κΈ°μΈκΈ°λ₯Ό μ
λ ₯ λ³μμ νμκ³Ό κ°μμ§λλ‘ λ³΅μ¬νλ€. (μλ
broadcast_to
ν¨μ μ¬μ©)- axis, keepdim μ§μμΌλ‘ μΈν΄ κΈ°μΈκΈ°μ νμμ λ³ννλ κ²½μ°κ° μκΈ°κΈ° λλ¬Έμ μ΄μ λμνλ ν¨μ : [utilsμ ꡬν]
- μμ ν :
-
λΈλ‘λμΊμ€νΈ ν¨μ
broadcast_to
: xμ μμλ₯Ό 볡μ νμ¬ shapeμΈμλ‘ μ§μ ν νμμ΄ λλλ‘ νλ€. - [FunctionμΌλ‘ ꡬν]- μμ ν :
numpyμ broadcast_to
ν¨μ μ¬μ© - μμ ν : 'μμ 볡μ¬'κ° μΌμ΄λ κ²½μ°, μμ ν λλ κΈ°μΈκΈ°μ 'ν©'μ ꡬνλ€. (μλ
sum_to
ν¨μ μ¬μ©)
- μμ ν :
sum_to
: xμ μμμ ν©μ κ΅¬ν΄ shape νμμΌλ‘ λ§λ€μ΄μ£Όλ ν¨μ - [FunctionμΌλ‘ ꡬν]- μμ ν : numpyμ sum_to ν¨μ μμ - [utilsμ ꡬν | (μ°Έκ³ )chainerμ μ½λ]
- μμ ν : μ
λ ₯ xμ νμμ΄ κ°μμ§λλ‘ κΈ°μΈκΈ°μ μμ 볡μ νλ€. (μμ
broadcast_to
ν¨μ μ¬μ© (μλ‘ μνΈμμ‘΄μ ))
- λΈλ‘λμΊμ€νΈ λμ
- λ¬Έμ : numpyμ broadcast_toκ° λ³΄μ΄μ§ μλ κ³³μμ μ΄λ£¨μ΄μ§λ©΄ μμ νκ° μΌμ΄λμ§ μλλ€.
- ν΄κ²° : Add, Mul, Sub, Div λ± μ¬μΉμ°μ° ν΄λμ€μμ, μμ ν λ broadcastκ° μΌμ΄λ¬λ€κ³ νλ¨λλ©΄ μμ ν λ DeZeroμ sum_toλ₯Ό μ¬μ©νμ¬ λ³΄μ νλ€. - [coreμ λ°μ]
-
νλ ¬μ κ³±
- κ°λ
matmul
: νλ ¬ κ³± κ³μ° - [FunctionμΌλ‘ ꡬν]- μμ ν :
numpyμ dot
ν¨μ μ¬μ©np.dot(x, W)
λμx.dot(W)
λ‘ κ΅¬ννμ¬ ndarray μΈμ€ν΄μ€μλ λμν μ μλλ‘ νλ€.
- μμ ν : μμ ν κ³μ°μμμ νλ ¬μ κ³±μ
matmul
ν¨μ μ¬μ©
- μμ ν :
-
μ¬λΌμ΄μ€ μ‘°μ ν¨μ
GetItem
,get_item
: Variableμ λ€μ°¨μ λ°°μ΄ μ€μμ μΌλΆλ₯Ό μ¬λΌμ΄μ€(slice)νμ¬ λ½λλ€. - [FunctionμΌλ‘ ꡬν | Variable ν΄λμ€μ μΆκ°]- μμ ν : numpyμ ndarrayμ slice κΈ°λ₯ κ·Έλλ‘ μ¬μ©
- μμ ν : μλμ
GetItemGrad
ν¨μ μ΄μ©
GetItemGrad
- [FunctionμΌλ‘ ꡬν]- μμ ν :
numpyμ add.at
ν¨μ μ΄μ© - μμ ν : μμ
get_item
ν¨μ μ΄μ©
- μμ ν :
- νκ·(regression) : xλ‘λΆν° μ€μ«κ° yλ₯Ό μμΈ‘νλ κ²
- μ ν νκ·(linear regression) : νκ· λͺ¨λΈ μ€ μμΈ‘κ°μ΄ μ ν(μ§μ )μ μ΄λ£¨λ κ²
- μ ν νκ· κ΅¬ν μμ
- κ²½μ¬νκ°λ²μΌλ‘ 맀κ°λ³μλ₯Ό κ°±μ ν λ, κ³μ° κ·Έλνλ₯Ό λ§λ€μ§ μλλ‘ W.data, W.grad.dataκ°μ μ΄μ©νλ€.
- DeZero λ΄λΆμμ Variable μΈμ€ν΄μ€λ‘ λ³ννλ―λ‘ ndarray μΈμ€ν΄μ€λ μ²λ¦¬ν μ μλ€. μμΌλ‘λ xκ° ndarray μΈμ€ν΄μ€μΈ μνλ‘ λ€μ΄κ° μ μμ
- μ ν λ³ν(linear transformation) (νΉμ μν λ³ν(affine transformation))
- y = F.matmul(x, W) + b
- W : κ°μ€μΉ(weight), b : νΈν₯(bias)
- [κΈ°λ³Έ ꡬν | FunctionμΌλ‘ ꡬν]
- λΆνμν μ€κ° κ³μ° κ²°κ³Όμ ndarray μΈμ€ν΄μ€λ μ¦μ μμ νλ κ²μ΄ λ°λμ§νλ€.
- (μ°Έκ³ )chainerμ Aggressive Buffer Release : λΆνμν ndarray μΈμ€ν΄μ€ μμ λ₯Ό μλννλ λ°©λ²
- μμ μ°κ²°κ³μΈ΅(fully connected layer)μ ν΄λΉνλ€.
- y = F.matmul(x, W) + b
- λΉμ ν λ³ν(nonlinear transformation)
- νμ±ν ν¨μ(activation function)
- ex) ReLU ν¨μ, μκ·Έλͺ¨μ΄λ ν¨μ
- μκ·Έλͺ¨μ΄λ ν¨μ(sigmoid function)
- νμ±ν ν¨μ(activation function)
- 2μΈ΅ μ κ²½λ§ κ΅¬ν μμ
- μ λ ₯μΈ΅(input layer), μλμΈ΅(hidden layer or middle layer), μΆλ ₯μΈ΅(output layer)
- κ°μ€μΉμ μ΄κΉκ°μ 무μμλ‘ μ€μ νλ κ²μ΄ μ’λ€.
- Parameter ν΄λμ€
- 맀κ°λ³μ : κ²½μ¬νκ°λ² λ±μ μ΅μ ν κΈ°λ²μ μν΄ κ°±μ λλ λ³μ (κ°μ€μΉ, νΈν₯)
- Variable ν΄λμ€μ λκ°μ κΈ°λ₯μ κ°μ§μ§λ§ 맀κ°λ³μμμ ꡬλ³ν μ μλλ‘ ν¨
- [Parameter ν΄λμ€ κ΅¬ν]
class Parameter(Variable): pass
- Layer ν΄λμ€
- Function ν΄λμ€μ λ¬λ¦¬, 맀κ°λ³μλ₯Ό μ μ§νκ³ λ§€κ°λ³μλ₯Ό μ¬μ©νμ¬ λ³μλ₯Ό λ³ννλ ν΄λμ€
- [Layer ν΄λμ€ κ΅¬ν]
class Layer: def __init__(self): self._params = set() # 맀κ°λ³μ μ§ν©(μ€λ³΅ID μ μ₯ λ°©μ§) def __setattr__(self, name, value): # μΈμ€ν΄μ€ λ³μ μ€μ ν¨μ if isinstance(value, (Parameter, Layer)): self._params.add(name) super().__setattr__(name, value) def __call__(self, *inputs): outputs = self.forward(*inputs) if not isinstance(outputs, tuple): outputs = (outputs,) self.inputs = [weakref.ref(x) for x in inputs] # μ½ν μ°Έμ‘° self.outputs = [weakref.ref(y) for y in outputs] # μ½ν μ°Έμ‘° return outputs if len(outputs) > 1 else outputs[0] def forward(self, inputs): raise NotImplementedError() def params(self): for name in self._params: obj = self.__dict__[name] if isinstance(obj, Layer): yield from obj.params() # Layer μμ Layerμμ 맀κ°λ³μλ₯Ό μ¬κ·μ μΌλ‘ κΊΌλ else: yield obj # μ²λ¦¬λ₯Ό 'μΌμ μ€μ§(suspend)'νκ³ κ°μ λ°ν def cleargrads(self): for param in self.params(): # `params`λ©μλλ₯Ό νΈμΆ μ μ²λ¦¬λ₯Ό 'μ¬κ°(resume)' param.cleargrad()
yield
λ₯Ό μ¬μ©ν ν¨μλ₯Ό μ λλ μ΄ν°(generator)λΌκ³ νλ€.yield from
μ ν΅ν΄ λ λ€λ₯Έ μ λλ μ΄ν°λ₯Ό λ§λ€ μ μλ€.
- Linear ν΄λμ€
- κ³μΈ΅μΌλ‘μμ Linear ν΄λμ€μ΄λ©°, Layer ν΄λμ€λ₯Ό μμνμ¬ κ΅¬ννλ€.
- [Linear ν΄λμ€ κ΅¬ν]
__init__
: Layer ν΄λμ€μ__init__
ν¨μ μ€ν ν, μΈμμ λ°λΌ κ°μ€μΉμ λ³μ μΈμ€ν΄μ€ λ³μ μ€μ _init_W
: κ°μ€μΉ μ΄κΈ°ν ν¨μ(Xavier initialization)forward
: λ°μ΄ν°κ° νλ¬μ€λ μμ μ κ°μ€μΉλ₯Ό μ΄κΈ°νν μ μλ€.
- Model ν΄λμ€
- Layer ν΄λμ€λ₯Ό μ΄μ©νμ¬ μ κ²½λ§μμ μ¬μ©νλ 맀κ°λ³μλ₯Ό νκΊΌλ²μ κ΄λ¦¬ν μ μλ€.
- λ°λΌμ Layer ν΄λμ€λ₯Ό μμνμ¬ λͺ¨λΈ μ 체λ₯Ό νλμ ν΄λμ€λ‘ μ μν μ μλ€.
- [Model ν΄λμ€ κ΅¬ν]
class Model(Layer): def plot(self, *inputs, to_file='model.png'): # μκ°ν λ©μλλ§ μΆκ° y = self.forward(*inputs) return utils.plot_dot_graph(y, verbose=True, to_file=to_file)
- MLP ν΄λμ€
- λ€μΈ΅ νΌμ νΈλ‘ (Multi-Layer Perceptron) : μμ μ°κ²°κ³μΈ΅ μ κ²½λ§μ λ³μΉμΌλ‘ νν μ°μΈλ€.
- λ²μ©μ μΈ μμ μ°κ²°κ³μΈ΅ μ κ²½λ§μ μν λͺ¨λΈ (TwoLayerNetμ μμ°μ€λ¬μ΄ νμ₯)
- [MLP ν΄λμ€ κ΅¬ν]
self.l1 = ...
λμsetattr
ν¨μλ₯Ό μ¬μ©νμ¬ μΈμ€ν΄μ€ λ³μ μ€μ
- Optimizer ν΄λμ€
- 맀κ°λ³μ κ°±μ μμ μ λͺ¨λννκ³ μ½κ² λ€λ₯Έ λͺ¨λλ‘ λ체ν μ μλ ꡬ쑰
- μ μ²λ¦¬ μν ν¨μλ₯Ό μΆκ°ν μ μλλ‘ νλ©΄, κ°μ€μΉ κ°μ(Weight Decay)λ κΈ°μΈκΈ° ν΄λ¦¬ν(Gradient Clipping) κ°μ κΈ°λ²μ μ΄μ©ν μ μλ€.
- [Optimizer ν΄λμ€ κ΅¬ν]
class Optimizer: def __init__(self): self.target = None # 맀κ°λ³μλ₯Ό κ°λ ν΄λμ€(Model λλ Layer) self.hooks = [] # μ μ²λ¦¬λ₯Ό μννλ ν¨μλ€ def setup(self, target): # target μ€μ self.target = target return self def update(self): # λͺ¨λ 맀κ°λ³μ κ°±μ params = [p for p in self.target.params() if p.grad is not None] # gradκ° NoneμΈ λ§€κ°λ³μλ κ°±μ μ 건λλ΄λ€. # νμ μ μ μ²λ¦¬ μ§ν for f in self.hooks: f(params) # 맀κ°λ³μ κ°±μ for param in params: self.update_one(param) def update_one(self, param): # ꡬ체μ μΈ λ§€κ°λ³μ κ°±μ raise NotImplementedError() def add_hook(self, f): # μνλ μ μ²λ¦¬ ν¨μ μΆκ° self.hooks.append(f)
- SGD ν΄λμ€
- νλ₯ μ κ²½μ¬νκ°λ²(Stochastic Gradient Descent) : λμ λ°μ΄ν° μ€μμ 무μμλ‘(νλ₯ μ μΌλ‘) μ λ³ν λ°μ΄ν°μ λν΄ κ²½μ¬νκ°λ²μ μννλ€.
- Optimizer ν΄λμ€λ₯Ό μμνκ³ update_one λ©μλμμ 맀κ°λ³μ κ°±μ μ½λλ₯Ό ꡬννλ€.
- [SGD ν΄λμ€ κ΅¬ν]
class SGD(Optimizer): def __init__(self, lr=0.01): super().__init__() self.lr = lr def update_one(self, param): param.data -= self.lr * param.grad.data
- SGD ν΄λμ€ μ¬μ© μμ
- μ΄ μΈ
- λ€μ€ ν΄λμ€ λΆλ₯(multi-class classification) : λΆλ₯ λμμ΄ μ¬λ¬ κ°μ§ ν΄λμ€ μ€ μ΄λμ μνλμ§ μΆμ
- μννΈλ§₯μ€ ν¨μ(softmax function) : μμ κ°κ°μ νλ₯ λ‘ ν΄μ€ν μ μκ² λλ€.
-
(
)
- [κΈ°λ³Έ ꡬν | FunctionμΌλ‘ ꡬν]
-
- κ΅μ°¨ μνΈλ‘νΌ μ€μ°¨(cross entropy error)
- μν« λ²‘ν°(one-hot vector) : μ λ΅ λ°μ΄ν°μ κ° μμκ° μ λ΅μ ν΄λΉνλ ν΄λμ€λ©΄ 1, μλλ©΄ 0μΌλ‘ νν
-
-
- [κΈ°λ³Έ ꡬν | FunctionμΌλ‘ ꡬν]
-
μ λ°©μ§νκΈ° μν΄ `clip` ν¨μ μ΄μ©
- clip ν¨μ : Variable xμ μμκ° x_min μ΄νλ©΄ x_minμΌλ‘, x_max μ΄μμ΄λ©΄ x_maxλ‘ λ³ν
-
- λ€μ€ ν΄λμ€ λΆλ₯ μμ
- μ€νμ΄λ΄(spiral) λ°μ΄ν°μ : λμ ν νΉμ μμ©λμ΄ λͺ¨μ
- Dataset ν΄λμ€
- λκ·λͺ¨ λ°μ΄ν°μ μ μ²λ¦¬ν λ, ndarray μΈμ€ν΄μ€ νλλ‘ μ²λ¦¬νλ©΄ νκΊΌλ²μ λ©λͺ¨λ¦¬μ μ¬λ €μΌ νκΈ° λλ¬Έμ λ¬Έμ κ° λ μ μλ€.
- [Dataset ν΄λμ€ κ΅¬ν]
__getitem__
κ³Ό__len__
λ©μλκ° λ°μ΄ν°μ μ ν΅μ¬ λ©μλμ΄λ€.- λ°μ΄ν°μ
μ μ²λ¦¬ : λ°μ΄ν°μμ νΉμ κ°μ μ κ±°νκ±°λ λ°μ΄ν°μ νμμ λ³ννλ μ²λ¦¬
transforms.py
μ ꡬν- λ°μ΄ν° νμ₯(data augmentation), λ°μ΄ν° μ κ·ν(normalization) λ±
- Spiral ν΄λμ€
- [Spiral ν΄λμ€ κ΅¬ν]
- Dataset ν΄λμ€λ₯Ό μμνκ³
prepare
λ©μλμμ μΈμ€ν΄μ€ λ³μ dataμ labelμ λ°μ΄ν°λ₯Ό μ€μ νλ€. - (λλ
__getitem__
μ΄ λΆλ¦¬λ μμ μ λ°μ΄ν°λ₯Ό νμΌμμ μ½μ΄μ€λ λ°©λ²λ μλ€.)
- Dataset ν΄λμ€λ₯Ό μμνκ³
- Spiral λ°μ΄ν°μ
νμ΅ μμ
- κ° iterationμμ λ―Έλλ°°μΉλ₯Ό κΊΌλ΄κ³ (getitem), κ·Έ ν ndarray μΈμ€ν΄μ€λ‘ λ³ννλ€.
- [Spiral ν΄λμ€ κ΅¬ν]
- DataLoader ν΄λμ€
- λ―Έλλ°°μΉ μμ±κ³Ό λ°μ΄ν°μ λ€μκΈ° λ±μ κΈ°λ₯ μ 곡
- λ°λ³΅μ(iterator) : μμλ₯Ό λ°λ³΅νμ¬ κΊΌλ΄μ€λ€.
- νμ΄μ¬μ
iter
ν¨μλ₯Ό μ΄μ©νμ¬ λ°λ³΅μλ‘ λ³ννκ³ ,next
ν¨μλ₯Ό μ΄μ©νμ¬ μμλ₯Ό μ°¨λ‘λλ‘ κΊΌλΈλ€. - ν΄λμ€μμ νΉμ λ©μλ ꡬνμ ν΅ν΄ νμ΄μ¬ λ°λ³΅μλ‘ μ§μ λ§λ€ μλ μλ€.
__iter__
: μκΈ° μμ (self) λ°ν__next__
: λ€μ μμ λ°ν
- νμ΄μ¬μ
- [DataLoader ν΄λμ€ κ΅¬ν]
- dataset : Dataset μΈν°νμ΄μ€λ₯Ό λ§μ‘±νλ μΈμ€ν΄μ€(
__getitem__
,__len__
λ©μλ ꡬνλ¨) - batch_size : λ°°μΉ ν¬κΈ°
- shuffle : μν¬ν¬λ³λ‘ λ°μ΄ν°μ μ λ€μμμ§ μ¬λΆ
- dataset : Dataset μΈν°νμ΄μ€λ₯Ό λ§μ‘±νλ μΈμ€ν΄μ€(
- Spiral λ°μ΄ν°μ
νμ΅ μμ
- (μ°Έκ³ ) accuracy ν¨μ : μ λ΅λ₯ κ³μ°μ©, κ³μ° κ·Έλν κ·Έλ¦¬μ§ μμ
- MNIST λ°μ΄ν°μ
νμ΅ μμ
- (μ°Έκ³ ) chainer 곡μ mnist μμ
- (μ°Έκ³ ) pytorch 곡μ mnist μμ