README
using python 3
pip install -r requirements.txt
更新2.24
输出特定节点embedding相似度的分布图,在文件夹mypic5下,对应代码是emd_sim4.py
输出特定节点的pair出现次数分布图,在文件夹mypic6下,对应代码是pair_dis.py
更新信息
默认学习率改为0.001(原为0.01)
deepwalk的v_sample改为以度数为权重
部分结果已更新在exp1_5.xlsx上
最近的采样分布热力图在mypic2中,文件名带vc的是vcsample结果,dw是标准deepwalk结果
embedding的余弦相似度分布再mypic3文件夹下,文件名的数字是选取的点在度数排名(从小到大)的位置,不带数字的是整体的热力图。目前有标准deepwalk在email和cora的数据
vc-sampling
固定参数:
embedding维度128,训练epoch数20,一个epoch包含节点数是总数的50倍,batch size=1000,学习率0.01,负例是正例的5倍
模型调参
APP:停止概率 0.1, 0.15, 0.2, 0.25, 0.3(最大步数 80 固定)
deepwalk:window-size 2 4 6 8 10(另有LINE对应1)
评测可变参数
节点分类:训练集占比 0.1, 0.2, ..., 0.9
链接预测:删除的边占比 0.1, 0.3, 0.5, 0.7, 0.9
modularity:k-means的k值 2到30
详见vcsample文件夹下的readme
相关代码在vcsample文件夹下,现在主要是vctrainer.py和修改过的app.py,以及有点问题的deepwalk.py
vctrainer是训练的框架,调用model_v的sample_v(batch_size)和model_c的sample_c(h)产生vc对,用tensorflow训练。negative sampling的实现也在这个代码里面。
sample_v是采样“中心点”的generator,生成一个epoch的各个batch,通过yield语句每次输出一个batch的v。sample_c函数的参数是sample_v输出的所有“中心点”,它根据v采样context,得到context序列并输出。输出的都是lookup之后的标号,不是原图的标号。
对app而言,sample_v就是随机打乱节点顺序,然后每个节点依次取sample个,取满batch_size就yield,直到取完;sample_c就是遍历输入的序列,对每个中心点,从它出发以一定概率停止地走不超过10步,输出停止的节点lookup的标号。在email和cora上的结果不如原来的deepwalk,比原来的LINE好
关于deepwalk,我现在想先用pagerank计算平稳分布,再建立一个固定大小的列表(点数的fac倍大小),使得节点在列表的出现次数和pagerank值成正比,在sample_v中对列表做一遍random shuffle,然后依次取;采样context的时候,我想从中心点随机游走window步,将路径上的点都加入context。(实际操作的时候,记录了每个中心点对应的已走步数和当前位置,这样可以不受batch“隔断”的影响)。不过在email上的运行结果比LINE差,在Cora上的结果比APP稍差、比LINE好,不知道是不是哪里有问题。。
热力图
热力图:第i行第j列的色块对应vertex i和context j的出现次数,次数过大的做了最大值限制。i和j的数值是相应节点的度数从小到大的排名(相当于将节点按度数从小到大排了序),超过5000个点则把所有点排名乘5000除以点数取整,以保证复杂度不会过大。现有email, cora, blogcatalog在deepwalk, lpwalk, app上的结果,node2vec做了email上grid search 0.25, 1.0, 4.0,在mypic文件夹下。
相关代码:nesample/trainer在得到所有sample之后按每行“v c weight”格式输出到aaa.txt然后退出;pic.py读取sample信息和度数排序、绘制热力图;zrun_nesampler.bat是它的批处理文件。
Changes to OpenNE
增加了MH-Walk
修改__main__.py使得LINE不会在每个epoch之后都做test,只在最后做一次
增加了lpWalk
增加了APP
其中,默认iters=200, sample=200,按原代码实际的采样个数是node_num x iters x sample,batch_size = 1, epoch = 1, 时间开销非常大。
一方面,仅仅是采样的复杂度就已经远大于其他算法了,比如deepwalk是node_num x num_paths x walk_length,而它的num_paths和walk_length都比较小(10, 80),所以我想在APP里面也把参数调小一点。
另一方面,原代码每一步都做更新,但是在点数很多的时候,会导致非常大的更新次数。所以,除非不用tensorflow做训练,否则大概很难有效地复现APP算法。不知调大batch_size对结果会有怎样的影响。我试过batch_size=1000, epoch=10和batch_size=100, epoch=1,结果差不多
除上述差异外,原代码的学习率衰减在这里没有实现。
当前参数:iters=10, sample=50, batch_size=1000, epoch=10, learning_rate=0.001(adam) 其他参数按原代码:停止概率jump_factor=0.15, 最大步数step=10, negative_ratio=5
修复bug后,表现比deepwalk稍差,比line稍好,详见表格。
nesampler
修改了__main__.py, line.py, node2vec.py,增加了trainer.py
trainer是根据line的二阶部分修改而成的,根据权重建立alias表,生成负采样表,做mini-batch梯度下降
line只保留了二阶部分,直接调用trainer
node2vec包含了deepwalk和node2vec算法,先调用walker(未改动)采样路径,再用myparser函数生成samples,最后调用trainer。
问题1:myparser有两种方式:
-
每个点对都按权重1.0加入samples
-
统计点对出现次数作为权重
不确定哪一种方式更好。当前采用第二种,否则点对数量可能过大。
问题2:细节问题,点对是否可以包含(v, v)这样自己到自己的点对?当前没有包含。
修改:现在就是按照skipgram的算法,对于窗格内除了中心点之外的点,都加进点对。
问题3:使用trainer,在email数据集上表现和原来差不多(不论parser是哪种方式),但是在cora和blogcatalog上表现很差。
尝试1:修改optimizer。原先是adam,考虑改成SGD,结果在email上都不收敛了(loss基本不变,分类效果非常差)
尝试2:调整学习率。没找到更好的学习率。
尝试3:取消batch的随机化,调整negative_ratio。似乎影响不大
尝试4:修改batch_size。没有提升cora上的效果。
尝试5:修改epoch数。即使在loss基本稳定的情况下,也基本没有提升cora上的效果。
尝试6:怀疑log_sigmoid出现NAN,做clip_by_value使得log的参数在1e-81.0的范围(原本是0.01.0)。结果没有明显变化。
尝试7:修改loss为nce_loss……结果很差。
现在使用adam, lr=0.001, batch_size=1000, batch有random, 5个epoch(main的默认),有clip_by_value,loss仍然是log_sigmoid
修复bug:原先少了一个look_up。节点在graph的编号从0开始,但节点名称可能从1开始,所以需要look_up。
email数据集的节点名称从0开始,所以表现正常;cora从1开始,所以出现了问题。
现已修复。表现见表格。
Other files
myresult是存放embedding结果和其他输出信息(info)的
mydata里面是数据集,包括edge, label, degreeRank(度数排序), info(基本信息), partinfo(连通性),以及相关代码
mytest2是存放5次取平均的测试结果的
mycla是5次取平均的代码,含度数分段
combiner是把node2vec的grid search结果整合到一起的代码