Python:如何使用Python生成随机稀疏对称矩阵?

Python:如何使用Python生成随机稀疏对称矩阵?,python,sparse-matrix,Python,Sparse Matrix,如何使用python生成随机稀疏对称矩阵 在MATLAB中,我们有一个函数“” 但是在Python中如何做到这一点呢?如果您有scipy,您可以使用。下面的sprandsym函数生成一个稀疏的随机矩阵X,取其上三角部分,并将其转置添加到自身以形成对称矩阵。由于这将使对角线值加倍,因此对角线将减去一次 非零值正态分布,平均值为0,标准偏差为0 第1页。Kolomogorov-Smirnov测试用于检查非零值是否正确 符合正态分布图,直方图和 QQ图也生成,以可视化分布 import numpy a

如何使用python生成随机稀疏对称矩阵

在MATLAB中,我们有一个函数“”


但是在Python中如何做到这一点呢?

如果您有scipy,您可以使用。下面的
sprandsym
函数生成一个稀疏的随机矩阵X,取其上三角部分,并将其转置添加到自身以形成对称矩阵。由于这将使对角线值加倍,因此对角线将减去一次

非零值正态分布,平均值为0,标准偏差为0 第1页。Kolomogorov-Smirnov测试用于检查非零值是否正确 符合正态分布图,直方图和 QQ图也生成,以可视化分布

import numpy as np
import scipy.stats as stats
import scipy.sparse as sparse
import matplotlib.pyplot as plt
np.random.seed((3,14159))

def sprandsym(n, density):
    rvs = stats.norm().rvs
    X = sparse.random(n, n, density=density, data_rvs=rvs)
    upper_X = sparse.triu(X) 
    result = upper_X + upper_X.T - sparse.diags(X.diagonal())
    return result

M = sprandsym(5000, 0.01)
print(repr(M))
# <5000x5000 sparse matrix of type '<class 'numpy.float64'>'
#   with 249909 stored elements in Compressed Sparse Row format>

# check that the matrix is symmetric. The difference should have no non-zero elements
assert (M - M.T).nnz == 0

statistic, pval = stats.kstest(M.data, 'norm')
# The null hypothesis is that M.data was drawn from a normal distribution.
# A small p-value (say, below 0.05) would indicate reason to reject the null hypothesis.
# Since `pval` below is > 0.05, kstest gives no reason to reject the hypothesis
# that M.data is normally distributed.
print(statistic, pval)
# 0.0015998040114 0.544538788914

fig, ax = plt.subplots(nrows=2)
ax[0].hist(M.data, normed=True, bins=50)
stats.probplot(M.data, dist='norm', plot=ax[1])
plt.show()
而不是

 result = (X + X.T)/2.0
因为我无法说服自己
(X+X.T)/2.0
中的非零元素具有正确的分布。首先,如果
X
密集且正态分布,平均值为0,方差为1,即
N(0,1)
,那么
(X+X.T)/2.0
将是
N(0,1/2)
。当然,我们可以通过使用

 result = (X + X.T)/sqrt(2.0)
相反。然后
结果将是
N(0,1)
。但还有另一个问题:如果
X
是稀疏的,那么在非零位置,
X+X.T
通常是正态分布的随机变量加零。除以
sqrt(2.0)
会将正态分布挤压到接近0的位置,从而得到更紧密的尖峰分布。随着
X
变得稀疏,这可能越来越不像正态分布

import numpy as np
import scipy.stats as stats
import scipy.sparse as sparse
import matplotlib.pyplot as plt
np.random.seed((3,14159))

def sprandsym(n, density):
    rvs = stats.norm().rvs
    X = sparse.random(n, n, density=density, data_rvs=rvs)
    upper_X = sparse.triu(X) 
    result = upper_X + upper_X.T - sparse.diags(X.diagonal())
    return result

M = sprandsym(5000, 0.01)
print(repr(M))
# <5000x5000 sparse matrix of type '<class 'numpy.float64'>'
#   with 249909 stored elements in Compressed Sparse Row format>

# check that the matrix is symmetric. The difference should have no non-zero elements
assert (M - M.T).nnz == 0

statistic, pval = stats.kstest(M.data, 'norm')
# The null hypothesis is that M.data was drawn from a normal distribution.
# A small p-value (say, below 0.05) would indicate reason to reject the null hypothesis.
# Since `pval` below is > 0.05, kstest gives no reason to reject the hypothesis
# that M.data is normally distributed.
print(statistic, pval)
# 0.0015998040114 0.544538788914

fig, ax = plt.subplots(nrows=2)
ax[0].hist(M.data, normed=True, bins=50)
stats.probplot(M.data, dist='norm', plot=ax[1])
plt.show()

因为我不知道
(X+X.t)/sqrt(2.0)
会生成什么分布,所以我选择复制
X
的上三角部分(从而重复我知道的正态分布非零值)。

联合国大学的答案是性能和可扩展性方面的最佳答案——numpy和scipy一起,有很多来自matlab的功能

如果出于任何原因无法使用它们,或者您正在寻找纯python解决方案,您可以尝试

from random import randgauss, randint
sparse = [ [0 for i in range(N)] for j in range(N)]
# alternatively, if you have numpy but not scipy:
# sparse = numpy.zeros(N,N)
for _ in range(num_terms):
    (i,j) = (randint(0,n),randint(0,n))
    x = randgauss(0,1)
    sparse[i][j] = x
    sparse[j][i] = x

虽然它可能比unutbu的解决方案给您多一点控制,但您应该预期它会明显慢一些;scipy是一种你可能不想避免的依赖关系,矩阵也需要对称,这似乎被这里的两个答案掩盖了

def sparseSym(rank, density=0.01, format='coo', dtype=None, random_state=None):
  density = density / (2.0 - 1.0/rank)
  A = scipy.sparse.rand(rank, rank, density=density, format=format, dtype=dtype, random_state=random_state)
  return (A + A.transpose())/2
这将创建一个稀疏矩阵,然后将其转置添加到自身以使其对称


它考虑了这样一个事实,即密度会随着两个项的相加而增加,并且对角线项不会增加密度。

这是一个numpy矩阵还是仅仅是嵌套数组?如果您试图模拟matlab,numpy和scipy是一个很好的团队,正如unutbu所指出的,但缺少“对称”属性。我们如何使对角线元素必须非零?除了缺少对称属性之外,
scipy.sparse.rand
的值是均匀分布的,而
sprandsym
的distributed@hipoglucido:谢谢你指出这一点。我更新了答案,使结果与正态分布的值对称。这里,我需要所有非对角元素都是非零值,并且给出了非零值的最大数量。有什么想法吗?