自然語言處理--向量之間點積看基於TruncatedSVD 的垃圾短訊息分類的效果
阿新 • • 發佈:2021-01-11
技術標籤:自然語言處理python機器學習nlp自然語言處理
要了解向量空間模型在分類方面的效果如何,一種方法是檢視類別內部向量之間的餘弦相似度與它們的類別歸屬之間的關係。
我們應該會看到,任何垃圾短訊息(“sms2!”)之間的正的餘弦相似度(點積)更大:
import pandas as pd
from nlpia.data.loaders import get_data
from sklearn.feature_extraction.text import TfidfVectorizer
from nltk.tokenize.casual import casual_tokenize
from sklearn.decomposition import TruncatedSVD
import numpy as np
# 從 nlpia 包中的 DataFrame 載入短訊息資料
pd.options.display.width = 120
sms = get_data('sms-spam')
# 向短訊息的索引號後面新增一個感嘆號,以使垃圾短訊息更容易被發現
index = ['sms{}{}'.format(i, '!'*j) for (i,j) in zip(range(len(sms)), sms.spam)]
sms.index = index
print(sms.head( 6))
# 計算每條訊息的 TF-IDF 向量
tfidf = TfidfVectorizer(tokenizer=casual_tokenize)
tfidf_docs = tfidf.fit_transform(raw_documents=sms.text).toarray()
# 來自分詞器(casual_tokenize)的 9232 個不同的1-gram 詞條
print(len(tfidf.vocabulary_))
tfidf_docs = pd.DataFrame(tfidf_docs)
# 減去平均值對向量化的文件(詞袋向量)進行中心化處理
tfidf_docs = tfidf_docs - tfidf_docs.mean()
# 4837 條短訊息
print(tfidf_docs.shape)
# 有 638 條(13%)被標記為垃圾短訊息
print(sms.spam.sum())
print("詞彙表:\n", tfidf.vocabulary_)
# svd
svd = TruncatedSVD(n_components=16, n_iter=100)
svd_topic_vectors = svd.fit_transform(tfidf_docs.values)
columns = ['topic{}'.format(i) for i in range(svd.n_components)]
svd_topic_vectors = pd.DataFrame(svd_topic_vectors, columns=columns, index=index)
# TruncatedSVD 的這些主題向量與 前面PCA 生成的主題向量完全相同!這個結果是因為我們非
# 常謹慎地使用了很多的迭代次數(n_iter),並且還確保每個詞項(列)的 TF-IDF 頻率都做了
# 基於零的中心化處理(通過減去每個詞項上的平均值)。
print(svd_topic_vectors.round(3).head(6))
# 計算前10 條短訊息對應的前 10個主題向量之間的點積,我們應該會看到,
# 任何垃圾短訊息(“sms2!”)之間的正的餘弦相似度(點積)更大。
svd_topic_vectors = (svd_topic_vectors.T / np.linalg.norm(svd_topic_vectors, axis=1)).T
print(svd_topic_vectors.iloc[:10].dot(svd_topic_vectors.iloc[:10].T).round(1))