확률을 돌려주는 모델로 콘텐츠를 훑어봤다 — 질문 열한 개, 둘 남음

작성 · 수정


일본어 학습 앱의 단어 4,515개와 문장 572개를 TypeSafe Jev로 전수 훑었다. 질문 열한 개를 만들어 둘이 남았다. 결론은 분류기로는 못 쓰고 대기열 생성기로는 쓴다는 것이다.

왜 시작했나

시고또·바이또·레포또, 일본어 학습 앱 셋이 한 저장소에서 나온다. 콘텐츠 검토 문서에 이런 문장이 있다.

이번 회차에서 가장 큰 문제는 개별 오류가 아니라 8절의 교정이 두 팩으로 옮겨 가지 않은 것이었다.

한 팩에서 고친 설명이 다른 팩에 그대로 남아 있었다는 뜻이다. 지식의 문제가 아니다. 단어 4,515개와 문장 572개를 회차마다 사람이 전수로 볼 수 없어서 생긴 일이다.

그러면 전수로 훑는 쪽을 기계에 맡기고 판단만 사람이 하면 된다. TypeSafe의 Jev는 텍스트를 생성하지 않고 타입이 붙은 판단과 확률을 돌려준다. 예·아니오 확률(Noul), 정해진 보기 중 택일(Choice), 순서 있는 등급(Score) 셋이다. 코드가 곧바로 소비할 수 있는 모양이라 “훑어서 줄 세우기”에는 맞아 보였다.

다만 문서가 먼저 경고한다. 영어가 주 학습 언어고 CJK는 처리는 되나 정확도가 낮다고. 그래서 감으로 쓰지 않고 재기로 했다.

첫 실험 — 정규식보다 나은가

질문 하나를 만들었다. “이 설명이 예외나 상황 차이를 인정하지 않고 하나의 규칙으로 단정하는가.”

정답지는 git 이력에서 나왔다. 검토 교정이 들어간 커밋 전후로 문장의 설명이 바뀐 쌍이 40개 있었다. 수정 전이 양성, 수정 후가 음성이다.

문제는 그냥 돌리면 안 된다는 것이었다. 수정 전 설명에는 “반드시”, “가장”, “~만” 같은 단정 어휘가 거의 다 박혀 있다. grep 한 줄로도 갈린다. 그러면 모델을 쓸 이유가 없다.

그래서 잰 것은 pre/post가 갈리느냐가 아니라 정규식이 못 잡는 쌍을 모델이 잡느냐였다. 네 갈래로 세었다.

갈래수
정규식만6
둘 다21
모델만8
아무것도5

모델만 잡은 8건을 하나씩 눈으로 봤다. 진짜는 4건이었다.

다음은 전부 수정 전 원문이다. 틀린 설명이라 고쳤다.

  • でいらっしゃる는 상대에게, でございます는 자기에게 — 방향이 반대다
  • お世話になっております — 상대가 누구든 일단 이 말부터 한다
  • 内定辞退는 메일보다 전화가 먼저다
  • 훈독 명사에는 お

넷 다 앞의 정규식에 걸리는 어휘가 없다. 내용으로만 단정한 문장이라 어휘를 세는 방식으로는 잡히지 않는다. 이 자리가 모델을 쓸 이유다.

오탐이 절반이라는 것도 같이 기록했다. p >= 0.5를 자동 수정 기준으로 쓸 수 없다는 뜻이다.

질문 열한 개, 둘 남음

첫 질문이 통과했으니 같은 방식으로 후보를 늘렸다. 전부 검토 문서가 실제로 잡아낸 오류 유형에서 가져왔다.

질문대상검증결과
과잉일반화문장 설명40쌍 pre/post쓴다. 정밀도 20%
범위 좁힘 v2낱말 뜻풀이네 갈래 57건쓴다. 정밀도 16~20%
범위 좁힘 v1낱말 뜻풀이52쌍폐기
설명-문장 정합문장없음폐기. 정밀도 10%
한국어 직역번역없음폐기. 신호 없음
팩 간 불일치낱말 쌍 323없음폐기. 오탐만
경어 꼬리표문장30건폐기. 아래 참조
졸업 보기 겹침시험 문항30건일회성 점검용
문서 수명저장소 문서 10—“지울 것 없음”
색인 흡수결과 기록 10정답지 2실패
용례 정합낱말없음판정 안 함

열하나 중 둘이다. 나머지는 정규식이 이미 하거나, 구멍이 작거나, 모델이 사람보다 못했다.

실패가 알려준 것

confidence는 신호가 아니다

경어 꼬리표가 제일 유망해 보였다. 존경·겸양·정중 구분은 이 프로젝트가 한 번 통째로 틀렸던 영역이고, 빌드 검사는 꼬리표가 비었는지만 보지 맞는지는 보지 않는다. 문장 572개가 한 번도 검증된 적이 없었다.

Choice로 30건을 물었다. 지금 붙은 꼬리표와 22/30 일치, 평균 confidence 0.841. 숫자만 보면 좋다.

어긋난 8건을 보니 6~7건이 모델 쪽 오답이었다.

문장지금 → 모델실제
進んでおります겸양 → 정중지금이 맞다. おる는 いる의 겸양어다
お待ちください존경 → 정중지금이 맞다. お〜ください 꼴
御社を志望した존경 → 정중지금이 맞다
〜に関する문어 → 정중지금이 맞다

어긋난 8건 중 6건이 ”→ 정중”이다. 문장 끝의 ます·です를 보고 겉 공손도로 떨어뜨린 것이다. 꼬리표는 그 카드가 가르치려는 것을 가리키는 교육적 라벨인데, 모델은 문장의 겉 형태를 읽었다. 질문에 “가르치려는 핵심을 고른다”고 명시했는데도 그랬다.

더 나쁜 건 확률 쪽이다. 進んでおります를 0.940으로 확신하며 틀렸다. 앞선 실험에서 팩 간 불일치를 물었을 때는 평균 confidence가 0.539라 “모델도 헷갈린다”는 신호라도 있었다. 여기는 그 신호가 없다.

예·아니오 질문에는 애초에 confidence가 없고 확률만 온다. 그래서 확신도를 돌려주는 Choice가 낫겠다고 생각했는데, 그 전제가 이 실험에서 깨졌다. 적어도 이 30건에서는 확신도가 높은 쪽이 더 안전하지 않았다. 표본이 작으니 일반화할 일은 아니고, 확신도를 안전장치로 쓰려면 자기 데이터에서 먼저 재 봐야 한다는 정도로 남긴다.

라벨을 잘못 만들면 부호가 뒤집힌다

낱말 뜻풀이 질문의 첫 판은 52쌍에서 23/52로 실패했다. 사실상 동전 던지기다.

원인은 질문이 아니라 라벨이었다. 수정 후를 통째로 음성으로 놓았는데, 검토 교정 상당수가 조건을 덧붙이는 방향이었다.

해마다 닷새는 반드시 쓴다 → 연 10일 이상 부여받는 근로자에 대한 사용자의 연 5일 취득 확보 의무

고친 쪽이 조건을 더 많이 담았으니, “조건을 정의처럼 적었는가”를 묻는 질문에는 수정 후가 더 높게 나온다. 문장 설명에서는 교정이 단정을 덜어내는 방향이라 통했는데, 낱말 뜻풀이에서는 더하는 방향이라 부호가 뒤집혔다.

둘째 판은 라벨을 네 갈래로 갈랐다. 표적 양성, 어려운 음성(그 수정 후), 사실 오류 대조군, 쉬운 음성.

갈래평균
표적 양성0.688
어려운 음성0.353
사실 오류 대조군0.353
쉬운 음성0.211

표적 12쌍이 전부 갈렸고 평균 차가 0.334다. 사실 오류 대조군이 특히 중요하다. 뜻 자체가 틀린 항목들인데, 이것이 표적만큼 높았다면 질문은 “뜻풀이가 나쁜가”를 재는 것이었을 테다. 낮게 나왔으니 ‘좁힘’과 ‘틀림’을 실제로 가른다.

컨텍스트를 줄이면 정확도가 오른다

문서가 state가 커지면 정확도가 흔들린다고 적어 두는데, 실측으로도 나왔다. 1회차 낱말 스윕은 읽기와 용례까지 같이 보냈고, 2회차는 표기와 뜻만 보냈다. 같은 질문 계열에서 상위권의 쓸모가 눈에 띄게 달랐다.

정규식이 공짜로 하는 일을 시키지 말 것

“시점 표현이 낡았는가”를 후보로 올렸다가 부르지 않았다. 정규식 한 줄로 4,515개를 훑어 5건이 걸렸고, 그중 진짜로 낡는 것은 하나였다. 공교롭게도 낱말 스윕이 0.780으로 올렸던 바로 그 항목이다. 15센트짜리 스윕이 잡은 것을 정규식이 0원에 잡는다.

라벨 만들 때도 한 번 당했다. 보고서를 찍는 코드가 수정 전 설명 옆에 수정 후 문장을 나란히 출력하고 있었고, 나는 그것을 “설명이 딴 표현을 다룬다”는 오류로 읽었다. 없는 오류를 보고 질문 하나를 만들어 4,515건에 돌린 셈이다. 그 질문의 정밀도는 10%였다.

그래서 고친 것

두 회차로 19자리를 고쳤다. 물증 둘만 적는다.

年度. 한 팩에서는 “회계·행정 등의 기준 연도. 일본 정부·학교는 주로 4월 시작, 회사는 다를 수 있음”으로 이미 고쳐져 있었다. 다른 팩에는 “연도. 4월에 시작하는 한 해”가 그대로 남아 있었다. 검토 문서가 말한 미전파를 실제로 잡은 첫 건이다. 앞서 팩 간 뜻풀이를 323쌍 비교해 못 잡던 것을, 팩을 나란히 놓지 않고 각각 독립으로 물으니 잡혔다.

復唱いたします. 문장에 없는 표현을 설명이 권하고 있었다. 이력을 보니 원래는 “콜센터 화법이고 사무직은 쓰지 않는다”는 대조였다. 과잉일반화를 고치는 회차에서 그 단정을 눅이다가 배척하던 것이 권유로 뒤집혔다. 교정이 다른 종류의 오류를 만든 회귀다.

되돌릴 때 원래 판으로 돌리지 않았다. 그 판의 “반드시 되읽는다”는 일부러 눅인 단정이기 때문이다. 눅인 것은 두고 대조의 틀만 되살렸다.

값

요청 15,333회, 입력 약 990만 토큰, $0.417. 출력 토큰은 과금하지 않는다.

비용이 이 정도면 “돌려볼까”의 문턱이 사실상 없다. 문턱은 돈이 아니라 결과를 사람이 읽는 시간이다. 정밀도 20%짜리 대기열은 상위 30건을 읽어 6건을 건지는 것이다. 그 30건을 가르는 일은 이번에 자동화하지 못했다 — 모델에게 되물어 봤지만 사람 판정과 갈렸다.

남는 것

  • 확률 순위는 검토 대기열이지 발견 목록이 아니다. 이 선을 넘어 순위를 결과처럼 읽었다가 한 번 틀렸다.
  • 절대 문턱을 쓰지 않는다. 오답이라고 확인된 텍스트의 평균이 0.571이었다. 0.5를 겨우 넘는다.
  • 확신도를 안전장치로 쓰기 전에 자기 데이터에서 잰다. 0.940으로 틀린 사례를 봤다.
  • 질문을 만들기 전에 정규식이 못 하는 일인지 먼저 본다.
  • 라벨을 만들 때 교정이 어느 방향인지 본다. 더하는 방향이면 부호가 뒤집힌다.

한 줄로 줄이면 이렇다. 이 모델은 사람이 볼 목록을 만들어 준다. 사람 대신 보지는 않는다.

부록 — 이 글에도 돌려봤다

같은 질문을 이 글에 되돌렸다. 문단 24개, 입력 12,620 토큰, $0.0005.

0.5를 넘은 것이 10개였고 상위 8개를 읽었다. 4개는 동의해서 고쳤다.

  • “grep으로는 영원히 안 잡힌다. 이게 모델을 쓸 이유의 전부다” — 잰 범위를 넘었다. 앞의 정규식에 안 걸린다는 말로 좁혔다.
  • 확신도 문단 — 30건에서 본 것을 일반론으로 적고 있었다. 표본을 밝히고 눅였다.
  • 비용 문단의 “자동화되지 않는다” — 이번에 못 했다는 말로 바꿨다.
  • 수정 전 원문을 인용한 목록이 내 주장처럼 읽혔다. 인용임을 밝혔다.

나머지 4개는 동의하지 않아 그대로 뒀다. 수치와 이력을 함께 댄 서술이라 단정이 아니라고 봤다.

고친 뒤 다시 돌리니 평균이 0.452에서 0.415로 내려갔고, 남은 상위는 전부 내가 동의하지 않은 쪽이었다.

절반쯤 맞고 절반쯤 틀리는 이 비율이 본문에서 잰 정밀도와 비슷하다. 글을 대신 고쳐 주지는 않지만, 다시 읽을 자리는 짚어 준다.