{
  "id": 286889,
  "title": "저용량 데이터를 위한 Image Augmentation & Transfer Learning ",
  "url": "/competitions/animal-classification/discussion/286889",
  "author_name": "JinsoooPark",
  "post_date": "2021-11-11T09:16:42.853000",
  "votes": 6,
  "comment_count": 0,
  "views": 0,
  "content": "<p>이번 Competition에 쓰인 데이터의 특징은 적은 데이터(3000개), 적은 클래스(4)입니다. </p>\n<p>사실 이번 데이터에서 구분해야 하는 클래스는 4개밖에 안되기 때문에, 지금까지의 베이스라인 코드(CNN , Dropout,  Batch Normalization)만으로도 충분한 성능을 뽑아낼 수 있지 않을까? 라는 생각이 들긴 듭니다. </p>\n<p>그래서, 지금까지 과제에서 제출했던 베이스라인 코드와 과적합 해소 방안(Dropout, Batch Normalization)을 추가한 CNN 모델을 이용해 학습시켜보고 성능을 평가해보는 게 우선이라고 생각합니다.</p>\n<hr>\n<p><strong>단, Test data를 불러올 때 <code>shuffle=False</code>를 사용해야 합니다 !</strong></p>\n<pre><code># test data 불러오기\n\ntestd=test_gen.flow_from_directory('/kaggle/input/animal-classification/test',\n   target_size = (299,299),       # 이미지의 크기는 특정 size로 통일\n   class_mode='sparse',\n   shuffle=False,                        # shuffle=False 필수\n   batch_size=1)                         # 필수는 아닐 듯\n</code></pre>\n<p>sample submission csv에 저희 모델로 예측(<code>model_first.predict_generator(testd)</code>)한 라벨을 탑재할 때에는 데이터 폴더에서 불러오는 이미지 <strong>순서 그대로</strong> 넣어야 합니다. 그렇기 때문에 이미지 데이터를 불러올 때에 순서가 섞이지 않게 Shuffle을 꺼주어야 한다고 생각합니다.</p>\n<p>(Default 값으로 Shuffle=False로 들어갈 줄 알았는데 찾아보니 Shuffle=True가 Default라고 합니다.)</p>\n<hr>\n<p>아무튼, 과제에 사용했던 기본적인 CNN 구조와 (Data Augmentation, Dropout, Batch Normalization, …) 등 과적합 해소 기법들만으로도 저희 모델은 4개의 Class를 잘 구분할 수도 있습니다.<br>\n그렇다면 굳이 복잡한 모델을 끌고와서 학습시키는 것은 시간 낭비겠지요.</p>\n<p>다만 데이터가 너무 적어서 성능이 잘 안 나올 수도 있습니다.  </p>\n<p>이럴 때,  성능을 더욱 올리기 위해 일반적으로 사용하는 대표적인 방법은 아래와 같습니다.</p>\n<ol>\n<li><p>모델 구조 변경</p>\n<ul>\n<li>CNN을 층을 더 많이 쌓는다든지, 혹시나 Dropout -&gt; conv2d -&gt; BatchNorm layer 중에 하나를 빼먹었다면 추가를 해준다든지.. </li></ul></li>\n<li><p><strong>데이터 증강(Data Augmentation)</strong></p>\n<ul>\n<li>과제에 사용했던 CNN 모델을 사용하더라도, 적은 데이터를 보완하기 위해 Data Augmentation을 수행해주는 것이 좋습니다(강의 내 슬라이드 참고).</li></ul></li>\n<li><p><strong>전이 학습(Transfer Learning)</strong></p>\n<ul>\n<li>전이학습도 강의 내 슬라이드에서 간략히 다루었습니다. </li>\n<li>과제에 사용했던 CNN 모델을 사용하지 않고 대용량 데이터에 학습시켜놨던 대규모 모델을 불러와 저희 task에 맞게 다시 학습하는 과정입니다.</li>\n<li>모델 자체가 기본적인 CNN 모델과는 비교도 안 되게 크기 때문에 아무리 Transfer learning이라 해도 오래 걸릴 수 있습니다. </li>\n<li>아래에서 조금 더 자세히 다루겠습니다.</li></ul></li>\n</ol>\n<p>여기서는 모델 구조보다는 <strong>데이터 증강</strong>과 <strong>전이학습</strong>에 대해서 간략히 다루도록 하겠습니다.</p>\n<p><br></p>\n<h1>1. 데이터 증강</h1>\n<hr>\n<p>데이터 증강은 슬라이드에 나와있었던 것처럼 </p>\n<pre><code>from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\nigen=ImageDataGenerator(rescale=1/255, validation_split=0.2, \n                       width_shift_range=0.2, height_shift_range=0.2, \n                       zoom_range=0.2, \n                        horizontal_flip=True, vertical_flip=True,\n                        shear_range=0.2,brightness_range=(0.2,1.3))\n</code></pre>\n<p>이미지를 불러올 때 위와 같은 shift, zoom, flip, shear, brightness에 대한 인자를 넣어주면 됩니다.<br>\n그러면, 자동적으로 매 epoch마다 새롭게 변한 이미지를 추출해 학습하기 때문에 더욱 많은 데이터로 학습하는 효과를 얻을 수 있습니다. <br>\n<br></p>\n<h2>2. 전이 학습</h2>\n<hr>\n<p>이미지 분야든, 자연어 처리 분야든 대용량의 데이터에 미리 학습시켜 놓은 초대형 모델(pre-trained model)을 이용해 저희들이 원하는 task에 전이학습(transfer learning)을 적용시키는 것이 성능 보장을 위한 가장 확실한 방법입니다.</p>\n<p>본래 저희가 예측할 데이터에 대해<br>\n(1) pre-trained 모델에 쓰인 데이터와 우리 데이터의 특징이 비슷한지<br>\n(2) 우리 data의 size가 어떤지</p>\n<p>에 따라 학습 전략을 나누기는 해야 합니다..만은<br>\n어차피 저희가 사용할 데이터는 동물이기 때문에 (1)은 신경쓸 필요가 없습니다.</p>\n<p>즉, 적은 데이터를 사용하는 저희 모델에만 조심스럽게 전이학습 시키면 됩니다.</p>\n<p>이에 대해서는 아래의 tutorial code를 참고해 거의 유사하게 따라하면 됩니다.</p>\n<p><strong>영어(추천)</strong><br>\n<a href=\"https://keras.io/guides/transfer_learning/\" target=\"_blank\">https://keras.io/guides/transfer_learning/</a></p>\n<ul>\n<li>위 두 개의 tutorial 중에 영어로 된 keras guide는 전이학습(특징 추출 &amp; 미세 조정 - 강의 슬라이드에도 존재)에 대한 내용만 담고 있기 때문에 훨씬 더 깔끔합니다. </li>\n</ul>\n<ol>\n<li>강의 내 과제에서 했던 것과 똑같이 데이터 전처리 -&gt; 이미지 분석 … 실행</li>\n<li>위 keras guide 내 <strong>The typical transfer-learning workflow</strong> 이하 코드들을 참고해 특징 추출 &amp; 미세 조정 진행.</li>\n</ol>\n<p><strong>한글(참고용)</strong><br>\n<a href=\"https://www.tensorflow.org/tutorials/images/transfer_learning?hl=ko\" target=\"_blank\">https://www.tensorflow.org/tutorials/images/transfer_learning?hl=ko</a></p>\n<ul>\n<li>한글로 된 tensorflow tutorial는 특징 추출 &amp; 미세 조정 외에도 데이터 전처리를 포함하고 있기 때문에 참고하기에 좋지는 않습니다.</li>\n<li>다만 내용자체는 영어판이랑 거의 똑같으며 해당 페이지 내 \"특징 추출\" 이하 코드부터 참고하면 좋을 것 같습니다. <br>\n<br></li>\n</ul>\n<h1>Tip</h1>\n<hr>\n<h2>1. 저희에게 주어진 데이터는 이미지의 크기가 제각각입니다.</h2>\n<ul>\n<li><p>그렇기 때문에 이미지의 크기는 정사각형 크기의 이미지로 통합해주어야 합니다.</p></li>\n<li><p>여기에는 다양한 방법(이미지의 크기를 모두 불러와 평균 크기의 사이즈로 모두 바꾼다든지…)이 있겠지만, 저희가 배웠던 method <code>flow_from_directory</code> 의 <code>target_size</code> 인수를 이용하면 이미지의 크기를 모두 통일할 수 있습니다.</p></li>\n</ul>\n<pre><code>traind=igen.flow_from_directory(trainp, target_size = (150,150), #여기\n    batch_size = bs,class_mode = 'sparse' , subset='training')\n</code></pre>\n<p>저희 데이터의 이미지 크기는 대략 300~400 정도 되는 걸로 기억하기 때문에 위처럼 target_size를 (150, 150)로 통일해도 문제는 없습니다(저희 이미지가 30 x 30인데 150 x 150로 키우는 건 문제가 많겠죠).</p>\n<p>위에서 굳이 (150,150)를 예시로 든 이유는 위에 첨부한 keras guide의 예시(아래)가 pre-trained 모델인 Xception을 불러올 때 input_shape를 (150,150,3)으로 불러왔기 때문입니다.</p>\n<pre><code>base_model = keras.applications.Xception(\n    weights='imagenet',  # Load weights pre-trained on ImageNet.\n    input_shape=(150, 150, 3), # 여기\n    include_top=False)  # Do not include the ImageNet classifier at the top.\n</code></pre>\n<p>당연히 저희가 이미지 전처리할 때 통일할 target_size와 저희가 사용할 pre-trained model의 input_shape는 통일시켜주어야 합니다.</p>\n<p>다만 저희 이미지는 300~400인데 이미지 사이즈를 150으로 줄인다면 성능이 안 좋아질 수도 있기 때문에, 각 모델이 허용하는 최대 크기의 이미지로 통일하는 게 좋습니다(위의 예시에서 Xception을 불러올 때 input shape를 (150,150,3)으로 했으나, 원래 default는 (299,299,3)까지 지원합니다). </p>\n<h2>2. 사용할 pre-trained model 고르기</h2>\n<p>위의 예시에서는 pre-trained model로 Xception을 사용했습니다만, 더 좋은 모델이 있을 수 있겠죠? </p>\n<p><a href=\"https://keras.io/api/applications/\" target=\"_blank\">https://keras.io/api/applications/</a></p>\n<p>위의 링크를 참고해 분류 성능이 좋고, 가벼운 모델을 잘 골라서 pre-trained 모델로 사용하면 됩니다.</p>\n<ul>\n<li>지금 보니 Xception도 성능이 굉장히 좋고, 가볍네요.</li>\n</ul>\n<h2>3. Test data Generator에는 당연히 data augmentation을 적용하면 안 됩니다.</h2>\n<pre><code># DataGenerator를 새로 생성하되, 그냥 이미지의 scale만 조정해주어야 합니다.\ntest_gen=ImageDataGenerator(rescale=1/255)\n</code></pre>\n<ul>\n<li>원래 Valid data Generator에도 data augmentation을 적용하면 안 된다고는 하는데(test data랑 밀접해야 하므로),  여러모로 귀찮을 것 같아서 그냥 Validation data도 똑같은 Generator에서 불러왔습니다(찾아보면 valid data에 augmentation 적용하지 않는 방법도 있지 않을까 합니다). </li>\n</ul>\n<pre><code># (위에서 정의한 image generator)\ntraind=igen.flow_from_directory(trainp, target_size = (299,299),\n    batch_size = bs,class_mode = 'sparse' , subset='training')\n\n# 원래 validation data에는 Augmentation이 적용되면 안 되지만, 크게 상관은 없으리라 생각하고\n# Data augmentation을 적용한 Generator에서 validation data도 가져옵니다.\nvald=igen.flow_from_directory(trainp, target_size = (299,299),\n    batch_size = bs,class_mode = 'sparse' , subset='validation')\n</code></pre>\n<h2>4. 위에서 말했다시피 Test data를 불러올 때 <code>shuffle=False</code>를 사용해야 합니다 !</h2>\n<pre><code># test data 불러오기\ntestd=test_gen.flow_from_directory('/kaggle/input/animal-classification/',target_size = (299,299)\n                                  ,class_mode='sparse',\n                                  shuffle=False, batch_size=1) # shuffle=False 필수일 것.\n</code></pre>\n<ul>\n<li>Label을 제출할 때에는 이미지 폴더에 적재된 이미지를 순서대로 불러와야 온전한 평가가 가능하기 때문에 위에서 test data를 불러올 때에는 shuffle=False를 할당해야 합니다.</li>\n<li>저 인자를 사용하지 않았을 때에 점수가 어떻게 나오는 지는 확인하지 않았지만, 학습의 의미를 잃기 때문에 아마 랜덤하게 라벨을 예측할 것이고, 25%가량의 정확도(4개 class 중 하나)가 나올 것이라 생각합니다.</li>\n<li>(아닐 수도 있습니다 ㅎㅎ)</li>\n</ul>\n<hr>\n<ul>\n<li>참고로 저는 Fine-Tuning까지 하지 않고 그냥 Feature Extraction만 수행했습니다. 베이스 라인 모델(pre trained model)의 모든 레이어가 trainable하게 설정해준 다음 fine tuning까지 조심스레 해준다면 성능이 더 높아지지 않을까 싶습니다. </li>\n</ul>",
  "messages": [
    {
      "id": 1578689,
      "postDate": "2021-11-11T09:16:42.853Z",
      "content": "<p>이번 Competition에 쓰인 데이터의 특징은 적은 데이터(3000개), 적은 클래스(4)입니다. </p>\n<p>사실 이번 데이터에서 구분해야 하는 클래스는 4개밖에 안되기 때문에, 지금까지의 베이스라인 코드(CNN , Dropout,  Batch Normalization)만으로도 충분한 성능을 뽑아낼 수 있지 않을까? 라는 생각이 들긴 듭니다. </p>\n<p>그래서, 지금까지 과제에서 제출했던 베이스라인 코드와 과적합 해소 방안(Dropout, Batch Normalization)을 추가한 CNN 모델을 이용해 학습시켜보고 성능을 평가해보는 게 우선이라고 생각합니다.</p>\n<hr>\n<p><strong>단, Test data를 불러올 때 <code>shuffle=False</code>를 사용해야 합니다 !</strong></p>\n<pre><code># test data 불러오기\n\ntestd=test_gen.flow_from_directory('/kaggle/input/animal-classification/test',\n   target_size = (299,299),       # 이미지의 크기는 특정 size로 통일\n   class_mode='sparse',\n   shuffle=False,                        # shuffle=False 필수\n   batch_size=1)                         # 필수는 아닐 듯\n</code></pre>\n<p>sample submission csv에 저희 모델로 예측(<code>model_first.predict_generator(testd)</code>)한 라벨을 탑재할 때에는 데이터 폴더에서 불러오는 이미지 <strong>순서 그대로</strong> 넣어야 합니다. 그렇기 때문에 이미지 데이터를 불러올 때에 순서가 섞이지 않게 Shuffle을 꺼주어야 한다고 생각합니다.</p>\n<p>(Default 값으로 Shuffle=False로 들어갈 줄 알았는데 찾아보니 Shuffle=True가 Default라고 합니다.)</p>\n<hr>\n<p>아무튼, 과제에 사용했던 기본적인 CNN 구조와 (Data Augmentation, Dropout, Batch Normalization, …) 등 과적합 해소 기법들만으로도 저희 모델은 4개의 Class를 잘 구분할 수도 있습니다.<br>\n그렇다면 굳이 복잡한 모델을 끌고와서 학습시키는 것은 시간 낭비겠지요.</p>\n<p>다만 데이터가 너무 적어서 성능이 잘 안 나올 수도 있습니다.  </p>\n<p>이럴 때,  성능을 더욱 올리기 위해 일반적으로 사용하는 대표적인 방법은 아래와 같습니다.</p>\n<ol>\n<li><p>모델 구조 변경</p>\n<ul>\n<li>CNN을 층을 더 많이 쌓는다든지, 혹시나 Dropout -&gt; conv2d -&gt; BatchNorm layer 중에 하나를 빼먹었다면 추가를 해준다든지.. </li></ul></li>\n<li><p><strong>데이터 증강(Data Augmentation)</strong></p>\n<ul>\n<li>과제에 사용했던 CNN 모델을 사용하더라도, 적은 데이터를 보완하기 위해 Data Augmentation을 수행해주는 것이 좋습니다(강의 내 슬라이드 참고).</li></ul></li>\n<li><p><strong>전이 학습(Transfer Learning)</strong></p>\n<ul>\n<li>전이학습도 강의 내 슬라이드에서 간략히 다루었습니다. </li>\n<li>과제에 사용했던 CNN 모델을 사용하지 않고 대용량 데이터에 학습시켜놨던 대규모 모델을 불러와 저희 task에 맞게 다시 학습하는 과정입니다.</li>\n<li>모델 자체가 기본적인 CNN 모델과는 비교도 안 되게 크기 때문에 아무리 Transfer learning이라 해도 오래 걸릴 수 있습니다. </li>\n<li>아래에서 조금 더 자세히 다루겠습니다.</li></ul></li>\n</ol>\n<p>여기서는 모델 구조보다는 <strong>데이터 증강</strong>과 <strong>전이학습</strong>에 대해서 간략히 다루도록 하겠습니다.</p>\n<p><br></p>\n<h1>1. 데이터 증강</h1>\n<hr>\n<p>데이터 증강은 슬라이드에 나와있었던 것처럼 </p>\n<pre><code>from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\nigen=ImageDataGenerator(rescale=1/255, validation_split=0.2, \n                       width_shift_range=0.2, height_shift_range=0.2, \n                       zoom_range=0.2, \n                        horizontal_flip=True, vertical_flip=True,\n                        shear_range=0.2,brightness_range=(0.2,1.3))\n</code></pre>\n<p>이미지를 불러올 때 위와 같은 shift, zoom, flip, shear, brightness에 대한 인자를 넣어주면 됩니다.<br>\n그러면, 자동적으로 매 epoch마다 새롭게 변한 이미지를 추출해 학습하기 때문에 더욱 많은 데이터로 학습하는 효과를 얻을 수 있습니다. <br>\n<br></p>\n<h2>2. 전이 학습</h2>\n<hr>\n<p>이미지 분야든, 자연어 처리 분야든 대용량의 데이터에 미리 학습시켜 놓은 초대형 모델(pre-trained model)을 이용해 저희들이 원하는 task에 전이학습(transfer learning)을 적용시키는 것이 성능 보장을 위한 가장 확실한 방법입니다.</p>\n<p>본래 저희가 예측할 데이터에 대해<br>\n(1) pre-trained 모델에 쓰인 데이터와 우리 데이터의 특징이 비슷한지<br>\n(2) 우리 data의 size가 어떤지</p>\n<p>에 따라 학습 전략을 나누기는 해야 합니다..만은<br>\n어차피 저희가 사용할 데이터는 동물이기 때문에 (1)은 신경쓸 필요가 없습니다.</p>\n<p>즉, 적은 데이터를 사용하는 저희 모델에만 조심스럽게 전이학습 시키면 됩니다.</p>\n<p>이에 대해서는 아래의 tutorial code를 참고해 거의 유사하게 따라하면 됩니다.</p>\n<p><strong>영어(추천)</strong><br>\n<a href=\"https://keras.io/guides/transfer_learning/\" target=\"_blank\">https://keras.io/guides/transfer_learning/</a></p>\n<ul>\n<li>위 두 개의 tutorial 중에 영어로 된 keras guide는 전이학습(특징 추출 &amp; 미세 조정 - 강의 슬라이드에도 존재)에 대한 내용만 담고 있기 때문에 훨씬 더 깔끔합니다. </li>\n</ul>\n<ol>\n<li>강의 내 과제에서 했던 것과 똑같이 데이터 전처리 -&gt; 이미지 분석 … 실행</li>\n<li>위 keras guide 내 <strong>The typical transfer-learning workflow</strong> 이하 코드들을 참고해 특징 추출 &amp; 미세 조정 진행.</li>\n</ol>\n<p><strong>한글(참고용)</strong><br>\n<a href=\"https://www.tensorflow.org/tutorials/images/transfer_learning?hl=ko\" target=\"_blank\">https://www.tensorflow.org/tutorials/images/transfer_learning?hl=ko</a></p>\n<ul>\n<li>한글로 된 tensorflow tutorial는 특징 추출 &amp; 미세 조정 외에도 데이터 전처리를 포함하고 있기 때문에 참고하기에 좋지는 않습니다.</li>\n<li>다만 내용자체는 영어판이랑 거의 똑같으며 해당 페이지 내 \"특징 추출\" 이하 코드부터 참고하면 좋을 것 같습니다. <br>\n<br></li>\n</ul>\n<h1>Tip</h1>\n<hr>\n<h2>1. 저희에게 주어진 데이터는 이미지의 크기가 제각각입니다.</h2>\n<ul>\n<li><p>그렇기 때문에 이미지의 크기는 정사각형 크기의 이미지로 통합해주어야 합니다.</p></li>\n<li><p>여기에는 다양한 방법(이미지의 크기를 모두 불러와 평균 크기의 사이즈로 모두 바꾼다든지…)이 있겠지만, 저희가 배웠던 method <code>flow_from_directory</code> 의 <code>target_size</code> 인수를 이용하면 이미지의 크기를 모두 통일할 수 있습니다.</p></li>\n</ul>\n<pre><code>traind=igen.flow_from_directory(trainp, target_size = (150,150), #여기\n    batch_size = bs,class_mode = 'sparse' , subset='training')\n</code></pre>\n<p>저희 데이터의 이미지 크기는 대략 300~400 정도 되는 걸로 기억하기 때문에 위처럼 target_size를 (150, 150)로 통일해도 문제는 없습니다(저희 이미지가 30 x 30인데 150 x 150로 키우는 건 문제가 많겠죠).</p>\n<p>위에서 굳이 (150,150)를 예시로 든 이유는 위에 첨부한 keras guide의 예시(아래)가 pre-trained 모델인 Xception을 불러올 때 input_shape를 (150,150,3)으로 불러왔기 때문입니다.</p>\n<pre><code>base_model = keras.applications.Xception(\n    weights='imagenet',  # Load weights pre-trained on ImageNet.\n    input_shape=(150, 150, 3), # 여기\n    include_top=False)  # Do not include the ImageNet classifier at the top.\n</code></pre>\n<p>당연히 저희가 이미지 전처리할 때 통일할 target_size와 저희가 사용할 pre-trained model의 input_shape는 통일시켜주어야 합니다.</p>\n<p>다만 저희 이미지는 300~400인데 이미지 사이즈를 150으로 줄인다면 성능이 안 좋아질 수도 있기 때문에, 각 모델이 허용하는 최대 크기의 이미지로 통일하는 게 좋습니다(위의 예시에서 Xception을 불러올 때 input shape를 (150,150,3)으로 했으나, 원래 default는 (299,299,3)까지 지원합니다). </p>\n<h2>2. 사용할 pre-trained model 고르기</h2>\n<p>위의 예시에서는 pre-trained model로 Xception을 사용했습니다만, 더 좋은 모델이 있을 수 있겠죠? </p>\n<p><a href=\"https://keras.io/api/applications/\" target=\"_blank\">https://keras.io/api/applications/</a></p>\n<p>위의 링크를 참고해 분류 성능이 좋고, 가벼운 모델을 잘 골라서 pre-trained 모델로 사용하면 됩니다.</p>\n<ul>\n<li>지금 보니 Xception도 성능이 굉장히 좋고, 가볍네요.</li>\n</ul>\n<h2>3. Test data Generator에는 당연히 data augmentation을 적용하면 안 됩니다.</h2>\n<pre><code># DataGenerator를 새로 생성하되, 그냥 이미지의 scale만 조정해주어야 합니다.\ntest_gen=ImageDataGenerator(rescale=1/255)\n</code></pre>\n<ul>\n<li>원래 Valid data Generator에도 data augmentation을 적용하면 안 된다고는 하는데(test data랑 밀접해야 하므로),  여러모로 귀찮을 것 같아서 그냥 Validation data도 똑같은 Generator에서 불러왔습니다(찾아보면 valid data에 augmentation 적용하지 않는 방법도 있지 않을까 합니다). </li>\n</ul>\n<pre><code># (위에서 정의한 image generator)\ntraind=igen.flow_from_directory(trainp, target_size = (299,299),\n    batch_size = bs,class_mode = 'sparse' , subset='training')\n\n# 원래 validation data에는 Augmentation이 적용되면 안 되지만, 크게 상관은 없으리라 생각하고\n# Data augmentation을 적용한 Generator에서 validation data도 가져옵니다.\nvald=igen.flow_from_directory(trainp, target_size = (299,299),\n    batch_size = bs,class_mode = 'sparse' , subset='validation')\n</code></pre>\n<h2>4. 위에서 말했다시피 Test data를 불러올 때 <code>shuffle=False</code>를 사용해야 합니다 !</h2>\n<pre><code># test data 불러오기\ntestd=test_gen.flow_from_directory('/kaggle/input/animal-classification/',target_size = (299,299)\n                                  ,class_mode='sparse',\n                                  shuffle=False, batch_size=1) # shuffle=False 필수일 것.\n</code></pre>\n<ul>\n<li>Label을 제출할 때에는 이미지 폴더에 적재된 이미지를 순서대로 불러와야 온전한 평가가 가능하기 때문에 위에서 test data를 불러올 때에는 shuffle=False를 할당해야 합니다.</li>\n<li>저 인자를 사용하지 않았을 때에 점수가 어떻게 나오는 지는 확인하지 않았지만, 학습의 의미를 잃기 때문에 아마 랜덤하게 라벨을 예측할 것이고, 25%가량의 정확도(4개 class 중 하나)가 나올 것이라 생각합니다.</li>\n<li>(아닐 수도 있습니다 ㅎㅎ)</li>\n</ul>\n<hr>\n<ul>\n<li>참고로 저는 Fine-Tuning까지 하지 않고 그냥 Feature Extraction만 수행했습니다. 베이스 라인 모델(pre trained model)의 모든 레이어가 trainable하게 설정해준 다음 fine tuning까지 조심스레 해준다면 성능이 더 높아지지 않을까 싶습니다. </li>\n</ul>",
      "rawMarkdown": "이번 Competition에 쓰인 데이터의 특징은 적은 데이터(3000개), 적은 클래스(4)입니다. \n\n사실 이번 데이터에서 구분해야 하는 클래스는 4개밖에 안되기 때문에, 지금까지의 베이스라인 코드(CNN , Dropout,  Batch Normalization)만으로도 충분한 성능을 뽑아낼 수 있지 않을까? 라는 생각이 들긴 듭니다. \n\n그래서, 지금까지 과제에서 제출했던 베이스라인 코드와 과적합 해소 방안(Dropout, Batch Normalization)을 추가한 CNN 모델을 이용해 학습시켜보고 성능을 평가해보는 게 우선이라고 생각합니다.\n\n---\n\n**단, Test data를 불러올 때 `shuffle=False`를 사용해야 합니다 !**\n\n ```python\n# test data 불러오기\n\ntestd=test_gen.flow_from_directory('/kaggle/input/animal-classification/test',\n   target_size = (299,299),       # 이미지의 크기는 특정 size로 통일\n   class_mode='sparse',\n   shuffle=False,                        # shuffle=False 필수\n   batch_size=1)                         # 필수는 아닐 듯\n```\n\nsample submission csv에 저희 모델로 예측(`model_first.predict_generator(testd)`)한 라벨을 탑재할 때에는 데이터 폴더에서 불러오는 이미지 **순서 그대로** 넣어야 합니다. 그렇기 때문에 이미지 데이터를 불러올 때에 순서가 섞이지 않게 Shuffle을 꺼주어야 한다고 생각합니다.\n\n(Default 값으로 Shuffle=False로 들어갈 줄 알았는데 찾아보니 Shuffle=True가 Default라고 합니다.)\n\n---\n\n\n아무튼, 과제에 사용했던 기본적인 CNN 구조와 (Data Augmentation, Dropout, Batch Normalization, ...) 등 과적합 해소 기법들만으로도 저희 모델은 4개의 Class를 잘 구분할 수도 있습니다.\n그렇다면 굳이 복잡한 모델을 끌고와서 학습시키는 것은 시간 낭비겠지요.\n\n\n다만 데이터가 너무 적어서 성능이 잘 안 나올 수도 있습니다.  \n\n이럴 때,  성능을 더욱 올리기 위해 일반적으로 사용하는 대표적인 방법은 아래와 같습니다.\n\n1. 모델 구조 변경\n  - CNN을 층을 더 많이 쌓는다든지, 혹시나 Dropout -> conv2d -> BatchNorm layer 중에 하나를 빼먹었다면 추가를 해준다든지.. \n\n2. **데이터 증강(Data Augmentation)**\n  - 과제에 사용했던 CNN 모델을 사용하더라도, 적은 데이터를 보완하기 위해 Data Augmentation을 수행해주는 것이 좋습니다(강의 내 슬라이드 참고).\n\n3. **전이 학습(Transfer Learning)**\n  - 전이학습도 강의 내 슬라이드에서 간략히 다루었습니다. \n  - 과제에 사용했던 CNN 모델을 사용하지 않고 대용량 데이터에 학습시켜놨던 대규모 모델을 불러와 저희 task에 맞게 다시 학습하는 과정입니다.\n  - 모델 자체가 기본적인 CNN 모델과는 비교도 안 되게 크기 때문에 아무리 Transfer learning이라 해도 오래 걸릴 수 있습니다. \n  - 아래에서 조금 더 자세히 다루겠습니다.\n\n\n여기서는 모델 구조보다는 **데이터 증강**과 **전이학습**에 대해서 간략히 다루도록 하겠습니다.\n\n<br>\n# 1. 데이터 증강\n\n---\n\n\n데이터 증강은 슬라이드에 나와있었던 것처럼 \n\n```python\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\nigen=ImageDataGenerator(rescale=1/255, validation_split=0.2, \n                       width_shift_range=0.2, height_shift_range=0.2, \n                       zoom_range=0.2, \n                        horizontal_flip=True, vertical_flip=True,\n                        shear_range=0.2,brightness_range=(0.2,1.3))\n```\n\n이미지를 불러올 때 위와 같은 shift, zoom, flip, shear, brightness에 대한 인자를 넣어주면 됩니다.\n그러면, 자동적으로 매 epoch마다 새롭게 변한 이미지를 추출해 학습하기 때문에 더욱 많은 데이터로 학습하는 효과를 얻을 수 있습니다. \n<br>\n## 2. 전이 학습\n\n---\n\n이미지 분야든, 자연어 처리 분야든 대용량의 데이터에 미리 학습시켜 놓은 초대형 모델(pre-trained model)을 이용해 저희들이 원하는 task에 전이학습(transfer learning)을 적용시키는 것이 성능 보장을 위한 가장 확실한 방법입니다.\n\n본래 저희가 예측할 데이터에 대해\n(1) pre-trained 모델에 쓰인 데이터와 우리 데이터의 특징이 비슷한지\n(2) 우리 data의 size가 어떤지\n\n에 따라 학습 전략을 나누기는 해야 합니다..만은\n어차피 저희가 사용할 데이터는 동물이기 때문에 (1)은 신경쓸 필요가 없습니다.\n\n즉, 적은 데이터를 사용하는 저희 모델에만 조심스럽게 전이학습 시키면 됩니다.\n\n\n이에 대해서는 아래의 tutorial code를 참고해 거의 유사하게 따라하면 됩니다.\n\n**영어(추천)**\nhttps://keras.io/guides/transfer_learning/\n\n- 위 두 개의 tutorial 중에 영어로 된 keras guide는 전이학습(특징 추출 & 미세 조정 - 강의 슬라이드에도 존재)에 대한 내용만 담고 있기 때문에 훨씬 더 깔끔합니다. \n\n1. 강의 내 과제에서 했던 것과 똑같이 데이터 전처리 -> 이미지 분석 ... 실행\n2. 위 keras guide 내 **The typical transfer-learning workflow** 이하 코드들을 참고해 특징 추출 & 미세 조정 진행.\n\n**한글(참고용)**\nhttps://www.tensorflow.org/tutorials/images/transfer_learning?hl=ko\n\n\n\n- 한글로 된 tensorflow tutorial는 특징 추출 & 미세 조정 외에도 데이터 전처리를 포함하고 있기 때문에 참고하기에 좋지는 않습니다.\n- 다만 내용자체는 영어판이랑 거의 똑같으며 해당 페이지 내 \"특징 추출\" 이하 코드부터 참고하면 좋을 것 같습니다. \n<br>\n# Tip\n\n---\n\n## 1. 저희에게 주어진 데이터는 이미지의 크기가 제각각입니다. \n\n- 그렇기 때문에 이미지의 크기는 정사각형 크기의 이미지로 통합해주어야 합니다.\n\n- 여기에는 다양한 방법(이미지의 크기를 모두 불러와 평균 크기의 사이즈로 모두 바꾼다든지...)이 있겠지만, 저희가 배웠던 method `flow_from_directory` 의 `target_size` 인수를 이용하면 이미지의 크기를 모두 통일할 수 있습니다.\n\n```python\ntraind=igen.flow_from_directory(trainp, target_size = (150,150), #여기\n    batch_size = bs,class_mode = 'sparse' , subset='training')\n```\n\n저희 데이터의 이미지 크기는 대략 300~400 정도 되는 걸로 기억하기 때문에 위처럼 target_size를 (150, 150)로 통일해도 문제는 없습니다(저희 이미지가 30 x 30인데 150 x 150로 키우는 건 문제가 많겠죠).\n\n위에서 굳이 (150,150)를 예시로 든 이유는 위에 첨부한 keras guide의 예시(아래)가 pre-trained 모델인 Xception을 불러올 때 input_shape를 (150,150,3)으로 불러왔기 때문입니다.\n\n```python\nbase_model = keras.applications.Xception(\n    weights='imagenet',  # Load weights pre-trained on ImageNet.\n    input_shape=(150, 150, 3), # 여기\n    include_top=False)  # Do not include the ImageNet classifier at the top.\n```\n당연히 저희가 이미지 전처리할 때 통일할 target_size와 저희가 사용할 pre-trained model의 input_shape는 통일시켜주어야 합니다.\n\n다만 저희 이미지는 300~400인데 이미지 사이즈를 150으로 줄인다면 성능이 안 좋아질 수도 있기 때문에, 각 모델이 허용하는 최대 크기의 이미지로 통일하는 게 좋습니다(위의 예시에서 Xception을 불러올 때 input shape를 (150,150,3)으로 했으나, 원래 default는 (299,299,3)까지 지원합니다). \n\n\n## 2. 사용할 pre-trained model 고르기\n\n위의 예시에서는 pre-trained model로 Xception을 사용했습니다만, 더 좋은 모델이 있을 수 있겠죠? \n\nhttps://keras.io/api/applications/\n\n위의 링크를 참고해 분류 성능이 좋고, 가벼운 모델을 잘 골라서 pre-trained 모델로 사용하면 됩니다.\n\n- 지금 보니 Xception도 성능이 굉장히 좋고, 가볍네요.\n\n\n## 3. Test data Generator에는 당연히 data augmentation을 적용하면 안 됩니다. \n\n```python\n# DataGenerator를 새로 생성하되, 그냥 이미지의 scale만 조정해주어야 합니다.\ntest_gen=ImageDataGenerator(rescale=1/255)\n```\n\n- 원래 Valid data Generator에도 data augmentation을 적용하면 안 된다고는 하는데(test data랑 밀접해야 하므로),  여러모로 귀찮을 것 같아서 그냥 Validation data도 똑같은 Generator에서 불러왔습니다(찾아보면 valid data에 augmentation 적용하지 않는 방법도 있지 않을까 합니다). \n\n```python\n# (위에서 정의한 image generator)\ntraind=igen.flow_from_directory(trainp, target_size = (299,299),\n    batch_size = bs,class_mode = 'sparse' , subset='training')\n\n# 원래 validation data에는 Augmentation이 적용되면 안 되지만, 크게 상관은 없으리라 생각하고\n# Data augmentation을 적용한 Generator에서 validation data도 가져옵니다.\nvald=igen.flow_from_directory(trainp, target_size = (299,299),\n    batch_size = bs,class_mode = 'sparse' , subset='validation')\n```\n\n## 4. 위에서 말했다시피 Test data를 불러올 때 `shuffle=False`를 사용해야 합니다 ! \n```python\n# test data 불러오기\ntestd=test_gen.flow_from_directory('/kaggle/input/animal-classification/',target_size = (299,299)\n                                  ,class_mode='sparse',\n                                  shuffle=False, batch_size=1) # shuffle=False 필수일 것.\n```\n\n- Label을 제출할 때에는 이미지 폴더에 적재된 이미지를 순서대로 불러와야 온전한 평가가 가능하기 때문에 위에서 test data를 불러올 때에는 shuffle=False를 할당해야 합니다.\n- 저 인자를 사용하지 않았을 때에 점수가 어떻게 나오는 지는 확인하지 않았지만, 학습의 의미를 잃기 때문에 아마 랜덤하게 라벨을 예측할 것이고, 25%가량의 정확도(4개 class 중 하나)가 나올 것이라 생각합니다.\n- (아닐 수도 있습니다 ㅎㅎ)\n\n\n---\n\n- 참고로 저는 Fine-Tuning까지 하지 않고 그냥 Feature Extraction만 수행했습니다. 베이스 라인 모델(pre trained model)의 모든 레이어가 trainable하게 설정해준 다음 fine tuning까지 조심스레 해준다면 성능이 더 높아지지 않을까 싶습니다. \n\n\n\n\n",
      "votes": 6
    }
  ],
  "comments": [],
  "raw_markdown_by_id": {
    "1578689": "이번 Competition에 쓰인 데이터의 특징은 적은 데이터(3000개), 적은 클래스(4)입니다. \n\n사실 이번 데이터에서 구분해야 하는 클래스는 4개밖에 안되기 때문에, 지금까지의 베이스라인 코드(CNN , Dropout,  Batch Normalization)만으로도 충분한 성능을 뽑아낼 수 있지 않을까? 라는 생각이 들긴 듭니다. \n\n그래서, 지금까지 과제에서 제출했던 베이스라인 코드와 과적합 해소 방안(Dropout, Batch Normalization)을 추가한 CNN 모델을 이용해 학습시켜보고 성능을 평가해보는 게 우선이라고 생각합니다.\n\n---\n\n**단, Test data를 불러올 때 `shuffle=False`를 사용해야 합니다 !**\n\n ```python\n# test data 불러오기\n\ntestd=test_gen.flow_from_directory('/kaggle/input/animal-classification/test',\n   target_size = (299,299),       # 이미지의 크기는 특정 size로 통일\n   class_mode='sparse',\n   shuffle=False,                        # shuffle=False 필수\n   batch_size=1)                         # 필수는 아닐 듯\n```\n\nsample submission csv에 저희 모델로 예측(`model_first.predict_generator(testd)`)한 라벨을 탑재할 때에는 데이터 폴더에서 불러오는 이미지 **순서 그대로** 넣어야 합니다. 그렇기 때문에 이미지 데이터를 불러올 때에 순서가 섞이지 않게 Shuffle을 꺼주어야 한다고 생각합니다.\n\n(Default 값으로 Shuffle=False로 들어갈 줄 알았는데 찾아보니 Shuffle=True가 Default라고 합니다.)\n\n---\n\n\n아무튼, 과제에 사용했던 기본적인 CNN 구조와 (Data Augmentation, Dropout, Batch Normalization, ...) 등 과적합 해소 기법들만으로도 저희 모델은 4개의 Class를 잘 구분할 수도 있습니다.\n그렇다면 굳이 복잡한 모델을 끌고와서 학습시키는 것은 시간 낭비겠지요.\n\n\n다만 데이터가 너무 적어서 성능이 잘 안 나올 수도 있습니다.  \n\n이럴 때,  성능을 더욱 올리기 위해 일반적으로 사용하는 대표적인 방법은 아래와 같습니다.\n\n1. 모델 구조 변경\n  - CNN을 층을 더 많이 쌓는다든지, 혹시나 Dropout -> conv2d -> BatchNorm layer 중에 하나를 빼먹었다면 추가를 해준다든지.. \n\n2. **데이터 증강(Data Augmentation)**\n  - 과제에 사용했던 CNN 모델을 사용하더라도, 적은 데이터를 보완하기 위해 Data Augmentation을 수행해주는 것이 좋습니다(강의 내 슬라이드 참고).\n\n3. **전이 학습(Transfer Learning)**\n  - 전이학습도 강의 내 슬라이드에서 간략히 다루었습니다. \n  - 과제에 사용했던 CNN 모델을 사용하지 않고 대용량 데이터에 학습시켜놨던 대규모 모델을 불러와 저희 task에 맞게 다시 학습하는 과정입니다.\n  - 모델 자체가 기본적인 CNN 모델과는 비교도 안 되게 크기 때문에 아무리 Transfer learning이라 해도 오래 걸릴 수 있습니다. \n  - 아래에서 조금 더 자세히 다루겠습니다.\n\n\n여기서는 모델 구조보다는 **데이터 증강**과 **전이학습**에 대해서 간략히 다루도록 하겠습니다.\n\n<br>\n# 1. 데이터 증강\n\n---\n\n\n데이터 증강은 슬라이드에 나와있었던 것처럼 \n\n```python\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\nigen=ImageDataGenerator(rescale=1/255, validation_split=0.2, \n                       width_shift_range=0.2, height_shift_range=0.2, \n                       zoom_range=0.2, \n                        horizontal_flip=True, vertical_flip=True,\n                        shear_range=0.2,brightness_range=(0.2,1.3))\n```\n\n이미지를 불러올 때 위와 같은 shift, zoom, flip, shear, brightness에 대한 인자를 넣어주면 됩니다.\n그러면, 자동적으로 매 epoch마다 새롭게 변한 이미지를 추출해 학습하기 때문에 더욱 많은 데이터로 학습하는 효과를 얻을 수 있습니다. \n<br>\n## 2. 전이 학습\n\n---\n\n이미지 분야든, 자연어 처리 분야든 대용량의 데이터에 미리 학습시켜 놓은 초대형 모델(pre-trained model)을 이용해 저희들이 원하는 task에 전이학습(transfer learning)을 적용시키는 것이 성능 보장을 위한 가장 확실한 방법입니다.\n\n본래 저희가 예측할 데이터에 대해\n(1) pre-trained 모델에 쓰인 데이터와 우리 데이터의 특징이 비슷한지\n(2) 우리 data의 size가 어떤지\n\n에 따라 학습 전략을 나누기는 해야 합니다..만은\n어차피 저희가 사용할 데이터는 동물이기 때문에 (1)은 신경쓸 필요가 없습니다.\n\n즉, 적은 데이터를 사용하는 저희 모델에만 조심스럽게 전이학습 시키면 됩니다.\n\n\n이에 대해서는 아래의 tutorial code를 참고해 거의 유사하게 따라하면 됩니다.\n\n**영어(추천)**\nhttps://keras.io/guides/transfer_learning/\n\n- 위 두 개의 tutorial 중에 영어로 된 keras guide는 전이학습(특징 추출 & 미세 조정 - 강의 슬라이드에도 존재)에 대한 내용만 담고 있기 때문에 훨씬 더 깔끔합니다. \n\n1. 강의 내 과제에서 했던 것과 똑같이 데이터 전처리 -> 이미지 분석 ... 실행\n2. 위 keras guide 내 **The typical transfer-learning workflow** 이하 코드들을 참고해 특징 추출 & 미세 조정 진행.\n\n**한글(참고용)**\nhttps://www.tensorflow.org/tutorials/images/transfer_learning?hl=ko\n\n\n\n- 한글로 된 tensorflow tutorial는 특징 추출 & 미세 조정 외에도 데이터 전처리를 포함하고 있기 때문에 참고하기에 좋지는 않습니다.\n- 다만 내용자체는 영어판이랑 거의 똑같으며 해당 페이지 내 \"특징 추출\" 이하 코드부터 참고하면 좋을 것 같습니다. \n<br>\n# Tip\n\n---\n\n## 1. 저희에게 주어진 데이터는 이미지의 크기가 제각각입니다. \n\n- 그렇기 때문에 이미지의 크기는 정사각형 크기의 이미지로 통합해주어야 합니다.\n\n- 여기에는 다양한 방법(이미지의 크기를 모두 불러와 평균 크기의 사이즈로 모두 바꾼다든지...)이 있겠지만, 저희가 배웠던 method `flow_from_directory` 의 `target_size` 인수를 이용하면 이미지의 크기를 모두 통일할 수 있습니다.\n\n```python\ntraind=igen.flow_from_directory(trainp, target_size = (150,150), #여기\n    batch_size = bs,class_mode = 'sparse' , subset='training')\n```\n\n저희 데이터의 이미지 크기는 대략 300~400 정도 되는 걸로 기억하기 때문에 위처럼 target_size를 (150, 150)로 통일해도 문제는 없습니다(저희 이미지가 30 x 30인데 150 x 150로 키우는 건 문제가 많겠죠).\n\n위에서 굳이 (150,150)를 예시로 든 이유는 위에 첨부한 keras guide의 예시(아래)가 pre-trained 모델인 Xception을 불러올 때 input_shape를 (150,150,3)으로 불러왔기 때문입니다.\n\n```python\nbase_model = keras.applications.Xception(\n    weights='imagenet',  # Load weights pre-trained on ImageNet.\n    input_shape=(150, 150, 3), # 여기\n    include_top=False)  # Do not include the ImageNet classifier at the top.\n```\n당연히 저희가 이미지 전처리할 때 통일할 target_size와 저희가 사용할 pre-trained model의 input_shape는 통일시켜주어야 합니다.\n\n다만 저희 이미지는 300~400인데 이미지 사이즈를 150으로 줄인다면 성능이 안 좋아질 수도 있기 때문에, 각 모델이 허용하는 최대 크기의 이미지로 통일하는 게 좋습니다(위의 예시에서 Xception을 불러올 때 input shape를 (150,150,3)으로 했으나, 원래 default는 (299,299,3)까지 지원합니다). \n\n\n## 2. 사용할 pre-trained model 고르기\n\n위의 예시에서는 pre-trained model로 Xception을 사용했습니다만, 더 좋은 모델이 있을 수 있겠죠? \n\nhttps://keras.io/api/applications/\n\n위의 링크를 참고해 분류 성능이 좋고, 가벼운 모델을 잘 골라서 pre-trained 모델로 사용하면 됩니다.\n\n- 지금 보니 Xception도 성능이 굉장히 좋고, 가볍네요.\n\n\n## 3. Test data Generator에는 당연히 data augmentation을 적용하면 안 됩니다. \n\n```python\n# DataGenerator를 새로 생성하되, 그냥 이미지의 scale만 조정해주어야 합니다.\ntest_gen=ImageDataGenerator(rescale=1/255)\n```\n\n- 원래 Valid data Generator에도 data augmentation을 적용하면 안 된다고는 하는데(test data랑 밀접해야 하므로),  여러모로 귀찮을 것 같아서 그냥 Validation data도 똑같은 Generator에서 불러왔습니다(찾아보면 valid data에 augmentation 적용하지 않는 방법도 있지 않을까 합니다). \n\n```python\n# (위에서 정의한 image generator)\ntraind=igen.flow_from_directory(trainp, target_size = (299,299),\n    batch_size = bs,class_mode = 'sparse' , subset='training')\n\n# 원래 validation data에는 Augmentation이 적용되면 안 되지만, 크게 상관은 없으리라 생각하고\n# Data augmentation을 적용한 Generator에서 validation data도 가져옵니다.\nvald=igen.flow_from_directory(trainp, target_size = (299,299),\n    batch_size = bs,class_mode = 'sparse' , subset='validation')\n```\n\n## 4. 위에서 말했다시피 Test data를 불러올 때 `shuffle=False`를 사용해야 합니다 ! \n```python\n# test data 불러오기\ntestd=test_gen.flow_from_directory('/kaggle/input/animal-classification/',target_size = (299,299)\n                                  ,class_mode='sparse',\n                                  shuffle=False, batch_size=1) # shuffle=False 필수일 것.\n```\n\n- Label을 제출할 때에는 이미지 폴더에 적재된 이미지를 순서대로 불러와야 온전한 평가가 가능하기 때문에 위에서 test data를 불러올 때에는 shuffle=False를 할당해야 합니다.\n- 저 인자를 사용하지 않았을 때에 점수가 어떻게 나오는 지는 확인하지 않았지만, 학습의 의미를 잃기 때문에 아마 랜덤하게 라벨을 예측할 것이고, 25%가량의 정확도(4개 class 중 하나)가 나올 것이라 생각합니다.\n- (아닐 수도 있습니다 ㅎㅎ)\n\n\n---\n\n- 참고로 저는 Fine-Tuning까지 하지 않고 그냥 Feature Extraction만 수행했습니다. 베이스 라인 모델(pre trained model)의 모든 레이어가 trainable하게 설정해준 다음 fine tuning까지 조심스레 해준다면 성능이 더 높아지지 않을까 싶습니다. \n\n\n\n\n"
  }
}