Python中的稀疏随机矩阵,其范围不同于[0,1]

时间:2015-06-02 03:31:45

标签: python random scipy sparse-matrix

我需要在Python中生成一个稀疏随机矩阵,其中所有值都在[-1,1]范围内,且分布均匀。最有效的方法是什么?

我有一个基本的稀疏随机矩阵:

from scipy import sparse
from numpy.random import RandomState

p = sparse.rand(10, 10, 0.1, random_state=RandomState(1))

这给了我[0,1]中的值:

print p
  (0, 0)    0.419194514403
  (0, 3)    0.0273875931979
  (1, 4)    0.558689828446
  (2, 7)    0.198101489085
  (3, 5)    0.140386938595
  (4, 1)    0.204452249732
  (4, 3)    0.670467510178
  (8, 1)    0.878117436391
  (9, 0)    0.685219500397
  (9, 3)    0.417304802367

最好有一个就地解决方案或不需要将其吹到完整矩阵的东西,因为在实践中我将使用非常大的尺寸。令我惊讶的是,没有为sparse.rand本身设置一些快速参数。

2 个答案:

答案 0 :(得分:5)

看起来您想要的功能大约在两个月前添加,并且将以scipy 0.16提供:https://github.com/scipy/scipy/blob/77af8f44bef43a67cb14c247bc230282022ed0c2/scipy/sparse/construct.py#L671

您将能够调用sparse.random(10, 10, 0.1, random_state=RandomState(1), data_fvs=func) func “应该使用一个参数来指定它将返回的ndarray的长度。稀疏随机矩阵的结构非零条目将取自此函数采样的数组。“因此,您将能够提供任意分布到样本。

现在,你可以通过将p乘以标量N来至少将均匀分布拉伸到[0,N]:

>>> print 2*p

(0, 0)  0.838389028807
(9, 0)  1.37043900079
(4, 1)  0.408904499463
(8, 1)  1.75623487278
(0, 3)  0.0547751863959
(4, 3)  1.34093502036
(9, 3)  0.834609604734
(1, 4)  1.11737965689
(3, 5)  0.28077387719
(2, 7)  0.39620297817

你不能添加标量,但是作为一个黑客,你可以创建一个稀疏矩阵,其中包含p.ceil()的非零元素中的所有元素,因为p的所有元素都是在[0,1]内生成的]。然后将均匀分布转换为[-1,1],你可以做

 print 2*p - p.ceil()

(0, 0)  -0.161610971193
(0, 3)  -0.945224813604
(1, 4)  0.117379656892
(2, 7)  -0.60379702183
(3, 5)  -0.71922612281
(4, 1)  -0.591095500537
(4, 3)  0.340935020357
(8, 1)  0.756234872782
(9, 0)  0.370439000794
(9, 3)  -0.165390395266

所以一般来说,如果你需要一些间隔[a,b],只需执行:

p = (b - a)*p + a*p.ceil()

我目前看不到更好的解决方案,而不是编写类似于sparse.rand的自己的构造函数,但我很想知道是否有人知道如何绕过{{1}黑客

答案 1 :(得分:2)

由于sparse.rand生成coo矩阵(默认情况下),您可以直接操作其.data属性。 (' csr'格式可以通过这种方式进行转换)

p=sparse.rand(10,10,0.1)
p.data *=2
p.data -=1

值之前和之后:

  (0, 4)    0.758811389117
  (1, 8)    0.703514506105
  (1, 9)    0.640418745353
  (4, 0)    0.896198785835
  (4, 6)    0.511459880587
  (5, 2)    0.580048680358
  (7, 1)    0.739418689993
  (8, 3)    0.506395207688
  (8, 5)    0.900696518461
  (9, 4)    0.474014207942

  (0, 4)    0.517622778234
  (1, 8)    0.40702901221
  (1, 9)    0.280837490706
  (4, 0)    0.79239757167
  (4, 6)    0.0229197611736
  (5, 2)    0.160097360716
  (7, 1)    0.478837379986
  (8, 3)    0.0127904153758
  (8, 5)    0.801393036923
  (9, 4)    -0.051971584115

相同的空间密度,只是不同的价值分布。

实际上,您可以生成全新的.data值。 sparse.rand的结尾是:

....
j = .... # tweak random values
i = ...  # tweak ints
vals = random_state.rand(k).astype(dtype)
return coo_matrix((vals, (i, j)), shape=(m, n)).asformat(format)

随机数组由3个随机序列生成,2个在正确的形状范围内产生整数,第3个产生随机值。

例如从列表中选择的随机值:

In [209]: p.data=np.random.choice(np.arange(20)-10,len(p.data))/10

In [210]: print(p.A)
[[ 0.   0.   0.   0.   0.9  0.   0.   0.   0.   0. ]
 [ 0.   0.   0.   0.   0.   0.   0.   0.  -0.1 -0.7]
 [ 0.   0.   0.   0.   0.   0.   0.   0.   0.   0. ]
 [ 0.   0.   0.   0.   0.   0.   0.   0.   0.   0. ]
 [-1.   0.   0.   0.   0.   0.  -0.8  0.   0.   0. ]
 [ 0.   0.   0.5  0.   0.   0.   0.   0.   0.   0. ]
 [ 0.   0.   0.   0.   0.   0.   0.   0.   0.   0. ]
 [ 0.   0.   0.   0.   0.   0.   0.   0.   0.   0. ]
 [ 0.   0.   0.   0.5  0.   0.4  0.   0.   0.   0. ]
 [ 0.   0.   0.   0.  -0.8  0.   0.   0.   0.   0. ]]

开发代码只是将第2行更改为最后一行:

vals = data_rvs(k).astype(dtype)

其中data_rvs是参数(或默认randomstate.rand)。