===
PCA
===
scikit-learn์ PCA๋ชจํ์ ๋ฌธ์ ๋ฉ์์ง๋ค์ ์ ์ฉ
import pandas as pd
from nlpia.data.loaders import get_data
sms = get_data("sms-spam")
sms.head()
index = ['sms{}{}'.format(i,'!'*j)
for (i,j) in zip(range(len(sms)), sms.spam)]
sms.index = index
# ๊ฐ ๋ฉ์์ง์ TF-IDF ๋ฒกํฐ๋ฅผ ๊ณ์ฐ
from sklearn.feature_extraction.text import TfidfVectorizer
from nltk.tokenize.casual import casual_tokenize
tfidf = TfidfVectorizer(tokenizer=casual_tokenize)
tfidf_docs = tfidf.fit_transform(raw_documents=sms.text).toarray()
len(tfidf.vocabulary_)
tfidf_docs = pd.DataFrame(tfidf_docs)
tfidf_docs = tfidf_docs - tfidf_docs.mean() # ํ๊ท ์ ๋ปฌ์ ๋ฌธ์์ ๋ฒกํฐ ํํ๋ค์ ์ค์ฌํํ๋ค.
tfidf_docs.shape
from sklearn.decomposition import PCA
pca = PCA(n_components=16)
pca.fit(tfidf_docs)
pca_topic_vectors = pca.transform(tfidf_docs)
columns = ['topic{}'.format(i) for i in range(pca.n_components)]
pca_topic_vectors = pd.DataFrame(pca_topic_vectors,columns=columns,index=index)
pca_topic_vectors.round(3).head(6)
# topic0 topic1 topic2 topic3 ... topic12 topic13 topic14 topic15
# sms0 0.201 0.003 0.037 0.011 ... 0.006 -0.034 -0.016 0.023
# sms1 0.404 -0.094 -0.078 0.051 ... 0.042 -0.019 0.047 -0.045
# sms2! -0.030 -0.048 0.090 -0.067 ... 0.020 -0.023 -0.040 0.046
# sms3 0.329 -0.033 -0.035 -0.016 ... 0.072 -0.038 0.017 -0.061
# sms4 0.002 0.031 0.038 0.034 ... 0.028 0.037 -0.086 -0.031
# sms5! -0.016 0.059 0.014 -0.006 ... -0.033 0.066 0.002 0.028
spam ๋ถ๋ฅ ๋ฉ์์ง PCA ๋ถ์์ ์งํํ๋ค.
pca_topic_vectors๋ ๊ฐ ์ฃผ์ ์ ๋จ์ด๊ฐ ์ผ๋ง๋ "๋ด๊ฒจ ์๋์ง"๋ฅผ ๋ณด๋ฉด ์ฆ ๊ทธ ์ฃผ์ ์ ๋ํ ๊ฐ ๋จ์ด์ ๊ฐ์ค์น๋ฅผ ๋ณด๋ฉด ์ง์ํ ์์๋ค.
PCA ๋ณํ์ ๋ชจ๋ ์ฐจ์์ ๋จ์ด๋ค์ ๋ฐฐ์
tfidf.vocabulary_
# {'go': 3807,
# 'until': 8487,
# 'jurong': 4675,
# 'point': 6296,
# ',': 13,
# 'crazy': 2549,
# '..': 21,
# 'available': 1531,
# 'only': 5}
์ดํ์ ๋จ์ด๋ค์ ๋น๋ ์์ผ๋ก ์ ๋ ฌ
columns_nums, terms = zip(*sorted(zip(tfidf.vocabulary_.values(),tfidf.vocabulary_.keys())))
terms[:5]
#terms[:5] ('!', '"', '#', '#150', '#5000')
๊ฐ ์ฃผ์ ๊ฐ ์ค์ ๋ก ๋ฌด์์ ๊ดํ ๊ฒ์ธ์ง ๊ฐ์ค์น๋ฅผ ๋ด์ผํ๋ค.
์คํธ์ ํด๋น ํ ๊ฑฐ๊ฐ์ ๋จ์ด๋ค์ ์ถ์ถํด ๋ณด์๋ค.
weights = pd.DataFrame(pca.components_,columns=terms,index=['topic{}'.format(i) for i in range(pca.n_components)])
pd.options.display.max_columns = 12
weights.head(4).round(3)
deals = weights['! ;) :) half off free crazy deal only $ 80 %'.split()].round(3)*100
deals
# ! ;) :) half off free crazy deal only $ 80 %
# topic0 -7.1 0.1 -0.5 -0.0 -0.4 -2.0 -0.0 -0.1 -2.2 0.3 -0.0 -0.0
# topic1 6.3 0.0 7.4 0.1 0.4 -2.3 -0.2 -0.1 -3.8 -0.1 -0.0 -0.2
# topic2 7.1 0.2 -0.1 0.0 0.3 4.4 0.1 -0.1 0.7 0.0 0.0 0.1
# topic3 -5.9 -0.3 -7.1 0.2 0.3 -0.2 0.0 0.1 -2.3 0.1 -0.1 -0.3
# topic4 38.1 -0.1 -12.5 -0.1 -0.2 9.9 0.1 -0.2 3.0 0.3 0.1 -0.1
# topic5 -26.5 0.1 -1.6 -0.3 -0.7 -1.3 -0.6 -0.2 -1.8 -0.9 0.0 0.0
# topic6 -10.9 -0.5 19.9 -0.4 -0.9 -0.6 -0.2 -0.1 -1.4 -0.0 -0.0 -0.1
# topic7 16.1 0.1 -18.0 0.8 0.8 -2.9 0.0 0.1 -1.8 -0.3 0.0 -0.1
# topic8 34.2 0.1 5.0 -0.5 -0.5 -0.3 -0.4 -0.4 3.4 -0.6 -0.0 -0.2
# topic9 7.2 -0.3 16.6 1.4 -0.9 6.2 -0.5 -0.4 3.1 -0.4 -0.0 0.0
# topic10 -32.3 -0.2 -10.0 0.1 0.1 12.8 0.1 -0.0 0.5 -0.0 -0.0 -0.2
# topic11 21.5 0.4 31.8 0.4 1.5 -4.1 0.0 0.1 -0.1 -0.4 -0.0 -0.3
# topic12 -23.5 -0.2 39.2 -0.3 0.1 -4.0 -0.5 0.1 3.6 0.3 -0.0 0.3
# topic13 11.8 -0.3 29.1 -0.4 0.5 4.9 0.4 0.1 -1.7 -0.4 0.0 -0.2
# topic14 -0.5 -0.1 13.9 -0.1 -1.0 5.1 0.1 -0.1 3.9 -0.0 0.0 -0.5
# topic15 6.6 -0.5 1.0 -0.5 -1.4 -5.1 -0.8 0.5 0.3 -0.5 0.1 0.0
๊ฐ์ค์น๋ฅผ ํฉํด์ ์ฃผ์ ๋ณ ๊ฐ์ฅ ๋์ ์์น๋ฅผ ํ์ธ
deals์ ์ ์ฌํ ์ฃผ์ ๋ 4, 8, 9์์ ์ ์ ์๋ค. 0, 3, 5 ๋ deals์ ์๋ฐ๋ ์๋ฏธ์์ ๊ฐ์ค์น๋ฅผ ํตํด ์ ์ ์๋ค.
deals.T.sum()
# topic0 -11.9
# topic1 7.5
# topic2 12.7
# topic3 -15.5
# topic4 38.3
# topic5 -33.8
# topic6 4.8
# topic7 -5.2
# topic8 39.8
# topic9 32.0
# topic10 -29.1
# topic11 50.8
# topic12 15.1
# topic13 43.8
# topic14 20.7
# topic15 -0.3
# dtype: float64
์ด ์ฒ๋ผ ์ฐจ์์ด ์๋ฏธํ๋ ๊ฒ์ ์๋ ๊ฒ์ ์ด๋ ต๋ค. LSA์ ๋จ์ ์ค ํ๋์ด๋ค. LSA๋ ๋จ์ด๋ค ์ฌ์ด์ ์ผ์ฐจ ๊ด๊ณ๋ง ํ์ฉํ๋ค.๋ํ ์ฌ๋์ด ์๋ฏธ๋ฅผ ํ์ ํ๊ธฐ ์ด๋ ค์ด ๋จ์ด ์กฐํฉ๋ค๋ ๋ง์ด ๋์จ๋ค. PCA๋ ๋จ์ด ๋น๋๋ค์ ๋ถ์ฐ์ด ๊ฐ์ฅ ์ปค์ง๋ ์กฐํฉ์ ์ฐพ์๋ฟ์ด๋ค. ๋ฐ๋ผ์ ์ฌ๋์ด ๋ณด๊ธฐ์๋ ์ ํ ๋ค๋ฅธ ์ฃผ์ ์ ์ฌ๋ฌ ๋จ์ด๊ฐ ํ๋์ ์ฐจ์์ผ๋ก ํฉ์ณ์ง๋ ์ผ์ด ๋ฐ์ํ๋ค.
===
SVD
===
scikit-learn์ TruncatedSVD ๋ชจํ์ LSA์ ๋ํ ์ข ๋ ์ง์ ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ด๋ค. ์ด ๋ชจํ์์๋ scikit-learn PCA ๋ชจํ์ด ์จ๊ฒผ๋ ์ธ๋ถ ์ฌํญ์ ์ด๋ ์ ๋ ์ง์ ์ดํด ๋ณผ ์ ์๋ค. ์๋ฃ ๋ชจํ์ด ํด ๊ฒฝ์ฐ์๋ TruncatedSVD ๋์ PCA๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋น ๋ฅด๋ค. Truncated์ SVD๋ถ๋ถ์ TF-IDF ํ๋ ฌ์ ์ธ ๊ฐ์ ํ๋ ฌ๋ก ๋ถํ ํ๋ค. TF-IDF ํ๋ ฌ์ ๊ดํ ์ ๋ณด๊ฐ ์ ์ ์ฐจ์๋ค์ ํ๊ธฐํ๋ค. ํ๊ธฐ๋ ์ฐจ์๋ค์ ๋ง๋ญ์น์ ๋ฌธ์๋ค ์ ์ฒด์์ ๊ทธ ๋ถ์ฐ์ด ์์ '์ฃผ์ '์ ํด๋นํ๋ค. ์ด๋ฐ ์ฐจ์์ ์๋ฏธ์ ํฐ ์์ฉํ์ง ์๋๋ค. ์ด๋ฐ ์ฃผ์ ๋ค์ ๋ฌธ์์์ ์์๊ฐ ์๋ ๋จ์ด๋ค์ด๋ค. ๋ถ์ฉ์ด, ์กฐ์ฌ ๋ฑ์ด ํด๋น๋๋ค.
from sklearn.decomposition import TruncatedSVD
svd = TruncatedSVD(n_components=16,n_iter=100)
svd_topic_vectors = svd.fit_transform(tfidf_docs.values)
svd_topic_vectors = pd.DataFrame(svd_topic_vectors,columns=columns,index=index)
svd_topic_vectors.round(3).head(3)
# topic0 topic1 topic2 topic3 topic4 topic5 ... topic10 topic11 topic12 topic13 topic14 topic15
# sms0 0.201 0.003 0.037 0.011 -0.019 -0.053 ... 0.007 -0.007 0.002 -0.036 -0.014 0.037
# sms1 0.404 -0.094 -0.078 0.051 0.100 0.047 ... -0.004 0.036 0.043 -0.021 0.051 -0.042
# sms2! -0.030 -0.048 0.090 -0.067 0.091 -0.043 ... 0.125 0.023 0.026 -0.020 -0.042 0.052
# TruncatedSVD๊ฐ ์ฐ์ถํ ์ฃผ์ ๋ฒกํฐ๋ค์ด PCA๋ชจํ์ด ์ฐ์ถํ ๊ฒ๋ค๊ณผ ์ ํํ ์ผ์นํ๋ค. n_iter๋ฅผ ๊ธฐ๋ณธ๋ณด๋ค ํจ์ฌ ํฌ๊ฒ ์ก์๊ณ ๊ฐ ๋จ์ด์ TF-IDF ๋น๋๋ค์ 0์ ๋ํด ์ค์ฌํํ ๋๋ถ์ด๋ค.
PCA์ ๊ฒฝ์ฐ์ฒ๋ผ ๊ฐ ์ฃผ์ ์ ์๋ฏธ๋ฅผ ์๋ ค๋ฉด ๋จ์ด ๊ฐ์ค์น๋ค์ ์ดํด๋ด์ผํ๋ค. sms! ๋๋ํ๊ฐ ์คํธ ๋ฉ์ผ ๊ตฌ๋ถ์์ด๋ค. ํด๋น ์ด์ ์ ์๊ฐ ๊ฐ์ฅ ๋์ ๊ฒ์ ๋ณด๋ฉด topic11์ ๋ํ pca์ฐจ์์ด ์คํธ ๋ฉ์ผ์ ๊ตฌ๋ถ ์ง๋ ๋จ์ด์ ์ฃผ์ ์ผ ํ๋ฅ ์ด ํฌ๋ค. ์ด ์ฃผ์ ๋ฅผ ๋น๊ตํ๋ฉด ์คํธ์ธ์ง ์๋ ์ง๋ฅผ ์ ์ ์๋ค.
* ์คํธ ๋ถ๋ฅ์ ๋ํ LSA์ ์ ํ๋
import numpy as np
svd_topic_vectors = (svd_topic_vectors.T/np.linalg.norm(svd_topic_vectors,axis=1)).T
svd_topic_vectors.iloc[:10].dot(svd_topic_vectors.iloc[:10].T).round(1)
# sms0 sms1 sms2! sms3 sms4 sms5! sms6 sms7 sms8! sms9!
# sms0 1.0 0.6 -0.1 0.6 -0.0 -0.3 -0.3 -0.1 -0.3 -0.3
# sms1 0.6 1.0 -0.2 0.8 -0.2 0.0 -0.2 -0.2 -0.1 -0.1
# sms2! -0.1 -0.2 1.0 -0.2 0.1 0.4 0.0 0.3 0.5 0.4
# sms3 0.6 0.8 -0.2 1.0 -0.2 -0.3 -0.1 -0.3 -0.2 -0.1
# sms4 -0.0 -0.2 0.1 -0.2 1.0 0.2 0.0 0.1 -0.4 -0.2
# sms5! -0.3 0.0 0.4 -0.3 0.2 1.0 -0.1 0.1 0.3 0.4
# sms6 -0.3 -0.2 0.0 -0.1 0.0 -0.1 1.0 0.1 -0.2 -0.2
# sms7 -0.1 -0.2 0.3 -0.3 0.1 0.1 0.1 1.0 0.1 0.4
# sms8! -0.3 -0.1 0.5 -0.2 -0.4 0.3 -0.2 0.1 1.0 0.3
# sms9! -0.3 -0.1 0.4 -0.1 -0.2 0.4 -0.2 0.4 0.3 1.0
svd_topic_vectors์ ์ฝ์ฌ์ธ ์ ์ฌ๋๋ฅผ ๋ณด๋ฉด sms0์ธ ์ ์ ๋ฉ์ผ์ ๋ณด๋ฉด sms 2 5 6 8 9์ ๊ฑฐ๋ฆฌ๊ฐ ๋จผ ๊ฒ์ผ๋ก ์คํธ ๋ฉ์ผ๊ณผ ๋ค๋ฅด๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
* Cosine similarity : ์ฃผ์ ๋ฒกํฐ์ ํด๋น ๋ฒกํฐ์์ ๊ด๊ณ๋ฅผ ๋ฒกํฐ์์ ์ค์นผ๋ผ ๊ฐ์ผ๋ก ์๋ ค์ค๋ค.
Heatmap
svd_topic_vectors_heatmap = svd_topic_vectors.iloc[:10].dot(svd_topic_vectors.iloc[:10].T).round(1)
import seaborn as sns
sns.heatmap(svd_topic_vectors_heatmap,cmap='YlGnBu')
๋ค๋ง ์์ ์ ์ฌ๋๋ฅผ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด ์คํธ์ฑ์๋ ๋ฉ์ผ์ ํ๋๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ค๋ฅธ ์คํธ์ ๋ถ๋ฅํ๊ธฐ์๋ ์ค๋ฅ๊ฐ ์๋ค. ex) sms9! - sms7
์ด๋ฌํ ๋ฐฉ์์ผ๋ก ๋ถ๋ฅ ๊ธฐ์ค์ ๊ธฐ๊ณ๊ฐ ํ์ต์ ํ๊ฒ ํ๋ค๋ฉด ์คํธ๊ณผ ๋น์คํธ ๋ฉ์ผ์ ๊ฒฝ๊ณ์ ์ ์ ์ ์์ ๊ฒ์ด๋ค.
์ ๋จ๋ SVD๋ฅผ ์ฌ์ฉํ ๋๋ ์ฃผ์ ๋ฒกํฐ๋ค์ ๊ณ์ฐํ๊ธฐ์ ์์ ํน์๊ฐ๋ค์ ํ๊ธฐํ ํ์๊ฐ ์๋ค.
- ๋ฐฉ๋ฒ 1: TF-IDF ๋ฒกํฐ๋ค์ ํด๋น ๊ธธ์ด(L2-norm)์ผ๋ก ์ ๊ทํ
- ๋ฐฉ๋ฒ 2: ๊ฐ TF-IDF ์ฉ์ด ๋น๋์์ ํ๊ท ๋น๋๋ฅผ ๋นผ์ ๋น๋๋ค์ ์ค์ฌํ
SVD๋ TF-IDF ๋ฒกํฐ๋ค์ ๋ณํํ๋ ํ๋ ฌ์ ํ์ ์ฑ๋ถ๋ค๋ง ์ฒ๋ฆฌํ๊ฒ ๋๋ค. ์ด์ฒ๋ผ ๊ณ ์ณ๊ฐ(eigenvalue)๋ค์ ๋ฌด์ํ๋ ๊ฒ์ ์ฃผ์ ๋ฒกํฐ ๊ณต๊ฐ์ ๊ฒฝ๊ณ ์ง๋ ์ด์ ๋ฐฉ์ฒด(hypercube)๋ฅผ "๋ฐ๋ก ์ธ์ฐ๋(square up)" ๊ฒ์ ํด๋นํ๋ค. scikit-learn์ PCA๊ตฌํ์ ์๋ฃ๋ฅผ '์ค์ฌํ','๋ฐฑํ'ํจ์ผ๋ก์จ ์ ๊ทํ๋ฅผ ์ํํ๋ค.
############
LSA์ LSD ๊ฐ์
############
์๋ฏธ ๋ถ์๊ณผ ์ฐจ์ ์ถ์์ ํน์๊ฐ ๋ถํด๊ฐ ์ ์ฉํ๋ค๋ ์ ์ด ๋ฐํ์ง๋ฉด์ ์ฐ๊ตฌ์๋ค์ ํน์๊ฐ ๋ถํด ์๊ณ ๋ฆฌ์ฆ์ ๋์ฑ ํ์ฅํ๊ณ ๊ฐ์ ํ๋ค.
์๋ฏธ ๋ถ์ ํ์ดํ๋ผ์ธ ๊ฐ์ ์
- ์ด์ฐจ ํ๋ณ ๋ถ์(quadratic discriminant analysis, QDA)
- ๋ฌด์์ ํฌ์(random projection)
- ๋น์์ ํ๋ ฌ ์ธ์๋ถํด(nonnegative matrix factorization, NFM; ๋๋ ์์ ๋ฏธํฌํจ ํ๋ ฌ ๋ถํด)
QDA๋ LDA์ ํ ๋์์ด๋ค. QDA๋ ์ ํ ๋ณํ์ด ์๋๋ผ ์ด์ฐจ ๋คํญ์ ๋ณํ ํ๋ ฌ์ ์ฐ์ถํ๋ค. ์ด ๋ณํ ํ๋ ฌ์ด ์ ์ํ๋ ๋ฒกํฐ ๊ณต๊ฐ์ ์ด์ฉํด์ ๋ฒกํฐ๋ค์ ์ฌ๋ฌ ๋ถ๋ฅ๋ก ๋๋๋ค.
๋ฌด์์ ํฌ์์ SVD์ ๋น์ทํ ํ๋ ฌ ๋ถํด ๋ฐ ๋ณํ ์ ๊ทผ ๋ฐฉ์์ด์ง๋ง, ์๊ณ ๋ฆฌ์ฆ์ด ํ๋ฅ ์ ์ด๊ธฐ ๋๋ฌธ์ ์คํํ ๋๋ง๋ค ๋ค๋ฅธ ํด๋ต์ด ๋์จ๋ค. ๊ทธ๋ ์ง๋ง ์ด๋ฐ ํ๋ฅ ์ ์ฑ๊ฒฉ ๋๋ถ์ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ๋ฌ ๋์ ์ปดํจํฐ์์ ๋ณ๋ ฌ๋ก ์ํํ๊ธฐ๊ฐ ์ฝ๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ์๊ณ ๋ฆฌ์ฆ์ ์ฌ๋ฌ ๋ฒ ์คํํ๋ฉด SVD์ ๊ฒฐ๊ณผ๋ณด๋ค ๋์ ๊ฒฐ๊ณผ๊ฐ ๋์ค๊ธฐ๋ ํ๋ค. ๊ทธ๋ฌ๋ NLP๋ฌธ์ ์๋ ๋ฌด์์ ํฌ์์ ๊ฑฐ์ ์์ด๋ค. ๊ทธ๋์ ํจํค์ง๊ฐ ์ ์ด ๊ตฌํ์ ์ฌ์ฉ์๊ฐ ์ง์ ํด์ผํ๋ค.
๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ด๋ฐ ๊ฐ์ ์๋ค๋ณด๋ค๋ ํจ๊ณผ๊ฐ ์ด๋ฏธ ๊ฒ์ฆ๋ SVD์๊ณ ๋ฆฌ์ฆ์ ๊ธฐ์ดํ LSA๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ซ๋ค.
'๐ฃ๏ธ Natural Language Processing' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
MaLSTM (0) | 2021.02.13 |
---|---|
[Kaggle] ๋ค์ด๋ฒ ์ํ ๋ฆฌ๋ทฐ ๋ถ๋ฅ(1) (0) | 2021.02.12 |
CNN ํ ์คํธ ์ ์ฌ๋ ๋ถ์(Feat. Quora pairs) (0) | 2021.02.10 |
KoNLPy ์ข ๋ฅ (0) | 2021.02.06 |
SVD(singular value decomposition) VS SVM(support vector machine) (0) | 2021.02.05 |