簡體   English   中英

在 Numpy 中生成對稱矩陣

[英]Generating Symmetric Matrices in Numpy

我正在嘗試在 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

你可以這樣做:

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

此外,如果您想添加一些隨機放置的零,您始終可以生成一組隨機索引並用零替換這些值。

我最好這樣做:

a = np.random.rand(N, N)
m = np.tril(a) + np.tril(a, -1).T

因為在這種情況下,矩陣的所有元素都來自相同的分布(在這種情況下是均勻的)。

矩陣中有一個數學屬性可以輕松創建這樣的結構: 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

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)

這對我有用

如果您不介意在對角線上有零,您可以使用以下代碼段:

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 個隨機變量。

我正在使用以下函數使矩陣在垂直和水平方向對稱:

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

這里有一個優雅的答案,它生成一個矩陣,其中所有條目都遵循相同的分布。 但是,該答案會丟棄(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值,填充當前行直到並包括對角線和當前列直到(但不包括)對角線。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM