44.1 Parameter 클래스 구현
class Parameter(Variable):
pass
Variable 클래스를 상속하기만 했습니다.
44.2 Layer 클래스 구현
Layer 클래스는 매개변수를 유지하고 매개변수를 사용하여 변환을 하는 클래스입니다.
from dezero.core import Parameter
class Layer:
def __init__(self):
self._params = set() # 매개변수 보관
def __setattr__(self, name, value):
if isinstance(value, (Parameter, Layer)):
self._params.add(name)
super().__setattr__(name, value)
__setattr__은 인스턴스 변수를 설정할 때 호출되는 특수 메서드입니다.
__setattr__(self, name, value)는 이름이 name인 인스턴스 변수에 값으로 value로 전달해줍니다.
이렇게 구현해서 어떻게 쓰냐면 아래 코드처럼 씁니다.
layer = Layer()
layer.p1 = Parameter(np.array(1))
layer.p2 = Parameter(np.array(2))
layer.p3 = Parameter(np.array(3))
layer.p4 = 'test'
print(layer._params)
for name in layer._prams:
print(name, layer.__dict__[name])
Layer 클래스에 call, forward, parmas, cleargrads 메서드를 추가합니다.
class Layer:
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()
else:
yield obj
def cleargrads(self):
for param in self.params():
param.cleargrad()
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]
call 메서드는 forward 메서드를 호출해 입력받은 인수를 넣어 아웃풋을 뽑아주고 출력이 하나면 출력을 직접 반환합니다. 그리고 입력과 출력 변수를 약한 참조로 유지하고 있습니다.
def params(self):
for name in self._params:
obj = self.__dict__[name]
if isinstance(obj, Layer):
yield from obj.params()
else:
yield obj
파람 메서드는 layer 인스턴스에 담겨있는 Parameter 인스턴스들을 꺼내줍니다.
def cleargrads(self):
for param in self.params():
param.cleargrad()
cleargrads 메서드는 Layer 인스턴스에 담겨 있는 파라미터 인스턴스들을 꺼내주고 모든 매개변수 기울기를 재설정합니다.
44.3 Linear 클래스 구현
class Linear(Layer):
def __init__(self, out_size, nobias=False, dtype=np.float32, in_size=None):
super().__init__()
self.in_size = in_size
self.out_size = out_size
self.dtype = dtype
self.W = Parameter(None, name='W')
if self.in_size is not None:
self._init_W()
if nobias:
self.b = None
else:
self.b = Parameter(np.zeros(out_size, dtype=dtype), name='b')
def _init_W(self, xp=np):
I, O = self.in_size, self.out_size
W_data = xp.random.randn(I, O).astype(self.dtype) * np.sqrt(1 / I)
self.W.data = W_data
def forward(self, x):
if self.W.data is None:
self.in_size = x.shape[1]
xp = cuda.get_array_module(x)
self._init_W(xp)
y = F.linear(x, self.W, self.b)
return y
class Linear(Layer):
Linear 클래스는 Layer 클래스를 상속합니다.
def __init__(self, out_size, nobias=False, dtype=np.float32, in_size=None):
입력 크기, 출력 크기, 편향 사용 여부 플래그를 인수로 받습니다.
in_size가 None으로 지정되어 있고 None이면 self.W.data 초기화를 연기합니다.
forward(self, x) 메서드에서 입력 x의 크기에 맞게 가중치 데이터를 생성합니다.
self.W = Parameter(None, name='W')
if self.in_size is not None:
self._init_W()
if nobias:
self.b = None
else:
self.b = Parameter(np.zeros(out_size, dtype=dtype), name='b')
가중치와 편향은 Parameter 인스턴스를 인스턴스 변수에 설정합니다.
44.4 Layer를 이용한 신경망 구현
if '__file__' in globals():
import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import numpy as np
import dezero.functions as F
import dezero.layers as L # L로 임포트
np.random.seed(0)
x = np.random.rand(100, 1)
y = np.sin(2 * np.pi * x) + np.random.rand(100, 1)
l1 = L.Linear(10) # 출력 크기 지정
l2 = L.Linear(1)
def predict(x):
y = l1(x)
y = F.sigmoid(y)
y = l2(y)
return y
lr = 0.2
iters = 10000
for i in range(iters):
y_pred = predict(x)
loss = F.mean_squared_error(y, y_pred)
l1.cleargrads()
l2.cleargrads()
loss.backward()
for l in [l1, l2]:
for p in l.params():
p.data -= lr * p.grad.data
if i % 1000 == 0:
print(loss)

'Study 공부할레나' 카테고리의 다른 글
| [스터디/밑시딥3] 제 4고지 신경망 만들기_46. Optimizer로 수행하는 매개변수 갱신 (0) | 2023.10.15 |
|---|---|
| [스터디/밑시딥3] 제 4고지 신경망 만들기_45. 계층을 모아두는 계층 (1) | 2023.10.14 |
| [스터디/밑시딥3] 제 4고지 신경망 만들기_43. 신경망 (2) | 2023.10.10 |
| [스터디/밑시딥3] 제 4고지 신경망 만들기_42. 선형 회귀 (1) | 2023.10.10 |
| [스터디/밑시딥3] 제 4고지 신경망 만들기_41. 행렬의 곱 (1) | 2023.10.09 |