Python/DeepLearning

딥러닝 - ImageDataGenerator

하니__ 2024. 4. 18. 16:51
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Sequential
from keras.layers import Conv2D,MaxPooling2D
from keras.layers import Flatten,Dense

 

ImageDataGenerator는 이미지 데이터를 전처리하거나 증식할 때 사용하는 도구로서

회전, 이동, 확대, 축소, 뒤집기 등 다양한 변형을 사용하여 

훈련 데이터의 다양성을 높여 모델의 일반화 성능을 향상시킬 수 있다

또한 픽셀 값의 스케일링, 정규화, 이미지 크기 조정도 가능하다

 

flow_from_directory(  )와 같은 메소드를 사용하여 디렉토리에서 이미지 데이터를 읽을 수 있다

이는 메모리 효율적인 데이터 로딩을 가능하게 한다

 

 

def build_model() :
  model = Sequential()
  model.add(Conv2D( 32, (3, 3), activation = 'relu',input_shape = ( 150, 150, 3 ) ) )
  model.add(MaxPooling2D(2, 2) ) #(2행2열),(2칸씩 점프)
  model.add(Conv2D( 64, (3, 3), activation = 'relu' ) )
  model.add(MaxPooling2D(2, 2) ) 
  model.add(Conv2D( 128, (3, 3), activation = 'relu' ) )
  model.add(MaxPooling2D(2, 2) ) 
  model.add(Conv2D( 128, (3, 3), activation = 'relu' ) )
  model.add(MaxPooling2D(2, 2) ) 

  model.add(Flatten())
  model.add(Dense( 512,activation = 'relu' ) )
  model.add(Dense( 1, activation = 'sigmoid' ) )
  model.compile(loss = 'binary_crossentropy', optimizer = 'rmsprop', metrics=['accuracy'] )
  return model
model = build_model()

 

 

 

ImageDataGenerator 라이브러리 이용
파일로 존재하는 데이터를 메모리로 준비

 

 

 

ImageDataGenerator( rescale = 1 / 255  )

 

파일을 Numpy로 바꿔서 피쳐스케일링(정규화(MinMax)) 후 메모리로 만드는 코드

 

 

 

 

아래는 이미지 증강까지 해서 메모리에 데이터 생성하는 코드다

train_datagen = ImageDataGenerator( rescale = 1 / 255, 
                   rotation_range = 40,
                   width_shift_range = 0.2,
                   height_shift_range = 0.2,
                   shear_range = 0.2,
                   zoom_range = 0.2,
                   horizontal_flip = True,
                   fill_mode = 'nearest')

 

 

위에서 언급했던

 

rotation_range = 40,         회전
width_shift_range = 0.2,   수평이동
height_shift_range = 0.2, 수직이동
zoom_range = 0.2,           확대/축소 = 숫자를 하나만 쓰게되면 ±퍼센트로 확대과 축소가 되며

                                         ( a, b )로 적게 되면 a가 축소 b가 확대로 적용된다
horizontal_flip = True,      좌우반전 /  vertical_flip = false 상하반전

fill_mode = 'nearest'        이미지를 변형할 때 경계 밖으로 나가는 픽셀들을 가장 가까운 경계 픽셀의 값으로 채운다

                                        이미지 변형으로 인한 왜곡을 최소화할 수 있다

                                        보편적으로 쓰이는 nearest는 가장 가까운 경계 픽셀의 값을 사용하여 경계 밖을 채우며 

                                        경계가 부드럽게 연결되며, 이미지 변형으로 인한 왜곡을 최소화할 수 있기에

                                        다른 모드보다 많이 쓰인다

shear_range = 0.2,          전단 변형 = 대각선 방향으로 늘어나거나 압축되는 효과 (아래 그림 참고)

 

 

 

 

 

 

 

train_generator = train_datagen.flow_from_directory(train_dir,
                                  target_size = (150, 150),
                                  class_mode = 'binary')

 

위에서 적었듯이

flow_from_directory( )를 이용하여 이미지파일 = 데이터를 읽을 수 있다

이때 train_dir는 X_train , y_train를 다 가지고 있는데 뒤에 후술하겠다

 

target_size는 위에서 만든 모델의 input_shape과 일치 해야 한다(행과 열만)

이미지 크기가 서로 다르다면 모델 훈련에 영향을 주기 때문에

로드된 모든 이미지가 150x150 픽셀로 크기 조정될 것을 의미한다

 

class_mode는 레이블(클래스) 데이터의 형식을 지정하는 옵션 

'binary'는 이진 분류 문제(binary classification)에 사용

즉, 해당 문제가 0과 1의 이진 분류 문제라고 지정해주는것

 

 

2000개의 이미지와 2개의 클래스를 찾은것을 확인 할 수 있다

 

 

 

train_generator는 X_train , y_train을 다 가지고 있다

 

훈련용 데이터인 train폴더

그러니까 X_train이 되는 데이터들이 

cats 와dogs 안에 존재하기에

y_train이 cats와 dogs로 자연스럽게 들어가게된다

 

val_datagen = ImageDataGenerator( rescale = 1 / 255 )
val_generator = val_datagen.flow_from_directory(val_dir,
                                target_size = ( 150, 150 ),
                                class_mode = 'binary')

validation 데이터들도 똑같이 준비 해준다

 

 

early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience = 5)
epoch_history = model.fit(train_generator,
                          epochs = 20,
                          validation_data = val_generator,
                          callbacks = [ early_stop ] )

 

 

 

해당 모델은

 

딥러닝의 결과를 얻기까지 상당한 시간이 소요되며

아무리 잘 나와도 정답률이 70~80%정도라서

 

그렇게 좋은 모델이라고 할 수 없겠지만...

 

이런 과정도 있다는것을 알아두자