응용 AI 엔지니어가 평가 루프에서 실제로 사용하는 수학
요약
본 글은 AI 서비스의 성능 개선(평균 정확도 상승)이 반드시 제품 출시로 이어져서는 안 되며, 실패 사례 분석을 통해 위험도를 평가해야 함을 강조합니다. 특히 RAG 시스템에서는 최종 답변뿐 아니라 검색 단계 자체를 평가하는 것이 중요하며, 이를 위해 수학적 지식과 체계적인 평가 루프 구축이 필요하다고 설명합니다.
핵심 포인트
- AI 서비스는 평균 개선만으로 출시해서는 안 되며 위험도 분석이 필수입니다.
- 평가 시에는 쿼리, 시나리오, 출처 식별자 등 상세한 실패 비용을 정의해야 합니다.
- RAG 시스템은 최종 답변 외에 검색(Retrieval) 단계의 성능 지표(예: recall@k)를 측정해야 합니다.
- 임베딩과 유사도 측정법이 단순한 비교 규칙임을 이해하는 선형대수학적 접근이 필요합니다.
한 팀이 두 가지 버전의 AI 서비스를 비교합니다. 평균 정확도가 82%에서 86%로 상승했습니다. 새 버전이 더 좋아 보이므로, 이를 출시하는 것이 당연한 결정처럼 보입니다.
그러자 한 엔지니어가 실패 사례를 유형별로 분리해 봅니다. 시스템은 이제 간단한 질문에 대해서는 실수를 덜 하지만, 청구(billing)나 계약과 관련된 질문의 경우 출처 없이 자신 있게 답변할 가능성이 두 배가 됩니다. 평균은 개선되었지만 제품 위험도는 증가했습니다.
이 지점에서 응용 AI 엔지니어에게 수학이 필요합니다. 이것은 입학 시험처럼 필요한 것도 아니고, 대학 과정을 몇 주 만에 압축하려는 시도도 아닙니다. 수학은 시스템의 동작을 공학적 결정(엔지니어링 결정)과 연결하기 때문에 유용합니다: 새 버전을 출시할 것인지, 더 많은 작업이 필요하다고 판단하여 되돌릴 것인지, 아니면 특정 시나리오를 제한할 것인지를 결정하는 것입니다.
시작하는 가장 실용적인 방법은 작은 평가 루프(evaluation loop)를 구축하는 것입니다. 이 루프의 모든 공식은 하나의 공학적 질문에 답해야 합니다.
먼저 평가 단위를 정의하라
약한 테스트 세트(weak test set)는 종종 몇 쌍의 쿼리 -> 좋은 답변 외에는 거의 포함하고 있지 않습니다. 이것만으로는 진단하기에 충분하지 않습니다.
각 평가 사례마다 다음을 최소한 저장해야 합니다:
- 사용자의 쿼리;
- 시나리오 또는 세그먼트;
- 시스템이 검색해야 할 출처의 식별자;
- 허용 가능한 동작: 답변, 명확화(clarify), 또는 거부(refuse);
- 결과가 인간 검토를 필요로 하는지 여부;
- 이 특정 실패의 비용.
단순한 Python 딕셔너리만으로 첫 번째 버전을 표현하기에 충분합니다:
case = {
"query": "결제 후 청구 주체(billing entity)를 변경할 수 있나요?",
"segment": "billing",
...
failure_cost의 값은 보편적인 수학적 진리가 아닙니다. 그것은 명시적인 팀 결정입니다. 낮은 위험도의 참고 답변에서의 실수는 1점의 비용이 들 수 있습니다. 결제에 대한 뒷받침되지 않은 주장은 5점의 비용이 들 수 있습니다. 돌이킬 수 없는 결과를 초래하는 행동은 다른 점수로 줄여지기보다는 별도의 정책으로 차단되어야 합니다.
이러한 라벨링(labeling) 없이는, 메트릭은 소유주가 없는 숫자가 되어버립니다.
최종 답변과 분리하여 검색을 평가하라
RAG 시스템에서 잘못된 답변은 여러 원인을 가질 수 있습니다. 필요한 문서가 인덱스에 들어가지 않았을 수도 있고, 검색(Retrieval)이 그것을 상위권에 배치하지 못했을 수도 있습니다. 모델이 올바른 출처를 받았지만 무시했을 수도 있으며, 또는 그 출처 자체가 구식이거나 쓸모없었을 수도 있습니다.
최종 답변만 측정한다면, 이러한 실패들은 하나의 결과로 뭉개집니다.
유용한 첫 번째 검색 지표는 recall@k입니다. 이는 필요한 출처 중 처음 k개의 결과에 나타나는 비율을 의미합니다.
def recall_at_k(cases, retrieved_by_case, k):
recalls = []
...
만약 recall@5가 낮다면, 답변 생성 프롬프트(answer-generation prompt)를 변경하는 것은 성급합니다. 먼저 문서 분할(document splitting), 메타데이터(metadata), 필터(filters), 임베딩(embeddings), 그리고 인덱스 신선도(index freshness)를 확인해야 합니다.
이 지점에서 선형대수학(linear algebra)이 실용적이 됩니다. 엔지니어는 임베딩(embedding)이 벡터라는 것, 그리고 코사인 유사도(cosine similarity)나 다른 거리 측정법(distance measure)이 단지 비교 규칙일 뿐이라는 것을 이해해야 합니다. 높은 유사도가 문서가 질문에 답한다는 것을 증명하지 않습니다. 그것은 단지 선택된 표현(representation)과 측정법이 객체들을 유사하다고 간주한다는 것만을 의미할 뿐입니다.
평균 정확도에 실패 유형 추가하기
시스템이 들어오는 요청을 분류하고 해당 부서로 라우팅(route)한다고 가정해 봅시다. 클래스 불균형(imbalanced classes)이 있거나, 실수마다 결과가 다르다면 정확도(Accuracy)만으로는 충분하지 않습니다.
최소한 다음 사항들을 구분해야 합니다:
- 거짓 양성 (false positive): 시스템이 증거가 충분하지 않은 시나리오를 선택하는 경우;
- 놓친 사례 (missed case): 필요한 시나리오를 인식하지 못하는 경우;
- 지원되지 않는 답변 (unsupported answer);
- 불필요한 거부 (unnecessary refusal): 안전하게 도울 수 있었음에도 불구하고 거부하는 경우;
- 사람에게 잘못 에스컬레이션(wrong escalation to a person)되는 경우.
이렇게 하면 올바른 결과의 비율뿐만 아니라 가중치 위험도(weighted risk)를 계산할 수 있습니다:
FAILURE_COST = {
"false_positive": 2,
"missed_case": 3,
...
프로세스 소유자(process owner)는 각 실패의 비용에 대해 합의해야 합니다. 이 공식이 비즈니스 결정을 내리는 것은 아닙니다. 단지 그 결정을 가시화하고 팀이 동일한 규칙을 사용하여 버전을 비교할 수 있게 해줄 뿐입니다.
평균을 신뢰하기 전에 세그먼트 검사하기
전체 지표(aggregate metric)는 테스트 세트에 쉬운 케이스가 많이 포함되어 있기 때문에 단순히 개선될 수 있습니다. 따라서 다음과 같은 몇 가지 의미 있는 세그먼트별로 결과를 분해하여 살펴보아야 합니다:
- 작업 유형(task type);
- 데이터 소스(data source);
- 언어(language);
- 신규 사용자 또는 재방문 사용자(new or returning user);
- 저위험 또는 민감한 시나리오(low-risk or sensitive scenario);
- 거절 유형(refusal type).
단순한 세그먼트별 계산만으로도 전체 지표 하나보다 더 많은 정보를 얻을 수 있습니다:
from collections import defaultdict
def accuracy_by_segment(results):
...
전체 결과가 개선되었음에도 불구하고 민감한 세그먼트에서 성능이 저하되었다면, 그 하락세(regression)를 논의의 핵심 동력으로 삼아야 합니다. 평균적인 수치가 팀이 사전에 합의한 안전 경계(safety boundary)를 무시해서는 안 됩니다.
신뢰도와 관찰된 품질 일치 여부 확인하기
또 다른 흔한 실수는 높은 신뢰도를 답변이 정확하다는 증거로 간주하는 것입니다.
더 나은 질문은 다음과 같습니다. 시스템이 0.8 근처의 신뢰도를 보고할 때, 실제로 그 경우의 약 80%가 맞는 것인가?
이를 검사하려면 답변들을 신뢰도 구간(confidence intervals)으로 그룹화하고, 평균적으로 보고된 신뢰도와 관찰된 정확한 결과 비율을 비교해야 합니다. 큰 격차는 낮은 보정성(poor calibration)을 나타냅니다.
보정성은 제품 규칙에 직접적인 영향을 미칩니다:
- 신뢰도가 낮을 경우, 시스템이 명확히 하는 질문(clarifying question)을 요청합니다;
- 민감한 시나리오에서는 결과가 전문가에게 전달됩니다;
- 뒷받침하는 소스 없이 답변할 수 없을 경우, 시스템이 답변을 거부합니다;
- 자동화된 조치는 추가적인 확인을 필요로 합니다.
오류 비용(cost of errors)과 분리하여 임계값(threshold)을 설정할 수는 없습니다. 한 제품에서는 불필요한 거절이 거의 무해하지만, 다른 제품에서는 그 제품의 핵심 기능을 파괴합니다.
작은 샘플이 큰 결론을 정당화하지 못한다
30개의 평가 케이스가 3가지 시연(demonstration)보다 낫지만, 여전히 실제 트래픽을 제대로 대표하지 못할 수 있습니다.
최소한의 규율은 간단합니다:
- 비교하는 두 버전 간에 테스트 세트를 변경하지 마십시오.
- 프롬프트나 규칙을 튜닝하는 데 사용되지 않은 별도의 케이스 세트를 유지하십시오.
- 개별적으로 검사하지 않고 세그먼트들을 결합하지 마십시오.
- 모델이 비결정적(nondeterministic)일 때는 불안정한 검사를 반복하십시오.
- 모든 중요한 프로덕션 실패 사례를 회귀 테스트 세트에 추가하십시오.
이 시점에서 엔지니어는 샘플, 평균(means), 분산(variance), 그리고 신뢰 구간(confidence intervals)을 이해하는 것에서 이점을 얻습니다. 목표는 더 인상적인 보고서를 만드는 것이 아닙니다. 작은 샘플에서의 무작위 움직임을 개선이라고 부르는 것을 피하는 것입니다.
첫 번째 평가 루프 구축하기
복잡한 플랫폼 없이도 유용한 첫 버전을 만들 수 있습니다:
- 실제 작업 유형에서 30개에서 50개의 케이스를 수집합니다.
- 예상 출처, 허용 가능한 동작(acceptable behavior), 세그먼트, 그리고 실패 비용을 레이블링합니다.
- 기준선(baseline)과 새로운 버전을 동일한 세트로 실행합니다.
- 검색(retrieval), 최종 출력, 거부(refusal), 에스컬레이션(escalation)을 개별적으로 측정합니다.
- 종합 지표(aggregate metric), 세그먼트, 가중 위험도(weighted risk), 그리고 보정(calibration)을 비교합니다.
- 가장 비용이 많이 드는 실패 사례를 수동으로 검토합니다.
- 릴리스 결정과 그 이유 및 한계를 함께 기록합니다.
이 루프는 추가적인 수학적 연구에 구체적인 맥락을 제공합니다. 검색에 실패했다면, 벡터(vectors), 거리 측정(distance measures), 그리고 순위 지정(ranking)으로 더 깊이 들어가십시오. 모델이 자신감 있게 틀렸다면, 확률(probability)과 보정(calibration)이 다음 단계가 됩니다. 결과가 실행 간에 상당히 다르면, 샘플링(sampling)과 가변성(variability)을 더 신중하게 연구하십시오.
첫 번째 루프 이후 무엇을 연구할 것인가
유용한 순서는 다음과 같을 수 있습니다:
- 벡터(vectors), 행렬(matrices), 내적(dot products), 그리고 정규화(normalization);
- 조건부 확률(conditional probability) 및 기본적인 확률적 추론(probabilistic reasoning);
- 정밀도(precision), 재현율(recall), F1, 그리고 순위 지정 지표(ranking metrics);
- 샘플(samples), 평균(means), 분산(variance), 그리고 신뢰 구간(confidence intervals);
- 손실 함수(loss functions) 및 최적화 기초(optimization fundamentals);
- 보정(calibration) 및 결정 임계값(decision thresholds).
이는 더 이상 추상적인 커리큘럼이 아닙니다. 각 주제는 엔지니어가 평가 루프에서 이미 관찰할 수 있는 실패 사례와 연결됩니다.
핵심 지점
응용 AI 엔지니어는 시스템을 제대로 측정하기 위해 완전한 수학 교육을 기다릴 필요가 없습니다.
먼저 평가 단위를 선택하고, 시스템의 단계를 분리하며, 실패 유형을 명명하고, 이를 결과와 연결하는 것부터 시작합니다. 수학은 더 이상 장벽 역할을 하지 않습니다. 대신 새로운 버전이 진정으로 왜 더 나은지, 또는 외관상 더 좋아 보이는 평균치가 출시를 정당화하지 못하는 이유를 설명하는 도구가 됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기