【问题标题】:"could not convert integer scalar" error when using DBSCAN使用 DBSCAN 时出现“无法转换整数标量”错误
【发布时间】:2017-07-21 10:52:25
【问题描述】:

我正在尝试使用 scikit-learn 的 DBSCAN 实现来聚类一堆文档。首先,我使用 scikit-learn 的 TfidfVectorizer 创建 TF-IDF 矩阵(它是一个 163405x13029 类型的 numpy.float64 稀疏矩阵)。然后我尝试对这个矩阵的特定子集进行聚类。当子集很小(例如,多达几千行)时,一切正常。但是对于大型子集(具有数万行),我得到ValueError: could not convert integer scalar

这是完整的回溯(idxs 是索引列表):


ValueError                        Traceback (most recent call last)
<ipython-input-1-73ee366d8de5> in <module>()
    193     # use descriptions to clusterize items
    194     ncm_clusterizer = DBSCAN()
--> 195     ncm_clusterizer.fit_predict(tfidf[idxs])
    196     idxs_clusters = list(zip(idxs, ncm_clusterizer.labels_))
    197     for e in idxs_clusters:

/usr/local/lib/python3.4/site-packages/sklearn/cluster/dbscan_.py in fit_predict(self, X, y, sample_weight)
    294             cluster labels
    295         """
--> 296         self.fit(X, sample_weight=sample_weight)
    297         return self.labels_

/usr/local/lib/python3.4/site-packages/sklearn/cluster/dbscan_.py in fit(self, X, y, sample_weight)
    264         X = check_array(X, accept_sparse='csr')
    265         clust = dbscan(X, sample_weight=sample_weight,
--> 266                        **self.get_params())
    267         self.core_sample_indices_, self.labels_ = clust
    268         if len(self.core_sample_indices_):

/usr/local/lib/python3.4/site-packages/sklearn/cluster/dbscan_.py in dbscan(X, eps, min_samples, metric, algorithm, leaf_size, p, sample_weight, n_jobs)
    136         # This has worst case O(n^2) memory complexity
    137         neighborhoods = neighbors_model.radius_neighbors(X, eps,
--> 138                                                          return_distance=False)
    139 
    140     if sample_weight is None:

/usr/local/lib/python3.4/site-packages/sklearn/neighbors/base.py in radius_neighbors(self, X, radius, return_distance)
    584             if self.effective_metric_ == 'euclidean':
    585                 dist = pairwise_distances(X, self._fit_X, 'euclidean',
--> 586                                           n_jobs=self.n_jobs, squared=True)
    587                 radius *= radius
    588             else:

/usr/local/lib/python3.4/site-packages/sklearn/metrics/pairwise.py in pairwise_distances(X, Y, metric, n_jobs, **kwds)
   1238         func = partial(distance.cdist, metric=metric, **kwds)
   1239 
-> 1240     return _parallel_pairwise(X, Y, func, n_jobs, **kwds)
   1241 
   1242 

/usr/local/lib/python3.4/site-packages/sklearn/metrics/pairwise.py in _parallel_pairwise(X, Y, func, n_jobs, **kwds)
   1081     if n_jobs == 1:
   1082         # Special case to avoid picklability checks in delayed
-> 1083         return func(X, Y, **kwds)
   1084 
   1085     # TODO: in some cases, backend='threading' may be appropriate

/usr/local/lib/python3.4/site-packages/sklearn/metrics/pairwise.py in euclidean_distances(X, Y, Y_norm_squared, squared, X_norm_squared)
    243         YY = row_norms(Y, squared=True)[np.newaxis, :]
    244 
--> 245     distances = safe_sparse_dot(X, Y.T, dense_output=True)
    246     distances *= -2
    247     distances += XX

/usr/local/lib/python3.4/site-packages/sklearn/utils/extmath.py in safe_sparse_dot(a, b, dense_output)
    184         ret = a * b
    185         if dense_output and hasattr(ret, "toarray"):
--> 186             ret = ret.toarray()
    187         return ret
    188     else:

/usr/local/lib/python3.4/site-packages/scipy/sparse/compressed.py in toarray(self, order, out)
    918     def toarray(self, order=None, out=None):
    919         """See the docstring for `spmatrix.toarray`."""
--> 920         return self.tocoo(copy=False).toarray(order=order, out=out)
    921 
    922     ##############################################################

/usr/local/lib/python3.4/site-packages/scipy/sparse/coo.py in toarray(self, order, out)
    256         M,N = self.shape
    257         coo_todense(M, N, self.nnz, self.row, self.col, self.data,
--> 258                     B.ravel('A'), fortran)
    259         return B
    260 

ValueError: could not convert integer scalar

我正在使用 Python 3.4.3(在 Red Hat 上)、scipy 0.18.1 和 scikit-learn 0.18.1。

我尝试了建议的猴子补丁here,但没有奏效。

四处搜索我发现了一个bugfix,它显然解决了其他类型的稀疏矩阵(如 csr)的相同问题,但不适用于 coo。

按照here 的建议,我尝试为 DBSCAN 提供一个稀疏半径邻域图(而不是特征矩阵),但同样的错误发生了。

我试过HDBSCAN,但同样的错误发生了。

我该如何解决或绕过这个问题?

【问题讨论】:

  • fit_predict(tfidf[idxs]) 中的 idxs 是什么。您是否仅使用 tfidf 中的一些值?
  • idxs 索引列表(是的,我只使用了 tfidf 中的一些值 - 它总共有 ~163k 个文档,但我只使用了 ~107k 个)跨度>
  • 你试过更新 scipy 和 scikit 版本吗?
  • 它们都是最新的 (v0.18.1)。
  • 什么是tfidf?打印type(tfidf)tfidf.shape

标签: python scipy scikit-learn dbscan


【解决方案1】:

即使实现允许,DBSCAN 也可能会在如此高维度的数据上产生不好的结果(从统计的角度来看,因为维度的诅咒)。

相反,我建议您使用 TruncatedSVD 类将 TF-IDF 特征向量的维数减少到 50 或 100 个分量,然后将 DBSCAN 应用于结果。

【讨论】:

    猜你喜欢
    • 2015-05-23
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    • 2013-06-25
    • 1970-01-01
    • 2018-11-16
    相关资源
    最近更新 更多