layer 직렬 연결
가변인자를 받을 수 있는 함수의 정의해 봅니다. 가변인자를 받는 함수란 입력의 개수가 미리 정해지지 않은 함수를 말합니다.
# 가변인자를 받을 수 있는 함수의 정의
def my_function(*args):
for arg in args:
print(arg)
my_function(1, 2, 3)
가변인자 리스트를 받는 함수는 *list 를 이용하여 함수의 입력단에서 list 객체를 풀어서 전달할 수 있습니다.
# 예시
a = [1,2,3]
my_function(*a)
nn.Sequential 은 가변인자를 받을 수 있는 함수입니다. 입력개수가 정해지지 않아도 됩니다.
# 예시
layers = nn.Sequential(
nn.Conv2d(1, 64, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2))
*list 를 이용하여 함수의 입력단에서 list 객체를 풀어서 전달할 수 있습니다.
# 예시
layers = [nn.Conv2d(1, 64, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)]
model = nn.Sequential(*layers)
print(model)
x = torch.randn(20,1,5,10)
yhat = model(x)
yhat.shape
다음은 ModuleList 의 활용방법을 알아봅니다. ModuleList의 layer 리스트로 extend 혹은 append 기능 사용할 수 있습니다. 다음은 ModuleList를 활용하여 여러개의 hidden layer를 연결하는 FFN 을 만듭니다. 입력값으로 hidden layer 의 dim을 입력한 리스트를 입력값으로 받습니다. 예를 들면 입력 데이터 차원에서 잠재층의 차원이 10, 20, 30, 20 으로 하여 output 으로 변환되는 FFN 을 만드는 것을 생각해봅니다. 여기서 이 FFN을 만들때 [10, 20, 30, 20]을 입력값으로 하여 layer를 결합하고자 합니다. 이 작업은 두 단계로 이루어집니다.
- nn.ModuleList 를 이용하고 list comprehension 방법으로 layer 를 정의합니다.
- forward 단계에서 연결된 텐서를 만들어 FFN 을 만듭니다.
# ModuleList를 이용한 레이어의 연결
import torch
import torch.nn as nn
import torch.nn.functional as F
class MyModel(nn.Module):
def __init__(self, input_dim, hidden_dims, output_dim):
super(MyModel, self).__init__()
# hidden_layers 확인
self.hidden_layers = nn.ModuleList([nn.Linear(input_dim, hidden_dims[0])])
self.hidden_layers.extend([nn.Linear(hidden_dims[i], hidden_dims[i+1]) for i in range(len(hidden_dims) - 1)])
self.output_layer = nn.Linear(hidden_dims[-1], output_dim)
def forward(self, x):
for layer in self.hidden_layers:
x = F.relu(layer(x))
x = self.output_layer(x)
return x
만든 class 로 모형을 만들고 실행해봅니다.
# 예제 문장
input_dim = 10
hidden_dims = [20, 20, 40, 40, 30, 10]
output_dim = 5
batch_size = 8
model = MyModel(input_dim, hidden_dims, output_dim)
input_data = torch.randn(batch_size, input_dim)
input_data.shape
output = model(input_data)
print(output)
layer 병렬 연결
범주형 변수가 여러개 주어진 경우 임베딩을 병렬적으로 결합하는 방법입니다. 여기서는 모든 범주형 변수의 레벨이 수가 같은 경우만 다룹니다
# 예제
class MyModel(nn.Module):
def __init__(self, num_classes, embedding_dims):
super(MyModel, self).__init__()
# embeddings 확인 (List 형태로 관리)
self.embeddings = nn.ModuleList([nn.Embedding(num_classes, embedding_dim) for embedding_dim in embedding_dims])
def forward(self, x):
# Embedding each categorical variable
embedded_vars = [emb_layer(x[:, i])
for i, emb_layer in enumerate(self.embeddings)]
concatenated_embeddings = torch.cat(embedded_vars, dim=-1)
return concatenated_embeddings
실행해봅니다.
d = [3,4,5]
x = torch.randint(0,3, (10,3))
model = MyModel(3,d)
model(x).shape
다음으로 입력데이터의 차원이 정해지지 않은 레이어의 정의합니다. init 단계에서 이름을 None 으로 정해놓고 입력값이 들어올때 정의합니다.
# 예시
class FFN(nn.Module):
def __init__(self):
super(FFN, self).__init__()
self.fc1 = None
self.relu = nn.ReLU()
self.fc2 = None
self.fc3 = None
self.sigmoid = nn.Sigmoid()
def forward(self, x):
if self.fc1 is None:
input_dim = x.shape[1]
self.fc1 = nn.Linear(input_dim, 5).to(x.device)
self.fc2 = nn.Linear(5, 5).to(x.device)
self.fc3 = nn.Linear(5, 1).to(x.device)
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
x = self.relu(x)
x = self.fc3(x)
x = self.sigmoid(x)
return x
실행해봅시다.
x = torch.randn(size = (10,20)) model = FFN() model(x)