TL;博士
简短回答:不,将签名矩阵用于 K 均值聚类没有意义。至少,并非没有重大操纵。
一些解释
在弄清楚如何自己做同样的事情(文本聚类)几天后,我来了。我可能错了,但我的看法是你犯了同样的错误:使用 MinHash 构建[n_samples x n_perms]
矩阵,然后将其用作X
运行 k-means 的特征矩阵。
我猜你正在做类似的事情:
# THIS CODE IS AN EXAMPLE OF WRONG! DON'T IMPLEMENT!
import numpy as np
import MinHash
from sklearn.cluster import KMeans
# Get your data.
data = get_your_list_of_strings_to_cluster()
n_samples = len(data)
# Minhash all the strings
n_perms = 128
minhash_values = np.zeros((n_samples, n_perms), dtype='uint64')
minhashes = []
for index, string in enumerate(data):
minhash = MinHash(num_perm=n_perms)
for gram in ngrams(string, 3):
minhash.update("".join(gram).encode('utf-8'))
minhash_values[index, :] = minhash.hashvalues
# Compute clusters
clusterer = KMeans(n_clusters=8)
clusters = clusterer.fit_predict(minhash_values)
由于致命的缺陷,这将表现得非常糟糕minhash_values
——数组不是特征矩阵。每一行基本上都是出现在该文本样本中的特征(散列)列表......但它们不是列对齐的,因此特征分散到错误的维度中。
要将其转换为特征矩阵,您必须查看其中的所有唯一哈希,minhash_values
然后创建一个矩阵,即[n_samples x n_unique_hashes]
,(n_unique_hashes
是找到的唯一特征的数量)将其设置为1
文本样本在其他地方包含该特征的位置0
。通常这个矩阵会很大而且很稀疏。然后你可以聚集在那个上面。
文本聚类的替代方法
多么令人难以置信的麻烦!幸运的是,scikit-learn
有帮助。它提供了一些非常易于使用和可扩展的矢量化器:
所以你的问题很容易解决:
# Imports
from sklearn.feature_extraction.text import HashingVectorizer
from sklearn.cluster import KMeans
# Get your data
data = get_your_list_of_strings_to_cluster()
# Get your feature matrix
text_features = HashingVectorizer(analyzer="word").fit_transform(data)
# Compute clusters
clusterer = KMeans(n_clusters=2)
clusters = clusterer.fit_predict(text_features)
你去吧。从那里:
- 微调你的矢量化器(也尝试 TfidfVectorizer,调整输入参数等),
- 尝试其他集群(f/ex 我发现
HDBSCAN 英里比 kmeans 更好——更快、更健壮、更准确、更少调整)。
希望这可以帮助。
汤姆