首页 > 解决方案 > 如何将矩形矩阵转换为随机且不可约矩阵?

问题描述

我编写了以下代码来将矩阵转换为随机且不可约矩阵。我遵循了一篇论文(Deeper Inside PageRank)来编写这段代码。此代码适用于方阵,但会给出矩形矩阵的错误。如何修改它以将矩形矩阵转换为随机和不可约矩阵?

我的代码:

 import numpy as np
 P = np.array([[0, 1/2, 1/2, 0, 0, 0], [0, 0, 0, 0, 0, 0], [1/3, 1/3, 0, 0, 1/3, 0], [0, 0, 0, 0, 1/2, 1/2], [0, 0, 0, 1/2, 0, 1/2]])
 #P is the original matrix containing 0 rows

 col_len = len(P[0])
 row_len = len(P)

 eT = np.ones(shape=(1, col_len))  # Row vector of ones to replace row of zeros
 e = eT.transpose()  # it is a column vector e
 eT_n = np.array(eT / col_len) # obtained by dividing row vector of ones by order of matrix

 Rsum = 0
 for i in range(row_len):
     for j in range(col_len):
         Rsum = Rsum + P[i][j]
 if Rsum == 0:
     P[i] = eT_n
 Rsum = 0
 P_bar = P.astype(float) #P_bar is stochastic matrix obtained by replacing row of ones by eT_n in P
 alpha = 0.85

 P_dbar = alpha * P_bar + (1 - alpha) * e * (eT_n) #P_dbar is the irreducible matrix
 print("The stocastic and irreducible matrix P_dbar is:\n", P_dbar)

预期输出:

A rectangular stochastic and irreducible matrix.

实际输出:

Traceback (most recent call last):
  File "C:/Users/admin/PycharmProjects/Recommender/StochasticMatrix_11Aug19_BSK_v3.py", line 13, in <module>
P_dbar = alpha * P_bar + (1 - alpha) * e * (eT_n) #P_dbar is the irreducible matrix
ValueError: operands could not be broadcast together with shapes (5,6) (6,6)

标签: pythonnumpy

解决方案


您正在尝试将两个不同形状的数组相乘。这是行不通的,因为一个数组有 30 个元素,而另一个数组有 36 个元素。

您必须确保该数组e * eT_n与您的输入数组具有相同的形状P

您没有使用该row_len值。但如果e行数正确,您的代码将运行。

# e = eT.transpose()  # this will only work when the input array is square
e = np.ones(shape=(row_len, 1))  # this also works with a rectangular P 

您可以检查形状是否正确:

(e * eT_n).shape == P.shape 

您应该学习 numpy 文档和教程以了解如何使用 ndarray 数据结构。它非常强大,但也与原生 python 数据类型有很大不同。

例如,您可以用向量化数组操作替换这个冗长且非常慢的嵌套 python 循环。

原始代码(带有固定缩进):

for i in range(row_len):
    Rsum = 0
    for j in range(col_len):
        Rsum = Rsum + P[i][j]
    if Rsum == 0:
        P[i] = eT_n

惯用的 numpy 代码:

P[P.sum(axis=1) == 0] = eT_n

此外,您不需要创建数组eT_n。由于它只是重复的单个值,因此您可以直接分配标量 1/6。

# eT = np.ones(shape=(1, col_len))  
# eT_n = np.array(eT / col_len)

P[P.sum(axis=1) == 0] = 1 / P.shape[1]

推荐阅读