Python 주제 분석


수강중

15. NMF 실습

전처리된 데이터 불러오기

import joblib
data = joblib.load('movie.pkl')
locals().update(data)

NMF 모형 생성

from sklearn.decomposition import NMF

NMFn_components: 문서 주제(특성 또는 성분)의 개수를 설정

random_state: 재현가능한 결과를 위해 임의의 숫자를 지정

nmf = NMF(n_components=20, random_state=1234)
nmf.fit(x_train)
NMF(alpha=0.0, beta_loss='frobenius', init=None, l1_ratio=0.0, max_iter=200,
    n_components=20, random_state=1234, shuffle=False, solver='cd', tol=0.0001,
    verbose=0)

차원 축소

테스트 데이터 x_testx_train과 동일하게 2,000차원이다.

x_test.shape
(6978, 2000)

테스트 데이터 x_text를 차원 축소한다.

doc_emb = nmf.transform(x_test)

20차원으로 축소되었습니다.

doc_emb.shape
(6978, 20)

0번째 문서의 주제를 확인한다.. 20개의 주제에 대한 값이 출력된다. 값이 클 수록 그 주제가 차지하는 비율이 크다.

doc_emb[0]
array([0.00410407, 0.        , 0.        , 0.        , 0.04713942,
       0.15739583, 0.        , 0.05560005, 0.        , 0.        ,
       0.        , 0.06405412, 0.00115137, 0.02936864, 0.        ,
       0.        , 0.        , 0.        , 0.        , 0.        ])

5번 주제의 값이 가장 크다.

doc_emb[0].argmax()
5

주제 보기

어떤 단어들이 각각의 주제와 관련되어 있는지 확인해본다. nmf.components_가 주제와 단어의 관계를 나타낸다. 이 행렬의 크기는 (20, 2000)로, 20개의 주제와 2,000개의 단어의 관계를 나타낸다.

nmf.components_.shape
(20, 2000)

편리하게 다루기 위해 판다스 데이터 프레임으로 변환한다.

import pandas as pd
loading = pd.DataFrame(nmf.components_.T)
loading['word'] = cv.get_feature_names()

5번 주제과 관련이 높은 단어를 확인한다. men, killed, group, escape, kill 등의 단어가 나온다.

i = 5
loading.sort_values(i, ascending=False).loc[:, [i, 'word']].head()
5 word
1151 4.746426 men
986 3.824056 killed
767 3.338384 group
589 3.267987 escape
985 3.257324 kill

오차 계산

inverse_transform을 하면 원래의 x_test와 비슷한 행렬을 복원할 수 있다.

x_recover = nmf.inverse_transform(doc_emb)

이것은 축소된 행렬로부터 복원되었기 때문에 x_test와 정확히 똑같지는 않다. NMF에서 오차는 프로베니우스 노름(Frobenius norm)으로 구한다. 복잡한 이름과 달리 실제로는 모든 원소들끼리 차이를 구해서, 그 차이를 모두 제곱하여 더한 것이다. 구하는 방법은 아래와 같다. 오차는 작을 수록 더 잘 복원된 것이다.

import numpy as np

np.linalg.norm(x_recover - x_test)
1412.176610674724