반응형

이전 게시글의 결과를 분석하면

현재 상태 분석

항목상태 및 해석
cuDNN 사용 확인 Loaded cuDNN version 8100 → 정상
GPU 인식됨 GTX 1050, 2775MB 사용 중
훈련 진행됨 Epoch 27까지 무사히 진행 중
⚠️ GPU 사용률 낮음 이미지상 1~3% 수준 유지
⚠️ Epoch당 평균 시간 12분(Epoch 1) ~ 14분(Epoch 26)
⚠️ 발열 온도 90도 이상 유지, 냉각 부족 가능성
정확도 향상 곡선 정상 Epoch 1: acc 1% → Epoch 26: acc 32.8%, val_acc 60.2%
  • 주요 병목 현상 원인 : 1. GPU 연산 비중이 낮고, 병렬처리 최적화 부족
    • GPU가 활성화돼 있어도 연산을 효율적으로 활용 못 하고 있음 (1~3% 사용률)
    • 주요 원인:
      • TensorFlow 연산 중 일부가 여전히 CPU fallback
      • Data pipeline(입력 이미지 처리)이 병목
      • 모델 구조상 cuDNN이 최적 커널을 사용하지 못함 (특히 DenseNet 계열)

이에 따라 실행시간 단축을 위해 MobileNetV2 모델로 변경하여 수행

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import GlobalAveragePooling2D, Dense, Dropout, Rescaling
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.utils import image_dataset_from_directory
from tensorflow.keras.callbacks import EarlyStopping
import pathlib
import pickle
import matplotlib.pyplot as plt

# ✅ GPU 메모리 자동 증가 설정
gpus = tf.config.list_physical_devices('GPU')
if gpus:
    try:
        for gpu in gpus:
            tf.config.experimental.set_memory_growth(gpu, True)
        print(f"{len(gpus)} GPU(s) available.")
    except RuntimeError as e:
        print(e)
else:
    print("GPU not found.")

# ✅ 데이터 경로 설정
data_path = pathlib.Path('datasets/stanford_dogs/images/images')

# ✅ 원본 데이터셋 생성 및 클래스 이름 추출
train_ds_raw = image_dataset_from_directory(
    data_path,
    validation_split=0.2,
    subset='training',
    seed=123,
    image_size=(224, 224),
    batch_size=4
)

test_ds_raw = image_dataset_from_directory(
    data_path,
    validation_split=0.2,
    subset='validation',
    seed=123,
    image_size=(224, 224),
    batch_size=4
)

# ✅ 클래스 이름 저장 (prefetch 전에 추출)
class_names = train_ds_raw.class_names
with open('dog_species_names.txt', 'wb') as f:
    pickle.dump(class_names, f)

# ✅ 데이터 성능 최적화 (cache + prefetch)
AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds_raw.cache().prefetch(buffer_size=AUTOTUNE)
test_ds = test_ds_raw.cache().prefetch(buffer_size=AUTOTUNE)

# ✅ 사전 학습된 MobileNetV2 모델 로딩
base_model = MobileNetV2(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
base_model.trainable = False  # 전체 동결 (추후 일부 fine-tuning 가능)

# ✅ 전체 모델 구성
cnn = Sequential([
    Rescaling(1.0 / 255.0),
    base_model,
    GlobalAveragePooling2D(),
    Dense(512, activation='relu'),
    Dropout(0.5),
    Dense(120, activation='softmax')  # 120개의 견종
])

# ✅ 컴파일
cnn.compile(
    loss='sparse_categorical_crossentropy',
    optimizer=Adam(learning_rate=1e-4),
    metrics=['accuracy']
)

# ✅ EarlyStopping 콜백 설정
earlystop = EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True)

# ✅ 모델 학습
hist = cnn.fit(
    train_ds,
    epochs=30,
    validation_data=test_ds,
    verbose=2,
    callbacks=[earlystop]
)

# ✅ 평가 및 저장
test_acc = cnn.evaluate(test_ds, verbose=0)[1]
print(f'정확률 = {test_acc * 100:.2f}%')

cnn.save('mobilenetv2_dog_classifier.h5')

# ✅ 정확도 시각화
plt.plot(hist.history['accuracy'])
plt.plot(hist.history['val_accuracy'])
plt.title('Accuracy graph')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Validation'])
plt.grid()
plt.show()

# ✅ 손실 시각화
plt.plot(hist.history['loss'])
plt.plot(hist.history['val_loss'])
plt.title('Loss graph')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Validation'])
plt.grid()
plt.show()

실행 결과는 다음과 같다.

(tf310) C:\Users\ksseo\Downloads\source_4548_1\source\ch8>python 8-7-MobileNetV2.py
1 GPU(s) available.
Found 20580 files belonging to 120 classes.
Using 16464 files for training.
2025-07-19 16:53:45.437421: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX AVX2
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2025-07-19 16:53:46.000395: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1616] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 2775 MB memory:  -> device: 0, name: NVIDIA GeForce GTX 1050, pci bus id: 0000:01:00.0, compute capability: 6.1
Found 20580 files belonging to 120 classes.
Using 4116 files for validation.
Epoch 1/30
2025-07-19 16:53:54.346380: I tensorflow/stream_executor/cuda/cuda_dnn.cc:384] Loaded cuDNN version 8100
4116/4116 - 115s - loss: 2.1133 - accuracy: 0.4825 - val_loss: 0.8946 - val_accuracy: 0.7456 - 115s/epoch - 28ms/step
Epoch 2/30
4116/4116 - 105s - loss: 0.9972 - accuracy: 0.7088 - val_loss: 0.7530 - val_accuracy: 0.7699 - 105s/epoch - 26ms/step
Epoch 3/30
4116/4116 - 106s - loss: 0.7998 - accuracy: 0.7566 - val_loss: 0.7154 - val_accuracy: 0.7665 - 106s/epoch - 26ms/step
Epoch 4/30
4116/4116 - 107s - loss: 0.6698 - accuracy: 0.7946 - val_loss: 0.7038 - val_accuracy: 0.7750 - 107s/epoch - 26ms/step
Epoch 5/30
4116/4116 - 107s - loss: 0.5769 - accuracy: 0.8192 - val_loss: 0.6811 - val_accuracy: 0.7852 - 107s/epoch - 26ms/step
Epoch 6/30
4116/4116 - 109s - loss: 0.4952 - accuracy: 0.8409 - val_loss: 0.6892 - val_accuracy: 0.7821 - 109s/epoch - 27ms/step
Epoch 7/30
4116/4116 - 108s - loss: 0.4493 - accuracy: 0.8564 - val_loss: 0.6801 - val_accuracy: 0.7840 - 108s/epoch - 26ms/step
Epoch 8/30
4116/4116 - 108s - loss: 0.3897 - accuracy: 0.8757 - val_loss: 0.6951 - val_accuracy: 0.7813 - 108s/epoch - 26ms/step
Epoch 9/30
4116/4116 - 108s - loss: 0.3473 - accuracy: 0.8845 - val_loss: 0.7061 - val_accuracy: 0.7787 - 108s/epoch - 26ms/step
Epoch 10/30
4116/4116 - 108s - loss: 0.3113 - accuracy: 0.8997 - val_loss: 0.6975 - val_accuracy: 0.7881 - 108s/epoch - 26ms/step
Epoch 11/30
4116/4116 - 108s - loss: 0.2798 - accuracy: 0.9076 - val_loss: 0.6887 - val_accuracy: 0.7877 - 108s/epoch - 26ms/step
Epoch 12/30
4116/4116 - 108s - loss: 0.2531 - accuracy: 0.9182 - val_loss: 0.7069 - val_accuracy: 0.7830 - 108s/epoch - 26ms/step
정확률 = 78.40%

반응형
Posted by 세상을 살아가는 사람
,
반응형

프로그램 8-7 DenseNet121로 견종 인식하기
처음 실행하니 CPU로만 실행하여 처리시간이 너무 오래 걸려 Epoch 1/200을 출력하지도 못할 것 같았다.
내 컴퓨터에는 GPU가 내장되어 있으므로 GPU를 사용하기로 하였다.
GPU를 사용하기 위해서는 지금까지 사용하던 tensorflow 버전으로는 동작을 하지 않아 버전을 2.10으로 downgrade 하였으며, 그에 따라 CUDA 버전도 11.8, cuDNN 버전도 8.6.0으로 변경을 하였다.

작업관리자를 띄워서 성능을 보면 위 그림과 같이 GPU 사용률은 1% 밖에 되지 않는데, 전용 GPU/메모리가 3.1/4.0GB로 사용량이 높고, GPU 온도가 92도까지 올라가기도 한다. 처음에는 89도에서 92도까지 변화되어 선풍기로 냉각을 시키고, 에어컨도 틀어주었다. 그랬더니 GPU 온도가 84도까지 떨어져서 그래도 안정된 것 같다.

위 그림을 보면 Epoch를 한번 수행하는데 740초가량이 소요되어 13분 정도 시간이 걸린다. 200/200까지 수행하려면 12분 20초 * 200 = 2467분 = 41시간이 소요될 것으로 예측이 되므로 도저히 어려울 것 같다.
다행히 Epoch가 증가할수록 정확도가 개선되고 있으며 8/200에서는 27.43%까지 올라간 것을 확인할 수가 있었다.
4116/4116 - 735s - loss: 4.1016 - accuracy: 0.1104 - val_loss: 3.5437 - val_accuracy: 0.3027 - 735s/epoch - 179ms/step
Epoch 10/200
4116/4116 - 735s - loss: 3.9944 - accuracy: 0.1271 - val_loss: 3.3806 - val_accuracy: 0.3370 - 735s/epoch - 179ms/step
Epoch 11/200
4116/4116 - 743s - loss: 3.9041 - accuracy: 0.1416 - val_loss: 3.2306 - val_accuracy: 0.3695 - 743s/epoch - 181ms/step
Epoch 12/200
4116/4116 - 734s - loss: 3.8290 - accuracy: 0.1573 - val_loss: 3.0833 - val_accuracy: 0.3953 - 734s/epoch - 178ms/step
Epoch 13/200
4116/4116 - 740s - loss: 3.7360 - accuracy: 0.1676 - val_loss: 2.9486 - val_accuracy: 0.4191 - 740s/epoch - 180ms/step
Epoch 14/200
4116/4116 - 742s - loss: 3.6363 - accuracy: 0.1840 - val_loss: 2.8093 - val_accuracy: 0.4385 - 742s/epoch - 180ms/step
Epoch 15/200
4116/4116 - 743s - loss: 3.5539 - accuracy: 0.2006 - val_loss: 2.6805 - val_accuracy: 0.4546 - 743s/epoch - 180ms/step
Epoch 16/200
4116/4116 - 737s - loss: 3.4811 - accuracy: 0.2161 - val_loss: 2.5578 - val_accuracy: 0.4704 - 737s/epoch - 179ms/step
Epoch 17/200
4116/4116 - 1785s - loss: 3.4074 - accuracy: 0.2256 - val_loss: 2.4417 - val_accuracy: 0.4864 - 1785s/epoch - 434ms/step
Epoch 18/200
4116/4116 - 727s - loss: 3.3276 - accuracy: 0.2354 - val_loss: 2.3386 - val_accuracy: 0.5032 - 727s/epoch - 177ms/step
Epoch 19/200
4116/4116 - 726s - loss: 3.2528 - accuracy: 0.2499 - val_loss: 2.2391 - val_accuracy: 0.5155 - 726s/epoch - 176ms/step
Epoch 20/200
4116/4116 - 729s - loss: 3.1741 - accuracy: 0.2647 - val_loss: 2.1461 - val_accuracy: 0.5338 - 729s/epoch - 177ms/step
Epoch 21/200
4116/4116 - 729s - loss: 3.1237 - accuracy: 0.2739 - val_loss: 2.0590 - val_accuracy: 0.5420 - 729s/epoch - 177ms/step
Epoch 22/200
4116/4116 - 729s - loss: 3.0502 - accuracy: 0.2894 - val_loss: 1.9787 - val_accuracy: 0.5547 - 729s/epoch - 177ms/step
Epoch 23/200
4116/4116 - 732s - loss: 2.9809 - accuracy: 0.2958 - val_loss: 1.9031 - val_accuracy: 0.5695 - 732s/epoch - 178ms/step
Epoch 24/200
4116/4116 - 729s - loss: 2.9353 - accuracy: 0.3001 - val_loss: 1.8319 - val_accuracy: 0.5739 - 729s/epoch - 177ms/step
Epoch 25/200
4116/4116 - 728s - loss: 2.8716 - accuracy: 0.3179 - val_loss: 1.7644 - val_accuracy: 0.5884 - 728s/epoch - 177ms/step
Epoch 26/200
4116/4116 - 851s - loss: 2.8193 - accuracy: 0.3277 - val_loss: 1.7095 - val_accuracy: 0.6018 - 851s/epoch - 207ms/step
Epoch 27/200
4116/4116 - 746s - loss: 2.7599 - accuracy: 0.3376 - val_loss: 1.6465 - val_accuracy: 0.6122 - 746s/epoch - 181ms/step
Epoch 28/200
시간이 너무 많이 걸려 도중에 중단을 하였다. Epoch 27/200까지 정확도가 61.22%가 되었다.

반응형
Posted by 세상을 살아가는 사람
,