graph --- > Graph embedding (一)

本文介绍了图表示学习的概念,通过将图转化为结构化数据以适应机器学习算法。DeepWalk是最早应用随机游走和Word2Vec技术的算法之一,Line则通过一阶和二阶相似度明确学习目标。Node2Vec通过调整参数在广度优先搜索和深度优先搜索之间取得平衡。此外,文章还提到了GraRep和TADW等方法,GraRep通过矩阵分解学习多阶关系,TADW结合内容信息进行网络表示学习。这些方法在大规模网络数据的分析和应用中具有重要意义。
摘要由CSDN通过智能技术生成

背景

目前很多机器学习算法都是针对于结构化数据,即每个样本的特征数都固定,这样可将数据按照预定的模式去学习,但也有不少学习场景中,还存在大量的关联性数据,如用户的购买赠送行为,用户的社交关系等等,这些数据很难直接应用目前的算法。
Graph representations 学习是一种通过图来学习节点表示向量的方法,通过将其转化为结构化的数据,进而应用我们已有的大量学习算法进行学习。首先将深度学习应用在图表示学习中的是DeepWalk,利用随机游走生成序列,然后利用类似Word2vec的技术,将其转化为向量,后面又出现Line,Node2Vec等大量的学习方法。

DeepWalk

当我们构建好关联图后,迭代每一个节点,随机游走,采样固定长度的序列,比如5,如图所示:

将采集到的这些序列使用Word2Vec的技术,如CBOW或Skip-Gram,为每个节点训练得到一个节点向量;论文里作者使用SkipGram, 以及Hierarchical Softmax(算法复杂度由O(|V|)到O(log|V|)),以及SGD进行求解。
该方法还以进行在线学习,并行化,应用于网络分类,异常检测等

算法流程如下:

其他:

  1. 在node2vec提到,使用Hierarchical softmax相比于negative sampling并不有效。
  2. Line中提到其没有明确的目标函数,能够清楚知道什么网络属性被保留下来。
  3. DeepWalk适用于无权网络

Line

相比于DeepWalk,Line定义了明确的学习函数,同时考虑了一阶相似度和二阶相似度。

优势:

  • 更具扩展性: 无向,有向图,或者权重图
  • 一阶学习local网络结构,二阶学习到更global结构,如6和7:一阶代表两者相连,二阶代表具有相同朋友的节点往往也具有某种相似性,如5和6。

优化目标

对于一阶:
节点 v i v_i vi v j v_j vj之间的联合概率分布 p 1 ( v i , v j ) p_1(v_i, v_j) p1(vi,vj)与其经验分布 p ^ 1 ( v i , v j ) \hat p_1(v_i, v_j) p^1(vi,vj)的差距最小,即设KL散度目标最小
O 1 = d ( p ^ 1 ( ⋅ , ⋅ ) , p 1 ( ⋅ , ⋅ ) ) O_1 = d(\hat p_1(\cdot, \cdot), p_1(\cdot, \cdot)) O1=d(p^1(,),p1(,))
其中 p ^ 1 ( v i , v j ) = w i j ∑ ( i , j ) ∈ E w i j \hat p_1(v_i, v_j) = \frac{w_{ij}}{\sum\limits_{(i,j)\in E}w_{ij}} p^1(vi,vj)=(i,j)Ewijwij p 1 ( v i , v j ) = 1 1 + e x p ( − u → i T ⋅ u → j ) p_1(v_i, v_j)=\frac{1}{1+exp(-\overrightarrow u_i^T \cdot \overrightarrow u_j)} p1(vi,vj)=1+exp(u iTu j)1,其中 u → i \overrightarrow u_i u i为节点 v i v_i vi的向量表示。

继续化简 O 1 O_1 O1,得到:
O 1 = − ∑ ( i , j ) ∈ E w i j l o g p 1 ( ( v i , v j ) ) O_1 = - \sum\limits_{(i,j)\in E }w_{ij} log p_1((v_i, v_j)) O1=(i,j)Ewijlogp1((vi,vj))

对于二阶:

直接写成目标函数
O 2 = − ∑ ( i , j ) ∈ E w i j l o g p 2 ( v j ∣ v i ) O_2 = -\sum\limits_{(i,j)\in E} w_{ij}log p_2(v_j|v_i) O2=(i,j)Ewijlogp2(vjvi)

代码部分
注:在实现上,为每个节点生成两个向量:

作者:浅梦
链接:https://zhuanlan.zhihu.com/p/56478167
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

ef line_loss(y_true, y_pred):
    return -K.mean(K.log(K.sigmoid(y_true*y_pred)))

def create_model(numNodes, embedding_size, order='second'):

    v_i = Input(shape=(1,))
    v_j = Input(shape=(1,))

    first_emb = Embedding(numNodes, embedding_size, name='first_emb')
    second_emb = Embedding(numNodes, embedding_size, name='second_emb')
    context_emb = Embedding(numNodes, embedding_size, name='context_emb')

    v_i_emb = first_emb(v_i)
    v_j_emb = first_emb(v_j)

    v_i_emb_second = second_emb(v_i)
    v_j_context_emb = context_emb(v_j)

    first = Lambda(lambda x: tf.reduce_sum(
        x[0]*x[1], axis=-1, keep_dims=False), name='first_order')([v_i_emb, v_j_emb])
    second = Lambda(lambda x: tf.reduce_sum(
        x[0]*x[1], axis=-1, keep_dims=False), name='second_order')([v_i_emb_second, v_j_context_emb])

    if order == 'first':
        output_list = [first]
    elif order == 'second':
        output_list = [second]
    else:
        output_list = [first, second]

    model = Model(inputs=[v_i, v_j], outputs=output_list)
    

其他:

  • 采用了Negative sampling
  • Alias sampling
    时间复杂度为O(1)的抽样算法,普通的算法为O(N)或者为O(logN), Alias 通过维护两个数组,达到采样时间复杂度为O(1)。用于离散数据的采样。

alias sampling

=>乘以 N

=>前两个多出来的部分补到后面两个缺失的部分中,但Alias Method一定要保证:每列中最多只放两个事件,所以此时需要讲1中的补满3中去:


=>

  1. 将整个概率拉平1*N的长方形 Alias Table,构建上述图,储存两个数组,
    一个是i列对于的面积百分比即 p r o b = [ 2 3 , 1 , 1 3 , 1 3 ] prob =[\frac23,1,\frac13,\frac13] prob=[32,1,31,31
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Molecular-graph-BERT 是一种基于图神经网络的化学分子表示方法,可用于分子性质预测、分子设计等应用。以下是 Molecular-graph-BERT 的代码实现。 1. 安装依赖 ```python !pip install torch !pip install dgl !pip install rdkit ``` 2. 数据预处理 ```python import dgl from rdkit import Chem from dgl.data.utils import load_graphs, save_graphs from dgl.data.chem.utils import smiles_to_bigraph, CanonicalAtomFeaturizer # 将 SMILES 序列转换为 DGLGraph def graph_from_smiles(smiles): mol = Chem.MolFromSmiles(smiles) return smiles_to_bigraph(smiles, atom_featurizer=CanonicalAtomFeaturizer()) # 读取数据,并将 SMILES 序列转换为 DGLGraph data = [] with open('data.txt', 'r') as f: for line in f: smiles, label = line.strip().split('\t') g = graph_from_smiles(smiles) label = int(label) data.append((g, label)) # 将 DGLGraph 序列化并保存为二进制文件 save_graphs('data.bin', data) ``` 3. 定义模型 ```python import torch import torch.nn as nn import dgl.function as fn # 定义 GraphConvLayer class GraphConvLayer(nn.Module): def __init__(self, in_feats, out_feats): super(GraphConvLayer, self).__init__() self.linear = nn.Linear(in_feats, out_feats) self.activation = nn.ReLU() def forward(self, g, features): with g.local_scope(): g.ndata['h'] = features g.update_all(fn.copy_u('h', 'm'), fn.sum('m', 'neigh')) h_neigh = g.ndata['neigh'] h = self.linear(features + h_neigh) h = self.activation(h) return h # 定义 MolecularGraphBERT 模型 class MolecularGraphBERT(nn.Module): def __init__(self, hidden_size, num_layers): super(MolecularGraphBERT, self).__init__() self.embed = nn.Embedding(100, hidden_size) self.layers = nn.ModuleList([GraphConvLayer(hidden_size, hidden_size) for _ in range(num_layers)]) self.pool = dgl.nn.pytorch.glob.max_pool def forward(self, g): h = self.embed(g.ndata['feat']) for layer in self.layers: h = layer(g, h) g.ndata['h'] = h hg = self.pool(g, g.ndata['h']) return hg ``` 4. 训练模型 ```python from torch.utils.data import DataLoader from dgl.data.utils import load_graphs # 加载数据 data, _ = load_graphs('data.bin') labels = torch.tensor([d[1] for d in data]) # 划分训练集和测试集 train_data, test_data = data[:80], data[80:] train_labels, test_labels = labels[:80], labels[80:] # 定义训练参数 lr = 0.01 num_epochs = 50 hidden_size = 128 num_layers = 3 # 定义模型和优化器 model = MolecularGraphBERT(hidden_size, num_layers) optimizer = torch.optim.Adam(model.parameters(), lr=lr) # 训练模型 for epoch in range(num_epochs): model.train() for i, (g, label) in enumerate(train_data): pred = model(g) loss = nn.functional.binary_cross_entropy_with_logits(pred, label.unsqueeze(0).float()) optimizer.zero_grad() loss.backward() optimizer.step() model.eval() with torch.no_grad(): train_acc = 0 for g, label in train_data: pred = model(g) train_acc += ((pred > 0).long() == label).sum().item() train_acc /= len(train_data) test_acc = 0 for g, label in test_data: pred = model(g) test_acc += ((pred > 0).long() == label).sum().item() test_acc /= len(test_data) print('Epoch {:d} | Train Acc {:.4f} | Test Acc {:.4f}'.format(epoch, train_acc, test_acc)) ``` 以上就是 Molecular-graph-BERT 的代码实现。需要注意的是,由于 Molecular-graph-BERT 是基于图神经网络的方法,需要使用 DGL 库来构建和操作图数据,因此需要先安装 DGL 库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值