Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/bab2min/tomotopy

Python package of Tomoto, the Topic Modeling Tool
https://github.com/bab2min/tomotopy

correlated-topic-model dirichlet-multinomial-regression hierarchical-dirichlet-processes latent-dirichlet-allocation nlp pachinko-allocation python-library supervised-lda topic-modeling topic-models

Last synced: about 1 month ago
JSON representation

Python package of Tomoto, the Topic Modeling Tool

Awesome Lists containing this project

README

        

tomotopy
========

.. image:: https://badge.fury.io/py/tomotopy.svg
:target: https://pypi.python.org/pypi/tomotopy

.. image:: https://zenodo.org/badge/186155463.svg
:target: https://zenodo.org/badge/latestdoi/186155463

🌐
`English`_,
**ν•œκ΅­μ–΄**.

.. _English: README.rst

tomotopy λž€?
------------------
`tomotopy`λŠ” ν† ν”½ λͺ¨λΈλ§ 툴인 `tomoto`의 Python ν™•μž₯ λ²„μ „μž…λ‹ˆλ‹€. `tomoto`λŠ” c++둜 μž‘μ„±λœ 깁슀 μƒ˜ν”Œλ§ 기반의 ν† ν”½ λͺ¨λΈλ§ 라이브러리둜,
μ΅œμ‹  CPU의 벑터화 κΈ°μˆ μ„ ν™œμš©ν•˜μ—¬ 처리 속도λ₯Ό μ΅œλŒ€λ‘œ λŒμ–΄μ˜¬λ ΈμŠ΅λ‹ˆλ‹€.
ν˜„μž¬ λ²„μ „μ˜ `tomoto`μ—μ„œλŠ” λ‹€μŒκ³Ό 같은 μ£Όμš” ν† ν”½ λͺ¨λΈλ“€μ„ μ§€μ›ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

* Latent Dirichlet Allocation (`tomotopy.LDAModel`)
* Labeled LDA (`tomotopy.LLDAModel`)
* Partially Labeled LDA (`tomotopy.PLDAModel`)
* Supervised LDA (`tomotopy.SLDAModel`)
* Dirichlet Multinomial Regression (`tomotopy.DMRModel`)
* Generalized Dirichlet Multinomial Regression (`tomotopy.GDMRModel`)
* Hierarchical Dirichlet Process (`tomotopy.HDPModel`)
* Hierarchical LDA (`tomotopy.HLDAModel`)
* Multi Grain LDA (`tomotopy.MGLDAModel`)
* Pachinko Allocation (`tomotopy.PAModel`)
* Hierarchical PA (`tomotopy.HPAModel`)
* Correlated Topic Model (`tomotopy.CTModel`)
* Dynamic Topic Model (`tomotopy.DTModel`)
* Pseudo-document based Topic Model (`tomotopy.PTModel`)

더 μžμ„Έν•œ μ •λ³΄λŠ” https://bab2min.github.io/tomotopy/index.kr.html μ—μ„œ ν™•μΈν•˜μ‹œκΈΈ λ°”λžλ‹ˆλ‹€.

μ‹œμž‘ν•˜κΈ°
---------------
λ‹€μŒκ³Ό 같이 pipλ₯Ό μ΄μš©ν•˜λ©΄ tomotopyλ₯Ό μ‰½κ²Œ μ„€μΉ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
::

$ pip install --upgrade pip
$ pip install tomotopy

μ§€μ›ν•˜λŠ” 운영체제 및 Python 버전은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

* Python 3.6 이상이 μ„€μΉ˜λœ Linux (x86-64)
* Python 3.6 이상이 μ„€μΉ˜λœ macOS 10.13λ‚˜ κ·Έ 이후 버전
* Python 3.6 이상이 μ„€μΉ˜λœ Windows 7μ΄λ‚˜ κ·Έ 이후 버전 (x86, x86-64)
* Python 3.6 이상이 μ„€μΉ˜λœ λ‹€λ₯Έ 운영체제: 이 κ²½μš°λŠ” c++14 ν˜Έν™˜ 컴파일러λ₯Ό ν†΅ν•œ μ†ŒμŠ€μ½”λ“œ 컴파일이 ν•„μš”ν•©λ‹ˆλ‹€.

μ„€μΉ˜κ°€ λλ‚œ λ’€μ—λŠ” λ‹€μŒκ³Ό 같이 Python3μ—μ„œ λ°”λ‘œ importν•˜μ—¬ tomotopyλ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
::

import tomotopy as tp
print(tp.isa) # 'avx2'λ‚˜ 'avx', 'sse2', 'none'λ₯Ό 좜λ ₯ν•©λ‹ˆλ‹€.

ν˜„μž¬ tomotopyλŠ” 가속을 μœ„ν•΄ AVX2, AVX or SSE2 SIMD λͺ…λ Ήμ–΄ μ„ΈνŠΈλ₯Ό ν™œμš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
νŒ¨ν‚€μ§€κ°€ import될 λ•Œ ν˜„μž¬ ν™˜κ²½μ—μ„œ ν™œμš©ν•  수 μžˆλŠ” μ΅œμ„ μ˜ λͺ…λ Ήμ–΄ μ„ΈνŠΈλ₯Ό ν™•μΈν•˜μ—¬ μ΅œμƒμ˜ λͺ¨λ“ˆμ„ μžλ™μœΌλ‘œ κ°€μ Έμ˜΅λ‹ˆλ‹€.
λ§Œμ•½ `tp.isa`κ°€ `none`이라면 ν˜„μž¬ ν™˜κ²½μ—μ„œ ν™œμš© κ°€λŠ₯ν•œ SIMD λͺ…λ Ήμ–΄ μ„ΈνŠΈκ°€ μ—†λŠ” κ²ƒμ΄λ―€λ‘œ ν›ˆλ ¨μ— 였랜 μ‹œκ°„μ΄ 걸릴 수 μžˆμŠ΅λ‹ˆλ‹€.
κ·ΈλŸ¬λ‚˜ 졜근 λŒ€λΆ€λΆ„μ˜ Intel 및 AMD CPUμ—μ„œλŠ” SIMD λͺ…λ Ήμ–΄ μ„ΈνŠΈλ₯Ό μ§€μ›ν•˜λ―€λ‘œ SIMD 가속이 μ„±λŠ₯을 크게 ν–₯μƒμ‹œν‚¬ 수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€.

κ°„λ‹¨ν•œ 예제둜 'sample.txt' 파일둜 LDA λͺ¨λΈμ„ ν•™μŠ΅ν•˜λŠ” μ½”λ“œλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.
::

import tomotopy as tp
mdl = tp.LDAModel(k=20)
for line in open('sample.txt'):
mdl.add_doc(line.strip().split())

for i in range(0, 100, 10):
mdl.train(10)
print('Iteration: {}\tLog-likelihood: {}'.format(i, mdl.ll_per_word))

for k in range(mdl.k):
print('Top 10 words of topic #{}'.format(k))
print(mdl.get_topic_words(k, top_n=10))

mdl.summary()

tomotopy의 μ„±λŠ₯
-----------------------
`tomotopy`λŠ” 주제 뢄포와 단어 뢄포λ₯Ό μΆ”λ‘ ν•˜κΈ° μœ„ν•΄ Collapsed Gibbs-Sampling(CGS) 기법을 μ‚¬μš©ν•©λ‹ˆλ‹€.
일반적으둜 CGSλŠ” `gensim의 LdaModel`_κ°€ μ΄μš©ν•˜λŠ” Variational Bayes(VB) 보닀 느리게 μˆ˜λ ΄ν•˜μ§€λ§Œ 각각의 λ°˜λ³΅μ€ λΉ λ₯΄κ²Œ 계산 κ°€λŠ₯ν•©λ‹ˆλ‹€.
κ²Œλ‹€κ°€ `tomotopy`λŠ” λ©€ν‹°μŠ€λ ˆλ“œλ₯Ό μ§€μ›ν•˜λ―€λ‘œ SIMD λͺ…λ Ήμ–΄ μ„ΈνŠΈλΏλ§Œ μ•„λ‹ˆλΌ 닀쀑 μ½”μ–΄ CPU의 μž₯μ κΉŒμ§€ ν™œμš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이 덕뢄에 각각의 반볡이 훨씬 λΉ λ₯΄κ²Œ 계산 κ°€λŠ₯ν•©λ‹ˆλ‹€.

.. _gensim의 LdaModel: https://radimrehurek.com/gensim/models/ldamodel.html

λ‹€μŒμ˜ μ°¨νŠΈλŠ” `tomotopy`와 `gensim`의 LDA λͺ¨ν˜• μ‹€ν–‰ μ‹œκ°„μ„ λΉ„κ΅ν•˜μ—¬ λ³΄μ—¬μ€λ‹ˆλ‹€.
μž…λ ₯ λ¬Έν—Œμ€ μ˜μ–΄ μœ„ν‚€λ°±κ³Όμ—μ„œ κ°€μ Έμ˜¨ 1000개의 μž„μ˜ λ¬Έμ„œμ΄λ©° 전체 λ¬Έν—Œ 집합은 총 1,506,966개의 λ‹¨μ–΄λ‘œ κ΅¬μ„±λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. (μ•½ 10.1 MB).
`tomotopy`λŠ” 200회λ₯Ό, `gensim` 10회λ₯Ό 반볡 ν•™μŠ΅ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

.. image:: https://bab2min.github.io/tomotopy/images/tmt_i5.png

Intel i5-6600, x86-64 (4 cores)μ—μ„œμ˜ μ„±λŠ₯

.. image:: https://bab2min.github.io/tomotopy/images/tmt_xeon.png

Intel Xeon E5-2620 v4, x86-64 (8 cores, 16 threads)μ—μ„œμ˜ μ„±λŠ₯

`tomotopy`κ°€ 20λ°° 더 많이 λ°˜λ³΅ν•˜μ˜€μ§€λ§Œ 전체 μ‹€ν–‰μ‹œκ°„μ€ `gensim`보닀 5~10λ°° 더 λΉ¨λžμŠ΅λ‹ˆλ‹€. λ˜ν•œ `tomotopy`λŠ” μ „λ°˜μ μœΌλ‘œ μ•ˆμ •μ μΈ κ²°κ³Όλ₯Ό 보여주고 μžˆμŠ΅λ‹ˆλ‹€.

CGS와 VBλŠ” μ„œλ‘œ 접근방법이 μ•„μ˜ˆ λ‹€λ₯Έ 기법이기 λ•Œλ¬Έμ— λ‘˜μ„ μ§μ ‘μ μœΌλ‘œ λΉ„κ΅ν•˜κΈ°λŠ” μ–΄λ ΅μŠ΅λ‹ˆλ‹€λ§Œ, μ‹€μš©μ μΈ κ΄€μ μ—μ„œ 두 κΈ°λ²•μ˜ 속도와 결과물을 비ꡐ해볼 수 μžˆμŠ΅λ‹ˆλ‹€.
λ‹€μŒμ˜ μ°¨νŠΈμ—λŠ” 두 기법이 ν•™μŠ΅ ν›„ 보여쀀 단어당 둜그 κ°€λŠ₯도 값이 ν‘œν˜„λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

.. image:: https://bab2min.github.io/tomotopy/images/LLComp.png

μ–΄λ–€ SIMD λͺ…λ Ήμ–΄ μ„ΈνŠΈλ₯Ό μ‚¬μš©ν•˜λŠ”μ§€λŠ” μ„±λŠ₯에 큰 영ν–₯을 λ―ΈμΉ©λ‹ˆλ‹€.
λ‹€μŒ μ°¨νŠΈλŠ” SIMD λͺ…λ Ήμ–΄ μ„ΈνŠΈμ— λ”°λ₯Έ μ„±λŠ₯ 차이λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.

.. image:: https://bab2min.github.io/tomotopy/images/SIMDComp.png

λ‹€ν–‰νžˆλ„ μ΅œμ‹  x86-64 CPU듀은 λŒ€λΆ€λΆ„ AVX2 λͺ…λ Ήμ–΄ μ„ΈνŠΈλ₯Ό μ§€μ›ν•˜κΈ° λ•Œλ¬Έμ— λŒ€λΆ€λΆ„μ˜ 경우 AVX2의 높은 μ„±λŠ₯을 ν™œμš©ν•  수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€.

λͺ¨λΈμ˜ μ €μž₯κ³Ό 뢈러였기
-------------------
`tomotopy`λŠ” 각각의 ν† ν”½ λͺ¨λΈ ν΄λž˜μŠ€μ— λŒ€ν•΄ `save`와 `load` λ©”μ†Œλ“œλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.
λ”°λΌμ„œ ν•™μŠ΅μ΄ λλ‚œ λͺ¨λΈμ„ μ–Έμ œλ“ μ§€ νŒŒμΌμ— μ €μž₯ν•˜κ±°λ‚˜, νŒŒμΌλ‘œλΆ€ν„° λ‹€μ‹œ μ½μ–΄μ™€μ„œ λ‹€μ–‘ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
::

import tomotopy as tp

mdl = tp.HDPModel()
for line in open('sample.txt'):
mdl.add_doc(line.strip().split())

for i in range(0, 100, 10):
mdl.train(10)
print('Iteration: {}\tLog-likelihood: {}'.format(i, mdl.ll_per_word))

# νŒŒμΌμ— μ €μž₯
mdl.save('sample_hdp_model.bin')

# νŒŒμΌλ‘œλΆ€ν„° 뢈러였기
mdl = tp.HDPModel.load('sample_hdp_model.bin')
for k in range(mdl.k):
if not mdl.is_live_topic(k): continue
print('Top 10 words of topic #{}'.format(k))
print(mdl.get_topic_words(k, top_n=10))

# μ €μž₯된 λͺ¨λΈμ΄ HDP λͺ¨λΈμ΄μ—ˆκΈ° λ•Œλ¬Έμ—,
# LDA λͺ¨λΈμ—μ„œ 이 νŒŒμΌμ„ μ½μ–΄μ˜€λ €κ³  ν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•©λ‹ˆλ‹€.
mdl = tp.LDAModel.load('sample_hdp_model.bin')

νŒŒμΌλ‘œλΆ€ν„° λͺ¨λΈμ„ 뢈러올 λ•ŒλŠ” λ°˜λ“œμ‹œ μ €μž₯된 λͺ¨λΈμ˜ νƒ€μž…κ³Ό μ½μ–΄μ˜¬ λͺ¨λΈμ˜ νƒ€μž…μ΄ μΌμΉ˜ν•΄μ•Όν•©λ‹ˆλ‹€.

이에 λŒ€ν•΄μ„œλŠ” `tomotopy.LDAModel.save`와 `tomotopy.LDAModel.load`μ—μ„œ 더 μžμ„Έν•œ λ‚΄μš©μ„ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

μΈν„°λž™ν‹°λΈŒ λͺ¨λΈ λ·°μ–΄
------------------

.. raw:: html

v0.13.0λΆ€ν„°λŠ” ν† ν”½ λͺ¨λΈλ§μ˜ κ²°κ³Όλ₯Ό μΈν„°λž™ν‹°λΈŒ λ·°μ–΄λ₯Ό 톡해 μ‚΄νŽ΄λ³΄λŠ” 것도 κ°€λŠ₯ν•©λ‹ˆλ‹€.

::

import tomotopy as tp
model = tp.LDAModel(...)
# ... some training codes ...
tp.viewer.open_viewer(model, host="localhost", port=9999)
# And open http://localhost:9999 in your web browser!

이미 μ €μž₯된 λͺ¨λΈ 파일이 μžˆλ‹€λ©΄ λ‹€μŒ λͺ…령행을 ν†΅ν•΄μ„œλ„ κ°„λ‹¨νžˆ λ·°μ–΄λ₯Ό ꡬ동할 수 μžˆμŠ΅λ‹ˆλ‹€.

::

python -m tomotopy.viewer a_trained_model.bin --host localhost --port 9999

μžμ„Έν•œ λ‚΄μš©μ€ `tomotopy.viewer`을 μ°Έμ‘°ν•˜μ„Έμš”.

λͺ¨λΈ μ•ˆμ˜ λ¬Έν—Œκ³Ό λͺ¨λΈ λ°–μ˜ λ¬Έν—Œ
-------------------------------------------
ν† ν”½ λͺ¨λΈμ€ 크게 2가지 λͺ©μ μœΌλ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
κΈ°λ³Έμ μœΌλ‘œλŠ” λ¬Έν—Œ μ§‘ν•©μœΌλ‘œλΆ€ν„° λͺ¨λΈμ„ ν•™μŠ΅ν•˜μ—¬ λ¬Έν—Œ λ‚΄μ˜ μ£Όμ œλ“€μ„ λ°œκ²¬ν•˜κΈ° μœ„ν•΄ ν† ν”½ λͺ¨λΈμ„ μ‚¬μš©ν•  수 있으며,
더 λ‚˜μ•„κ°€ ν•™μŠ΅λœ λͺ¨λΈμ„ ν™œμš©ν•˜μ—¬ ν•™μŠ΅ν•  λ•ŒλŠ” 주어지지 μ•Šμ•˜λ˜ μƒˆλ‘œμš΄ λ¬Έν—Œμ— λŒ€ν•΄ 주제 뢄포λ₯Ό μΆ”λ‘ ν•˜λŠ” 것도 κ°€λŠ₯ν•©λ‹ˆλ‹€.
μ „μžμ˜ κ³Όμ •μ—μ„œ μ‚¬μš©λ˜λŠ” λ¬Έν—Œ(ν•™μŠ΅ κ³Όμ •μ—μ„œ μ‚¬μš©λ˜λŠ” λ¬Έν—Œ)을 **λͺ¨λΈ μ•ˆμ˜ λ¬Έν—Œ**,
ν›„μžμ˜ κ³Όμ •μ—μ„œ μ£Όμ–΄μ§€λŠ” μƒˆλ‘œμš΄ λ¬Έν—Œ(ν•™μŠ΅ 과정에 ν¬ν•¨λ˜μ§€ μ•Šμ•˜λ˜ λ¬Έν—Œ)을 **λͺ¨λΈ λ°–μ˜ λ¬Έν—Œ**이라고 가리킀도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€.

`tomotopy`μ—μ„œ 이 두 μ’…λ₯˜μ˜ λ¬Έν—Œμ„ μƒμ„±ν•˜λŠ” 방법은 λ‹€λ¦…λ‹ˆλ‹€. **λͺ¨λΈ μ•ˆμ˜ λ¬Έν—Œ**은 `tomotopy.LDAModel.add_doc`을 μ΄μš©ν•˜μ—¬ μƒμ„±ν•©λ‹ˆλ‹€.
add_doc은 `tomotopy.LDAModel.train`을 μ‹œμž‘ν•˜κΈ° μ „κΉŒμ§€λ§Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
즉 train을 μ‹œμž‘ν•œ μ΄ν›„λ‘œλŠ” ν•™μŠ΅ λ¬Έν—Œ 집합이 κ³ μ •λ˜κΈ° λ•Œλ¬Έμ— add_doc을 μ΄μš©ν•˜μ—¬ μƒˆλ‘œμš΄ λ¬Έν—Œμ„ λͺ¨λΈ 내에 μΆ”κ°€ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

λ˜ν•œ μƒμ„±λœ λ¬Έν—Œμ˜ μΈμŠ€ν„΄μŠ€λ₯Ό μ–»κΈ° μœ„ν•΄μ„œλŠ” λ‹€μŒκ³Ό 같이 `tomotopy.LDAModel.docs`λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

::

mdl = tp.LDAModel(k=20)
idx = mdl.add_doc(words)
if idx < 0: raise RuntimeError("Failed to add doc")
doc_inst = mdl.docs[idx]
# doc_inst is an instance of the added document

**λͺ¨λΈ λ°–μ˜ λ¬Έν—Œ**은 `tomotopy.LDAModel.make_doc`을 μ΄μš©ν•΄ μƒμ„±ν•©λ‹ˆλ‹€. make_doc은 add_docκ³Ό λ°˜λŒ€λ‘œ train을 μ‹œμž‘ν•œ 이후에 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
λ§Œμ•½ train을 μ‹œμž‘ν•˜κΈ° 전에 make_doc을 μ‚¬μš©ν•  경우 μ˜¬λ°”λ₯΄μ§€ μ•Šμ€ κ²°κ³Όλ₯Ό μ–»κ²Œ λ˜λ‹ˆ 이 점 μœ μ˜ν•˜μ‹œκΈΈ λ°”λžλ‹ˆλ‹€. make_doc은 λ°”λ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν•˜λ―€λ‘œ λ°˜ν™˜κ°’μ„ λ°›μ•„ λ°”λ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

::

mdl = tp.LDAModel(k=20)
# add_doc ...
mdl.train(100)
doc_inst = mdl.make_doc(unseen_doc) # doc_inst is an instance of the unseen document

μƒˆλ‘œμš΄ λ¬Έν—Œμ— λŒ€ν•΄ μΆ”λ‘ ν•˜κΈ°
------------------------------
`tomotopy.LDAModel.make_doc`을 μ΄μš©ν•΄ μƒˆλ‘œμš΄ λ¬Έν—Œμ„ μƒμ„±ν–ˆλ‹€λ©΄ 이λ₯Ό λͺ¨λΈμ— μž…λ ₯ν•΄ 주제 뢄포λ₯Ό μΆ”λ‘ ν•˜λ„λ‘ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
μƒˆλ‘œμš΄ λ¬Έν—Œμ— λŒ€ν•œ 좔둠은 `tomotopy.LDAModel.infer`λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

::

mdl = tp.LDAModel(k=20)
# add_doc ...
mdl.train(100)
doc_inst = mdl.make_doc(unseen_doc)
topic_dist, ll = mdl.infer(doc_inst)
print("Topic Distribution for Unseen Docs: ", topic_dist)
print("Log-likelihood of inference: ", ll)

infer λ©”μ†Œλ“œλŠ” `tomotopy.Document` μΈμŠ€ν„΄μŠ€ ν•˜λ‚˜λ₯Ό μΆ”λ‘ ν•˜κ±°λ‚˜ `tomotopy.Document` μΈμŠ€ν„΄μŠ€μ˜ `list`λ₯Ό μΆ”λ‘ ν•˜λŠ”λ° μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
μžμ„Έν•œ 것은 `tomotopy.LDAModel.infer`을 μ°Έμ‘°ν•˜κΈΈ λ°”λžλ‹ˆλ‹€.

Corpus와 transform
--------------------
`tomotopy`의 λͺ¨λ“  ν† ν”½ λͺ¨λΈλ“€μ€ 각자 λ³„λ„μ˜ 내뢀적인 λ¬Έν—Œ νƒ€μž…μ„ 가지고 μžˆμŠ΅λ‹ˆλ‹€.
그리고 이 λ¬Έν—Œ νƒ€μž…λ“€μ— λ§žλŠ” λ¬Έν—Œλ“€μ€ 각 λͺ¨λΈμ˜ `add_doc` λ©”μ†Œλ“œλ₯Ό 톡해 생성될 수 μžˆμŠ΅λ‹ˆλ‹€.
ν•˜μ§€λ§Œ 이 λ•Œλ¬Έμ— λ™μΌν•œ λͺ©λ‘μ˜ λ¬Έν—Œλ“€μ„ μ„œλ‘œ λ‹€λ₯Έ ν† ν”½ λͺ¨λΈμ— μž…λ ₯ν•΄μ•Ό ν•˜λŠ” 경우
맀 λͺ¨λΈμ— 각 λ¬Έν—Œμ„ μΆ”κ°€ν• λ•Œλ§ˆλ‹€ `add_doc`을 ν˜ΈμΆœν•΄μ•Όν•˜κΈ° λ•Œλ¬Έμ— λΉ„νš¨μœ¨μ΄ λ°œμƒν•©λ‹ˆλ‹€.
λ”°λΌμ„œ `tomotopy`μ—μ„œλŠ” μ—¬λŸ¬ λ¬Έν—Œμ„ λ¬Άμ–΄μ„œ κ΄€λ¦¬ν•΄μ£ΌλŠ” `tomotopy.utils.Corpus` 클래슀λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.
ν† ν”½ λͺ¨λΈ 객체λ₯Ό μƒμ„±ν• λ•Œ `tomotopy.utils.Corpus`λ₯Ό `__init__` λ©”μ†Œλ“œμ˜ `corpus` 인자둜 λ„˜κ²¨μ€ŒμœΌλ‘œμ¨
μ–΄λ–€ λͺ¨λΈμ—λ“  μ‰½κ²Œ λ¬Έν—Œλ“€μ„ μ‚½μž…ν•  수 있게 ν•΄μ€λ‹ˆλ‹€.
`tomotopy.utils.Corpus`λ₯Ό ν† ν”½ λͺ¨λΈμ— μ‚½μž…ν•˜λ©΄ corpus 객체가 가지고 μžˆλŠ” λ¬Έν—Œλ“€ μ „λΆ€κ°€ λͺ¨λΈμ— μžλ™μœΌλ‘œ μ‚½μž…λ©λ‹ˆλ‹€.

그런데 일뢀 ν† ν”½ λͺ¨λΈμ˜ 경우 λ¬Έν—Œμ„ μƒμ„±ν•˜κΈ° μœ„ν•΄ μ„œλ‘œ λ‹€λ₯Έ 데이터λ₯Ό μš”κ΅¬ν•©λ‹ˆλ‹€.
예λ₯Ό λ“€μ–΄ `tomotopy.DMRModel`λŠ” `metadata`λΌλŠ” `str` νƒ€μž…μ˜ 데이터λ₯Ό μš”κ΅¬ν•˜κ³ ,
`tomotopy.PLDAModel`λŠ” `labels`λΌλŠ” `List[str]` νƒ€μž…μ˜ 데이터λ₯Ό μš”κ΅¬ν•©λ‹ˆλ‹€.
κ·ΈλŸ¬λ‚˜ `tomotopy.utils.Corpus`λŠ” ν† ν”½ λͺ¨λΈμ— μ’…μ†λ˜μ§€ μ•Šμ€ 독립적인 λ¬Έν—Œ 데이터λ₯Ό λ³΄κ΄€ν•˜κΈ° λ•Œλ¬Έμ—,
corpusκ°€ 가지고 μžˆλŠ” λ¬Έν—Œ 데이터가 μ‹€μ œ ν† ν”½ λͺ¨λΈμ΄ μš”κ΅¬ν•˜λŠ” 데이터와 μΌμΉ˜ν•˜μ§€ μ•Šμ„ κ°€λŠ₯성이 μžˆμŠ΅λ‹ˆλ‹€.
이 경우 `transform`λΌλŠ” 인자λ₯Ό 톡해 corpus λ‚΄μ˜ 데이터λ₯Ό λ³€ν˜•μ‹œμΌœ ν† ν”½ λͺ¨λΈμ΄ μš”κ΅¬ν•˜λŠ” μ‹€μ œ 데이터와 μΌμΉ˜μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.
μžμ„Έν•œ λ‚΄μš©μ€ μ•„λž˜μ˜ μ½”λ“œλ₯Ό ν™•μΈν•΄μ£Όμ„Έμš”:

::

from tomotopy import DMRModel
from tomotopy.utils import Corpus

corpus = Corpus()
corpus.add_doc("a b c d e".split(), a_data=1)
corpus.add_doc("e f g h i".split(), a_data=2)
corpus.add_doc("i j k l m".split(), a_data=3)

model = DMRModel(k=10)
model.add_corpus(corpus)
# `corpus`에 있던 `a_data`λŠ” 사라지고
# `DMRModel`이 μš”κ΅¬ν•˜λŠ” `metadata`μ—λŠ” 기본값인 빈 λ¬Έμžμ—΄μ΄ μ±„μ›Œμ§‘λ‹ˆλ‹€.

assert model.docs[0].metadata == ''
assert model.docs[1].metadata == ''
assert model.docs[2].metadata == ''

def transform_a_data_to_metadata(misc: dict):
return {'metadata': str(misc['a_data'])}
# 이 ν•¨μˆ˜λŠ” `a_data`λ₯Ό `metadata`둜 λ³€ν™˜ν•©λ‹ˆλ‹€.

model = DMRModel(k=10)
model.add_corpus(corpus, transform=transform_a_data_to_metadata)
# 이제 `model`μ—λŠ” 기본값이 μ•„λ‹Œ `metadata`κ°€ μž…λ ₯λ©λ‹ˆλ‹€. 이듀은 `transform`에 μ˜ν•΄ `a_data`λ‘œλΆ€ν„° μƒμ„±λ©λ‹ˆλ‹€.

assert model.docs[0].metadata == '1'
assert model.docs[1].metadata == '2'
assert model.docs[2].metadata == '3'

병렬 μƒ˜ν”Œλ§ μ•Œκ³ λ¦¬μ¦˜
----------------------------
`tomotopy`λŠ” 0.5.0버전뢀터 병렬 μ•Œκ³ λ¦¬μ¦˜μ„ κ³ λ₯Ό 수 μžˆλŠ” 선택지λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.
0.4.2 μ΄μ „λ²„μ „κΉŒμ§€ 제곡되던 μ•Œκ³ λ¦¬μ¦˜μ€ `COPY_MERGE`둜 이 기법은 λͺ¨λ“  ν† ν”½ λͺ¨λΈμ— μ‚¬μš© κ°€λŠ₯ν•©λ‹ˆλ‹€.
μƒˆλ‘œμš΄ μ•Œκ³ λ¦¬μ¦˜μΈ `PARTITION`은 0.5.0이후뢀터 μ‚¬μš©κ°€λŠ₯ν•˜λ©°, 이λ₯Ό μ‚¬μš©ν•˜λ©΄ 더 λΉ λ₯΄κ³  λ©”λͺ¨λ¦¬ 효율적으둜 ν•™μŠ΅μ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 단 이 기법은 일뢀 ν† ν”½ λͺ¨λΈμ— λŒ€ν•΄μ„œλ§Œ μ‚¬μš© κ°€λŠ₯ν•©λ‹ˆλ‹€.

λ‹€μŒ μ°¨νŠΈλŠ” ν† ν”½ κ°œμˆ˜μ™€ μ½”μ–΄ κ°œμˆ˜μ— 따라 두 κΈ°λ²•μ˜ 속도 차이λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.

.. image:: https://bab2min.github.io/tomotopy/images/algo_comp.png

.. image:: https://bab2min.github.io/tomotopy/images/algo_comp2.png

버전별 속도 차이
----------------------
μ•„λž˜ κ·Έλž˜ν”„λŠ” 버전별 속도 차이λ₯Ό ν‘œμ‹œν•œ κ²ƒμž…λ‹ˆλ‹€.
LDAλͺ¨λΈλ‘œ 1000회 iteration을 μˆ˜ν–‰μ‹œ κ±Έλ¦¬λŠ” μ‹œκ°„μ„ 초 λ‹¨μœ„λ‘œ ν‘œμ‹œν•˜μ˜€μŠ΅λ‹ˆλ‹€.
(Docs: 11314, Vocab: 60382, Words: 2364724, Intel Xeon Gold 5120 @2.2GHz)

.. image:: https://bab2min.github.io/tomotopy/images/lda-perf-t1.png

.. image:: https://bab2min.github.io/tomotopy/images/lda-perf-t4.png

.. image:: https://bab2min.github.io/tomotopy/images/lda-perf-t8.png

μ–΄νœ˜ 사전뢄포λ₯Ό μ΄μš©ν•˜μ—¬ 주제 κ³ μ •ν•˜κΈ°
--------------------------------------
0.6.0 버전뢀터 `tomotopy.LDAModel.set_word_prior`λΌλŠ” λ©”μ†Œλ“œκ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이 λ©”μ†Œλ“œλ‘œ νŠΉμ • λ‹¨μ–΄μ˜ 사전뢄포λ₯Ό μ‘°μ ˆν•  수 μžˆμŠ΅λ‹ˆλ‹€.
예λ₯Ό λ“€μ–΄ λ‹€μŒ μ½”λ“œμ²˜λŸΌ 단어 'church'의 κ°€μ€‘μΉ˜λ₯Ό Topic 0에 λŒ€ν•΄μ„œλŠ” 1.0, λ‚˜λ¨Έμ§€ Topic에 λŒ€ν•΄μ„œλŠ” 0.1둜 μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
μ΄λŠ” 단어 'church'κ°€ Topic 0에 할당될 ν™•λ₯ μ΄ λ‹€λ₯Έ Topic에 할당될 ν™•λ₯ λ³΄λ‹€ 10λ°° λ†’λ‹€λŠ” 것을 μ˜λ―Έν•˜λ©°, λ”°λΌμ„œ λŒ€λΆ€λΆ„μ˜ 'church'λŠ” Topic 0에 ν• λ‹Ήλ˜κ²Œ λ©λ‹ˆλ‹€.
그리고 ν•™μŠ΅μ„ 거치며 'church'와 κ΄€λ ¨λœ 단어듀 μ—­μ‹œ Topic 0에 λͺ¨μ΄κ²Œ λ˜λ―€λ‘œ, μ΅œμ’…μ μœΌλ‘œ Topic 0은 'church'와 κ΄€λ ¨λœ μ£Όμ œκ°€ 될 κ²ƒμž…λ‹ˆλ‹€.
이λ₯Ό 톡해 νŠΉμ • λ‚΄μš©μ˜ 주제λ₯Ό μ›ν•˜λŠ” Topic λ²ˆν˜Έμ— κ³ μ •μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

::

import tomotopy as tp
mdl = tp.LDAModel(k=20)

# add documents into `mdl`

# setting word prior
mdl.set_word_prior('church', [1.0 if k == 0 else 0.1 for k in range(20)])

μžμ„Έν•œ λ‚΄μš©μ€ `example.py`의 `word_prior_example` ν•¨μˆ˜λ₯Ό μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€.

예제 μ½”λ“œ
---------
tomotopy의 Python3 예제 μ½”λ“œλŠ” https://github.com/bab2min/tomotopy/blob/main/examples/ λ₯Ό ν™•μΈν•˜μ‹œκΈΈ λ°”λžλ‹ˆλ‹€.

예제 μ½”λ“œμ—μ„œ μ‚¬μš©ν–ˆλ˜ 데이터 νŒŒμΌμ€ https://drive.google.com/file/d/18OpNijd4iwPyYZ2O7pQoPyeTAKEXa71J/view μ—μ„œ λ‹€μš΄λ°›μ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

λΌμ΄μ„ΌμŠ€
---------
`tomotopy`λŠ” MIT License ν•˜μ— λ°°ν¬λ©λ‹ˆλ‹€.

역사
-------
* 0.13.0 (2024-08-05)
* μ‹ κ·œ κΈ°λŠ₯
* ν† ν”½ λͺ¨λΈ 뷰어인 `tomotopy.viewer.open_viewer()`의 μ£Όμš” κΈ°λŠ₯이 μ™„μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.LDAModel.get_hash()`κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. λͺ¨λΈμ˜ 128bit ν•΄μ‹œλ₯Ό κ΅¬ν•΄μ€λ‹ˆλ‹€.
* `ngram_list` μΈμžκ°€ `tomotopy.utils.SimpleTokenizer`에 μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* Bug fixes
* `Corpus.concat_ngrams` 호좜 후에 `spans`이 비일관적인 버그가 μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.LDAModel.load()`와 `tomotopy.LDAModel.save()`의 병λͺ©μ„ μ΅œμ ν™”ν•˜μ—¬ 속도λ₯Ό 10λ°° 이상 κ°œμ„ ν–ˆμŠ΅λ‹ˆλ‹€.

* 0.12.7 (2023-12-19)
* μ‹ κ·œ κΈ°λŠ₯
* ν† ν”½ λͺ¨λΈ 뷰어인 `tomotopy.viewer.open_viewer()`κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.utils.Corpus.process()`의 속도λ₯Ό κ°œμ„ ν–ˆμŠ΅λ‹ˆλ‹€.
* Bug fixes
* `Document.span`이 이제 λ°”μ΄νŠΈ λ‹¨μœ„κ°€ μ•„λ‹ˆλΌ 문자 λ‹¨μœ„λ‘œ λ²”μœ„λ₯Ό μ œλŒ€λ‘œ λ°˜ν™˜ν•©λ‹ˆλ‹€.

* 0.12.6 (2023-12-11)
* μ‹ κ·œ κΈ°λŠ₯
* `tomotopy.LDAModel.train`κ³Ό `tomotopy.LDAModel.set_word_prior`에 λͺ‡κ°€μ§€ 편의 κΈ°λŠ₯을 μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.
* `LDAModel.train`κ°€ 이제 ν•™μŠ΅ 진행상황을 λͺ¨λ‹ˆν„°λ§ν•  수 μžˆλŠ” `callback`, `callback_interval`, `show_progres` 인자λ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
* `LDAModel.set_word_prior`κ°€ 이제 `prior` 인자둜 `Dict[int, float]` νƒ€μž…λ„ 받을 수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.12.5 (2023-08-03)
* μ‹ κ·œ κΈ°λŠ₯
* Linux ARM64 μ•„ν‚€ν…μ²˜μ— λŒ€ν•œ 지원을 μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.

* 0.12.4 (2023-01-22)
* New features
* macOS ARM64 μ•„ν‚€ν…μ²˜μ— λŒ€ν•œ 지원을 μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.
* Bug fixes
* `tomotopy.Document.get_sub_topic_dist()`κ°€ bad argument μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€λŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* μ˜ˆμ™Έ λ°œμƒμ΄ μ’…μ’… ν¬λž˜μ‹œλ₯Ό λ°œμƒμ‹œν‚€λŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.

* 0.12.3 (2022-07-19)
* κΈ°λŠ₯ κ°œμ„ 
* 이제 `tomotopy.LDAModel.add_doc()`둜 빈 λ¬Έμ„œλ₯Ό μ‚½μž…ν•  경우 μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€λŠ” λŒ€μ‹  κ·Έλƒ₯ λ¬΄μ‹œν•©λ‹ˆλ‹€. μƒˆλ‘œ μΆ”κ°€λœ 인자인 `ignore_empty_words`λ₯Ό False둜 μ„€μ •ν•  경우 μ΄μ „μ²˜λŸΌ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.
* μœ νš¨ν•˜μ§€ μ•Šμ€ 토픽듀을 λͺ¨λΈμ—μ„œ μ œκ±°ν•˜λŠ” `tomotopy.HDPModel.purge_dead_topics()` λ©”μ†Œλ“œκ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* 버그 μˆ˜μ •
* `tomotopy.SLDAModel`μ—μ„œ `nuSq` 값을 지정할 λ•Œ λ°œμƒν•˜λŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€. (by @jucendrero)
* `tomotopy.utils.Coherence`κ°€ `tomotopy.DTModel`에 λŒ€ν•΄μ„œ μž‘λ™ν•˜μ§€ μ•ŠλŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* `train()` 호좜 전에 `make_dic()`을 ν˜ΈμΆœν•  λ•Œ μ’…μ’… ν¬λž˜μ‹œκ°€ λ°œμƒν•˜λŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* seedκ°€ κ³ μ •λœ μƒνƒœμ—μ„œλ„ `tomotopy.DMRModel`, `tomotopy.GDMRModel`의 κ²°κ³Όκ°€ λ‹€λ₯΄κ²Œ λ‚˜μ˜€λŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.DMRModel`, `tomotopy.GDMRModel`의 νŒŒλΌλ―Έν„° μ΅œμ ν™” 과정이 λΆ€μ •ν™•ν•˜λ˜ 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.PTModel.copy()` 호좜 μ‹œ μ’…μ’… ν¬λž˜μ‹œκ°€ λ°œμƒν•˜λŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* μ‹±κΈ€μŠ€λ ˆλ“œμ—μ„œμ˜ μž‘λ™ νš¨μœ¨μ„ κ°œμ„ ν–ˆμŠ΅λ‹ˆλ‹€.

* 0.12.2 (2021-09-06)
* `min_cf > 0`, `min_df > 0`λ‚˜ `rm_top > 0`둜 μ„€μ •λœ `tomotopy.HDPModel`μ—μ„œ `convert_to_lda`λ₯Ό ν˜ΈμΆœν• λ•Œ ν¬λž˜μ‹œκ°€ λ°œμƒν•˜λŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.Document.get_topics`와 `tomotopy.Document.get_topic_dist`에 `from_pseudo_doc` μΈμžκ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
이 μΈμžλŠ” `PTModel`에 λŒ€ν•΄μ„œλ§Œ μœ νš¨ν•˜λ©°, 이λ₯Ό 톡해 ν† ν”½ 뢄포λ₯Ό ꡬ할 λ•Œ 가상 λ¬Έν—Œμ„ μ‚¬μš©ν• μ§€ μ—¬λΆ€λ₯Ό 선택할 수 μžˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.PTModel` μƒμ„±μ‹œ κΈ°λ³Έ μΈμžκ°’μ΄ λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€. `p`λ₯Ό μƒλž΅μ‹œ `k * 10`으둜 μ„€μ •λ©λ‹ˆλ‹€.
* `make_doc`으둜 μƒμ„±ν•œ λ¬Έν—Œμ„ `infer` 없이 μ‚¬μš©ν•  경우 λ°œμƒν•˜λŠ” ν¬λž˜μ‹œλ₯Ό ν•΄κ²°ν•˜κ³  κ²½κ³  메세지λ₯Ό μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.
* λ‚΄λΆ€ C++μ½”λ“œκ°€ clang c++17 ν™˜κ²½μ—μ„œ μ»΄νŒŒμΌμ— μ‹€νŒ¨ν•˜λŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.

* 0.12.1 (2021-06-20)
* `tomotopy.LDAModel.set_word_prior()`κ°€ ν¬λž˜μ‹œλ₯Ό λ°œμƒμ‹œν‚€λ˜ 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* 이제 `tomotopy.LDAModel.perplexity`와 `tomotopy.LDAModel.ll_per_word`κ°€ TermWeightκ°€ ONE이 μ•„λ‹Œ κ²½μš°μ—λ„ μ •ν™•ν•œ 값을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
* μš©μ–΄κ°€μ€‘μΉ˜κ°€ 적용된 λΉˆλ„μˆ˜λ₯Ό λ°˜ν™˜ν•˜λŠ” `tomotopy.LDAModel.used_vocab_weighted_freq`κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* 이제 `tomotopy.LDAModel.summary()`κ°€ λ‹¨μ–΄μ˜ μ—”νŠΈλ‘œν”ΌλΏλ§Œ μ•„λ‹ˆλΌ, μš©μ–΄ κ°€μ€‘μΉ˜κ°€ 적용된 λ‹¨μ–΄μ˜ μ—”νŠΈλ‘œν”Όλ„ ν•¨κ»˜ λ³΄μ—¬μ€λ‹ˆλ‹€.

* 0.12.0 (2021-04-26)
* 이제 `tomotopy.DMRModel`와 `tomotopy.GDMRModel`κ°€ 닀쀑 메타데이터λ₯Ό μ§€μ›ν•©λ‹ˆλ‹€. (https://github.com/bab2min/tomotopy/blob/main/examples/dmr_multi_label.py μ°Έμ‘°)
* `tomotopy.GDMRModel`의 μ„±λŠ₯이 κ°œμ„ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* κΉŠμ€ 볡사λ₯Ό μˆ˜ν–‰ν•˜λŠ” `copy()` λ©”μ†Œλ“œκ°€ λͺ¨λ“  ν† ν”½ λͺ¨λΈ ν΄λž˜μŠ€μ— μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `min_cf`, `min_df` 등에 μ˜ν•΄ ν•™μŠ΅μ—μ„œ μ œμ™Έλœ 단어가 잘λͺ»λœ ν† ν”½id값을 κ°€μ§€λŠ” λ¬Έμ œκ°€ ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이제 μ œμ™Έλ‹¨ 단어듀은 ν† ν”½id둜 λͺ¨λ‘ `-1` 값을 κ°€μ§‘λ‹ˆλ‹€.
* 이제 `tomotopy`에 μ˜ν•΄ μƒμ„±λ˜λŠ” μ˜ˆμ™Έ 및 κ²½κ³ κ°€ λͺ¨λ‘ Python ν‘œμ€€ νƒ€μž…μ„ λ”°λ¦…λ‹ˆλ‹€.
* 컴파일러 μš”κ΅¬μ‚¬ν•­μ΄ C++14둜 상ν–₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.11.1 (2021-03-28)
* λΉ„λŒ€μΉ­ alpha와 κ΄€λ ¨λœ 치λͺ…적인 버그가 μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이 λ²„κ·Έλ‘œ 인해 0.11.0 버전은 λ¦΄λ¦¬μ¦ˆμ—μ„œ μ‚­μ œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.11.0 (2021-03-26)
* 짧은 ν…μŠ€νŠΈλ₯Ό μœ„ν•œ ν† ν”½ λͺ¨λΈμΈ `tomotopy.PTModel`κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.HDPModel.infer`κ°€ μ’…μ’… segmentation faultλ₯Ό λ°œμƒμ‹œν‚€λŠ” λ¬Έμ œκ°€ ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* numpy API 버전 좩돌이 ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* 이제 λΉ„λŒ€μΉ­ λ¬Έν—Œ-ν† ν”½ 사전 뢄포가 μ§€μ›λ©λ‹ˆλ‹€.
* ν† ν”½ λͺ¨λΈ 객체λ₯Ό λ©”λͺ¨λ¦¬ μƒμ˜ `bytes`둜 μ§λ ¬ν™”ν•˜λŠ” κΈ°λŠ₯이 μ§€μ›λ©λ‹ˆλ‹€.
* `get_topic_dist()`, `get_topic_word_dist()`, `get_sub_topic_dist()`에 결과의 μ •κ·œν™” μ—¬λΆ€λ₯Ό μ‘°μ ˆν•˜λŠ” `normalize` μΈμžκ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.DMRModel.lambdas`와 `tomotopy.DMRModel.alpha`κ°€ 잘λͺ»λœ 값을 μ œκ³΅ν•˜λ˜ λ¬Έμ œκ°€ ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.GDMRModel`에 λ²”μ£Όν˜• 메타데이터 지원이 μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. (https://github.com/bab2min/tomotopy/blob/main/examples/gdmr_both_categorical_and_numerical.py μ°Έμ‘°)
* Python3.5 지원이 μ’…λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.10.2 (2021-02-16)
* `tomotopy.CTModel.train`κ°€ 큰 K값에 λŒ€ν•΄ μ‹€νŒ¨ν•˜λŠ” λ¬Έμ œκ°€ μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.utils.Corpus`κ°€ `uid`값을 μžƒλŠ” λ¬Έμ œκ°€ μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.10.1 (2021-02-14)
* `tomotopy.utils.Corpus.extract_ngrams`에 빈 λ¬Έν—Œμ„ μž…λ ₯μ‹œ λ°œμƒν•˜λ˜ μ—λŸ¬λ₯Ό μˆ˜μ •ν–ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.LDAModel.infer`κ°€ μ˜¬λ°”λ₯Έ μž…λ ₯에도 μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€λ˜ 문제λ₯Ό μˆ˜μ •ν–ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.HLDAModel.infer`κ°€ 잘λͺ»λœ `tomotopy.Document.path` 값을 μƒμ„±ν•˜λŠ” 문제λ₯Ό μˆ˜μ •ν–ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.HLDAModel.train`에 μƒˆλ‘œμš΄ νŒŒλΌλ―Έν„° `freeze_topics`κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 ν•™μŠ΅ μ‹œ μ‹ κ·œ ν† ν”½ 생성 μ—¬λΆ€λ₯Ό μ‘°μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

* 0.10.0 (2020-12-19)
* `tomotopy.utils.Corpus`와 `tomotopy.LDAModel.docs` κ°„μ˜ μΈν„°νŽ˜μ΄μŠ€κ°€ ν†΅μΌλ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이제 λ™μΌν•œ λ°©λ²•μœΌλ‘œ μ½”νΌμŠ€ λ‚΄μ˜ λ¬Έν—Œλ“€μ— μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.utils.Corpus`의 __getitem__이 κ°œμ„ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. int νƒ€μž… μΈλ±μ‹±λΏλ§Œ μ•„λ‹ˆλΌ Iterable[int]λ‚˜ slicingλ₯Ό μ΄μš©ν•œ 닀쀑 인덱싱, uidλ₯Ό μ΄μš©ν•œ 인덱싱 등이 μ œκ³΅λ©λ‹ˆλ‹€.
* `tomotopy.utils.Corpus.extract_ngrams`와 `tomotopy.utils.Corpus.concat_ngrams`이 μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. PMIλ₯Ό μ΄μš©ν•΄ μ½”νΌμŠ€ λ‚΄μ—μ„œ μžλ™μœΌλ‘œ n-gram collocation을 λ°œκ²¬ν•΄ ν•œ λ‹¨μ–΄λ‘œ ν•©μΉ˜λŠ” κΈ°λŠ₯을 μˆ˜ν–‰ν•©λ‹ˆλ‹€.
* `tomotopy.LDAModel.add_corpus`κ°€ μΆ”κ°€λ˜μ—ˆκ³ , `tomotopy.LDAModel.infer`κ°€ Raw μ½”νΌμŠ€λ₯Ό μž…λ ₯으둜 받을 수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.coherence` λͺ¨λ“ˆμ΄ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μƒμ„±λœ ν† ν”½ λͺ¨λΈμ˜ coherenceλ₯Ό κ³„μ‚°ν•˜λŠ” κΈ°λŠ₯을 λ‹΄λ‹Ήν•©λ‹ˆλ‹€.
* `tomotopy.label.FoRelevance`에 window_size νŒŒλΌλ―Έν„°κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.HDPModel` ν•™μŠ΅ μ‹œ μ’…μ’… NaN이 λ°œμƒν•˜λŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* 이제 Python3.9λ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
* py-cpuinfo에 λŒ€ν•œ μ˜μ‘΄μ„±μ΄ 제거되고, λͺ¨λ“ˆ λ‘œλ”©μ†λ„κ°€ κ°œμ„ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.9.1 (2020-08-08)
* 0.9.0 λ²„μ „μ˜ λ©”λͺ¨λ¦¬ λˆ„μˆ˜ λ¬Έμ œκ°€ ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.CTModel.summary()`κ°€ 잘λͺ»λœ κ²°κ³Όλ₯Ό 좜λ ₯ν•˜λŠ” λ¬Έμ œκ°€ ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.9.0 (2020-08-04)
* λͺ¨λΈμ˜ μƒνƒœλ₯Ό μ•Œμ•„λ³΄κΈ° μ‰½κ²Œ 좜λ ₯ν•΄μ£ΌλŠ” `tomotopy.LDAModel.summary()` λ©”μ†Œλ“œκ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* λ‚œμˆ˜ 생성기λ₯Ό `EigenRand`_둜 λŒ€μ²΄ν•˜μ—¬ 생성 속도λ₯Ό 높이고 ν”Œλž«νΌ κ°„μ˜ κ²°κ³Ό 차이λ₯Ό ν•΄μ†Œν•˜μ˜€μŠ΅λ‹ˆλ‹€.
* 이둜 인해 `seed`κ°€ 동일해도 λͺ¨λΈ ν•™μŠ΅ κ²°κ³Όκ°€ 0.9.0 이전 버전과 λ‹¬λΌμ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.HDPModel`μ—μ„œ κ°„ν—μ μœΌλ‘œ λ°œμƒν•˜λŠ” ν•™μŠ΅ 였λ₯˜λ₯Ό μˆ˜μ •ν–ˆμŠ΅λ‹ˆλ‹€.
* 이제 `tomotopy.DMRModel.alpha`κ°€ 메타데이터별 ν† ν”½ λΆ„ν¬μ˜ 사전 νŒŒλΌλ―Έν„°λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.
* `tomotopy.DTModel.get_count_by_topics()`κ°€ 2차원 `ndarray`λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.DTModel.alpha`κ°€ `tomotopy.DTModel.get_alpha()`와 λ™μΌν•œ 값을 λ°˜ν™˜ν•˜λ„λ‘ μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.GDMRModel`의 document에 λŒ€ν•΄ `metadata` 값을 μ–»μ–΄μ˜¬ 수 μ—†λ˜ λ¬Έμ œκ°€ ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* 이제 `tomotopy.HLDAModel.alpha`κ°€ λ¬Έν—Œλ³„ 계측 λΆ„ν¬μ˜ 사전 νŒŒλΌλ―Έν„°λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.
* `tomotopy.LDAModel.global_step`이 μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* 이제 `tomotopy.MGLDAModel.get_count_by_topics()`κ°€ μ „μ—­ ν† ν”½κ³Ό 지역 ν† ν”½ λͺ¨λ‘μ˜ 단어 개수λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.
* `tomotopy.PAModel.alpha`, `tomotopy.PAModel.subalpha`, `tomotopy.PAModel.get_count_by_super_topic()`이 μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

.. _EigenRand: https://github.com/bab2min/EigenRand

* 0.8.2 (2020-07-14)
* `tomotopy.DTModel.num_timepoints`와 `tomotopy.DTModel.num_docs_by_timepoint` ν”„λ‘œνΌν‹°κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `seed`κ°€ 동일해도 ν”Œλž«νΌμ΄ λ‹€λ₯΄λ©΄ λ‹€λ₯Έ κ²°κ³Όλ₯Ό λ‚΄λ˜ λ¬Έμ œκ°€ 일뢀 ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이둜 인해 32bit λ²„μ „μ˜ λͺ¨λΈ ν•™μŠ΅ κ²°κ³Όκ°€ 이전 λ²„μ „κ³ΌλŠ” λ‹¬λΌμ‘ŒμŠ΅λ‹ˆλ‹€.

* 0.8.1 (2020-06-08)
* `tomotopy.LDAModel.used_vocabs`κ°€ 잘λͺ»λœ 값을 λ°˜ν™˜ν•˜λŠ” 버그가 μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* 이제 `tomotopy.CTModel.prior_cov`κ°€ `[k, k]` λͺ¨μ–‘μ˜ 곡뢄산 행렬을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
* 이제 인자 없이 `tomotopy.CTModel.get_correlations`λ₯Ό ν˜ΈμΆœν•˜λ©΄ `[k, k]` λͺ¨μ–‘μ˜ 상관관계 행렬을 λ°˜ν™˜ν•©λ‹ˆλ‹€.

* 0.8.0 (2020-06-06)
* NumPyκ°€ tomotopy에 λ„μž…λ¨μ— 따라 λ§Žμ€ λ©”μ†Œλ“œμ™€ ν”„λ‘œνΌν‹°λ“€μ΄ `list`κ°€ μ•„λ‹ˆλΌ `numpy.ndarray`λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* Tomotopy에 μƒˆ μ˜μ‘΄κ΄€κ³„ `NumPy >= 1.10.0`κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€..
* `tomotopy.HDPModel.infer`κ°€ 잘λͺ»λœ 좔둠을 ν•˜λ˜ λ¬Έμ œκ°€ μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* HDP λͺ¨λΈμ„ LDA λͺ¨λΈλ‘œ λ³€ν™˜ν•˜λŠ” λ©”μ†Œλ“œκ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.LDAModel.used_vocabs`, `tomotopy.LDAModel.used_vocab_freq`, `tomotopy.LDAModel.used_vocab_df` λ“±μ˜ μƒˆλ‘œμš΄ ν”„λ‘œνΌν‹°κ°€ λͺ¨λΈμ— μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* μƒˆλ‘œμš΄ ν† ν”½ λͺ¨λΈμΈ g-DMR(`tomotopy.GDMRModel`)κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* macOSμ—μ„œ `tomotopy.label.FoRelevance`λ₯Ό 생성할 λ•Œ λ°œμƒν•˜λ˜ λ¬Έμ œκ°€ ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.utils.Corpus.add_doc`둜 `raw`κ°€ μ—†λŠ” λ¬Έν—Œμ„ μƒμ„±ν•œ λ’€ ν† ν”½ λͺ¨λΈμ— μž…λ ₯ν•  μ‹œ λ°œμƒν•˜λŠ” 였λ₯˜λ₯Ό μˆ˜μ •ν–ˆμŠ΅λ‹ˆλ‹€.

* 0.7.1 (2020-05-08)
* `tomotopy.HLDAModel`용으둜 `tomotopy.Document.path`κ°€ μƒˆλ‘œ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.label.PMIExtractor` μ‚¬μš©μ‹œμ— λ°œμƒν•˜λ˜ λ©”λͺ¨λ¦¬ λ¬Έμ œκ°€ ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* gcc 7μ—μ„œ λ°œμƒν•˜λ˜ 컴파일 였λ₯˜κ°€ ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.7.0 (2020-04-18)
* `tomotopy.DTModel`이 μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.utils.Corpus.save`κ°€ μ œλŒ€λ‘œ μž‘λ™ν•˜μ§€ μ•ŠλŠ” 버그가 μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.Document.get_count_vector`κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* λ¦¬λˆ…μŠ€μš© λ°”μ΄λ„ˆλ¦¬κ°€ manylinux2010 λ²„μ „μœΌλ‘œ λ³€κ²½λ˜μ—ˆκ³  이에 λ”°λ₯Έ μ΅œμ ν™”κ°€ μ§„ν–‰λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.6.2 (2020-03-28)
* `save`와 `load`에 κ΄€λ ¨λœ 치λͺ…적인 버그가 μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€. ν•΄λ‹Ή λ²„κ·Έλ‘œ 0.6.0 및 0.6.1 버전은 λ¦΄λ¦¬μ¦ˆμ—μ„œ μ‚­μ œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.6.1 (2020-03-22) (μ‚­μ œλ¨)
* λͺ¨λ“ˆ λ‘œλ”©κ³Ό κ΄€λ ¨λœ 버그가 μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.6.0 (2020-03-22) (μ‚­μ œλ¨)
* λŒ€λŸ‰μ˜ λ¬Έν—Œμ„ κ΄€λ¦¬ν•˜κΈ° μœ„ν•œ `tomotopy.utils.Corpus`κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* μ–΄νœ˜-주제 λΆ„ν¬μ˜ 사전 ν™•λ₯ μ„ μ‘°μ ˆν•  수 μžˆλŠ” `tomotopy.LDAModel.set_word_prior` λ©”μ†Œλ“œκ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* λ¬Έν—Œ λΉˆλ„λ₯Ό 기반으둜 μ–΄νœ˜λ₯Ό 필터링할 수 μžˆλ„λ‘ ν† ν”½ λͺ¨λΈμ˜ μƒμ„±μžμ— `min_df`κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* ν† ν”½ 라벨링 κ΄€λ ¨ μ„œλΈŒλͺ¨λ“ˆμΈ `tomotopy.label`이 μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. ν˜„μž¬λŠ” `tomotopy.label.FoRelevance`만 μ œκ³΅λ©λ‹ˆλ‹€.

* 0.5.2 (2020-03-01)
* `tomotopy.LLDAModel.add_doc` μ‹€ν–‰μ‹œ segmentation faultκ°€ λ°œμƒν•˜λŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.HDPModel`μ—μ„œ `infer` μ‹€ν–‰μ‹œ μ’…μ’… ν”„λ‘œκ·Έλž¨μ΄ μ’…λ£Œλ˜λŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.LDAModel.infer`μ—μ„œ ps=tomotopy.ParallelScheme.PARTITION, together=True둜 μ‹€ν–‰μ‹œ λ°œμƒν•˜λŠ” 였λ₯˜λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.

* 0.5.1 (2020-01-11)
* `tomotopy.SLDAModel.make_doc`μ—μ„œ 결츑값을 μ§€μ›ν•˜μ§€ μ•Šλ˜ 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.SLDAModel`이 이제 결츑값을 μ§€μ›ν•©λ‹ˆλ‹€. 결츑값을 가진 λ¬Έν—Œμ€ ν† ν”½ λͺ¨λΈλ§μ—λŠ” μ°Έμ—¬ν•˜μ§€λ§Œ, 응닡 λ³€μˆ˜ νšŒκ·€μ—μ„œλŠ” μ œμ™Έλ©λ‹ˆλ‹€.

* 0.5.0 (2019-12-30)
* `tomotopy.PAModel.infer`κ°€ topic distributionκ³Ό sub-topic distribution을 λ™μ‹œμ— λ°˜ν™˜ν•©λ‹ˆλ‹€.
* `tomotopy.Document`에 get_sub_topics, get_sub_topic_dist λ©”μ†Œλ“œκ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. (PAModel μ „μš©)
* `tomotopy.LDAModel.train` 및 `tomotopy.LDAModel.infer` λ©”μ†Œλ“œμ— parallel μ˜΅μ…˜μ΄ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 ν•™μŠ΅ 및 μΆ”λ‘ μ‹œ μ‚¬μš©ν•  병렬화 μ•Œκ³ λ¦¬μ¦˜μ„ 선택할 수 μžˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.ParallelScheme.PARTITION` μ•Œκ³ λ¦¬μ¦˜μ΄ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이 μ•Œκ³ λ¦¬μ¦˜μ€ μž‘μ—…μž μˆ˜κ°€ λ§Žκ±°λ‚˜ ν† ν”½μ˜ κ°œμˆ˜λ‚˜ μ–΄νœ˜ 크기가 클 λ•Œλ„ 효율적으둜 μž‘λ™ν•©λ‹ˆλ‹€.
* λͺ¨λΈ μƒμ„±μ‹œ min_cf < 2μΌλ•Œ rm_top μ˜΅μ…˜μ΄ μ μš©λ˜μ§€ μ•ŠλŠ” 문제λ₯Ό μˆ˜μ •ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

* 0.4.2 (2019-11-30)
* `tomotopy.LLDAModel`와 `tomotopy.PLDAModel` λͺ¨λΈμ—μ„œ ν† ν”½ 할당이 잘λͺ» μΌμ–΄λ‚˜λ˜ 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* `tomotopy.Document` 및 `tomotopy.Dictionary` ν΄λž˜μŠ€μ— 가독성이 쒋은 __repr__κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.4.1 (2019-11-27)
* `tomotopy.PLDAModel` μƒμ„±μžμ˜ 버그λ₯Ό μˆ˜μ •ν–ˆμŠ΅λ‹ˆλ‹€.

* 0.4.0 (2019-11-18)
* `tomotopy.PLDAModel`와 `tomotopy.HLDAModel` ν† ν”½ λͺ¨λΈμ΄ μƒˆλ‘œ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.3.1 (2019-11-05)
* `min_cf` ν˜Ήμ€ `rm_top`κ°€ μ„€μ •λ˜μ—ˆμ„ λ•Œ `get_topic_dist()`의 λ°˜ν™˜κ°’μ΄ λΆ€μ •ν™•ν•œ 문제λ₯Ό μˆ˜μ •ν•˜μ˜€μŠ΅λ‹ˆλ‹€.
* `tomotopy.MGLDAModel` λͺ¨λΈμ˜ λ¬Έν—Œμ˜ `get_topic_dist()`κ°€ 지역 토픽에 λŒ€ν•œ 뢄포도 ν•¨κ»˜ λ°˜ν™˜ν•˜λ„λ‘ μˆ˜μ •ν•˜μ˜€μŠ΅λ‹ˆλ‹€..
* `tw=ONE`μΌλ•Œμ˜ ν•™μŠ΅ 속도가 κ°œμ„ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.3.0 (2019-10-06)
* `tomotopy.LLDAModel` ν† ν”½ λͺ¨λΈμ΄ μƒˆλ‘œ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `HDPModel`을 ν•™μŠ΅ν•  λ•Œ ν”„λ‘œκ·Έλž¨μ΄ μ’…λ£Œλ˜λŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
* `HDPModel`의 ν•˜μ΄νΌνŒŒλΌλ―Έν„° μΆ”μ • κΈ°λŠ₯이 μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이 λ•Œλ¬Έμ— μƒˆ λ²„μ „μ˜ `HDPModel` κ²°κ³ΌλŠ” 이전 버전과 λ‹€λ₯Ό 수 μžˆμŠ΅λ‹ˆλ‹€.
이전 λ²„μ „μ²˜λŸΌ ν•˜μ΄νΌνŒŒλΌλ―Έν„° 좔정을 끄렀면, `optim_interval`을 0으둜 μ„€μ •ν•˜μ‹­μ‹œμ˜€.

* 0.2.0 (2019-08-18)
* `tomotopy.CTModel`와 `tomotopy.SLDAModel` ν† ν”½ λͺ¨λΈμ΄ μƒˆλ‘œ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `rm_top` νŒŒλΌλ―Έν„° μ˜΅μ…˜μ΄ λͺ¨λ“  ν† ν”½ λͺ¨λΈμ— μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
* `PAModel`κ³Ό `HPAModel` λͺ¨λΈμ—μ„œ `save`와 `load`κ°€ μ œλŒ€λ‘œ μž‘λ™ν•˜μ§€ μ•ŠλŠ” 문제λ₯Ό ν•΄κ²°ν•˜μ˜€μŠ΅λ‹ˆλ‹€.
* `HDPModel` μΈμŠ€ν„΄μŠ€λ₯Ό νŒŒμΌλ‘œλΆ€ν„° λ‘œλ”©ν•  λ•Œ μ’…μ’… ν”„λ‘œκ·Έλž¨μ΄ μ’…λ£Œλ˜λŠ” 문제λ₯Ό ν•΄κ²°ν•˜μ˜€μŠ΅λ‹ˆλ‹€.
* `min_cf` > 0으둜 μ„€μ •ν•˜μ˜€μ„ λ•Œ `ll_per_word` 값이 잘λͺ» κ³„μ‚°λ˜λŠ” 문제λ₯Ό ν•΄κ²°ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

* 0.1.6 (2019-08-09)
* macOS와 clangμ—μ„œ μ œλŒ€λ‘œ μ»΄νŒŒμΌλ˜μ§€ μ•ŠλŠ” 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.

* 0.1.4 (2019-08-05)
* `add_doc` λ©”μ†Œλ“œκ°€ 빈 리슀트λ₯Ό λ°›μ•˜μ„ λ•Œ λ°œμƒν•˜λŠ” 문제λ₯Ό ν•΄κ²°ν•˜μ˜€μŠ΅λ‹ˆλ‹€.
* `tomotopy.PAModel.get_topic_words`κ°€ ν•˜μœ„ν† ν”½μ˜ 단어 뢄포λ₯Ό μ œλŒ€λ‘œ λ°˜ν™˜ν•˜μ§€ λͺ»ν•˜λŠ” 문제λ₯Ό ν•΄κ²°ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

* 0.1.3 (2019-05-19)
* `min_cf` νŒŒλΌλ―Έν„°μ™€ λΆˆμš©μ–΄ 제거 κΈ°λŠ₯이 λͺ¨λ“  ν† ν”½ λͺ¨λΈμ— μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

* 0.1.0 (2019-05-12)
* **tomotopy**의 졜초 버전

λ‹€λ₯Έ μ–Έμ–΄μš© 바인딩
-------------------
* Ruby: https://github.com/ankane/tomoto

ν¬ν•¨λœ λΌμ΄λΈŒλŸ¬λ¦¬λ“€μ˜ λΌμ΄μ„ΌμŠ€
-------------------------------
* Eigen:
This application uses the MPL2-licensed features of Eigen, a C++ template library for linear algebra.
A copy of the MPL2 license is available at https://www.mozilla.org/en-US/MPL/2.0/.
The source code of the Eigen library can be obtained at http://eigen.tuxfamily.org/.

* EigenRand: `MIT License
`_

* Mapbox Variant: `BSD License
`_