如何使用 Sklearn Kmeans 对稀疏数据进行聚类

Posted

技术标签:

【中文标题】如何使用 Sklearn Kmeans 对稀疏数据进行聚类【英文标题】:How to cluster sparse data using Sklearn Kmeans 【发布时间】:2017-10-05 08:06:38 【问题描述】:

如何使用 Sklearn 的 Kmeans 实现对稀疏数据进行聚类?

尝试根据我自己的用例调整他们的示例,我尝试了:

from sklearn.feature_extraction import DictVectorizer
from sklearn.cluster import KMeans

mydata = [
    (1, 'word1': 2, 'word3': 6, 'word7': 4),
    (2, 'word11': 1, 'word7': 9, 'word3': 2),
    (3, 'word5': 7, 'word1': 3, 'word9': 8),
]

kmeans_data = []
for index, raw_data in mydata:
    cnt_sum = float(sum(raw_data.values()))
    freqs = dict((k, v/cnt_sum) for k, v in raw_data.items())
    v = DictVectorizer(sparse=True)
    X = v.fit_transform(freqs)
    kmeans_data.append(X)

kmeans = KMeans(n_clusters=2, random_state=0).fit(kmeans_data)

但这会引发异常:

  File "/myproject/.env/lib/python3.5/site-packages/sklearn/cluster/k_means_.py", line 854, in _check_fit_data
    X = check_array(X, accept_sparse='csr', dtype=[np.float64, np.float32])
  File "/myproject/.env/lib/python3.5/site-packages/sklearn/utils/validation.py", line 382, in check_array
    array = np.array(array, dtype=dtype, order=order, copy=copy)
ValueError: setting an array element with a sequence.

大概我没有正确构建我的稀疏输入矩阵 X,因为它是一个稀疏矩阵列表,而不是一个包含列表的稀疏矩阵。如何构造合适的输入矩阵?

【问题讨论】:

【参考方案1】:

您正在逐步构建稀疏矩阵。我不确定您是否可以增量方式使用 DictVectorizer。将元素一个一个地添加到矩阵中会更简单。请参阅scipy.sparse.csr_matrixdocumentation 中的最后一个示例。

增量构建

考虑以下双循环:

data = []
rows = []
cols = []
vocabulary = 
for index, raw_data in mydata:
    cnt_sum = float(sum(raw_data.values()))
    for k,v in raw_data.items():
        f = v/cnt_sum
        i = vocabulary.setdefault(k,len(vocabulary))
        cols.append(i)
        rows.append(index-1)
        data.append(f)

kmeans_data = csr_matrix((data,(rows,cols)))

那么kmeans_data是一个稀疏矩阵,适合用作K-means分类器的输入。

直接构造

使用 DictVectorizer,您可以从元组列表中构造数据矩阵,然后使用稀疏线性代数例程执行行的归一化。

# 1. Construct the sparse matrix with numbers_of_occurrences
D = [d[1] for d in mydata]
v = DictVectorizer(sparse=True)
kmeans_data = v.fit_transform(D)
# 2. Normalize by computing sums for each row and dividing 
import numpy as np
sums = np.sum(kmeans_data,axis=1).A[:,0]
N = len(s)
divisor = csr_matrix((np.reciprocal(s),(range(N),range(N))))
kmeans_data = divisor*kmeans_data)

【讨论】:

以上是关于如何使用 Sklearn Kmeans 对稀疏数据进行聚类的主要内容,如果未能解决你的问题,请参考以下文章

Sklearn Pipeline:如何构建kmeans,聚类文本?

Sklearn.KMeans:如何避免内存或值错误?

如何使用 KMeans 进行距离聚类

如何在sklearn中打印聚类结果

使用 sklearn 对大型稀疏矩阵执行 PCA

使用 sklearn 同时使用数字和分类变量来拟合决策树