45.1 Layer 클래스 확장

Layer 클래스 안에 Layer가 들어간 구조로 만드는 것이 이번장의 목표입니다.
class Layer:
def __init__(self):
self._params = set()
def __setattr__(self, name, value):
if isinstance(value, (Parameter, Layer)): # 1. Layer 추가
self._params.add(name)
super().__setattr__(name, value)
def params(self):
for name in self._params:
obj = self.__dict__[name]
if isinstance(obj, Layer):
yield from obj.params() # 2.Layer에서 매개변수 꺼내기
else:
yield obj
def __init__(self):
self._params = set()
Layer 클래스의 생성자 메서드로 새 인스턴스를 생성할 때 호출됩니다.
예를 들어 model = Layer() 이렇게 생성될때 호출됩니다.
self._params = set() 부분은 Layer 인스턴스마다 고유한 빈 집합을 생성하고 해당 레이어에 속한 매개변수의 이름을 저장할 준비를 한다는 의미입니다.
def __setattr__(self, name, value):
if isinstance(value, (Parameter, Layer)): # 1. Layer 추가
self._params.add(name)
super().__setattr__(name, value)
def __setattr__(self, name, value):
__setattr__는 python의 특수한 메서드로 객체의 속성을 설정할 때 호출되는 메서드입니다.
name과 value를 사용하여 객체의 속성을 설정하고 관련된 동작을 수행합니다.
if isinstance(value, (Parameter, Layer)): # 1. Layer 추가
value가 Parameter 클래스나 Layer의 클래스의 인스턴스인지 확인합니다.
self._params.add(name)
위의 조건이 참이면 self._params라는 이름의 set에 현재 속성 name을 추가합니다.
super().__setattr__(name, value)
부모 클래스의 __setattr__메서드를 호출하여 속성을 설정합니다.
def params(self):
for name in self._params:
obj = self.__dict__[name]
if isinstance(obj, Layer):
yield from obj.params() # 2.Layer에서 매개변수 꺼내기
else:
yield obj
for name in self._params:
_params 집합에 저장된 매개변수의 이름을 for문으로 반복합니다.
obj = self.__dict__[name]는 매개변수 이름에 해당하는 속성을 self.__dict__를 사용해 검색하고 obj 변수에 저장합니다.
이렇게하면 실제 매개변수 객체에 접근할 수 있습니다.
if isinstance(obj, Layer): 검색된 obj가 Layer 클래스의 인스턴스인지 확인합니다.
yield from obj.params() 검색한 객체가 Layer인 경우, 해당 레이어의 params 메서드를 재귀적으로 호출합니다.
yield from을 사용하여 중첩된 레이어에서 매개변수를 가져옵니다. 현재 레이어와 하위 레이어의 매개변수를 연결하여 하나의 제너레이터로 반환합니다.
else: 검색한 객체가 Layer가 아닌 경우, Parameter 클래스의 인스턴스 또는 다른 타입의 객체인 경우
yield obj 현재 객체를 제너레이터로 반환합니다. 이러면 현재 레이어의 매개변수가 아닌 다른 객체를 차례대로 반환할 수 있습니다.
import dezero.layers as L
import dezero.functions as F
from dezero import Layer
model = Layer()
model.l1 = L.Linear(5)
model.l2 = L.Linear(3)
def predict(model, x):
y = model.l1(x)
y = F.sigmoid(y)
y = model.l2(y)
return y
for p in model.params():
print(p)
model.cleargrads()
model = Layer()에서 인스턴스를 생성한 다음 model의 인스턴스 변수로 Linear 인스턴스를 추가합니다.
model.params()로 model 내에 존재하는 모든 매개변수에 접근할 수 있고 프린트해서 매개변수를 확인할 수 있습니다.

model.cleargrads()는 모든 매개변수의 기울기를 재설정합니다.
Layer 클래스를 더 편리하게 사용하는 방법은 Layer 클래스를 상속하여 모델 전체를 하나의 클래스로 정의하는 방법입니다.
class TwoLayerNet(Layer):
def __init__(self, hidden_size, out_size):
super().__init__()
self.l1 = L.Linear(hidden_size)
self.l2 = L.Linear(out_size)
def forward(self, x):
y = F.sigmoid(self.l1(x))
y = self.l2(y)
return y
TwoLayerNet이라는 이름으로 클래스 모델을 정의하고 Layer를 상속했고 __init__과 forward 매서드를 구현했습니다.
init은 필요한 layer들을 생성하고 forward에서는 추론을 수행하는 코드로 작성했습니다.
45.2 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)
Model 클래스는 Layer의 클래스의 기능을 이어받으면 시각화 메서드가 하나 추가됩니다.
Layer를 상속해서 TwoLayerNet(Model)이라고 작성할 수 있습니다.
plot은 inputs으로 전달받은 데이터를 forward메서드로 계산한 다음, 생성된 계산 그래프를 이미지 파일로 내보냅니다.
import numpy as np
from dezero import Variable, Model
import dezero.layers as L
import dezero.functions as F
from dezero import Layer
class TwoLayerNet(Model):
def __init__(self, hidden_size, out_size):
super().__init__()
self.l1 = L.Linear(hidden_size)
self.l2 = L.Linear(out_size)
def forward(self, x):
y = F.sigmoid(self.l1(x))
y = self.l2(y)
return y
x = Variable(np.random.randn(5, 10), name='x')
model = TwoLayerNet(100, 10)
model.plot(x)

45.3 Model을 사용한 문제 해결
if '__file__' in globals():
import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import numpy as np
from dezero import Model
import dezero.layers as L
import dezero.functions as F
np.random.seed(0)
x = np.random.rand(100, 1)
y = np.sin(2 * np.pi * x) + np.random.rand(100, 1)
# Hyperparameters
lr = 0.2
max_iter = 10000
hidden_size = 10
# Model definition
class TwoLayerNet(Model):
def __init__(self, hidden_size, out_size):
super().__init__()
self.l1 = L.Linear(hidden_size)
self.l2 = L.Linear(out_size)
def forward(self, x):
y = F.sigmoid(self.l1(x))
y = self.l2(y)
return y
model = TwoLayerNet(hidden_size, 1)
for i in range(max_iter):
y_pred = model(x)
loss = F.mean_squared_error(y, y_pred)
model.cleargrads()
loss.backward()
for p in model.params():
p.data -= lr * p.grad.data
if i % 1000 == 0:
print(loss)
np.random.seed(0)
x = np.random.rand(100, 1)
y = np.sin(2 * np.pi * x) + np.random.rand(100, 1)
우선 데이터를 만들어줍니다.
# Hyperparameters
lr = 0.2
max_iter = 10000
hidden_size = 10
하이퍼 파라미터 값을 설정해줍니다.
# Model definition
class TwoLayerNet(Model):
def __init__(self, hidden_size, out_size):
super().__init__()
self.l1 = L.Linear(hidden_size)
self.l2 = L.Linear(out_size)
def forward(self, x):
y = F.sigmoid(self.l1(x))
y = self.l2(y)
return y
model = TwoLayerNet(hidden_size, 1)
Model 클래스를 상속한 TwoLayerNet으로 신경망을 구현해줍니다.
for i in range(max_iter):
y_pred = model(x)
loss = F.mean_squared_error(y, y_pred)
model.cleargrads()
loss.backward()
for p in model.params():
p.data -= lr * p.grad.data
if i % 1000 == 0:
print(loss)
반복문을 통해 loss값이 줄어드는 방향으로 학습을 시작합니다.
45.4 MLP 클래스
class TwoLayerNet(Model):
def __init__(self, hidden_size, out_size):
super().__init__()
self.l1 = L.Linear(hidden_size)
self.l2 = L.Linear(out_size)
def forward(self, x):
y = F.sigmoid(self.l1(x))
y = self.l2(y)
return y
위의 코드는 하나의 클래스로 2층 신경망으로 Multi Layer Perceptron을 만들었습니다.
범용적으로 완전연결계층 신경망을 구현해보겠습니다.
class MLP(Model):
def __init__(self, fc_output_sizes, activation=F.sigmoid):
super().__init__()
self.activation = activation
self.layers = []
for i, out_size in enumerate(fc_output_sizes):
layer = L.Linear(out_size)
setattr(self, 'l' + str(i), layer)
self.layers.append(layer)
def forward(self, x):
for l in self.layers[:-1]:
x = self.activation(l(x))
return self.layers[-1](x)
초기화 인수는 fc_output_size, actiavation을 받아줍니다.
인스턴스 변수를 설정하는 식으로 계층에 포함된 매개변수들을 관리합니다.
위 코드 구현으로
model = MLP((10, 1))
model = MLP((10, 20, 30, 40, 1))
2층 MLP, 5층 MLP를 만들 수 있었습니다.
'Study 공부할레나' 카테고리의 다른 글
| [스터디/밑시딥3] 제 4고지 신경망 만들기_47. 소프트맥스 함수와 교차 엔트로피 오차 (0) | 2023.10.16 |
|---|---|
| [스터디/밑시딥3] 제 4고지 신경망 만들기_46. Optimizer로 수행하는 매개변수 갱신 (0) | 2023.10.15 |
| [스터디/밑시딥3] 제 4고지 신경망 만들기_44. 매개변수를 모아두는 계층 (1) | 2023.10.10 |
| [스터디/밑시딥3] 제 4고지 신경망 만들기_43. 신경망 (2) | 2023.10.10 |
| [스터디/밑시딥3] 제 4고지 신경망 만들기_42. 선형 회귀 (1) | 2023.10.10 |