상세 컨텐츠

본문 제목

[Python] tomotopy로 쉽게 토픽 모델링 실시하기

프로그래밍/NLP

by 적분 ∫2tdt=t²+c 2019. 5. 22. 17:06

본문

저번 글에 소개했던 것처럼, 토픽 모델링 툴인 tomoto의 Python 패키지 버전을 며칠 전에 공개했었습니다. 이번 포스팅에서는 Python에서 이를 이용해서 쉽게 토픽 모델링을 하는 예제 코드를 공유하고자 합니다.

Step 1. tomotopy 패키지 설치하기

명령줄 혹은 Terminal 에서 다음과 같이 입력하여 tomotopy를 설치합니다. (만약 파이썬이 설치가 되지 않은 경우라면 먼저 파이썬을 설치해야겠죠. 3.5 버전 이상을 설치하는걸 추천드립니다)

$ pip install --upgrade tomotopy

Step 2. 토픽 모델링 코드를 작성하기

의외로 간단합니다. 바로 보도록 하시죠.


참 쉽죠? 단 입력 파일인 input_file.txt의 모양을 잘 생각해보셔야합니다. 이 파일은 한 줄에 문헌 하나를 담고 있다고 가정합니다. 또한 각 단어들은 공백 문자로 구분되어 있어야하구요. 그게 아니라면 제대로 처리가 되지 않겠죠?

자연언어처리에서 제일 중요한 건 전처리죠. 그런데 이 코드에는 전처리 부분이 없습니다. 입력 파일이 전처리되지 않았다면 결과가 이쁘게 나오지 않을테니 nltk를 이용해 전처리하는 코드를 추가해보도록 하겠습니다.

Step 3. (영어) 전처리 코드 추가하기


전처리 코드를 이용하면 토픽 모델에 좀더 깔끔한 데이터를 입력할 수 있겠죠?


실행하면 다음과 같은 결과를 얻을 수 있으실 겁니다. 제가 사용한 데이터는 호텔 리뷰 데이터였습니다.

Topic #0 great, hotel, view, stay, nice, beach, locat, street, room, plaza

Topic #1 locat, hotel, great, walk, good, room, staff, close, time, distanc

Topic #2 park, hotel, not, charg, free, internet, no, room, day, fee

Topic #3 room, nice, bed, small, clean, comfort, hotel, good, bathroom, littl

Topic #4 servic, hotel, stay, not, time, wait, minut, food, check, get

Topic #5 hotel, not, check, room, book, charg, told, stay, would, us

Topic #6 room, smell, smoke, not, dirti, like, clean, carpet, bed, stay

Topic #7 good, need, hotel, room, clean, locat, staff, price, updat, nice

Topic #8 hotel, good, close, airport, nice, shuttl, stay, clean, place, breakfast

Topic #9 breakfast, no, room, coffe, not, machin, clean, ice, good, fridg

Topic #10 stay, great, staff, hotel, nice, room, friendli, clean, good, again

Topic #11 room, not, air, hotel, no, condit, night, work, sleep, ac

Topic #12 room, night, door, nois, hotel, could, next, floor, peopl, hear

Topic #13 desk, staff, front, not, hotel, servic, help, friendli, no, check

Topic #14 stay, not, hotel, place, would, get, price, again, night, look

Topic #15 room, desk, front, call, get, us, not, check, back, day

Topic #16 bathroom, shower, room, not, door, toilet, no, need, water, wall

Topic #17 pool, water, not, hot, hotel, no, shower, nice, tub, kid

Topic #18 hotel, not, stay, would, renov, inn, star, disappoint, expect, year

Topic #19 room, bed, not, hotel, book, two, one, us, doubl, king

Step 3b. (한국어) 전처리 코드 추가하기

한국어 전처리는 영어에 비해 까다롭습니다. 명사나 형용사, 동사 등에 조사나 어미가 복잡하게 결합하고, 항상 단어 단위로 띄어쓰기를 하는것도 아니기 때문이죠. 이 때문에 한국어 분석을 위해서는 형태소 분석기가 필요합니다. 다행히도 여러 한국어 형태소 분석기가 이미 개발되어 있고, 또 파이썬에서도 쉽게 이들을 사용할 수 있어서, 한국어 분석도 편하게 진행할 수 있습니다. 여기에서는 마침 '과거의 제'가 개발한 kiwi의 파이썬 버전을 이용해보도록 하겠습니다. (kiwi 설치 역시 pip install --upgrade kiwipiepy 로 쉽게 하실 수 있습니다.)


마찬가지로 위에서처럼 add_doc에 tokenize(line)을 넣어주면 되겠죠.

(추가) 불용어를 지정하여 제거하고 싶은경우 아래와 같이 조건을 하나 더 추가할 수도 있겠습니다.


Step 4. 불용어 제거가 어려운 경우, 용어 가중치를 변경하자

이렇게 했는데도, 토픽별 상위 단어들이 너무 일반적이거나 자주 나오는 거라서 결과가 마음에 안 들수가 있습니다. 이 경우 용어 가중치 정책을 바꿔서 결과를 개선하는 방법을 사용할 수도 있습니다. 용어 가중치 정책은 모델 생성시에 설정해 줄 수 있습니다.


용어 가중치 정책에 대해서는 이전 포스팅에서 다룬 바 있으니 해당 글(https://bab2min.tistory.com/605)을 참조하시면 되겠습니다. Step 3에서 사용한 호텔 리뷰 데이터에 IDF 가중치 정책을 사용한 결과는 다음과 같습니다.

Topic #0 coffe, breakfast, no, cereal, tv, fridg, egg, juic, shower, cup

Topic #1 need, bathroom, carpet, dirti, shower, old, wall, not, stain, smell

Topic #2 plaza, street, fremont, great, vega, casino, downtown, locat, nice, la

Topic #3 air, water, hot, shower, work, ac, no, heat, condition, condit

Topic #4 beach, great, love, view, pool, nice, beauti, food, restaur, kid

Topic #5 dirti, bed, toilet, sheet, bathroom, bug, towel, stain, hair, carpet

Topic #6 bed, doubl, king, queen, size, room, two, book, us, park

Topic #7 locat, squar, walk, central, great, hotel, good, london, station, excel

Topic #8 peopl, not, get, back, never, go, look, like, around, say

Topic #9 breakfast, good, restaur, great, conveni, food, locat, nice, hotel, comfort

Topic #10 good, need, clean, staff, friendli, great, nice, price, stay, comfort

Topic #11 check, desk, told, call, ask, us, front, said, not, get

Topic #12 nois, hear, loud, thin, wall, door, noisi, sleep, could, night

Topic #13 smoke, smell, cigarett, non-smok, non, like, room, dog, stale, odor

Topic #14 desk, front, call, us, check, told, manag, phone, not, fix

Topic #15 star, price, not, hotel, rate, qualiti, expect, it, stay, better

Topic #16 charg, fee, park, internet, per, pay, extra, day, free, hilton

Topic #17 pool, ice, machin, floor, hot, elev, door, no, water, swim

Topic #18 ever, iron, worst, i, pillow, stay, servic, not, bed, time

Topic #19 shuttl, airport, park, close, flight, walk, driver, taxi, ride, bu

입력 데이터는 같은데 전혀 다른 결과가 나왔죠? 이는 자주 등장하는 단어 hotel, room 등의 가중치를 낮게 계산하고, 적게 등장한 단어들의 가중치를 높게 계산하는 데에서 기인한 차이입니다.

내친김에 가중치를 PMI로 계산한 결과도 보시죠.

Topic #0 view, beach, walk, locat, nice, great, close, restaur, hotel, disneyland

Topic #1 good, locat, breakfast, clean, staff, price, nice, great, hotel, valu

Topic #2 pool, hot, water, cold, no, heat, swim, tub, indoor, con

Topic #3 great, nice, staff, stay, friendli, hotel, famili, good, comfort, clean

Topic #4 plaza, great, casino, fremont, vega, downtown, nice, hotel, street, stay

Topic #5 shower, water, toilet, work, door, bathroom, no, broken, hot, not

Topic #6 food, restaur, order, bar, breakfast, buffet, dinner, servic, tabl, coffe

Topic #7 check, desk, front, rude, us, card, manag, servic, ask, arriv

Topic #8 check, desk, call, front, room, us, told, back, get, went

Topic #9 internet, wifi, breakfast, free, no, access, servic, connect, slow, not

Topic #10 dog, pet, outsid, sign, secur, keep, tabl, light, open, lot

Topic #11 nois, loud, sleep, noisi, night, hear, next, room, air, sound

Topic #12 smell, smoke, room, dirti, carpet, stain, sheet, like, bathroom, cigarett

Topic #13 stay, not, place, money, noth, i, hotel, would, pictur, do

Topic #14 need, old, room, bed, not, bathroom, dirti, updat, air, carpet

Topic #15 locat, airport, hotel, shuttl, walk, great, squar, good, central, conveni

Topic #16 bed, doubl, king, size, room, queen, two, book, small, suit

Topic #17 need, inn, hotel, motel, place, price, stay, ok, holiday, night

Topic #18 no, coffe, fridg, microwav, iron, towel, tv, refriger, maker, soap

Topic #19 park, charg, fee, resort, per, extra, pay, hotel, cost, car

용어 가중치 정책은 LDAModel 뿐만 아니라 tomotopy에서 제공하는 나머지 모든 토픽 모델(DMR, HDP, MGLDA, PA, HPA)에 대해서도 적용 가능합니다. 

이외에도 좀더 세세하게 토픽 모델링을 적용하고 싶으신 분들은 tomotopy 한국어 API문서를 살펴보시면 되겠습니다.

지금까지 tomotopy를 이용해 쉽게 토픽 모델링 하는 방법에 대해서 살펴보았습니다. 다음 번에는 tomotopy를 이용해 좀 더 다양한 데이터와 모델을 사용해보는 방법을 공유해보도록 하겠습니다~


관련글 더보기

댓글 영역

  • 이전 댓글 더보기
  • 프로필 사진
    2019.06.06 15:40
    비밀댓글입니다
    • 프로필 사진
      2019.06.06 23:49 신고
      stopwords set을 만들어서 여기에 불용어 리스트를 삽입하시고, 이에 포함된 단어들을 제거하도록 조건문을 고쳐주시면 됩니다.
      본문에 해당 코드도 추가하였으니 확인하시면 되겠습니다
  • 프로필 사진
    2019.06.09 13:05
    비밀댓글입니다
  • 프로필 사진
    2019.06.09 13:06
    안녕하세요. 우선 귀중한 자료 공유해주셔서 정말 감사합니다.
    다름이 아니라, kiwi 를 터미널에서 설치하는 데 있어 오류가 발생하는데 해결 방법이 있을까 하여 문의 드립니다.
    • 프로필 사진
      2019.06.09 13:07
      터미널에서 발생한 오류 코드는 다음과 같습니다.

      Collecting kiwipiepy
      Using cached https://files.pythonhosted.org/packages/d1/15/398522c1c9b8aca3d21140f09c4afd2617975493134785f97442825e2379/kiwipiepy-0.6.3.tar.gz
      Building wheels for collected packages: kiwipiepy
      Building wheel for kiwipiepy (setup.py) ... error
      ERROR: Complete output from command /usr/local/opt/python/bin/python3.7 -u -c 'import setuptools, tokenize;__file__='"'"'/private/var/folders/kr/rb29h92n73n7z8sydd2gjjth0000gn/T/pip-install-s3ih6w3t/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/kr/rb29h92n73n7z8sydd2gjjth0000gn/T/pip-wheel-fa_bvg97 --python-tag cp37:
      ERROR: running bdist_wheel
      running build
      running build_py
      creating build
      creating build/lib.macosx-10.14-x86_64-3.7
      creating build/lib.macosx-10.14-x86_64-3.7/kiwipiepy
      copying kiwipiepy/__init__.py -> build/lib.macosx-10.14-x86_64-3.7/kiwipiepy
      copying kiwipiepy/__main__.py -> build/lib.macosx-10.14-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.14-x86_64-3.7/kiwipiepy
      copying kiwipiepy/extract.mdl -> build/lib.macosx-10.14-x86_64-3.7/kiwipiepy
      copying kiwipiepy/sj.lang -> build/lib.macosx-10.14-x86_64-3.7/kiwipiepy
      copying kiwipiepy/sj.morph -> build/lib.macosx-10.14-x86_64-3.7/kiwipiepy
      running build_ext
      building 'kiwipiepycore' extension
      creating build/temp.macosx-10.14-x86_64-3.7
      creating build/temp.macosx-10.14-x86_64-3.7/KiwiLibrary
      clang -Wno-unused-result -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers -I/usr/local/include -I/usr/local/opt/openssl/include -I/usr/local/opt/sqlite/include -I/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/include/python3.7m -c KiwiLibrary/Utils.cpp -o build/temp.macosx-10.14-x86_64-3.7/KiwiLibrary/Utils.o -std=c++1y -O3 -fpermissive
      In file included from KiwiLibrary/Utils.cpp:2:
      In file included from KiwiLibrary/KTrie.h:4:
      KiwiLibrary/Trie.hpp:55:13: error: use of undeclared identifier 'end'
      if (it == end()) return {};
      ^
      KiwiLibrary/Trie.hpp:62:13: error: use of undeclared identifier 'end'
      if (it == end()) return this->emplace(key, typename _Map::mapped_type{}).first->second;
      ^
      KiwiLibrary/Utils.cpp:178:16: warning: comparison of integers of different signs: 'uint32_t' (aka 'unsigned int') and 'int32_t' (aka 'int') [-Wsign-compare]
      return v - (v >= vSize[i] ? (1 << ((i + 1) * 7)) : 0);
      ~ ^ ~~~~~~~~
      1 warning and 2 errors generated.
      error: command 'clang' 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 ... error
      ERROR: Complete output from command /usr/local/opt/python/bin/python3.7 -u -c 'import setuptools, tokenize;__file__='"'"'/private/var/folders/kr/rb29h92n73n7z8sydd2gjjth0000gn/T/pip-install-s3ih6w3t/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/kr/rb29h92n73n7z8sydd2gjjth0000gn/T/pip-record-uuz4l1ml/install-record.txt --single-version-externally-managed --compile:
      ERROR: running install
      running build
      running build_py
      creating build
      creating build/lib.macosx-10.14-x86_64-3.7
      creating build/lib.macosx-10.14-x86_64-3.7/kiwipiepy
      copying kiwipiepy/__init__.py -> build/lib.macosx-10.14-x86_64-3.7/kiwipiepy
      copying kiwipiepy/__main__.py -> build/lib.macosx-10.14-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.14-x86_64-3.7/kiwipiepy
      copying kiwipiepy/extract.mdl -> build/lib.macosx-10.14-x86_64-3.7/kiwipiepy
      copying kiwipiepy/sj.lang -> build/lib.macosx-10.14-x86_64-3.7/kiwipiepy
      copying kiwipiepy/sj.morph -> build/lib.macosx-10.14-x86_64-3.7/kiwipiepy
      running build_ext
      building 'kiwipiepycore' extension
      creating build/temp.macosx-10.14-x86_64-3.7
      creating build/temp.macosx-10.14-x86_64-3.7/KiwiLibrary
      clang -Wno-unused-result -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers -I/usr/local/include -I/usr/local/opt/openssl/include -I/usr/local/opt/sqlite/include -I/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/include/python3.7m -c KiwiLibrary/Utils.cpp -o build/temp.macosx-10.14-x86_64-3.7/KiwiLibrary/Utils.o -std=c++1y -O3 -fpermissive
      In file included from KiwiLibrary/Utils.cpp:2:
      In file included from KiwiLibrary/KTrie.h:4:
      KiwiLibrary/Trie.hpp:55:13: error: use of undeclared identifier 'end'
      if (it == end()) return {};
      ^
      KiwiLibrary/Trie.hpp:62:13: error: use of undeclared identifier 'end'
      if (it == end()) return this->emplace(key, typename _Map::mapped_type{}).first->second;
      ^
      KiwiLibrary/Utils.cpp:178:16: warning: comparison of integers of different signs: 'uint32_t' (aka 'unsigned int') and 'int32_t' (aka 'int') [-Wsign-compare]
      return v - (v >= vSize[i] ? (1 << ((i + 1) * 7)) : 0);
      ~ ^ ~~~~~~~~
      1 warning and 2 errors generated.
      error: command 'clang' failed with exit status 1
      ----------------------------------------
      ERROR: Command "/usr/local/opt/python/bin/python3.7 -u -c 'import setuptools, tokenize;__file__='"'"'/private/var/folders/kr/rb29h92n73n7z8sydd2gjjth0000gn/T/pip-install-s3ih6w3t/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/kr/rb29h92n73n7z8sydd2gjjth0000gn/T/pip-record-uuz4l1ml/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /private/var/folders/kr/rb29h92n73n7z8sydd2gjjth0000gn/T/pip-install-s3ih6w3t/kiwipiepy/


      입니다.
    • 프로필 사진
      2019.06.09 15:02 신고
      친절한 오류 제보에 감사합니다.
      해당 문제는 일부 코드가 clang과 호환되지 않게 작성되어서 발생한 것으로 확인되었습니다. 해당 문제를 해결한 0.6.5 버전을 새로 업로드하였으니

      pip install -U kiwipiepy>=0.6.5

      를 통하여 다시 설치해주시면 감사하겠습니다!
  • 프로필 사진
    2019.07.15 03:21
    역사학과라고 글을 읽은거 같은데 대단하시네요. 각종 정보는 어떻게 얻는지도 궁금합니다.
    • 프로필 사진
      2019.07.22 14:45 신고
      과찬이십니다. 복수전공으로 정보학을 공부했구요, 학부/대학원 전공에서 공부한것 중심으로 키워드를 잡고 블로그 및 논문 등을 찾아서 배움을 넓히려고 하고 있습니다.
  • 프로필 사진
    2019.08.08 11:09
    tomotopy를 설치하니 이런 에러가 뜨는데 어찌할까요?
    Command "/anaconda3/bin/python -u -c "import setuptools, tokenize;__file__='/private/var/folders/lk/fzv4sw4s3lsdftpmlsfv1l_40000gn/T/pip-install-xtk61581/tomotopy/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/lk/fzv4sw4s3lsdftpmlsfv1l_40000gn/T/pip-record-_2ggos0e/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /private/var/folders/lk/fzv4sw4s3lsdftpmlsfv1l_40000gn/T/pip-install-xtk61581/tomotopy/
    Note: you may need to restart the kernel to use updated packages.
    • 프로필 사진
      2019.08.08 17:52 신고
      혹시 사용중인 OS와 Python(anaconda) 버전을 알려주시겠어요?
    • 프로필 사진
      2019.08.08 18:05
      macOS Mojave 버전 10.14.5
      Python 3.7.3
      conda 4.7.5
      입니다
    • 프로필 사진
      2019.08.09 02:12 신고
      예, 테스트해본 결과 해당 환경에서 발생하는 컴파일 오류가 있어서 이를 해결한 tomotopy 0.1.6 버전을 올렸습니다. 소중한 제보 감사합니다. 최신 버전으로 다시 설치해보시길 부탁드립니다!
    • 프로필 사진
      2019.08.09 12:54
      다운 잘 받았습니다. 답변 감사합니다^^
  • 프로필 사진
    2019.08.10 16:13
    안녕하세요. 블로그를 통해 많은 도움을 얻고 있습니다.
    다름이 아니라 Tomoto Gui와 파이썬의 Tomoto 패키지를 이용한 결과가 사뭇 다릅니다.
    LDA의 초기 arbitrary 토픽 할당 때문으로 생각했으나, 같은 하이퍼 파라미터(k=2, alpha=0.1, eta=0.01)를 두고
    여러번 돌려본 결과 텍스트 전처리 부분에서 차이가 있는 것 같습니다.
    예를들면, Tomoto Gui와는 달리 파이썬에서는 -하는, -하고에서 '하'가 독립적으로 떨어지는 느낌이 듭니다.
    올려주신 한국어 전처리 이외에 작업이 Tomoto Gui에서 이루어지나요?
    제가 아직 미숙해서 텍스트 전처리를 제대로 못한걸수도 있습니다 .^^;;
    저는 Gui의 결과가 맘에 드는데 어떻게 하면 Gui의 출력처럼 나오게 할 수 있을까요? 감사합니다.
    • 프로필 사진
      2019.08.11 00:15 신고
      tomoto gui에서 사용하는 라이브러리 버전이 조금더 옛날것이라 발생하는 차이로 보입니다.
      -하는, -하고 와 같은 표현의 경우 형태소 분석기를 거치면 하/XSV, 는/ETM, 혹은 하/XSV, 고/EC 와 같이 분리가 되는게 맞습니다. 아마 예전 버전의 결과에서는 이것이 제대로 분리되지 않은 것으로 보입니다.

      즉, '분석하다'라는 문장이 입력되면 최신 버전의 kiwi에서는
      분석/NNG + 하/XSV + 다/EF
      로 분해가 됩니다.

      이를 붙여주시기 위해서는 kiwi로 분석한 결과 중 품사 태그가 XSV나 XSA인 경우 앞의 단어와 합치는 작업을 수행하셔야 합니다.
    • 프로필 사진
      2019.08.22 00:56
      품사 태그는 세종품사태그를 사용하셨군요. 감사합니다.
    • 프로필 사진
      2019.08.23 00:15 신고
      네 맞습니다. 미약하나마 도움이 되셨길 바랍니다!
  • 프로필 사진
    2019.10.19 07:20
    비밀댓글입니다
    • 프로필 사진
      2019.10.19 10:20 신고
      토픽모델링은 확률적인 샘플링 과정을 거치기 때문에 실행시마다 결과가 달라질 수 밖에 없습니다. 좋은 방법은 iteration 횟수를 크게 높여 모델이 안정적인 상태로 수렴하게 하는 것이지만, 이 역시도 실행시마다 결과가 바뀝니다.

      결과를 고정시키는 확실한 방법은 난수의 시드값을 고정시키는 수밖에 없는데, 처음에 LDAModel을 만들때 tp.LDAModel(~~~~, seed=원하는값) 으로 설정하여 seed값을 고정시키시고
      train할때 train(workers=1)로 하여 멀티쓰레딩을 끄시면 됩니다.
    • 프로필 사진
      2019.10.21 14:53
      비밀댓글입니다
  • 프로필 사진
    2019.11.30 20:14
    안녕하세요, 정말 좋은 자료 감사드립니다! 지금 tomotopy를 이용해서 토픽모델링을 진행하고 있는데요, 각 문헌별 각 토픽에 속할 확률을 어떻게 보는지 API를 계속 들여다봐도 잘 작동이 되지 않습니다ㅠㅠ 아마 get_topics 메서드를 써야하는 것 같은데.. 혹시 어떻게 코드를 실행해야 하는지 알 수 있을까요?
    • 프로필 사진
      2019.12.01 00:18 신고
      토픽 모델 변수가 mdl이라고 했을때
      mdl.docs[i].get_topics(top_n=10)을 수행하시면 i번째 문헌의 토픽 비중 상위 10개가 반환됩니다.
      문헌 번호는 add_doc을 실행한 순서대로 0번부터 차례로 주어집니다.
    • 프로필 사진
      2019.12.02 01:15 신고
      https://bab2min.tistory.com/641 에 관련 글을 올렸습니다. 도움이 되시기를 바랍니다!
    • 프로필 사진
      2019.12.02 17:00
      헉 빠른 답변 완전 감사드립니다ㅠㅠㅠ 정말 많은 도움이 되었습니다!! 복 많이 받으세요!!
  • 프로필 사진
    2020.03.19 11:28
    안녕하세요,
    프로젝트 진행하면서 토픽모델링까지 오게 되었습니다. tomotopy에서 dmr모델을 사용하면서 궁금한 점이 생겨서 질문드립니다! 학습데이터 넣을때 구문만 넣는다면 그냥 예시 따라한대로 add_doc를 통해서 쉽게 넣을 수 있었는데요, 날짜나 평점 같은 메타데이터까지 같이 넣을때는 add_doc의 파라미터를 어떤식으로 해야하는지 궁금합니다 :)
    감사합니다!
    • 프로필 사진
      2020.03.19 13:18
      안녕하세요 ㅎㅎ metadata에는 라벨을 넣고 words파라미터에 메타데이터 정보를 포함해야하는 건줄 알았는데, 아예 그냥 메타데이터자체를 넣는거였군요! 보통 2개 이상의 메타데이터에 대해서는 어떤식으로 처리하나요? 그냥 하나의 스트링으로 합쳐서 넣으면 되는걸까요?
      감사합니다
    • 프로필 사진
      2020.03.19 21:47 신고
      네, metadata로 메타데이터 자체를 넣어주시면 됩니다. 메타 데이터가 2개 이상인 경우는 실험 목적에 따라 하나만 골라서 넣으시거나 둘을 합쳐서 넣으시면 되겠습니다.
    • 프로필 사진
      2020.03.20 09:54
      넵 친절한 답변 감사드립니다 :)
  • 프로필 사진
    2020.05.03 14:17
    저한테만 생기는 문제인지는 모르겠지만
    tomotopy를 import하고 pyinstaller 로 컴파일을 하면 CPU가 100%가 되면서
    재귀적으로 자신을 계속 실행하는 현상이 있던데요...

    import tomotopy as tp
    from kiwipiepy import Kiwi

    model = tp.LDAModel(k=10, alpha=0.1, eta=0.01, min_cf=2)

    요렇게만 넣어도 같은 현상이 있네요 ^^;;
    (python 3.7 / WIN10 64bit)
    • 프로필 사진
      2020.05.03 21:32 신고
      아마 pyinstaller와 호환이 잘 안되는 부분이 있는거 같습니다. 원인에 대해 자세히 확인해보고 알려드리도록 하겠습니다~
  • 프로필 사진
    2020.05.16 06:34
    안녕하세요. 현재 Tomoto에서는 topic_word_dist이 확률값으로 주어지는데,
    혹시 확률값을 계산하기 전에 topic별 word count를 뽑아볼수없나요?

    비율이 아닌 count를 써야할 일이있는데 tomoto에 정의된 함수에서는,
    비율만 제공을 하는 것같아서요.
    • 프로필 사진
      2020.05.21 12:47 신고
      현재는 확률만 제공되고 있구요 카운트를 제공하는 별도의 함수는 없습니다. 다만 다음과 같은 방법으로 직접 카운팅을 할수는 있습니다.

      from collections import Counter
      count = Counter()
      for doc in models.docs:
      count.update(doc.topics)

      for k, n in count.most_common():
      print(k, n)

      다음버전에서는 카운트를 바로 제공하는 함수도 추가해보도록 하겠습니다~!
  • 프로필 사진
    2020.08.06 00:52
    혹시 토픽별 수치나 단어별 수치 값은 안나올까요?
    • 프로필 사진
      2020.08.06 01:00 신고
      나옵니다. model.get_topic_words()가 리턴하는 값이 (단어, 단어의 확률값)입니다. 위의 예시는 단어만 출력한거구요. 원하신다면 둘 다 출력하실 수 있습니다.

      마찬가지로 문헌별 토픽 비율도 model.docs[0].get_topics()로 얻을 수 있습니다.
  • 프로필 사진
    2020.08.06 15:57
    비밀댓글입니다
    • 프로필 사진
      2020.08.07 13:47 신고
      음 코드 전체를 보여주셔아 어디가 문제인지 알 수 있을거 같습니다. 혹시 전체 코드와 데이터 샘플을 공유해주실수 있나요?
  • 프로필 사진
    2020.08.07 17:44
    비밀댓글입니다
  • 프로필 사진
    2020.11.05 16:35
    한국어 코드가 큰 도움이 됩니다. 감사드립니다. 아래의 코드까지 사용하여 토픽별로 군집화를 해 보았습니다. 학습된 토픽들을 출력하는 코드에서 질문 드립니다.

    for i in range(model.k):
    # 토픽 개수가 총 XX개이니, 0~19번까지의 토픽별 상위 단어 20개를 뽑아봅시다.
    res = model.get_topic_words(i, top_n=20)
    print('Topic #{}'.format(i), end='\t')
    print(', '.join(w for w, p in res))

    (1) 각 토픽을 가장 많이 반영하는 문서들을 어떻게 하면 찾을 수 있나요?
    (2) pyLDAvis를 써서 시각화를 하고 싶은데 코드를 어떻게 진행하는지 모르겠습니다. 그리고 pyLDAvis의 원리는 원이 서로 독립적으로 분포하면 토픽 분류가 잘된 것이라고 하는데 tomotopy도 적용이 되나요?
    • 프로필 사진
      2020.11.08 19:47 신고
      1번은 https://bab2min.tistory.com/641 여기에 있는 코드를 참고하시면 될거 같습니다.
      2번은 https://github.com/bab2min/tomotopy/blob/main/examples/lda_visualization.py 에 예시코드가 있으니 그대로 따라하시면 됩니다.
      tomotopy의 LDAModel 역시 동일하게 LDA 토픽 모델링을 실시한 것이라서 같은 법칙이 통용된다고 보시면 됩니다.
  • 프로필 사진
    2020.11.11 02:03
    안녕하세요. 예전부터 토픽모델링 관련 여러 방법론들 잘 읽고 있던 사람입니다 오랜만에 들어오니 대단한 일을 하고 계시네요 ㅎㅎ 한 가지 궁금한 게 있어 질문드려요.

    이전에 토픽모델링 위해 자주 쓰이던 gensim이나 R의 토픽모델링 활용에는 topic coherence 같이 적절해보이는 토픽 개수를 유추할 수 있는 코드들이 있어서 참고하곤 했었는데요 이 토모토피는 아직 gensim 만큼 널리 퍼지진 않았는지 토모토피의 lda에서 토픽개수를 유추할 만한 코드가 안 보이더라고요. 혹시 작성하신 기능 내에서 비슷한 과정을 거칠 수 있는 방법이 있을런지요?
    • 프로필 사진
      2020.11.12 14:20 신고
      안타깝게도 현재 topic coherence를 계산하는 코드 자체는 tomotopy에서 지원하지 않고 있습니다.
      https://github.com/bab2min/tomotopy/issues/73#issuecomment-721546760 에 gensim의 CoherenceModel을 tomotopy에 적용하는 코드가 있으니 일단 이를 참고하시길 바랍니다.
      또한 추후 coherence를 계산하는 모듈을 tomotopy에 추가할 계획을 가지고 있으니 조금만 기다려주시면 좀 더 편하게 coherence를 계산할 수도 있을 걸로 기대됩니다.
  • 프로필 사진
    2020.11.30 20:21
    https://github.com/bab2min/tomotopy/blob/main/examples/lda_visualization.py 이곳 들어가서 pyldavis를 활용하고싶은데 님꼐서 적어주신 ldamodel를 어디다 넣어야하는지 잘모르겠고
    님의 요 페이지에있는 한글토픽모델링은 다 했는데 pyldavis 예시코드를 어떻게 활용해야되는지 모르겠어서 문의드려요 ㅠㅠ
    • 프로필 사진
      2020.12.01 00:12 신고
      https://github.com/bab2min/tomotopy/blob/main/examples/lda_visualization.py#L50
      해당 코드 50번째 이하 줄들을 그대로 가져다가 쓰시면 됩니다.
      예를 들 준형님께서 만드신 LDAModel을 mdl 변수에 저장했다고 가정할때 다음과 같이 사용하시면 되겠네요.

      # mdl = tp.LDAModel(...)

      import numpy as np
      import pyLDAvis

      topic_term_dists = np.stack([mdl.get_topic_word_dist(k) for k in range(mdl.k)])
      doc_topic_dists = np.stack([doc.get_topic_dist() for doc in mdl.docs])
      doc_lengths = np.array([len(doc.words) for doc in mdl.docs])
      vocab = list(mdl.used_vocabs)
      term_frequency = mdl.used_vocab_freq

      prepared_data = pyLDAvis.prepare(
      topic_term_dists,
      doc_topic_dists,
      doc_lengths,
      vocab,
      term_frequency
      )
      pyLDAvis.save_html(prepared_data, 'ldavis.html')
    • 프로필 사진
      2020.12.01 22:36
      50번쨰 이하 줄을 사용해보았는데 need at least one array to stack 라는 오류가나와요
    • 프로필 사진
      2020.12.01 22:39
      mdl = tp.LDAModel(k=20, alpha=0.1, eta=0.01, min_cf=5, tw=tp.TermWeight.IDF)

      import numpy as np
      import pyLDAvis

      topic_term_dists = np.stack([mdl.get_topic_word_dist(k) for k in range(mdl.k)])
      doc_topic_dists = np.stack([doc.get_topic_dist() for doc in mdl.docs])
      doc_lengths = np.array([len(doc.words) for doc in mdl.docs])
      vocab = list(mdl.used_vocabs)
      term_frequency = mdl.used_vocab_freq

      prepared_data = pyLDAvis.prepare(
      topic_term_dists,
      doc_topic_dists,
      doc_lengths,
      vocab,
      term_frequency
      )
      pyLDAvis.save_html(prepared_data, 'ldavis.html')


      이렇게 사용했는데
      doc_topic_dists = np.stack([doc.get_topic_dist() for doc in mdl.docs])

      요부분에서 오류가 난다고 나오네요
    • 프로필 사진
      2020.12.01 22:53 신고
      시각화에 앞서 mdl에 add_doc()으로 문헌들을 추가하시고, train()을 하셔야 합니다. 그냥 LDAModel만 만들어두면 해당 모델에 아무 문헌도 추가되어 있지 않은 빈 깡통인셈이라 작동하지 않습니다.

      본 포스팅 step2에 있는 add_doc 및 train을 하는 코드를 사용하시고 그 뒤에 pyLDAVis를 쓰셔야지요.
  • 프로필 사진
    2021.01.23 17:09
    안녕하세요. 좋은 패키지 정말 감사합니다. 저는 hdp모델을 사용해서 해봤는데요, random seed를 고정해도 결과가 다르게 나오고, 뽑힌 마지막 토픽 몇 개가 아예 똑같이 나오는 경우(coherence score까지 똑같더군요 ㅠㅠ)는 왜 그런 건지 혹시 알려주실 수 있을까요?
    • 프로필 사진
      2021.01.23 22:38 신고
      random seed를 고정해도 multi threading인 경우에는 결과가 다르게 나옵니다. seed를 고정하고 workers=1로 설정한 경우에만 결과가 동일하게 나올거에요.

      그리고 아마 HDP에서 동일한 토픽이 나오는 경우는 해당 토픽이 비중이 적어서 delete된 경우일겁니다. is_live_topic으로 토픽이 살아있는지 확인한 뒤에 살아있는것만 출력해주시면 될거 같습니다.
  • 프로필 사진
    2021.08.01 19:02
    안녕하세요 저는 데이터분석을 공부하는 학생입니다! 좋은 패키지를 만들어 주시고 배포해주셔서 감사합니다! 다름이 아니라 본문에 train(200)으로 설정하셨는데 혹시 이유가 있을까요? API문서에서는 train 값을 설정하는 것에 따라 add_doc 그리고 설정 이후에는 make_doc 을 사용하는 등 사용법(?)에 따라 함수를 설정할 수 있는 것 같은데 따로 그 이유에 대한 설명을 찾기가 힘드네요 (train을 수정해서 다시 모델을 실행시켰을때 토픽이 달라집니다ㅠ )
    제가 아직 배우는 학생이다보니 코드레벨이 많이 낮아서 이래저래 두서없이 작성하였는데 혹시 답변을 주신다면..정말 감사하겠습니다 ㅠㅠ!
    • 프로필 사진
      2021.08.02 00:26 신고
      확률적 과정에 따라 모델을 학습시키는거라 매 시행마다 결과가 달라질 수 있구요, train의 iteration을 200으로 잡은거는 그냥 예시일뿐입니다. 데이터셋에 따라 수렴에 이르는데 필요한 iteration 횟수는 다 달라요. 잘 모르시겠다면 최대한 횟수를 크게 잡고 오래 돌리시면 됩니다.
  • 프로필 사진
    2021.09.03 11:42
    비밀댓글입니다