Giter VIP home page Giter VIP logo

kiwipiepy's People

Contributors

bab2min avatar bing-su avatar hyejuseon avatar hyunwoongko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kiwipiepy's Issues

"그렇다" 와 "그러하다" 를 다르게 인식하는 문제가 있습니다.

입력: "그건 그렇다.", "그건 그러하다."
[('그거', 'NP', 0, 2), ('ᆫ', 'JX', 2, 0), ('그렇', 'VA', 3, 2), ('다', 'EF', 5, 1), ('.', 'SF', 6, 1)]
[('그거', 'NP', 0, 2), ('ᆫ', 'JX', 2, 0), ('그러', 'XR', 3, 2), ('하', 'XSA', 5, 1), ('다', 'EF', 6, 1), ('.', 'SF', 7, 1)]
"그렇다" 와 "그러하다" 는 동일한 품사이며 동일한 의미입니다. 그러나 분석 결과는 위처럼 다르게 나옵니다.

[Question] load_user_dictionary 사용

load_user_dictionary의 txt 파일에서
(단어1 [탭문자] 품사태그 [탭문자] 단어점수)

  1. 품사태그를 입력하지 않을시 기본으로 적용되는 품사태그가 있나요?
  2. 단어점수의 범위가 있나요?

코퍼스에서 미등록단어 추출시 커널이 뻗어버리는 문제

안녕하세요, 저번 사용자 사전 추가후 분석 불가 문제를 잘 처리해주셔서 감사합니다.

미말록과 우분투 시스템 사용시 램 저장소 문제가 발생한 거라 들었습니다.

이번에는 같은 환경에서 미등록단어 추출을 사용하면 커널이 죽는 에러가 발생합니다.

데이터와 관계 없이 에러가 발생합니다.

소스코드는 아래와 같습니다. (예제코드와 같습니다.)

kiwi = Kiwi()

class ReaderExam:

    def __init__(self, filePath):
        self.file = open(filePath)

    def read(self, id):
        if id == 0: 
            self.file.seek(0)
        return self.file.readline()

reader = ReaderExam('./corpus.txt')

filtered_words = kiwi.extract_filter_words(reader.read)

사용환경은 다음과 같습니다.

Ryzen 3900X
RAM 96GB
Ubuntu 18.04.1
python 3.7

감사합니다.

고유명사 사용자 사전 등록

README에 나와있는 사용자 사전 추가 내용 중에

# 스타크래프트 관련 명사 목록
스타크래프트 NNP 3.0
저글링 NNP
울트라리스크 NNP 3.0

  1. 위 사용자 사전 파일 내용 중 '울트라리스크'와 같이 두 개 이상의 형태소로 잘게 쪼개지는 고유명사를 하나의 형태소 NNP로 분석이 가능한가요?
    위 사용자 사전 파일 내용을 아래와 같이 호출시 결과에 사용자 사전 적용 이전과 동일하게 나오는 것 같습니다.
def main():
    kiwi = Kiwi()
    print(kiwi.load_user_dictionary(dict_path='userdic.txt'))
    kiwi.prepare()
    result = kiwi.analyze('울트라리스크가 뭐야?')
    print(result)

[([Token(form='울트라', tag='NNG', start=0, len=3), Token(form='리스크', tag='NNG', start=3, len=3), Token(form='가', tag='JKS', start=6, len=1), Token(form='뭐', tag='NP', start=8, len=1), Token(form='이', tag='VCP', start=9, len=1), Token(form='야', tag='EF', start=9, len=1), Token(form='?', tag='SF', start=10, len=1)], -38.33686447143555)]

  1. 사용자 사전을 적용해보는 도중에 사용자 사전 단어 순서에 따라 사전 내용 적용 유무가 달라지는 것을 확인했는데 사용자 사전에서 단어 순서도 분석 내용에 영향이 있나요?
    확인해본 케이스는 아래와 같습니다.
\# userdict1
울트라리스크	NNP	3.0
파일즈	NNG	0.0

위 파일을 1번 코드 내용과 같이 동일하게 호출하여 분석 시 '울트라리스크'가 NNP로 분석이 되고 있습니다.
([Token(form='울트라리스크', tag='NNP', start=0, len=6), Token(form='가', tag='JKS', start=6, len=1), Token(form='뭐', tag='NP', start=8, len=1), Token(form='이', tag='VCP', start=9, len=1), Token(form='야', tag='EF', start=9, len=1), Token(form='?', tag='SF', start=10, len=1)], -12.41728687286377)

\# userdict2
파일즈	NNG	0.0
울트라리스크	NNP	3.0

위 파일을 1번 코드 내용과 같이 동일하게 호출하여 분석 시 '울트라' '리스크'로 쪼개져서 분석이 되고 있습니다.
([Token(form='울트라', tag='NNG', start=0, len=3), Token(form='리스크', tag='NNG', start=3, len=3), Token(form='가', tag='JKS', start=6, len=1), Token(form='뭐', tag='NP', start=8, len=1), Token(form='이', tag='VCP', start=9, len=1), Token(form='야', tag='EF', start=9, len=1), Token(form='?', tag='SF', start=10, len=1)], -38.33686447143555)

감사합니다.

분석 결과에서 용언의 불규칙 활용여부 표지 추가

묻다/물어묻다/묻어와 같이 형태소 분석 후 기본형만 출력시 규칙 활용 동사인지 불규칙 활용 동사인지 알 수가 없어지는 문제가 있음.
이를 구분해주기 위해 형태소 분석 결과에 regular 필드를 추가하여 불규칙 활용 여부를 알 수 있게 하면 좋을듯.

숫자를 포함한 고유명사를 인식하지 못하는 이슈

안녕하세요!

'2차전지' , '코로나19' 처럼 명사 + 숫자로 된 단어의 경우 사용자 사전에 해당 단어들을 등록해도 명사 + 숫자로만 토크나이징이 되는 이슈가 있는 것 같아요!

예전 버젼에서는 사용자 사전에 해당 단어들을 등록하면 하나의 고유명사로 잘 분류가 되었던 것 같은데, 혹시 관련해서 변경사항이 있는 걸까요?

[Error]kiwi::KiwiUnicodeException

춥다...집콕 시작​​​​​​​​#아침#무스비 아침으로 무스비를 거하게 먹고​​#후식#올리브빵#카페라떼 남편이 스타벅스 리저브에거 사온 올리브 빵을또 먹었네요​​​​​​​ 사실 여기서 혼자 장보기는 나에게 뭔가도전과 같은거​계산도 핸드폰으로 하고 뭐가 문제인가 싶지만난 뭐든 혼자하는건 겁난다​​이날은 다 좋았는데무게, 양 조절 실패로​몇번이나 쉬면서 집으로🤪​​​​​​​#운동 카도오픈샌드위치#패션푸르츠#abc쥬스 아침에 밥 먹었으니 저녁은 샌디치​사실은 빵사온거 빨리 먹고파서빵수니🥖​​​​​#석류 한국에선 잘 안먹던 과일인데여기선 열심히 먹고 있는 석류​여말랭이피클, 호두과자, 석류 ​​​​​​​#비빔밥#부추전 나물반찬이 많아서 간만에 바빔밥근데 너무 과하게 많이 먹었....​​​​#후식#마카롱#아이스아메리카노 그래놓고 또 후 그래도 나름 꾸준히 운동중사실 유산소 조금, 홈트 조금이지만​운동 세상 싫어하던 나에겐아주 큰 발전​​​​​​​#호박마스크 귀여운 딸학교에서 만들었다며버스에서부터 마스크를 쓰고온...​히히​나 저녁은 간단히하지만 고칼로리​​ 후식으로 석류까지 알차게 냠냠​​​​​​​​​#아침#소떡소떡 아침부터 소떡소떡을 해먹습니다​☺️​​​​​​​#학습지 딸 영어 학습지 이날 학교 일정이 런치 먹고 일찍 하교였는데​요즘 너무 춥고사실...엄마 요즘 심심해...그래서 애들 학교 안보내고엄마랑 놀아달라고 부탁했다​학교 가겠다는 어린이들 꼬시려고케이크 만들기, 영화 관람으로 딜...​그래서 간만에 케이 초코머핀 믹스 였는데머핀 만들기는 번거로워서 그냥 한판으로 구워서 케이크로​마카롱과 함께 먹으니참 맛있었어요✌​​​​​​#저녁식사#월남쌈#수박쥬스 요즘 정말 너무 먹는 것 같아서#어린이도시락 유부초밥, 치킨너겟, 오이피클, 패션푸르츠, 유산균음료 ​​​​​​​#스타벅스#크리스마스컵 스타벅스컵이 크리스마스 패키지로 바뀌었다고...​​​​​​#국제택배#우체국택배 하다보니뭔가 또 엄청 오래걸린기분​​ 꼭 부탁하지 않아도젤리며 이런저런 간식, 애들 장난감, 옷 등꼭 껴서 보내주는 시누이​진짜 천사.......사랑하는 시누이다 심지어 이건 뭔지 모르겠는데넘 맛이라 아껴먹고 이뜸​​ 자된 기분❤️​​​​​​#도시락#런치박스 토마토펜네파스타, 오이피클, 방울토마토, 누룽지, 약과 ​​​​​​​​​​​#아침#크로와상버섯샌드위치#노란수박#옥수수#카페라떼 냉털메뉴였는데 이뻐서 샀는데나름 유명한 브랜드에 법랑재질이었...​​중국어 몰라서 쇼핑을 해도 이런식 ㅋㅋ와봐야 안다여튼 법랑 재질에 가벼워서애들 컵으로도 괜찮을 것 같아서하나 더 주문했다​​​#할머니선물#고모선물 친정고...​엄마도 아빠도 안하는 주식을 딸이 먼저 샀다​덤으로 고모가 준 용돈은 기부까지❤️​​남은 오만원은 엄마 쓸께^^^^^^^^^​​​​​​​#팬드리 허접하지만 우리집 팬트리(?)​택배온거 싹 정리하고 나니세상뿌듯​ 오고있는 요즘​​​​​​​#하교 어린이들 하교길​나는 육출🧡​​​​​​​#저녁식사 대충 차려먹어도이만큼​난 먹는데는 대충이 없다보다​​엄청 가지가지네​​​​​​​​#감성카페#가족출동 가족과 함께 카페 출동​오픈시간에 맞춰가서창가자리 사수​​심지어 이날은 디져트도 시켰는데마카롱 맛집맛있어​​​​​​#저녁#꿔바로우#마라탕#마라샹궈#칭따오맥주 저녁은 간만에 세트메뉴🧡🤎​말해뭐해​​​​​​​​#일요일아침#빵식 간단히 아침 먹고​​​#날씨굿 난 마사지남편과 아이들 남편이랑 애들이 장보고난 마사지받고 합류해메트로​우리집 과소비 요인인 곳(아닌가^^^;타오바온가)​​​​​​#점저#떡볶이#부라타치즈떡볶이 추억의 국민학교 치즈 떡먹어지길래같이 먹어보았는데...​떡볶이는 기본 떡볶이가 제일 맛있는걸로^^​​​​​​​​​​​​​#도시락 치킨너겟, 콩나물무침, 무말랭이피클, 김,샤인머스켓, 약과, 딸기우유 ​​​​​​#아침#아보카도닭가슴살샌드위치#방울토마토 운동#헬스장 헬스장 등록 기간이 얼마 안남아서특히 열심히 가고 있다30분 유산소만 해도​다녀오면​몸이 한결 가벼워서 좋다​​​​​​#하교길 애들 하교 버스 마중가는데흑곰인가요 털장갑, 털운동화 필수​날씨 변덕적응안대​​​​​​​#저녁식사#도토리건조묵골뱅이무침 우와이거 대박 맛났음​건조 묵... 좀 비쌌는데​다음 택배 받을때 좀 쟁여놔야게뜸​​​​​​#도시락#어린이도시락샌드위치#킨더하마초콜릿 맨날 냉털이래근데 샌드위치 속재료는 정말 있는거 없는거상할 것 같은 것도막 채워 넣는다그럼 그냥 맛나​​​메르로에서 우연히 발견한킨더하마초콜렛도​소문대로 맛있더군​​​​​​#패딩기간에 득템​​데헷맘에드로​​​​​#저녁메뉴#단호박에그스럿#패션후르츠#방울토마토#abc쥬스 저녁 간단히​​단호박 에그슬럿은간단한듯 안간단...​맛은 쏘쏘​​​​​​​​​#velosan#독일#무쇠에그팬 나​​​​​​​#도시락 장조림버터볶음밥, 녹두전, 샤인머스킷, 방울토마토, 오이,요거트견과류 ​​​​​​​#가정학습 조금 기침을 했지만​계속 등교를 시켰는데학교에선 가끔씩 심하게 기침 한다고속 누나랑 아빠 찾음)​​​​​​#소시지치즈또띠아롤#샤인머스킷#방울토마토#아이스아메리카노 치즈 잔뜩 소시지 계란 넣은 또띠아버터 넣은 팬에 굽굽하다롤롤​대박 느끠​​ 후식은 요요요요 맛매일 계속 한다​​​재밋나바​​​​#도시락#엄마표도시락 짜장밥, 발울토마토,무말랭이피클, 빼빼로, 요구르크, 샤인머스켓 김주먹밥, 치킨너겟, 오이피클, 패션푸르츠, 미니약과, 젤리 ​​​​​​​​#맥도날드#햄버거 ​​​​​기빨리고 정말 아무것도 하기 싫어서오전 내내 누워서 미드보다맥날 시켜 점심​​​​​​맥날은 나의 힘!​​​​저거 혼자 다 먹었다​​​​​​​​#드레곤우드게임 하다하다둘이도 하고 혼자도 하고​​게임중독자들​​​​​​​#서프라이즈#airpod프라이즈로 사온 에어팟​​거마워🤍​​(근데 아마 자기 해드폰 사며 눈치보여 사온듯?!)​​​​​​​#모녀데이트#스타벅스 아들과 남편이 짐보리 갈때보통 집에 있는데​어제 하루종시간 지루하니공부할거, 독서할 것도 챙기고​완전 알찬 데이트였다‍❤️​딸 너무 좋앙​​​​​​#짐보리 미술 수업인데얜 이수업이 쿠키먹는 수업인줄 안다​쿠키 먹는 수업만 되면​아이 라이크 쿠키를 그렇게 외치며 손을 든다고핑한다고 들렀는데이거저거 나에게 리젝 당하고​빈손으로 나옴​​​미얀​ 그래도 엄마 거셀은 좀 찌그껨​​​​​ 빈손이지만 쿨한 여자담에 꼭 필요한거 사자​​​​​​​​#운동#헬스장 느낀건난 움직이고 활동해야오히려 힐링되는 사람​​오전 외출하고남편 대학원 수업 끝나자마자운동하러...​​유산소 운동 30분 겨우 했지만게운해​그럼 되찌 머​​​​​#저녁 다이어트 절대 못하는 나인데​가끔 살이 빠지는 ​스트레스​​​​​​​🤮​​​​​​입맛 뚝​​간단히 저녁 먹기​​​​​​​그리고 썬데이투데이​​마사지 갔다 운동하고 밥먹고 또 침대에서 미드보고​정말 깨알같이 은근 많은걸 했는데아직 7시...​​​​​요몇일 정말 별거 아닌일(?)로 멘붕오고덕분에핑계로잘 쉬었다​​​우리끼리 행복하니 되쓰​​​​암오케이​​​​​​​​​​​​​​​​​​​​​​​​하지만...이러나저러나 빨리 ㅋㄹㄴ ㅆㄲ 사라져서한국가서 가족들 보고프다​(끝날듯 끝나지 않는 포슷힝)​​ 108. 잘먹고 잘살기

현재 0.8.2 버전에서도 libc++abi.dylib: terminating with uncaught exception of type kiwi::KiwiUnicodeException: unpaired surrogate
오류 발생합니다

except에서 어플리케이션에 영향없게 패스 해주고 싶은데 analyze 부분의 catch에서 걸리지가 않습니다

[ERROR_REPORT]libc++abi.dylib: terminating with uncaught exception of type std::__1::future_error: The state of the promise has already been set.

안녕하세요! bab2min 님!

미등록 코퍼스에서 단어 추출하기를 실험하고 있는데 에러가 나고 있어서 문의드립니다.

사용 환경은 Mac, Python 3.7 입니다.

README.md 에 작성하신 샘플 코드를 가지고 진행 했습니다.

from kiwipiepy import Kiwi
kiwi = Kiwi()
kiwi.prepare()
0

class ReaderExam:
    def __init__(self, filePath):
        self.file = open(filePath)
    def read(self, id):
        if id == 0: self.file.seek(0)
        return self.file.readline()
reader = ReaderExam('test.txt')

kiwi.extractWords(reader.read, 10, 10, 0.25)
libc++abi.dylib: terminating with uncaught exception of type std::__1::future_error: The state of the promise has already been set.
libc++abi.dylib: terminating with uncaught exception of type std::__1::future_error: The state of the promise has already been set.
[1]    73128 abort      python

오탈자 보정기능 개선 제안

안녕하세요, 오탈자 교정기능을 잘 사용하고 있습니다.

다만 현재 로직에서는 오자를 교정하다 보니 탈자 교정은 불가능한 한계가 있습니다.

좋아용 -> 좋아/IC 용/NNG
좋아영 -> 좋아/IC 영/NNG

인터넷에서 많이 쓰이는 문체가 종성을 추가하는 경우가 있으므로
음절 구성요소(초, 중, 종성)를 삭제하거나 추가하여서 자연스러운 문장이 되는지 추론하는 로직으로 개선되었으면 합니다.

감사합니다.

[Question] 기본 말뭉치 사전

이 프로젝트는 현재 기존의 타 말뭉치 사전을 이용하는것이 아닌 Kiwi만의 사전을 구축하여 신조어에 대응하고 있나요?

이 질문을 하는 이유는, 분석 전 단어 추출을 통해서 신조어 및 사전에 없는 단어를 추출하는것도 있지만
만약 맞다면, 사용자가 패키지 업데이트를 자주 해주는것이 유리하게 작용하는지 궁금해서 입니다.

ImportError

macOS Big Sur 환경입니다.

!pip install --upgrade kiwipiepy 후 임포트 시에
ImportError: dlopen(/users .../_kiwipiepy.cpython-38-darwin.so, 2): Library not loaded: /Users/runner/hostedtoolcache/Python/3.8.11/x64/lib/libpython3.8.dylib)
이런 식의 에러가 납니다.
virtualenv 만들어 사용해도 같은 에러가 나는데 무슨 문제일까요?

[Error] kiwi::KiwiUnicodeException

#바둑#장기#오목 귀요미#보드판🐥\n#어린이임블리의 놀이였는데, 이제는 가물갸물🙄모르겠\n장이요멍이요ㅎㅎㅎ다시 한 번 재미를 붙여 보까ㅎ\n할 일이 태산인데😭, 하고 싶은건 무궁무진🤦\u200d♀️ 큰 일이다 #바둑#장기#오목 귀요미#보드판🐥\n#어린이임블리의 놀이였는데, 이제는 가물갸물🙄모르겠\n장이요멍이요ㅎㅎㅎ다시 한 번 재미를 붙여 보까ㅎ\n할 일이 태산인데😭, 하고 싶은건 무궁무진🤦\u200d♀️ 큰 일이다

위의 문장의 분석 중 에러 발생합니다
libc++abi.dylib: terminating with uncaught exception of type kiwi::KiwiUnicodeException: unpaired surrogate

원문: https://www.instagram.com/p/CFgnSIXlgx4/

`kiwi().join()`이 텍스트를 제대로 복원하지 못하는 문제

from kiwipiepy import Kiwi

kiwi = Kiwi()
kiwi.join(kiwi.tokenize("너무 좋은데?"))

위 코드를 실행할 경우 "너무 조는데?"라는 결과를 리턴합니다.

특정 단어에 대해 이렇게 제대로 복원되지 않는 문제가 있는데, 이를 어떻게 해결할 수 있을지요?

멀티프로세싱 이슈

멀티프로세스 환경에서 사용할때 Error detail: Resource temporarily unavailable라는 에러가 나는데 혹시 어떤 문제일까요?

형태소 기반 일치/탐색/치환 기능 추가

문제 상황

문장 내에서 형태소를 기반으로 한 특정 패턴을 추출하거나, 일치 여부를 판정하거나, 일부 형태소를 다른 형태소로 교체해야하는 작업을 하는 경우 조건문을 이용하는 수 밖에 없는데, 이 형태소 조건들이 복잡해질 경우 이 작업이 굉장히 고단해지는 문제가 있음.
예를 들어 숫자(SN) 뒤에 의존 명사(NNB)가 오고, 그 뒤에 주격 조사(JKS) 혹은 목적격 조사(JKO)가 나오는 문자열을 탐색한다고 하면

tokens = kiwi.tokenize(some_text)
for i in range(0, len(tokens) - 3):
  if tokens[i].tag == 'SN' and tokens[i + 1].tag == 'NNB' and tokens[i + 2].tag in ('JKS', 'JKO):
    print(some_text[tokens[i].start : tokens[i+2].end])

와 같이 장황하게 조건을 나열해야 한다. 게다가 이는 최적화된 탐색 알고리즘을 사용하기도 어려우므로 대량의 텍스트 내에서 탐색을 수행시 비효율적인 문제까지도 있음. 탐색 후 치환의 경우는 훨씬 더 복잡해지는 문제가 있다.

제안

문자열 일치/탐색/치환에 널리 쓰이는 정규표현식 문법을 형태소 탐색용으로 개량하여 사용한다. 그리고 Python3의 표준 정규표현식 모듈에서 제공하는 re.match, re.search, re.sub와 유사한 함수를 제공하여, 한국어 텍스트를 형태소 기반으로 일치/탐색/치환할 수 있도록 한다.

pattern = kiwi.Pattern(r"(/NN) /JKO (/VV /EF /SF?)") # re.compile과 유사하게 패턴을 미리 컴파일하여 최적화한다.
m = pattern .match("밥을 먹어요?") # 일치 시 Match object 반환, 불일치 시 None 반환
m.group() # "밥을 먹어요?" (일치된 전체 텍스트)
m.group(1) # "밥" (첫번째 괄호로 지정된 텍스트)
m.group(2) # "먹어요?" (두번째 괄호로 지정된 텍스트)
m.span() # (0, 7)  (일치된 전체 텍스트 영역)
m.span(1) # (0, 1) (첫번째 괄호로 지정된 텍스트 영역)
m.span(2) # (3, 7) (두번째 괄호로 지정된 텍스트 영역)
m.token() # [Token(form='밥', tag='NNG', start=0, len=1), ..., Token(form='?', tag='SF', start=6, len=1)] (일치된 전체 텍스트의 형태소 목록)
m.token(1) # [Token(form='밥', tag='NNG', start=0, len=1)]  (첫번째 괄호로 지정된 텍스트의 형태소 목록)
m.token(2) # [Token(form='먹', tag='VV', start=3, len=1), ..., Token(form='?', tag='SF', start=6, len=1)]  (두번째 괄호로 지정된 텍스트의 형태소 목록)

m = pattern.search("저도 밥을 먹어요?") # re.match 와 re.search의 관계와 동일. 

pattern = kiwi.Pattern(r"(/VV) /EP (/EF)")
result = pattern.sub(r"\1 \2", "길을 걸었다.") # \1과 \2는 각각 패턴 내의 첫번째, 두번째 괄호와 일치.
# result: "길을 걷다." (걸었다->걷다 로 치환됨)
result = pattern.sub(r"\1 \2", "옷을 걸었다.")
# result: "옷을 걸다." (걸었다->걸다 로 치환됨)

pattern = kiwi.Pattern(r"/NNG")
result = pattern.sub(r"바다/NNG", "길을 걸었다.")
# result: "바다를 걸었다." (길->바다 로 치환됨, 이에 따라 뒤의 조사도 함께 변환됨)

형태소용으로 개량된 정규표현식

기본적으로 표현식은 각각의 형태소를 표현하기 위해 쓰이고, 문자에 대한 일치 여부는 되도록 하지 않는 것을 원칙으로 한다.

  • /품사태그 : 품사태그는 앞글자만 사용하고 뒷글자는 생략할 수 있다. 예를 들어 /NN은 일반명사(NNG), 고유명사(NNP), 의존명사(NNB)에 모두 일치할 수 있다. 마찬가지로 모든 동사/형용사를 지칭하는 데에는 /V, 모든 접미사에는 /XS를 사용하는 식으로 응용이 가능하다. 추가로 아무 태그도 명시하지 않은 /의 경우 모든 품사의 형태소와 일치할 수 있다.
  • 형태/품사태그: 구체적으로 특정 형태소를 명시하기 위해서는 / 앞에 형태를 지정할 수 있다. 바다/NNG는 일반명사인 바다만을 지칭한다. 마찬가지로 형태가 바다인 모든 형태소를 가리키기 위해서 바다/와 같이 쓸 수 있다.
  • //SP: 문자 /는 형태소 상으로는 구두점(SP) 품사에 속하므로, / 문자 그 자체를 지칭하기 위해서는 //SP라고 표기한다.
  • 연속된 형태소: 여러 형태소가 연속하는 것을 표현하기 위해서는 공백을 두고 각 형태소 표기를 연결한다. 즉, 명사 뒤에 조사가 오는 경우 /NN /J와 같이 쓸 수 있다. 여기서 공백은 형태소 사이를 구분하는 역할만 수행하며 실제 문자열 상의 공백과 일치하지는 않는다! 따라서 /NN /J/NN /J나 동일하게 연속하는 명사-조사 패턴을 가리킨다.
  • 형태소 수량자: 정규표현식의 수량자 *, +, ?를 지원한다. 단, 이는 형태소를 수식하는데에 쓰인다. 즉 /NNG*의 경우 일반 정규표현식에서마냥 /NN, /NNG, /NNGG와 일치하는 것이 아니라 , /NNG, /NNG /NNG, /NNG /NNG /NNG 등과 일치한다. 나머지 수량자도 마찬가지.
  • []: 일반 정규표현식과 마찬가지로 문자집합을 지원한다. 단, 형태나 품사태그 위치에서만 쓰일 수 있다. 예를 들어 /V[VA]는 동사와 형용사만을 지칭하고, [은는]/JX는 보조사 중 만을 지칭한다.
  • |: 여러 분기 중 하나와 일치하는 경우를 나타낸다. 즉 /NNG | /VV는 일반명사 혹은 동사 하나와 일치한다. 정규표현식과 마찬가지로 우선순위가 제일 낮다. /NNG | /VV+는 일반명사 오직 하나, 혹은 동사 하나 이상과 일치한다. 형태 내에서는 쓰일 수 없다.
  • ,: 형태 내의 분기를 나타내기 위해 쓰인다. 품사 태그에는 쓰일 수 없다. 하늘,땅/NNG는 일반명사 중 하늘 혹은 땅 중 하나와 일치한다.
  • .: 형태 내의 글자 하나와 일치한다. 품사 태그에는 쓰일 수 없다. 가./NNG로 시작하는 두 글자 일반명사 전부와 일치한다.
  • 형태 내 수량자: *, +, ?를 형태 내에서도 사용할 수 있다. 예를 들어, 가.+미/NNG의 경우 로 시작하고 로 끝나는 세 글자 이상의 모든 일반명사와 일치한다. 또 얼마나?/의 경우 형태가 얼마이거나 얼마나인 모든 형태소와 일치한다.
  • (): 괄호는 정규표현식과 마찬가지로 캡처그룹을 지정하고, 우선순위를 조절하기 위해 사용된다. 단 형태 내에서는 쓰일 수 없고, 형태소 간에서만 쓰일 수 있다. /VV (/EF | /EC)/VV /E[FC]와 동일하다. (/NN /J)+는 명사-조사가 연속하여 여러번 등장하는 패턴(명사-조사, 명사-조사-명사-조사 등)을 나타낸다.

구현

Python쪽에서 쉽게 구현하는 방법으로는, 형태소 분석 결과를 문자열로 직렬화하여 나타낸 다음, 위 형태소용 정규표현식을 적당히 변환하여 이 직렬화된 문자열과 일치시키는 것이 있다. 그러나 궁극적으로는 C++ 내부로 형태소용 정규표현식 일치 엔진을 가지고 들어가는게 성능 상에서 크게 유리할 듯하다. 특히 내부적으로 각 형태소는 고유 id로 변환되어 16~32bit int로 처리되므로, 위의 형태소용 정규표현식을 파싱하여 int 배열에 대한 DFA를 생성하면 의외로 쉽게 구현 가능할지도 모른다.

[Question] Kiwi 의 사전 품사태그

사용자 사전을 구축하려고 합니다.
txt 파일에 포맷을 설명해놓으셨는데 어떤 품사태그들을 사용하는지 정리해놓은 자료가 있을까요?

그리고 해당 라이브러리는 불용어 (stop word) 사전을 지원할 생각이 있나요?

Token 결과값 정리 관련

안녕하세요.

Kiwipiepy 넘 잘 쓰고 있습니다.

다름이 아니고 analyze하면 Token값이 나오는데, 결과값을 저장/활용할 때 불편한 점이 있어서요.

긴 문장을 분석하고 나면 다중 리스트의 형태로 나와 하나의 단어를 확인하려면 불필요한 작업이 필요하더라고요.

예를 들면

res = kiwi.analyze("샘플 문장입니다. 샘플 문장이에요. 샘플입니다")
print(res[0][0][0])
Token(form="샘플", tag="NNG", start=0, end=2)

이렇게 3중리스트까지 활용해야 접근이 가능합니다. --- (1번)
아마 여러 결과값을 함께 반환하는 것 때문인 것 같은데 이 점수를 활용하지 않는 경우(예: top_n=1)에는 따로 표기가 안되면 어떨까요.

그리고 결과값을 저장하고 싶은데 Token 클래스가 계속 함께 나오는 문제가 있더라고요.
한 sentence의 결과값을 저장할 때에는 불필요한 loop를 사용해서 tuple로 변환해주는 작업을 해야합니다.
-- (2번)

결과적으로 제안드리는거는
(1번) 단순 리스트의 형태로 결과값을 반환하면 어떨까요?
(2번) Token 클래스 말고 단순 튜플형태로 결과값이 나오도록 하는 옵션을 추가하면 어떨까요? (혹은 이미 있는데 제가 API에서 못찾은 것인지..ㅎㅎ)
(추가) 결과값을 Token 클래스말고 딕셔너리 형태로 반환하는 것도 있으면 어떨까요?

바쁘실텐데 항상 감사합니다.

extract_words() 관련 문의

안녕하세요? 미등재어 추출에 관심이 있어 관련 정보를 찾다가 이 페이지까지 오게 되었습니다:)
kiwipiepy의 extract_words() 사용 예제를 보니 파일의 내용을 읽어 처리하는 방식인 것 같습니다.
DB에서 읽어 온 자료를 사용해 보고 싶은데 첫 번째 파라미터를 어떤 형식으로 넘겨 주면 가능할까요?

`join`시 원인을 알 수 없는 segmentation fault 오류

안녕하세요! 저번에 #86 를 해결해주신뒤로, 완전히 kiwipiepy로 갈아탔습니다. 덕분에 코드가 훨씬 간결해졌어요. 감사합니다 ㅎㅎ

이번에는 오류를 하나 발견하게 되어 다시 이슈를 올려봅니다. 오류가 발생하는 코드는 다음과 같습니다:

from kiwipiepy import Kiwi

short = "안녕하세요! 만나서 반갑습니다"
long = "한글(韓㐎[1], 영어: Hangeul[2]또는 Hangul[3])은 한국어의 공식문자로서, 세종이 한국어를 표기하기 위하여 창제한 문자인 '훈민정음'(訓民正音)을 20세기 초반 이후 달리 이르는 명칭이다.[4][5] 한글이란 이름은 주시경 선생과 국어연구학회 회원들에 의해 지어진것으로 알려져 있으며[6][7][8][9] 그 뜻은 '으뜸이 되는 큰글', '오직 하나뿐인 큰글', '한국인의 글자'이다.[6][10] 한글의 또 다른 별칭으로는 정음(正音), 언문(諺文)[11], 언서(諺書), 반절(反切), 암클, 아햇글, 가갸글, 국문(國文)[12] 등이 있다.[5]"

kiwi = Kiwi()
# this succeeds
print(kiwi.join(kiwi.tokenize(short)))
# but this does not
print(kiwi.join(kiwi.tokenize(long)))
안녕하세요! 만나서 반갑습니다
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

short를 토크나이즈하고 다시 복구하는 과정은 문제가 없는데, 좀 더 지저분하고 긴 long을 똑같이 처리할 때는 segmentation fault 오류가 발생합니다. C++ 구현체에서 오류가 발생하는 것으로 보이는데요.

혹시 확인해주실 수 있을까요? 입력으로 넣으면 안되는 텍스트가 있는걸까요?

모델과 바이너리 분리하여 패키징하기

프로젝트당 pypi 용량 제한에 걸려 wheel을 더 이상 올릴수가 없음
공유가능한 모델 파일들은 kiwipiepy-model로 분리하고,
소스 및 바이너리는 kiwipiepy에 남겨두는 식으로 분리하는 게 좋을듯.

분석 결과의 구조적 반환

현재는 analyze()의 결과를 (형태소, 품사태그, 시작위치, 끝위치) 형태로 길이 4인 튜플로 반환 중.
이는 추후 기능 확장 시 호환성을 해칠 수 있으므로 다음과 같이 nametuple과 유사하게 구조적인 형태로 반환하도록 개선하면 좋을 듯.

Token(form='형태소', tag='NNG', start=0, end=3)
기존 튜플 방식과의 호환성을 위해 길이 4의 튜플로 변환 가능하며 0~3 사이의 인덱스로 접근 가능. 동시에 attr로도 접근 가능

len(t) == 4 # 길이는 4로 고정
form, tag, start, end = t # 튜플로 unpacking 지원
t[0], t[1], t[2], t[3] # 튜플처럼 인덱싱 지원
t.form, t.tag, t.start, t.end # 추가로 attr로도 접근 가능

소수점 과 kiwipiepy_model 문의

아래와 같이 소수점이 있는 문장은 두개의 문장으로 분리되길래... 혹시 별도 설정이 필요할지 문의드립니다.
사용자 단어로 0.1 혹은 0.1%를 추가해도 단어로 인식이 안돼서...

EBS 부모특강 - 0.1%의 비밀

EBS/SL + 부모/NNG + 특강/NNG + -/SO + 0/SN + ./SF
1/SN + %/SW + 의/JKG + 비밀/NNG

위와 같은 간단한 문장 테스트는 Kiwi_Gui 에서 먼저 테스트를 하는 경우가 있는데
우연잖게 이번에 배포해주신 Kiwi_Gui의 model 과 kiwipiepy_model 을 보게 되었는데 combiningRule.txt 이 다른 듯해서요...
kiwipiepy 업데이트시 kiwipiepy_model 가 같이 업데이트 되는 것 같지는 않기도 해서 따로 업데이트 해봤는데도 다르네요...
(나머지 파일들은 바이너리 비교해 보진 않았지만 날짜만 다른 것 같기는 한데...)

ARM64 wheel 지원이 혹시 가능할까요?

https://github.com/bab2min/kiwipiepy/blob/main/.github/workflows/deploy.yml

manylinux_aarch64 를 혹시 wheel 생성시 추가요청할 수 있을까요?

이와 같은 형태만 추가되면 될듯 싶습니다.

  build_archs:
    name: Build wheels manylinux_aarch64
    runs-on: ubuntu-20.04

    steps:
      - uses: actions/checkout@v2
        with:
          submodules: recursive

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v1
        with:
          platforms: all

      - name: Build wheels
        uses: pypa/[email protected]
        env:
          CIBW_ARCHS_LINUX: aarch64
          CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_24
          CC: gcc-9
          GXX: g++-9

      - uses: actions/upload-artifact@v2
        with:
          path: ./wheelhouse/*.whl

종결어미와 부사격조사가 함께 쓰인 부분을 문장으로 분리해버리는 이슈

아래의 문장이 포함된 문단을 split_into_sents을 사용해 분절했을 때 문장이 아래와 같이 두 문장으로 분리됩니다.

  1. Amazon Smbhav Venture Fund라는 이름의 해당 펀드를 통해 Amazon은 SMB들이 온라인을 통해 상품을 판매하고, 사업 운영을 디지털화 및 자동화함으로써 사업 범위를 해외로 확장할 수 있도록 돕는 스타트업들에 투자할 계획으로 총 몇 년 동안 펀드를 운영하게 될 지
  2. 에 대해서는 공개하지 않았습니다.

품사를 확인해보니 '-ㄹ 지'를 종결 어미로 인식해서 그 뒤에 나오는 부사격 조사인 '에'와 함께 쓰였을 경우를 구분하지 못하는 것 같습니다.

Token(form='하', tag='XSV', start=152, len=1)
Token(form='게', tag='EC', start=153, len=1)
Token(form='되', tag='VV', start=155, len=1)
Token(form='ᆯ', tag='ETM', start=155, len=1)
Token(form='지', tag='EF', start=157, len=1)
Token(form='에', tag='JKB', start=158, len=1)

이 경우 어떤 방향으로 해결해 나갈 수 있을까요?

나무위키를 분석하는데 320만~330만라인 쯤에서 항상 에러가 발생합니다.(코퍼스문제X)

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
라는 에러가 발생하는데

재현을 위해서는
https://mu-star.net/wikidb
위 링크에서 2020/03 나무위키 덤프 파일을 다운받으시고
아래 코드를 실행하시면 됩니다.

코드는 매우 간단합니다.

`from namuwiki.extractor import extract_text

def work(document):
return {
'title': "#"+document['title'],
'content': extract_text(document['text'])
}

with open('namuwiki200302.json', 'r', encoding='utf-8') as input_file:
namu_wiki = json.load(input_file)

with Pool() as pool:
documents = pool.map(work, namu_wiki)

with open("namuextrac.txt", 'w', encoding='utf-8') as outf:
for page in documents:
outf.write(page['title']+"\n")
outf.write(page['content']+"\n")
from kiwipiepy import Kiwi
kiwitags = ["NNG", "NNP", "XR", "VA", "VX", "SL"]

kiwi = Kiwi()
kiwi.load_user_dictionary('dicword.txt')
kiwi.prepare()

with open("namuextrac.txt", encoding='utf-8') as inf:
with open("kiwi-namu.txt", 'w', encoding='utf-8') as outf:
for i, result in enumerate(kiwi.analyze(inf.readlines())):
if i % 100000 == 0:
print(f'Analyzed {i}th row')
outf.write(' '.join(map(lambda x: x[0] if x[1] in kiwitags else "", result[0][0])) + "\n")`

이렇게 매우 짧은 구성입니다.

실행환경은 3900X, 128GB입니다.
이외의 SSD와 GPU는 실행요소가 아니라서 기재하지 않았습니다.

항상 320만라인에서 330만라인쯤에서 에러가 발생합니다.
코퍼스의 문제인가 싶어 해당 라인을 찾아가 앞뒤로 10라인씩 지워봤지만
380만라인에서 에러가 발생하는 것으로 보아 에러의 발생을 늦출 뿐입니다.

혹시나 20개로 나눠서 동작시키면 가능할까 해보았지만
같은 에러가 뜨며 동작하지 않았고
20개의 파일을 수작업으로 하나씩 돌리고 파이썬이 완전히 종료된 후 다시 실행해보아도
매번 비슷한 320만 ~ 330만 라인쯤에서 에러가 발생합니다.
에러가 나는 정확한 위치는 계속 수십~수백라인사이에서 바뀌지만
문제가 되는 라인을 지우더라도 계속해서 에러는 다른 곳에서 발생합니다.

해당 에러메세지를 인터넷에 찾아보니 스레드가 서로 공유하는 메모리에서 변수를 바꾸는 것과 관련된 이슈로 보입니다.
디버깅 부탁드립니다.

python 3.7에서 IOhandler에 오류가 뜹니다.

아니콘다 python3.7버전에서 사용하려고 했습니다
예제 맨 밑의 IOhandler클래스를 그대로 가져다 썼는데
if id == 0:
self.input.seek(0) <--여기서 오류가 납니다.
파이썬 3.6버전으로 하니 다시 잘 동작합니다.
확인부탁드려요

reader와 receiver 파이썬 리스트 활용 가능 여부

안녕하세요. 키위를 연구에 활용중인 대학원생입니다.
bab2min님 블로그도 자주 들어가서 보고있는데요. 이자리를 빌어 감사의 말씀 드리고 싶습니다.
얼마전에 석사논문도 읽었는데 좋은 연구 논문이었습니다. 저에게도 많은 영감을 주셔서 또한 감사합니다.

다름이 아니라 토크나이징에서 reader 와 receiver를 따로 분리해 속도를 높일 수 있는데요.

  1. 이걸 파이썬 리스트 형태로 receiver 처리가 가능한건지 예컨대 파일 형태로 write 하는 것이 아니라 바로 파이썬 리스트에 저장하면 속도가 떨어지는지요?
  2. 또한 reader, receiver를 따로 설정해 토크나이징 할 경우 블로그에서 쓰신 것처럼 사용자에 맞는 토크나이징이 가능한지 궁금합니다. 아래는 블로그에서 보여주신 코드 입니다.

def tokenize(sent):
res, score = kiwi.analyze(sent)[0] # 첫번째 결과를 사용
return [word + ('다' if tag.startswith('V') else '') # 동사에는 '다'를 붙여줌
for word, tag, _, _ in res
if not tag.startswith('E') and not tag.startswith('J') and not tag.startswith('S') and word not in stopwords] # 조사, 어미, 특수기호 및 stopwords에 포함된 단어는 제거

사용 방법 문의

안녕하세요 @bad2min님, 최신이 최고야! 라는 생각에 kiwi가지고 형태소 분석을 해보고 있습니다.
사용하는 중 문의사항이 있어 문의 드립니다.

  1. extractWords method 를 분석 했을때 나오는 점수들의 의미가 궁금합니다.
    샘플 결과 ('브랜드', 4.506464004516602, 22, -2.085695505142212)
    각각의 의미와 숫자들이 어떤 방식으로 매겨지는지 알고 싶습니다.

  2. extract_add_words method를 통해 추가되는 사용자 사전은 해당 클래스에만 적용이 되고 파이썬 인터프리터 종료시 종료되는 일시적인 사전으로 봐야하는지 궁금합니다. 그리고 저장시 단어명 tab NNP tab 스코어 로 저장이 되는지, 아니면 단어명 Tab NNP 로 저장이 되는지 문의합니다.

  3. 사용자 사전의 단어 점수의 범위는 어떻게 될까요? soynlp는 0~1 이었는데 예시에 3이 있어서 얼마가 최대인지 궁금합니다.

감사합니다.

특정 표현의 tokenize 불가 문제

안녕하세요

kiwi tokenizer를 사용 중, 특정 형태의 한국어 텍스트가 들어가면 kiwi가 빈 리스트를 반환합니다.

오류 발생 조건은 아래와 같습니다.

from kiwipiepy import Kiwi
# kiwi = Kiwi()
kiwi = Kiwi(num_workers=0, model_path=None, load_default_dict=True, integrate_allomorph=True)



for er in err.split():   # err는 list of string입니다
    if kiwi.tokenize(er) == []:   # 문제가 있는 경우 이 결과가 빈 리스트로 나옵니다
        print(err)   # 문제가 있는 경우에서의 원문
        print('>>>', er, kiwi.tokenize(er))   # 문제가 생긴 단어와 그때의 토크나이징 결과
        print('--')


 중견기업 
 끊임없는 추락 
 미래불분며ㅇ 
 발전가능성없음 
 이건아니지
>>> 미래불분며ㅇ []
--

 바란다고 바뀌는 분들이 였으면 이미 회사는 많이 발전 했을것므로 말을 하지 않겠음
>>> 했을것므로 []
--

월급은 월급대로 안되고 일만 많은  
 충분히 클수 있믄 규모인데  확장해샤 사원복제에 힘써줬으면 
>>> 있믄 []
--

 정규직이어됴4대보험은알아서찾아넣고 최저시급도안나고 12시간정도 일한다 
 시간좀주여주고 최저시급이라도 주면좋겠다
>>> 정규직이어됴4대보험은알아서찾아넣고 []
--

성장하고 있믄 회사이나 직원 복지면에서 많이 부족하고 급여가 낮음 
>>> 있믄 []
--

 본인이 볼때는 구성원간에 장난도 잘치고 허물없이 지내는거 같아 보기 좋았고 서열간의 불화은 찾아보기 힘들었음 
 그에반몀 , 업무강도가 강하고 주말에도 출근하는 직원들도 많으며 , 퇴근을 제시간에 못할때가 많음 
 퇴근시간을 칼같이 지켜주기는것은 바라지 않지만 직원복지에 조금더 많은 관심을 주었으면
>>> 그에반몀 []
--

개발자가좋다정말로잘해주고남다릐다20자채우기빡세다 
 눈치안봄 , 광주에서 탑급은아니어도사람답게살수있다 눈치도안보고집삼 
>>> 개발자가좋다정말로잘해주고남다릐다20자채우기빡세다 []
--


 연봉도 같은업계에서는 높은편이다 
 단점이라고하면 업무편자이다 
 정말 일이없는 부서도 있는반며 
 야근만 주구장창하는 부서도있다 
 근데 이베이가 정체도있는시기인것같아 
>>> 있는반며 []
--

각 텍스트는 온라인에서 수집된 기업 리뷰의 일부입니다.
주로 정확한 한글 표현이 아닌 오탈자 발생시에 문제가 생기는 것 같습니다.

오타교정 기능과 join 기능을 동시에 활용시 발생하는 에러

안녕하세요, 잘쓰고 있습니다.

다음과 같은 코드 실행시 컴파일러가 튕기는 에러가 발생합니다.

from kiwipiepy import Kiwi
kiwi = Kiwi(typos='basic')
kiwi.join(kiwi.analyze('쁘'))

'쁘' 외에도 쁜, 쁨, 쯔, 쯥, 조아 등이 input으로 들어가면 같은 에러가 발생합니다.

또한 typos 기능 사용시 튜플형태의 문장을 입력하면 에러가 발생합니다.

from kiwipiepy import Kiwi
kiwi = Kiwi(typos='basic')
kiwi.join([('사랑','NNG')])

감사합니다.

숫자를 포함한 고유명사를 인식 하지 못 하는 경우 (추가)

안녕하세요!
아래에도 등록된 이슈와 같이
'k9', 'k55' 등 영문+숫자, 한글+숫자로 이루어진 단어의 경우 사용자 사전에 추가를 해도 토크나이징이 제대로 되지 않는 현상이 있습니다.

제가 사용하는 버젼은 kiwipiepy v0.13.1 이구요.

"k9 k55" 를 토크나이징 했을 때 결과는 아래와 같습니다.


kiwi.add_user_word("k9", "NNP")
kiwi.add_user_word("k55", "NNP")
kiwi.tokenize("K9 K55")

[Token(form='K', tag='SL', start=0, len=1),
Token(form='9', tag='SN', start=1, len=1),
Token(form='K', tag='SL', start=3, len=1),
Token(form='55', tag='SN', start=4, len=2)]

사용자 사전 추가 삭제

안녕하세요.

사용자 사전추가한 단어 삭제를 하고싶은데 어떻게하면 될까요??
ex) kiwi.add_user_word("플랫폼", "NNP") 추가한 단어 삭제

그리고 혹시 사용자 사전을 엑셀이나 텍스트 파일로 관리 할 수 있는 기능이 있나요?

시작 위치 및 길이가 제대로 분석되지 않습니다.

안녕하세요, 먼저 좋은 프로그램 잘 쓰고 있습니다. 감사합니다.

$ python3 -m kiwipiepy
>>되었다
([('되', 'VV', 0, 1), ('었', 'EP', 1, 1), ('다', 'EC', 2, 1)], -12.622314453125)
>>됐다
([('되', 'VV', 1, 0), ('었', 'EP', 0, 1), ('다', 'EC', 1, 1)], -12.622314453125)
>>하였다
([('하', 'VV', 2, 0), ('었', 'EP', 1, 1), ('다', 'EC', 2, 1)], -16.640380859375)
>>했다
([('하', 'VV', 1, 0), ('었', 'EP', 0, 1), ('다', 'EC', 1, 1)], -16.640380859375)
>>

준말과 관련된 "시작 위치"가 조금 이상하게 동작하는 것 같습니다.

"시작 위치"를 "끝 위치에서 단어의 길이를 뺀 값"으로 생각하면 됐다했다의 경우는 이해가 갑니다만, 되었다에 비해 여전히 하였다가 작동하는 방식은 잘 이해가 가지 않습니다.

띄어쓰기 및 원형 복구 문제

안녕하세요!
전 현재 형태소 분석기가 필요한 라이브러리를 개발중인 개발자입니다. 지금은 khaiii를 사용중인데요. khaiii가 다른건 다 좋은데 배포하는게 까다로워요. 그래서 배포가 훨씬 간편한 kiwipiepy로 이전하려고 하는데요.

다만 문제가 하나 있어요. 제 프로젝트는 입력으로 주어지는 문장 속 띄어쓰기와 형태소 분석 이전의 원형을 복구하는 기능을 필요로 하는데요. 그게 khaiii에서는 쉽지만 kiwipiepy에서는 그렇지 않은 것 같아요.

예를 들어볼게요. 우선 khaiii를 사용하면 다음과 같이 토큰화 후에도 손쉽게 띄어쓰기와 원형을 복구할 수 있어요:

sent = "시끄럽게 코고는 소리에 놀라서 난 잠이 깼다."
api = KhaiiiApi()
    tokens = api.analyze(sent)
    print(" ".join([token.lex for token in tokens]))
시끄럽게 코고는 소리에 놀라서 난 잠이 깼다.

반면, kiwipiepy를 사용해서 똑같은 기능을 구현하는 것이 쉽지도, 정확하지도 않아요. 우선 띄어쓰기 복구는 token.starttoken.len을 잘 활용해서 어찌저찌 가능은 하지만, 아래처럼 코드가 khaiii에 비해 너무 지저분해집니다. 그리고 띄어쓰기를 복구하더라도, khaiii처럼 입력된 원형을 접근하는 방법이 없어요. 그래서 아래처럼 코고는코골는으로, 놀라서놀라어서로 훼손돼요.

sent = "시끄럽게 코고는 소리에 놀라서 난 잠이 깼다."
kiwi = Kiwi()
    tokens = kiwi.tokenize(sent)
    starts = np.array([token.start for token in tokens] + [0])
    lens = np.array([token.len for token in tokens] + [0])
    sums = np.array(starts) + np.array(lens)
    spacings = (starts[1:] - sums[:-1]) > 0  # if it is greater than 1, than it should be spaced.
    texts = [token.form + " " if spacing else token.form for token, spacing in zip(tokens, spacings)]
    sent = "".join(texts)
    print(sent)
시끄럽게 코골는 소리에 놀라어서 난 잠이 깨었다.

이 문제만 khaiii처럼 해결만 된다면 바로 kiwipiepy로 이전이 가능할 것 같은데요. 혹시 이 부분 패치가 가능할까요?

좋은 라이브러리를 계속 업데이트 해주셔서 감사합니다 :)

문장 분리 문제

~할까 걱정 => ~할까 / 걱정
~할까 봐요 => ~할까 / 봐요
~지 싶다 => ~지 / 싶다
~할까 싶다 => ~할까 / 싶다

하나의 문장으로 인식하지 못하고 분리되는 문제가 있네요.

키위 패키지 너무 잘 사용하고 있습니다. 연구 개발 정말 감사드립니다~ :)

사용자 사전 추가시 100kb가 넘는 데이터에 관하여 형태소분석 수행불가

안녕하세요, 성능 좋은 형태소분석기 개발에 감사합니다.

현재 저는 ubuntu 21.04, python 3.9.4 환경에서 개발 중이며,
시스템은 Ryzen 3950x, RAM 32G*3, (samsung 980pro 1TB) 세팅으로 사용 중입니다.
개인적으로 구성한 아래 사용자 사전을 로딩하여 형태소 분석기 실행시 커널이 죽어버립니다(주피터 노트북).
py파일로 컴파일하여 터미널에서 실행시킬 경우 다음과 같은 오류를 호출합니다.
: 세그멘테이션 오류 (코어 덤프됨)

메모리 문제여서 시스템 사용량도 체크를 하였으나 해당 부분엔 로드가 없고
100kb이하의 텍스트 파일을 분석하는 별도의 py파일을 구성하고 터미널에서 반복 실행해야 오류가 나지 않는 것을 확인했습니다.(100kb가 넘는 데이터에 분석시 메모리 에러 발생)

사용자 사전이나 텍스트에서 단어사전을 추출하여 구성하는 기능을 사용하지 않으면 이러한 버그가 생기지 않습니다.

아래는 분석에 사용한 소스코드입니다. 필요하시면 이메일로 분석데이터도 보내드리겠습니다.

감사합니다.

from kiwipiepy import Kiwi
kiwi = Kiwi()
#no matter of num_workers or options

kiwi.load_user_dictionary('userDic.txt')
kiwi.prepare()

with open('corpus.txt', 'r') as file:
    corpus = file.readlines()

tokenList = {'NNG': '일반 명사', 'NNP': '고유 명사', 'VV': '동사', 'VA': '형용사'}
corpus2 = []
with open('/home/tony/reviews_tokenized.csv','a') as file:
    for item in kiwi.analyze(corpus):
        for token in item[0][0]:
            if token[1] in tokenList:
                file.write(token[0]+',')
        file.write('\n')

문의사항

안녕하세요 사용 중에 문의사항이 생겨 이슈 남깁니다

  1. 사용자 사전 추가
    Kiwi.add_user_word(word, pos, score, orig_word=None)
    위 코드로 사용사 단어를 추가하려 하면, pos argument가 없다고 나오네요
    따로 키워드를 명시하지 않고 넣으면 돌아는 갑니다
    내부적으로 함수의 키워드가 바뀌었는데 설명에 반영이 아직 안된건가요?

  2. 형태소 분석 후 종성
    가족적인 분위기를 분석하면 ['가족', '적', '이', 'ᆫ', '분위기'] 로 결과가 나오는데,
    이때 종성인 ㄴ이 일반적인 키보드로 입력하는 ㄱㄴㄷㄹ...의 ㄴ이 아닌걸로 나오네요
    종성이 분리되는 것 까진 괜찮은데, 이게 regex의 ㄱ-ㅎ 범위에 포함되지 않아 문제입니다.
    혹시 이걸 일반적인 자음으로 바꿀 수 있는 옵션을 추가해주실 수 있나요?

그럼 좋은 형태소 분석기 만들어주셔서 감사합니다.

인용문이 여러개 포함된 문장을 인식하지 못하는 문제

안녕하세요,
지난 번에 빠른 피드백으로 많은 도움 얻었습니다.
계속해서 같은 모듈 사용 중에 문제가 발생했는데요,
문장 안에 인용문이 여러개 포함되어 있을 경우에 문장을 하나로 파악하지 못하는 것 같습니다.

예를 들어 아래와 같은 문장의 경우 세 문장으로 구분을 해냅니다.

'조현준 효성그룹 회장도 신년사를 통해 “속도와 효율성에 기반한 민첩한 조직으로 탈바꿈해야 한다며 “이를 위해 무엇보다 데이터베이스 경영이 뒷받침돼야 한다”고 말했다.'

['조현준 효성그룹 회장도 신년사를 통해 “속도와 효율성에 기반한 민첩한 조직으로 탈바꿈해야 한다”',
'며 “이를 위해 무엇보다 데이터베이스 경영이 뒷받침돼야 한다”',
'고 말했다.']

이 경우 어떤 것이 문제이고, 어떻게 해결 가능할까요?

12.0 버전에서는 기본 stopwords.txt 가 없어진건가요?

이전에는 stopwords.txt 기본값이 있었던 것 같은데 이번 버전에는 없는 듯 보이는군요...
소스상에는 test_corpus에 custom_stopwords.txt으로는 있던데
기존에 제가 만들어 둔 것에는 stopwords를 정의하는 루틴이 있는데 kiwipiepy/corpus/stopwords.txt 에 파일이 없다고 종료되길래요...

cmake 설치 명시 필요

@bab2min
안녕하세요~
pip install kiwipiepy를 통해 설치시 cmake 없어 오류가 발생했습니다.
README.md에 명시하거나 혹은 pypi 배포시 dependency를 지정하면 좋을 것 같습니다.

오류 내용 남겨놓습니다.

$ pip install kiwipiepy
Collecting kiwipiepy
  Downloading kiwipiepy-0.10.3.tar.gz (5.6 MB)
     |████████████████████████████████| 5.6 MB 17.1 MB/s
  Preparing metadata (setup.py) ... done
Collecting kiwipiepy_model~=0.10
  Downloading kiwipiepy_model-0.10.0.tar.gz (25.7 MB)
     |████████████████████████████████| 25.7 MB 31.8 MB/s
  Preparing metadata (setup.py) ... done
Building wheels for collected packages: kiwipiepy, kiwipiepy-model
  Building wheel for kiwipiepy (setup.py) ... error
  ERROR: Command errored out with exit status 1:
   command: /Users/daniellee/Develop/konlpy_py3/.venv/bin/python -u -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/x8/rtsz9nj93kdd9vy3_52zngfc0000gn/T/pip-install-x9wpd0g6/kiwipiepy_76fc195f2ea24fec8420046853ff440c/setup.py'"'"'; __file__='"'"'/private/var/folders/x8/rtsz9nj93kdd9vy3_52zngfc0000gn/T/pip-install-x9wpd0g6/kiwipiepy_76fc195f2ea24fec8420046853ff440c/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /private/var/folders/x8/rtsz9nj93kdd9vy3_52zngfc0000gn/T/pip-wheel-ipcqpesv
       cwd: /private/var/folders/x8/rtsz9nj93kdd9vy3_52zngfc0000gn/T/pip-install-x9wpd0g6/kiwipiepy_76fc195f2ea24fec8420046853ff440c/
  Complete output (29 lines):
  running bdist_wheel
  running build
  running build_py
  creating build
  creating build/lib.macosx-10.14.6-arm64-3.8
  creating build/lib.macosx-10.14.6-arm64-3.8/kiwipiepy
  copying kiwipiepy/_version.py -> build/lib.macosx-10.14.6-arm64-3.8/kiwipiepy
  copying kiwipiepy/_wrap.py -> build/lib.macosx-10.14.6-arm64-3.8/kiwipiepy
  copying kiwipiepy/__init__.py -> build/lib.macosx-10.14.6-arm64-3.8/kiwipiepy
  copying kiwipiepy/utils.py -> build/lib.macosx-10.14.6-arm64-3.8/kiwipiepy
  copying kiwipiepy/__main__.py -> build/lib.macosx-10.14.6-arm64-3.8/kiwipiepy
  running egg_info
  writing kiwipiepy.egg-info/PKG-INFO
  writing dependency_links to kiwipiepy.egg-info/dependency_links.txt
  writing requirements to kiwipiepy.egg-info/requires.txt
  writing top-level names to kiwipiepy.egg-info/top_level.txt
  reading manifest file 'kiwipiepy.egg-info/SOURCES.txt'
  reading manifest template 'MANIFEST.in'
  no previously-included directories found matching 'Kiwi/ModelGenerator'
  no previously-included directories found matching 'Kiwi/eval_data'
  adding license file 'LICENSE.txt'
  writing manifest file 'kiwipiepy.egg-info/SOURCES.txt'
  copying kiwipiepy/documentation.rst -> build/lib.macosx-10.14.6-arm64-3.8/kiwipiepy
  creating build/lib.macosx-10.14.6-arm64-3.8/kiwipiepy/corpus
  copying kiwipiepy/corpus/stopwords.txt -> build/lib.macosx-10.14.6-arm64-3.8/kiwipiepy/corpus
  running build_ext

  ERROR: CMake must be installed to build dlib

  ----------------------------------------
  ERROR: Failed building wheel for kiwipiepy

kiwi의 발전을 항상 기원합니다.

분석을 돌리면 단어가 바뀌는 현상?

진짜 푸짐하고 뜨끈~하게 맛있는 감자탕 먹엇어용!
저는 감자탕하면 살코기는 별로 없고 뼈만 크다구 생각햇는데
완전 5산 오브 5산,,, 여긴시 살코기도 푸짐하고
식감도 부드러워서 너무 맛잇게 잘 먹엇다는 ㅜㅜ♥️
바람 쌩쌩불고 밖에 나가지도 못하는데
이렇게 든든하구 맛난 밀키트 하나만 잇어도
온 가족 저녁 걱정은 필요 없다구요🥺🥺♥️
라면사리랑 신선한 야채도 잘 포장되어 와서
양도 푸짐하니 든든한 느낌😌😌
감자도 포슬포슬하니 맛나고 따로 포장되어 좋앗어요🥰
국물도 맛잇어서 밥도 국물 사라질때까지 말아먹기 가능👍🏻
저에게 감자탕에 대한 편견을 깨준 감자탕패밀리!!
이젠 집에서 간단하게 끓이기만 해두 사먹는 것보다
맛잇게 먹을 수 잇는 시대라니,,, 넘나 좋은것

위 문장 분석시 "신선한 야채도 잘 포장되어 와서" 부분에서 와서가 왜 오어서로 변경되는건가요?

('포장', 'NNP', 205, 2), ('되', 'XSV', 207, 1), ('어', 'EC', 208, 1), ('오', 'VV', 211, 1), ('어서', 'EC', 210, 2), ('양도', 'NNG', 213, 2)

끊어진 텍스트 결합하기

문제 상황

OCR 결과나 PDF 등에서 추출된 텍스트의 경우 줄이 바뀔 때마다 강제 개행이 들어가는 문제가 있음. 예를 들어 다음과 같은 텍스트가 있다고 하면

그러나  알고보니 그 봉
지 안에 있던 것은 바로
레몬이었던 것이다.

여기서 추출된 텍스트는 그러나 알고보니 그 봉\n지 안에 있던 것은 바로\n레몬이었던 것이다.와 같은 모양이 된다.
그리고 \n는 공백으로 처리되어 뜻하지 않게 봉지로 분해되고, 여기서 발생한 오류가 다음 단계로 전파되는 문제가 있다.
봉\n지에 있는 강제개행은 제거하여 봉지로, 바로\n레몬의 경우 그냥 개행은 공백으로 복원해주는 기능이 있으면 굉장히 유용할듯 하다.

구현 방법

형태소 분석기가 사용하는 언어 모델을 이용하여 \n을 뺀 경우와 공백으로 바꾼 경우의 언어 모델 점수를 비교하면 어떤 것이 더 자연스러운 연결인지 확인할 수 있을 듯하다.

kiwi.analyze("그러나  알고보니 그 봉지 안에 있던 것은 바로")[0][1] # -54.1859
kiwi.analyze("그러나  알고보니 그 봉 지 안에 있던 것은 바로")[0][1] # -70.9644

kiwi.analyze("지 안에 있던 것은 바로레몬이었던 것이다.")[0][1] # -60.1843
kiwi.analyze("지 안에 있던 것은 바로 레몬이었던 것이다.")[0][1] # -60.1843

봉-지의 경우 둘을 붙인 경우가 더 높은 점수가 나왔으므로, 둘 사이는 붙이고, 바로-레몬의 경우는 붙이나 떼나 점수 차이가 없으므로 공백을 삽입하는 식..?

인터페이스

강제개행으로 분리된 텍스트를 붙여주는 기능이므로 glue라는 이름이 좋아보인다.

chunks = [
  "그러나  알고보니 그 봉",
  "지 안에 있던 것은 바로",
  "레몬이었던 것이다.",
]
result = kiwi.glue(chunks) # Iterable[str]을 받아서 적절하게 결합된 str을 반환해준다.
# "그러나  알고보니 그 봉지 안에 있던 것은 바로 레몬이었던 것이다."

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.