array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 PageRank算法简单实现 - 爱码网

PageRank with DGL Message Passing

  • 使用DGL实现PageRank算法

PageRank算法

PageRank让链接来"投票"

  一个页面的“得票数”由所有链向它的页面的重要性来决定,到一个页面的超链接相当于对该页投一票。一个页面的PageRank是由所有链向它的页面(“链入页面”)的重要性经过递归算法得到的。一个有较多链入的页面会有较高的等级,相反如果一个页面没有任何链入页面,那么它没有等级。

  假设一个由4个页面组成的小团体:A,B,C和D。如果所有页面都链向A,那么A的PR(PageRank)值将是B,C及D的Pagerank总和。
 
PR(A)=PR(B)+PR(C)+PR(D)PR(A) = PR(B) + PR(C) + PR(D)

  继续假设B也有链接到C,并且D也有链接到包括A的3个页面。一个页面不能投票2次。所以B给每个页面半票。以同样的逻辑,D投出的票只有三分之一算到了A的PageRank上。

PR(A)=PR(B)2+PR(C)1+PR(D)3PR(A) = \frac{PR(B)}{2} + \frac{PR(C)}{1} + \frac{PR(D)}{3}

由于“没有向外链接的页面”传递出去的PageRank会是0,所以,给每个页面一个最小值:(1d)N\frac{(1-d)}{N}

PR(u)=1dN+d×vN(u)PR(v)D(v)PR(u) = \frac{1-d}{N} + d \times \sum_{v \in \mathcal{N}(u)} \frac{PR(v)}{D(v)}

  • NN is the number of nodes in the graph.
  • D(v)D(v) is the out-degree of a node vv.
  • N(u)\mathcal{N}(u) is the neighbornodes.
  • dd is damping factor.

简单实现

  • 创建一个包含有100个节点(网页)的网络,use networkx
  • erdos_renyi_graph(),return a random graph
  • Parameters:
    • n (int) – The number of nodes.
    • p (float) – Probability for edge creation.
    • seed (integer, random_state, or None (default)) – Indicator of random number generation state.
    • directed (bool, optional (default=False)) – If True, this function returns a directed graph.
import dgl
import torch
import networkx as nx
import matplotlib.pyplot as plt
%matplotlib inline

N = 50  # number of nodes
DAMP = 0.85  # damping factor,阻尼系数
K = 10  # number of iterations
g = nx.nx.erdos_renyi_graph(N, 0.1)
g = dgl.DGLGraph(g)
plt.figure(figsize=(15, 8))
nx.draw(g.to_networkx(), node_size=50, node_color=[[.5, .5, .5,]])

PageRank算法简单实现

step 1

PageRank consists of two phases in a typical scatter-gather pattern.

  • 初始化每个节点的PR值为 1N\frac{1}{N}.
  • 把每个节点的出度(out-degree)作为图中节点的特征.
# pr : init pagerank value
# od : out degree
g.ndata['pr'] = torch.ones(N) / N
g.ndata['od'] = g.out_degrees(g.nodes()).float()

# g.ndata['pr']
g.nodes[:].data['pr']
tensor([0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200,
        0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200,
        0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200,
        0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200,
        0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200,
        0.0200, 0.0200, 0.0200, 0.0200, 0.0200])
# g.nodes[:].data['od']
g.ndata['od']
tensor([ 5.,  4.,  4.,  6.,  5.,  5.,  5.,  9.,  5.,  8.,  9., 10.,  4.,  4.,
         1.,  6.,  6.,  6.,  4.,  7.,  5.,  8.,  7.,  6.,  1.,  5.,  5.,  5.,
         5.,  6.,  4.,  7.,  1.,  7.,  7.,  2.,  4.,  5.,  2.,  6.,  7.,  6.,
         6.,  2.,  3.,  7.,  2.,  5.,  5.,  6.])

UDFs : works on a batch of edges, nodes

  • message function : 计算每个节点传递给它的邻接节点的PR值(message)
    • 传入参数为edges,deges{src, dst, data}
      • edges.src[‘pr’] : 访问边src端节点的pr
      • edges.src[‘od’] : 访问边src端节点的出度
  • reduce function : 通过一个节点收到的来自周围邻接几点发送的(message|pr),计算并更新自己的PageRank value.
    • 传入参数为nodes,nodes {data, mailbox.data}
    • nodes.mailbox[‘pr’] : 指向该节点的邻接节点传递给它的message(pr)
def pagerank_message_func(edges):
    return {'pr' : edges.src['pr'] / edges.src['od']}

def pagerank_reduce_func(nodes):
    msgs = torch.sum(nodes.mailbox['pr'], dim=1)
    pv = (1 - DAMP) / N + DAMP * msgs
    return {'pr' : pv}

## register
g.register_message_func(pagerank_message_func)
g.register_reduce_func(pagerank_reduce_func)

one PageRank iteration:

# 便利每条边还节点,进行信息的传递和pr的更新
def pagerank_naive(g):
    # Phase #1: send out messages
    for u, v in zip(*g.edges()):
        g.send((u, v))
    # Phase #2: compute, update new PageRank values.
    for v in g.nodes():
        g.recv(v)

批处理

compute on a batch of nodes or edges. For example
DGL如何并行处理多个边和节点:

  • 由于每个节点的出入度不同,所以不能将不同长度的张量’对叠’在一起
  • DGL按照每个node入度的数量分组,然后对每一组调用pagerank_reduce_func
def pagerank_batch(g):
    g.send(g.edges())
    g.recv(g.nodes())

higher level APIs

level-2 APIs 包含了所有的sendrecv操作

def pagerank_level2(g):
    g.update_all()

DGL也提供了内置函数

  • dgl.function.copy_src(src, out) : an edge UDF
  • dgl.function.sum(msg, out) : a node UDF
import dgl.function as fn

def pagerank_builtin(g):
    g.ndata['pr'] = g.ndata['pr'] / g.ndata['od']
    g.update_all(message_func=fn.copy_src(src='pr', out='m'),
                 reduce_func=fn.sum(msg='m',out='m_sum'))
    g.ndata['pr'] = (1 - DAMP) / N + DAMP * g.ndata['m_sum']

如果使用了DLG的builtin function,这将会覆盖之前的操作,即注册的两个函数:

  • pagerank_message_func
  • pagerank_reduce_func
    使用内置的函数,除了代码更清晰,还会更快,这是应为:DGL将融合copy_src消息函数和函数sum简化为一个稀疏矩阵向量(spMV)乘法.CPU可以为这种计算进行加速.

Using spMV for PageRank

Rk=1dN1+dARk1\mathbf{R}^{k} = \frac{1-d}{N} \mathbf{1} + d \mathbf{A}*\mathbf{R}^{k-1}

  • Rk\mathbf{R}^k :第kk次迭代,所有nodes的PR值向量
  • A\mathbf{A} :图的稀疏邻接矩阵
for k in range(K):
    # pagerank_naive(g)
    # pagerank_batch(g)
    # pagerank_level2(g)
    pagerank_builtin(g)
print(g.ndata['pr'])
tensor([0.0107, 0.0221, 0.0219, 0.0181, 0.0269, 0.0255, 0.0267, 0.0193, 0.0179,
        0.0150, 0.0176, 0.0068, 0.0179, 0.0143, 0.0142, 0.0191, 0.0330, 0.0277,
        0.0393, 0.0153, 0.0266, 0.0327, 0.0185, 0.0207, 0.0177, 0.0178, 0.0255,
        0.0315, 0.0177, 0.0219, 0.0357, 0.0281, 0.0251, 0.0214, 0.0188, 0.0142,
        0.0144, 0.0075, 0.0106, 0.0139, 0.0183, 0.0226, 0.0210, 0.0115, 0.0181,
        0.0223, 0.0070, 0.0171, 0.0213, 0.0109])

相关文章: