Gemma 3 LoRA Adapter Composition 실험 - 2

Gemma 3 LoRA Adapter Composition 실험 - 2
Photo by Mavis Hopper / Unsplash

지난 포스트에서는 LoRA 두 개를 합쳐 보는 실험을 했다. 하나는 영화 "범죄와의 전쟁"에서 부산 사투리를 쓰는 인물 최익현의 말투를 배운 LoRA 이고, 다른 하나는 의료 상담 대화를 배운 LoRA 다. 이 둘을 PEFT 라이브러리로 한 모델에 함께 끼워 테스트했다.

안타깝게도 두 LoRA 의 결합 자체가 불완전해 보였다. 결합하면 오히려 답변이 짧아지고, 캐릭터의 말투와 의료상담의 특성이 모두 약해졌다.

지난 포스트에서는 두 LoRA 를 1:1 로 결합했을 때 "부산 사투리 + 문진 질문 목록 + 위험 신호 안내"처럼 두 특성이 함께 나오기를 기대했지만, 결과는 그렇지 못했다. 그래서 이번에는 먼저 각 LoRA 가 혼자서 제대로 답하는지부터 점검해 학습 데이터와 학습 설정을 고치고, 그다음 두 LoRA 를 다시 결합해 보기로 한다.

먼저 알아 두면 좋은 말

  • LoRA: 거대한 언어 모델 전체를 다시 학습하지 않고, 작은 추가 부품만 학습해서 모델의 말투나 지식을 바꾸는 방법이다. 이 부품을 Adapter 라고도 부른다.
  • 결합: LoRA 두 개를 한 모델에 동시에 끼우는 것이다. "1.0 : 1.0"은 두 LoRA 를 같은 세기로 끼웠다는 뜻이다.
  • 문진: 의사가 진단하기 전에 환자에게 증상을 묻는 것이다.
  • 위험 신호 안내: "이런 증상이 있으면 바로 병원에 가라"는 안내다.
  • 토큰: 모델이 글을 만드는 단위다. 대략 글자 조각 하나라고 생각하면 된다.

진행 순서는 다음과 같다.

  1. 캐릭터 LoRA 학습 데이터 1차 개선
  2. 캐릭터 LoRA 학습 데이터 2차 개선
  3. 학습 하이퍼파라미터 개선
  4. 의료 LoRA 학습 데이터 개선
  5. 결합이 실패하는 원인 분석
  6. 캐릭터 LoRA 학습 데이터 3차 개선
  7. 처음 보는 질문으로 검증하기
  8. 캐릭터 LoRA 학습 데이터 4차 개선
  9. 결론

01. 캐릭터 LoRA 학습 데이터 1차 개선

모델 테스트 결과를 보면, 먼저 시나리오에서 뽑아낸 최익현이라는 캐릭터의 특성이나 특유의 부산 사투리가 잘 나타나지 않았다. 이 부분부터 개선을 해보고자 한다.

1) 데이터를 어떻게 바꿨나

이전 학습 데이터가 영화 시나리오 대사를 기반으로 만들다 보니 대사 자체가 부족했고, 내가 기억하는 최익현의 과장된 모습들을 학습하기에도 부족했다고 판단했다. 그래서 표현을 조금 과장한 학습 데이터를 만들어 다시 학습시켰다. 다음은 그 테스트 결과다.

개선 후 질문 테스트)

며칠째 기침이 계속되고 밤에 더 심해집니다. 열은 없는데 어떤 점을 확인해야 하나요?
구성응답
Base며칠째 기침이 계속되고 밤에 더 심해지는 증상은 다양한 원인으로 발생할 수 있습니다......(생략)
캐릭터 LoRA 단독며칠째 계속되면 감기인지 다른 원인이 있는지 확인해 봐야제. 증상이 심해지면 진료를 받아야제.
의료 LoRA 단독기침이 계속되고 밤에 더 심해진다면, 감기나 인플루엔자 같은 바이러스 감염일 수 있습니다. 그러나 다른 원인도 있을 수 있으므로, 의사의 진단을 받아보는 것이 좋습니다.
결합(cat) 1.0 : 1.0기침이 계속되면 감기나 바이러스 감염일 수 있제. 24시간 동안 증상이 심해지면 응급실을 찾아야 한다.
결합(cat) 1.5 : 0.2마, 며칠째면 감기인지 오래서야 알제. 고르게 쉬지 말아야제. 증상이 심하면 진료를 받아 보라 카이.
결합(cat) 1.5 : 1.5밤에 심해지면 감기인지는 알겠제. 증상이 계속되면 진료를 받아야 안 되겠나?

2) 1차 개선 결과와 남은 문제

캐릭터의 표현을 강조한 학습 데이터로 재학습한 결과 이전보다 부산 사투리의 화법이 뚜렷하게 나타났다. 하지만 테스트 결과를 자세히 보면 아직 해결해야 할 문제가 많았다.

  • 사투리가 단조롭다.
    • 거의 모든 문장이 "~해야제"로 끝난다. 과장된 최익현이라기보다는 표준어에 어미만 바꾼 느낌에 가깝다.
  • 결합하면 답변이 한두 문장으로 짧아진다.
    • 문진 질문은 하나도 나오지 않는다.
  • 의료 LoRA 단독도 약하다.
    • 질문을 하지 않고 "의사의 진단을 받아보라"로 끝난다. 결합 이전에 의료 LoRA 자체도 개선이 필요해 보였다.
  • 가중치를 키워도 해결되지 않는다.
    • 1.5 : 1.5 로 올려도 답변은 여전히 짧다.

결국 표현을 과장하는 것만으로는 부족했고, 학습 데이터를 한 번 더 들여다보기로 했다.

02. 캐릭터 LoRA 학습 데이터 2차 개선

1차 개선의 결과를 보고 학습 데이터를 문장 단위로 하나하나 세어 봤다. 생각보다 문제가 컸다.

1) 데이터를 다시 들여다보니

  • 같은 문장이 수백 번 반복되고 있었다.
    • "확인되지 않은 사실을 만들어 붙이지 않는 게 중요하다" 같은 내용 없는 문장이 최대 284 번 반복됐고, 이런 반복 문장이 전체 답변 문장의 절반 가까이를 차지했다. 결합했을 때 나왔던 의미 없는 답변들도 결국 이 문장들을 외운 결과였다.
  • 사투리가 생각보다 옅었다.
    • "해 봐라", "하자" 같은 표준어 반말은 빼고 진짜 사투리 어미로 끝나는 문장만 세어 보니 원본은 21.5%, 1차 개선 데이터도 46.1% 에 불과했다. 그마저도 "보래이", "아이가" 같은 몇 개 어미만 기계적으로 반복되고 있었다.

2) 어떻게 바꿨나

  • 반복되던 문장은 지우거나 캐릭터성이 있는 여러 문장 ("마, 내 말 함 들어 봐라." 같은) 으로 골고루 바꿨다.
  • 문장 끝을 형태별로 나눠 "-데이", "-는 기라", "-아이가", "-래이", "-제" 같은 어미를 골고루 섞었고, "단디", "억수로", "우째", "그라믄" 같은 어휘도 바꿨다.
  • 의문문은 경상도 문법대로 의문사가 있으면 "-노/-고", 없으면 "-나/-가"로 맞췄다. (예: "색깔은 우떻노?", "가래가 나오나?")
  • 학습이 잘 됐는지 채점할 때 쓰는 데이터(검증용 데이터)도 같은 사투리로 바꿨다. 그래야 채점 점수가 "사투리를 얼마나 잘 배웠는가"를 제대로 보여 준다.
지표원본1차 개선2차 개선
사투리 어미로 끝나는 문장 비율21.5%46.1%74.5%
사투리 어휘가 들어간 답변 비율35.0%35.0%69.1%
한 문장이 가장 많이 반복된 횟수284 번258 번50 번
서로 다른 문장 수1,4151,7362,229

LoRA 는 학습된 데이터보다 과장해서 말하지 않는다. 데이터가 "살짝 사투리"면 모델도 "살짝 사투리"이고 같은 문장을 수백 번 보여 주면 그 문장만 따라 한다.

03. 학습 하이퍼파라미터 개선

데이터만의 문제는 아니었다. 2차 재학습에서는 데이터와 함께 학습 설정도 바꿨다. 학습 설정을 보니 학습이 제대로 일어나기 어려운 조건이 겹쳐 있었다. 하이퍼파라미터는 학습을 시작하기 전에 사람이 정해 주는 설정값이다.

파라미터이전이후이유
학습률(LR)3e-51.5e-4 (의료 1e-4)3e-5 는 모델 전체를 학습할 때 쓰는 작은 보폭이다. LoRA 는 고치는 부분이 작아서 보폭을 키워야 한다.
LoRA r816LoRA 가 모델을 고칠 수 있는 폭이다(아래 참고). 여유를 두고, 결합할 의료 LoRA 와 조건을 같게 맞추기 위해 16 으로 늘렸다.
LoRA alpha (배율)8 (배율 1.0)32 (배율 2.0)배운 내용이 출력에 반영되는 세기다. 너무 작으면 학습해도 티가 안 난다.
max_grad_norm0.31.0한 번에 고칠 수 있는 양의 최대치다. 0.3 은 너무 작아서, 가뜩이나 작은 보폭을 한 번 더 줄이고 있었다.
Epoch1최대 2 + Early Stopping충분히 학습하되, 외우기 시작하면 멈추고 가장 좋았던 시점으로 되돌린다.

참고: r(rank) 이 뜻하는 것

LoRA 는 원래 모델의 큰 가중치 행렬 W 를 직접 바꾸지 않는다. 대신 작은 행렬 두 개(A, B)를 곱한 변화량 ΔW 를 더한다.

W' = W + ΔW,  ΔW = B × A

여기서 r 은 두 작은 행렬 A, B 의 크기를 정하는 숫자다. r 이 클수록 원래 모델을 더 여러 방향으로 고칠 수 있다.

  • r=8: LoRA 를 붙인 가중치 행렬마다 최대 8 가지 방향으로만 모델을 고칠 수 있다.
  • r=16: 최대 16 가지 방향으로 고칠 수 있다.

비유하면 원래 모델이라는 그림에 덧칠할 때 쓸 수 있는 물감의 색 수다. 색이 많을수록 더 다양한 변화를 표현할 수 있다. 다만 말투 같은 변화는 r=8 로도 충분한 경우가 많고, 이번에는 학습률, 배율, 제한, 학습 시간을 함께 바꿨기 때문에 r 을 늘린 효과만 따로 확인하지는 않았다.

정리하면 작은 보폭, 작은 배율, 강한 제한, 짧은 학습이라는 네 겹의 브레이크를 밟고 있었던 셈이다. 이걸 풀고 나서야 학습 효과가 눈에 보이기 시작했다.

한 가지 흥미로운 점이 있었다. 학습을 500 번(step) 진행하도록 했는데, 200 번째에서 이미 채점 점수가 가장 좋았고 그 뒤로는 오히려 나빠졌다. 데이터가 단조로워서 금방 외워 버렸다는 뜻이다. 이건 설정을 바꿔서는 해결할 수 없는 데이터의 한계다.

참고로 2차 개선부터는 평가할 때의 설정도 두 가지 바꿨다. 첫째, 같은 말을 반복하지 못하게 막는 기능(repetition_penalty)을 껐다. 이 기능이 "-데이" 같은 사투리 어미나 "1. 2. 3." 같은 목록 번호까지 막았기 때문이다. 둘째, 답변이 중간에 잘리지 않도록 최대 길이를 320 토큰으로 늘렸다. 그래서 01 의 결과와 그 뒤의 결과는 평가 조건이 조금 다르다.

2차 개선 후 질문 테스트)

며칠째 기침이 계속되고 밤에 더 심해집니다. 열은 없는데 어떤 점을 확인해야 하나요?
구성응답
1차 캐릭터 LoRA 단독며칠째 계속되면 감기인지 다른 원인이 있는지 확인해 봐야제. 증상이 심해지면 진료를 받아야제.
2차 캐릭터 LoRA 단독기침이 며칠째고 밤에 더 심하믄 무조건 대충 넘길 일이 아이다. 열은 없는데도 사람마다 증상이 다르제. 상태가 우째 바뀌는지부터 살펴보고, 이상한 기 나오믄 의료진과 상의해 봐래이.

1차에서는 거의 모든 문장이 "~해야제"로 끝났는데, 2차에서는 "~아이다", "~제", "~봐래이" 같은 어미와 "우째", "이상한 기" 같은 어휘가 섞이면서 말투가 훨씬 다양해졌다. 캐릭터 LoRA 단독으로는 개선이 확실히 보였기 때문에, 다음으로 의료 LoRA 를 손본 뒤 다시 결합해 보기로 했다.

04. 의료 LoRA 학습 데이터 개선

01 의 테스트에서 의료 LoRA 단독도 질문 없이 "의사의 진단을 받아보라"로 끝나는 것을 확인했다. 그래서 의료 데이터도 다시 들여다봤다.

사용한 데이터(squarelike/ko_medical_chat, 3038 개 대화) 는 영어 의료 상담 데이터를 GPT 로 한국어 대화로 바꾼 것이라 변환 과정에서 발생한 어색한 번역의 흔적이 꽤 남아 있었다.

문제실측처리
의사 답변이 중간에 잘려 두 턴으로 나뉨 ("…진료도 도" + "도움이 될…")599 개 대화 (19.7%)기존 코드는 이런 대화를 통째로 버리고 있었다. 이어 붙여서 살렸다.
구체적인 약 용량 처방 ("○○ 120 mg 를 매일 한 번씩 복용")의사 답변의 1.5%해당 문장만 "용량은 진료 후 의사나 약사와 상의"로 바꿨다.
"Chat Doctor 에 오신 것을 환영합니다" 같은 원본 흔적의사 답변의 2.6%문장을 제거했다.
"끊긴 부분부터 계속 작성하라" 같은 GPT 지시문30 문장문장을 제거했다.
질문 목록 형태의 문진거의 없음증상 42 종으로 목록형 문진 658 개를 만들어 추가했다.

마지막 항목이 특히 중요했다. 원본은 "한 번에 질문 하나" 구조라서, 의료 LoRA 가 질문 목록을 만들지 못했던 것도 당연했다. 정리 후 학습 샘플은 9,700 개에서 12,886 개로 늘었고, 하이퍼파라미터도 캐릭터 LoRA 와 같은 r=16 / alpha=32 로 맞췄다.

개선 후 질문 테스트)

며칠째 기침이 계속되고 밤에 더 심해집니다. 열은 없는데 어떤 점을 확인해야 하나요?
구성응답
개선 전 의료 LoRA기침이 계속되고 밤에 더 심해진다면, 감기나 인플루엔자 같은 바이러스 감염일 수 있습니다. 그러나 다른 원인도 있을 수 있으므로, 의사의 진단을 받아보는 것이 좋습니다.
개선 후 의료 LoRA증상의 원인을 좁히기 위해 다음을 확인하겠습니다.
1. 기침은 언제부터 있었나요?
2. 가래가 나오나요? 나온다면 색깔은 어떤가요?
3. 최근 감기에 걸렸거나 주변에 기침하는 사람이 있었나요?
4. 최근 새로 먹기 시작한 약이 있나요?
이 내용을 알려 주시면 다음 단계를 함께 정하겠습니다.
숨이 몹시 차거나 피가 섞인 가래, 가슴 통증이 나타나면 기다리지 말고 즉시 진료를 받으세요.

의료 LoRA 단독으로 질문 목록과 위험 신호 안내까지 하게 됐다.

05. 결합이 실패하는 원인 분석

두 LoRA 를 각각 개선했으니 이번엔 결합이 잘 될 거라 기대했다. 결과는 그렇지 않았다.

구성 (1.0 : 1.0)응답
캐릭터 2차 개선 + 의료 개선기침이 오래가믄 바이러스나 알레르기성 원인도 있을 수 있제. 가만 있어 봐라, 내가 하나씩 풀어 주께.

"하나씩 풀어 주께"라고 약속하고는 그대로 끝나 버렸다. 질문 목록도, 위험 신호 안내도 없다.

1) 두 LoRA 의 크기와 방향을 재 봤다

두 LoRA 가 원래 모델을 얼마나 세게, 그리고 어느 쪽으로 바꾸는지 재 봤다.

원래 모델을 지도 위의 한 점이라고 생각하면, LoRA 는 그 점을 어딘가로 미는 화살표다. 화살표의 길이는 얼마나 세게 미는지(크기), 화살표가 가리키는 쪽은 어디로 미는지(방향)다. 두 LoRA 를 합친다는 건 이 화살표 두 개를 이어 붙이는 것과 같다.

  • 같은 쪽을 가리키면 더 멀리 간다. 서로를 키워 준다.
  • 반대쪽을 가리키면 제자리로 돌아온다. 서로를 지운다.
  • 직각이면 각자 밀고 싶은 만큼 그대로 간다. 서로 방해하지 않는다.
궁금했던 것측정 결과뜻
누가 더 세게 미나?캐릭터 화살표의 길이가 의료의 약 0.55 배캐릭터 LoRA 가 훨씬 약하게 민다
같은 쪽을 가리키나?거의 직각 (cos 평균 0.02)두 LoRA 는 서로 상관없는 쪽으로 민다
서로 지우는 곳이 있나?반대쪽을 가리키는 곳은 5% 뿐서로 지우는 일은 거의 없다

측정 방법

LoRA 가 붙은 238 개 가중치 행렬마다 두 LoRA 가 더하는 변화량을 계산해서 길이와 각도를 비교했다. 각도는 cos 으로 쟀는데, 1 이면 같은 방향, 0 이면 직각, -1 이면 반대 방향이다.

크기는 절반이고 서로 방해하지도 않는데, 결과는 캐릭터 LoRA 가 완전히 장악했다. 원인은 응답 형식에 있었다.

캐릭터 LoRA 는 "한마디 하고 짧게 끝내기"를, 의료 LoRA 는 "질문 목록을 차근차근 나열하기"를 배웠다. 합치면 캐릭터 LoRA 가 답변을 어떻게 시작하고 언제 끝낼지를 정해 버린다. 그래서 의료 LoRA 의 질문 목록은 시작도 못 하고 끝난다.

2) 가중치를 바꿔 봤다

캐릭터 : 의료결과
1.0 : 1.0 / 1.0 : 1.2캐릭터가 장악. 짧은 사투리 두 문장
0.9 : 1.2 / 0.85 : 1.2위험 신호 한 문장만 말하고 끝 (표준어)
0.8 : 1.0둘 다 사라짐. 표준어 한 문장
0.8 : 1.3질문 목록 + 위험 신호. 사투리는 "-믄" 정도만 남음
0.6 : 1.0 / 0.6 : 1.3의료가 장악. 의료 LoRA 단독과 거의 같음

가중치를 조금씩 바꾸면 결과도 조금씩 섞일 줄 알았는데, 실제로는 어느 순간 한쪽으로 확 넘어갔다. 마치 스위치 같았다. 사투리와 질문 목록이 함께 나오는 구간은 아주 좁았고, 그마저도 질문이 바뀌면 흔들렸다. 가중치 조절로는 해결이 안 된다는 결론을 내렸다.

06. 캐릭터 LoRA 학습 데이터 3차 개선

원인이 형식 싸움이라면, 캐릭터 LoRA 에게도 의료 질문에 답하는 형식을 가르치면 된다.

캐릭터 학습 데이터에 의료 LoRA 와 같은 구조 (도입 → 질문 목록 → 위험 신호 안내)의 사투리 문진 665 개를 추가했다.

처음에는 기존 존댓말 답변을 사투리로 변환해 봤는데 "말씀하신 … 기라" 처럼 높임말과 사투리가 뒤섞여서, 처음부터 사투리로 만들었다.

추가한 데이터는 다음과 같은 형태다.

Q. 일어날 때 핑 도는 느낌이 들어요. 문진하듯이 필요한 질문을 해 주세요.

가만 보자, 원인을 좁힐라믄 이거부터 알아야 된데이.
1. 어지러움은 언제부터 시작됐노?
2. 메스꺼움이나 구토가 있나?
3. 주변이 빙빙 도는 느낌이가, 아니믄 쓰러질 것 같은 느낌이가?
4. 실제로 쓰러지거나 넘어진 적이 있나?
5. 지금 묵는 약이 있나?
이거 듣고 나서 우째 할지 같이 정하자.
근데 의식을 잃음, 말이 어눌해짐, 한쪽 팔다리 마비, 심한 두통이 있으믄 그때는 참지 말고 바로 병원 가래이.

위 (05. 결합이 실패하는 원인 분석) 에서 봤던 "내가 하나씩 풀어 주께"처럼 약속만 하고 끝나는 답변도 학습 데이터에 91 개 있어서 함께 정리했다. 의료 문진 데이터는 캐릭터 학습 데이터 전체의 15% 정도로 맞췄다.

개선 후 질문 테스트)

(가중치 1.0 : 1.0)

며칠째 기침이 계속되고 밤에 더 심해집니다. 열은 없는데 어떤 점을 확인해야 하나요?
구성응답
이전 캐릭터 + 의료기침이 오래가믄 바이러스나 알레르기성 원인도 있을 수 있제. 가만 있어 봐라, 내가 하나씩 풀어 주께.
형식을 맞춘 캐릭터 + 의료말씀하신 것만으로 원인을 단정할 수는 없습니다. 먼저 이거를 확인해 보겠습니다.
1. 기침은 언제부터 있었노?
2. 숨이 차거나 누우믄 답답한가?
3. 가래가 나오나? 나온다믄 색깔은 우떻게 됐노?
4. 같은 계절에도 퍼지거나 반복되는 편이?
5. 최근 새로 먹기 시작한 약이 있나?
이거 알려 주믄 다음 단계를 같이 보자.
다만 숨이 몹시 차거나 피가 섞인 가래, 가슴 통증이 있으믄 기다리지 말고 바로 병원이나 응급실 가래이.

기본 비율 1.0 : 1.0 에서 처음으로 사투리, 질문 목록, 위험 신호 안내가 함께 나왔다. 첫 문장이 존댓말이고 4 번 질문이 어색한 것처럼 다듬어지지 않은 부분은 있지만, 같은 질문과 같은 비율에서 결과가 확연히 달라졌다.

두 LoRA 가 서로를 보완하는 모습도 보였다. "두통이 있어요. 확인할 질문을 6개 알려주세요."라고 물었을 때, 캐릭터 LoRA 와 의료 LoRA 는 각각 단독으로는 약 질문을 반복해서 6 개를 겨우 채웠다. 그런데 결합하면 시작 시점, 동반 증상, 일상생활 지장, 통증 느낌, 시간대, 복용 약까지 서로 다른 질문 6 개가 나왔다.

07. 처음 보는 질문으로 검증하기

여기서 끝내도 되나 싶었는데, 한 가지가 걸렸다. 캐릭터 LoRA 에 넣은 사투리 문진과 의료 LoRA 에 넣은 목록형 문진은 같은 증상 42 종으로 만들었다. 그러니 기침처럼 이미 배운 증상에서 잘 나온 결과는 결합이 잘 된 것인지, 둘이 같은 내용을 외운 것인지 구분할 수 없다.

그래서 "두 LoRA 가 배우지 않은 증상"으로 다시 확인해 봤다.

개선 후 질문 테스트)

뜨거운 물에 손등을 데었는데 물집이 생겼어요. 어떤 점을 확인해야 하나요?
구성질문 목록판단
의료 LoRA 단독물집은 언제 생겼나요? / 물집이 터졌나요? / 주변이 붓거나 붉게 변했나요? / 이전에 화상을 입은 적이 있나요?화상에 맞음
캐릭터 LoRA 단독손등이 얼마나 데긴 느낌이? / 피부가 얇아지거나 변색된 부분이 있나? / 비슷한 증상을 전에도 겪은 적이 있나?대체로 맞음
결합 1.0 : 1.0손가락 모양이 변했나? / 같은 손가락이 반복적으로 붓고 낫다 사라지나? / 같은 손가락을 자주 접질리나?화상과 무관
결합 0.6 : 1.0손가락이 저리거나 감각이 이상한가요? / 물집이 터졌거나 붓고 붉어진가요? / …사투리는 사라지고 손가락 질문은 남음

각자 따로 쓰면 화상에 맞게 답하는데, 합쳤을 때만 손가락 관절을 묻는 엉뚱한 질문이 나왔다. 학습한 42 개 증상 중 손목, 발목 항목에 있던 질문을 "손가락"으로 바꿔 쓴 것이다. "손등"이라는 단어를 단서로 가장 가까운 증상의 내용을 꺼내 온 것으로 보인다. 신체 부위 단어가 없는 딸꾹질 질문에서는 이런 현상이 나타나지 않았다.

[결합 1.0 : 1.0]
말씀하신 내용만으로 원인을 단정할 수는 없습니다. 먼저 이거를 확인해 보자.
1. 손가락 모양이 변했나?
2. 같은 손가락이 반복적으로 붓고 낫다 사라지나?
3. 새로 생긴 증상인가, 오래된 건지?
4. 같은 손가락을 자주 접질리나?
5. 요새 새로 먹기 시작한 약이 있나?
이 내용을 알려 주믄 다음 단계를 같이 보자. 10분 넘게 누우믄 손가락 모양이 붓고 변하는 경우가 보이믄 기다리지 말고 퍼뜩진료 받아래이.

마지막 위험 신호 문장도 "10분 넘게 누우믄 손가락 모양이…"처럼 깨져 있다.

두 LoRA 의 방향도 다시 재 봤다.

지표형식을 맞추기 전형식을 맞춘 후
방향 유사도 (cos 평균)0.0240.055
서로 반대 방향인 행렬 비율5%0%

같은 증상 데이터를 함께 배운 뒤로 두 LoRA 가 모든 행렬에서 조금씩 같은 쪽을 향하게 됐다.

다만 이 숫자는 아주 작아서 이것만으로 결론을 내릴 수는 없다. 그래서 가중치를 0.6 : 1.0 으로 낮춘 결과와 함께 살펴봤다.

캐릭터 LoRA 에만 있는 사투리는 가중치를 낮추자 바로 사라졌는데, 두 LoRA 가 똑같이 배운 손목, 발목 질문은 가중치를 낮춰도 남았다. 그것도 "같은 발목을 자주 접질리나요?"가 "같은 손가락을 자주 접질리나?"로 바뀌는 식으로, 질문 속 "손등"에 맞춰 신체 부위만 바꿔 가며 나왔다.

이 해석이 맞는지 확인하기 위해 데이터를 한 번 더 바꿔 봤다.

08. 캐릭터 LoRA 학습 데이터 4차 개선

07 의 해석이 맞다면, 두 LoRA 가 같은 내용을 배우지 않게 하면 엉뚱한 질문이 사라져야 한다. 그래서 캐릭터 LoRA 의 의료 문진을 의료 LoRA 와 겹치지 않는 증상으로 다시 만들어 재학습해 봤다.

1) 무엇을 바꿨나

항목3차4차
증상 목록의료 LoRA 와 같은 42 종겹치지 않는 42 종 (탈모, 생리통, 다래끼, 코골이 등)
질문 문장의료 LoRA 와 같은 질문 (말투만 사투리)같은 문장 0 개
위험 신호 안내여러 표현이 섞임"미루지 말고 바로 병원이나 응급실 가래이" 하나로 통일
답변 형식과 비중도입 → 질문 목록 → 위험 신호, 전체의 15%같음
학습 설정r=16 / alpha=32, LR 1.5e-4같음

형식과 비중, 학습 설정을 모두 3차와 같게 맞춰서, 결과가 달라진다면 "내용을 나눈 것" 때문이라고 볼 수 있게 했다.

2) 평가 질문을 먼저 고정했다

결과를 보고 유리한 질문을 고르지 않도록 평가 질문 17 개를 먼저 정했고, 이 질문들은 학습 데이터에서 모두 뺐다.

  • A. 의료 LoRA 만 배운 증상 4 개
    :
    기침, 두통, 어지럼증
  • B. 두 LoRA 모두 배우지 않은 증상 10 개
    :
    화상, 발뒤꿈치, 딸꾹질, 통풍, 이명, 대상포진, 벌 쏘임, 손톱 주변 등
  • C. 일상 질문 3 개 (결과를 다루지 않았다)

같은 세션에서 3차와 4차 캐릭터 LoRA 를 번갈아 끼워 가며, 의료 LoRA 와 1.0 : 1.0 으로 결합한 결과를 A, B 의 의료 질문 14 개로 비교했다.

3) 결과: 엉뚱한 질문은 줄었지만, 질문 목록이 무너졌다

4차 개선 후 질문 테스트)

뜨거운 물에 손등을 데었는데 물집이 생겼어요. 어떤 점을 확인해야 하나요?
구성 (1.0 : 1.0)응답
3차 캐릭터 + 의료1. 손가락 모양이 변했나?
2. 같은 손가락이 반복적으로 붓고 낫다 사라지나?
… (화상과 무관)
4차 캐릭터 + 의료1. 손등 물집은 처음 시작된 기 언제고?
2. 물집이 커지거나 아프나?
… (화상에 맞음)

질문 목록이 제대로 나온 경우에는 질문이 증상에 더 맞게 확실히 바뀌었다.

벌에 쏘였다는 질문에 3차는 "발진이 퍼지고 있나?"처럼 다른 증상의 질문을 했는데, 4차는 숨이 차거나 쌕쌕거리는지를 물었다. 손톱 주변이 붓는다는 질문에서도 붓기가 커지거나 퍼지는지를 물었다.

3차에서는 두 LoRA 가 같은 증상 목록을 배웠다. 그래서 처음 보는 증상이 들어오면 둘이 함께 같은 "비슷한 증상"의 질문을 떠올렸다. 4차에서는 캐릭터 LoRA 가 다른 증상으로 배웠다. 그래서 캐릭터 LoRA 는 말투와 형식만 보태고, 어떤 질문을 할지는 의료 LoRA 에 더 맡기게 된 것으로 보인다.

다만 템플릿(학습 때 외운 정해진 질문 문장)이 사라진 것은 아니다. "숨이 차거나 쌕쌕거리나?"도 의료 LoRA 가 배운 질문이다. 템플릿을 고르는 기준이 겉에 보이는 단어에서 증상의 의미 쪽으로 옮겨 간 것에 가깝다.

3차가 엉뚱한 질문을 한 원인도 확인했다. 같은 화상 상황에서 신체 부위 단어 하나만 바꿔서 물어봤다.

  • "화상을 입어서 물집이 생겼어요" → 3차 결합 모델도, 의료 LoRA 단독도 화상 질문을 했다.
  • "뜨거운 물에 배를 데었는데 물집이 생겼어요" → 3차 결합 모델은 변비나 설사를 묻는 복통 질문을 했고, 의료 LoRA 단독도 "배가 아프거나 부어있나요?"라고 물었다.

상황은 같은데 "배"라는 단어 하나에 답이 바뀌었다. 두 LoRA 가 배운 증상 목록에 "복통" 항목이 있어서, "배"가 나오면 복통 질문을 하도록 학습된 것이다. 손등 화상에 손가락 질문을 한 것도 같은 이유다. 의료 LoRA 를 혼자 썼을 때도 같은 일이 생겼다. 그러니 이건 결합의 문제가 아니라, 증상 목록으로 만든 학습 데이터의 한계다. 결합은 이 한계를 더 자주 드러나게 했을 뿐이다.

문제는 다른 곳에서 터졌다. 4차 결합 모델은 의료 질문 14 개 중 6 개에서 질문 목록 없이 한 문장으로 끝나 버렸다.

4차 개선 후 질문 테스트)

며칠째 기침이 계속되고 밤에 더 심해집니다. 열은 없는데 어떤 점을 확인해야 하나요?
구성 (1.0 : 1.0)응답
3차 캐릭터 + 의료사투리 질문 목록 5 개 + 위험 신호 안내
4차 캐릭터 + 의료증상이 언제부터 그랬나요?
항목3차 + 의료4차 + 의료
의료 LoRA 보강 데이터와 닮은 질문 수 (처음 보는 증상, 평균)0.8 개0.5 개
질문 수 (처음 보는 증상, 평균)3.9 개2.2 개
위험 신호 안내 (처음 보는 증상)70%50%
한 문장으로 무너진 질문0 / 146 / 14

4) 왜 무너졌을까

단서는 의료 LoRA 단독 결과에 있었다. "아침마다 어지럽고 구토는 없습니다. 확인할 것을 물어봐 주세요"라는 질문에 의료 LoRA 단독도 "어지러움은 언제부터 시작되었나요?" 한 문장만 답했다. 4차 결합 모델이 무너진 모양과 똑같다.

의료 LoRA 에는 답하는 방식이 두 가지 섞여 있다. 원본 대화 3,000 개에서 온 "한 번에 질문 하나" 방식이 약 90% 이고, 04 에서 추가한 "질문 목록" 방식이 약 10% 다.

  • 3차 캐릭터 개선: 캐릭터 LoRA 가 의료 LoRA 의 목록형 문진과 같은 내용을 배웠다. 합치면 둘이 함께 "질문 목록" 방식을 밀어 줘서, 적은 쪽인 목록 방식이 이겼다.
  • 4차 캐릭터 개선: 내용을 나누자 캐릭터 LoRA 가 목록 방식을 함께 밀어 주던 힘이 사라졌다. 그러자 많은 쪽인 "질문 하나" 방식이 이기는 경우가 생겼다.

질문 개수를 정해 준 경우("질문 6 개", "네 개")에는 4 개 중 3 개가 목록을 유지했고, 정하지 않은 경우에는 10 개 중 5 개가 무너졌다. 질문 안에 목록으로 답하라는 신호가 있으면 버틴다는 뜻이라 위 해석과도 맞는다.

결국 3차에서 두 LoRA 가 공유한 내용은 엉뚱한 질문을 끌어오는 부작용도 있었지만, 동시에 의료 LoRA 를 목록 방식으로 끌어내는 스위치 역할도 하고 있었다. 내용을 나누면 해결될 거라던 예상은 반만 맞은 셈이다. 또 07 에서는 "두 LoRA 가 함께 배운 내용은 합치면 더 강해진다"고 해석했는데, 질문 10 개로 다시 확인해 보니 일부 질문에서만 그랬다.

09. 결론

한 줄로 정리하면, 두 LoRA 를 합칠 때 중요한 건 얼마나 섞느냐(가중치)가 아니라 무엇을 가르쳤느냐(데이터)였다.

이번 포스트에서 확인한 내용을 세 가지로 정리하면 다음과 같다.

1) 캐릭터 LoRA 는 네 번의 재학습으로 말투를 얻었고, 의료 질문에 답하는 형식까지 배웠다.

차수바꾼 것결과
1차표현을 과장한 학습 데이터사투리가 생겼지만 거의 모든 문장이 "~해야제"로 끝날 만큼 단조로웠다. 결합하면 한두 문장으로 짧아졌다.
2차반복 문장 제거, 사투리 비율 46% → 74%, 학습 하이퍼파라미터 개선단독으로는 사투리가 뚜렷해졌다. 하지만 결합하면 "내가 하나씩 풀어 주께"라고 약속만 하고 끝났다.
3차의료 LoRA 와 같은 형식의 사투리 문진 추가1:1 결합에서 처음으로 사투리, 질문 목록, 위험 신호 안내가 함께 나왔다. 단, 학습한 증상에서만이다.
4차의료 문진의 증상과 질문을 의료 LoRA 와 겹치지 않게다른 증상의 질문을 끌어오는 일은 줄었지만, 결합하면 의료 질문 14 개 중 6 개가 한 문장으로 무너졌다.

결국 LoRA 는 데이터보다 과장해서 말하지 않았다. 학습 설정을 바꾼 것도 도움이 됐지만 말투가 달라진 건 데이터를 고쳤을 때였다. 2차에서 500 step 중 200 step 만에 가장 좋은 점수가 나온 것도, 데이터가 단조로우면 금방 외워 버린다는 걸 보여 준다.

2) 의료 LoRA 는 데이터를 정리하자 스스로 문진하게 됐다.

GPT 로 번역된 원본 데이터에서 잘려서 버려지던 대화 20% 를 살리고, 약 용량 처방과 번역 흔적을 지우고, 질문 목록 형태의 문진을 추가했다. 그 결과 질문 없이 "의사의 진단을 받아보라" 로 끝나던 답변이, 질문 목록과 위험 신호 안내로 바뀌었다.

학습하지 않은 화상 질문에도 물집이 터졌는지, 주변이 붉게 변했는지처럼 맞는 질문을 했다. 다만 배운 증상에서 질문을 6 개처럼 많이 요구하면 같은 질문을 반복해 개수를 채우는 한계는 남았다.

또 하나 알게 된 점은 의료 LoRA 안에 답변 방식이 두 가지 섞여 있다는 것이다. 원본 대화에서 온 "한 번에 질문 하나"(약 90%)와 보강 데이터에서 온 "질문 목록"(약 10%)이다. 단독으로는 대부분 목록으로 답했지만, 이 섞임이 결합 결과를 흔드는 원인이 됐다.

3) 결합이 잘 안 됐던 이유는 가중치가 아니라 데이터에 있었다.

  • 서로 지우는 문제는 아니었다. 두 LoRA 는 거의 직각 방향으로 모델을 바꾸고 있어서, 더한다고 서로 상쇄되지 않았다.
  • 문제는 답변 형식 싸움이었다. 캐릭터 LoRA 는 크기가 의료 LoRA 의 절반인데도 답변을 어떻게 시작하고 언제 끝낼지를 정하고 있었다. 가중치를 바꾸면 결과가 섞이지 않고 스위치처럼 한쪽으로 넘어갔다.
  • 형식을 맞추자 학습한 증상에서는 합쳐졌다. 캐릭터 LoRA 에도 같은 형식의 사투리 문진을 가르치니 두 LoRA 가 형식을 두고 싸우지 않았다.
  • 같은 내용을 공유하면 엉뚱한 질문이 끼어들었다. 처음 보는 화상 질문에 손목, 발목 질문을 "손가락"으로 바꿔 답하는 식이었고, 질문 속 신체 부위 단어가 단서가 됐다.
  • 내용을 나누자 이번엔 질문 목록이 무너졌다. 공유한 내용이 의료 LoRA 를 목록 방식으로 끌어내는 스위치 역할도 하고 있었기 때문이다.

정리하면, LoRA 결합의 결과는 각 LoRA 가 무엇을 배웠는지만으로 정해지지 않았다. 함께 결합한 LoRA 가 어떤 답변 방식을 끌어내느냐에 따라서도 달라졌다. 그래서 결합할 LoRA 는 데이터 안에 답변 방식이 섞이지 않도록 한 가지 방식으로 맞춰야 하고, 그 결과는 반드시 학습하지 않은 질문으로 확인해야 한다.