Git Product home page Git Product logo

kiwi's People

Contributors

bab2min avatar emiatej9 avatar kkweon avatar mrchypark avatar xdfc1745 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kiwi's Issues

0.11.1 버전 모델 파일 배포 문의

항상 감사합니다.

이번 0.11.1 버전 배포에 모델이 base만 배포 된 것을 확인하였습니다.

혹시 패치 버전에서는 더 배포하지 않으시려고 하시는 것인지 궁금합니다.

[제안] 모델 파일을 레포에서 분리

현재 base 모델을 git-lfs 를 이용해서 관리하고 있는 것으로 알고 있습니다.
git-lfs가 많이 쓰이는 것은 맞습니다만 기본으로 사용되는 도구는 아닌 점을 고려하였습니다.
그리고 모델이 많아지고 있음으로 보아 모델 파일 관리를 분리하는 것을 제안합니다.

검토해봐주시면 감사하겠습니다.

static 빌드에 -fPIC 옵션 추가 하는 방법 문의

안녕하세요, 좋은 패키지 개발해주셔서 감사합니다.

다름이 아니라 static 파일을 사용해서 패키지를 만들어서 사용하려고 하는데요.
현재 cmake의 빌드를 그대로 사용하면 kiwi_static.a 생성시 -fPIC 옵션을 사용하지 않는 것을 확인했습니다.

혹시 cmake 명령에서 추가하는 방법이 있는 것인지, 아니면 cmake를 수정해야 하는 것인지 문의드립니다.

googletest에서 cmake deprecation warning 발생

현재 cmake 3.19.2 버전을 사용하고 있는데 cmake -DCMAKE_BUILD_TYPE=Release ../ 명령 실행 시에 다음과 같은 deprecation waring 이 발생합니다.

CMake Deprecation Warning at third_party/googletest/CMakeLists.txt:1 (cmake_minimum_required):
  Compatibility with CMake < 2.8.12 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.

googletest에서 발생하는 것으로 보이는데, googletest에서는 Bump CMake minimum to 2.8.12 에서 해당 이슈가 해결되었고, v1.11.0 에 반영되어있습니다.

현재 서브모듈로 포함되어있는 googletest 는 v1.8.x 네요. googletest 버전을 올려되 되지 않을까 합니다.

Light 버전 모델 지원 문의

좋은 프로젝트 공유해 주셔서 감사합니다!
KNLM 파일이 약 50MB 정도 되는데요.
혹시 지금보다 더 경량화한 버전의 모델을 지원하실 계획은 없는지 궁금합니다.
감사합니다^^

KiwiBuilder 소멸자 호출 시, pointer being freed was not allocated 에러 발생

안녕하세요. 테스트를 위해 아래와 같이 간단한 코드 작성 후 실행하였는데 pointer being freed was not allocated 에러가 발생합니다.

  • 소스코드
int main() {
  const std::string model_path = "./model";
  const std::u16string sentence = u"이것은 먹이다.";

  kiwi::KiwiBuilder kiwiBuilder =
     kiwi::KiwiBuilder{model_path, 0, kiwi::BuildOption::none};

  kiwi::Kiwi kiwi = kiwiBuilder.build();
  kiwi::TokenResult tokenResult = kiwi.analyze(sentence, kiwi::Match::all);

  std::wcout.imbue(std::locale("ko_KR.UTF-8"));
  std::wcout << convert(sentence, tokenResult) << std::endl;

  return 0;
}
  • 실행결과
❯ ./build/kiwi-analyzer
이것/NP + 은/JX + 먹이/NNG + 이/VCP + 다/EF + ./SF
kiwi-analyzer(80276,0x11377fe00) malloc: *** error for object 0x20000044600: pointer being freed was not allocated
kiwi-analyzer(80276,0x11377fe00) malloc: *** set a breakpoint in malloc_error_break to debug

main 함수가 종료되면서 KiwiBuilder 의 소멸자가 호출되는 과정에서 발생하는 에러로 짐작하고 있습니다.
아래는 stack backtrace 입니다.

❯ lldb build/kiwi-analyzer
(lldb) target create "build/kiwi-analyzer"
Current executable set to '/Users/hongmin/Documents/projects/Kiwi-App/build/kiwi-analyzer' (x86_64).
(lldb) run
Process 80391 launched: '/Users/hongmin/Documents/projects/Kiwi-App/build/kiwi-analyzer' (x86_64)
이것/NP + 은/JX + 먹이/NNG + 이/VCP + 다/EF + ./SF
kiwi-analyzer(80391,0x100a17e00) malloc: *** error for object 0x20000044600: pointer being freed was not allocated
kiwi-analyzer(80391,0x100a17e00) malloc: *** set a breakpoint in malloc_error_break to debug
Process 80391 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff2038b92e libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
->  0x7fff2038b92e <+10>: jae    0x7fff2038b938            ; <+20>
    0x7fff2038b930 <+12>: movq   %rax, %rdi
    0x7fff2038b933 <+15>: jmp    0x7fff20385ad9            ; cerror_nocancel
    0x7fff2038b938 <+20>: retq
Target 0: (kiwi-analyzer) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff2038b92e libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff203ba5bd libsystem_pthread.dylib`pthread_kill + 263
    frame #2: 0x00007fff2030f406 libsystem_c.dylib`abort + 125
    frame #3: 0x00007fff201ef165 libsystem_malloc.dylib`malloc_vreport + 548
    frame #4: 0x00007fff201f22aa libsystem_malloc.dylib`malloc_report + 151
    frame #5: 0x0000000100005895 kiwi-analyzer`std::__1::_DeallocateCaller::__do_call(__ptr=0x0000020000044600) at new:334:12
    frame #6: 0x0000000100005879 kiwi-analyzer`std::__1::_DeallocateCaller::__do_deallocate_handle_size(__ptr=0x0000020000044600, __size=48) at new:292:12
    frame #7: 0x0000000100005851 kiwi-analyzer`std::__1::_DeallocateCaller::__do_deallocate_handle_size_align(__ptr=0x0000020000044600, __size=48, __align=2) at new:262:12
    frame #8: 0x0000000100005825 kiwi-analyzer`std::__1::__libcpp_deallocate(__ptr=0x0000020000044600, __size=48, __align=2) at new:340:3
    frame #9: 0x000000010000b33c kiwi-analyzer`std::__1::allocator<char16_t>::deallocate(this=0x0000000101d257b8, __p=u"화엄일승법계도", __n=24) at memory:1673:10
    frame #10: 0x000000010000b2b5 kiwi-analyzer`std::__1::allocator_traits<std::__1::allocator<char16_t> >::deallocate(__a=0x0000000101d257b8, __p=u"화엄일승법계도", __n=24) at memory:1408:14
    frame #11: 0x000000010000b27c kiwi-analyzer`std::__1::basic_string<char16_t, std::__1::char_traits<char16_t>, std::__1::allocator<char16_t> >::~basic_string(this=u"화엄일승법계도") at string:2198:9
    frame #12: 0x0000000100003b95 kiwi-analyzer`std::__1::basic_string<char16_t, std::__1::char_traits<char16_t>, std::__1::allocator<char16_t> >::~basic_string(this=u"화엄일승법계도") at string:2193:1
    frame #13: 0x00000001000088ff kiwi-analyzer`kiwi::FormT<true>::~FormT(this=0x0000000101d257b8) at Form.h:51:9
    frame #14: 0x00000001000088c8 kiwi-analyzer`kiwi::Form::~Form(this=0x0000000101d257b8) at Form.h:89:9
    frame #15: 0x00000001000088a5 kiwi-analyzer`kiwi::Form::~Form(this=0x0000000101d257b8) at Form.h:89:9
    frame #16: 0x0000000100008889 kiwi-analyzer`std::__1::allocator<kiwi::Form>::destroy(this=0x00007ffeefbff600, __p=0x0000000101d257b8) at memory:1686:92
    frame #17: 0x000000010000885d kiwi-analyzer`void std::__1::allocator_traits<std::__1::allocator<kiwi::Form> >::__destroy<kiwi::Form>((null)=std::__1::true_type @ 0x00007ffeefbff418, __a=0x00007ffeefbff600, __p=0x0000000101d257b8) at memory:1578:21
    frame #18: 0x000000010000882d kiwi-analyzer`void std::__1::allocator_traits<std::__1::allocator<kiwi::Form> >::destroy<kiwi::Form>(__a=0x00007ffeefbff600, __p=0x0000000101d257b8) at memory:1419:14
    frame #19: 0x00000001000087db kiwi-analyzer`std::__1::__vector_base<kiwi::Form, std::__1::allocator<kiwi::Form> >::__destruct_at_end(this=0x00007ffeefbff5f0, __new_last=0x0000000101b00000) at vector:428:9
    frame #20: 0x000000010000870b kiwi-analyzer`std::__1::__vector_base<kiwi::Form, std::__1::allocator<kiwi::Form> >::clear(this=0x00007ffeefbff5f0) at vector:371:29
    frame #21: 0x0000000100008577 kiwi-analyzer`std::__1::__vector_base<kiwi::Form, std::__1::allocator<kiwi::Form> >::~__vector_base(this=0x00007ffeefbff5f0) at vector:465:9
    frame #22: 0x0000000100008488 kiwi-analyzer`std::__1::vector<kiwi::Form, std::__1::allocator<kiwi::Form> >::~vector(this=0x00007ffeefbff5f0 size=57167) at vector:557:5
    frame #23: 0x0000000100005f85 kiwi-analyzer`std::__1::vector<kiwi::Form, std::__1::allocator<kiwi::Form> >::~vector(this=0x00007ffeefbff5f0 size=57167) at vector:552:5
    frame #24: 0x0000000100005ede kiwi-analyzer`kiwi::Kiwi::~Kiwi(this=0x00007ffeefbff5e8) at Kiwi.h:35:8
    frame #25: 0x0000000100004805 kiwi-analyzer`kiwi::Kiwi::~Kiwi(this=0x00007ffeefbff5e8) at Kiwi.h:35:8
    frame #26: 0x0000000100004454 kiwi-analyzer`main at main.cc:58:1
    frame #27: 0x00007fff203d5f3d libdyld.dylib`start + 1

자세한 코드는 https://github.com/emiatej9/Kiwi-App 에 있습니다

  • 실행환경
❯ uname -a
Darwin Yangui-MacBookPro.local 20.6.0 Darwin Kernel Version 20.6.0: Wed Jun 23 00:26:31 PDT 2021; root:xnu-7195.141.2~5/RELEASE_X86_64 x86_64

macOS 에서 conda 환경 설치 에러

conda create 로 "kiwi" 이름으로 작성한후, conda install 진행할 시 아래와 같은 에러가 납니다.

제가 python이 어색해서 잘 진행이 안되는데, 어떻게 하면 좋을까요? 미리 감사드립니다.

Collecting kiwipiepy==0.6.5
  Using cached https://files.pythonhosted.org/packages/78/97/40ac16b89e85796739dc57428747ddb430d14178daf32ae62ec3c128b201/kiwipiepy-0.6.5.tar.gz
Building wheels for collected packages: kiwipiepy
  Building wheel for kiwipiepy (setup.py): started
  Building wheel for kiwipiepy (setup.py): finished with status 'error'
  ERROR: Complete output from command /Users/sktelecom/Miniconda3/envs/kiwi/bin/python -u -c 'import setuptools, tokenize;__file__='"'"'/private/var/folders/2m/p_q96v4n11j36h38tcd6yj540000gn/T/pip-install-sst956nx/kiwipiepy/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /private/var/folders/2m/p_q96v4n11j36h38tcd6yj540000gn/T/pip-wheel-rv26j6s3 --python-tag cp37:
  ERROR: running bdist_wheel
  running build
  running build_py
  creating build
  creating build/lib.macosx-10.7-x86_64-3.7
  creating build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
  copying kiwipiepy/__init__.py -> build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
  copying kiwipiepy/__main__.py -> build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
  running egg_info
  writing kiwipiepy.egg-info/PKG-INFO
  writing dependency_links to kiwipiepy.egg-info/dependency_links.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'
  writing manifest file 'kiwipiepy.egg-info/SOURCES.txt'
  copying kiwipiepy/default.dict -> build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
  copying kiwipiepy/extract.mdl -> build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
  copying kiwipiepy/sj.lang -> build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
  copying kiwipiepy/sj.morph -> build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
  running build_ext
  building 'kiwipiepycore' extension
  creating build/temp.macosx-10.7-x86_64-3.7
  creating build/temp.macosx-10.7-x86_64-3.7/KiwiLibrary
  gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/sktelecom/Miniconda3/envs/kiwi/include -arch x86_64 -I/Users/sktelecom/Miniconda3/envs/kiwi/include -arch x86_64 -I/Users/sktelecom/Miniconda3/envs/kiwi/include/python3.7m -c KiwiLibrary/Utils.cpp -o build/temp.macosx-10.7-x86_64-3.7/KiwiLibrary/Utils.o -std=c++1y -O3 -fpermissive
  warning: include path for stdlibc++ headers not found; pass '-stdlib=libc++' on the command line to use the libc++ standard library instead [-Wstdlibcxx-not-found]
  In file included from KiwiLibrary/Utils.cpp:1:
  In file included from KiwiLibrary/stdafx.h:8:
  KiwiLibrary/KiwiHeader.h:3:10: fatal error: 'cstring' file not found
  #include <cstring>
           ^~~~~~~~~
  1 warning and 1 error generated.
  error: command 'gcc' failed with exit status 1
  ----------------------------------------
  ERROR: Failed building wheel for kiwipiepy
  Running setup.py clean for kiwipiepy
Failed to build kiwipiepy
Installing collected packages: kiwipiepy
  Running setup.py install for kiwipiepy: started
    Running setup.py install for kiwipiepy: finished with status 'error'
    ERROR: Complete output from command /Users/sktelecom/Miniconda3/envs/kiwi/bin/python -u -c 'import setuptools, tokenize;__file__='"'"'/private/var/folders/2m/p_q96v4n11j36h38tcd6yj540000gn/T/pip-install-sst956nx/kiwipiepy/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /private/var/folders/2m/p_q96v4n11j36h38tcd6yj540000gn/T/pip-record-t53vucj0/install-record.txt --single-version-externally-managed --compile:
    ERROR: running install
    running build
    running build_py
    creating build
    creating build/lib.macosx-10.7-x86_64-3.7
    creating build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
    copying kiwipiepy/__init__.py -> build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
    copying kiwipiepy/__main__.py -> build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
    running egg_info
    writing kiwipiepy.egg-info/PKG-INFO
    writing dependency_links to kiwipiepy.egg-info/dependency_links.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'
    writing manifest file 'kiwipiepy.egg-info/SOURCES.txt'
    copying kiwipiepy/default.dict -> build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
    copying kiwipiepy/extract.mdl -> build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
    copying kiwipiepy/sj.lang -> build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
    copying kiwipiepy/sj.morph -> build/lib.macosx-10.7-x86_64-3.7/kiwipiepy
    running build_ext
    building 'kiwipiepycore' extension
    creating build/temp.macosx-10.7-x86_64-3.7
    creating build/temp.macosx-10.7-x86_64-3.7/KiwiLibrary
    gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/sktelecom/Miniconda3/envs/kiwi/include -arch x86_64 -I/Users/sktelecom/Miniconda3/envs/kiwi/include -arch x86_64 -I/Users/sktelecom/Miniconda3/envs/kiwi/include/python3.7m -c KiwiLibrary/Utils.cpp -o build/temp.macosx-10.7-x86_64-3.7/KiwiLibrary/Utils.o -std=c++1y -O3 -fpermissive
    warning: include path for stdlibc++ headers not found; pass '-stdlib=libc++' on the command line to use the libc++ standard library instead [-Wstdlibcxx-not-found]
    In file included from KiwiLibrary/Utils.cpp:1:
    In file included from KiwiLibrary/stdafx.h:8:
    KiwiLibrary/KiwiHeader.h:3:10: fatal error: 'cstring' file not found
    #include <cstring>
             ^~~~~~~~~
    1 warning and 1 error generated.
    error: command 'gcc' failed with exit status 1
    ----------------------------------------
ERROR: Command "/Users/sktelecom/Miniconda3/envs/kiwi/bin/python -u -c 'import setuptools, tokenize;__file__='"'"'/private/var/folders/2m/p_q96v4n11j36h38tcd6yj540000gn/T/pip-install-sst956nx/kiwipiepy/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /private/var/folders/2m/p_q96v4n11j36h38tcd6yj540000gn/T/pip-record-t53vucj0/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /private/var/folders/2m/p_q96v4n11j36h38tcd6yj540000gn/T/pip-install-sst956nx/kiwipiepy/
Error: Error 1 occurred installing packages into conda environment kiwi

ㅋㅋㅋ등이 따라 붙는 경우 처리

특히 음절에 ㅋ이 덧붙어서 분석에 실패하는 경우가 많음.
이를 분리해서 처리하는 옵션을 추가하면 좋을듯

예: 그거 아닌뎈ㅋㅋ -> 그거 아닌데 + ㅋㅋㅋ

간단한 오타가 포함된 텍스트 분석시 오류를 교정하는 기능 추가

연속적인 입력을 처리해야하는 형태소 분석의 특성상 앞 부분에서 발생한 오류 때문에 뒷부분까지 분석 결과가 틀어지는 일이 잦다. 특히 인터넷 텍스트를 분석하는 경우 오타가 매우 자주 입력되는데, 이 때문에 문장 전체가 잘못 분석될 수 있다.

>>> kiwi.tokenize("뛰엇습니다")
[Token(form='뛰엇', tag='NNG', start=0, len=2), Token(form='습니다', tag='EC', start=2, len=3)]
>>> kiwi.tokenize("되지를 먹었다")
[Token(form='되', tag='VV', start=0, len=1), Token(form='지', tag='EC', start=1, len=1), Token(form='를', tag='JKO', start=2, len=1), Token(form='먹', tag='VV', start=4, len=1), Token(form='었', tag='EP', start=5, len=1), Token(form='다', tag='EC', start=6, len=1)]
>>> kiwi.tokenize("체식주의자세요?")
[Token(form='체식주의자세', tag='NNP', start=0, len=6), Token(form='요', tag='JX', start=6, len=1), Token(form='?', tag='SF', start=7, len=1)]

ㅅ/ㅆㅐ/ㅔ/ㅒ/ㅖ, ㅚ/ㅙ/ㅞ, 므/무, 브/부, 프/푸 등은 자주 혼동되어 틀리게 쓰는 경우가 많은 자소 쌍인데, 이런 경우는 탐색 범위가 좁아서 비교적 쉽게 오류를 교정할 수 있을 것으로 보인다. 오타 때문에 분석 전체가 틀어진 경우는 최종 분석 스코어가 매우 낮게 나오는 특징이 있기 때문.

>>> kiwi.analyze("체식주의자세요?")
[([Token(form='체식주의자세', tag='NNP', start=0, len=6), Token(form='요', tag='JX', start=6, len=1), Token(form='?', tag='SF', start=7, len=1)], -40.00871276855469)]
>>> kiwi.analyze("채식주의자세요?")
[([Token(form='채식주의자', tag='NNG', start=0, len=5), Token(form='이', tag='VCP', start=6, len=1), Token(form='시', tag='EP', start=6, len=1), Token(form='어요', tag='EF', start=5, len=2), Token(form='?', tag='SF', start=7, len=1)], -24.523874282836914)]

체식주의자세요?의 경우 약 -40, 채식주의자세요?의 경우 약 -24 정도로 점수 차이가 극단적인 것을 볼 수 있다. 따라서 오타 복원 옵션이 추가하여, 이 옵션이 참인 경우에는 형태소 트라이를 구축시 채식주의자 형태에 이형태로 체식주의자를 넣어서 함께 구축하고, 탐색시 체식주의자라는 형태에도 채식주의자가 일치되도록 한다(단, 오타 개수에 따라 penalty를 부여). 이러면 기초적인 오타를 교정하면서 오류가 문장 뒷쪽까지 전파되는 것을 막는 것이 어느 정도 가능할 것으로 보인다.

다만 언어모델을 이용한 교정은 확률이 높은쪽을 따라가게 되므로, 철자가 비슷한 두 단어가 있는 경우(결제/결재) 맞는 표현임에도 과도교정하는 경우가 발생할 수 있고, 또한 탐색 범위가 늘어나서 분석 속도에도 영향을 미칠 수 있으므로 기본으로 제공하지는 않고, 옵션으로 선택할 수 있도록 한다.

kiwi = Kiwi() # spell_correct의 기본값은 False
kiwi_correction = Kiwi(spell_correct=True) # 교정 옵션을 켜서 모델 생성
tokens = kiwi_correction.tokenize("체식주의자세요?")
# tokens: [Token(form='채식주의자', tag='NNG', start=0, len=5), Token(form='이', tag='VCP', start=6, len=1), Token(form='시', tag='EP', start=6, len=1), Token(form='어요', tag='EF', start=5, len=2), Token(form='?', tag='SF', start=7, len=1)]
tokens[0].form # 채식주의자
tokens[0].is_corrected # True (교정이 적용되었는지 유무)
tokens[0].raw_form # 체식주의자 (교정 전의 원래 형태)

한글이 포함된 경로가 있는 경우 오류

pyinstaller를 통해 컴파일시 model 파일들을 포함하도록 했는데
사용자 이름이 한글인 경우 임시 폴더에도 한글이 포함되게 되어 오류가 나서 문의드립니다...

Uncaughted c++ exception: Failed to open model file 'C:\Users?쒖쓽??1\AppData\Local\Temp_MEI241162./model/extract.mdl'.Traceback (most recent call last):
.....
File "kiwipiepy_wrap.py", line 67, in init
RuntimeError: Failed to open model file 'C:\Users\한글~1\AppData\Local\Temp_MEI241162./model/extract.mdl'.

부분적으로 분석된 문자열에 대해 형태소 분석을 수행하는 기능

기능 설명

형태소 분석시 일부 형태소가 이미 분석된 경우 나머지 부분만 추가로 분석하여 전체 분석결과를 반환하는 기능

유용성

  1. 이미 고유 명사구에 대해 태깅이 완료된 텍스트가 제공되는 경우가 많음:
    예) 함안(咸安) 사람 전 부사직(副司直) 조성준(趙成俊) 이 그 아우 조성복(趙成福) 과 불화하여 ... (굵은 부분이 고유 명사구(엔티티)로 태깅된 부분)
  2. 형태소 분석기에 의해 분할되지 않기를 바라는 특수 패턴이 있는 경우가 있음. 형태소 분석 결과를 후처리하는 것도 가능하기는 하지만 이렇게 하면 번거로운 경우가 많으므로, 해당 부분을 미리 정규식으로 매칭하여 묶어낸 뒤 나머지 부분에 대해서만 형태소 분석을 수행하면 유용할 것.
    예) 4!1 * 2 * 3 * 4 와 같이 계산됩니다. (굵은 부분이 패턴으로 묶어내고 싶은 부분.)

구현

입력 처리

analyze함수가 복수 개의 Text Span을 입력받는 것을 허용. 각 Text Span은 총 3가지 종류를 지원한다.

  1. Raw: 분석이 진행되어야할 텍스트
  2. Split: 분할만 되고 품사 태그가 붙지 않은 텍스트. (반드시 한 형태소로 분석되어야 함)
  3. Analyzed: 이미 분석이 끝난 텍스트. 1개 이상의 형태소로 구성됨

Beam 탐색

Raw Text Span에 대해서는 기존과 동일하게 분할 뒤 경로 탐색 진행.
Split Text Span에 대해서는 분할 없이 품사 태그로만 분기하여 경로 탐색 진행.
Analyzed Text Span에 대해서는 분기 없이 결정된 형태소 경로를 일직선으로 탐색 진행.
위 3종류 Text Span이 서로 연속적으로 이어진 경우에도 매끄럽게 탐색이 진행되도록 Path를 효율적으로 구축하는게 필요.

인용문구 부호? 사용자정의사전? 어떤 문제일지...

"윗뱃살빼기 허리살빼기만으로는 안될거 같아."

텍스트 분석 중 위와 같은 인용문구가 들어간 경우가 있었는데 결과가 이상해
제가 혹시나 잘못 적용했나 해서 배포해주신 키위형태소 분석기 GUI (v0.11.0)로 해봤는데도 약간 이상해서요...

"윗뱃/NNG + 살/NNG + 빼/VV + 기/ETN + 허리살빼기/NNG + 만/JX + 으로/JKB + 는/JX + 안/MAG + 되/VV + ᆯ/ETM + 거/NNB + 같/VA + 어/EF + ./SF
"/SS

사용자 정의 사전을 활용해야 할 문제인지 인용문구 부호문제일지 해서 문의드려봅니다...

용언 형태소의 불규칙 활용 여부 표지 추가

#54 가 구현되려면 용언류 형태소의 불규칙 활용여부를 분석과정에서 탐지해내야 한다.

이를 위해서 불규칙 활용과 규칙 활용이 동시에 존재하는 형태소의 경우 각각 별도의 형태소로 모델에 등재하고

Kiwi/include/kiwi/Form.h

Lines 29 to 35 in c59ed5e

struct MorphemeRaw
{
uint32_t kform = 0; /**< 형태에 대한 포인터 */
POSTag tag = POSTag::unknown; /**< 품사 태그 */
CondVowel vowel = CondVowel::none; /**< 선행형태소의 자/모음 조건 */
CondPolarity polar = CondPolarity::none; /**< 선행형태소의 모음조화 조건 */

에 새로운 필드를 추가하여 해당 형태소가 규칙활용인지 불규칙활용인지 표기하도록 한다.

사전 & 모델 생성 쪽과 연관이 깊은 수정 사항이므로 #39와 병행하여 작업하면 좋을듯 하다.

`KiwiBuilder::addWord` 순서에 따라 분석결과가 달라지는 문제

bab2min/kiwipiepy#58 에서 처음 제보된 문제로, c++용 재현가능한 코드는 다음과 같다:

KiwiBuilder builder{ MODEL_PATH };
builder.addWord(u"울트라리스크", POSTag::nnp, 3.0);
builder.addWord(u"파일즈", POSTag::nnp, 0.0);
Kiwi kiwi = builder.build();
TokenResult res = kiwi.analyze(u"울트라리스크가 뭐야?", Match::all);
KiwiBuilder builder{ MODEL_PATH };
builder.addWord(u"파일즈", POSTag::nnp, 0.0);
builder.addWord(u"울트라리스크", POSTag::nnp, 3.0);
Kiwi kiwi = builder.build();
TokenResult res = kiwi.analyze(u"울트라리스크가 뭐야?", Match::all);

위 두 코드는 builder에 addWord로 단어를 추가하는 순서만 다를뿐이라 동일한 결과가 나와야하지만 전자는 울트라리스크/NNP가 뽑히지만, 후자는 울트라/NNG + 리스크/NNG로 잘못 뽑히는 문제가 있다.

kiwi R package 제안

안녕하세요, 소중한 패키지 제작해 주셔서 정말 감사드립니다.

다름이 아니라 kiwi를 R 패키지화 하는 작업을 진행하고 있는데요.
혹시 제가 계속 제작해서 제공해도 괜찮을지 문의드리려고 합니다.

https://github.com/mrchypark/Elbird

다시 한 번 좋은 패키지 제작해주셔서 대단히 감사드립니다.

이/VCP 생략 추적

모음으로 끝나는 명사 뒤에서는 이/VCP가 생략될 수 있는데, 현재 시스템에서는 반영이 안됨.

사용법을 알려 주십시오

안녕하십니까?

윈도우용 그리고 리눅스용 바이너리를 설치했습니다

kiwi-cli
kiwi-evaluator
kiwi-test

3가지 실행 파일이 있는데요, 각 실행 파일의 역할과 사용법을 알려 주시기 바랍니다

그리고, kiwi model이라는 것이 있는데요, 이것은 무엇을 말하는 것인지
어떻게 사용하는지 알려주시면 감사 드리겠습니다

형태소에서 텍스트를 복원하는 기능 추가

하/VV + 었/EP + 다/EF => 했다
집/NNG + 에/JKB + 가/VV + 었/EP + 어/EF => 집에 갔어
등과 같이 형태소 배열을 받았을때 이를 다시 합쳐 원래의 텍스트로 복원하는 기능이 있으면 좋을듯.

이 기능이 구현되면 Kiwi 형태소 분석기를 일종의 tokenizer처럼 임의의 text를 encode/decode하는 데 사용하는것이 가능해짐.

단, 이 기능을 위해서는 용언류 형태소의 불규칙 활용여부를 판단할 수 있는 기능이 필요하다. 이는 다음과 같이 동일한 어간을 가지는 형태소가 다르게 활용될 가능성이 있기 때문:
묻/VV + 어/EC => 묻어 (규칙 활용)
묻/VV + 어/EC => 물어 (불규칙 활용)

사실 불규칙 활용여부 판단 기능은 #42 와도 어느 정도 연관되지만, 일단 단순한 구현을 위해서 표층형에서 확실히 구별되는 경우에만 규칙/불규칙 표지를 붙이고(ex: 물어 vs 묻어), 구분되지 않는 경우에는 미정인 상태로 두는 것으로(ex: 묻다 vs 묻다) 진행해도 무방할듯.

규칙적으로 변형된 형태소를 이용자 사전에 쉽게 추가하기

사투리나 인터넷 어투 등에서는 표준어의 형태소를 일정한 규칙으로 변형해서 사용하는 경우들이 꽤 있다. 대표적인 사례가 어미(EF)로, 받침이나 음절을 덧붙여서 새로운 어미를 생성하는게 용이하기 때문에 폭 넓게 쓰이며 사람이나 기계가 이를 규칙으로 파악하기도 쉽다.
예:

  • 으로 교체: 했어요 -> 했어용, 해봐요 -> 해봐용, 하세요 -> 하세용
  • 습니다슴다로 교체: 했습니다 -> 했슴다, 하겠습니다 -> 하겠슴다

위와 같이 변형된 형태소는 분석기가 스스로 잡아낼 수는 없기 때문에 이용자 사전을 통해서 관리되어야 한다. 문제는 변형된 형태소를 일일히 사전에 추가하는게 굉장히 번거롭다는 점이다. 일례로 -> 규칙이 적용가능한 어미(EF) 형태소의 목록만 해도 100종류가 넘는다. (예: 어요, 아요, 에요, 지요, 거든요 ...)
따라서 이런 변형된 형태소들을 이용자가 직접 추가하도록 하기보다는 이용자는 변형 규칙만 입력하고 시스템 상에서 규칙을 통해 자동으로 변형된 형태소를 생성하여 자동 추가하는게 좋아보인다. 변형 규칙은 Python re 모듈의 sub함수를 따라가도록 한다. 또한 규칙을 통해 변형하여 형태소를 추가할 경우 해당 변형 형태소의 원본 형태소가 무엇인지 시스템이 파악할 수 있으므로, 언어모델 탐색시 출현 확률 정보가 없는 변형 형태소 대신 원본 형태소를 사용하여 분석 성능을 높이는 것도 가능할 듯하다.

kiwi = Kiwi()
# EF 품사들 중 정규표현식 '요$'에 매칭되는 형태소만 골라내어 '요$'를 '용'으로 바꾸어 이용자 사전에 추가
# penalty는 언어 모델 탐색시 변형 형태소에 부여될 확률 점수 페널티. '어용'이 '어요'보다는 낮은 점수를 가지도록 하여, EF가 아닌 다른 '어용'이라는 형태소가 분석 결과 순위에서 밀려나는 일을 줄이기 위함.
result = kiwi.add_user_rule(tag='EF', pattern=r'요$', repl='용', penalty=-1.0) 
# result: 추가된 변형 형태소의 리스트를 반환한다(예: ['어용', '아용', '에용', ...] )

외국어 문자 태그 개선

현재 A-Z, a-z 범위의 단순 로마자 알파벳에 대해서만 SL 태그를 붙이며, diacritic이 붙은 문자에 대해서는 SW 태그를 붙여주게 되어 있는데, 이를 개선하여 diacritic 유무와 관계없이 로마자 알파벳에는 일괄적으로 SL을 붙여주는게 좋을 것 같습니다.
또한 알파벳 뿐만 아니라 히라가나, 가타카나나 키릴 문자, 그리스 문자 등 다양한 외국어 글자들에 대한 태그로 추가할 수 있으면 좋겠습니다.

loadDictionary에서 tag를 제대로 인식 못하는 문제

tag 문자열 뒤에 whitespace가 붙어있는 경우 tag 인식 실패하는 문제가 있음
tag 뒤에 뒤따르는 whitespace가 있는 경우 이를 제거할 필요가 있음

Kiwi/src/KiwiBuilder.cpp

Lines 427 to 442 in 0996518

while (getline(ifs, line))
{
auto wstr = utf8To16(line);
if (wstr[0] == u'#') continue;
auto fields = split(wstr, u'\t');
if (fields.size() < 2) continue;
if (!fields[1].empty())
{
auto pos = toPOSTag(fields[1]);
float score = 0.f;
if (fields.size() > 2) score = stof(fields[2].begin(), fields[2].end());
if (pos == POSTag::max)
{
throw Exception("[loadUserDictionary] Unknown Tag '" + utf16To8(fields[1]) + "'");
}

참고 이슈: bab2min/kiwipiepy#48 (comment)

분석 오류

고기를 굽다. -> 고기/NNG + 를/JKO + 굽/VV + 이/VCP + 다/EF + ./SF
: V계열 태그는 연속하여 나타날 수 없음

'은'은 광물이다. -> '/SS + 은/JX + '/SS + 은/JX + 광물/NNG + 이/VCP + 다/EF + ./SF

포은 정몽주 -> 포/NNG + 은/JX + 정몽주/NNP
: 결합조건을 어기는 J태그

소수점 분할 버그

bab2min/kiwipiepy#79 (@nowtoday) 에서 제보된 버그

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

0.1이 0/SN ./SF 1/SN로 분리되어 분석되며, 사용자 사전을 이용해도 수정할 수 없는 문제가 있음.

typedef int(*kiwi_reader_t)(int, char*, void*); 사용법 문의

안녕하세요, 형태소 분석기를 개발해 주셔서 정말 감사드립니다.

다름이 아니라 capi를 이용해서 다른 wrapper 패키지(golang)를 만들고 있는 중인데요.
extract_word 함수에서 사용하는 콜백함수 파라미터인 kiwi_reader_t 가 어떻게 동작해야 하는지 잘 모르겠어서 질문드립니다.

혹시 바쁘시겠지만, 설명을 좀 더 추가해주실 수 있으신가요?

파생 동사/형용사 분석 시 어근과 어미를 통합하여 분석하기

사랑하다 같은 경우 사랑/NNG + 하/XSV + 다/EF와 같이 분석되는데
종종 동사/형용사의 경우 어근을 분리하지 않고 전체형인 사랑하/VV + 다/EF와 같이 분석하는게 용이할 때도 있음.
파생 동사/형용사의 품사 패턴은 일정하므로 후처리에서 옵션을 통해 일괄적으로 결합하는게 가능할듯

(NN.|XR) + XSV =>VV
(NN.|XR) + XSA => VA

CMake compile 과정 문의

안녕하세요. Kiwi를 사용해보고자 CMake를 활용해 설치하고자 하는데, 오류가 나서 문의드립니다.
환경은 아래와 같습니다.

  • Ubuntu 18.04
  • GCC 7.5.0 (C++14 지원)

별도의 지시사항이 없어서 다음과 같이 실행했습니다.

cmake .
make

오류는 다음과 같습니다.

[ 10%] Building CXX object CMakeFiles/kiwi_cli-0.6.6.out.dir/src/runner.cpp.o
In file included from /home/bydelta/git/Kiwi/src/core/Kiwi.h:5:0,
                 from /home/bydelta/git/Kiwi/src/runner.cpp:5:
/home/bydelta/git/Kiwi/src/core/ThreadPool.h: In constructor ‘ThreadPool::ThreadPool(size_t, size_t)’:
/home/bydelta/git/Kiwi/src/core/ThreadPool.h:38:7: warning: ‘ThreadPool::stop’ will be initialized after [-Wreorder]
  bool stop;
       ^~~~
/home/bydelta/git/Kiwi/src/core/ThreadPool.h:37:9: warning:   ‘size_t ThreadPool::maxQueued’ [-Wreorder]
  size_t maxQueued;
         ^~~~~~~~~
/home/bydelta/git/Kiwi/src/core/ThreadPool.h:42:8: warning:   when initialized here [-Wreorder]
 inline ThreadPool::ThreadPool(size_t threads, size_t _maxQueued)
        ^~~~~~~~~~
In file included from /home/bydelta/git/Kiwi/src/core/KModelMgr.h:3:0,
                 from /home/bydelta/git/Kiwi/src/core/Kiwi.h:7,
                 from /home/bydelta/git/Kiwi/src/runner.cpp:5:
/home/bydelta/git/Kiwi/src/core/KNLangModel.h: In member function ‘void kiwi::KNLangModel::Node::setLL(kiwi::KNLangModel::WID, float)’:
/home/bydelta/git/Kiwi/src/core/KNLangModel.h:210:27: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
     next[n] = *(int32_t*)&ll;
                           ^~
/home/bydelta/git/Kiwi/src/runner.cpp: In function ‘int main(int, const char**)’:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26: error: no matching function for call to ‘begin(std::pair<std::vector<kiwi::KWordPair>, float>&)’
     for (const auto& c : cands)
                          ^~~~~
In file included from /usr/include/c++/7/string:51:0,
                 from /usr/include/c++/7/stdexcept:39,
                 from /usr/include/c++/7/array:39,
                 from /home/bydelta/git/Kiwi/src/core/KiwiHeader.h:7,
                 from /home/bydelta/git/Kiwi/src/runner.cpp:4:
/usr/include/c++/7/bits/range_access.h:105:37: note: candidate: template<class _Tp> const _Tp* std::begin(const std::valarray<_Tp>&)
   template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
                                     ^~~~~
/usr/include/c++/7/bits/range_access.h:105:37: note:   template argument deduction/substitution failed:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26: note:   ‘std::pair<std::vector<kiwi::KWordPair>, float>’ is not derived from ‘const std::valarray<_Tp>’
     for (const auto& c : cands)
                          ^~~~~
In file included from /usr/include/c++/7/string:51:0,
                 from /usr/include/c++/7/stdexcept:39,
                 from /usr/include/c++/7/array:39,
                 from /home/bydelta/git/Kiwi/src/core/KiwiHeader.h:7,
                 from /home/bydelta/git/Kiwi/src/runner.cpp:4:
/usr/include/c++/7/bits/range_access.h:104:31: note: candidate: template<class _Tp> _Tp* std::begin(std::valarray<_Tp>&)
   template<typename _Tp> _Tp* begin(valarray<_Tp>&);
                               ^~~~~
/usr/include/c++/7/bits/range_access.h:104:31: note:   template argument deduction/substitution failed:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26: note:   ‘std::pair<std::vector<kiwi::KWordPair>, float>’ is not derived from ‘std::valarray<_Tp>’
     for (const auto& c : cands)
                          ^~~~~
In file included from /usr/include/c++/7/string:51:0,
                 from /usr/include/c++/7/stdexcept:39,
                 from /usr/include/c++/7/array:39,
                 from /home/bydelta/git/Kiwi/src/core/KiwiHeader.h:7,
                 from /home/bydelta/git/Kiwi/src/runner.cpp:4:
/usr/include/c++/7/bits/range_access.h:87:5: note: candidate: template<class _Tp, long unsigned int _Nm> constexpr _Tp* std::begin(_Tp (&)[_Nm])
     begin(_Tp (&__arr)[_Nm])
     ^~~~~
/usr/include/c++/7/bits/range_access.h:87:5: note:   template argument deduction/substitution failed:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26: note:   mismatched types ‘_Tp [_Nm]’ and ‘std::pair<std::vector<kiwi::KWordPair>, float>’
     for (const auto& c : cands)
                          ^~~~~
In file included from /usr/include/c++/7/string:51:0,
                 from /usr/include/c++/7/stdexcept:39,
                 from /usr/include/c++/7/array:39,
                 from /home/bydelta/git/Kiwi/src/core/KiwiHeader.h:7,
                 from /home/bydelta/git/Kiwi/src/runner.cpp:4:
/usr/include/c++/7/bits/range_access.h:58:5: note: candidate: template<class _Container> decltype (__cont.begin()) std::begin(const _Container&)
     begin(const _Container& __cont) -> decltype(__cont.begin())
     ^~~~~
/usr/include/c++/7/bits/range_access.h:58:5: note:   template argument deduction/substitution failed:
/usr/include/c++/7/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.begin()) std::begin(const _Container&) [with _Container = std::pair<std::vector<kiwi::KWordPair>, float>]’:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26:   required from here
/usr/include/c++/7/bits/range_access.h:58:56: error: ‘const struct std::pair<std::vector<kiwi::KWordPair>, float>’ has no member named ‘begin’
     begin(const _Container& __cont) -> decltype(__cont.begin())
                                                 ~~~~~~~^~~~~
/usr/include/c++/7/bits/range_access.h:48:5: note: candidate: template<class _Container> decltype (__cont.begin()) std::begin(_Container&)
     begin(_Container& __cont) -> decltype(__cont.begin())
     ^~~~~
/usr/include/c++/7/bits/range_access.h:48:5: note:   template argument deduction/substitution failed:
/usr/include/c++/7/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.begin()) std::begin(_Container&) [with _Container = std::pair<std::vector<kiwi::KWordPair>, float>]’:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26:   required from here
/usr/include/c++/7/bits/range_access.h:48:50: error: ‘struct std::pair<std::vector<kiwi::KWordPair>, float>’ has no member named ‘begin’
     begin(_Container& __cont) -> decltype(__cont.begin())
                                           ~~~~~~~^~~~~
In file included from /usr/include/c++/7/utility:76:0,
                 from /usr/include/c++/7/array:38,
                 from /home/bydelta/git/Kiwi/src/core/KiwiHeader.h:7,
                 from /home/bydelta/git/Kiwi/src/runner.cpp:4:
/usr/include/c++/7/initializer_list:89:5: note: candidate: template<class _Tp> constexpr const _Tp* std::begin(std::initializer_list<_Tp>)
     begin(initializer_list<_Tp> __ils) noexcept
     ^~~~~
/usr/include/c++/7/initializer_list:89:5: note:   template argument deduction/substitution failed:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26: note:   ‘std::pair<std::vector<kiwi::KWordPair>, float>’ is not derived from ‘std::initializer_list<_Tp>’
     for (const auto& c : cands)
                          ^~~~~
/home/bydelta/git/Kiwi/src/runner.cpp:134:26: error: no matching function for call to ‘end(std::pair<std::vector<kiwi::KWordPair>, float>&)’
In file included from /usr/include/c++/7/string:51:0,
                 from /usr/include/c++/7/stdexcept:39,
                 from /usr/include/c++/7/array:39,
                 from /home/bydelta/git/Kiwi/src/core/KiwiHeader.h:7,
                 from /home/bydelta/git/Kiwi/src/runner.cpp:4:
/usr/include/c++/7/bits/range_access.h:107:37: note: candidate: template<class _Tp> const _Tp* std::end(const std::valarray<_Tp>&)
   template<typename _Tp> const _Tp* end(const valarray<_Tp>&);
                                     ^~~
/usr/include/c++/7/bits/range_access.h:107:37: note:   template argument deduction/substitution failed:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26: note:   ‘std::pair<std::vector<kiwi::KWordPair>, float>’ is not derived from ‘const std::valarray<_Tp>’
     for (const auto& c : cands)
                          ^~~~~
In file included from /usr/include/c++/7/string:51:0,
                 from /usr/include/c++/7/stdexcept:39,
                 from /usr/include/c++/7/array:39,
                 from /home/bydelta/git/Kiwi/src/core/KiwiHeader.h:7,
                 from /home/bydelta/git/Kiwi/src/runner.cpp:4:
/usr/include/c++/7/bits/range_access.h:106:31: note: candidate: template<class _Tp> _Tp* std::end(std::valarray<_Tp>&)
   template<typename _Tp> _Tp* end(valarray<_Tp>&);
                               ^~~
/usr/include/c++/7/bits/range_access.h:106:31: note:   template argument deduction/substitution failed:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26: note:   ‘std::pair<std::vector<kiwi::KWordPair>, float>’ is not derived from ‘std::valarray<_Tp>’
     for (const auto& c : cands)
                          ^~~~~
In file included from /usr/include/c++/7/string:51:0,
                 from /usr/include/c++/7/stdexcept:39,
                 from /usr/include/c++/7/array:39,
                 from /home/bydelta/git/Kiwi/src/core/KiwiHeader.h:7,
                 from /home/bydelta/git/Kiwi/src/runner.cpp:4:
/usr/include/c++/7/bits/range_access.h:97:5: note: candidate: template<class _Tp, long unsigned int _Nm> constexpr _Tp* std::end(_Tp (&)[_Nm])
     end(_Tp (&__arr)[_Nm])
     ^~~
/usr/include/c++/7/bits/range_access.h:97:5: note:   template argument deduction/substitution failed:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26: note:   mismatched types ‘_Tp [_Nm]’ and ‘std::pair<std::vector<kiwi::KWordPair>, float>’
     for (const auto& c : cands)
                          ^~~~~
In file included from /usr/include/c++/7/string:51:0,
                 from /usr/include/c++/7/stdexcept:39,
                 from /usr/include/c++/7/array:39,
                 from /home/bydelta/git/Kiwi/src/core/KiwiHeader.h:7,
                 from /home/bydelta/git/Kiwi/src/runner.cpp:4:
/usr/include/c++/7/bits/range_access.h:78:5: note: candidate: template<class _Container> decltype (__cont.end()) std::end(const _Container&)
     end(const _Container& __cont) -> decltype(__cont.end())
     ^~~
/usr/include/c++/7/bits/range_access.h:78:5: note:   template argument deduction/substitution failed:
/usr/include/c++/7/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.end()) std::end(const _Container&) [with _Container = std::pair<std::vector<kiwi::KWordPair>, float>]’:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26:   required from here
/usr/include/c++/7/bits/range_access.h:78:54: error: ‘const struct std::pair<std::vector<kiwi::KWordPair>, float>’ has no member named ‘end’; did you mean ‘second’?
     end(const _Container& __cont) -> decltype(__cont.end())
                                               ~~~~~~~^~~
                                               second
/usr/include/c++/7/bits/range_access.h:68:5: note: candidate: template<class _Container> decltype (__cont.end()) std::end(_Container&)
     end(_Container& __cont) -> decltype(__cont.end())
     ^~~
/usr/include/c++/7/bits/range_access.h:68:5: note:   template argument deduction/substitution failed:
/usr/include/c++/7/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.end()) std::end(_Container&) [with _Container = std::pair<std::vector<kiwi::KWordPair>, float>]’:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26:   required from here
/usr/include/c++/7/bits/range_access.h:68:48: error: ‘struct std::pair<std::vector<kiwi::KWordPair>, float>’ has no member named ‘end’; did you mean ‘second’?
     end(_Container& __cont) -> decltype(__cont.end())
                                         ~~~~~~~^~~
                                         second
In file included from /usr/include/c++/7/utility:76:0,
                 from /usr/include/c++/7/array:38,
                 from /home/bydelta/git/Kiwi/src/core/KiwiHeader.h:7,
                 from /home/bydelta/git/Kiwi/src/runner.cpp:4:
/usr/include/c++/7/initializer_list:99:5: note: candidate: template<class _Tp> constexpr const _Tp* std::end(std::initializer_list<_Tp>)
     end(initializer_list<_Tp> __ils) noexcept
     ^~~
/usr/include/c++/7/initializer_list:99:5: note:   template argument deduction/substitution failed:
/home/bydelta/git/Kiwi/src/runner.cpp:134:26: note:   ‘std::pair<std::vector<kiwi::KWordPair>, float>’ is not derived from ‘std::initializer_list<_Tp>’
     for (const auto& c : cands)
                          ^~~~~
CMakeFiles/kiwi_cli-0.6.6.out.dir/build.make:62: recipe for target 'CMakeFiles/kiwi_cli-0.6.6.out.dir/src/runner.cpp.o' failed
make[2]: *** [CMakeFiles/kiwi_cli-0.6.6.out.dir/src/runner.cpp.o] Error 1
CMakeFiles/Makefile2:72: recipe for target 'CMakeFiles/kiwi_cli-0.6.6.out.dir/all' failed
make[1]: *** [CMakeFiles/kiwi_cli-0.6.6.out.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

Python 3 모듈의 setup.py는 build가 잘 되던데, 혹시 설정에 차이가 있나요?

구두점 없는 긴 텍스트 분할하여 처리하기

현재 분석기 알고리즘 상 입력 텍스트가 길수록 속도가 느려지고 정확도도 떨어지는 한계가 있음.
이를 회피하기 위해 마침표를 기준으로 입력 텍스트를 분할하여 여러 단위로 각각 분석을 실시한 뒤 다시 결합하는 방식을 사용중.
그러나 일부 웹 텍스트의 경우 명시적으로 마침표를 사용하지 않고 문장을 길게 잇는 경우도 있어 분석 정확도가 크게 손실되는 문제가 있음.
이에 다음과 같은 개선 방안을 제안

  1. 간단한 규칙기반 문장 분리기를 사용하여 빠르게 텍스트를 분할하기
  2. 전이 그래프에서 노드가 한 곳으로 모이는 지점을 찾아내어 해당 지점 전후로 동적으로 그래프 분할하기

새버전 `iostream` 에러

오류

안녕하세요! 새롭게 릴리즈하신 Kiwi v0.11.0를 설치 후, 전에는 없던 오류가 발생하고 있어 기존의 코드가 아예 실행조차되지 않는군요. 운영체제는 macOS Monterey이며 CPU는 M1 입니다. 혹시 확인해주실 수 있을까요?

실행코드

from kiwipiepy import Kiwi


kiwi = Kiwi()

sent = "시끄럽게 코고는 소리에 놀라서 난 잠이 깼다."


def main():
    tokens = kiwi.tokenize(sent)
    for token in tokens:
        print(token)


if __name__ == '__main__':
    main()

오류메시지

/Users/eubinecto/Desktop/Projects/Big/politetune/venv/bin/python /Users/eubinecto/Desktop/Projects/Big/politetune/explore/explore_kiwi_indices.py
Uncaughted c++ exception: Cannot open '/Users/eubinecto/Desktop/Projects/Big/politetune/venv/lib/python3.9/site-packages/kiwipiepy_model/sj.morph': unspecified iostream_category error
Traceback (most recent call last):
  File "/Users/eubinecto/Desktop/Projects/Big/politetune/explore/explore_kiwi_indices.py", line 4, in <module>
    kiwi = Kiwi()
  File "/Users/eubinecto/Desktop/Projects/Big/politetune/venv/lib/python3.9/site-packages/kiwipiepy/_wrap.py", line 63, in __init__
    super().__init__(
RuntimeError: Cannot open '/Users/eubinecto/Desktop/Projects/Big/politetune/venv/lib/python3.9/site-packages/kiwipiepy_model/sj.morph': unspecified iostream_category error

Process finished with exit code 1

ARM64 컴파일 오류

출처: bab2min/kiwipiepy#54
대부분의 코드는 c++ 표준에 맞춰 작성되어 있어서 아키텍처에 의존적인 부분이 적지만, 일부 코드가 최적화를 위해 x86-64 intrinsic을 사용하고 있음. 이 부분만 수정해주면 ARM64를 비롯한 다양항 아키텍처에서 동작 가능할 것으로 보임. 문제가 되는 부분은 다음 두 파일.

#include <immintrin.h>

#include <immintrin.h>

이용자 사전 기능 강화

기능 설명

현재 이용자 사전에는 형태소 1개짜리 단어만 등록이 가능하다. 공백을 포함하는 여러 단어를 추가하거나 특정 패턴의 분석 방법을 설정해 등록할 수 있도록 하면 유용할듯.

여러 단어로 구성된 엔트리 등록

복합 명사 : 복합_명사/NNP

복합 명사 혹은 복합명사라는 표현을 만나면 복합_명사/NNP로 분석할 수 있도록 단어를 추가한다

이 기능은 형태소 Trie를 탐색시 공백으로 분리된 토큰을 한 덩어리로 묶어서 처리하는 기능이 지원되어야 개발 가능함.

기분석된 패턴 등록

튕겼 : 튕기다/VV + 었/EP

튕겼을 만나면 튕기다/VV + 었/EP으로 분석할 수 있도록 사전에 표층형-실질형을 등록한다.

이미 내부 사전에는 chunks라는 이름으로 여러 형태소를 한 덩어리로 묶고 이에 고유한 Form을 배정하는 기능이 등록되어 있음. 이 기능을 이용자 사전에서도 접근가능하도록 수정하면 될 것으로 보임.

Kiwi/include/kiwi/Form.h

Lines 10 to 20 in 844474e

template<bool baked>
struct MorphemeT
{
typename std::conditional<baked, const KString*, uint32_t>::type kform = 0;
POSTag tag = POSTag::unknown;
CondVowel vowel = CondVowel::none;
CondPolarity polar = CondPolarity::none;
uint8_t combineSocket = 0;
typename std::conditional<baked, FixedVector<const Morpheme*>, std::vector<uint32_t>>::type chunks;
int32_t combined = 0;
float userScore = 0;

인용부호 및 괄호 태그 세분화

SS 태그에 할당되어 있는 인용부호 및 괄호의 경우 대개 여는 부호와 닫는 부호가 쌍으로 쓰인다. 여는 부호와 닫는 부호를 명확히 구분하여 각각 SSOSSC로 별도 태그를 할당한다면, 괄호나 인용문의 시작/끝을 처리하는데 품사 태그를 이용할 수 있을 것이다.
특히 인용문이나 괄호의 시작/끝을 처리한다면 여러 문장이 중첩된 텍스트의 문장 분리 기능(bab2min/kiwipiepy#84) 을 고도화하는 것이 가능.

명사 축약 분석 문제

텐데 => 터인데
내 => 나의

현재 모델은 위와 같이 축약되는 명사 + 조사형을 복원하는것을 수행하지 못함. 수정 필요.

분석 결과에 문장 번호 추가

품사 태그 EF를 기준으로 문장이 나뉜다고 가정하고, 이에 따라 문장 번호를 부여하면 유용할 것. 더 나아가 이 기능을 이용해 Kiwi에 문장 분리 기능을 추가할수도 있을 것으로 보인다.

linux 환경에서는 어떻게 쓰는건가요?

안녕하세요 블로그 잘 보고있는 사람입니다.

한번 kiwi 형태소분석기 사용해보려고 하는데, linux환경에서는 어떻게 사용하는건가요?

현재 제가 사용하는 OS가 UBUNTU 16.04 LTS 인데, KiwiRunLinux 폴더에 있는 파일은 비쥬얼스튜디오 프로젝트 파일인 것 같아서요...

감사합니다.

필수 사전 & 언어 모델 빌드 기능 API화하여 노출

현재 KiwiBuilder에 전처리된 사전 데이터로부터 KiwiBuilder를 생성하는 기능은 추가되어 있음.

Kiwi/include/kiwi/Kiwi.h

Lines 169 to 171 in 844474e

void loadMMFromTxt(std::istream&& is, MorphemeMap& morphMap, std::unordered_map<POSTag, float>* posWeightSum, const std::function<bool(float, POSTag)>& selector);
void loadCMFromTxt(std::istream&& is, MorphemeMap& morphMap);
void loadPCMFromTxt(std::istream&& is, MorphemeMap& morphMap);

또 말뭉치로부터 언어모델을 학습하는 기능도 하드코딩으로 구현은 되어있음.

Kiwi/src/KiwiBuilder.cpp

Lines 364 to 369 in 844474e

Vector<Vector<uint16_t>> sents;
addCorpusTo(sents, ifstream{ rawDataPath + "/ML_lit.txt" }, realMorph);
addCorpusTo(sents, ifstream{ rawDataPath + "/ML_spo.txt" }, realMorph);
vector<pair<uint16_t, uint16_t>> bigramList;
auto cntNodes = utils::count(sents.begin(), sents.end(), 1, 1, 3, nullptr, &bigramList);
langMdl = lm::KnLangModelBase::create(lm::KnLangModelBase::build(cntNodes, 3, 1, 2, 0, 1, 1e-5, 8, false, &bigramList));

ModelGenerator 폴더 내에 파이썬 스크립트로 중구난방으로 작성되어 있는 원본 말뭉치 -> 전처리된 사전 데이터 추출부를 다듬어 API 형태로 제공하고, 위의 기능들도 잘 다듬어 API로 노출한다면 말뭉치만 있으면 누구나 쉽게 형태소 분석 모델을 구축할 수 있는 시스템을 제공할 수 있을 것.

이렇게하여 다양한 형태소 분석 모델을 학습할 수 있게 한다면 이용자 각자가 자신의 목적에 맞는 모델을 선택하거나 직접 구축하여 사용할 수 있어서 매우 유용할 것으로 보인다.

사전 로딩 성능 개선

사전에 사용자 정의 단어 목록이 추가될 수록 로딩속도가 느려지는 문제가 있음.
또한 사전에 새로 단어를 추가할때마다 모델 전체를 다시 읽어와야하는 문제도 개선 필요

파이썬 버전에서 오류가 발생합니다.

환경

  • OS : Windows 10 1809 64bit
  • CPU : Intel i7 7700HQ
  • Python : Python 3.7

본문

예제와 같이 pip3 install kiwipiepy로 설치했고, 코드는 아래와 같습니다.

from kiwipiepy import Kiwi
kiwi = Kiwi()

image

위와같은 오류가 발생하고 있습니다. 해결 방법을 알 수 있을까요?

이용자 사전에 단어 추가시 최적의 스코어 자동 탐지

상황 설명

현재 이용자 사전에 신규 어휘를 추가할 경우 user_score를 직접 입력받도록 하고 있음. 이 값에 따라 동일한 입력에 대해서도 형태소 분석 결과가 달라질 수 있다.

add_word(골리, NNP, 0)
analyze(사람을 골리다)
: [사람/NNG, 을/JKO, 골리/NNP, 다/EC], -31.064453125

analyze(골리는 사람이다)
: [골리/NNP, 는/JX, 사람/NNG, 이/VCP, 다/EC], -25.12841796875
add_word(골리, NNP, -6)
analyze(사람을 골리다)
: [사람/NNG, 을/JKO, 골리/VV, 다/EC], -36.505615234375

analyze(골리는 사람이다)
: [골리/NNP, 는/JX, 사람/NNG, 이/VCP, 다/EC], -31.12841796875

골리라는 고유 명사를 추가할 때 score를 너무 높게 주면 골리다라는 동사를 잘못 분석할 수 있으며, 반대로 score를 너무 낮게 주면 골리라는 명사를 포함하는 분석 결과 자체가 누락될 가능성이 있다. 문제는 어휘에 따라 최적의 점수가 크게 바뀔 수 있기 때문에 이 값을 선택하는데에 어려움이 많다는 것. 이를 개선하기 위해 다음과 같이 자동화된 탐색 방법을 제안한다.

기능

추가하려는 신규 어휘의 품사에 맞춰 탐색 템플릿을 구축하여 둔다. 예를 들어 NNP의 경우 다음과 같다:

그 이름은 ___이다 : 그/MM 이름/NNG 은/JX ___/NNP 이/VCP 다/EF
___의 말을 따르면: ___/NNP 의/JKG 말/NNG 을/JKO 따르/VV 면/EC

위와 같은 템플릿은 학습 데이터에서 NNP가 등장하는 문맥을 모아서 NNP만 빈 칸으로 대체하면 확보가능하다. 마찬가지로 VV가 등장하는 문맥을 모아둔다. 해당 신규 어휘가 NNP로써 제대로 작동하려면 NNP 템플릿에 신규 어휘를 넣었을때 템플릿과 분석되는 사례가 많아야 하고, 반대로 VV 템플릿에 신규 어휘를 넣었을 때 NNP로 잘못 분석되는 사례가 적어야 한다. 따라서 이 둘을 기준 삼아 최적의 user score를 기계적으로 계산하는 것이 가능할 것으로 보인다.

문제는 품사별 양질의 템플릿을 구축하는 것인데 양이 너무 많으면 탐색에 걸리는 시간이 길어질 수 있으므로, 말뭉치 내에서 적당한 양의 데이터를 임의로 추출해보고 크기를 줄여가면서 성능이 나쁘지 않은 지점을 찾아야할 것으로 보인다.

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.