DeepWalk随机游走

算法思想

2021-10-09_17-04.png

参考资料

https://zhuanlan.zhihu.com/p/45167021

代码实现与注解

思路

  • 理清successor,outdegree函数的输入输出
  • 查看补全函数的返回类型--分析可能的结果--我最初的猜测:这walks应该是多个向量的集合,最后确实也是【[[],..]这样的结构多用于扩充,然后联想需要学习向量,所以想到向量递推的那种向量集合】
  • 生成随机采样索引序列集 -- 这个需要匹配采样形状,以及索引阈值--我是参考一个示例修改的,感悟是: 利用随机数0~1,给rand传入指定shape,再乘以一个相同shape的数据,可以得到一个>=0, <=最大出度-1的值,这样就可以用来索引采样了
  • 理清上下文变量关系,进行zip打包遍历到一起,然后进行聚合操作即可。

Code

%%writefile userdef_graph.py
from pgl.graph import Graph

import numpy as np


class UserDefGraph(Graph):
    def random_walk(self, nodes, walk_len):
        """
        输入:nodes - 当前节点id list (batch_size,)
             walk_len - 最大路径长度 int
        输出:以当前节点为起点得到的路径 list (batch_size, walk_len)

        用到的函数
        1. self.successor(nodes)
           描述:获取当前节点的下一个相邻节点id列表
           输入:nodes - list (batch_size,)
           输出:succ_nodes - list of list ((num_successors_i,) for i in range(batch_size))
        2. self.outdegree(nodes)
           描述:获取当前节点的出度
           输入:nodes - list (batch_size,)
           输出:out_degrees - list (batch_size,)
        """
        # 首先获得当前节点列表对应的一个向量
        walks = [[node] for node in nodes]
        # 游走路径中节点对应id号
        walks_ids = np.arange(0, len(nodes))
        # 当前节点情况
        cur_nodes = np.array(nodes)
        # 根据游走长度进行遍历--破出条件:1. range结束;2. outdegree==0【出度为零,没有可继续的节点】
        for l in range(walk_len):
            """选取有下一个节点的路径继续采样,否则结束"""
            # 计算当前节点的出度--也就是对应有哪些位置的邻近节点
            outdegree = self.outdegree(cur_nodes)
            # 根据出度来确定掩码--True, False--将出度为0的部分复制为False,反之True
            walk_mask = (outdegree != 0)
            # 判断是否没有可继续的节点情况--出度为0
            if not np.any(walk_mask):
                break
            # 根据掩码获取可继续前进的节点,作为后边讨论的当前可前行节点
            cur_nodes = cur_nodes[walk_mask]
            # 获取掩码下,原节点id,组成新的work_ids用于后边讨论,但本身还是作为一个节点的标记,对应这是第几个节点
            walks_ids = walks_ids[walk_mask]
            # 根据掩码获取相应的不为0的出度--用于后边计算前行的路径
            outdegree = outdegree[walk_mask]
            # 返回可继续的节点集合 successor 可获取当前节点的下一个相邻节点id列表,
            # 那么successor 计算出下一节点的集合后,我们需要从中随机取出一个节点--所以我们要创建随机采样的index_list(索引序列集)
            succ_nodes = self.successor(cur_nodes)
            # 创建index_list=>为了才到合适的index信息,采用np.floor与np.random,rand()实现:
            # eg: np.floor(np.random.rand(outdegree.shape[0]) * outdegree).astype('int64')
            # np.random.rand(outdegree.shape[0]): 根据出度集的形状来取得相应形状的随机数--这里体现游走的随机性
            # np.random.rand(outdegree.shape[0]) * outdegree:利用生成的随机数与出度集对应元素相乘——这里得到一些列的随机数
            # 随机数范围在0~最大出度值--保证路径有效
            # np.floor(np.random.rand(outdegree.shape[0]) * outdegree)——实现向下取整,这样就得到了相应游走路径中接下来那个点的索引
            sample_index = np.floor(np.random.rand(outdegree.shape[0]) * outdegree).astype('int64')
            """
            具体实例:
            np.floor(np.random.rand(20) * 3).astype('int64')
            result: array([0, 1, 2, 1, 0, 0, 0, 0, 1, 1, 1, 2, 0, 2, 2, 2, 2, 1, 2, 0])
            """
            # 知道了随机采样的序列集了,那么接下就是分配新的游走路径了
            # 用于后边存放—— 装配有下一个节点的新路径
            next_nodes = []
            # succ_nodes:相邻节点id列表
            # sample_index:对应出度生成的随即索引集
            # walks_ids:游走路径中节点对应id号
            for s, ind, walk_id in zip(succ_nodes, sample_index, walks_ids):
                # 将节点列表、随机采样序列、游走路径中节点对应id号一一对应进行填充
                # 为相应节点添加可以继续前行的节点,形成一条路径
                walks[walk_id].append(s[ind])# walks=>[[], [], []]是这种形式的
                # 同时获取接下来要重新讨论游走时所需的新节点
                next_nodes.append(s[ind])
                """
                如:从1走到了2,从3走到了7: [[1], [3]]=>[[1, 2], [3, 7]]     
                next_nodes.append(s[ind])        
                # 接下来自然就该考虑把新的2, 7 作为下一次游走时讨论出度的节点啦
                """
            cur_nodes = np.array(next_nodes)  # 将节点转换为np类型,方便一些操作运算--同时保证前后数据类型
            # 并且list中,元素本质是对象。如:L = [1, 2, 3],需要3个指针和三个整数对象,对于数值运算比较浪费内存和CPU
            # Numpy提供了ndarray(N-dimensional array object)对象:存储单一数据类型的多维数组。
        # 遍历完游走长度的次数,就可以返回得到的随机游走路径啦
        return walks

print(np.floor(np.random.rand(20) * 3).astype('int64'))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容