
class MyCNN(nn.Module):
def __init__(self, name='cnn', xdim = [3, 512, 384], ksize = 3, cdims = [32, 64],
hdims = [1024, 128], ydim = 18, USE_BATCHNORM=False):
super(MyCNN,self).__init__()
self.name = name
self.xdim = xdim
self.ksize = ksize
self.cdims = cdims
self.ydim = ydim
self.hdims = hdims
self.USE_BATCHNORM = USE_BATCHNORM
self.layers=[]
prev_cdim = xdim[0]
for cdim in self.cdims:
self.layers.append(
nn.Conv2d(in_channels=prev_cdim,
out_channels=cdim,
kernel_size=self.ksize,
stride=(1,1),
padding = self.ksize//2))
if self.USE_BATCHNORM:
self.layers.append(nn.BatchNorm2d(cdim))
self.layers.append(nn.ReLU(True))
self.layers.append(nn.MaxPool2d(kernel_size=(2,2), stride=(2,2)))
self.layers.append(nn.Dropout2d(p=0.5))
prev_cdim = cdim
self.layers.append(nn.Flatten())
prev_hdim = prev_cdim*(self.xdim[1]//(2*len(self.cdims)))*(self.xdim[2]//(2**len(self.cdims)))
for hdim in self.hdims:
self.layers.append(nn.Linear(prev_hdim, hdim, bias=True))
self.layers.append(nn.ReLU(True))
prev_hdim = hdim
self.layers.append(nn.Linear(prev_hdim, self.ydim, bias=True))
self.net = nn.Sequential()
for i_idx, layer in enumerate(self.layers):
layer_name ="%s_%02d"%(type(layer).__name__.lower(),i_idx)
self.net.add_module(layer_name, layer)
self.init_param()
def init_param(self):
for m in self.modules():
if isinstance(m,nn.Conv2d):
nn.init.kaiming_normal_(m.weight)
nn.init.zeros_(m.bias)
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight,1)
nn.init.constant_(m.bias,0)
elif isinstance(m, nn.Linear):
nn.init.kaiming_normal_(m.weight)
nn.init.zeros_(m.bias)
def forward(self,x):
return self.net(x)
요약
많은 Pre-Trained Model을 활용해보며 결과를 예측하였다. 처음에는 Tensorboard가 안되어 어쩔 수 없이 메모장에 최종적인 결과를 적어 비교하였지만, 나중에는 WandB도 활용하였다.
자세한 수행점
txt 파일에 한 여러 가지 실험들
EPOCH 10번. 나머지는 Default
nn.Linear만 Resnet에 붙였을 경우 : 70.08%
nn.Conv2D만 Resnet에 붙였을 경우 : 71.63%
nn.Linear를 활용해 여러 Layer : 69.64%
-> Overfitting의 위험성까지 고려해보면 안하는게 맞곘다!
Conv2D를 활용해서 여러 Layer : 69.64%
그런데, Epoch 늘려서 실험은 한 번 더 해보긴 하자
60 Epoch
nn.Linear 1개 Layer를 추가한 Model : 76.61%
nn.Linear 1개 Layer를 추가한 Model : 77.02% -
-> 왜 이게 더 좋게.. Flatten해도 좋으면 이거 써야겠다
nn.Linear 3개 Layer & Flatten을 활용한 Model : 77.28%
nn.Linear 1개 Layer & Flatten을 활용한 Model : 76.67
나중에 후회할 점에 쓰겠지만, 너무 큰 편견을 가지고 있어서 실험 결과를 가지고 판단하지 않고 내 주관에 실험 결과를 맞추려고 실험을 한 것 같다. 이번 프로젝트에서 두고두고 매우 후회되는 부분이다.
Trnasform 활용
아무것도 활용하지 않음 : 75.09%
RandomHorizontal : 76.49%
RandomPerspective : 75.20%
RandomRotation : 75.32%
Validation Set을 변경해야 한다!
Cross Validation을 위해 Data를 쪼갤 때, transform을 적용하면 Validation Data에도 해당 Transform이 적용되는 문제점이 존재했다. 예를 들어, Random GrayScale을 활용했을 때 Validation Set에도 흑백 사진으로 데이터가 바뀌는 경우가 존재했다. Validation Set은 무조건 원래 Image와 가까워야 하므로, Transform되면 안되기 때문에 Validation Data과 Train Data에 서로 다른 Transform을 적용하기 위해 코드를 짰다.
Loss Function(모두다 3 Layer로 수행함)
지금까지의 실험 결과 : 모두 CrossEntropy
Focal Loss : 76.90%
F1 Loss : 활용하고 싶었으나 학습이 제대로 진행되지 않는 것 같아 활용하지 못할 것 같음
나의 한계점이 조금 드러났던 실험이였다. Focal Loss와 CrossEntropy는 모두 이미 구현되어 있으므로 쉽게 활용 가능했지만 F1 Loss 같은 경우 조금의 Custom이 필요했다. 하지만 내가 한 Custom 방식으로는 제대로 된 학습이 수행되지 않아 결국 버리게 되었다. 나중에 설명을 들을 때 F1 Loss를 활용했다는 것을 듣고, 꼭 제대로 공부하여 더 많은 기법을 다양한 곳에 활용해야겠다는 생각을 하였다
Pretrained Model
vgg19 : 시간이 진짜 오래 걸린다. 77.81%
-> 활용... 괜찮을지도?
densenet : 77.20%
mnasnet1_0 : 37%
나의 착각이 작은 불이였다면, 이 착각에 기름을 부어버린 실험 결과 였다. mnasnet의 정확도가 매우 낮게 나오고 densenet 보다는 vgg가 Accuracy가 더 높게 나와 이후 이틀 동안 VGG를 기준으로 코드를 짰다.(위에서 말한 나의 가정이 맞는 줄 알았다)
하지만, 훗날 WandB를 활용했을 때 나의 잘못짠 코드와 우연한 결과의 환장의 콜라보라는 것을 알게 되었고, WandB의 유용성을 앎과 동시에 실험에 내 개인적인 생각이 들어가면 안되겠다는 생각을 하였다.
val 마지막에 합친 것 : 77.40
focal + vgg : 77.40
val 마지막에 합침 + focal + vgg : 76.87%
vgg + Only Linear : 77.55%
val 마지막에 합침 + vgg + Only Linear + focal : 77.55%
Cross Validation 기법에서 Train Data를 가장 마지막 3번 학습 때 활용하겠다는 생각으로 코드를 짜 실험을 수행하였다.
내가 Cross Validation에 대해 매우 무지했다는 것을 알게되는 실험 결과이다. 훗날 프로젝트를 피드백하면서 매우 부끄러운 부분이였다.
densenet 활용해보기
-> 유용할만 하다. 활용해보자
shufflenet 활용해보기
-> 유용하긴 하지만 Loss가 맘에 안 듬. 너무 높다
focal(혹시 모르니..) 활용해 보기
-> 생각보다 경향성이 괜찮다. 활용할까?
vgg도 활용은 해보자.(시간 남으면) -> 개쓰레기
vgg로 짠 코드를 자신만만하게 제출했지만 정확도가 더 낮아져 나의 생각이 틀렸다는 것을 알게 된 이후 다시 여러 Model을 활용하여 실험 한 결과이다.
WandB를 활용한 여러 가지 실험

잘했다고 생각한 점
정말 내가 할 수 있는 최대한의 실험을 해봤다고 생각한다. 물론 아는 것이 다른 사람보다 적어 활용할 수 있는 툴이 적었다는 것도 고려했어야 겠지만, 그래도 많은 Model을 활용했고 이를 통해 AI 프로젝트에 대한 자신감이 생겼다는 것이 가장 큰 소득이 아니였나 싶다.
또한 WandB에 대해 완벽히 파악했다는 것이 좋았다. 최소한 다음 팀에 가서도 WandB는 내가 담당할 수 있을 정도로 공부하였고 활용해봤기 때문에 많은 자신감이 생겼고, 다음부터는 프로젝트 초기부터 Loss에 대한 경향성을 파악하며 실험할 수 있다는 것이 가장 큰 이득인 것 같다.
아쉬운 점
아쉽기도 하고, 나에게 매우 큰 교훈을 준 기간이였다.
먼저, 편견을 버려야 한다는 생각을 했다. 3/3 가장 점수가 높게 나온 코드를 분석해보니 1개 Layer만 추가하였음을 알 수 있었다.
나는 무조건 Layer가 여러 개 있으면 좋을 줄 알고 일부러 3개 Layer를 추가시키고, 이 상황에서 가장 높은 Accuracy를 가지는 상황을 찾았다. 또한, Epoch을 10번도 돌리지 않았는데 가장 높은 Accuracy를 가지게 된다는 것이 정말 이해가 되지도 않았다. 내가 생각하는 AI는 최소 30~40번의 학습을 통해 완벽한 학습이 진행될 것이라고 착각했기 때문이다.
하지만 결론적으로는 제일 좋은 코드에서는 절대 epoch이 20번을 넘지 않았으며, 나중에 내가 따로 짜본 1층 Layer를 WandB로 경향성 파악을 해보니 Loss도 매우 좋고 Accuracy도 더 높게 나왔음을 알 수 있었다.
매우 후회된다. 앞으로 실험할 때는 절대 편견을 가지지 말고 무념무상으로 실험한 뒤 실험 결과를 스펀지처럼 흡수하며 생각을 발전시켜 나가야겠다.
배운 점
EfficientNet이라는 Model의 존재를 알게 되었다.
WandB의 활용 방법과 유용성을 알게 되었다.

