일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 알고리즘
- NEXT
- lazy propagation
- 가끔은_말로
- 미래는_현재와_과거로
- 문자열
- c++
- 조합론
- dropout
- 너비 우선 탐색
- 크루스칼
- 2023
- tensorflow
- 자바스크립트
- DP
- BFS
- pytorch
- back propagation
- 다익스트라
- 이분 탐색
- dfs
- 분할 정복
- 플로이드 와샬
- 가끔은 말로
- object detection
- 백트래킹
- 우선 순위 큐
- Overfitting
- 회고록
- 세그먼트 트리
- Today
- Total
Doby's Lab
tensorflow의 ImageDataGenerator 본문
✅ Contents
- 1. Intro
- 2. Generator란
- 3. ImageDataGenerator
- 4. flow (flow_from_directory)
- 5. Code
- 6. How to Work (Question)
- 7. Better Training?
- 8. Outro
- 9. Reference
✅ 1. Intro
프로젝트를 하면서 Image Augmentation이라는 기술을 접했는데 대부분 ImageDataGenerator를 사용하여 Image Augmentation을 하는 코드를 많이 봤습니다.
이번 포스팅에서는 ImageDataGenerator에 대해 알아봅시다.
✅ 2. Generator란
Generator라는 개념에 대해서는 아래의 포스팅에서 정리하였으니 참고하시길 바랍니다.
https://draw-code-boy.tistory.com/511
https://draw-code-boy.tistory.com/512
✅ 3. ImageDataGenerator
ImageDataGenerator란 tf.keras.preprocessing.image에서 모듈로 가지고 있는 Generator 생성을 위한 Class입니다.
코드로 먼저 보겠습니다.
train_data_generator = ImageDataGenerator(rescale=1./255,
rotation_range=10,
shear_range =0.7,
width_shift_range=0.2,
height_shift_range=0.2,
validation_split=0.06
)
위 코드는 어떤 Generator를 만들 것인가에 대한 코드입니다.
Argument들을 통해 이미지에 어떤 변환들을 주어 이미지들을 발생시킬지 정할 수 있습니다.
자주 쓰이는 Argument들을 정리해 보겠습니다.
- rescale: 해당 값을 곱하여 scaling을 합니다. 대부분 Normalization을 위해 사용합니다. (default는 0이나 None으로 default일 때는 적용하지 않습니다.)
- width_shift_range: argument의 형태가 많지만 자주 사용하는 건 float 값으로 가로넓이의 비율만큼 가로로 밀어버린다는 뜻입니다.
- height_shift_range: width_shift_range와 마찬가지로 높이를 밀어버립니다.
- horizontal_flip: 이미지를 랜덤 하게 수평으로 뒤집습니다. (default = False)
- vertical_flip: 이미지를 랜덤하게 수직으로 뒤집습니다. (default = False)
- rotation_range: 랜덤하게 회전하는 것에 대한 각도의 범위입니다.
- fill_mode: 변환된 후에 경계 바깥 공간은 어떻게 채워 넣을지에 대한 Argument입니다. (default = 'nearest')
- constant: kkkkkkkk|abcd|kkkkkkkk (cval=k)
- 'nearest': aaaaaaaa|abcd|dddddddd
- 'reflect': abcddcba|abcd|dcbaabcd
- 'wrap': abcdabcd|abcd|abcdabcd
- cval: fill_mode가 constant인 경우, 어떤 값을 채워넣을지 결정하는 Argument입니다.
- brightness_range: 두 float 값의 리스트 혹은 튜플로 이루어져 있으며 밝기 정도를 조절할 값의 범위입니다.
- shear_range: 반시계 방향의 도 단위로 이미지의 층을 밀어버립니다. 그에 따른 Intensity(강도)입니다.
- zoom_range: float 값이나 [lower, upper]의 리스트로 확대 및 축소를 할 범위입니다. (1 - zoom_range, 1 + zoom_range)
- validation_split: validation_set으로 사용할 데이터의 비율입니다.
✅ 4. flow (flow_from_directory)
이렇게 Generator를 만들 수 있고, 이제 Generator Iterator를 만들어봅시다.
Iterator는 ImageDataGenerator에 있는 flow 메서드에 따라 다양한 종류의 Iterator를 만들 수 있습니다.
(flow: NumpyArrayIterator, flow_from_directory: DirectoryIterator, flow_from_dataframe: DataFrameIterator)
이번 포스팅에서는 flow_from_directory를 통해 DirectoryIterator인 Iterator를 만들어봅시다.
train_generator = train_data_generator.flow_from_directory(
'/training_set/training_set',
target_size = (224, 224),
batch_size = BATCH_SIZE,
class_mode = 'binary',
color_mode ='grayscale',
shuffle = True,
subset='training')
위 코드를 통해 Iterator를 생성하였습니다. flow마다 Argument가 비슷하기 때문에 Argument를 통해 설명해 보겠습니다.
- directory: 데이터셋이 존재하는 경로입니다.
- target_size: 데이터의 사이즈의 (weight, height)를 지정합니다.
- color_mode: 'grayscale', 'rgb', 'rgba'로 이미지의 채널을 convert 합니다.
- class_mode: Label 배열의 종류를 결정합니다.
- categorical: 2D 형태의 One-hot encoding이 된 Label입니다.
- binary: 1D 형태의 Binary Label입니다.
- sparse: 1D 형태의 정수형 Label입니다.
- input: 인풋이미지와 동일한 이미지입니다.
- None: 어떠한 Label도 반환되지 않습니다.
- Interpolation: target size로 resize 하면서 어떤 보간법을 쓸지 정합니다.
- batch_size: 배치를 구성하는 샘플의 개수로 한 번 next()를 쓸 때 batch를 반환합니다. (default = 32)
- subset: 'training'으로 쓸 지 'validation'으로 쓸 지 결정합니다.
- shuffle: 데이터를 섞을지 말지 정합니다. (한 번의 데이터셋 안에서 shuffle 됩니다. 즉, 데이터가 한 번에 중복되어 나오는 경우는 없습니다.)
✅ 5. Code
Generator Iterator를 학습시키는 방법은 아래의 코드와 같이 작성할 수 있습니다.
history = model.fit(train_generator, epochs=200, validation_data=val_generator,
steps_per_epoch = 7525//BATCH_SIZE+1, validation_steps = 480//BATCH_SIZE+1,
callbacks=[early_stopping_cb, learning_rate_reduction_cb])
Directory Iterator를 통해 Label까지 가져왔기 때문에 한 번에 Iterator를 넘겨 학습시킵니다.
추가적으로 Iterator를 통한 학습에서는 steps_per_epoch와 validation_steps라는 argument가 중요합니다.
이에 대해서는 아래 포스팅에서 정리해 두었으니 참고하시길 바랍니다.
https://draw-code-boy.tistory.com/513
✅ 6. How to Work (Question)
ImageDataGenerator를 사용하는 방법은 알게 되었지만 어떤 식으로 작동하는지는 와닿지 않았기 때문에 공부하던 중 떠오른 질문들에 대한 답을 통해 정리해 보겠습니다.
📄 6.1. Argument를 한 번에 모두 적용하는가?
처음에 ImageDataGenerator를 알게 되면서 생긴 질문이었습니다.
'Original Image에 argument를 적용하면 결국 변환된 데이터셋만을 학습하기 때문에 큰 효과가 없지 않은가'라는 생각이었지만
각 argument를 공부하면서 범위 내에서 랜덤 하게 적용하는 argument들이 많다는 것을 알게 되었습니다. 즉, Generator를 통해 생성할 때마다 범위 내에서 새롭게 변환된 이미지가 발생하는 것입니다.
(물론 rescale(Normalization) 같은 argument들은 계속 적용되어야 합니다.)
📄 6.2. ImageDataGenerator를 통해 만들어진 데이터셋의 크기는?
Generator를 공부했다면 데이터셋이라는 것을 만드는 것이 아닌 Generator를 실행할 때마다 batch를 리턴한다는 것을 알 수 있습니다.
굳이 데이터셋의 크기라 말하고 싶다면 batch는 필요한 대로 계속 발생시킬 수 있기 때문에 무한대라고 할 수 있습니다.
이에 따라 epoch에 맞게 조절하기 위해 step_per_epoch라는 argument의 역할이 중요하기도 합니다.
📄 6.3. batch size보다 작은 사이즈의 나머지 데이터들은 하나의 batch로 묶이는가 or 나머지 사이즈를 채우는가?
질문이 길고 어렵게 느껴질 수 있어 그림으로 설명하겠습니다.
Generator는 계속 batch를 발생시키는데 한 데이터셋에 대하여 batch size만 한 batch를 더 이상 발생시키지 못할 때 남은 사이즈만큼의 batch는 어떻게 발생되는지에 대한 질문입니다.
위 그림의 경우 Sample의 개수는 20개인데 batch size는 6으로 잡아서 batch 3개까지 발생시키다가 데이터셋에는 2개의 sample이 남은 상황이라 어떻게 발생시킬지가 의문이라 할 수 있습니다.
간단한 구현을 통해 이를 확인할 수 있었습니다.
이미지 개수가 20개인 데이터셋을 통해 구현했습니다.
batch_1 = next(training_set)
batch_2 = next(training_set)
batch_3 = next(training_set)
batch_4 = next(training_set)
next()를 통해 batch를 4개까지 만듭니다. 그럼 4번째 batch의 shape를 통해 나머지 데이터만 batch로 가져오는지 아닌지를 확인할 수 있습니다.
print(batch_4[0].shape)
# output
(2, 64, 64, 3)
shape를 통해 2개의 이미지만 batch로 가져오는 것을 확인했고, 나머지 사이즈를 채우기 위해 데이터셋에서 한 번 더 데이터를 가져오는 것은 아니라는 걸 알게 되었습니다.
이를 통해서 steps_per_epoch를 통해 데이터셋 전체 샘플의 개수에서 batch size를 나누어 한 에포크에서 변형된 하나의 데이터셋이 학습될 수 있도록 할 수 있다는 것을 알 수 있습니다.
✅ 7. Better Training?
기존의 프로젝트(Cat n Dog Classification Version 2)에서는 직접 Augmentation을 하면서 데이터셋에 (Original + Augmentation)이 모두 들어가게 되면서 모두 한 에포크에서 같은 데이터셋이 반복적으로 학습되게 만들었었습니다.
하지만, ImageDataGenerator는 계속 변형된 데이터셋들을 하나하나 한 에포크에 학습되도록 합니다. (사람마다 다르게 할 수도 있지만 지금까지 봐온 노트북에서는 그런 경향이 있는 거 같습니다.)
즉, 그림으로 표현하면 아래와 같은 차이가 있는 것입니다.
이러한 차이점에서 어떤 방법이 더 나은 학습 방법일까 라는 생각을 하게 되는데
ImageDataGenerator를 사용한 데이터를 version 2 모델에서 학습시켜 보았지만 모델 자체가 version 2의 데이터에 맞추어 제작되었기 때문에 기존 모델에서 좋은 성능을 띄진 않습니다.
그렇기 때문에 무엇이 더 나은 학습 방법론인지는 아직 잘 모르겠습니다만 더 탐구해보아야 할 부분이라 생각됩니다.
✅ 8. Outro
여기까지 ImageDataGenerator에 대한 공부를 마칩니다.
과정에서 파이썬에 Iterator와 Generator라는 신기한 객체를 알게 되어서 재밌었습니다.
keras의 Github 주석 부분을 보면 Generator를 추천하지는 않습니다. 없어질 예정인지는 모르겠습니다.
그래서 tensorflow에서는 tf.data.Dataset을 사용하여 preprocessing을 통해 증강하는 것을 추천하거나
preprocssing layer를 통해 증강하는 것을 추천하고 있습니다.
https://www.tensorflow.org/api_docs/python/tf/data/Dataset
https://www.tensorflow.org/tutorials/images/data_augmentation
✅ 9. Reference
https://keras.io/ko/preprocessing/image/
https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator
'Code about AI > tensorflow' 카테고리의 다른 글
ArgumentIndexError: tensorflow의 LSTM을 사용할 때 주의 깊게 보아야 할 Parameter, return_sequences (0) | 2023.08.24 |
---|---|
tf.data.Dataset & tf.data.Dataset의 유용한 Methods (0) | 2023.08.17 |
steps_per_epoch, validation_steps (tensorflow model.fit의 Argument) (0) | 2023.01.10 |
Tensorflow의 Callback(EarlyStopping, ReduceLROnPlateau) (0) | 2023.01.03 |
Dataset Shuffle을 해야 하는 이유 (0) | 2022.12.25 |