8

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

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

http://pastebin.com/4GXpAYTM

但是,我的代码并非每次都有效——在某些情况下,行中的第三个条目为负数,因为前两个条目太大。而且我不知道如何解决这个问题,据我所知,Python 中没有一个函数可以让你生成随机数,这些随机数总和是特定的。

任何帮助表示赞赏。

(请注意,这不是家庭作业问题,它只是为了在我的数学课上获得额外的学分,教授不介意使用外部资源。)

4

5 回答 5

15

使用@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]:
于 2015-07-12T05:59:13.470 回答
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

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

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

于 2015-07-12T05:45:08.393 回答
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。我在变量“精度”中使用了精度,如果这是 1000,则表示随机数在逗号后将有 3 位数字. 在 y 示例中使用了 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]]
于 2015-07-12T05:56:26.323 回答
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 x M 矩阵

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

然后我们通过使用np.apply_along_axis()withaxis=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

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

于 2015-07-12T05:56:30.033 回答
0

漏掉了一个小点。随机矩阵是一个 M x N 非负元素矩阵,其行总和为 1.0。上面的 MBo 评论指出:

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

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

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

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

 X[i, j] = Math.Abs(random.Next(100, 900));
于 2019-04-01T02:23:08.457 回答