Gal*_*lon 8 python numpy matrix svd matrix-decomposition
我想在 numpy 中生成一个 5 级 100x600 矩阵,其中所有条目均从 np.random.uniform(0, 20) 采样,以便所有条目将均匀分布在 [0, 20) 之间。在 python 中这样做的最佳方法是什么?
我看到这里有一种受 SVD 启发的方法(https://math.stackexchange.com/questions/3567510/how-to-generate-a-rank-r-matrix-with-entries-uniform),但是我不知道如何编码。我正在寻找这种 SVD 启发方式的工作示例来获取均匀分布的条目。
实际上,我已经通过垂直堆叠五个 20x100 1 阶矩阵,然后打乱垂直索引,成功地编码了 5 阶 100x100 矩阵。然而,生成的 100x100 矩阵没有均匀分布的条目 [0, 20)。
这是我的代码(我最好的尝试):
import numpy as np
def randomMatrix(m, n, p, q):
# creates an m x n matrix with lower bound p and upper bound q, randomly.
count = np.random.uniform(p, q, size=(m, n))
return count
Qs = []
my_rank = 5
for i in range(my_rank):
L = randomMatrix(20, 1, 0, np.sqrt(20))
# L is tall
R = randomMatrix(1, 100, 0, np.sqrt(20))
# R is long
Q = np.outer(L, R)
Qs.append(Q)
Q = np.vstack(Qs)
#shuffle (preserves rank 5 [confirmed])
np.random.shuffle(Q)
Run Code Online (Sandbox Code Playgroud)
我只是无法接受这样一个事实:我以前的解决方案(“选择”方法)并没有真正产生严格均匀分布的条目,而只是有时足以欺骗统计测试。然而,渐近情况几乎肯定不会均匀分布。但我确实想到了另一个同样糟糕的疯狂想法,但以另一种方式——它并不是真正随机的。
在这个解决方案中,我的做法与 OP 的方法类似,即形成秩为 1 的 R 矩阵,然后将它们连接起来,但略有不同。我通过将基向量堆叠在其自身顶部乘以 0.5 来创建每个矩阵,然后将它们堆叠在移动了均匀分布动态范围一半的同一基向量上。这个过程继续乘以三分之一、三分之二和 1,然后移位等等,直到我在矩阵的该部分中获得所需向量的数量。
我知道这听起来难以理解。但不幸的是,我找不到更好的方法来解释它。希望阅读代码能带来更多启发。
我希望这个“阶梯”方法更加可靠和有用。
import numpy as np
from matplotlib import pyplot as plt
'''
params:
N - base dimention
M - matrix length
R - matrix rank
high - max value of matrix
low - min value of the matrix
'''
N = 100
M = 600
R = 5
high = 20
low = 0
# base vectors of the matrix
base = low+np.random.rand(R-1, N)*(high-low)
def build_staircase(base, num_stairs, low, high):
'''
create a uniformly distributed matrix with rank 2 'num_stairs' different
vectors whose elements are all uniformly distributed like the values of
'base'.
'''
l = levels(num_stairs)
vectors = []
for l_i in l:
for i in range(l_i):
vector_dynamic = (base-low)/l_i
vector_bias = low+np.ones_like(base)*i*((high-low)/l_i)
vectors.append(vector_dynamic+vector_bias)
return np.array(vectors)
def levels(total):
'''
create a sequence of stritcly increasing numbers summing up to the total.
'''
l = []
sum_l = 0
i = 1
while sum_l < total:
l.append(i)
i +=1
sum_l = sum(l)
i = 0
while sum_l > total:
l[i] -= 1
if l[i] == 0:
l.pop(i)
else:
i += 1
if i == len(l):
i = 0
sum_l = sum(l)
return l
n_rm = R-1 # number of matrix subsections
m_rm = M//n_rm
len_rms = [ M//n_rm for i in range(n_rm)]
len_rms[-1] += M%n_rm
rm_list = []
for len_rm in len_rms:
# create a matrix with uniform entries with rank 2
# out of the vector 'base[i]' and a ones vector.
rm_list.append(build_staircase(
base = base[i],
num_stairs = len_rms[i],
low = low,
high = high,
))
rm = np.concatenate(rm_list)
plt.hist(rm.flatten(), bins = 100)
Run Code Online (Sandbox Code Playgroud)
现在用 N = 1000,M = 6000 来凭经验证明近渐近行为:

| 归档时间: |
|
| 查看次数: |
482 次 |
| 最近记录: |