오늘의 수업 요약

한식 이미지 분류 VGG19 전이학습

거대 모델의 지혜를 빌려와(Transfer Learning) 적은 데이터로도 고성능 한식 분류기 만들기

무엇을 배울까요?

💡 쉬운 예시: 이미 온갖 사물을 다 구별할 줄 아는 '미술 전문가(VGG19)'에게 우리 한식 사진들을 보여주며 "전문가님, 이건 제육이고 저건 된장찌개예요"라고 핵심만 가르치는 것과 같아요.

1

한식 데이터 로드 및 전처리 (복습)

왜 이 코드를 실행하나요? 14번 수업과 동일하게 한식 이미지를 폴더별로 읽어오고 스케일링을 수행합니다. 이번에는 우리가 직접 만든 CNN 대신, 검증된 VGG19 모델을 사용할 준비를 하는 단계입니다.
# 데이터 로드 및 분할 생략 (14번과 동일)
# X_train, y_train, X_test, y_test 준비됨
X_train = X_train / 255.
# 픽셀값을 0~1 사이로 정규화해요.
X_test = X_test / 255.
# 테스트 데이터도 똑같이 정규화해요.
from tensorflow.keras import utils
y_train = utils.to_categorical(y_train, 6)
# 훈련 정답을 원-핫 벡터로 바꿔요.
y_test = utils.to_categorical(y_test, 6)
# 테스트 정답도 똑같이 변환해요.
실제 출력
(실제 데이터 238장 로드 및 전처리 완료)
출력 해설: 14번에서 확인했던 데이터들을 VGG19 모델의 입력 규격에 맞춰 다시 한번 정돈했습니다.
2

전이학습(Transfer Learning) 설정

왜 이 코드를 실행하나요? VGG19의 똑똑한 특징 추출 능력은 그대로 빌려오되, 우리가 가진 6가지 한식을 분류할 수 있도록 마지막 층만 새로 설계합니다. 처음에는 VGG의 가중치를 고정(trainable=False)하여 학습 효율을 높입니다.
from tensorflow.keras.applications.vgg19 import VGG19
import tensorflow as tf
model = VGG19(input_shape=(96, 96, 3), include_top=False, weights='imagenet')
# ImageNet으로 학습된 VGG19를 불러와요. (96x96 입력, 분류층 제외)
model.trainable = False
# 이미 배운 능력(가중치)은 변하지 않게 꽁꽁 잠가요.
t_model = tf.keras.models.Sequential([
# 새로운 순차적 모델을 시작해요.
model,
# 잠가놓은 VGG19를 첫 번째 특징 추출기로 넣어요.
tf.keras.layers.GlobalAveragePooling2D(),
# VGG가 뽑은 복잡한 특징맵을 평균내서 단순화해요.
tf.keras.layers.Dense(128, activation='relu'),
# 추출된 정보를 조합할 중간 지능 층을 추가해요.
tf.keras.layers.Dense(6, activation='softmax')
# 6가지 음식을 맞히는 마지막 출구를 만들어요.
])
# 전이학습용 학습 규칙(Adam 0.001)을 설정해요.
t_model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
# 결합된 모델의 전체 지도를 그려봐요.
loss='categorical_crossentropy',
metrics=['accuracy'])
t_model.summary()
예상 출력
Model: "sequential" _________________________________________________________________ vgg19 (Functional) (None, 3, 3, 512) 20024384 global_average_pooling2d (None, 512) 0 dense (None, 128) 65664 dense_1 (None, 6) 774 ================================================================= Total params: 20,090,822 Trainable params: 66,438 Non-trainable params: 20,024,384
출력 해설: 약 2,000만 개의 파라미터 중 우리가 추가한 6만 개만 학습 가능(Trainable)한 상태인 것을 확인해야 합니다.
실제 데이터 샘플
3

미세 조정(Fine-Tuning)으로 성능 극대화

왜 이 코드를 실행하나요? 분류기가 어느 정도 학습되었다면, 잠가두었던 VGG19의 레이어들도 아주 미세하게(낮은 학습률) 다시 학습시켜 우리 데이터에 최적화합니다. 이를 통해 모델이 한식 고유의 특징을 더 잘 잡게 됩니다.
t_model.trainable = True
# 잠겨있던 VGG 레이어들을 포함해 전체 모델을 다시 학습 가능하게 풀어요.
t_model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),
# 기존 지식이 파괴되지 않게 아주 낮은 학습률(0.0001)로 설정을 바꿔요.
loss='categorical_crossentropy',
# 전체 파라미터가 다시 학습 가능해진 상태를 확인해요.
metrics=['accuracy'])
t_model.summary()
예상 출력
Trainable params: 20,090,822 Non-trainable params: 0
출력 해설: 이제 모든 파라미터가 '한식 마스터'가 되기 위해 미세하게 조정될 준비가 끝났습니다.
4

체크포인트 저장 및 학습 실행

왜 이 코드를 실행하나요? 미세 조정 과정에서 가장 높은 검증 정확도를 기록한 순간의 모델을 파일로 저장합니다. 이 파일은 나중에 웹 서비스(food.py)에서 불러와서 사용하게 됩니다.
from tensorflow.keras.callbacks import ModelCheckpoint
checkpoint = ModelCheckpoint("c:/data/models/food_vgg_best.keras", monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')
# VGG 기반의 최고 성능 모델을 저장할 경로를 지정해요.
hist = t_model.fit(X_train, y_train, batch_size=32, validation_split=0.2, epochs=50, callbacks=[checkpoint])
# 50번의 반복 학습을 수행하며 매번 최고의 상태를 저장해요.
예상 출력
Epoch 1/50 5/5 [==============================] - 5s 800ms/step - loss: 0.820 - accuracy: 0.750 - val_loss: 0.610 - val_accuracy: 0.820 ... Epoch 50/50 5/5 [==============================] - 1s 250ms/step - loss: 0.050 - accuracy: 0.990 - val_loss: 0.280 - val_accuracy: 0.940
출력 해설: 직접 만든 CNN보다 훨씬 높은 정확도(90% 이상)가 나오는 것을 실시간으로 지켜볼 수 있습니다.