개미들을 위한 퀀트 자동 매매 프로그램 개발자 블로그입니다. 프로그래밍과 퀀트 투자를 합니다.

방구석퀀트

네이버카페 : 방구석 퀀트 놀러오세요^^ https://cafe.naver.com/conerquant 가입해 주세요.

2018년 8월 18일 토요일

(TF 1.9 & Slim) 3. 내 이미지로 학습 하기 ( caltech 이미지 사용 )

* Tensorflow 1.9 버전에서 Slim을 사용하기 위한 튜토리얼 리비전 입니다.

1. 윈도우에 Tensorflow GPU 버전 설치하기
2 딥러닝 slim 라이브러리 설치, 학습, 평가하기
3. 내 이미지로 학습 하기 ( caltech 이미지 사용 )
4. 학습된 모델 사용하기

2장까지 slim 모델을 이용해 flower 이미지를 학습하고 평가까지 실습 해 보았습니다. 코드 내용은 잘 모르지만 어쨋든 우리는 딥러닝(CNN)을 실제 사용해 본 것입니다. 그럼 우리가 원하는 이미지들에 대해서는 어떻게 학습 시킬 수 있을까요? 그 힌트는 우리가 직접 실습해본 flower 예제 파일에 있습니다. flower 예제 파일만 참고하여 응용하면 되기 때문입니다.

- 실습에 사용할 내 이미지 다운로드


Caltech-256 Object Category Dataset

다운로드 링크 : http://www.vision.caltech.edu/Image_Datasets/Caltech256/256_ObjectCategories.tar

관련 정보 링크
http://authors.library.caltech.edu/7694/

 257 카테고리로 이미지가 분류되어 제공되는 이미지 데이터 셋입니다. 압축된 상태에서 전체 파일 용량은 1.1GB 입니다. 총 이미지 수는 3만607개이고, 한 분류당 최대 827개, 최소 80개의 다양한 사이즈의 이미지로 구성되어 있습니다.


다운로드 받은 파일을 d:\tmp 폴더에 압축을 풀겠습니다.

- Caltech 이미지 폴더 변경하기


 flowers 이미지를 TFRecord로 변환시켰던 실습을 기억하실 겁니다.( 2장 ) 그 때 사용된 코드를 약간 변형 시켜 보겠습니다.

 그에 앞서 Caltech 이미지를 Flowers 이미지와 같은 형태로 폴더 구성을 먼저 해보겠습니다. 먼저 D:\tmp 폴더의 Flowers 폴더의 구조를 살펴 보겠습니다.


Flowers 폴더 하위에 Flowers_photos 폴더가 있고 그 하위에 각 category 별로 이미지들이 분류되어 저장되어 있는 것을 볼 수 있습니다. Caltech도 똑같이 구성해 보겠습니다.


 D:\tmp 폴더 하위에 기존 256_ObjectCategories 폴더의 이름을 caltech256으로 변경하고 그 하위 폴더의 256_ObjectCategories 폴더 이름을 caltech256_photos로 변경하였습니다.

- TFRecord 형태로 변환하기


* download_and_convert_data.py 수정

 위 파일은 지정한 이미지 데이터 셋을 다운로드하고 TFRecord 형태로 변환시키는 코드입니다. 우리는 이미지를 이미 수동으로 다운로드 받아 준비했기 때문에 TFRecord로 변환만 시키면 됩니다. 기존 Flowers 라는 키워드로 변환되게 작동하던 코드를 caltech256 이라는 키워드로 작동 될 수 있게 코드를 수정해보겠습니다!

- download_and_convert_data.py 코드 변경


 앞절에 이어 Caltech 이미지들을 TFRecord 형태로 변환 시키기 위해 download_and_convert_data.py 코드를 Spyder로 열어 분석 해보겠습니다.


 39~41, 62~67 라인을 보면 각각의 이미지 셋에 대응하는 또다른 python 코드들이 할당 되어 있는 것을 볼 수 있습니다. 우리는 Caltech256 이라는 키워드를 사용할 것이기 때문에 기존 코드에 Caltech256 관련 코드를 추가해 보겠습니다.


 위와 42라인, 69~70라인에 clatech256 키워드가 작동하도록 코드를 추가하고 저장하세요.


- slim\datasets\ 에 Caltech 파일 만들기


slim 모델 폴더에 보면 datasets 라는 폴더가 보일 겁니다. 그 안에 보면 아래와 같은 파일들로 구성되어 있습니다.


오호라... 딱 보니 각 이미지셋 마다 대응되는 파일들이 만들어져 있네요. 그럼 같은 형태로 Caltech256 파일도 만들어주면 되겠습니다. 우리는 현재 Flowers를 참고해서 만들고 있기 때문에 download_and_convert_flowers.py 를 복사해서 이름을 download_and_convert_caltech256.py로 변경하겠습니다. 동일하게 flowers.py를 복사해서 이름을 caltech256.py로 변경 하겠습니다.


- download_and_convert_caltech256.py 파일 수정하기


그럼 download_and_convert_caltech256.py 파일을 Spyder로 열어서 살펴보겠습니다.


 코드를 수정하면서 진행하기 때문에 코드 라인넘버는 무시하고 키워드를 보면서 본인의 실습 코드를 수정하기 바랍니다.
 처음 변경해야 하는 코드는 _NUM_VALIDATION 입니다. 기존 flower 이미지에서는 350으로 설정되어 있었습니다. 설정 값의 의미는 TFRecord 형태의 파일로 변환 할때 Train 용 파일과 Validation 파일용으로 따로 변환하게 되는데 이때 Validation에 해당하는 파일에 몇개의 이미지를 할당할것인지 정하는 값입니다. 우리는 Caltech256 이미지가 총 30607개이고 여기에서 20%에 해당하는 6121개의 이미지를 Validation 용으로 할당하겠습니다.
 다음 코드는 _NUM_SHARDS 입니다. Flowers 이미지는 5라는 값이 설정되어 있었습니다. 실제 tmp\flowers\ 폴더에 가보면 TFRecord로 변환된 이미지 파일이 Train/Validation 각각 5개의 파일로 변환되어 있는 것을 볼 수 있습니다. Train의 파일 하나가 40MB 정도 되네요. 그럼 Caltech256 전체 이미지 용량이 1.1GB 정도 되니 20을 설정하면 Train 파일 하나당 40MB 정도 될거 같네요.

 다음은 def _get_filenames_and_classes(dataset_dir): 함수를 수정해 보겠습니다. 위와 같이 flower라는 단어가 보일 겁니다. 아래와 같이 flower 를 caltech256으로 변경하겠습니다.



 마지막으로 바꿀 코드는 아래와 같습니다. TFRecord 형태의 출력 파일 이름을 설정하는 코드 입니다. flowers 를 caltech256으로 변경하고 저장해주세요. 190라인은 flowers 이미지를 다운 받는 코드인데 #으로 주석 처리 해주세요.



- caltech256.py 코드 변경


 이번 파일에서는 딱 3줄만 변경하면 됩니다. 우선 32라인의 flowers를 caltech256으로 변경하세요.  다음 SPLITS_TO_SIZES의 validation 값은 기존 350에서 6121로 변경하고, train 값은 3320에서 24486으로 변경하겠습니다.(30607 - 6121) 마지막으로 _NUM_CLASSES는 분류되어 있는 category 갯수로 바꾸면 되는데 caltech256은 257 categories 이기 때문에 257로 변경하고 저장하겠습니다.


다 됐을까요? 다 변경 한 것인가요??? 파일 하나 더 변경해야 합니다!

- dataset_factory.py 코드 변경


 이제 진짜 마지막 파일입니다. 힘을 냅시다. Spyder로 dataset_factory.py를 열어 보겠습니다. 오 아주 간단하게 추가만 하면 되겠네요. 아래와 같이 추가하고 저장하세요.


- TFRecord 변환하기(download_and_convert_data.py 실행)


드디어 TFRecord 파일로 변환을 시켜 보겠습니다. slim 폴더로 이동해서 아래 코드를 실행 시켜 보세요.
python download_and_convert_data.py --dataset_name=caltech256 --dataset_dir=/tmp/caltech256
아... 변환이 잘 되는 듯 하다 에러가 나네요. 제가 이 에러 잡으려고 삽질 많이 했습니다. 어떤 문제인지 확인 하기 위해 datasets 폴더의 download_and_convert_caltech256.py 코드에 현재 변환되고 있는 이미지 파일 이름을 표시하도록 아래와 같이 수정하겠습니다.


자 다시 아래 코드를 실행 시켜 보겠습니다.
python download_and_convert_data.py --dataset_name=caltech256 --dataset_dir=/tmp/caltech256
어떤 이미지에서 에러가 났는지 잡았습니다!


caltech 이미지중 56번 dog category 폴더에 greg 라는 파일이... 이미지 파일이 아니라 폴더 이름입니다. 지워버리세요!

다시 코드를 실행하겠습니다. 또 에러입니다. 이번엔 JPG 파일이 아니네요. 198번 spider category 폴더에 RENAME2라는 파일이 있습니다. 지워버리세요!

자 다시 아래 코드를 실행 시켜 보겠습니다.
python download_and_convert_data.py --dataset_name=caltech256 --dataset_dir=/tmp/caltech256
변환에 성공 했습니다! 아래 폴더에 보면 아래화면과 같이 TFRecord로 변환된 파일이 생성된 것을 확인할 수 있습니다!



- 학습하기


이제 학습을 해보겠습니다.  2장 2.2절 모델 학습하기 실습 중 2) Fine-tuning a model from an existing checkpoint 에서 사용한 방법으로 학습을 진행 하겠습니다.

- 학습 1번 과정 #Fine-tune only the new layers for 1000 steps.


python train_image_classifier.py
  --train_dir=\tmp\train_inception_v1_caltech256_FineTune_logs
  --dataset_name=caltech256
  --dataset_split_name=train
  --dataset_dir=\tmp\caltech256
  --model_name=inception_v1
  --checkpoint_path=\tmp\my_checkpoints/inception_v1.ckpt
  --checkpoint_exclude_scopes=InceptionV1/Logits
  --trainable_scopes=InceptionV1/Logits

  --max_number_of_steps=1000
  --batch_size=16
  --learning_rate=0.01
  --learning_rate_decay_type=fixed
  --save_interval_secs=60
  --save_summaries_secs=60
  --log_every_n_steps=100
  --optimizer=rmsprop
  --weight_decay=0.00004
python train_image_classifier.py --train_dir=\tmp\train_inception_v1_caltech256_FineTune_logs --dataset_name=caltech256 --dataset_split_name=train --dataset_dir=\tmp\caltech256 --model_name=inception_v1 --checkpoint_path=\tmp\my_checkpoints\inception_v1.ckpt --checkpoint_exclude_scopes=InceptionV1/Logits --trainable_scopes=InceptionV1/Logits --max_number_of_steps=1000 --batch_size=16 --learning_rate=0.01  --learning_rate_decay_type=fixed --save_interval_secs=60 --save_summaries_secs=60 --log_every_n_steps=100 --optimizer=rmsprop --weight_decay=0.00004
 학습이 잘 이루어졌습니다.


- 학습 2번 과정 # Fine-tune all the new layers for 500 steps.


python train_image_classifier.py
  --train_dir=\tmp\train_inception_v1_caltech256_FineTune_logs\all
  --dataset_name=caltech256
  --dataset_split_name=train
  --dataset_dir=\tmp\caltech256
  --model_name=inception_v1

  --checkpoint_path=\tmp\train_inception_v1_caltech256_FineTune_logs

  --max_number_of_steps=500

  --batch_size=16

  --learning_rate=0.0001
  --learning_rate_decay_type=fixed
  --save_interval_secs=60
  --save_summaries_secs=60
  --log_every_n_steps=10
  --optimizer=rmsprop
  --weight_decay=0.00004

python train_image_classifier.py --train_dir=\tmp\train_inception_v1_caltech256_FineTune_logs\all --dataset_name=caltech256 --dataset_split_name=train --dataset_dir=\tmp\caltech256 --model_name=inception_v1 --checkpoint_path=\tmp\train_inception_v1_caltech256_FineTune_logs --max_number_of_steps=500 --batch_size=16 --learning_rate=0.0001 --learning_rate_decay_type=fixed --save_interval_secs=60 --save_summaries_secs=60 --log_every_n_steps=10 --optimizer=rmsprop --weight_decay=0.00004
 학습이 잘 이루어졌습니다.


- 평가하기


2장 2.3절에서 3번 모델 평가 방법으로 코드를 실행해 보겠습니다.



python eval_image_classifier.py
--alsologtostderr
--checkpoint_path=\tmp\train_inception_v1_caltech256_FineTune_logs\all\
--dataset_dir=\tmp\caltech256
--dataset_name=caltech256
--dataset_split_name=validation
--model_name=inception_v1
python eval_image_classifier.py –alsologtostderr --checkpoint_path=\tmp\train_inception_v1_caltech256_FineTune_logs\all\ --dataset_dir=\tmp\caltech256 --dataset_name=caltech256 --dataset_split_name=validation --model_name=inception_v1
모델 예측 정확도 평가가 나왔습니다.


학습하는데 10분도 사용하지 않았는데 TOP 5 예측 정확도가 90.5%가 나옵니다.

이상 TF-slim 모델을 응용해 Caltech 256 이미지를 학습시키고 평가까지 해보았습니다. 지금의 3장을 잘 응용하면 자신이 원하는 이미지에 얼마든지 딥러닝을 적용 시켜 볼 수 있습니다!

질문은 댓글로 주세요.

댓글 7개:

  1. 2번 학습과정은 원래 했던 학습을 이어서 하는 개념으로 이해하면 되는건가요?
    이어서 하되 추가로 이미지를 넣었을경우에는 레코드 변환부터 다시해야 하는지 궁금합니다!

    답글삭제
    답글
    1. 네 맞아요~ 새로 추가할 이미지를 해당 분류 라벨의 폴더에 넣고, tfrecord 생성과정을 다시 해야합니다~

      삭제
  2. 안녕하세요? 우선 좋은 글 감사합니다.
    1번의 과정과 2번 과정에서 learning_rate를 다르게 하는 이유가 있나요??
    모든 레이어를 파인 튜닝하려면 느리게 하는게 더 효과적인가요??

    답글삭제
  3. 학습한 코드를 바탕으로 새로운 이미지 한 장을 준비하여 비교하려면 어떻게 해야하나요??

    답글삭제
  4. 만약, caltech256에서 분류할 이미지를 추가한다면 처음부터 TFRecord를 다시 만들어서, 1번과정을 거치고 2번과정을 거치는 것밖에 방법이 없나요?
    Inception_v1처럼 caltech256을 가장 마지막에 학습시킨 모델을 바탕으로 1번 2번 방법을 사용해서 추가 학습을 시킬 수는 없는 것인지 궁금합니다.

    답글삭제
    답글
    1. 분류할 category 갯수가 같다면, 이미지를 추가하고 TFRecord를 새로 만든 후 2번으로 바로 넘어 가면 됩니다.
      1번을 하는 이유는 category 갯수가 원래 inception 모델과 달라서 caltech에 맞게 바꾸어 준다는 의미이고요,
      2번에서는 --checkpoint_path=\tmp\train_inception_v1_caltech256_FineTune_logs 이 옵션이 들어감으로써 이미 존재하던 모델을 기반으로 계속해서 학습해 나가는 겁니다.
      위 옵션이 안들어 간다면 완전 새롭게 처음부터 학습을 하게 됩니다.

      삭제
  5. 자세한 설명 감사합니다!!
    한가지 여쭤볼게있는데 4개 클래스 총 25개 이미지로는 정확도가 0이 나올수가있나요? 이미지가 많아야하는건지
    테스트하면 마지막에

    I0406 23:42:38.494717 4408 evaluation.py:167] Evaluation [1/1]
    eval/Accuracy[0]
    eval/Recall_5[1]

    이렇게 출력되네요 ㅜ ㅜ

    답글삭제

가장 많이 본 글