networkx2.6.3中的pagerank源码分析

networkx中的pagerank源码分析

调用入口

def pagerank(
    G,  # 一个一个NetworkX图。 无方向的图将被转换为有方向的图,每条无方向的边有两条有方向的边。
    alpha=0.85,  # PageRank的阻尼参数,默认=0.85。
    personalization=None,  #  "个性化向量 "由一个字典组成。默认情况下,使用的是均匀分布。
    max_iter=100,  # 幂法特征值求解器中的最大迭代次数。
    tol=1.0e-6,  # 误差容限用于检查幂法求解器的收敛性
    nstart=None,  # 每个节点的PageRank迭代的起始值。
    weight="weight", # 要用作权重的边对应的数据键(这里是图G中"weight"键对应的值作为权重)。如果“无”权重设置为1。
    dangling=None,  # 终止点如何处理。即出度为0的点。默认dangling node和其他结点的权重一样
):
    return pagerank_scipy(
    G, alpha, personalization, max_iter, tol, nstart, weight, dangling
    )

其中,实际的执行代码如下:

def pagerank_scipy(
    G,
    alpha=0.85,
    personalization=None,
    max_iter=100,
    tol=1.0e-6,
    nstart=None,
    weight="weight",
    dangling=None,
):
    msg = "networkx.pagerank_scipy is deprecated and will be removed in NetworkX 3.0, use networkx.pagerank instead."
    warn(msg, DeprecationWarning, stacklevel=2)
    import numpy as np
    import scipy as sp
    import scipy.sparse  # call as sp.sparse

    N = len(G)  # 图的节点数量
    if N == 0:  # 如果节点为空,直接返回
        return {}

    nodelist = list(G)  # 节点的名字列表
    M = nx.to_scipy_sparse_matrix(G, nodelist=nodelist, weight=weight, dtype=float)  # 依nodelist为顺序,用稀疏邻接矩阵的方式表示这个图。weight可以影响转移概率矩阵中的概率?
    S = np.array(M.sum(axis=1)).flatten()  # 计算每个点对应的出度
    S[S != 0] = 1.0 / S[S != 0]  # 计算转移概率。值为  1/出度
    Q = sp.sparse.spdiags(S.T, 0, *M.shape, format="csr")  # 把上面的S转为M形状的对角阵。压缩稀疏行(CSR,Compressed Sparse Row)。
    M = Q * M  # 得到每个节点的转移概率矩阵

    # initial vector
    if nstart is None:  # 如果没有指定初始的pr值,默认为 1/N,其中N为节点数量
        x = np.repeat(1.0 / N, N)
    else:
        x = np.array([nstart.get(n, 0) for n in nodelist], dtype=float)
        x = x / x.sum()

    # Personalization vector
    if personalization is None:  # 如果没有指定节点的权重,则默认为  1/N
        p = np.repeat(1.0 / N, N)
    else:  #  以字典{"节点名字":权重}的方式指定,则节点权重为  p/p.sum()
        p = np.array([personalization.get(n, 0) for n in nodelist], dtype=float)
        if p.sum() == 0:
            raise ZeroDivisionError
        p = p / p.sum()
    # Dangling nodes
    if dangling is None:
        dangling_weights = p  # 默认终止点的转移概率为 1/N
    else:
        # Convert the dangling dictionary into an array in nodelist order
        dangling_weights = np.array([dangling.get(n, 0) for n in nodelist], dtype=float)
        dangling_weights /= dangling_weights.sum()
    is_dangling = np.where(S == 0)[0]  # 标记没有出度的点,也就是终止点

    # power iteration: make up to max_iter iterations
    # !!! 这里是计算的核心部分了
    for _ in range(max_iter):
        xlast = x  # xlast用于保存上一次的pagerank值
        x = alpha * (x * M + sum(x[is_dangling]) * dangling_weights) + (1 - alpha) * p  # pagerank计算公式,x * M 的大小为(节点数量,),每个值为对应点的pr值。sum(x[is_dangling])是终止点的pr值的和,作为系数乘以dangling_weights,乘积值作为对整体pr值的修正。alpha是阻尼系数,p默认情况下为 1/N。p也可以为归一化的personalization值。
        # check convergence, l1 norm
        err = np.absolute(x - xlast).sum()  # pr值相对上一次计算的pr值的误差,再累加。理论上logN次后会稳定。
        if err < N * tol:  # 如果在指定收敛误差内,则返回结果,否则抛出异常
            return dict(zip(nodelist, map(float, x)))
    raise nx.PowerIterationFailedConvergence(max_iter)

对networkx 2.6.3 版本中的pagerake分析就到这里。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值