벌써 7월이 찾아와서 많이 덥네요.
요즘 자격증 공부도 하고 백준 풀면서 네부캠 준비도 하는데 이게 참 힘든 일이네요.
어떤 일 하나에 집중해서 잘하는 것도 능력입니다...
이것저것 다 해내고 싶은 욕심도 중요하지만 무엇이든지 마무리까지 잘 달리는 능력이 더 중요한 것 같습니다.
아래 모든 내용은 부스트캠프 AI Tech 프리코스에서 가져왔습니다.
모델들은 결국엔 여러 층의 연속일 뿐입니다.
그 층을 잘 찾아서 쌓는 것이 중요한 것.
이런 Layer들을 정의할 수 있는 방법으로 torch.nn.Module이 있습니다.
Input, Output, Forward, Backward 등을 정의할 수 있고
학습에 사용되는 파라미터를 결정해줄 수 있습니다.

Forward는 그냥 FNN 식 같은 것일 거고, Backward 부분이 미분을 통해서 파라미터 값을 학습시킵니다.
이 미분을 AutoGrad을 통해 처리해주는 것이 파이토치의 CNN의 장점입니다.
# PyTorch의 Parameter를 사용하여, linear layer 구현
class MyLinear(nn.Module):
def __init__(self, in_features, out_features, bias=True):
super().__init__()
self.in_features = in_features
self.out_features = out_features
# (in_features, out_features) shape을 갖는 random tensor를 학습 가능한 Parameter 객체로 변환
self.weights = nn.Parameter(
torch.randn(in_features, out_features))
# (out_features) shape을 갖는 random tensor를 학습 가능한 Parameter 객체로 변환
self.bias = nn.Parameter(torch.randn(out_features))
def forward(self, x : Tensor):
# input tensor를 선형 변환한 후, bias term을 더하는 연산 정의
return x @ self.weights + self.bias
nn.Parameter은 이렇게 input feature과 output feature을 지정하고 계산하는 데에 쓰입니다.
for epoch in range(epochs):
# input과 label을 PyTorch Variable 객체로 변환
if torch.cuda.is_available():
inputs = Variable(torch.from_numpy(x_train).cuda())
labels = Variable(torch.from_numpy(y_train).cuda())
else:
inputs = Variable(torch.from_numpy(x_train))
labels = Variable(torch.from_numpy(y_train))
# 이전 기록된 gradient를 0으로 초기화
optimizer.zero_grad()
# model을 통해 input forward propagation 진행
outputs = model(inputs)
# loss 값 계산
loss = criterion(outputs, labels)
print(loss)
# 모든 파라미터에 대해 gradient 계산
loss.backward()
# 파라미터 업데이트
optimizer.step()
print('epoch {}, loss {}'.format(epoch, loss.item()))
이 코드는 앞뒤는 자르고 볼게요. 각 epoch마다 optimizer에서 zero_grad()를 통해 전 단계의 정보는 지우고요.
들어온 값을 처리합니다.
y hat에서 y를 빼서 오차를 구하고, 오차에 대하여 편미분을 진행합니다. 이건 backward() 를 통해 행해집니다.
위 코드는 데이터 로더 없이 모든 그래디언트를 사용하게 됩니다.
SGD를 사용하면 또 다를 수도 있습니다.
# flatten을 수행하기 위한 class 정의
class ReshapeTransform:
def __init__(self, new_size):
self.new_size = new_size
def __call__(self, img):
result = torch.reshape(img, self.new_size)
return result
# 이미지 변환을 위한 transforms 정의. image Resize, Center Crop, tensor로 변경, flatten
data_transforms = {
'train': transforms.Compose([
transforms.Resize(224),
transforms.CenterCrop(224),
transforms.ToTensor(),
ReshapeTransform((-1,))
]),
'val': transforms.Compose([
transforms.Resize(224),
transforms.CenterCrop(224),
transforms.ToTensor(),
ReshapeTransform((-1,))
]),
}
# image dataset 생성 개미: 클래스 0 / 벌: 클래스 1
image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x),
data_transforms[x])
for x in ['train', 'val']}
데이터 증강 코드도 한 번 보겠습니다.
이미지를 가져와서 변형해주고, 데이터셋에 추가해주고, 데이터 로더(위 코드엔 없음)도 설정해줍니다.
데이터셋 API도 알아봅시다.
모으고, 전처리하고, 트랜스폼한 데이터를 모아 데이터셋 삼을 수 있습니다.
예를 들어 happy라는 텍스트가 있고 여기에 Positive라는 레이블링을 하겠습니다.
from torch.utils.data import Dataset, DataLoader
# 파이토치의 Dataset 클래스를 상속받아 CustomDataset 클래스를 정의합니다.
class CustomDataset(Dataset):
# 초기화 함수: 객체 생성 시 호출되며, 데이터와 레이블을 인자로 받아 저장합니다.
def __init__(self, text, labels):
# 레이블 정보를 저장합니다.
self.labels = labels
# 텍스트 데이터를 저장합니다.
self.data = text
# 데이터셋의 총 길이(데이터 개수)를 반환하는 함수입니다.
def __len__(self):
return len(self.labels)
# 인덱스를 받아 해당 인덱스의 데이터와 레이블을 반환하는 함수입니다.
def __getitem__(self, idx):
# 해당 인덱스의 레이블을 가져옵니다.
label = self.labels[idx]
# 해당 인덱스의 텍스트 데이터를 가져옵니다.
text = self.data[idx]
# 텍스트와 레이블을 딕셔너리 형태로 묶어 반환합니다.
sample = {"Text": text, "Class": label}
return sample
그러면 위 코드와 같은 방식으로 데이터를 받아, 데이터셋으로 만들어줄 수 있습니다.
이건 그냥 단순한 텍스트여서 별 거 없는데, 이미지나 음성 데이터라면 텐서로 변환하고 데이터셋으로 처리해야 할 수 있습니다.
이런 표준화를 잘 해두어야 남들이 사용할 때 쉽게 사용할 수가 있습니다.
늘 잘 정리하는 것이 협업의 지름길!
이렇게 데이터셋을 만들었으면 DataLoader를 통해 Batch를 생성하고 데이터를 변환합니다.
# 배치 크기가 2인 DataLoader 객체를 생성하고 데이터를 섞어서 로드합니다.
MyDataLoader = DataLoader(MyDataset, batch_size=2, shuffle=True)
# DataLoader에서 첫 번째 배치의 데이터를 가져와 출력합니다.
next(iter(MyDataLoader))
MyDataLoader을 Iterable한 제네레이터로 생성해주고, 배치 크기가 2이기 때문에 매 호출마다 2쌍의 데이터가 불러와집니다.
셔플 옵션 때문에 순서는 랜덤으로 나오겠네요.
DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,
batch_sampler=None, num_workers=0, collate_fn=None,
pin_memory=False, drop_last=False, timeout=0,
worker_init_fn=None, *, prefetch_factor=2,
persistent_workers=False)
이런 옵션들이 있는데 collate_fn은 { Data : Label } 쌍이 데이터는 데이터끼리, 레이블은 레이블끼리 묶어주는 기능이라고 합니다.
그 외에도 여러 옵션이 있으나 이건 알아두면 좋은 거 정도?
데이터를 로드해와서 트랜스포머로 224 사이즈로 자른다든가 뒤집는다든가 해서 다양한 데이터를 만들고 텐서로 바꿔주면
데이터를 올바르게 사용하는 게 되겠습니다!
'CS > AI' 카테고리의 다른 글
| [ML] Hyperparameter Tuning (0) | 2025.07.11 |
|---|---|
| [PyTorch] 모델 불러오기 / PyTorch 모니터링 (0) | 2025.07.10 |
| [ML] CNN과 RNN 첫걸음 (0) | 2025.07.01 |
| [부스트캠프 AI Tech 프리코스] 경사하강법과 딥러닝 학습 방법 (0) | 2025.06.24 |
| [ML, DL] 간단한 합성곱 신경망의 개념과 AlexNet (0) | 2025.06.20 |
