创建一个任意大小的矩阵,其中行总和为1?

问题描述 投票:6回答:5

我的任务是为任意数量的事件创建一个模拟离散时间马尔可夫链的程序。然而,现在我正在努力的部分是创建代表概率的正确的随机矩阵。右边的随机矩阵是一个矩阵,其行条目总和为1.对于给定的大小,我知道如何编写执行该操作的矩阵,但问题是我不知道如何做到这一点任意大小。

例如:这是我的3x3矩阵代码,以及我得到的输出示例。

http://pastebin.com/4GXpAYTM

但是,我的代码每次都不起作用 - 有时候行中的第三个条目是负数,因为前两个条目太大了。我不知道怎么解决这个问题,据我所知,Python中没有一个函数可以让你生成随机数,特别是某些东西。

任何帮助表示赞赏。

(请注意,这不是一个家庭作业问题,它仅用于我的数学课程中的额外学分,教授不介意使用外部资源。)

python matrix random markov
5个回答
10
投票

使用@ MBo的想法:

In [16]: matrix = np.random.rand(3,3)

In [17]: matrix/matrix.sum(axis=1)[:,None]
Out[17]:
array([[ 0.25429337,  0.22502947,  0.52067716],
       [ 0.17744651,  0.42358254,  0.39897096],
       [ 0.36179247,  0.28707039,  0.35113714]])

In [18]:

3
投票

使用随机值生成NxN矩阵。 对于每一行: 找到行S的总和

S[j] = Sum(0..N-1){A[j, i]}

然后从该行中的每个值中减去(S-1)/ N.

A[j, i] = A[j, i] - (S[j] - 1) / N

如果只需要非负值,则生成非负的random,并将行中的每个值除以该行的总和

A[j, i] = A[j, i] / S[j]


3
投票

这是一些代码:

import random

precision = 1000000

def f(n) :
    matrix = []
    for l in range(n) :
        lineLst = []
        sum = 0
        crtPrec = precision
        for i in range(n-1) :
            val = random.randrange(crtPrec)
            sum += val
            lineLst.append(float(val)/precision)
            crtPrec -= val
        lineLst.append(float(precision - sum)/precision)
        matrix.append(lineLst)
    return matrix


matrix = f(5)
print matrix

我假设随机数必须为正数,原始数字的总和必须为1.我在变量'precision'中使用精度给出,如果这是1000则意味着随机数将在逗号后面有3位数。例如,使用6位数字,您可以使用更多。

输出:

[[0.086015, 0.596464, 0.161664, 0.03386, 0.121997], 
[0.540478, 0.040961, 0.374275, 0.003793, 0.040493], 
[0.046263, 0.249761, 0.460089, 0.006739, 0.237148], 
[0.594743, 0.125554, 0.142809, 0.056124, 0.08077], 
[0.746161, 0.151382, 0.068062, 0.005772, 0.028623]]

1
投票

右随机矩阵是一个实矩阵,每行总和为1。

这是一个你可以创建一个函数的例子,我把它作为家庭作业留给你

In [26]: import numpy as np

In [27]: N, M = 5, 5

In [28]: matrix = np.random.rand(N, M)

In [29]: matrix
Out[29]:
array([[ 0.27926909,  0.37026136,  0.35978443,  0.75216853,  0.53517512],
       [ 0.93285517,  0.54825643,  0.43948394,  0.15134782,  0.31310007],
       [ 0.91934362,  0.51707873,  0.3604323 ,  0.78487053,  0.85757986],
       [ 0.53595238,  0.80467646,  0.88001499,  0.4668259 ,  0.63567632],
       [ 0.83359167,  0.41603073,  0.21192656,  0.22650423,  0.95721952]])

In [30]: matrix = np.apply_along_axis(lambda x: x - (np.sum(x) - 1)/len(x), 1, matrix)

In [31]: matrix
Out[31]:
array([[ 0.01993739,  0.11092965,  0.10045272,  0.49283682,  0.27584341],
       [ 0.65584649,  0.27124774,  0.16247526, -0.12566087,  0.03609139],
       [ 0.43148261,  0.02921772, -0.12742871,  0.29700952,  0.36971886],
       [ 0.07132317,  0.34004725,  0.41538578,  0.00219669,  0.17104711],
       [ 0.50453713,  0.08697618, -0.11712798, -0.10255031,  0.62816498]])

说明

我们创建一个N×M矩阵

然后我们计算(sum - 1) / N从行中逐项减去

然后我们通过使用np.apply_along_axis()axis=1将其应用于矩阵的每一行,以应用于每一行

验证结果

每行需要总计为1

In [37]: matrix.sum(axis=1)
Out[37]: array([ 1.,  1.,  1.,  1.,  1.])

但是如何从行中的每个条目中减去该值?

在我的例子中,我使用了相当于这个函数的lambda

def subtract_value(x):
    return x - (np.sum(x) - 1)/len(x)

您可以将函数传递给apply_along_axis()以在轴上的每个元素上调用,在我们的示例中它是行

还有其他方式像numpy.vectorize()numpy.frompyfunc

制作一个函数并像上面的任何方法一样应用它比循环遍历每一行中的每个项目更快,更少代码,更容易阅读/理解意图


1
投票

遗漏了一个小问题。随机矩阵是非负元素的M×N矩阵,其行总和为1.0。上述MBo评论指出:

如果只需要非负值,则生成非负的random,并将行中的每个值除以该行的总和

A [j,i] = A [j,i] / S [j]

仅当存储的矩阵完全由整数(不一定是整数)组成时才是这样。否则,得到的矩阵可能包含负数,矩阵越大,负元素越多。

这可以使用以下方法完成:

 X[i, j] = Math.Abs(random.Next(100, 900));
© www.soinside.com 2019 - 2024. All rights reserved.