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

Sparse random matrix in Python with different range than [0,1]

我需要在 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 本身设置一些快速参数。

看起来您想要的功能大约是两个月前添加的,并且将在 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) where func "should take a single argument specifying the length of the ndarray that it will return. The structurally nonzero entries of the sparse random matrix will be taken from the array sampled by this function." 因此您将能够提供任意分布以供采样.

现在,您至少可以通过将 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 的构造函数之外,目前我看不到更好的解决方案,但我很想知道是否有人至少知道绕过 ceil()破解。

由于 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 个生成正确形状范围内的整数,第三个生成随机值。

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

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)。