9장. 모델 평가와 활용, QLoRA
부작용 점검: 일반 질문에도 말투가 번진다
사투리 연기 연습을 한 달 내내 한 배우를 떠올려 봅니다. 연습은 잘되었지만, 촬영이 끝난 뒤 은행 창구에서도 사투리가 튀어나옵니다. 좁은 데이터로 학습하면 학습 목표와 상관없는 질문에도 영향이 갑니다. 이 과정의 페르소나 데이터(냉소적인 절대 군주 말투)는 말투 차이를 눈으로 보기 쉽게 고른 학습용 데이터라서, 이런 번짐이 특히 잘 보입니다.
그림의 왼쪽은 어댑터를 끈 원래 모델, 오른쪽은 어댑터를 켠 모델의 답입니다. 같은 질문 "대한민국의 수도는 어디인가요?"에 오른쪽도 "서울"을 말하긴 하지만, 말투가 바뀌고 쓸데없는 비꼼이 붙었습니다. 실습 2에서는 "3 더하기 5는 얼마인가요?"에 정답(8) 대신 "더하기 해서 네 속은 변하지 않아."가 나옵니다.
실무에서의 대응
| 대응 | 방법 | 배우로 치면 |
|---|---|---|
| 데이터 섞기 | 목표 행동 데이터에 일반 질문에 정확히 답하는 예시를 함께 넣는다 | 사투리 연습 중에도 표준어 장면을 섞기 |
| 덜 건드리기 | epoch 과 학습률을 줄여 기존 능력을 덜 바꾼다 | 연습 기간을 줄이기 |
| 필요할 때만 켜기 | 어댑터를 필요한 요청에만 켜서 쓴다 | 촬영장에서만 사투리 쓰기 |
짧은 예시
# 실습 2의 실제 출력에서 옮긴 일반 질문 세 개와 답(학습 전 = 어댑터 끔, 학습 후 = 어댑터 켬)
checks = [
("대한민국의 수도는 어디인가요?", "서울", "대한민국의 수도는 서울입니다.", "서울이지. 네 지름길이라니."),
("3 더하기 5는 얼마인가요?", "8", "3 더하기 5은 8입니다.", "더하기 해서 네 속은 변하지 않아."),
("물은 몇 도에서 끓나요?", "100", "물은 대부분의 경우 물리적으로 빠르게 움직이지 않습니다.", "천문관에 다다르면 물이 뜯어질 거예요."),
]
for question, key, before, after in checks:
# 정답 낱말(key)이 답에 들어 있는지 본다: 정답을 말했는지의 아주 단순한 규칙
print(f"{question:<18} 끔: {key in before!s:<5} 켬: {key in after}")
# 결과: 수도 끔 True 켬 True / 덧셈 끔 True 켬 False / 끓는점 끔 False 켬 False이 코드가 뜻하는 것
배우가 촬영장 밖에서도 표준어로 말할 수 있는지, 대본 세 줄로 확인한 것과 같습니다. 덧셈 질문은 어댑터를 끄면 맞히고 켜면 놓칩니다. 이것이 부작용입니다. 끓는점 질문은 어댑터를 꺼도 틀립니다. 0.5B 라는 작은 모델의 한계라서, 어댑터 탓으로 보면 안 됩니다. 여기서 대본이 checks, 정답 낱말이 key, 점검 결과가 key in after 입니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
checks = [...] | 질문, 정답 낱말, 두 답을 묶는다 | 점검표의 행 |
key in before | 어댑터를 끈 답에 정답 낱말이 있나 | 원래 실력 |
key in after | 어댑터를 켠 답에 정답 낱말이 있나 | 연수 뒤 실력 |
"끔은 맞히고 켬은 틀린" 행만 어댑터의 부작용입니다. 둘 다 틀린 행은 기반 모델부터 약한 질문입니다. 이렇게 "끔"과 "켬"을 나란히 두어야 원인을 가를 수 있습니다. 프로젝트에서 이 점검표를 pandas 표로 만듭니다.
주의할 점
- 정답 낱말 검사는 아주 거친 규칙입니다. "8이 아니라 9입니다"처럼 낱말이 들어 있어도 틀린 답일 수 있습니다.
- 실제 서비스 모델이라면 말투 변화가 허용 범위인지, 안전과 관련된 질문에서 답이 나빠지지 않았는지 꼭 확인합니다.
- 실습 2의 답은
do_sample=False(늘 가장 그럴듯한 토큰 고르기)로 만든 것이라 같은 모델에서는 다시 실행해도 같습니다. 학습을 다시 하면 어댑터가 바뀌어 답도 바뀝니다.