在 Numpy 中生成对称矩阵
Posted
技术标签:
【中文标题】在 Numpy 中生成对称矩阵【英文标题】:Generating Symmetric Matrices in Numpy 【发布时间】:2012-06-04 03:03:57 【问题描述】:我正在尝试在 numpy 中生成对称矩阵。具体来说,这些矩阵将具有随机位置条目,并且每个条目中的内容可以是随机的。沿着主对角线,我们不关心里面有什么实体,所以我也将它们随机化了。
我采用的方法是首先生成一个 nxn 全零矩阵,然后简单地循环遍历矩阵的索引。但是,考虑到循环在 python 中相对昂贵,我想知道是否可以在不使用 python 的 for 循环的情况下实现相同的目标。
numpy 中是否有一些东西可以让我更有效地实现我的目标?
这是我当前的代码:
import numpy as np
import random
def empty(x, y):
return x*0
b = np.fromfunction(empty, (n, n), dtype = int)
for i in range(0, n):
for j in range(0, n):
if i == j:
b[i][j] = random.randrange(-2000, 2000)
else:
switch = random.random()
random.seed()
if switch > random.random():
a = random.randrange(-2000, 2000)
b[i][j] = a
b[j][i] = a
else:
b[i][j] = 0
b[j][i] = 0
【问题讨论】:
【参考方案1】:你可以这样做:
import numpy as np
N = 100
b = np.random.random_integers(-2000,2000,size=(N,N))
b_symm = (b + b.T)/2
您可以在 np.random
或等效的 scipy 模块中选择您想要的任何发行版。
更新:如果您正在尝试构建类似图形的结构,请务必查看 networkx 包:
http://networkx.lanl.gov
它有许多内置例程来构建图表:
http://networkx.lanl.gov/reference/generators.html
此外,如果您想添加一些随机放置的零,您始终可以生成一组随机索引并将值替换为零。
【讨论】:
谢谢!这是一个有效的解决方案。但是,有什么方法可以让它随机放置零?这个矩阵应该表示图的一种邻接矩阵,所以最好有一个随机分布零的矩阵。 @Ryan:你关心随机条目有什么样的分布吗?如果加上b + b.T
,会得到集中在0附近的非均匀分布。
我正在验证矩阵的一些属性。它更多的是为某些数学性质提供令人信服的证据,因此这里的分布并不那么重要。不过谢谢!
@unutbu ,是的,然后使用np.tril(a) + np.tril(a, -1).T
。
np.random.randint(-5,5,size=(N,N))
似乎已被弃用需要使用randint
【参考方案2】:
我最好这样做:
a = np.random.rand(N, N)
m = np.tril(a) + np.tril(a, -1).T
因为在这种情况下,矩阵的所有元素都来自相同的分布(在这种情况下是均匀的)。
【讨论】:
这是保持相同分布的一种非常优雅的方式!【参考方案3】:矩阵中有一个数学属性可以轻松创建这样的结构:AT * A 其中 A 是行向量,At 是转置(列向量)。这总是返回一个总是可逆的平方正定对称矩阵,所以你不用担心空枢轴;)
# any matrix algebra will do it, numpy is simpler
import numpy.matlib as mt
# create a row vector of given size
size = 3
A = mt.rand(1,size)
# create a symmetric matrix size * size
symmA = A.T * A
【讨论】:
ps:“永远可逆”适用于矩阵,不适用于向量。因此,执行 mt.rand(size, size) 在数值上会更加稳健。无论如何,它都会返回一个大小 x 大小的矩阵,但计算成本更高。【参考方案4】:import numpy as np
n = 5
M = np.random.randint(-2000,2000,(n,n))
symm = M@M.T
# test for symmetry
print(symm == symm.T)
这对我有用
【讨论】:
【参考方案5】:如果您不介意在对角线上使用零,您可以使用以下 sn-p:
def random_symmetric_matrix(n):
_R = np.random.uniform(-1,1,n*(n-1)/2)
P = np.zeros((n,n))
P[np.triu_indices(n, 1)] = _R
P[np.tril_indices(n, -1)] = P.T[np.tril_indices(n, -1)]
return P
请注意,由于对称性,您只需要生成 n*(n-1)/2 个随机变量。
【讨论】:
【参考方案6】:我正在使用以下函数来使矩阵在垂直和水平方向上对称:
def make_sym(a):
w, h = a.shape
a[w - w // 2 :, :] = np.flipud(a[:w // 2, :])
a[:, h - h // 2:] = np.fliplr(a[:, :h // 2])
让我们看看它是如何工作的:
>>> m = (np.random.rand(10, 10) * 10).astype(np.int)
>>> make_sym(m)
>>> m
array([[2, 7, 5, 7, 7, 7, 7, 5, 7, 2],
[6, 3, 9, 3, 6, 6, 3, 9, 3, 6],
[1, 4, 6, 7, 2, 2, 7, 6, 4, 1],
[9, 2, 7, 0, 8, 8, 0, 7, 2, 9],
[5, 5, 6, 1, 9, 9, 1, 6, 5, 5],
[5, 5, 6, 1, 9, 9, 1, 6, 5, 5],
[9, 2, 7, 0, 8, 8, 0, 7, 2, 9],
[1, 4, 6, 7, 2, 2, 7, 6, 4, 1],
[6, 3, 9, 3, 6, 6, 3, 9, 3, 6],
[2, 7, 5, 7, 7, 7, 7, 5, 7, 2]])
【讨论】:
【参考方案7】:这里有一个优雅的答案,它会生成一个矩阵,其中所有条目都遵循相同的分布。但是,该答案会丢弃 (n-1)*n/2
随机数而不使用它们。
如果您想让所有值遵循相同的分布,一次性生成它们并只生成您要使用的值,那么您可以运行以下命令:
>>> import numpy as np
>>> n = 5
>>> r = np.random.rand(n*(n+1)//2)
>>> sym = np.zeros((n,n))
>>> for i in range(n):
... t = i*(i+1)//2
... sym[i,0:i+1] = r[t:t+i+1]
... sym[0:i,i] = r[t:t+i]
...
>>> print(sym)
[[0.03019945 0.30679756 0.85722724 0.78498237 0.56146757]
[0.30679756 0.46276869 0.45104513 0.28677046 0.10779794]
[0.85722724 0.45104513 0.62193894 0.86898652 0.11543257]
[0.78498237 0.28677046 0.86898652 0.13929717 0.45309959]
[0.56146757 0.10779794 0.11543257 0.45309959 0.5671571 ]]
这里的想法是按照三角形数字来了解之前已经使用了随机向量中的多少元素。给定这个t
值,将当前行填充到对角线并包括对角线,将当前列填充到(但不包括)对角线。
【讨论】:
以上是关于在 Numpy 中生成对称矩阵的主要内容,如果未能解决你的问题,请参考以下文章