본문 바로가기

카테고리 없음

[I2S] renet을 이용한 transferlearning

랩요정들은 인코더에서 사용한 pre-trained모델의 전체 레이어에서 앞단의 5개 레이어를 제외한 네트워크 파라미터를 업데이트 하였다.

"Fine-tuning은 모델의 전체 레이어에서 앞단의 5개의 레이어를 제외한 네트워크의 파라미터를 업데이트하여 이루어졌습니다."

 

Fine-tuning 이란?

- 기존에 학습되어져 있는 모델을 기반으로 아키텍쳐를 새로운 목적(나의 이미지 데이터에 맞게)변형하고 이미 학습된 모델 Weights로 부터 학습을 업데이트하는 방법을 말한다. 

출처: https://eehoeskrap.tistory.com/186 [Enough is not enough]

# EFNS = [efn.EfficientNetB0, efn.EfficientNetB1, efn.EfficientNetB2, efn.EfficientNetB3, 
#         efn.EfficientNetB4, efn.EfficientNetB5, efn.EfficientNetB6]


class CNN_Encoder(tf.keras.Model): # tf.keras.Model을 상속받음.
  # you should define your layers in __init__ 
  def __init__(self, embedding_dim):
      super(CNN_Encoder, self).__init__() # super : 자식 클래스에서 부모클래스의 내용을 사용하고 싶을 경우 사용.
      # self.base = EFNS[ef](input_shape=(224,224,3),weights='imagenet',include_top=False) # --> (None,7,7,1280)
      self.base = tf.keras.applications.ResNet152(include_top=False, weights='imagenet',input_shape=(224,224,3))
      for i, layer in enumerate(self.base.layers): 
        if i<5 : 
          layer.trainable = False
          print(i,"번째 label trainable : " ,layer.trainable)
        else : 
          print(i,"번째 label trainable : " ,layer.trainable)
      self.dropout = tf.keras.layers.Dropout(0.5)
      self.fc = tf.keras.layers.Dense(embedding_dim, dtype='float32')

  #you should implement the model's forward pass in call.
  def call(self, x):
      x = self.base(x)
      x = self.dropout(x)
      x = tf.reshape(x, [tf.shape(x)[0],tf.shape(x)[1]*tf.shape(x)[2],feature_shape]) # (BATCH_SIZE, 49,1280)
      x = self.fc(x)
      x = tf.nn.relu(x)

      return x

0~4번째layer는  trainable을 False로 두었다

5~514번째 layer는 True로 두었다.

batchsize를 24로 줄이고 (*8)로 하니 메모리 문제는 해결이 되었는데 

듀토리얼.-->

다음과 같이 loss가 nan이 나왔다 왜 그런것일까?

이유가 뭘까?

원인파악

1. 일단. 랩요정들 코드에서정의한 fine_tune함수를 분석해보자. 

    def fine_tune(self, fine_tune=True):
        for p in self.resnet.parameters():
            p.requires_grad = False
        # If fine-tuning, only fine-tune convolutional blocks 2 through 4
        for c in list(self.resnet.children())[5:]: #5층 이후부터 학습이 가능하게 했다.
            for p in c.parameters():
                p.requires_grad = fine_tune # 자동 미분을 가능하게 한다. 이게 무슨 말이지?

5충부터 부터 자동 미분을 가능하게 했는데 실제로도 5~514번째 layer를 학습가능하게 한 것인지 확인 해 볼 필요가 있다.

pytorch에서는Resnet.parameters의 개수가464까지밖에 안나온다. 

뭐가 다른 것인가.

 

label trainable

 

미세조정(fine_tuning)이란?

모델을 재사용하는 데 널리 사용되는 하나의 기법은 특성 추출을 보완하는 미세 조정(fine-tuning) 입니다. 미세 조정은 특성 추출에 사용했던 동결 모델의 상위 층 몇 개를 동결에서 해제하고 모델에 새로 추가한 층(여기서는 완전 연결 분류기)과 함께 훈련하는 것입니다. 재사용 모델의 표현을 일부 조정하기에 미세 조정이라고 부릅니다. 네트워크를 미세 조정하는 단계는 다음과 같습니다.

  1. 사전에 훈련된 기반 네트워크 위에 새로운 네트워크를 추가
  2. 기반 네트워크 동결
  3. 새로 추가한 네트워크 훈련
  4. 기반 네트워크에서 일부 층 동결 해제
  5. 동결 해제 층과 새로 추가한 층을 함께 훈련

완전 연결 분류기의 값이 지나치게 조정하는 것을 방지하기 위해 새로 추가한 네트워크를 먼저 훈련합니다. 즉 위에서 이미 3단계까지는 한 것입니다. 여기서는 구조가 너무 길어 생략하지만 본 사전 훈련된 네트워크의 구조는 5 블록으로 이루어져있고, 각 단계는 합성곱 층 3개와 풀링 층 1개로 이루어져있습니다. 미세 조정은 block_5에서만 진행합니다. 더 많은 층을 미세 조정하지 않는 이유는 다음과 같습니다.

  • 합성곱 기반 층에 있는 하위 층들은 좀 더 일반적이고 재사용 가능한 특성들을 인코딩
  • 반면 상위 층은 좀 더 특화된 특성을 인코딩 -> 새로운 문제에는 구체적 특성이 필요 -> 상위층만
  • 훈련해야 할 파라미터가 많으면 과대적합의 위험이 커짐. 작은 데이터 셋에 1500만개의 파라미터는 위험.

이제 미세조정은 다음과 같이 하드코딩합니다.

https://subinium.github.io/Keras-5-2/

 

블로그의 예제에서는 vgg16을 썼는데 

Resnet152의 경우는 어떻게 바뀌는지 확인해보자. 

 

resnet152는 몇개의 블록으로 이루어져 있는가? : 5개의 블록으로 이루어져 있다.

각 단계는 합성곱층 몇개와 풀링층 몇개로 이루어져 있는가? : 아래 표와 같다. 

https://towardsdatascience.com/review-resnet-winner-of-ilsvrc-2015-image-classification-localization-detection-e39402bfa5d8

https://m.blog.naver.com/PostView.nhn?blogId=laonple&logNo=220764986252&proxyReferer=https:%2F%2Fwww.google.co.kr%2F

block5에서만 미세조정을 진행한다!

랩요정들은 어떻게 미세조정을 진행했는가?

block 3,4,5 전부 미세조정을 진행한것 같다.

only fine-tune convolutional blocks 2 through 4 ??

"Fine-tuning은 모델의 전체 레이어에서 앞단의 5개의 레이어를 제외한 네트워크의 파라미터를 업데이트하여 이루어졌습니다." 라고 했다.