在scipy中无需替换即可生成缓慢的随机样本

时间:2017-06-11 07:27:31

标签: python random scipy hashmap sparse-matrix

我正在尝试创建随机哈希映射h的稀疏矩阵表示:[n] - > [t]映射每个i      确切地说是可用d个位置的随机位置,并且这些位置的值是从一些离散分布中得出的。

:param d: number of bins
:param n: number of items hashed
:param s: sparsity of each column
:param distribution: distribution object. 

这是我的尝试:

start_time=time.time()
distribution = scipy.stats.rv_discrete(values=([-1.0, +1.0  ], [0.5, 0.5]),name = 'dist')

data = (1.0/sqrt(self._s))*distribution.rvs(size=self._n*self._s)
col = numpy.empty(self._s*self._n)
for i in range(self._n):
  col[i*self._s:(i+1)*self._s]=i

row = numpy.empty(self._s*self._n)

print time.time()-start_time

for i in range(self._n):
  row[i*self._s:(i+1)*self._s]=numpy.random.choice(self._d, self._s, replace=False)

S = scipy.sparse.csr_matrix( (data, (row, col)), shape = (self._d,self._n))

print time.time()-start_time

return S

现在为n = 500000,s = 10,d = 1000创建这个地图,在我体面的工作站上花了大约20秒,其中90%的时间用于生成行索引。有什么办法可以加快速度吗?任何替代品?感谢。

1 个答案:

答案 0 :(得分:1)

col = numpy.empty(self._s*self._n)
for i in range(self._n):
  col[i*self._s:(i+1)*self._s]=i

看起来像可以写成一个非循环表达式的东西;虽然它可能不是消费者的大时间

我的第一个猜测是 - 但我需要玩这个才能确定;我认为它正在为列索引号分配所有行。

col = np.empty(self._s, self._n)
col[:,:] = np.arange(self._n)
col = col.ravel()

类似的东西:

for i in range(self._n):
    row[i*self._s:(i+1)*self._s]=numpy.random.choice(self._d, self._s, replace=False)
我认为

是从_s _d次中挑选_n个值。 <_ 1}}允许替换_s,但是允许替换_n可能会很棘手。

如果不自行运行代码(使用较小的n),我就会磕磕绊绊。哪个是缓慢的部分,生成colrow或最终的csr?对n=500000的迭代将变慢。

矩阵将是(1000,500000),但是(10 * 500000)非零项。所以.01的稀疏性。仅仅为了比较,生成类似大小和稀疏度的稀疏随机矩阵将是有趣的

In [5]: %timeit sparse.random(1000, 500000, .01)
1 loop, best of 3: 24.6 s per loop

和密集的随机选择:

In [8]: timeit np.random.choice(1000,(10,500000)).shape
10 loops, best of 3: 53 ms per loop
In [9]: np.array([np.random.choice(1000,(10,)) for i in range(500000)]).shape
Out[9]: (500000, 10)
In [10]: timeit np.array([np.random.choice(1000,(10,)) for i in range(500000)]).
    ...: shape
1 loop, best of 3: 12.7 s per loop

所以,是的,大型迭代循环很昂贵。但鉴于替代政策可能没有办法解决这个问题。或者有吗?

首先猜测,创建row需要一半的时间,另一半创建稀疏矩阵。我不惊讶。您正在使用coo输入样式,这需要lexsorting并在转换为csr时对重复项求和。我们可以通过使用indptr类型的输入来获得速度。总和不会有重复。而且由于每行始终有10个非零项,因此生成indptr值并不难。但我无法做到这一点。 (哎呀,这就是转置)。

random稀疏到csr只是有点慢:

In [11]: %timeit sparse.random(1000, 500000, .01, 'csr')
1 loop, best of 3: 28.3 s per loop