Graph Embedding| Node2Vec
Graph Embedding
什么是Graph Embedding
Graph Embedding场景:
- 社交网络,生物信息,用户行为序列(购物,浏览)都存在着大量的关系图谱
- Graph Embedding是一种Embedding降维技术,可以有效的挖掘图网络中的节点特征表示
- 在推荐系统、计算广告领域中的热点模型
- word2vec等Embedding技术的延伸
Graph Embedding的作用:
帮助我们从图网络中进行特征提取,将图网络中的点用低维的向量表示,并且这些向量要能反应原有网络的特性,比如原网络中两个点的结构类似,那么这两个点表示的向量也应该类似
主要方法:
- factorization methods (图因式分解机)
- random walk techniques(随机游走)
- deep learning(深度学习)
Deep Walk
Deep Walk算法:
- DeepWalk Online Learning of Social Representations, 2014 KDD
- https://classes.cs.uoregon.edu/17S/cis607bddl/papers/Perozzi.pdf
- 输入是一张图网络,输出为网络中顶点的向量表示
- 通过截断随机游走(truncated random walk)学习出一个网络的社会表示(social representation),在网络标注顶点很少的情况也能得到比较好的效果
- 具有可扩展的优点,能够适应网络的变化
115个平权的顶点,假如一个顶点可以产生5个句子,遍历每个顶点,找到它的邻居顶点,random随机选择,限制句子最大长度10;
一共会产生多少个句子,115*5=575个,575*10; 把图变成多个一维数组;
- 借助NLP中的word2vec,也就是word embedding(词嵌入)
- word embedding的基本元素是word,在Graph中表示的就是Node,
- word embedding是对构成一个句子中单词序列进行分析,在Graph Network中Node构成的序列就是Random Walk
- random walk,即随机游走,指的是从某个特定的端点开始,游走的每一步都从与当前节点相连的边中随机选择一条,沿着选定的边移动到下一个顶点,不断重复这个过程
Deep Walk算法:
- DeepWalk = Random Walk + Skip-gram
- Step1,给定当前访问起始节点,从其邻居中随机采样节点作为下一个访问节点,重复此过程,直到访问序列长度满足预设条件,产生大量词序列(句子)
- Step2,将这些词序列作为训练样本输入word2vec,用Skip-gram + Hierarchical softmax进行训练,得到词的embedding
Deep Walk算法:
- DeepWalk = Random Walk + Skip-gram
用户行为中如何对物品进行Embedding:
- 基于用户行为序列构建了物品相关图,物品A,B之间存在边是因为用户U1先后购买了物品A和物品B,所以产生了A => B的有向边。
- 如果后续产生了多条相同的有向边,则有向边的权重被加强。将所有用户行为序列都转换成物品相关图中的边之后,全局的物品相关图就建立起来了
- 采用随机游走的方式随机选择起始点,重新产生物品序列
- 最终将这些物品序列输入word2vec模型,生成最终的物品Embedding向量
用户u1,u2,u3,假设用户u1点击了D A B,虚线是时间间隔大于30min (以session作为划分),把它转化为图;
D->A->B;
B->E; D->E->F;
E->C->B;B->A;
通过random walk generation,生成如图c,限制最大长度为5个;
最后通过skip-gram,一个学习向量化表达,得到商品的embedding;
Deep Walk算法
随机游走的跳转概率,也就是到达节点vi后,下一步遍历vi的临接点vj的概率
如果物品的相关图是有向有权图,那么从节点vi跳转到节点vj的概率定义为
N+(vi)是节点vi所有的出边集合,Mij是节点vi到节点vj边的权重。
如果物品相关图是无相无权重图,那么跳转概率将是上面公式的一个特例,即权重Mij将为常数1,且N+(vi)应是节点vi所有“边”的集合,而不是所有“出边”的集合
Project美国大学生足球队Embedding
import networkx as nx # 数据加载,构造图 G = nx.read_gml('football.gml') #球队总数 print(len(G)) #都有哪些球队 print(G.nodes()) #都有哪些比赛 print(G.edges()) # 随机游走,input: 将节点和被遍历的路径的长度作为输入,output: 返回遍历节点的顺序: def get_randomwalk(node, path_length): random_walk = [node] for i in range(path_length-1): temp = list(G.neighbors(node)) temp = list(set(temp) - set(random_walk)) if len(temp) == 0: break random_node = random.choice(temp) random_walk.append(random_node) node = random_node return random_walk print(get_randomwalk('EastCarolina', 10)) # 从图获取所有节点的列表 all_nodes = list(G.nodes()) # 捕获数据集中所有节点的随机游走序列 random_walks = [] for n in tqdm(all_nodes): # 每个节点游走5次,每次最长距离为10 for i in range(5): random_walks.append(get_randomwalk(n,10)) # 输出随机游走序列,及序列个数 print(random_walks) print(len(random_walks)) ## 一共115支球队,每支球队游走5次,一共115*5=575个word sequence # 使用skip-gram,提取模型学习到的权重 from gensim.models import Word2Vec # 训练skip-gram (word2vec)模型 model = Word2Vec(window = 4, sg = 1, hs = 0, negative = 10, # 负采样 alpha=0.03, min_alpha=0.0007, seed = 14) # 从random_walks中创建词汇表 model.build_vocab(random_walks, progress_per=2) model.train(random_walks, total_examples = model.corpus_count, epochs=20, report_delay=1) print(model) # 输出和EastCarolina相似的球队 print(model.similar_by_word('EastCarolina')) # 在二维空间中绘制所选节点的向量 def plot_nodes(word_list): X = model[word_list] #print(type(X)) # 将100维向量减少到2维 pca = PCA(n_components=2) result = pca.fit_transform(X) #print(result) # 绘制节点向量 plt.figure(figsize=(12,9)) # 创建一个散点图的投影 plt.scatter(result[:, 0], result[:, 1]) for i, word in enumerate(word_list): plt.annotate(word, xy=(result[i, 0], result[i, 1])) plt.show() # 将所有的球队embedding进行绘制 plot_nodes(model.wv.vocab)
Word2Vec工具
gensim.models.word2vec.Word2Vec(sentences=None,size=100,alpha=0.025,window=5, min_count=5, sample=0.001,seed=1, orkers=3,min_alpha=0.0001, sg=0, hs=0, negative=5, iter=5, trim_rule=None)
- sentences,可以是一个list
- size,特征向量的维度,默认为100,更大的 size 值需要更多的训练数据,但也同时可以得到更准确的模型。合理的取值范围是几十到几百
- alpha,初始的学习速率,在训练过程中会线性地递减到min_alpha。
- window,窗口大小,表示当前词与预测词在一个句子中的最大距离
- min_count,可以对字典做截断,词频少于min_count次数的单词会被丢弃掉, 默认值为5
- max_vocab_size,设置词向量构建期间的RAM限制,设置成None则没有限制
- sample,高频词汇的随机降采样的配置阈值,默认为1e-3,范围是(0,1e-5)
- seed,随机数种子
- workers,训练的并行线程数
- min_alpha,学习率的最小值
- sg,指定训练算法,默认为0,CBOW算法,sg=1采用skip-gram算法
- hs,如果为1则会采用hierarchica softmax。如果设置为0(默认),则使用negative sampling
- negative,如果>0,采用negative sampling,用于设置多少个noise words(一般是5-20)
- iter,迭代次数,默认为5
- trim_rule,用于设置词汇表的整理规则,指定那些单词要留下,哪些要被删除。可以设置为None(min_count会被使用)
- 从一系列句子中创建词汇表
- build_vocab(sentences, update=False, progress_per=10000, keep_raw_vocab=False, trim_rule=None, **kwargs)
- 训练,从一系列句子更新模型的神经权重
- train(sentences, total_words=None, word_count=0, total_examples=None, queue_factor=2, report_delay=1.0)
- 如果想要支持从(初始)alpha到min_alpha的线性学习速率的衰减,需要提供total_examples(句子数)
- 模型保存
- model.save('mymodel')
- 模型载入
- new_model = gensim.models.Word2Vec.load('mymodel')
- 查询词向量
- model['computer']
- 结果:array([-0.00449447, -0.00310097, 0.02421786, ...], dtype=float32)
- 相似度任务
- model.most_similar(positive=['woman', 'king'], negative=['man'], topn=1) #woman + king - man = queen
- 结果:[('queen', 0.50882536)]
- model.similarity('woman', 'man')
- 结果:0.73723527
Node2Vec算法模型
Node2Vec算法:
- node2vec: Scalable Feature Learning for Networks, 2016 KDD
- https://arxiv.org/abs/1607.00653
- 在DeepWalk基础上进行改进,可以控制进行BFS,DFS随机游走(带偏置的random walk策略)
- BFS,Breadth-first Sampling,倾向于在初始节点的周围游走,反映出一个节点的邻居的微观特性 (广度优先,邻居、周边 微观)
- DFS,Depth-first Sampling,倾向于跑得离初始节点越来越远,反映出一个节点邻居的宏观特性 (深度优先,跑到远处 宏观)
Node2Vec算法:
- 从节点t跳转到节点v后,下一步从节点v跳转到周围各点的跳转概率 πVX = αpq (t, x).wvx
- 其中πVX代表边vx的权重, αpq (t, x) 称为Search bias,有3种情况: (下一个节点到上一个节点的距离有多少种可能性? (x1, x2, x3, t) 到t 的距离 )
dtx 代表节点t 到节点x 的距离;
p和q用来调节Node2Vec算法的参数
- p, return parameter(返回概率):
Thinking 如果 p>max(q,1), 往回走的概率高 or 低?
尽量不往回走,即下一个节点是上一个访问的节点t的概率低
如果 p< min(q,1), 那么采样会更倾向于返回上一个节点,也就是一直在起始点周围某些节点来回转来转去
- q, in-out parameter(出入参数):
Thinking 如果 q>1 ,游走于起始点周围 or 跑出去?
游走会倾向于在起始点周围的节点之间跑,可以反映出一个节点的BFS特性
如果 q<1 ,那么游走会倾向于往远处跑,反映出DFS特性
当p=1,q=1时,游走方式就等同于DeepWalk中的随机游走
Node2Vec算法:
- 通过调节p, q参数,可以调节BFS, DFS
- 挖掘网络中的同质性(homophily) 和 结构性(structural equivalence)
- 同质性,指的是距离相近节点的embedding应该尽量近似,节点u与相连的节点s1、s2、s3、s4的embedding表达应该是接近的 => 同质性
- 结构性,指的是结构上相似的节点的embedding应该相似,节点u和节点s6都是各自局域网络的中心节点,embedding表达相近 => 结构性
Node2Vec算法步骤:
- Step1,转移概率矩阵可以提前算好
- Step2,对图中的每个节点,进行r次随机游走得到r个长为l的walk,可以理解成每个给每个节点造句,r个l长的句子,全部节点的游走合起来就得到了这个网络的语料库
- Step3,经过类似skip-gram的训练可得节点的Embedding
Node2Vec实验结果
- 除了谱聚类,其他的算法都使用了Embedding这种连续的特征表示,实验结果一致的好于谱聚类。使用Embedding不仅可以应用于NLP,还可以用于网络特征表达
- 网络中每个节点的邻居集如何选择会很大程度的影响Embedding的效果。Node2Vec的创新之处就在于提出了一种灵活的选择节点邻居的方法,实验证明比其他的方法更有效
Node2Vec工具
Node2Vec工具:
- https://github.com/eliorc/node2vec
- Node2Vec(graph, dimensions=64, walk_length=30, num_walks=200, workers=4)
- dimensions, embedding维数,默认为128
- walk_length,节点随机游走的步长,默认为80
- num_walks,每个节点随机游走次数,默认为10
- p,返回概率参数,默认为1
- q,出入概率参数,默认为1
- workers,并行线程,默认为1
- quiet,是否打印计算过程,默认为False,即输出计算过程
Node2Vec.fit(window=4, iter=20)
- window,窗口大小,表示当前词与预测词在一个句子中的最大距离
- iter,迭代次数
数据探索EDA
Project A:美国大学生足球队Embedding
# 数据加载,构造图 G = nx.read_gml('football.gml') # 初始化Node2Vec模型 model = Node2Vec(G, walk_length = 10, num_walks = 5, p = 0.25, q = 4, workers = 1) # 模型训练 result = model.fit(window=4, iter=20) # 得到节点的embedding print(result.wv.most_similar('EastCarolina')) embeddings = result.wv # 在二维空间中绘制所选节点的向量 def plot_nodes(word_list): X = [] for item in word_list: X.append(embeddings[item]) # 将100维向量减少到2维 pca = PCA(n_components=2) result = pca.fit_transform(X) # 绘制节点向量 plt.figure(figsize=(12,9)) # 创建一个散点图的投影 plt.scatter(result[:, 0], result[:, 1]) for i, word in enumerate(list(word_list)): plt.annotate(word, xy=(result[i, 0], result[i, 1])) plt.show() plot_nodes(result.wv.vocab)
Graph Embedding工具:
- https://github.com/shenweichen/GraphEmbedding (同样是DeepCTR作者)
- 包括多种Graph Embedding算法,Deep Walk, Node2Vec等
- DeepWalk
- from graphembedding.ge.models import DeepWalk
- Node2Vec
- from graphembedding.ge.models import Node2Vec
Project A:美国大学生足球队Embedding(DeepWalk)
from graphembedding.ge.models import DeepWalk # 数据加载,构造图 G = nx.read_gml('football.gml') # 初始化DeepWalk模型 model = DeepWalk(G, walk_length=10, num_walks=5, workers=1) # 模型训练 model.train(window_size=4, iter=20) # 得到节点的embedding embeddings = model.get_embeddings() # 在二维空间中绘制所选节点的向量 def plot_nodes(word_list): …… plot_nodes(model.w2v_model.wv.vocab)
Project A:美国大学生足球队Embedding(Node2Vec)
from graphembedding.ge.models import Node2Vec # 数据加载,构造图 G = nx.read_gml('football.gml') # 需要将Graph转换为DiGraph DG = nx.DiGraph() DG.add_nodes_from(G.nodes()) DG.add_edges_from(G.edges()) print(type(G)) print(type(DG)) print(len(DG)) # 初始化Node2Vec模型 model = Node2Vec(DG, walk_length = 10, num_walks = 5, p = 0.25, q = 4, workers = 1) # 模型训练 model.train(window_size=4, iter=20) # 得到节点的embedding embeddings = model.get_embeddings() # 在二维空间中绘制所选节点的向量 def plot_nodes(word_list): …… plot_nodes(model.w2v_model.wv.vocab)
Summary
Graph Embedding主要方法:
- factorization methods (图因式分解机)
- random walk techniques(随机游走)
- deep learning(深度学习)
- DeepWalk = Random Walk + Skip-gram
- Node2Vec,在DeepWalk基础上,通过超参数p和q条件节点周边的微观特性,宏观特性获取
- BFS,Breadth-first Sampling,倾向于在初始节点的周围游走,反映出一个节点的邻居的微观特性
- DFS,Depth-first Sampling,倾向于跑得离初始节点越来越远,反映出一个节点邻居的宏观特性
工具使用
- Networkx
- Word2Vec
- RandomWalk + Word2Vec
- Node2Vec
- Graph Embedding
Project:移动推荐系统
移动推荐系统
https://tianchi.aliyun.com/competition/entrance/231522/information
在真实的业务场景下,需要对所有商品的一个子集构建个性化推荐模型。在这个任务中,不仅需要利用用户在这个商品子集上的行为数据,还需要利用更丰富的用户行为数据:
目标是使用D来构造U中用户对P中商品的推荐模型
移动推荐系统
- 2万用户的完整行为数据以及百万级的商品信息
- 训练数据包含了抽样出来的一定量用户在一个月时间(11.18~12.18)之内的移动端行为数据(D),对应数据表tianchi_fresh_comp_train_user.csv
- 商品子集(P),数据表为tianchi_fresh_comp_train_item.csv
- 评分数据是用户在一个月之后的一天(12.19)对商品子集(P)的购买数据
移动推荐系统
- 使用训练数据建立推荐模型,并输出用户在接下来一天(12月19日)对商品子集(P)购买行为的预测结果
- 输出结果:tianchi_mobile_recommendation_predict.csv
- 评估指标(F1值)
精确度(两者之间的交集/ 预测的指标)
召回率
F1值 (既考虑了Precision又考虑了Recall)
PredictionSet为算法预测的购买数据集合
ReferenceSet为真实的答案购买数据集合
以F1值作为最终的唯一评测标准
数据预处理
- 用户购买行对于购买的影响会随着时间逐渐减弱,可以设置test day考察日一周以内的特征数据
- 可以将数据切分成多组
- train1: 11.22~11.27 -> 11.28
- train2: 11.29~12.04 -> 12.05
- train3: 12.06~12.10 -> 12.12
- train4: 12.13~12.18 -> 12.19
Thinking:为什么要考察12.19,12.12,12.05,11.28
- 因为12月19日是周五,所以我们test day也需要为周五
- 因为train3包括了双12(异常期,大促),可以将train3省略
- 最终将数据集划分为3组,分别进行训练和测试
- train1: 11.22~11.27 -> 11.28
- train2: 11.29~12.04 -> 12.05
- train3: 12.13~12.18 -> 12.19
chunksize使用:
- pandas使用chunksize分块处理大型csv文件
- chunksize,单个IO大小,设置越大站占用内存高,需要的iteration少,速度快
# 设置解析 dateparse = lambda dates: pd.datetime.strptime(dates, '%Y-%m-%d %H') for df in pd.read_csv(open(file_name, 'r'), parse_dates=['time'], index_col = ['time'], date_parser = dateparse, chunksize = 100000): # 如果想要追加文件的话,设置mode=a train1.to_csv(train1_file, columns=['user_id','item_id','behavior_type','item_category'], header=False, mode='a') 基于简单规则: 用户总是先放到购物车,然后进行购买 对应behavior_type = 3 到 behavior_type = 4 观察user_id, item_id, time_3, time_4 计算delta_hour = time_4 - time_3 可视化delta_hour
基于简单规则:
- Thinking:想要预测2014-12-19的购买情况,可以根据哪天的购物车来进行预测?
- To do:使用rule-based,及2014-12-18放到购物车里,还没有完成购物的,假设会在2014-12-19完成购物,提交结果
Summary
- 对于图像、语音、文本信息,这种一维、二维的矩阵表示的数据,有天然的维度对齐特性,即使不同的数据也可以对齐到同样的特征尺度和矩阵维度 => CNN 或者 RNN
- 现实世界有大量的非结构化数据,比如社交网络,知识图谱等,是非欧几里得数据,即每个节点可能有不一样的连接方式
- Embedding 是深度学习中的“基本操作”(包括 NLP/CV,搜索排序,推荐系统)
- Embedding 指的是用一个低维度向量表示一个实体,可以是一个词(Word2Vec),可以是一个物品(Item2Vec),也可以是网络关系中的节点(Graph Embedding)
- DeepWalk是Graph Embedding领域的开山之作,NodeVec在此基础上进行改进
Node2Vec在工业界很成功
- Facebook:广告领域定制化受众
- Tencent:微信朋友圈广告(Lookalike)策略
- Lookalike,相似人群扩展
- DMP是Look-alike技术的核心基础
Thinking1:什么是Graph Embedding,都有哪些算法模型
Thinking2:如何使用Graph Embedding在推荐系统,比如NetFlix 电影推荐,请说明简要的思路
Thinking3:数据探索EDA都有哪些常用的方法和工具
Action1:seealsology是个针对Wikipidea页面的语义分析工具,可以找到与指定页面相关的Wikipidea
seealsology-data.tsv 文件存储了Wikipidea页面的关系(Source, Target, Depth)
使用Graph Embedding对节点(Wikipidea)进行Embedding(DeepWalk或Node2Vec模型)
对Embedding进行可视化(使用PCA呈现在二维平面上)
找到和critical illness insurance相关的页面
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
2020-06-14 数据结构-05 |散列表-① | 映射| 集合
2020-06-14 数据结构-04 |栈 |队列