赞
踩
数学上图论最早起源于哥尼斯堡七桥问题。
**main question: **如何充分的利用节点之间的连接,利用关系结构进行更好地数据挖掘、数据分析?——即如何对图数据进行数据挖掘。
把图神经网络看成一个黑箱,Input为Network,Output可以为Node labels, New links, Generated graphs and subgraphs。
实现端到端表示学习representation learning ,类似CNN的automatically learn the features。就是把节点变成d维向量的过程。
所谓的端到端就是不需要人工去干涉,不需要人工去辅助,自己学到关键的特征。
专门用来存储索引、推理图数据的数据库。
许多应用
例如导航从一个点到另一个点,可利用图来预计到达的时间。
Nodes:Road segments
Edges:Connectivity between road segments
Prediction:Time of Arrival(ETA)
图是最优质的长期资产。网络效应是一个企业最深的护城河。
如何设计本体图,取决于将来想解决什么问题。
可以用node degree表示其连接数,侧面反映一个节点的重要度。
无向图邻接矩阵为对称矩阵。主对角线为0
有向图为非对称矩阵。主对角线为0
为什么把图表示为矩阵的形式:
各种工具解决的都是矩阵运算的问题,加速的就是矩阵运算,把图表示成矩阵的形式,就是翻译成计算机能理解的。
图形数据结构可用以下表示形式:
大多数的网络的邻接矩阵是稀疏的。
连接列表只记录存在连接的节点对。连接表关心数据中的head和tail
邻接列表,把所有和该节点相关的都记下来。
例如:三国演义中任务关系的连接表和邻接表的示意:
connected graph/disconnected graph
强连通图:任意两个节点可以到达
弱连通图
强连通域,strongly connected components(SCCs)
六度空间理论:全世界任意两个人可以通过不超过六个中间人相互认识,可以跨越时间。
人工设计一些特征,进行编码低维向量。
例如一个银行的风控系统,每个节点是一个用户,节点有两种特征:
给定 G = ( V , E ) G = (V,E) G=(V,E),学习 f : V − > R f : V -> R f:V−>R,输入某个节点的D维向量,输出该节点是某类的概率。
例如半监督节点分类问题。
对每个节点构造特征:
即通过已知连接补全未知连接。
两种:
link-level features:
S = ∑ i = 1 ∞ β i A i = ( I − β A ) − 1 − I S = \sum^{\infty}_{i=1} \beta^{i}A^{i} = (I - \beta A)^{-1} - I S=i=1∑∞βiAi=(I−βA)−1−I
把整张图变成一个D维的向量,特征应能反应全图的特征。
weisfeiler-lehman kernel,使用颜色微调的方法,迭代的丰富节点词库。
例如:给定的两个图,先assign initial colors,经过gggregate neighboring colors,再把每一种颜色用不同数字代替,得到hash aggregated colors。
经过k步表示捕捉了全图中k跳的连接。计算量是非常高效的。
把两张图的向量作数量积得到一个标量的方法称为kernel method,在传统图机器学习中用的很多。
空手道俱乐部数据集
G = nx.karate_club_graph()
nx.draw(G, with_labels=True)
雨果《悲惨世界》人物关系
G = nx.les_miserables_graph()
plt.figure(figsize=(12,10))
pos = nx.spring_layout(G, seed=10) # 可设置一个布局
nx.draw(G, pos, with_labels=True)
数据来源:OpenKG-四大名著人物关系知识图谱和OWL本体
读取数据,利用zip创建边/连接,然后创建图:
df = pd.read_csv('triples.csv')
print(df.head())
# 构建连接
G = nx.DiGraph()
edges = [edge for edge in zip(df['head'], df['tail'])]
G.add_edges_from(edges)
G.edges('关羽')
节点可以为任意可哈希的对象,比如字符串、图像、XML对象,甚至另一个Graph、自定义的节点对象。
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_edge(1,2)
G.add_edge(1,3)
G.add_edge(1,5)
G.add_edge(2,3)
G.add_edge(3,4)
G.add_edge(4,5)
nx.draw(G, with_labels=True)
如图
设置坐标:
pos = {1:(0,0), 2:(-1,0.3), 3:(2,0.17), 4:(4,0.225), 5:(5,0.03)}
options = {
"font_size": 36,
"node_size": 3000,
"node_color": "white",
"edgecolors": "black",
"linewidths": 5,
"width" :5,
}
nx.draw_networkx(G, pos, **options)
ax = plt.gca()
ax.margins(0.20)
plt.axis("off")
plt.show()
如图:
pagerank = nx.pagerank(G, alpha=0.8) # 只对有向图有效,会自动把无向图转成双向图
自监督表示学习方法进行嵌入。
d维向量要充分的反应在原图中的结构信息等。
如何把节点映射成D维向量?
研究对象:
传统图机器学习需要人工进行特征工程。
表示学习:自动学习特征,将各模态转为向量。
将节点映射为d维向量,则该向量是低维的连续的稠密的,与下游任务无关的。
理解嵌入d维空间,相当于把一个节点嵌入到d空间的一个点。而且d维空间向量的相似度反映了原图中节点相似度。例如下图所示:
假设图G,V是节点集,A是邻接矩阵,仅利用节点连接信息,没有节点属性信息的情况。
编码器:输入节点,输出节点的向量。
解码器:假设两个节点经过编码后得到两个向量
z
u
,
z
v
z_{u}, z_{v}
zu,zv,这两个向量的点乘数值(即余弦相似度)能够反映节点的相似度。
如果两个节点有连接,计算出来的相似度可能就是1或者向量是平行的或是同一个向量或是共线的。
可以自己定义相似:本节中我们使用random walks,即随机游走采样得到一个节点序列,如果两个节点共同出现在这个序列中,则认为这两个向量是相似的。
这里的shallow encoding相对于深编码器的,
最简单就是查表,即把所有节点的d维向量写在一个矩阵里,例如下图中的
Z
Z
Z,一个5维的6个节点,然后乘以
v
v
v,
v
v
v是一个one-hot,取出某一个节点的嵌入向量。
我们的目标是:maximize
z
v
T
z
u
z_{v}^{T}z_{u}
zvTzu for node pairs (u, v) that are similar。
虽然没有针对某种特定的下游任务,但是可以用于下游任务当中。
随机游走就是字面意思,可以自己指定随机游走的策略。
图和NLP的认知对比,加深理解:
如何计算从
u
u
u节点出发的随机游走序列经过
v
v
v节点的概率?——使用非线性函数,softmax。
这里判定节点相似性的定义是共同出现在同一个随机游走序列。
步骤:
在deepwalk完全随机游走的基础上,增加p,q参数,实现有偏的二阶随机游走。
node2vec algorithm:
也有其他随机游走的方法:LINE方法
矩阵分解,假设两个向量相似,则点积后为1,不相似则点积后为0,例如下图中
Z
T
Z^{T}
ZT的第二行和
Z
Z
Z的第四列,如果两个相乘为1,如蓝色所示,则表明第二个节点和第四个节点是相似的(两节点相连)。
目标是:
m
i
n
z
∣
∣
A
−
Z
T
Z
∣
∣
min_{z} || A - Z^{T}Z ||
minz∣∣A−ZTZ∣∣
全图嵌入或者子图嵌入。
anonymous walks:每次见到不同节点,就发一个新编号。(认号不认人)
采样出不同匿名随机游走序列的个数,可以作为全图的向量。
例如:3个节点,匿名采样序列有五种,111,112,122,123
采样多少次?
匿名随机游走长度固定时,要使误差大于
ϵ
\epsilon
ϵ 的概率小于
δ
\delta
δ需要采样m次,其中
m
=
⌈
2
ϵ
2
(
l
o
g
(
2
n
−
2
)
−
l
o
g
(
δ
)
)
⌉
m = \lceil \frac{2}{\epsilon^{2}}(log(2^{n} - 2)- log(\delta))\rceil
m=⌈ϵ22(log(2n−2)−log(δ))⌉
后面还会介绍到分层聚类。
论文链接:DeepWalk: Online Learning of Social Representations
解决图嵌入问题,把图节点转成d维向量。后续就可以在嵌入的向量空间中进行任务,例如分类。
计算机认识向量,把事物表示成向量。
图机器学习第一步就是提取特征:
了解语言模型。
核心idea:short random walks = sentences
deepwalk步骤:
在线学习,把新增的节点和关系构建出随机游走序列,增量学习,迭代更新到原有模型中
可以参考B站精读。
还列出了一些参考:
deepwalk
网络数据化时期DeepWalk,随后又有了LINE、Node2Vec、NetMF、NetSMF等
GraphSAGE 使用多层聚合函数,每一层聚合函数会将节点及其邻居的信息聚合在一起得到下一层的特征向量,GraphSAGE 采用了节点的邻域信息,不依赖于全局的图结构。
视频中介绍了一个自动爬虫网站。
先导入一些必要的包:
import networkx as nx
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import random
from tqdm import tqdm # 进度条
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号
然后进行读入数据,查看数据数量:
# 读取数据
df = pd.read_csv('seealsology-data.tsv', sep = '\t')
print(df.head())
显示为:(13211,3)
然后定义生成随机游走序列的函数:
# 生成随机游走的节点序列的函数 def get_randomwalk(node, path_length): ''' 输入起始节点和路径长度,生成随机游走节点序列 :param node: :param path_length: :return: ''' random_walk = [node] for i in range(path_length - 1): temp = list(G.neighbors(node)) # 该节点的邻域节点列表 temp = list(set(temp) - set(random_walk)) # 减去random中已有的 if len(temp) ==0: break # 然后再从邻接节点中选择下一个节点 random_node = random.choice(temp) # 随机选择一个节点 random_walk.append(random_node) node = random_node return random_walk
然后查看图中节点名称,
# 查看图中节点个数
all_nodes = list(G.nodes())
all_nodes
以random forest节点出发,生成一个长为5的序列
# 以random forest节点为起始节点,走5步
get_randomwalk('random forest', 5)
输出为:
[‘random forest’,
‘bootstrap aggregating’,
‘out-of-bag error’,
‘cross-validation (statistics)’,
‘model selection’]
下面批量生成游走序列,
gamma = 10 # 表明每个节点作为起始节点生成随机游走序列个数
walk_length = 5 # 序列长度
random_walks = []
for n in tqdm(all_nodes): # 遍历每个节点
for i in range(gamma):
random_walks.append(get_randomwalk(n, walk_length))
然后建立模型进行训练
# 训练deepwalk,其实就是word2vec from gensim.models import Word2Vec model = Word2Vec( vector_size=256,# embedding维数 window=4, # 窗口宽度 sg = 1, # skip-gram hs = 0, # 不加分层softmax negative=10, # 负采样, alpha=0.03, # 初始学习率 min_alpha=0.0007, # 最小学习率 seed= 14 ) # 构建词汇表 model.build_vocab(random_walks, progress_per=2) # 训练 model.train(random_walks, total_examples=model.corpus_count, epochs=50, report_delay=1)
训练完成后返回:(16572157, 16576750)
然后就可以查看每一个节点deepwalk之后的embedding。
例如查看random forest节点,
model.wv.get_vector('random forest')
结果如图所示:
可以看到每一维度都是一个实数,是低维连续稠密的向量。
继续使用PCA进行降维
# 使用PCA降维,降到2维
X = model.wv.vectors
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
embed_2d = pca.fit_transform(X)
embed_2d.shape
然后绘制
# 绘制
plt.figure(figsize=(14,14))
plt.scatter(embed_2d[:,0], embed_2d[:,1])
plt.show()
如图所示
举例,可视化某个词条的二维embedding
term = 'computer vision'
term_256d = model.wv[term].reshape(1,-1) # 从model中取出的是256维的
term_256d.shape
输出:(1,256)
再把该节点的向量映射到2维的,然后在图中表示出来
term_2d = pca.transform(term_256d)
# 映射到二维的
print(term_2d)
plt.figure(figsize=(14,14))
plt.scatter(embed_2d[:,0], embed_2d[:,1])
plt.scatter(term_2d[:,0], term_2d[:,1], c= 'r', s = 200)
plt.show()
如图所示:
可视化一些词条的二维embedding
如下:
# 可视化某些词条的二维
pagerank = nx.pagerank(G)
node_importance = sorted(pagerank.items(), key=lambda x:x[1], reverse=True)
# 取最高的前n个点
n = 30
terms_chosen = []
for each in node_importance[:n]:
terms_chosen.append(each[0])
# 再手动补充一些节点
terms_chosen.extend(['computer vision','deep learning','convolutional neural network','convolution','natural-language processing','attention (machine learning)','support-vector machine','decision tree','random forest','computational imaging','machine vision','cognitive science','neuroscience','psychophysics','brain','visual cortex','visual neuroscience','cognitive model','finite difference','finite difference time domain','finite difference coefficients','finite difference methods for option pricing','iso 128','iso 10303'])
print(terms_chosen)
再绘制
# 得到索引
term2index = model.wv.key_to_index
plt.figure(figsize=(14,14))
plt.scatter(embed_2d[:,0], embed_2d[:,1])
for item in terms_chosen:
idx = term2index[item]
plt.scatter(embed_2d[idx, 0], embed_2d[idx, 1], c='r',s = 50 )
plt.annotate(item ,xy=(embed_2d[idx,0],embed_2d[idx, 1]), c= 'k', fontsize=12)
plt.show()
如图:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。