본문 바로가기
Python Tips

CountVectorizer + pyLDAvis (N-gram LDA)

by suminhan 2020. 6. 10.

dictionary = gensim.corpora.Dictionary()
dictionary.token2id = dict((word, uid) for word, uid in vect.vocabulary_.items())

pyLDAvis를 써서 위와 같이 시각화를 하고싶은데 bigram같은 feature를 뽑고싶은경우가 있을 것이다.

sklearn의 CountVectorizer를 쓰면 가능하지만, 이것을 gensim의 라이브러리를 써서 pyLDAvis로 어떻게 변환하는지에 대한 글이 없길래 써본다.

 

우선 아래의 라이브러리를 import한다.

from sklearn.feature_extraction.text import CountVectorizer
from gensim.models import LdaModel
import pyLDAvis.gensim
import scipy

일단 corpus를 string으로 이루어진 list로 만든다. (아래는 예시)

docs = ['요즘 중단 발 이 대세라면서요',
 '수요일 에 수업 없다 ..',
 '바나나 에서 벗어난 밤 서비스 많이 주셨으니깐 낮 과 밤 이대 맛집 공감 가는 사람 들 과 만나는건 항상 좋다',
 '회사 가 용서 되는 시간 ... ㅂㄷㅂㄷ 살이 쭉쭉쭉 플라잉 요가']

이후 CountVectorizer를 써서 원하는 파라미터를 넣고 vector transform을 한다.

stopwords = ['__', '___', 'all']
vect = CountVectorizer(ngram_range=(1, 2), max_features=3000, stop_words=stopwords)
corpus_vect = vect.fit_transform(docs)

이제 여기서 관건인데 gensim의 LDA모델이 받는 corpus의 형태가 있다. [[(1, 3), (2, 4)], ...] 이런 식으로 어떤 단어의 index와 해당 count를 집어넣어 주어야 한다.

위의 corpus_vect는 CSR형태의 sparse matrix이므로 row단위로 끊어서 input을 받아주어야 한다. CSR 공부를 더 하면 코딩하는 방법이 또 다를수 있는데, 귀찮아서 찾아보다가 COO matrix로 하는방법이 편해보여서 이를 이용하여 변환해보았다.

cx = scipy.sparse.coo_matrix(corpus_vect)
corpus = [[] for i in range(len(docs))]
for i, j, v in zip(cx.row, cx.col, cx.data):
    corpus[i].append((j, v))

이렇게 해주면 각 row에 위에서 말한 형태로 변환된다.

그리고 gensim dictionary를 따로 만든다.

dictionary = gensim.corpora.Dictionary()
dictionary.token2id = dict((word, uid) for word, uid in vect.vocabulary_.items())

이제 아래와같이 LDA모델을 만들고 pyLDAvis로 시각화하면된다.

lda = LdaModel(corpus, id2word=dict((id, word) for word, id in vect.vocabulary_.items()))
vis = pyLDAvis.gensim.prepare(lda, corpus_vect_gensim, dictionary)
pyLDAvis.display(vis)

댓글