티스토리 뷰

반응형

이번 글은 다양한 이미지를 폴더별로 저장되었을때 사용할 수 있는 기본적인  딥러닝 예측모델을 설명한다.

예를 들어 다음과 같이 감자 잎 마름병과 관련된 이미지를 폴더 3개로 클래스가 구분되었을 때 사용할 수 있는 아주 기초적인 딥러닝 모델을 설명한다. 

 

감자 잎 마름병 상태관련 이미지 폴더

 

1. 기본 딥러닝 모델에 필요한 패키지를 불러온다.

import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import cv2

import tensorflow as tf
from tensorflow.keras import layers, models

2. 폴더 경로를 지정하고 기본폴더내 있는 서브 폴더를 확인한다.

 

base_dir = "data/potato_disease/"

os.listdir(base_dir)

출력결과 :

['Potato___Early_blight', 'Potato___healthy', 'Potato___Late_blight']

 

3. 딥러닝 모델에 자주 사용하는 기본 변수인 이미지 크기, 배치크기, 이미지 채널 수, 모델학습 횟수를 설정한다.

IMG_SIZE = 256
BATCH_SIZE = 32
CHNNELS =3
EPOCHS = 100

4.  자료전처리

 

dataset = tf.keras.preprocessing.image_dataset_from_directory(
    base_dir,
    shuffle=True,
    image_size = (IMG_SIZE, IMG_SIZE),
    batch_size = BATCH_SIZE
)

출력결과 :

Found 2152 files belonging to 3 classes.

5. 다음 구문으로 자료 확인하면 결과적으로 채널이 3개인 256x256  크기의 이미지가 32개로 구성된다. 레이블은 32개로 구성된다.

for img_batch, label_batch in dataset.take(1):
    print(img_batch.shape)
    print(label_batch.numpy())

출력결과 : 

(32, 256, 256, 3)
[2 0 0 1 0 0 0 1 1 0 1 1 0 1 0 1 0 1 0 1 1 0 1 1 1 0 1 0 1 0 1 1]

6. 레이블 클래스 확인

 

class_names = dataset.class_names
print(class_names)

출력결과 :

['Potato___Early_blight', 'Potato___Late_blight', 'Potato___healthy']

7. 학습데이터 이미지 시각화하기

plt.figure(figsize=(10,10))

for img_batch, label_batch in dataset.take(1):
    for i in range(12):
        ax = plt.subplot(4, 3, i+1)
        img_arr = img_batch[i].numpy()
        plt.imshow(img_arr.astype("uint8"))
        plt.axis("off")
        plt.title(class_names[label_batch[i].numpy()])
  

출력결과

 

감자 잎 마름병 3가지 상태 이미지

8. 학습데이터 , 검증데이터, 평가 데이터 분리하는 함수 생성

def get_dataset_partitions(ds, train_split=0.8, test_split=0.1, val_split=0.1, shuffle = True, shuffle_size = 10000):
    
    dataset_size = len(ds)   
    
    if shuffle:
        ds = ds.shuffle(shuffle_size, seed=12)
    
    train_size = int(dataset_size * train_split)
    val_size = int(dataset_size * test_split)    
    train_ds = ds.take(train_size)
    test_ds = ds.skip(train_size)    
    val_ds = test_ds.take(val_size)   
    test_ds = test_ds.skip(val_size)
   
    
    return train_ds, val_ds, test_ds

9. 학습데이터 분리하고 각각 크기 확인하기

 

train_ds, val_ds, test_ds = get_dataset_partitions(dataset)
len(train_ds), len(val_ds), len(test_ds)

출력결과 : 54, 6, 8

 

10. 분리된 학습데이터를 모델에 입력시 수행속도 개선하기 위한 구문인데 없어도 그만임.

 

train_ds =train_ds.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
val_ds =val_ds.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
test_ds =test_ds.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)

11. 학습데이트 크기, 스케일, 증식하기

 

resize_and_rescale = tf.keras.Sequential([
    
    layers.experimental.preprocessing.Resizing(IMG_SIZE, IMG_SIZE),
    layers.experimental.preprocessing.Rescaling(1.0/255),
])
data_augmentation = tf.keras.Sequential([
    layers.experimental.preprocessing.RandomFlip("horizontal_and_vertical"),
    layers.experimental.preprocessing.RandomRotation(0.2),
])

12. 모델 정의

input_shape = (BATCH_SIZE, IMG_SIZE, IMG_SIZE, CHNNELS)
n_class = len(class_names)
print(n_class)


model = models.Sequential([
    
    resize_and_rescale,
    data_augmentation,
    layers.Conv2D(32, (3,3),  activation='relu', input_shape=input_shape),
    layers.MaxPooling2D((2,2)),
    layers.Conv2D(64, (3,3),  activation='relu'),
    layers.MaxPooling2D((2,2)),
    layers.Conv2D(64, (3,3),  activation='relu'),
    layers.MaxPooling2D((2,2)),
    layers.Conv2D(64, (3,3),  activation='relu'),
    layers.MaxPooling2D((2,2)),
    layers.Conv2D(64, (3,3),  activation='relu'),
    layers.MaxPooling2D((2,2)),
    layers.Conv2D(64, (3,3), activation='relu'),
    layers.MaxPooling2D((2,2)),
    
    
    layers.Flatten(),
    layers.Dense(64, activation="relu"),
    layers.Dense(n_class, activation="softmax"),
    
    
])

model.build(input_shape)

13. 모델 구조 보기

 

model.summary()

14.  모델 개발

model.compile(optimizer="adam",  loss="SparseCategoricalCrossentropy", metrics=['accuracy'])

15. 모델 학습

history = model.fit(
    train_ds, 
    epochs=EPOCHES, 
    batch_size=BATCH_SIZE, 
    verbose=1,
    validation_data=val_ds
)

16. 학습결과 확인

 

history.history.keys()

출력결과

dict_keys(['loss', 'accuracy', 'val_loss', 'val_accuracy'])
loss = history.history["loss"]
val_loss = history.history["val_loss"]
accuracy = history.history["accuracy"]
val_accuracy = history.history["val_accuracy"]

plt.figure(figsize=(15,5))

plt.subplot(121)
plt.plot(loss, label ="train_loss")
plt.plot(val_loss, label = "validation_loss")
plt.legend()

plt.subplot(122)
plt.plot(accuracy, label ="train_accuracy")
plt.plot(val_accuracy, label = "validation_accuracy")
plt.legend()

plt.show()

 

17. 모델 예측 함수 생성

 

def predict(model, img):
    
    img_array = tf.keras.preprocessing.image.img_to_array(img)
    img_array = tf.expand_dims(img_array, 0)
    
    predictions = model.predict(img_array, verbose=0)
    
    predicted_calss = class_names[np.argmax(predictions[0])]
    confidence = round(100* (np.max(predictions[0])), 2)
    
    return predicted_calss, confidence     

18. 예측결과 시각화

plt.figure(figsize=(15,15))

for images, labels in test_ds.take(1):
    for i in range(9):
        ax = plt.subplot(3,3, i+1)
        plt.imshow(images[i].numpy().astype("uint8"))        
        predicted_class, confidence = predict(model, images[i].numpy())        
        plt.title(f"Actual: {true}\n Predicted: {pred} \n confidence: {confidence}")       
        
        plt.axis("off")

모델예측결과 시각화

19. 모델 저장하기

os.makedirs("model", exist_ok=True)
model_version =max([int(i) for i in os.listdir("model")] + [0]) + 1 # 폴더이름이 숫자로 증가해서 저장
model.save(f"model/{model_version}")

 

반응형
댓글