Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 基于两个准则的Numpy数组过滤_Python_Numpy_Cluster Analysis_K Means - Fatal编程技术网

Python 基于两个准则的Numpy数组过滤

Python 基于两个准则的Numpy数组过滤,python,numpy,cluster-analysis,k-means,Python,Numpy,Cluster Analysis,K Means,我正在尝试运行一个定制的kmeans聚类算法,但在按集群获取二维numpy数组中每列(项)的文档频率时遇到了问题。我当前的算法有两个numpy数组,一个是按术语[2000L,9500L]列出文档的原始数据集,另一个是集群分配[2000L,]。有5个集群。我需要做的是创建一个数组,列出每个集群的文档频率——基本上是每列中的计数,其中列号与不同数组中的行号匹配。输出将是一个[5L,9500L]阵列(集群x术语)。我很难找到一种方法来完成countif和group by的等效操作。以下是一些示例数据和

我正在尝试运行一个定制的kmeans聚类算法,但在按集群获取二维numpy数组中每列(项)的文档频率时遇到了问题。我当前的算法有两个numpy数组,一个是按术语[2000L,9500L]列出文档的原始数据集,另一个是集群分配[2000L,]。有5个集群。我需要做的是创建一个数组,列出每个集群的文档频率——基本上是每列中的计数,其中列号与不同数组中的行号匹配。输出将是一个[5L,9500L]阵列(集群x术语)。我很难找到一种方法来完成countif和group by的等效操作。以下是一些示例数据和如果仅使用2个集群运行时所需的输出:

import numpy as np

dataset = np.array[[1,2,0,3,0],[0,2,0,0,3],[4,5,2,3,0],[0,0,2,3,0]]
clusters = np.array[0,1,1,0]
#run code here to get documentFrequency
print documentFrequency
>> [1,1,1,2,0],[1,2,1,1,1]
我的想法是选择与每个集群匹配的特定行,因为这样计数应该很容易。例如,如果我可以将数据拆分为以下数组:

cluster0 = np.array[[1,2,0,3,0],[0,0,2,3,0]]
cluster1 = np.array[[0,2,0,0,3],[4,5,2,3,0]]

任何方向或指针将不胜感激

我不认为有任何简单的方法可以对代码进行矢量化,但如果只有几个集群,您可以做显而易见的事情:

>>> cluster_count = np.max(clusters)+1
>>> doc_freq = np.zeros((cluster_count, dataset.shape[1]), dtype=dataset.dtype)
>>> for j in xrange(cluster_count):
...     doc_freq[j] = np.sum(dataset[clusters == j], axis=0)
... 
>>> doc_freq
array([[1, 2, 2, 6, 0],
       [4, 7, 2, 3, 3]])

正如@Jaime所说,如果你只有几个集群,那么使用通常的技巧手动循环最小的轴长度是有意义的。通常情况下,这会让你获得完全矢量化的大部分好处,而不会因为聪明而头痛

这就是说,当您发现自己需要
groupby
时,您通常处于一个更高级别的工具非常方便的领域,例如:

>>> pd.DataFrame(dataset).groupby(clusters).sum()
   0  1  2  3  4
0  1  2  2  6  0
1  4  7  2  3  3
如果需要,您可以轻松地退回到
ndarray

>>> pd.DataFrame(dataset).groupby(clusters).sum().values
array([[1, 2, 2, 6, 0],
       [4, 7, 2, 3, 3]])

根据BLAS的编译程度,将其写成矩阵乘法可能会更快:

cvals = (clusters == np.arange(clusters.max()+1)[:,None]).astype(int)

cvals
array([[1, 0, 0, 1],
       [0, 1, 1, 0]])

np.dot(cvals,dataset)
array([[1, 2, 2, 6, 0],
       [4, 7, 2, 3, 3]])
让我们创建两个定义:

def loop(cvals,dataset):
     cluster_count = np.max(cvals)+1
     doc_freq = np.zeros((cluster_count, dataset.shape[1]), dtype=dataset.dtype)
     for j in xrange(cluster_count):
         doc_freq[j] = np.sum(dataset[cvals == j], axis=0)
     return doc_freq

def matrix_mult(clusters,dataset):
     cvals = (clusters == np.arange(clusters.max()+1)[:,None]).astype(dataset.dtype)
     return np.dot(cvals,dataset)
现在了解一些时间安排:

arr = np.random.random((2000,9500))
cluster = np.random.randint(0,5,(2000))

np.allclose(loop(cluster,arr),matrix_mult(cluster,arr))
True

%timeit loop(cluster,arr)
1 loops, best of 3: 263 ms per loop

%timeit matrix_mult(cluster,arr)
100 loops, best of 3: 14.1 ms per loop

注:这是一个螺纹mkl BLAS。您的口味会有所不同。

谢谢Jaime的建议-我会试试。@flyingmeatball这可能会引起您的兴趣。我已经编写了一个gufunc版本的
np.bincount
,请参阅。如果您可以编译并安装它(如果您的系统设置正确,那么运行
python setup.py install
应该可以做到这一点),然后您可以执行类似于
import new_gufuncs as ng;doc_freq=ng.bincount(clusters,dataset.T).T
,所有的循环都发生在C中。谢谢,我来看看Pandas——你可能是对的,如果它不适合,最好尝试另一种方法。