想象你是一名旅行博主,来到一座陌生城市。你不拿地图,而是随机坐上公交,到站后随便换乘下一辆,把沿途遇到的每个街角、每张面孔和每次偶遇都记在日记里。你写了很多本“随缘游记”。神奇的是,当你和朋友分享这些日记时,发现经常在同一站出现的那些人,兴趣和职业也惊人地相似。你总结出一套规律:经常在同一时间出现在同一地点的人,大概率是同类人。 这就是 DeepWalk 的核心直觉——在庞大的图数据(比如社交网络、电商关系网、知识图谱)里,我们可以用“随机游走”模拟这个博主,把节点(用户、商品、实体)变成一串串“游记序列”,再像分析游记一样分析节点之间的共现关系,最终把每一个节点变成一个稠密的向量坐标。相似的节点在坐标系中距离相近,机器就能用坐标完成分类、推荐、预测等任务。
DeepWalk 是图嵌入的基石算法,掌握了它,你就掌握了如何让图数据“开口说话”——把抽象关系变成可计算的向量,是图分析工程师、推荐系统和知识图谱方向的必备基本功。
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
核心思路
旅行博主的每一篇游记,其实都在无意中记录了一张“关系的快照”:谁和谁总被写在同一页里。DeepWalk 的思路也极其简单——图嵌入的目标,就是把图中每个节点映射到一个低维稠密的向量空间,让原本“靠边连着”的关系,变成“靠距离算着”的关系。一切都是无监督的:我们不需要告诉机器“这些节点该分成几类”,只需要丢给它一批随机游走生成的序列即可。
为什么能做到?因为 DeepWalk 借用了自然语言处理中的 Zipf 定律直觉:在随机游走生成的序列里,节点出现的频率分布和自然语言中单词的频率分布非常相似。既然 Word2Vec 能通过“单词的上下文”学习词向量,DeepWalk 当然也可以用“节点的上下文”学习节点向量。这相当于把图“翻译”成了一门语言,而随机游走序列就是语言中的句子。
最终,DeepWalk 输出的每一个节点向量,都携带了它的“社交名片”——谁和它常出现在一起,谁与它气质相似,都编码在这串数字里。节点分类、链路预测、可视化,都能在这份向量上轻松展开。
回到旅行博主的比喻:她每去一座新城,不会画一张包含几千个路口的超大地图(那太占背包空间),而是只在日记本上记几个关键的“坐标感”——附近有谁、常去哪里、和谁同行。这些精炼的记录,就是节点的“低维向量”。
- 节点映射把集合 V 中每一个节点 v 映射成 d 维实数向量
- 降维约束向量维度 d 远小于节点总数,迫使模型把信息压缩到最本质的结构
节点表示学习
在 DeepWalk 出现之前,图节点最朴素的身份标识是 one-hot 编码:假设图里有 1 万个节点,每个节点就是一个长度 1 万的向量,其中只有自己的位置是 1,其他全是 0。这就像给每个路口发了一块只写着自己名字的巨大门牌号——信息量极少,却占满整面墙。而 DeepWalk 采用嵌入向量的思路,让每个节点变成一个蕴含“社交含义”的稠密短向量。
怎么学习这样的向量?核心在“语义由邻居塑造”。旅行博主写游记时,同一个地点总与相似的邻居相伴出现;在 DeepWalk 中,一个节点的向量,是由它周围频繁共现的节点共同“塑造”出来的。两个节点如果有相似“朋友圈”,它们的向量就会被训练得靠近。
维度选择则是一门平衡的艺术:维度太小,向量装不下复杂的关系结构;维度太大,不仅计算量大,还会引入噪音。实践中,DeepWalk 论文给出 64 到 128 维作为常用的稳妥区间,就像博主不会背一整本电话本(1 万维),也不必只记一个地标名(1 维),而是记几十条关键关系。
最终,这些向量组成了嵌入矩阵——相当于一本“城市人物志”,每个街区(节点)都在其中占一行,记录着它与其他街区的关联密码。下游任务只需要查表即可获得任意节点的表示,非常高效。
- 节点索引节点 $v_i$ 在图中拥有唯一编号
- 向量赋值为该节点学习一个 d 维向量 $\mathbf{x}_i$
随机游走采样
旅行博主不会按航线图走,她随机跳上公交,到站随机换乘——这种“无目的”行走,就是 随机游走采样。DeepWalk 从每个节点出发,按均匀概率随机选择当前节点的一个邻居作为下一站,重复 t 次,得到一条长度为 t 的节点序列。把这条序列看作一个句子,节点就是句子里的单词。
转移概率是随机游走的引擎。站在当前节点 $v_i$,选择邻居 $v_j$ 的概率是:
为了覆盖全图,DeepWalk 通常对每个节点执行 γ 次随机游走(论文中常取 $\gamma = 10$,游走长度 $t = 40$)。这些序列合在一起,就构成了训练 Skip-gram 模型的“语料库”。游走参数很重要:长度太短,序列捕捉不到远距离结构;次数太少,稀有节点无法被充分采样。
博主游走得越多,日记越丰富,对城市的理解越全面。随机游走同理:序列越多越有代表性。这份由游走产生的“语料库”,就是训练节点向量的全部素材。
- 邻居选择均匀随机地从邻居集合中选下一个节点,度数越高,每个邻居被选中的概率越小
- 语料规模对每个节点做 $\gamma$ 次游走,总序列数为 $\gamma \cdot |V|$ 条
Skip-gram模型
有了“游记语料”,DeepWalk 用 Skip-gram 模型 学习节点向量。Skip-gram 的任务是:给定序列中的一个中心节点 $v_i$,预测它周围窗口 $w$ 内的上下文节点。这就像博主翻到日记某一页,看到“街角咖啡店”,就能猜到前后页写的可能是邻桌的常客。模型希望最大化:
具体地,给定中心节点 $v_i$,上下文节点 $v_k$ 出现的概率由 softmax 定义:
直接计算 softmax 需要对全图所有节点求和,代价太高。DeepWalk 引入层次 Softmax:把所有节点组织成一棵二叉树,把归一化分母的求和变成沿树路径的若干次二分类。这样计算复杂度从 $O(|V|)$ 降到 $O(\log |V|)$。
博主不需要记住全城几万人才能判断“谁和咖啡店老板熟”,只需沿着“街区—街道—门店”的树状结构逐层对号入座。层次 Softmax 就是这个对号入座的过程。训练完成后,矩阵 $\Phi$ 的每一行就是图节点的最终向量。
- 共现目标最大化窗口内所有上下文节点同时出现的对数概率
- 条件概率用向量内积度量中心节点与上下文节点的亲和度,再经 softmax 归一化
- 层次加速把平铺的
|V|个节点组织成二叉树,沿树路径做二分类
参数与窗口影响
参数选择直接决定嵌入质量,最关键的当属窗口大小 w。窗口小(如 w=2)时,模型只关注直接邻居,向量强调局部结构;窗口大(如 w=10)时,模型能看到更远的上下文,向量能捕获社区结构。这就像博主写日记:如果只记录“我在 A 地遇到 B ”,A 和 B 的关联最紧;如果记录“我这一天从 A 兜转到 B 再到 C 又偶遇 D ”,A 和 D 之间也能产生间接关联。
嵌入维度 $d$ 也是核心参数:$d$ 太小,表达能力不足,相似节点挤作一团;$d$ 太大,容易引入噪音且训练变慢。经验上,64~128 维是性价比最高的区间。游走参数方面,游走长度 $t$ 和每人游走次数 $\gamma$ 共同决定语料规模,规模越大、覆盖越全,但计算成本也越高。
调参策略通常是“先定游走参数再调窗口”:固定 $\gamma=10, t=40$,在验证集上网格搜索 $w$ 和 $d$。如果任务侧重邻居预测,用小窗口;如果任务侧重社区发现,用大窗口。每一组参数都是一次新的“游记风格”,直接影响下游任务表现。
调参时,可以把窗口想象成博主的“视野半径”:视野窄,只看到眼前的人;视野宽,能发现整条街的社交圈子。DeepWalk 不给标准答案,只提供旋钮——你要根据业务场景决定博主该戴哪副眼镜。
- 上下文总数窗口大小为 w 时,每个中心节点有左右各 w 个上下文节点
- 带中心的总跨度加上中心节点自身,共涉及 $2w+1$ 个位置
应用与对比
DeepWalk 常被拿来与谱方法(如 Laplacian 特征映射)对比。谱方法通过学习拉普拉斯矩阵的底部特征向量来降维,理论上很优美,但需要矩阵分解,复杂度高,且新节点加入时必须整体重算。DeepWalk 用随机游走 + Skip-gram 绕开了全局矩阵分解,近似等价于对图的归一化拉普拉斯矩阵做因式分解,但支持在线学习和增量更新——有新闻节点加入时,只需对它生成序列、增量训练,不必重跑全图。
在应用上,DeepWalk 最典型的两个场景是节点分类和链接预测。节点分类:先对一部分节点打标签(如“垃圾账号”),用 DeepWalk 学到的向量做特征,训练一个分类器,再预测未标记节点。链接预测:把两个节点的向量拼接或做内积,作为“这两个人是否将成为好友”的特征。在社交网络中,DeepWalk 已被验证能在少量标注下达到高准确率。
回到博主的类比:谱方法像一个必须把全城地图扫描进电脑才能规划路线的“全局规划师”;DeepWalk 则是一个边走边写的“实地记者”——来一个新景点,只需补写一篇游记即可更新整本攻略,效率高且适合动态变化的社交网络。
- 相似度度量用两个节点向量的点积表示它们的亲密度
- 预测置信度经过 sigmoid 函数映射成 0-1 的连接概率
AI 应用场景
社交网络中的用户分类
阶段:特征工程与表示学习
解决的问题:传统方法只能依赖用户显式属性(年龄、地域),属性稀疏且易伪造。DeepWalk 通过随机游走把用户的关系网络变成用户向量,让“物以类聚”的结构隐含在特征中,分类器只需在少量标注样本上训练即可对全量用户打标。
具体案例:某社交平台要识别“水军”账号。团队从关注关系图中用 DeepWalk 得到 128 维用户向量,再训练一个逻辑回归分类器,在仅 5% 标注率下,F1 相比只用用户资料特征提升了 22%。原因是水军账号在图中的连接模式与真人明显不同(核心节点少、互粉密度高)。
知识图谱中的链接预测
阶段:关系推理与补全
解决的问题:知识图谱天然稀疏,大量真实关系未被记录。传统规则法依赖人工编写逻辑,无法覆盖长尾关系。DeepWalk 把实体视为节点,把关系路径视为游走序列,学到的实体向量能有效推断缺失的三元组,辅助知识图谱补全。
具体案例:在电商知识图谱中,DeepWalk 对“用户-商品-品牌”异构图做随机游走,将映射到同一低维空间的商品向量用于“你可能还喜欢”推荐。相比协同过滤,它对新品(冷启动节点)更友好,因为随机游走序列可以快速覆盖新品的关系网络。
生物网络中的模块发现
阶段:无监督聚类分析
解决的问题:蛋白质相互作用网络规模庞大且存在大量噪音,传统聚类难以捕捉多层次模块结构。DeepWalk 生成的节点向量配合标准聚类算法(如 KMeans),能在不预设模块数量的前提下发现功能相关蛋白质簇。
具体案例:研究团队对酵母蛋白质相互作用网络执行 DeepWalk(w=10, d=64),将得到的向量做聚类,发现的蛋白质模块与已知生物学通路高度吻合,显著优于直接在原始图结构上进行社区发现的效果。
Python 演示
import randomimport networkx as nxfrom gensim.models import Word2Vecfrom sklearn.decomposition import PCAimport matplotlib.pyplot as plt class DeepWalkSampler: def __init__(self, graph, walk_length=10, num_walks=5): self.g = graph self.walk_length = walk_length self.num_walks = num_walks def generate_walks(self): walks = [] nodes = list(self.g.nodes()) for _ in range(self.num_walks): random.shuffle(nodes) for node in nodes: walk = [node] for __ in range(self.walk_length - 1): neighbors = list(self.g.neighbors(walk[-1])) if not neighbors: break walk.append(random.choice(neighbors)) walks.append([str(n) for n in walk]) return walks def train_deepwalk_graph(G, window=5, dim=64, walk_length=10, num_walks=5): sampler = DeepWalkSampler(G, walk_length, num_walks) corpus = sampler.generate_walks() model = Word2Vec(corpus, vector_size=dim, window=window, min_count=0, sg=1, workers=2, epochs=5) return model def plot_embeddings(model, G, title): labels = list(G.nodes()) vectors = [model.wv[str(n)] for n in labels] low = PCA(n_components=2).fit_transform(vectors) color_map = nx.get_node_attributes(G, "community") colors = [color_map.get(n, "gray") for n in labels] plt.figure(figsize=(6, 5)) plt.scatter(low[:, 0], low[:, 1], c=colors, cmap="viridis", s=60) plt.title(title) plt.show() def main(): G = nx.karate_club_graph() comm = {n: G.nodes[n]["club"] for n in G.nodes()} nx.set_node_attributes(G, comm, "community") model_small = train_deepwalk_graph(G, window=2, dim=32) plot_embeddings(model_small, G, "DeepWalk small window w=2") model_large = train_deepwalk_graph(G, window=10, dim=64) plot_embeddings(model_large, G, "DeepWalk large window w=10") if __name__ == "__main__": main()
DeepWalkSampler.generate_walks对每个节点执行多次随机游走,产生节点序列,相当于“写游记”random.choice(neighbors)从邻居中随机挑选下一站,这是随机游走的核心转移规则Word2Vec(corpus, sg=1, ...)用 Skip-gram 模式在序列语料上训练节点向量,把节点当“单词”window=2` 与 `window=10两组窗口对比,小窗口抓局部关系、大窗口抓社区结构PCA(n_components=2)把高维嵌入降到二维,直观检查节点聚类效果
常见误区
误区我以为 DeepWalk 需要给节点打标签才能训练,就像分类器一样,没有标签它就没法学。
正解DeepWalk 实际是无监督的——它只利用图结构(谁连谁)生成随机游走序列,再用 Skip-gram 训练向量,全程不需要标签。标签只在下游任务(如节点分类)中作为评估信号使用。这就像博主不需要别人告诉她“哪个街区是好区”,只需她的足迹就能画出人群聚落图。
为何常见:因为 DeepWalk 常被展示在“节点分类”流程中,分类器是有监督的,很容易误以为嵌入训练本身也是监督学习。
误区我认为随机游走必须严格保证每个节点被访问次数相同,否则采样不公平。
正解DeepWalk 刻意不追求均匀。真实网络中节点的度数天然服从幂律分布,随机游走会让高度数节点(社交红人)被访问更多次,这恰好保留了网络的真实结构。类比博主:她会高频记录常路过的热门商圈,很少写冷门小巷——这本身就是城市结构的真实反映。
为何常见:直觉上我们觉得“公平采样”才是好的,但图嵌入追求的是“结构保真”,不是“频率均匀”。
误区我调参时总是把窗口设到最大,认为看到的上下文越多,学到的信息就越丰富。
正解窗口过大会引入远距离弱关系噪音,反而模糊局部社区边界。窗口小则只能看到直接邻居,丢失全局结构。正确的做法是根据下游任务选择:链路预测重局部用小窗口,社区发现重全局用大窗口。像博主拍照,镜头太广会把无关路人拍进来,特写又丢失街景氛围。
为何常见:深度学习中“更多数据=更好效果”的直觉深入人心,但窗口大小是超参数,过度放大并不会带来免费收益。
误区我拿到 DeepWalk 向量后,认为两节点向量的欧氏距离等同于它们在图中的最短路径长度。
正解随机游走 + Skip-gram 优化的是“共现概率”,与最短路径只是近似正相关,并不保证精确对应。两个节点即使相隔甚远,只要有大量随机游走使它们在同窗口出现,向量就会靠近。这是概率共现的“气质相近”,而非精确地理距离。
为何常见:因为可视化时向量距离近的节点看起来确实“结构接近”,容易让人误以为向量距离等于图距离。
误区我认为谱方法基于严格的数学特征分解,DeepWalk 只是随机采样加语言模型,肯定不如谱方法可靠。
正解谱方法虽然理论优美,但需要计算拉普拉斯矩阵的特征分解,复杂度为 $O(n^3)$,不适合大规模网络,且新节点加入必须全量重算。DeepWalk 不显式计算特征向量,复杂度接近 $O(|V| \log |V|)$,还支持增量更新,在工业级大规模图上实用性更强。
为何常见:把“数学精确”等同于“工程实用”是常见误区,实际工程更看扩展性和可维护性。
面试题
Q1. DeepWalk 中的“随机游走序列”在训练中扮演什么角色,最恰当的比喻是?
- A.一座城的官方地图坐标集
- B.旅行博主随缘写下的游记← 正确答案
- C.用户填写的实名注册资料
- D.交通部门发布的限行通告
答案:B。随机游走序列是把图结构“摊平”成线性上下文,正像博主随缘行走写下的游记;它不依赖任何显式标签或地图信息,是纯粹从结构中采样出的语料,因此 B 最贴切。A、C、D 都隐去了“随机游走”随缘采样的本质。
Q2. DeepWalk 算法整体上属于哪一类学习范式?
- A.有监督分类学习
- B.无监督表示学习← 正确答案
- C.强化学习策略优化
- D.主动学习样本选择
答案:B。DeepWalk 在生成嵌入时不使用标签,只利用图结构做随机游走并用 Skip-gram 训练向量,属于无监督表示学习。标签只在后续下游任务中出现,故 A 错误;C、D 与 DeepWalk 流程无关。
Q3. 随机游走中,从当前节点 $v_i$ 转移到邻居 $v_j$ 的概率是?
- A.$1/\deg(v_i)$,若 $v_j$ 是 $v_i$ 的邻居← 正确答案
- B.$1/\deg(v_j)$,若 $v_j$ 是 $v_i$ 的邻居
- C.$1/\deg(v_i)$,对图中所有节点恒成立
- D.$1/|V|$,对所有自然数节点成立
答案:A。转移概率为“从邻居中等概率挑一个”,所以分母是当前节点的度数 $\deg(v_i)$,且仅当存在边时概率非零。B 错误地用了目标节点度数;C 错在“所有节点”而非仅邻居;D 完全是均匀随机抽样,与图结构无关。
Q4. 相比谱方法,DeepWalk 的主要优势有哪些?
- A.不需要全局矩阵分解← 正确答案
- B.支持新节点的增量更新← 正确答案
- C.理论上一定比谱方法更精确
- D.适合大规模稀疏网络← 正确答案
答案:ABD。DeepWalk 用随机游走 + Skip-gram 绕开谱方法的特征分解,因此 A 对;新节点只需补做游走即可增量更新,B 对;它规模上适合工业级大网络,D 对。但“一定更精确”不成立——谱方法在中小规模图上仍有理论精度优势,C 错误。
Q5. 把 DeepWalk 的窗口大小从 w=2 增大到 w=10 后,最可能的变化是?
- A.向量更强调局部直接邻居
- B.向量能捕获更广的社区结构← 正确答案
- C.训练时间一定显著下降
- D.嵌入维度会自动变大
答案:B。窗口越大,中心节点的上下文覆盖越远,能捕获社区级结构,B 正确。A 是小窗口的特点;训练时间通常会上升;窗口大小与嵌入维度是相互独立的超参数,所以 C、D 错误。
Q6. DeepWalk 学到的向量“相似”的本质原因是?
- A.两节点在图中有完全相同的邻居集合
- B.两节点经常出现在同一条随机游走的同一窗口内← 正确答案
- C.两节点具有相同的度数
- D.两节点属于同一个连通分量
答案:B。Skip-gram 优化的正是共现概率——若两节点频繁在窗口中同现,它们的向量就会被拉近。A 是充分但非本质原因;C、D 只是弱相关,连通分量很大但向量不一定相似。这也解释了 DeepWalk 核心思想“共现塑造相似”。
Q7. DeepWalk 论文观察到随机游走序列与自然语言语料之间的关键相似性是?
- A.节点频率分布符合幂律分布← 正确答案
- B.序列长度永远服从均匀分布
- C.节点之间的转移概率恒为常数
- D.序列由严格的语法规则生成
答案:A。真实网络中度数服从幂律分布,导致随机游走生成的节点频率也呈幂律分布,这与自然语言中单词频率的 Zipf 定律高度吻合。B、C、D 都不符合真实网络和自然语言的统计特性。正是这个观察触发了把图嵌入迁移到 Word2Vec 的灵感。
Q8. DeepWalk 生成的节点嵌入可以直接用于哪些下游任务?
- A.节点分类(如识别水军账号)← 正确答案
- B.链接预测(如好友推荐)← 正确答案
- C.图的高维可视化(结合 PCA/t-SNE)← 正确答案
- D.SQL 数据库字段类型推断
答案:ABC。节点分类用嵌入做特征;链接预测用向量内积判断连接概率;可视化用 PCA 降到二维展示社区结构,A、B、C 都对。D 是关系型数据库的 schema 推断任务,与图节点嵌入无关。
Q9. 层次 Softmax 在 DeepWalk 中的作用是?
- A.把图中所有节点按度数排序
- B.加速 softmax 归一化的计算← 正确答案
- C.使随机游走更加均匀
- D.自动选择窗口大小
答案:B。softmax 分母需要对全图节点求和,成本太高。层次 Softmax 把节点组织成二叉树,把 $O(|V|)$ 的计算降至 $O(\log |V|)$,所以 B 正确。它与度数排序、游走均匀性和窗口选择均无关。
Q10. 训练 DeepWalk 时,如果完全删除图中所有社区之间的连边,最可能的结果是?
- A.所有节点向量变成全零向量
- B.各社区内部节点更“抱团”,社区间区分更明显← 正确答案
- C.训练损失函数会出现负无穷
- D.随机游走序列将无法生成
答案:B。删除社区间连边后,随机游走会被束缚在社区内部,共现关系完全集中在社区内,因此每个社区在向量空间中更加聚拢、彼此远离,B 正确。向量不会全零(内部结构仍可学);损失不会发散;只要图仍有边,游走就能生成。这个思想可用于理解“社区结构强度影响嵌入质量”。