본문 바로가기
데이터 분석 및 시각화

[DL] CNN,RNN을 활용한 정확도, 예측도 확인하기

by 바다의 공간 2024. 11. 22.

텐서플로우의 예제인 꽃 이미지를 분류하려고 합니다.

## cnn2.py
# CNN 꽃 이미지 분류

def p(str):
    print(str, '\n')

#라이브러리 로딩
import matplotlib.pyplot as plt
import numpy as np
import PIL #이미지 처리하는 라이브러리
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential


# 데이터 로딩 : 3670장의 꽃 사진데이터 가져오기
# 3670장의 꽃 사진은 daisy, dandelion, roses, sunflowers, tulips 로 5개의 클래스로 구성되어있음
import pathlib
dataset_url ='https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz'
#flower_photos폴더에 압출파일 해제
data_dir = tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)
#경로설정
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*.jpg')))
p(image_count)

#장미이미지 호출하기
roses=list(data_dir.glob('roses/*'))
image = PIL.Image.open(str(roses[1]))
image.show()

#튤립이미지 호출하기
tulips = list(data_dir.glob('tulips/*'))
image2 = PIL.Image.open(str(tulips[0]))
image2.show()

 

장미와 튤립이미지를 가져옵니다.


데이터셋 만들기

#데이터셋 만들기
#1.훈련셋만들기
train_ds= tf.keras.utils.image_dataset_from_directory(
    data_dir, #데이터 디렉토리
    validation_split=0.2, #검증셋 20%
    subset='training', #서브셋
    seed=123, #랜덤시드값
    image_size=(180, 180), #이미지 크기
    batch_size=32 #배치크기
)

#2. 검증셋만들기
val_ds = tf.keras.utils.image_dataset_from_directory(
    data_dir, #데이터 디렉토리
    validation_split=0.2, #검증셋 20%
    subset='validation', #서브셋
    seed=123, #랜덤시드값
    image_size=(180, 180), #이미지 크기
    batch_size=32 #배치크기
)

 


#클래스명
class_names = train_ds.class_names
p(class_names)

#시각화
import matplotlib.pyplot as plt

plt.figure(figsize=(10, 10))  # (가로 크기, 세로 크기)
for images, labels in train_ds.take(1):
    for i in range(9):
        ax = plt.subplot(3,3,i+1)
        plt.imshow(images[i].numpy().astype('uint8'))
        plt.title(class_names[labels[i]])
        plt.axis('off')
plt.show()

 

#데이터 정규화
normalization_layer = layers.Rescaling(1./255) # 0~1범위로 적용

#훈련데이터 각각의 정규화를 실행
normalization_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))

#모델생성
model = Sequential([
    layers.Rescaling(1./255, input_shape=(180, 180, 3)),
    layers.Conv2D(16, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Conv2D(32, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Conv2D(64, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dense(5)
])

model.summary()

 


모델컴파일이란?

기계어로 변환하는 작업입니다.

#모델생성
model = Sequential([
    layers.Rescaling(1./255, input_shape=(180, 180, 3)),
    layers.Conv2D(16, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Conv2D(32, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Conv2D(64, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dense(5)
])

model.summary()


#모델 컴파일
model.compile(
    optimizer='adam',
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=['accuracy']
)

# 모델 훈련시키기
history = model.fit(
    train_ds,
    validation_data = val_ds,
    epochs = 10,
)
Epoch 1/10
92/92 ━━━━━━━━━━━━━━━━━━━━ 12s 122ms/step
 - accuracy: 0.3439 - loss: 1.5755 - val_accuracy: 0.5545 - val_loss: 1.0971

Epoch 2/10
92/92 ━━━━━━━━━━━━━━━━━━━━ 11s 116ms/step 
- accuracy: 0.6028 - loss: 1.0273 - val_accuracy: 0.6253 - val_loss: 0.9540

Epoch 3/10
92/92 ━━━━━━━━━━━━━━━━━━━━ 11s 114ms/step 
- accuracy: 0.6711 - loss: 0.8513 - val_accuracy: 0.5995 - val_loss: 0.9700

Epoch 4/10
92/92 ━━━━━━━━━━━━━━━━━━━━ 11s 116ms/step 
- accuracy: 0.7416 - loss: 0.6901 - val_accuracy: 0.6199 - val_loss: 0.9595

Epoch 5/10
92/92 ━━━━━━━━━━━━━━━━━━━━ 10s 112ms/step 
- accuracy: 0.8209 - loss: 0.4745 - val_accuracy: 0.6035 - val_loss: 1.1636

Epoch 6/10
92/92 ━━━━━━━━━━━━━━━━━━━━ 10s 110ms/step
- accuracy: 0.9024 - loss: 0.2849 - val_accuracy: 0.6185 - val_loss: 1.2711

Epoch 7/10
92/92 ━━━━━━━━━━━━━━━━━━━━ 10s 109ms/step
- accuracy: 0.9447 - loss: 0.1798 - val_accuracy: 0.6322 - val_loss: 1.6090

Epoch 8/10
92/92 ━━━━━━━━━━━━━━━━━━━━ 10s 109ms/step 
- accuracy: 0.9662 - loss: 0.1248 - val_accuracy: 0.6376 - val_loss: 1.5558

Epoch 9/10
92/92 ━━━━━━━━━━━━━━━━━━━━ 10s 109ms/step 
- accuracy: 0.9681 - loss: 0.1055 - val_accuracy: 0.6226 - val_loss: 1.5605

Epoch 10/10
92/92 ━━━━━━━━━━━━━━━━━━━━ 10s 109ms/step 
- accuracy: 0.9885 - loss: 0.0416 - val_accuracy: 0.6322 - val_loss: 1.7783

이렇게 여러번 돌려보면서 최적의 에포크값을 찾는 연습을 해야합니다.

 


#훈련 결과 시각화
acc=  history.history['accuracy']
val_acc= history.history['val_accuracy']
loss= history.history['loss']
val_loss= history.history['val_loss']

plt.figure(figsize=(8,8))
plt.subplot(1,2,1)
plt.plot(range(20), acc, label='훈련 정확도')
plt.plot(range(20), val_acc, label='검증 정확도')
plt.legend(loc='lower right')
plt.title('훈련데이터셋과 검증데이터셋 정확도')

plt.subplot(1,2,2)
plt.plot(range(10), loss, label='훈련손실')
plt.plot(range(20), val_loss, label='검증 손실')
plt.legend(loc='upper right')
plt.title('훈련데이터셋과 검증데이터셋 손실')

plt.show()