資料探勘 - 如何用python實現《多重社群網路的影響力最大化問題分析》中的演算法?
PHP中文网
PHP中文网 2017-05-18 10:58:59
0
1
768

身為python小白,導師讓我用python實作論文中的演算法,對於其中所要求的技術點以及如何實作演算法顯得一頭霧水。目前python過完廖老師的python教程,正在看networkx文件。
望各位幫我解決以下問題:
1.實作演算法所要求技術點
2.如何應對此類論文
3.資料探勘方向學習建議

論文網址 : http://cjc.ict.ac.cn/online/o...

PHP中文网
PHP中文网

认证高级PHP讲师

全部回覆(1)
黄舟

經過一周,現已初步完成,其中多出代碼不夠美觀以及效率不高,還請指點

# _*_ coding:utf-8 _*_
# ==================================================================================
#
#       Description:  Influence Maximization on Multiple Social Networks
#
# ==================================================================================
import matplotlib.pyplot as plt  
import networkx as nx
import heapq


#总图
G = nx.DiGraph()

def load_graph(file):
    '''
    加载文件为列表格式,并得到G,画出图结构  
    '''
    
    #将总列表设成全局格式
    global  gllist
    
    #迭代文件中每个元素
    with open(file) as f:
        lines = f.readlines()
    mylist = [line.strip().split() for line in lines]
    
    gllist = []
    #将字符串型转换为整型
    for i in mylist:
        gllist.append(i[:-2]+map(lambda x: float(x), i[-2:]))
    print '初始全局列表:'
    print gllist

    drawlist=[]
    #提取二维列表mylist每行前三个元素,赋给新的列表drawlist
    for i in range(len(mylist)):
        drawlist.append([])
        for j in range(3):
            drawlist[i].append(mylist[i][j])
    #将列表drawlist加载为有向加权图
    G.add_weighted_edges_from(drawlist)
    nx.draw(G, with_labels=True, width=1, node_color='y', edge_color='b')
    plt.show()
    print 'G图中所有节点:',G.nodes()
    print 'G图中所有边:',G.edges()
    print '\n'


def get_self_node(gllist, target=None):
    '''
    获取目标节点的自传播节点,返回selflist并包含目标节点
    '''
    #初始化自传播节点列表
    selflist = [target]
    
    #存放已传播节点列表
    haslist = []
    
    flag = 0
    
    while (flag != 0):       
        flag = 0       
        for target in selflist:
            if target not in haslist:
                for i in range(len(gllist)):
                    #判断二维列表中,每行第三个元素是否为1,若为1,则为自传播节点
                    if ((gllist[i][0] == target)or(gllist[i][1]==target))and(gllist[i][3]==1.0):
                        if gllist[i][0] == target:
                            if gllist[i][1] not in haslist:
                                selflist.append(gllist[i][1])
                                haslist.append(gllist[i][1])
                                flag += 1
                        else:
                            if gllist[i][0] not in haslist:
                                selflist.append(gllist[i][0])
                                haslist.append(gllist[i][0])
                                flag += 1
                #去除重复元素
                haslist = set(haslist)        
            selflist = set(selflist)    

    #去除重复元素
    selflist = set(selflist)
    return selflist


def longest_path(gllist,source=None,target=None):
    '''
    获取起始点到实体的最大路径集合,返回为longestpath列表
    '''
    longestpath = []
    newlist = []
    for i in range(len(gllist)):
        newlist.append([])
        for j in range(3):
            newlist[i].append(gllist[i][j])
    #构建图结构
    G1 = nx.DiGraph()
    #添加带权有向边
    G1.add_weighted_edges_from(newlist)
    #获取目标节点的所有自传播街边,并存入selflist中
    selflist = get_self_node(gllist, target)
    max_path = 0
    val_path = 1
    #获取初始节点到目标节点及目标节点的自传播节点的最大路径
    for v in selflist:
        if v != source:
            #遍历两点之间所有路径,并进行比对
            for path in nx.all_simple_paths(G1,source=source,target=v):
                #判断路径后两个元素是否为相同实体(如:b1->b2)
                if is_self_transmit_node(path[-2], v) == 0: 
                    for i in range(0, len(path)-1):
                        val_path *= G1.get_edge_data(path[i], path[i+1])['weight']
                    if max_path < val_path:
                        max_path = val_path
                    val_path = 1
        #若目标节点为起始节点则直接跳出
        else: continue  ############ 有待商榷 ##############
        longestpath.append(max_path)
    #返回初始节点到实体的最大路径
    return longestpath


def is_self_transmit_node(u, v):
    '''
    判断目标节点不为起始节点的自传播点
    '''
    flag = 0
    #获得起始节点的所有自传播点
    selflist = get_self_node(gllist, v)
    for x in selflist:
        if u == x:
            flag = 1
    return flag


def single_strong_infl(longestpath):
    '''
    计算起始点到实体的传播概率(影响强度),返回影响强度stronginfl
    '''
    temp = 1
    for x in longestpath:
        temp *= 1-x
    stronginfl = 1-temp
    return stronginfl


def all_strong_infl(G):
    '''
    获得每个节点对实体的影响概率
    '''
    allstrong = [] #初始化所有节点的加权影响范围列表
    gnodes = [] #初始化节点列表
    tempnodes = [] #初始化临时节点列表
    
    gnodes = G.nodes()
    
    for u in gnodes:        
        strong = 0 #存储初始节点对每个实体的影响范围加权,初始化为0       
        #重置临时节点列表
        tempnodes = G.nodes()
        for v in tempnodes:
            #非自身节点
            if u != v:     
                #判断目标节点不为起始节点的自传播点
                if is_self_transmit_node(v, u) == 0:
                    #获取起始节点到实体间最大加权路径,并存入longestpath
                    longestpath = longest_path(gllist, u, v)
                    
                    #去除已遍历目标节点的所有自传播节点
                    renode = get_self_node(gllist, v)
                    for x in renode:
                        if x != v:
                            tempnodes.remove(x)

                    #计算起始节点到实体间传播概率(影响强度)
                    stronginfl = single_strong_infl(longestpath)
                    strong += stronginfl 

        #添加单个节点到所有实体的加权影响范围      
        allstrong.append([u, round(strong, 2)])
    
    #返回每个节点到所有实体的加权影响范围
    return allstrong
    #output allstrong : [['a1', 2.48], ['a2', 1.6880000000000002], ['b1', 0.7], ['b2', 0], ['c1', 0], ['d2', 0.6]]


def uS_e_uppergain(u, ev, S):
    '''
    获取节点u在集合S的基础上对实体ev的影响增益, 传入候选节点,上界gain(u|S, ev)
    '''
    
    #获取目前实体的所有自传播节点
    selflist = get_self_node(gllist, ev)
    stronglist = []
    #遍历自传遍节点
    for v in selflist:
        '''
        判断节点v是否存在种子集合S中
        其中v为单个节点,如v(ev, Gi)
        S为种子节点集合,如['a1','a2','b1','b2','c1','d2']
        '''
        if v in S:
            ppSv = 1
        else:
            longestpath = []
            #遍历种子集合
            for s in S:

                #初始化路径权值与最大路径权值
                val_path = 1
                max_path = 0

                #遍历两点之间所有路径,并进行比对
                for path in nx.all_simple_paths(G,source=s,target=v):
                    #判断路径后两个元素是否为相同实体(如:b1->b2)
                    if is_self_transmit_node(path[-2], v) == 0: 
                        for i in range(0, len(path)-1):
                            val_path *= G.get_edge_data(path[i], path[i+1])['weight']
                        if max_path < val_path:
                            max_path = val_path
                        #重置路径权值为1
                        val_path = 1
                #将最大加权路径存入longestpath列表
                longestpath.append(max_path)
            #得到上界pp(S,v)的影响概率,上界pp(S,v)
            ppSv = single_strong_infl(longestpath)

        stronglist.append(ppSv)
    #得到上界pp(S,ev)的影响概率,上界pp(S,ev)
    ppSev = single_strong_infl(stronglist)
    
    #获取pp(u,ev)
    ppuev = single_strong_infl(longest_path(gllist, u, ev))
    
    #计算上界gain(u|S,ev)
    uSevgain = (1 - ppSev) * ppuev   
    return uSevgain                    
            

def uppergain(u, emu, ems, S):
    '''
    在已有种子集合S的基础上,求得节点u的影响增益上界,
    其中传进参数ems为二维列表,如[['a1',2.48],['a2',1.688]],S则为['a1','a2']
    '''
    uSgain = 0.0
    #遍历emu得到列表形式,得到如['a1',2.48]形式
    for ev in emu:
        #判断节点是否存在种子集合中
        if ev[0] in S:
            uSgain += uS_e_uppergain(u, ev[0], S)
        else:
            uSgain += ev[1] 

    #返回上界gain(u|S)    
    return uSgain
  

def bound_base_imms(G, k):
    '''
    完全使用影响增益上界的方式选择top-k个种子节点的过程
    '''
    #初始化emu,H,初始化ems=空集,S=空集 

    Htemp = []
    Htemp = all_strong_infl(G)
    H = []
    #遍历Htemp=[['a1',2.48],['a2',1.688]],得到如['a1',2.48]形式
    for x in Htemp:
        #逐个获取二维列表中每一行,形式为['a1',2.48,0]
        H.append([x[0],x[1],0])

    emu = []
    emu = all_strong_infl(G)
    
    ems = []
    S = []
    
    for i in range(k):
        
        #提取堆顶元素,tnode的形式为['a1',2.48,0]
        tnode = heapq.nlargest(1, H, key=lambda x: x[1])
        #将[['b2', 3.1, 0]]格式改为['b2', 3.1, 0]格式
        tnode = sum(tnode, [])

        while (tnode[2] != i):
            gain = 0.0
            #获取节点u的影响增益上界
            gain = uppergain(tnode, emu, ems, S)
            #赋值影响范围
            tnode[1] = gain
            #修改status
            tnode[2] = i
            
            #对堆进行排序
            H = heapq.nlargest(len(H), H, key=lambda x: x[1])

        #获取堆顶元素
        tnode = heapq.nlargest(1, H, key=lambda x: x[1])
        tnode = sum(tnode, [])

        #添加node到种子集合
        S.append([tnode[0]])
        #更新ems,添加新节点及节点对每个实体的影响范围加权
        ems.append([tnode[0], tnode[1]])

        #删除堆顶元素
        H.remove(tnode)
    print ems
    return sum(S, [])


if __name__=='__main__':

    #大小为k的种子集合S
    k = 60
    
    #加载文件数据,得到图G和初始列表gllist
    load_graph('test.txt')
    
    #完全使用影响增益上界值的计算过程函数,打印种子集合S
    print '种子集合:',bound_base_imms(G, k)

test.txt
a1 b1 0.2 0
a1 c1 0.8 0
a2 b2 0.4 0
a2 d2 1 0
b1 c1 0.7 0
c2 a2 0.8 0 1 0.1 1
....
a1 l1 0.5 0
a1 m1 0.5 0
a1 q1 0.5 0
a1 v1 0.5 0
a1 z1 0.5 0
a1 s1 0.5 0
a1 w1 0.5 0
a1 u1 0.5 0
其中前兩列為傳播實體,第三列為實體間傳播機率,最後一列為0代表同一網路傳播,為1代表網路間自傳播。

下來要進行最佳化:
1.採用獨立級聯模型,設定閾值

2.將最大路徑改為最短路徑,利用log

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板