첫 블로그 내용으로는 BTS 이미지를 분류해봤습니다. BTS를 선택한 이유는 팬이기도 하고 유명하니까 자료 얻기도 쉽지 않을까 하는 생각에 선택했습니다! 그래서 BTS 멤버 이미지를 가지고 분류하는 코드를 작성해봤는데, 틀렸다거나 다른 이견이 있으시다면 언제든 말씀해 주시면 감사하겠습니다 ^^
자료는 다음 이미지를 크롤링했습니다. 한명 당 1300건을 수집했고, 훈련에 부적합한 이미지를 거른 후 총 7649장을 사용했습니다.
채널이 RGB가 아닌 사진들을 제거합니다. 삭제 전 후 이미지 수가 같은 이유는 사전에 미리 코드를 돌렸습니다.
대략 30장이 삭제되었는데 거의 15분 정도가 걸렸습니다.
각 멤버별로 인덱스를 enumerate로 넣어줍니다. class 2_idx는 tfrecord를 통해서 모델의 label로 사용됩니다.
첫 번째 고민했던 부분
실습 때와 다르게 각 멤버별로 이미지 수가 달라서 train, test를 어떻게 나눌까 였습니다.
"사실 처음 시도했을 때는 각 멤버별 이미지 수가 다르다는 걸 생각지 못했었습니다 ㅠ "
위 코드로 각 멤버별 이미지 수를 파악한 후에 7:3 비율로 분리했습니다.
7:3으로 분리하는 사용자 정의 함수를 만든 후, 각 멤버 별로 적용했습니다. "이제 보니까 for문으로 좀 더 깔끔하게 할 수 있지 않았을까 생각이 듭니다."
train_dir, validation_dir으로 분리된 이미지의 수를 파악해봅니다. train 이미지는 5358, validation 이미지는 2291장입니다. ""각 멤버 별 train 수가 1000장이 안되기 때문에 기대에 맞는 성능은 나오지 못할 거란 걸 알고 있었지만 크롤링한 이미지를 모두 전수 검사를 하다 보니까 (3시간 소요) 힘이 들어서 양을 늘릴 엄두를 못 냈습니다""
TFRecord File 생성
tfrecord에 대해서 더 공부해야 할 부분이 많지만 장점을 말씀드리자면 대규모 데이터를 효율적으로 처리할 수 있다는 장점을 가지고 있습니다. tfrecord형식은 이진 레코드의 시퀀스를 저장할 수 있는 간단한 형식입니다.
경험상 dataset으로 만드는 과정이 비교적 간단하다고 생각합니다.
tfrecord file을 저장할 경로를 설정해줍니다.
tensorflow 홈페이지에 있는 코드입니다. 이 함수들을 통해서 일반 data를 tfrecord data로 변환합니다.
image는 bite로 직렬화 해서 만들고, 레이블은 int형식으로 지정해줍니다. validation도 동일하게 위 코드처럼 진행해서 이미지는 생략했습니다.
생성이 되었는지 확인해 봅니다.
hyper parameter를 설정합니다.
tfrecord file를 data로 해석해주는 함수를 정의합니다. 해석된 data로 dataset를 만들 예정입니다. 그리고
IMG_SIZE= 224로 설정했습니다.
loss, acc 그래프를 그려본 결과입니다. loss감소, val_loss 증가 형태는 과적 합의 그래프입니다. epoch 수가 적기 때문에 단지 튀는 과정일 수도 있습니다. 따라서 acc 그래프도 같이 보았습니다.(오른쪽 사진)
acc 그래프에는 val_loss가 일정한 걸 보아서는 epoch를 늘려도 변함이 없어 보임으로 과적합임을 확인할 수 있었습니다. 과적합을 없애기 위해서 BatchNormalization과 데이터 증식을 적용시켜 봤습니다.
train 이미지에 다양한 옵션을 설정했습니다. validation 이미지에는 rescale만 적용시켜 줍니다.
위 사진처럼 같은 이미지라도 다르게 만들어서 Data의 부족을 해결합니다.
class_mode에서 이진 분류를 한다면 binary를 넣고, 이진이 아닌 다중 분류라면 정수 라벨을 반환하는 sparse로 설정합니다. BTS는 7개의 라벨이 있기 때문에 sparse로 적용시켜줍니다.
파라미터 정리
2D one-hot 부호화된 라벨이 반환됩니다.
binary : 1D 이진 라벨이 반환됩니다
sparse : 1D 정수 라벨이 반환됩니다.
val_accuray: 29.73%
loss, acc 그래프를 본 결과 과적합이 사라 졌음을 볼 수 있었습니다. epoch를 더 늘리면 성능이 좀 더 올라갈 것으로 보입니다.
이 결과를 통해 새로운 이미지를 test 해보겠습니다.
지민 사진을 넣었는데 예측 값으로 진이 나왔습니다.
과적합을 해결했지만 성능 측면에서 아쉬운 부분이 있습니다. 따라서, 사전학습을 통해 성능을 올려 보도록 하겠습니다.
사용될 사전학습 모델은 VGG16입니다.
모델을 imagenet을 통해 다운로드합니다.
이 외에 나머지 코드는 위에서 했던 코드와 상당수 일치하므로 새로 추가된 코드만 올리겠습니다
정확도가 전 모델에 비해 크게 상승했습니다. 그래프를 통해 과적합 여부를 쉽게 파악합니다.
epoch 10 이상부터는 과적합 전조 현상이 보입니다. v16 model에는 적용하지 않았지만 과적합을 줄이기 위해서 dropout를 시도해 볼 수도 있겠습니다.
마지막으로 아까와 같은 이미지로 테스를 진행해보겠습니다.
그 결과
"지민" -> "김남준"으로 오답을 예측했습니다.
과적합이 발생했기 때문에 정답을 맞혔더라도 모델 수정은 반드시 이뤄져야 할 것 같습니다.
느낀 점
처음으로 CNN 프로젝트를 짧게나마 진행해봤습니다. 깔끔하게 정리된 이미지를 가지고 실습하다가 실전 이미지를 다루다 보니 많은 시행착오가 있었습니다. 전처리하는데 대부분 시간이 소요되었습니다. 아직 많이 부족하지만 배울게 많다는 게 인공지능 분야의 장점이라고 생각합니다. 감사합니다