Nlptutti Manual
Nlptutti 0.0.0.12+

Nlptutti 한국어 STT 평가 매뉴얼

한 문장의 CER부터 여러 문장의 micro/macro 평가, 개체명 span의 Entity CER와 F1, 실제 치환·삭제·삽입 위치까지 한 흐름에서 확인하는 방법을 정리했다.

기존 사용자 호환성: rate_mode를 생략하면 과거 버전과 동일한 "normalized" 계산식이 적용된다. 표준 CER/WER는 rate_mode="standard"를 직접 적은 경우에만 사용된다. 유니코드 정규화도 기본적으로 켜지지 않는다.
동일 기존 기본 호출의 계산 결과
2 modes normalized 기본 / standard 선택
3.8+ 지원 Python 버전
Quick start

설치하고 첫 점수 확인하기

패키지명은 nlptutti다. 정답 문장을 첫 번째 인자, STT 결과를 두 번째 인자로 전달한다.

pip install -U nlptutti
import nlptutti as nt

result = nt.get_cer("아키택트", "아키택쳐")

print(result["cer"])            # 0.25
print(result["substitutions"])  # 1
print(result["deletions"])      # 0
print(result["insertions"])     # 0

점수는 낮을수록 좋다. 0.0은 완전 일치이며, 상세 편집 횟수는 같은 결과 딕셔너리에서 확인한다.

Compatibility

정규화 방식 선택

두 방식은 삽입 오류를 분모에 포함하는지가 다르다. 보고서나 논문에서 표준 CER/WER가 필요할 때만 standard를 명시한다.

normalized

(S + D + I) / (S + D + I + C)

Nlptutti의 역사적 기본값이다. 삽입을 분모에도 포함하므로 0과 1 사이에서 비교하기 쉽다.

standard

(S + D + I) / (S + D + C)

참조 길이를 분모로 사용한다. 삽입이 많으면 1보다 커질 수 있다.

같은 입력 비교

import nlptutti as nt

default_result = nt.get_cer("STEAM", "STREAM")
standard_result = nt.get_cer(
    "STEAM",
    "STREAM",
    rate_mode="standard",
)

print(default_result["cer"])   # 0.16666666666666666
print(standard_result["cer"])  # 0.2

기존 코드는 수정할 필요가 없다. 옵션을 생략한 호출은 계속 normalized로 계산된다. 한 프로젝트 안에서는 두 방식을 섞지 말고 결과와 함께 rate_mode를 기록한다.

Character

get_cer

문자 단위 오류율을 계산한다. 한국어 띄어쓰기 차이에 덜 민감하도록 공백은 항상 제거한다.

import nlptutti as nt

result = nt.get_cer(
    "제이 차 세계 대전",
    "제이차 세계대전",
)

print(result)
# {"cer": 0.0, "substitutions": 0, "deletions": 0, "insertions": 0}

띄어쓰기 자체도 오류로 평가해야 한다면 CER보다 별도 전처리 정책이나 WER를 함께 검토한다.

Word

get_wer

공백으로 구분한 단어 단위 오류율을 계산한다. 띄어쓰기 차이가 단어 경계를 바꾸면 점수에도 반영된다.

import nlptutti as nt

result = nt.get_wer(
    "오늘 날씨가 좋습니다",
    "오늘 정말 날씨가 좋습니다",
)

print(result["wer"])         # 0.25
print(result["insertions"])  # 1

표준 WER가 필요하면 같은 호출에 rate_mode="standard"를 추가한다.

Recognition

get_crr

문자 오류율의 보수인 1 - CER을 반환한다. 기존 호환성을 위해 소수점 둘째 자리로 반올림한다.

import nlptutti as nt

result = nt.get_crr("아키택트", "아키택쳐")

print(result["crr"])           # 0.75
print(result["substitutions"]) # 1

standard 모드에서는 CER가 1을 넘을 수 있으므로 CRR가 0보다 작아질 수도 있다. 0과 1 사이의 정답률이 필요하면 기본 normalized 모드를 사용한다.

Korean keyword

make_keyword_pattern

조사 결합과 키워드 내부의 불규칙한 띄어쓰기를 허용하는 정규식 패턴을 만든다.

import nlptutti as nt

pattern = nt.make_keyword_pattern("메리츠 화재")

print(bool(pattern.search("메리츠화재의 주가")))  # True
print(bool(pattern.search("메리츠 화재는 상승"))) # True
print(bool(pattern.search("비메리츠화재상품")))    # False

조사 목록을 생략하면 COMPLEX_JOSA가 사용된다. 직접 제어하려면 두 번째 인자에 조사 목록을, 세 번째 인자에 어미 목록을 전달한다.

Corpus

evaluate_corpus

여러 문장을 한 번에 평가해 전체 편집 횟수 기반 micro와 문장 평균 macro를 함께 반환한다.

import nlptutti as nt

report = nt.evaluate_corpus(
    ["가나", "다라"],
    ["가마", "다라바"],
)

print(report["rate_mode"])          # normalized
print(report["cer"]["micro"])       # 0.4
print(report["cer"]["macro"])       # 0.41666666666666663
print(report["perfect_sentences"])  # 0
print(report["sentence_error_rate"]) # 1.0
  • micro: 모든 문장의 편집 횟수를 합친 뒤 한 번 계산한다.
  • macro: 문장별 오류율을 동일한 가중치로 평균한다.
  • sentence_error_rate: CER 전처리 후 하나라도 문자 오류가 있는 문장의 비율이다.
Entity-aware ASR

evaluate_entities

전체 문장 점수와 별도로 회사명, 사람 이름, 상품명처럼 중요한 개체명의 문자 오류와 언급 보존 성능을 함께 평가한다.

이 함수는 NER 모델을 실행하지 않는다. 사용자가 제공한 개체명 사전을 문장에서 찾아 참조 개체명 span의 Entity CER와 정확한 언급 기준 precision, recall, F1을 계산한다.
import nlptutti as nt

report = nt.evaluate_entities(
    ["삼성전자의 갤럭시 S26 발표"],
    ["삼성전다의 갤럭시 에스 이십육 발표와 애플"],
    {
        "ORG": ["삼성전자", "애플"],
        "PRODUCT": ["갤럭시 S26"],
    },
    aliases={
        "갤럭시 S26": ["갤럭시 에스 이십육"],
    },
)

print(report["entity_cer"]["micro"])  # 0.1
print(report["summary"]["f1"])  # 0.5
print(report["labels"]["PRODUCT"]["f1"])  # 1.0
print([(e["type"], e["entity"]) for e in report["errors"]])
# [("misrecognition", "삼성전자"), ("addition", "애플")]

결과 읽기

  • entity_cer.micro: 모든 참조 개체명 span의 편집 횟수를 합쳐 계산한다.
  • entity_cer.macro: 참조 개체명 언급별 CER를 동일한 가중치로 평균한다.
  • 계산식 선택: 기본 normalized는 기존 패키지 호환용이다. 논문의 NE-WER처럼 참조 개체명 문자 수를 분모로 보고할 때는 rate_mode="standard"를 지정한다.
  • summary: 개체명 언급의 precision, recall, F1과 false positive, false negative를 제공한다.
  • labels: ORG, PERSON, PRODUCT처럼 사용자가 지정한 유형별 결과를 제공한다.
  • errors: omission, addition, misrecognition과 해당 문장 인덱스 및 편집 횟수를 보여준다.

한국어와 별칭 정책

  • 개체명 내부 띄어쓰기와 기본 조사·어미 결합을 허용하며, 조사는 개체명 span에 포함하지 않는다.
  • aliases를 생략하면 정확한 개체명 표기만 인정한다. 발음 유사도나 퍼지 매칭은 적용하지 않는다.
  • 숫자 읽기나 영문 표기의 허용 가능한 전사형처럼 실제로 같은 개체인 경우에만 별칭을 등록한다.
  • 별칭은 문자 정렬 전에 대표 개체명으로 바뀌므로 등록된 별칭의 Entity CER는 0.0이다.
  • 참조에 없는 개체명 추가는 Entity CER가 아니라 precision/F1과 addition 오류로 확인한다.

왜 두 점수를 함께 보나

LREC 2016의 NE-WER 연구는 전체 WER 대신 참조 개체명 span에 속한 오류를 따로 계산한다. Nlptutti는 한국어의 불안정한 단어 경계를 줄이기 위해 이 개념을 문자 단위 Entity CER로 독립 구현했다. 이는 특정 논문이나 공개 구현을 그대로 포팅한 지표가 아니며, 다른 구현과 점수가 같다는 의미도 아니다. 다만 참조 span 밖에 새로 생긴 개체명은 이 CER에 포함되지 않으므로 언급 precision/F1을 함께 반환한다.

NAACL 2025의 Spoken NER 연구도 개체명 오류율을 전체 WER의 대체제가 아닌 보완 지표로 설명한다. 따라서 보고서에는 전체 CER, Entity CER, 개체명 F1과 평가 정책을 함께 기록하는 것이 좋다.

Implementations

관련 공개 구현과 차이

논문 설명이 아니라 실제 실행 가능한 평가 코드를 기준으로 입력 형식과 계산 정책을 비교한다.

  • ContextASR-Bench 평가 코드: 개체명 목록을 이용해 WER, 퍼지 매칭 기반 NE-WER, 정확 일치 기반 NE-FNR을 계산한다. NVIDIA NeMo-Skills에도 같은 벤치마크 평가 구현이 있다. Nlptutti는 퍼지 매칭을 기본으로 사용하지 않고 한국어 문자 span과 사용자가 명시한 aliases를 평가한다.
  • Teklia ie-eval: BIO 형식의 정답·예측 파일을 입력받아 ECER/EWER와 유형별·순서 독립 점수를 계산한다. Nlptutti는 이미 태깅된 NER 출력 대신 원문 reference/hypothesis와 개체명 사전을 입력받으며 NER 모델을 실행하지 않는다.
  • PIER: 전체 문장을 먼저 정렬하고 참조에서 지정한 관심 단어 위치의 편집만 단어 단위로 센다. Nlptutti Entity CER는 같은 관심 구간 평가 원칙을 한국어 문자 단위로 적용한다.
해석 원칙: Nlptutti의 evaluate_entities는 위 코드를 복제한 함수가 아니다. NE-WER·ECER·PIER 계열의 공통 원칙을 한국어 원문과 개체명 사전 입력에 맞춰 독립 구현했다. 따라서 이름이 비슷한 점수를 직접 비교하기 전에 단어/문자 단위, 퍼지 매칭, NER 태그 입력 여부를 먼저 맞춰야 한다.

공통 계약과 의도적인 차이는 교차 검증 테스트고정 upstream 결과에 기록한다. CI에서는 외부 저장소를 내려받지 않고 검증한 커밋과 결과를 fixture로 고정한다.

Entity preservation

evaluate_keywords

지정한 고유명사나 핵심어가 STT 결과에 몇 번 보존됐고, 몇 번 빠지거나 추가됐는지 문장별로 집계한다.

import nlptutti as nt

report = nt.evaluate_keywords(
    [
        "삼성전자와 삼성전자가 협력했다.",
        "애플이 발표했다.",
    ],
    [
        "삼성전자가 협력했다.",
        "애플과 삼성전자가 발표했다.",
    ],
    {"ORG": ["삼성전자", "애플"]},
)

samsung = report["keywords"]["삼성전자"]
print(samsung["true_positives"])   # 1
print(samsung["false_negatives"])  # 1
print(samsung["false_positives"])  # 1
print(samsung["f1"])               # 0.5
print(report["labels"]["ORG"]["f1"])  # 0.6666666666666666
이 함수는 NER 모델이 아니다. 사용자가 지정한 키워드 목록의 언급 횟수를 평가한다. 같은 문장 안에서는 reference와 hypothesis의 등장 횟수 중 작은 값을 true positive로 본다. 문자 단위 Entity CER, 명시적 별칭, 누락·추가·오인식 목록이 필요하면 evaluate_entities를 사용한다. 실제 NER 모델의 span 예측 평가는 별도의 평가기가 필요하다. 조사와 어미 목록을 생략하면 각각 COMPLEX_JOSACOMPLEX_EOMI가 사용되며, 빈 목록을 전달하면 해당 접미사 매칭을 끌 수 있다.
Diagnostics

explain_errors

점수의 원인이 된 문자 또는 단어를 정렬하고 반복되는 치환·삭제·삽입을 빈도순으로 확인한다.

import nlptutti as nt

detail = nt.explain_errors(
    "아키택트",
    "아키택쳐",
)

print(detail["rate"])   # 0.25
print(detail["counts"])
# {"hits": 3, "substitutions": 1, "deletions": 0, "insertions": 0}

print(detail["error_frequencies"]["substitutions"])
# [{"reference": "트", "hypothesis": "쳐", "count": 1}]

단어 단위 분석은 unit="word"를 지정한다. 반환되는 alignment에는 equal, substitute, delete, insert가 순서대로 담긴다.

Compatibility API

calculate_keyword_error_rate_with_pattern

기존 사용자를 위해 유지되는 문장 존재 여부 기반 키워드 평가 함수다.

import nlptutti as nt

result = nt.calculate_keyword_error_rate_with_pattern(
    ["삼성전자가 발표했다."],
    ["삼성전자가 발표했다."],
    ["삼성전자"],
    nt.COMPLEX_JOSA,
)

print(result["keywords"]["삼성전자"]["accuracy"]) # 1.0

이 함수는 한 문장에 같은 키워드가 여러 번 나와도 1회로 집계하며, hypothesis에만 등장한 키워드는 false positive로 세지 않는다. 새 코드에서는 evaluate_keywords를 권장한다.

Preprocessing

전처리 옵션을 명시적으로 기록하기

점수 비교에서는 모델 이름만큼 공백, 문장부호, 유니코드 정규화 정책을 함께 남기는 것이 중요하다.

문장부호

result = nt.get_wer(
    "안녕하세요!",
    "안녕하세요",
    rm_punctuation=True,  # 기본값
)

유니코드 NFC

result = nt.get_cer(
    reference,
    hypothesis,
    unicode_normalization="NFC",
)
  • unicode_normalization=None이 기본값이며 과거 결과를 그대로 보존한다.
  • NFC/NFD/NFKC/NFKD를 선택할 수 있다. 일반적인 한글 조합형 차이에는 NFC가 적합하다.
  • CER와 CRR은 공백을 항상 제거한다. WER는 공백을 단어 경계로 사용한다.
  • 코퍼스, 키워드, 개체명 평가의 reference/hypothesis 문장 수가 다르면 ValueError가 발생한다.
References

논문과 참고 자료

Entity CER 설계와 한국어 문자 단위 평가를 설명할 때 참고한 1차 자료다.

Choose

목적에 맞는 함수 선택

한 문장 점수, 전체 데이터셋 평가, 특정 용어 보존, 오류 원인 분석을 분리하면 결과 해석이 선명해진다.

get_cer / get_wer / get_crr

한 쌍의 문장을 빠르게 점수화할 때 사용한다.

evaluate_corpus

데이터셋 전체의 micro/macro 성능과 완전 일치 문장 비율을 볼 때 사용한다.

evaluate_entities

개체명 span의 문자 오류, 언급 F1, 별칭과 실제 오류 목록을 함께 평가할 때 사용한다.

evaluate_keywords

회사명, 상품명, 전문용어의 누락과 추가 인식만 간단히 언급 횟수 기준으로 평가할 때 사용한다.

explain_errors

점수가 나빠진 실제 문자·단어와 반복 오류를 찾을 때 사용한다.