[AIFFEL] 22.Mar.23, GD_Data_Augmentation_3

Deok Jong Moon·2022년 3월 23일
0
post-thumbnail
post-custom-banner

오늘의 학습 리스트

  • 만약 custom 함수 안에 또 다른 custom 함수를 쓰는데 둘 다 같은 argument 이름을 갖는다 쳐도, 그게 제일 상위 함수에서 파라미터 값을 넣어줬을 때 안쪽 함수에 연결되어 있지 않으면 안쪽 함수의 파라미터로서 역할을 하지 않는다.

  • Order of .shuffle(), .repeat(), .batch() matters......

    • 아이펠 노드에서 전처리를 위해 써놓은 함수이다.

    • def normalize_and_resize_img(image, label):
        # Normalizes images: `uint8` -> `float32`
        image = tf.image.resize(image, [224, 224])
        return tf.cast(image, tf.float32) / 255., label
      
       def augment(image, label):
        image = tf.image.random_flip_left_right(image)
        image = tf.image.random_brightness(image, max_delta=0.2)
        image = tf.clip_by_value(image, 0, 1)
        return image, label
      
       def apply_normalize_on_dataset(ds, is_test=False, batch_size=16, with_aug=False, with_cutmix=False):
        ds = ds.map(
            normalize_and_resize_img, 
            num_parallel_calls=2
        )
        if not is_test and with_aug:
            ds = ds.map(
                augment
            )
        ds = ds.batch(batch_size)
        if not is_test and with_cutmix:
            ds = ds.map(
                cutmix,
                num_parallel_calls=2
            )
        else:
            ds = ds.map(
                onehot,
                num_parallel_calls=2
            )
        if not is_test:
            ds = ds.repeat()
            ds = ds.shuffle(200)
        ds = ds.prefetch(tf.data.experimental.AUTOTUNE)
        return ds
      
       print('=3')
       
    • 여기서 핵심은 cutmix, mixup이란 함수를 쓰려면 batch화가 먼저 되어야 한다는 건데

    • 일단 나는 아래와 같이 바꿔봤다.

    • def preprocess_on_dataset(ds, is_test=False, batch_size=16, with_cutmix=False, with_mixup=False):
      
        # 전체 다 실행하는 normalize_and_resize(+라벨 one-hot)
        ds = ds.map(normalize_and_resize_img, num_parallel_calls=tf.data.AUTOTUNE)
        
        if is_test:
            ds = ds.prefetch(tf.data.AUTOTUNE)
            return ds
        
        else:
            ds = ds.map(augment, num_parallel_calls=tf.data.AUTOTUNE) # train일 경우 기본 augmentation은 다 적용
            ds = ds.batch(batch_size) # batch화 해야지 cutmix 및 mixup을 할 수 있음
            if with_cutmix:
                ds = ds.map(cutmix, num_parallel_calls=tf.data.AUTOTUNE)
            elif with_mixup:
                ds = ds.map(mixup, num_parallel_calls=tf.data.AUTOTUNE)
            ds = ds.repeat().shuffle(1020).prefetch(tf.data.AUTOTUNE)
            return ds
    • 그런데 이렇게 하니까 어떤 건 cutmix, mixup이 아니지만 is_test=False이 아닌 전처리가 처리된 데이터셋은 shape이 (None, 224, 224, 3)과 같이 떴다((64, 224, 224, 3) 이런 거 기대했는데)

    • 왜 그럴까 찾아보니 batch, repeat, shuffle의 순서 때문인 것 같다...

    • 답변 링크

    • 아 사실 위에는 repeat, shuffle 들의 순서에 관련한 것이지만, 내 문제에 대한 해답은 알 수 없었다.

      • 참고로 저렇게 cutmix, mixup 처리된 것들이 ((64, 224, 224, 3)) 같은 shape을 나타내주는 게 왜인지 모르겠지만 정상인 것 같다.
      • 어쩌면 cutmix, mixup 함수를 구현할 때 그렇게 배치 사이즈별로 딱 그룹(?)화해서 넣어준 것 때문인 것 같다.
  • tf.data.experimental.cardinality(ds_train_norm)

    • 만약 무언가 배치화 했다면, 위의 함수를 써서 나오는 숫자는 배치의 수이다.
    • 첫번째 배치 내의 수 아님!!!!!!!!!
    • 따라서 2,000개의 데이터가 있었는데 10씩 배치화했다면, 위에서 나오는 수는 200이 됨
  • fit()에 쓰는 steps_per_epoch도 용도가 있었다.

    • 데이터셋에 repeat()을 걸어서 무한대로 가주니까 steps_per_epoch를 명시해줘야 한단다.(아니면 어디가 한 에포크의 기준선인지 모르단다.)

요즘 Tensorflow를 많이 써가면서 이것저것 그 안에 있는 것들의 용도와 원리들을 깨달아가고 있다. 참 감사한 순간이다.

profile
'어떻게든 자야겠어'라는 저 아이를 닮고 싶습니다
post-custom-banner

0개의 댓글