hyunsu blog

홈강좌LAYA 결정 모델 24편 중 5편째

학습 전에 먼저 잰다 — 기본 LAYA 는 우리 문의를 55% 맞혔다

목차 · 3
  1. 01평가 스크립트
  2. 02기본 모델의 점수
  3. 03실습 — 기준선을 먼저 재는 이유

학습시키기 전에 기본 모델이 내 일에서 몇 점인지부터 잰다. 평가용 고객 문의 200건으로 다국어 LAYA 를 재니 정확도 0.55 였다. 거의 모든 문의를 기술팀으로 보냈고, 틀릴 때도 평균 0.85 를 확신했다. 이 숫자가 기준선이 되어 8편부터 학습한 판마다 비교한다.

평가 데이터(tickets-eval.jsonl)는 다음 편에서 학습 데이터와 함께 만드는 200건이다. 학습에 쓰지 않는 표현으로만 만들었다. 미리 가져와 쓴다.

01 평가 스크립트

이 시리즈 내내 같은 스크립트로 잰다.

python
"""평가 세트(JSONL)로 체크포인트 하나를 잰다 — 팀 정확도·팀별 정확도·평균 확신·ECE·시간.

python evaluate.py base               # 학습 전 다국어 체크포인트
python evaluate.py ../checkpoints/v1  # 내가 학습한 체크포인트
"""
import json
import sys
import time
from collections import Counter

import numpy as np
import laya
from laya.common import ece_score

target = sys.argv[1]
eval_path = sys.argv[2] if len(sys.argv) > 2 else "tickets-eval.jsonl"

if target == "base":
    agent = laya.load("convaiinnovations/laya", subfolder="multilingual")
else:
    agent = laya.load(target)

cases = [json.loads(line) for line in open(eval_path, encoding="utf-8")]
correct, confidence, misses = [], [], Counter()
per_team = {}
start = time.time()
for case in cases:
    result = agent.predict(case["state"], case["questions"])
    team = result["answers"]["team"]
    gold = case["expected"]["team"]
    ok = team["choice"] == gold
    correct.append(ok)
    confidence.append(team["probabilities"][team["choice"]])
    per_team.setdefault(gold, []).append(ok)
    if not ok:
        misses[f"{gold} -> {team['choice']}"] += 1
elapsed = time.time() - start

correct = np.array(correct, dtype=float)
confidence = np.array(confidence)
print(f"model: {target}")
print(f"accuracy: {correct.mean():.3f} ({int(correct.sum())}/{len(cases)})")
for gold, oks in sorted(per_team.items()):
    print(f"  {gold:<9} {sum(oks) / len(oks):.3f} ({sum(oks)}/{len(oks)})")
print(f"mean confidence: {confidence.mean():.3f}")
print(f"ECE: {ece_score(confidence, correct, bins=10):.3f}")
print("most common mistakes:", ", ".join(f"{k} ×{v}" for k, v in misses.most_common(3)) or "none")
print(f"time: {elapsed / len(cases) * 1000:.0f} ms per case")
  • base 를 주면 공개된 다국어 체크포인트를, 폴더를 주면 내가 학습한 체크포인트를 읽는다(laya.load).
  • 평가 데이터의 질문 그대로 묻고, 팀 질문(team)의 답을 정답과 비교한다.
  • 정확도와 함께 팀별 정확도·평균 확신·ECE·자주 틀린 방향·한 건에 걸린 시간을 찍는다.

ECE(expected calibration error)는 확신과 실제 정답률의 차이다. 확신 0.9 라고 답한 것들이 실제로 90% 맞으면 0 에 가깝고, 실제로는 50% 만 맞으면 커진다(1편의 보정). laya.common.ece_score 를 그대로 썼다.

02 기본 모델의 점수

bash
python evaluate.py base
text
model: base
accuracy: 0.550 (110/200)
  account   0.222 (10/45)
  billing   0.397 (25/63)
  delivery  0.622 (28/45)
  technical 1.000 (47/47)
mean confidence: 0.846
ECE: 0.297
most common mistakes: billing -> technical ×34, account -> technical ×24, delivery -> technical ×17
time: 37 ms per case
그림 1.학습 전 기본 모델의 팀별 정확도
0.00.20.40.60.81.0accountbillingdeliverytechnicalaccount: 0.222billing: 0.397delivery: 0.622technical: 1.0000.2220.3970.6221.0000.00.20.40.60.81.0accountbillingdeliverytechnicalaccount: 0.222billing: 0.397delivery: 0.622technical: 1.0000.2220.3970.6221.000

technical 1.000 은 거의 모든 문의를 기술팀으로 보낸 쏠림이다

숫자로 보기
항목정확도
account0.222
billing0.397
delivery0.622
technical1.000

정확도 0.550 — 그런데 팀별로 보면

팀정확도
technical1.000
delivery0.622
billing0.397
account0.222

기술팀이 1.000 이다. 잘해서가 아니다. 끝에서 둘째 줄이 보여 주듯 결제 문의 34건, 계정 문의 24건, 배송 문의 17건을 기술팀으로 보냈다. 거의 모든 문의를 기술팀으로 보냈으니 기술팀은 다 맞을 수밖에 없다.

왜 그럴까. 기술팀 설명은 "앱·웹사이트 오류, 결제창 오류 포함" 이다. "결제" 라는 낱말이 들어 있고, "안 돼요"·"안 들어왔어요" 같은 불편 표현이 오류처럼 읽힌다. 사람이라면 "환불이 안 들어왔어요" 를 결제팀으로 보내겠지만, 기본 모델은 설명에 겹치는 낱말에 끌려갔다. 4편에서 본 대로 설명을 팀 이름만으로 줄이면 0.69 까지 오르지만, 그래도 회사 규칙은 가르칠 수 없다.

평균 확신 0.846, ECE 0.297

맞힌 것이 55% 인데 평균 0.85 를 확신한다. 틀린 답에도 높은 확신을 붙인다는 뜻이다. 이 상태로는 "확신이 낮으면 사람에게" 같은 규칙(9편)을 쓸 수 없다. 모델 카드도 배포된 체크포인트는 지나치게 확신하니 자기 데이터로 다시 보정하라고 적고 있다.

37ms

한 건에 37ms 다. 맥북의 GPU 로 판단 하나가 이만큼 걸린다. 평가 200건 전체도 10초가 안 걸리니, 판을 바꿀 때마다 부담 없이 다시 잴 수 있다.

03 실습 — 기준선을 먼저 재는 이유

  1. 학습할 가치가 있는지 안다. 기본 모델이 이미 0.95 라면 학습보다 질문 설계(4편)가 먼저다. 이번처럼 0.55 면 학습이 필요하다.
  2. 학습이 정말 좋아졌는지 판단할 기준이 생긴다. 학습 로그의 숫자는 믿을 수 없다(8편). 같은 평가 데이터로 잰 이 숫자만이 비교 대상이다.
  3. 어디가 문제인지 보인다. 팀별 정확도와 틀린 방향이 학습 데이터에서 무엇을 늘려야 할지 알려 준다.

자기 데이터로 평가 세트를 만들 때는 팀마다 최소 수십 건을 넣고, 학습 데이터와 겹치지 않게 먼저 떼어 둔다. 다음 편에서 학습 데이터를 만든다.