简介
对于影响力最大化问题,我以前写过两个blog
影响力最大化 IC模型+贪心算法
影响力最大化 模拟爆发(粗糙笔记)
但是,对于这两个方法都不是最优的:
- 对于IC模型
模型使用了贪心算法,然后遍历激活结点,每一次遍历将可能被激活的结点按照概率激活。然后选择影响力最大的组合。
对于我测试使用的邻接矩阵的大小是200*200的,也就是200个点的图,选出影响力最大的五个点的时间是13s左右。准确率比较高。
- 对于模拟爆发
模拟爆发只要设置足够多的模拟爆发次数就几乎可以得到最准确的影响力最大的五个点,但是缺点就是性能太差了,在实际的应用中根本不可能使用。
表现:
这个时间根本没法看。
废话不多说,IMRank绝对是我见过的影响力最大问题的最好方法,当然如果有更好的大家一定留言发我。这是我看到的一篇论文,本身没有代码,所以就自己实现了。可以说比 IC加贪心这个方法快了几百倍。
IMRank (边缘爆破)
IMRank,我干脆起个中文名字,叫边缘爆破,但是我还真不知道专业的怎么叫。我也没考证,管他呢,就这么叫了,什么是边缘爆破呢。
算法思路
这里我只说我自己的理解,借用论文中的一副图:
上图中的下角标是代表的当前的根据M的排名顺序,这个顺序是在不断地迭代中优化的。
实线表示存在传播概率,或者说传播概率不为零。
首先,总述一下算法,大致就是说,会为整个图的每一个结点得到一个M(边际影响力),然后根据边际影响力对所有点进行排序。通过不断优化这个排序,最终得到的排序顺序就是影响力最大的点的顺序,那么在我们一开始的要求下就只需要去除前五个点就可以了。
那么计算M其实是一个倒叙的方法,也就是从后往前推导,上图中的虚线表示扫描节点时传递影响分数的边缘。我们可以看到首先只有存在传播概率的(也就是图中存在实现的)才能存在边际影响力传递。但是v2和v3之间没有是因为2<3,所以不能传递。
定义M的计算公式:
优化迭代:
r表示根据M的排序,后面的实现中我用list存储。
效率分析
我们想一下为什么他这么快:
- 最重要的,只需要遍历一遍,这是我认为时间短的最重要的原因。
- 然后我觉得使用了动态规划的思想,每个结点存储的M是可以存储非邻居节点传过来的影响力的,这样大大减少了运算。
- 充分利用节点的等级与其基于等级的边际影响力扩散之间的相互作用,该框架有效地将任何初始等级调整为迭代式的自洽等级
- 论文评价:其可扩展性优于最新的启发式算法,同时其准确性可与贪婪算法相媲美
代码实现
import operator
import numpy as np
import copy
import time
data = np.loadtxt('graph.txt')
data = list(data)
def LFA(matrix):
n = len(matrix)
Mr = [1 for i in range(n)]
for i_ in range(1, n):
i = n - i_
for j in range(0, i + 1):
Mr[j] = Mr[j] + matrix[j][i] * Mr[i]
Mr[i] = (1 - matrix[j][i]) * Mr[i]
return Mr
def IMRank(matrix):
start = time.clock()
t = 0
r0 = [i for i in range(len(matrix))]
r = [0 for i in range(len(matrix))]
while(True):
t = t + 1
r = LFA(matrix)
r = np.argsort(-np.array(r))
if operator.eq(list(r0), list(r)):
break
r0 = copy.copy(r)
print('运行时间 : {}'.format(time.clock() - start))
print(r)
IMRank(data)
结果
可见,速度、正确性没得说。
大家共勉~~