创建稀疏零均值随机矩阵

时间:2017-12-14 01:34:31

标签: python scipy sparse-matrix

有没有人有创建稀疏矩阵的经验,非零值遵循[-0.5,0.5]的均匀分布,并且在python中具有零均值(零中心)(例如使用Scipy.sparse)?

我知道scipy.sparse包提供了一些创建随机稀疏矩阵的方法,比如' rand'和随机的'。但是我用这些方法无法达到我想要的效果。例如,我试过:

import numpy as np
import scipy.sparse as sp

s = np.random.uniform(-0.5,0.5)
W=sp.random(1024, 1024, density=0.01, format='csc', data_rvs=s)

说明我的想法: 假设我想要上面提到的非稀疏或密集的矩阵,我将通过以下方式创建它:

dense=np.random.rand(1024,1024)-0.5

' np.random.rand(1024,1024)'将创建一个密集的均匀矩阵,其值为[0,1]。为了使其为零均值,我将矩阵中心减去0.5。

但是,如果我创建一个稀疏矩阵,请说:

sparse=sp.rand(1024,1024,density=0.01, format='csc')

矩阵将具有均匀[0,1]的非零值。但是,如果我想将矩阵居中,我不能简单地做稀疏 - = 0.5'这将导致所有原始零项在减法后为零。

那么,如何实现稀疏矩阵上密集矩阵的上述例子呢?

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

sparse.random做两件事 - 随机分配非零值,并生成随机统一值。

In [62]: M = sparse.random(10,10,density=.2, format='csr')
In [63]: M
Out[63]: 
<10x10 sparse matrix of type '<class 'numpy.float64'>'
    with 20 stored elements in Compressed Sparse Row format>
In [64]: M.data
Out[64]: 
array([ 0.42825407,  0.51858978,  0.8084335 ,  0.08691635,  0.13210409,
        0.61288928,  0.39675205,  0.58242891,  0.5174367 ,  0.57859824,
        0.48812484,  0.13472883,  0.82992478,  0.70568697,  0.45001632,
        0.52147305,  0.72943809,  0.55801913,  0.97018861,  0.83236235])

您可以廉价地修改data值,而无需更改稀疏度分布:

In [65]: M.data -= 0.5
In [66]: M.A
Out[66]: 
array([[ 0.        ,  0.        ,  0.        , -0.07174593,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.01858978,  0.        ,  0.        ,  0.3084335 , -0.41308365,
         0.        ,  0.        ,  0.        ,  0.        , -0.36789591],
       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.11288928,
        -0.10324795,  0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
         0.        ,  0.        ,  0.08242891,  0.0174367 ,  0.        ],
       [ 0.        ,  0.        ,  0.07859824,  0.        ,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
         0.        , -0.01187516,  0.        ,  0.        , -0.36527117],
       [ 0.        ,  0.        ,  0.32992478,  0.        ,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.20568697,
         0.        ,  0.        , -0.04998368,  0.        ,  0.        ],
       [ 0.02147305,  0.        ,  0.22943809,  0.05801913,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.47018861,  0.33236235,  0.        ,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ,  0.        ]])
In [67]: np.mean(M.data)
Out[67]: 0.044118297661574338

或者用一组新值替换非零值:

In [69]: M.data = np.random.randint(-5,5,20)
In [70]: M
Out[70]: 
<10x10 sparse matrix of type '<class 'numpy.int32'>'
    with 20 stored elements in Compressed Sparse Row format>
In [71]: M.A
Out[71]: 
array([[ 0,  0,  0,  4,  0,  0,  0,  0,  0,  0],
       [-1,  0,  0,  1,  2,  0,  0,  0,  0, -4],
       [ 0,  0,  0,  0,  0,  4,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0, -5, -5,  0],
       [ 0,  0,  2,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0, -3,  0,  0,  3],
       [ 0,  0, -1,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0, -4,  0,  0, -1,  0,  0],
       [-1,  0, -5, -2,  0,  0,  0,  0,  0,  0],
       [ 0,  3,  1,  0,  0,  0,  0,  0,  0,  0]])
In [72]: M.data
Out[72]: 
array([ 4, -1,  1,  2, -4,  0,  4, -5, -5,  2, -3,  3, -1, -4, -1, -1, -5,
       -2,  3,  1])

答案 1 :(得分:0)

import numpy as np a = (['a','b','c',],['d','e','f','g'],['h','i','j','k']) for row in a: print row for lis in a: for item in lis: print item 参数期待&#34;可调用&#34;需要一个大小。从文档中可以看出这一点并不明显。这可以通过lambda完成,如下所示:

data_rvs

然后import numpy as np import scipy.sparse as sp W = sp.random(1024, 1024, density=0.01, format='csc', data_rvs=lambda s: np.random.uniform(-0.5, 0.5, size=s)) 给出:

print(W)

对于新手来说,lambda可能看起来很奇怪 - 这只是一个未命名的函数。 (243, 0) -0.171300809713 (315, 0) 0.0739590145626 (400, 0) 0.188151369316 (440, 0) -0.187384896218 : : (1016, 0) 0.29262088084 (156, 1) -0.149881296136 (166, 1) -0.490405135834 (191, 1) 0.188167190147 (212, 1) 0.0334533020488 : : (411, 1) 0.122330200832 (431, 1) -0.0494334160833 (813, 1) -0.0076379249885 (828, 1) 0.462807265425 : : (840, 1021) 0.456423017883 (12, 1022) -0.47313075329 : : (563, 1022) -0.477190349161 (655, 1022) -0.460942546313 (673, 1022) 0.0930207181126 (676, 1022) 0.253643616387 : : (843, 1023) 0.463793903168 (860, 1023) 0.454427252782 函数采用可选参数sp.random,默认为data_rvs。指定时,它应该是一个接受size参数并返回该随机数的函数。执行此操作的简单功能是:

None

我不知道API的来源,但不需要形状,因为def generate_n_uniform_randoms(n): return np.uniform(-0.5, 0.5, n) 可能首先计算出哪些指数不为零,然后它只需计算随机值那些指数,这是一个已知大小的集合。

lambda只是语法糖,允许我们根据其他函数调用来内联定义该函数。我们可以改为写

sp.random

实际上,这可以是一个&#34;可赎回的&#34; - 某些对象W = sp.random(1024, 1024, density=0.01, format='csc', data_rvs=generate_n_uniform_randoms) f返回f(n)个随机变量。这可以是一个函数,但它也可以是实现n函数的类的对象。例如:

__call__(self, n)

如果你需要平均值恰好为零(当然在舍入范围内),可以通过从非零值中减去均值来完成,如上所述:

class ufoo(object):

    def __call__(self, n):
        import numpy
        return numpy.random.uniform(-0.5, 0.5, n)

W = sp.random(1024, 1024, density=0.01, format='csc', 
              data_rvs=ufoo())

然后:

W.data -= np.mean(W.data)
  

-2.37186​​41632430623e-18

答案 2 :(得分:0)

在我看来,您的要求仍然不完整(见下文提到的不利条件)。

以下是我在评论中概述的简单构造的一些实现:

import numpy as np
import scipy.sparse as sp

M, N, NNZ = 5, 5, 10
assert NNZ % 2 == 0
flat_dim = M*N

valuesA = np.random.uniform(-0.5, 0.5, size=NNZ // 2)
valuesB = valuesA * -1
values = np.hstack((valuesA, valuesB))
positions_flat = np.random.choice(flat_dim, size=NNZ, replace=False)
positions_2d = np.unravel_index(positions_flat, dims=(M, N))
mat = sp.coo_matrix((values, (positions_2d[0], positions_2d[1])), shape=(M, N))
print(mat.todense())
print(mat.data.mean())

输出:

[[ 0.          0.          0.          0.0273862   0.        ]
 [-0.3943963   0.          0.         -0.04134932  0.        ]
 [-0.10121743  0.         -0.0273862   0.          0.04134932]
 [ 0.3943963   0.          0.          0.          0.        ]
 [-0.24680983  0.          0.24680983  0.10121743  0.        ]]
0.0

优点

  • 稀疏
  • 零均值
  • 来自统一分发的条目

潜在的劣势:

  • 对于矩阵中的每个值x,某处可以找到-x!
    • 含义:它在更广泛的联合分布意义上并不统一
    • 如果这只是伤害你只能告诉
    • 如果是:上述结构可以很容易地修改为使用某些分布中的任何居中值,因此您的问题会崩溃到这个更小的(但不一定更容易的问题)

现在关于那个相关的问题:我在这里猜测,但我不会惊讶地发现,使用约束x统一抽样mean(x)=0值是NP难的。

请记住,非贝罗斯的后验中心,如其他答案所推荐的,会改变基础分布(即使对于simple distributions)。在某些情况下甚至使边界无效(留下间隔-0.5,0.5)。

这意味着:这个问题是关于正式确定哪个目标是多么重要并以某种方式平衡这些目标。