해당 포스팅은 간단하게 코드를 어떻게 짰는지를 위주로 작성했습니다.
사실... 정확도가 낮고.. 나중에 발전시킨걸 분석할라고 했는데.. 생각보다 잘 나와서 바로 올리게 되었습니다. 정보/인공지능 이론은 나중에 추가적으로 포스팅하겠습니다.
1. Dataset
kaggle에 올라온 데이터를 이용했습니다.
class MyDataset(Dataset):
def __init__(self, folder):
super().__init__()
self.url = f'./dataset/{folder}'
self.transform = transforms.Compose([
transforms.Resize((128,128)),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
filenames = os.listdir(self.url)
self.categorys = []
self.Imgs = []
self.len = len(filenames)
for file in filenames:
category = file.split('.')[0]
self.Imgs.append(self.transform(Image.open(f'{self.url}/{file}')))
if(category=='dog'):
self.categorys.append(torch.FloatTensor([0]))
else: self.categorys.append(torch.FloatTensor([1]))
def __getitem__(self, index):
return self.Imgs[index], self.categorys[index]
def __len__(self):
return self.len
1) __init__ 함수
os를 통해 해당 폴더에 들어있는 사진의 이름을 list에 담고 모든 사진을 조회하면서 labeling하고 torchvision을 이용해 사진을 전처리 하였습니다. 그리고 빠른 수렴을 위해 Normalize함수를 사용했습니다.
2) __getitem__ / __len__ 함수
__getitem__ 은 해당 index에 해당되는 데이터를 return해주었고 __len__은 데이터 개수를 return했습니다.
2. Model Layer
class CNN_Model(nn.Module):
def __init__(self):
super().__init__()
self.conv_layer = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1),
nn.ReLU(),
nn.BatchNorm2d(32),
nn.MaxPool2d(2),
nn.Dropout(0.5),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1),
nn.ReLU(),
nn.BatchNorm2d(64),
nn.MaxPool2d(2),
nn.Dropout(0.5),
nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1),
nn.ReLU(),
nn.BatchNorm2d(128),
nn.MaxPool2d(2),
nn.Dropout(0.5),
nn.Conv2d(in_channels=128, out_channels=256, kernel_size=3, padding=1),
nn.ReLU(),
nn.BatchNorm2d(256),
nn.MaxPool2d(2),
nn.Dropout(0.5),
)
self.fc_layer = nn.Sequential(
nn.Flatten(),
nn.Linear(256*8*8, 256),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(256, 32),
nn.ReLU(),
nn.Linear(32,1),
nn.Sigmoid()
)
def forward(self, x):
out = self.conv_layer(x)
out = self.fc_layer(out)
return out
channel 의 수는 여러 번 모델을 돌리면서 그나마 최적일 것 같은 layer로 지정했습니다. (왜 해당 model이 정확도가 높게 나왔는진 잘 모르지만.. 다음에 이에 관해서 포스팅하겠습니다)
해당 Model에서 Parameter도 많고 하다보니.. 과적합을 방지하기 위해 Dropout 을 많이 사용하였고.. 활성함수는 가장 많이 사용하는 Relu를 사용했습니다. 그리고 해당 모델은 "이진분류" 로 계획했습니다.
(자세한 내용은 논문을 참고해 작성해볼게욥.. 혹시나 왜 그런지 아시는 분은 댓글 부탁드립니다)
3. 학습
TrainDataset = MyDataset('train')
TestDataset = MyDataset('test')
Train_DataLoader = DataLoader(TrainDataset, 128, shuffle=True)
Test_DataLoader = DataLoader(TestDataset, 128)
model = CNN_Model()
optimizer = optim.SGD(model.parameters(), lr = 0.005)
nb_epochs = 30
history = []
for i in range(nb_epochs):
for j, [image, label] in enumerate(Train_DataLoader):
output = model(image)
loss = F.binary_cross_entropy(output, label)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 선택.. 함수는 요런 작업 거쳐줘야함..
prediction = output >= torch.FloatTensor([0.5]) # 예측값이 0.5를 넘으면 True
correct_prediction = prediction.float() == label # 실제값과 같은 경우만 True
accuracy = correct_prediction.sum().item() / len(correct_prediction) # 정확도 계산
history.append(loss.item())
print('Epoch {:4d}/{}, [{}번째 실행중] Cost: {:.6f} Accuracy {:2.2f}%'.format(
i+1, nb_epochs,j+1, loss.item(), accuracy * 100,
))
이진분류 모델을 사용했기 때문에 확률을 0.5를 기준으로 고양이 / 개를 예측하고 정확도를 추산했습니다.
4. 성능 확인
model.eval()
correct = 0
total = 0
for image, label in Test_DataLoader:
x = image
y_ = label
output = model.forward(x)
prediction = output >= torch.FloatTensor([0.5]) # 예측값이 0.5를 넘으면 True
correct_prediction = prediction.float() == label # 실제값과 같은 경우만 True
correct += correct_prediction.sum().item()
total += len(label)
print('Acc : {}'.format(correct / total))
Model trainning 에 쓰이지 않았던 사진들을 사용해서 얼마나 잘 예측하는지 확인해 볼건데... 이 때 주의할 것은 model.eval() 을 사용한다는 점과... item() 같은 함수를 사용하는 부분.. 입니다. 원래는 output에 대한 loss를 계산하고 gradient를 계산하기 위해 torch.require_grad = True 로 되있는 상태인데... 이런 상태의 변수를 다른 곳에 함부로 쓰면.. 오류가 납니다. (예전에 이 사실을 잘 모르고 2시간을 쩔쩔 맸었죠..)
결과는 무려 88.25%... (아직 미숙하고 해서 실수로 matplotlib의 pyplot으로 history를 출력하는걸 까먹었어요 ㅠㅠ)
일단 결과는 잘 나오네욥...
사실 훈련시키면서 쫌 불안정하기도 했고.. 이미지 증폭을 하지 않아 해당 Model은 불안정한 것 같습니다. 그래도 Test_Data가 12000개가 넘는데 저 정도의 정확도가 나온 것도 신기하네요;;
(2024년 5월 5일 오후 1:42 수정)
TensorBoard 를 사용하면 학습이 잘 이뤄지고 있는지, 그리고 모델이 안정하며 정확한지 분석하기 편합니다! 다음 실습을 통해 알아보도록 하겠습니다.
오늘 포스팅은 코드를 짜보는 것을 목적으로 진행해봤고.. 생각보다 정확도가 높아서 올려봤습니다. 이론적인 것을 이해하는 것도 중요하지만 초보일 땐 역시 실습이나 project를 진행하면서 재미를 붙이는 것이 중요하다고 생각합니다.
또한 이론적인 것을 잘 알아도 성능 좋은 Model을 잘 만드는 것은 아니기 때문에 경험을 쌓는것도 중요하다고 생각합니다. 다음 포스팅에는 인공지능과 정보학 이론에 대해 잠깐 소개하고 Model Architecture를 설계하는 방법을 논문과 함께 설명하겠습니다.
고수분들은 저 모델이 안정한지... 그리고 왜 Test 결과는 저렇게 잘 나오는지 설명해주시면 감사하겠습니다..
'코딩 > 인공지능 및 데이터분석' 카테고리의 다른 글
[인공지능] pytorch 환경 설정 (feat. tensorboard) (1) | 2024.05.07 |
---|---|
[인공지능] Entropy, CrossEntropy 이해 (0) | 2024.05.05 |