가중치 동결: 빌려온 지식을 보호하기 위해 레이어를 trainable=False로 잠그는 필수 과정
미세 조정: 잠금을 풀고 아주 낮은 학습률로 모델을 내 데이터에 정교하게 맞추는 단계
회귀(Regression): 나이, 가격처럼 연속적인 수치값을 예측하는 신경망 설계법
서비스화: Flask 서버를 이용해 내가 만든 모델을 웹 환경에서 동작시키는 최종 워크플로우
PART 1. 개념 정복 퀴즈보기 클릭 시 바로 정답 체크!
CONCEPT QUIZ 1
1. '전이학습(Transfer Learning)'의 가장 핵심적인 작동 원리는 무엇인가요?
A) 매번 새로운 데이터를 위해 모델을 처음부터 다시 설계한다.
B) 사전에 거대 데이터로 학습된 가중치를 가져와 내 문제에 재사용한다.
C) 복잡한 수학 연산을 생략하여 하드웨어 부담을 줄인다.
D) 모든 데이터를 흑백으로 변환하여 학습 속도를 높인다.
💡 정답 해설
전이학습은 이미 수백만 장의 이미지(ImageNet 등)로 학습되어 '사물을 보는 눈'이 발달한 모델의 지식(가중치)을 그대로 가져오는 기법입니다. 덕분에 적은 양의 데이터와 짧은 시간으로도 매우 높은 정확도를 얻을 수 있어 실무에서 가장 선호되는 방식입니다.
CONCEPT QUIZ 2
2. VGG19 모델 로드 시 'include_top=False'를 설정하는 결정적인 이유는?
A) 모델의 메모리 사용량을 절반으로 줄이기 위해
B) 1,000가지 사물을 분류하는 기존의 출력층을 제거하고, 내 목적에 맞는 새 분류기를 달기 위해
C) 이미지의 해상도를 자동으로 224x224로 고정하기 위해
D) 훈련 속도를 높이기 위해 특정 레이어들을 삭제하기 위해
💡 정답 해설
VGG19는 기본적으로 1,000가지 사물을 맞히도록 설계되어 있습니다. 하지만 우리가 하려는 것은 '한식 분류'나 '나이 예측'처럼 다른 목적이죠. 따라서 기존의 '결정 부분(Top)'만 떼어내고, 사물의 특징만 기가 막히게 뽑아내는 '몸통 부분'만 빌려오기 위해 False를 사용합니다.
CONCEPT QUIZ 3
3. 미세 조정(Fine-tuning)을 할 때 학습률(Learning Rate)을 0.0001처럼 아주 낮게 잡는 이유는 무엇일까요?
A) 학습 시간을 의도적으로 늘려 더 꼼꼼히 배우게 하기 위해
B) 기존에 VGG가 배운 강력한 사물 인식 지식을 파괴하지 않으면서 내 데이터에 동화시키기 위해
C) 정확도가 너무 높게 나오는 것을 방지하기 위해
D) 모델의 파일 용량을 줄이기 위해
💡 정답 해설
이미 똑똑한 베테랑(VGG19)에게 새로운 일을 시킬 때, 너무 강한 자극(높은 학습률)을 주면 베테랑이 가진 기존 지식이 다 망가져 버립니다. 이를 '파괴적 망각'이라고 하죠. 기존 지식을 최대한 유지하면서 우리 데이터의 특성을 살짝 덧칠하기 위해 아주 섬세한 학습률이 필수입니다.
CONCEPT QUIZ 4
4. 골연령(Age) 예측 모델처럼 숫자를 직접 맞히는 '회귀(Regression)' 문제의 특징은?
A) 마지막 출력층의 활성화 함수로 반드시 'softmax'를 써야 한다.
B) 결과값이 항상 0 아니면 1로만 나와야 한다.
C) 마지막 층의 뉴런 수는 1개이며, 별도의 활성화 함수를 쓰지 않거나 선형 함수를 쓴다.
D) 이미지 데이터를 처리할 수 없는 방식이다.
💡 정답 해설
분류(Classification)는 여러 후보 중 '몇 번이냐'를 고르는 것이지만, 회귀는 '몇 살이냐'라는 연속된 수치를 직접 계산해야 합니다. 따라서 6개 메뉴 중 하나를 고르는 softmax 대신, 계산된 수치 그 자체를 내보내는 1개의 뉴런을 출구로 사용합니다.
CONCEPT QUIZ 5
5. 실전 웹 서비스(Flask)에서 사용자가 올린 사진을 모델에 넣기 전 반드시 해야 하는 과정은?
A) 사진의 이름을 영어로 바꾼다.
B) 학습 당시와 똑같은 크기로 리사이즈하고, 0~1 사이로 스케일링한다.
C) 서버를 재시작한다.
D) 사진을 데이터베이스에 먼저 저장한다.
💡 정답 해설
인공지능 모델은 자기가 공부했던 환경에 매우 민감합니다. 96x96 사진으로 공부한 모델에게 1000x1000 사진을 그냥 주면 에러가 나거나 엉뚱한 답을 합니다. 따라서 사용자가 어떤 사진을 올리든, 서버 측에서 학습 규격(Resize)과 데이터 범위(Normalization)를 완벽히 맞춰주는 '전처리 전담팀'이 필요합니다.
PART 2. 실전 코드 완성빈칸을 채우고 Enter를 누르세요!
CODE COMPLETION 1
Q1. VGG19의 기존 지식을 보호하기 위해 '학습 불가능' 상태로 레이어를 잠가보세요.
HINT 💡
vgg_model. = False
💡 코드 설명
trainable 속성을 False로 두는 것을 'Freezing(동결)'이라고 합니다. 이렇게 하면 VGG 레이어의 가중치는 업데이트되지 않고, 우리가 뒤에 새로 붙인 층들만 학습에 집중하게 되어 효율이 매우 올라갑니다.
✅ 정답: trainable
CODE COMPLETION 2
Q2. 낱개 사진(3차원)을 모델이 좋아하는 묶음 단위(4차원)로 차원을 확장해보세요.
HINT 💡
arr = np.(arr, axis=0)
💡 코드 설명
케라스 모델은 항상 '데이터 묶음(Batch)' 단위로 입력을 받습니다. 사진 1장을 넣더라도 '(1, 96, 96, 3)' 처럼 앞에 1(장수)이라는 차원이 있어야 합니다. expand_dims는 이 빈 방을 만들어주는 아주 중요한 역할을 합니다.
✅ 정답: expand_dims
CODE COMPLETION 3
Q3. 6가지 종류의 음식을 분류하기 위한 마지막 출력층(Dense)을 설정하세요.
HINT 💡
layers.Dense(, activation='softmax')
💡 코드 설명
마지막 층의 뉴런 개수는 우리가 맞히고 싶은 '정답 후보의 수'와 같아야 합니다. 한식 실습에서는 치킨부터 된장찌개까지 총 6가지였으므로 6을 써야 하며, 확률로 결과를 얻기 위해 softmax를 곁들입니다.
✅ 정답: 6
CODE COMPLETION 4
Q4. 회귀 문제(나이 예측)에서 실제값과 예측값의 차이를 계산하는 손실 함수를 설정하세요.
HINT 💡
model.compile(optimizer='adam', loss='')
💡 코드 설명
mae(평균 절대 오차)는 회귀 문제에서 모델이 얼마나 틀리고 있는지 직관적으로 보여주는 지표입니다. 예를 들어 MAE가 1.5라면 '평균적으로 실제 나이와 1.5살 정도 차이가 난다'는 아주 알기 쉬운 성적표가 됩니다.
✅ 정답: mae
CODE COMPLETION 5
Q5. Flask 서버에서 사용자가 보낸 파일 스트림에 접근할 때 쓰는 속성 이름을 채우세요.
HINT 💡
img = Image.open(request.['file'].stream)
💡 코드 설명
사용자가 웹 폼(Form)을 통해 보낸 파일 데이터는 Flask의 request.files 딕셔너리에 담겨 들어옵니다. 'file'은 우리가 HTML input 태그에서 정해준 이름(name)입니다.