Skip to content

join 메소드의, 특정 순서 조합에서의 띄어쓰기 발생 경향성 개선 검토 요청 #220

Open

Description

@regular-hopper-user

안녕하세요. 몇 가지 띄어쓰기 규칙 관련 검토자료 보내드립니다.

  1. 순서는 파이썬에서 tokenize > join 의 순서를 따릅니다.
  2. 입력 문자열을 몇가지 케이스를 한 번에 묶어 '1인 이상. 9%씩. (mike)'
  3. 기대 값은 '1인 이상. 9%씩. (mike)' 입니다.
  4. 출력 값은 '1 인 이상. 9 %씩. ( mike)' 입니다.

토큰 내용은 다음과 같습니다.
[('1', 'SN'), ('인', 'NNG'), ('이상', 'NNG'), ('.', 'SF'), ('9', 'SN'), ('%', 'SW'), ('씩', 'MAG'), ('.', 'SF'), ('(', 'SSO'), ('mike', 'SL'), (')', 'SSC')]

차기 버전에 검토 부탁드립니다.

Activity

  1. transferred this issue frombab2min/Kiwion Apr 29, 2026
  2. heeoneie commented on Sep 22, 2026

    @heeoneie
    Contributor

    보고해 주신 세 가지를 확인하고, 그중 두 가지를 고치는 PR을 Kiwi 쪽에 올렸습니다.
    bab2min/Kiwi#278

    재현 조건 — 0.23.2에서도 재현됩니다. 다만 join에 Token 객체를 그대로 넘기면 원문의 위치 정보로 띄어쓰기가 복원되기 때문에, (형태, 품사) 튜플로 넘길 때만 드러납니다.

    >>> text = '1인 이상. 9%씩. (mike)'
    >>> kiwi.join(kiwi.tokenize(text))                              # 위치 정보 있음
    '1인 이상. 9%씩. (mike)'
    >>> kiwi.join([(t.form, t.tag) for t in kiwi.tokenize(text)])   # 품사만으로 판단
    '1 인 이상. 9 %씩. ( mike)'

    고친 것 두 가지 — src/Joiner.hpp의 isSpaceInsertable에서 규칙 두 쌍이 서로 모순돼 있었습니다.

    1. 괄호 예외가 "SL·SN 앞에는 공백" 규칙보다 아래에 있어서, 괄호 뒤가 영문·숫자일 때만 공백이 들어갔습니다. (+mike → ( mike, (+1 → ( 1, 그러나 (+가 → (가.
    2. SW 앞에는 공백을 넣으면서 SW 뒤에는 넣지 않아서, 3,+,4를 이으면 3 +4가 나왔습니다. 3 + 4도 3+4도 아닌 결과입니다. 숫자 뒤의 기호는 붙여 쓰는 쪽(9%, 30℃)으로 맞췄습니다.

    1인은 성격이 다릅니다 — 이건 Joiner 규칙이 아니라 품사 태깅에서 갈리는 것으로 보입니다. 숫자 뒤 단위명사가 NNB로 태깅되면 이미 잘 붙습니다.

    붙는 경우(NNB) 안 붙는 경우(NNG)
    3등, 10위, 5번, 3명, 2년, 4월, 1시, 6개 1 인, 5 층, 2 팀, 7 급, 3 배, 1 종

    같은 형태라도 문맥에 따라 갈리기도 합니다(3장 분량의 장은 NNB, 2장 요약의 장은 NNG). 또 별도 모듈인 Kiwi.space()도 '1인이상' → '1 인 이상'을 내놓아 두 모듈이 서로 일치하고 있고, isSpaceInsertable은 GenerativeMADataset의 학습 데이터 생성에도 쓰이기 때문에, 한쪽만 임의로 바꾸지 않고 남겨두었습니다.

    @bab2min 이 부분은 어느 쪽이 의도하신 방향인지 여쭙고 싶습니다.

    1. 사전·태깅 쪽에서 인, 층, 팀 같은 단위성 의존명사를 NNB로 보도록 하는 것이 맞는지,
    2. 아니면 Joiner에 "SN 뒤의 1음절 NNG는 붙인다" 같은 규칙을 두는 편이 나은지 (다만 이 규칙은 2024 대선처럼 2음절 이상은 걸러내지만, 학습 데이터 생성에도 영향이 갑니다).

    방향을 알려주시면 그에 맞춰 후속 PR을 준비하겠습니다.

  3. bab2min commented on Sep 22, 2026

    @bab2min
    Owner

    @heeoneie 안녕하세요. 좋은 기여 감사드립니다.
    결론부터 말씀드리면 1번이 맞습니다.
    1인이 분할되는것은 근본적으로 형태소 분석에 오류가 있기 때문입니다. 숫자 뒤에서 일반명사(NNG)는 띄어쓰고 의존명사(NNB)는 붙여쓰도록 현재 규칙을 설정해놓았고 이게 일반적으로는 잘 통합니다. 그러나 형태소 분석 모델에서 종종 1인의 인을 일반명사로 잘못 분할하기 때문에 이런 현상이 발생하는데, 분석기에 탑재되는 모델 크기가 작기 때문에 모든 의존 명사를 다 잡는 건 쉽지 않습니다. 그래서 자주 쓰이는 의존 명사를 중심으로 모델이 잘 분석하도록 튜닝하는 방향을 현재 고려하고 있습니다.

  4. heeoneie commented on Sep 23, 2026

    @heeoneie
    Contributor

    확인 감사합니다. 말씀하신 대로 규칙이 아니라 분석 결과 쪽 문제였습니다.

    방향을 확인하고 나서 analyze(top_n=10)으로 후보를 들여다봤는데, 제가 앞선 댓글에서 한 묶음으로 적었던 사례들이 실제로는 원인이 셋으로 갈립니다. 튜닝 대상을 고르실 때 쓰실 수 있을 것 같아 정리해 둡니다.

    측정은 kiwi.analyze(f'{표현} 있다', top_n=10)으로 하고, 최상위 후보와 해당 형태소가 NNB로 분석된 첫 후보 사이의 점수 차를 적었습니다. (0.23.2, 기본 모델)

    A. 후보에 NNB가 있는데 점수에서 밀리는 경우 — 말씀하신 튜닝으로 해결 가능해 보이는 쪽

    표현 1위 분석 NNB 후보 순위 점수 차
    3조 조/NR 2위 0.24
    1종 종/NNG 2위 2.58
    1군 군/NNG 2위 3.25
    1인, 10인 인/NNG 2위 3.70
    3배 배/VV 3위 3.81
    7급, 2급 급/NNG 2위 6.41

    사전에는 이미 들어 있고 후보로도 올라오니, 점수만 뒤집히면 되는 사례들입니다. 3조는 0.24로 거의 붙어 있고 급은 6.41로 가장 멉니다.

    B. NNB 후보가 아예 생성되지 않는 경우 — 튜닝만으로는 안 될 것 같은 쪽

    5층, 4반은 상위 10개 후보 어디에도 NNB 분석이 나타나지 않습니다(층은 NNG/XSN만). 2팀도 마찬가지인데, 팀은 단위성 의존명사가 아니라 일반명사이니 NNG 태깅 자체는 오분석이 아닙니다. 다시 말해 2팀은 지금의 NNG/NNB 규칙으로는 붙일 수 없는 사례로 보입니다.

    C. 이미 잘 되는 경우

    2장, 3부, 5분은 NNB가 1위로 나와 정상적으로 붙습니다.

    앞선 댓글에서 층, 팀을 인과 같은 줄에 묶어 적은 것은 부정확했습니다. 바로잡습니다.


    혹시 도움이 된다면, A 그룹이 들어간 문장을 직접 작성해 eval_data/에 추가하는 PR을 준비할 수 있습니다. 튜닝 전후를 숫자로 비교할 회귀 측정 대상이 생기고, CONTRIBUTING.md에서 평가용 말뭉치 기여를 권장하고 계시기도 해서요. 필요하신지, 필요하다면 어느 파일(written.txt / web.txt)에 몇 문장 정도가 적절한지 알려주시면 그에 맞춰 작성하겠습니다. 저작권 문제가 없도록 문장은 새로 짓겠습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions