如何用Python计算网络的Eb(k)?

如何用Python计算网络的Eb(k)?,python,algorithm,social-networking,networkx,correlation,Python,Algorithm,Social Networking,Networkx,Correlation,在题为《度相关性的标度及其对无标度网络中扩散的影响》的论文中,作者定义了$E_b(k)$的数量来衡量度相关性的程度 纸张 L.K.Gallos,C.Song和H.A.Makse,度关联的标度及其对无标度网络中扩散的影响,Phys。牧师。莱特。100248701(2008年) 你可以阅读下面的文章或阅读相关文章 问题: 我的问题是如何用Python计算网络的Eb(k)?我的问题是我不能复制作者的结果。我用浓缩物数据来测试它。Eb(k)的结果如上图所示您可以看到我的图中的一个问题是Eb(k)远

在题为《度相关性的标度及其对无标度网络中扩散的影响》的论文中,作者定义了$E_b(k)$的数量来衡量度相关性的程度

纸张 L.K.Gallos,C.Song和H.A.Makse,度关联的标度及其对无标度网络中扩散的影响,Phys。牧师。莱特。100248701(2008年)

你可以阅读下面的文章或阅读相关文章

问题:

我的问题是如何用Python计算网络的Eb(k)?我的问题是我不能复制作者的结果。我用浓缩物数据来测试它。Eb(k)的结果如上图所示您可以看到我的图中的一个问题是Eb(k)远大于1!!我也尝试过互联网(As级数据)和WWW数据,但问题依然存在。毫无疑问,我的算法或代码有严重错误。您可以复制我的结果,并将其与作者的结果进行比较。非常感谢您的解决方案或建议。下面我将介绍我的算法和python脚本

我遵循以下步骤:
  • 对于每条边,找到其k=k且k'>3k的边。这些边的概率表示为P(k,k′)
  • 对于节点,为了得到度大于b*k的节点的比例,表示为p(k'),因此我们也可以有k'*p(k')
  • 要获得分子P1:P1=\sum P(k,k')/k'*P(k')
  • 要获取分母p2:p2=\sum P(k')
  • Eb(k)=p1/p2
  • Python脚本 python脚本如下所示:

    %matplotlib inline
    import networkx as nx
    import matplotlib.cm as cm
    import matplotlib.pyplot as plt
    from collections import defaultdict
    
    def ebks(g, b):
        edge_dict = defaultdict(lambda: defaultdict(int))
        degree_dict = defaultdict(int)
        edge_degree = [sorted(g.degree(e).values()) for e in g.edges()]
        for e in edge_degree:
            edge_dict[e[0]][e[-1]] +=1
        for i in g.degree().values():
            degree_dict[i] +=1
        edge_number = g.number_of_edges()
        node_number = g.number_of_nodes()
        ebks, ks = [], []
        for k1 in edge_dict:
            p1, p2 = 0, 0
            for k2 in edge_dict[k1]:
                if k2 >= b*k1:
                    pkk = float(edge_dict[k1][k2])/edge_number
                    pk2 = float(degree_dict[k2])/node_number
                    k2pk2 = k2*pk2
                    p1 += pkk/k2pk2
            for k in degree_dict:
                if k>=b*k1:
                    pk = float(degree_dict[k])/node_number
                    p2 += pk
            if p2 > 0:
                ebks.append(p1/p2)
                ks.append(k1)
        return ebks, ks
    
    我使用ca CondMat数据进行测试,您可以从以下url下载:

    更新:问题尚未解决

    def ebkss(g, b, x):
        edge_dict = defaultdict(lambda: defaultdict(int))
        degree_dict = defaultdict(int)
        edge_degree = [sorted(g.degree(e).values()) for e in g.edges()]
        for e in edge_degree:
            edge_dict[e[0]][e[-1]] +=1
        for i in g.degree().values():
            degree_dict[i] +=1
        edge_number = g.number_of_edges()
        node_number = g.number_of_nodes()
        ebks, ks = [], []
        for k1 in edge_dict:
            p1, p2 = 0, 0
            nk2k = np.sum(edge_dict[k1].values())
            pk1 = float(degree_dict[k1])/node_number
            k1pk1 = k1*pk1
            for k2 in edge_dict[k1]:
                if k2 >= b*k1:
                    pk2k = float(edge_dict[k1][k2])/nk2k
                    pk2 = float(degree_dict[k2])/node_number
                    k2pk2 = k2*pk2
                    p1 += (pk2k*k1pk1)/k2pk2
            for k in degree_dict:
                if k>=b*k1:
                    pk = float(degree_dict[k])/node_number
                    p2 += pk
            if p2 > 0:
                ebks.append(p1/p2**x)
                ks.append(k1)
        return ebks, ks
    

    考虑到使用数据的日志分块,可以采用以下功能

    import numpy as np
    
    def log_binning(x, y, bin_count=35):
        max_x = np.log10(max(x))
        max_y = np.log10(max(y))
        max_base = max([max_x,max_y])
        xx = [i for i in x if i>0]
        min_x = np.log10(np.min(xx))
        bins = np.logspace(min_x,max_base,num=bin_count)
        bin_means_y = (np.histogram(x,bins,weights=y)[0] / np.histogram(x,bins)[0])
        bin_means_x = (np.histogram(x,bins,weights=x)[0] / np.histogram(x,bins)[0])
        return bin_means_x,bin_means_y
    
    如果要线性存储数据,请使用以下函数:

    def LinearBinData(x, y, number): 
        data=sorted(zip(x,y))
        rs = np.linspace(min(x),max(x),number)
        rs = np.transpose(np.vstack((rs[:-1],rs[1:])))
        ndata = []
        within = []
        for start,end in rs:
            for i,j in data:
                if i>=start and i<end:
                    within.append(j)
            ndata.append([(start+end)/2.0,np.mean(np.array(within))]  )
        nx,ny = np.array(ndata).T
        return nx,ny
    
    def linearbinda(x,y,数字):
    数据=已排序(zip(x,y))
    rs=np.linspace(最小(x)、最大(x)、数量)
    rs=np.transpose(np.vstack((rs[:-1],rs[1:]))
    数据=[]
    内=[]
    对于开始,以rs结束:
    对于数据中的i,j:
    
    如果i>=start和i看起来你实际上是在用离散分布计算条件概率,所以你得到了很多零,这就产生了问题

    在论文(第二栏顶部,第二页)中,他们似乎在使用一个适合数据的幂律,用一个漂亮的平滑函数来替换有噪声的离散值。我想这也是为什么他们用积分而不是求和来写E_b


    如果我是你,我会向论文的作者索要他们的代码。然后我会要求该杂志停止发表没有支持代码的论文。

    根据该论文,Eb(k)的目的是获得相关指数ε:“[我们]引入一个标度不变量Ebk 简化ε的估算”(第二页,第一列底部)

    我还没有找到使Eb(k)<1的方法,但是我找到了一个正确计算epsilon的校正

    根据方程4,Eb(k)~k^-(ε伽马)(其中度分布p(k)~k^-伽马,幂律)。因此,如果我们绘制log(Eb(k))与log(k)的斜率,我们应该得到伽马ε。知道伽马,我们就能很容易地得到ε

    请注意,如果Eb(k)按常数缩放,则该斜率是不变的。因此,计算出的Eb(k)问题不是它大于1,而是它给了你一个约为.5的对数斜率,而在本文中斜率约为1.2,因此你会得到错误的ε

    我的算法 我首先复制您的代码,查看它,然后以等效的方式重新实现它。我的重新实施复制了您的结果。我很有信心您正确地实现了E_b(k)公式的离散版本。然而,对这篇论文的仔细研究表明,作者在他们的代码中使用了平滑近似

    在第二页和第二列中,说明了等式p(k | k')=p(k,k')/(k')^(1-gamma)。这相当于将第一个积分分母中的精确概率P(k')替换为阶分布的平滑幂律近似(k')^(-gamma),这不是一个等式

    作者将这种近似表示为无条件的等式,这一事实向我表明,他们可能在其代码中使用了这种近似。所以,我决定在代码中使用它们的近似值,结果如下(我得到的伽马=2.8的cond mat解释如下)

    结果 使用此代码:

    def get_logslope(x,y):
        A = np.empty((len(x), 2))
        A[:,0] = np.log(x)
        A[:,1] = 1
        res = la.lstsq(A, np.log(y))
        return res[0]
    
    def show_eb(ca, b, gamma):
        #calculate ebk 
        ebk, k = ebkss(ca, b=b,gamma=gamma)
        print "Slope = ", get_logslope(np.array(k), np.array(ebk) )
        plt.plot(k,ebk,'r^')
        plt.xlabel(r'$k$', fontsize = 16)
        plt.ylabel(r'$E_b(k)$', fontsize = 16)
        plt.xscale('log')
        plt.yscale('log')
        plt.show()
    show_eb(ca, 3, 2.8)
    
    我得到了这个输出:

    Slope =  1.22136715547
    

    斜率(小数点后最多1位,这是本文给出的全部)是正确的,因此现在可以正确计算ε

    关于伽马 通过将斜率1.2与ε值1.6相加,我得到了gamma=2.8的值(这从本文的等式4得出)。我还使用powerlawpython模块进行了一次快速的健全性检查,以确定这个gamma是否合适

    import powerlaw
    res = powerlaw.Fit(np.array(ca.degree().values())+1, xmin=10)
    print res.alpha
    
    这个输出

    2.84571139756
    
    因此,2.8对于四舍五入之前的伽马值是正确的

    使用WWW数据编辑 我用WWW数据集测试了我的方法。我最终得到了一个与论文中的坡度相近的坡度,但缩放比例仍在减小。 这是我的密码:

    def log_binning(x, y, bin_count=50):
        max_x = np.log10(max(x))
        max_y = np.log10(max(y))
        max_base = max([max_x,max_y])
        xx = [i for i in x if i>0]
        min_x = np.log10(np.min(xx))
        bins = np.logspace(min_x,max_base,num=bin_count)
        hist = np.histogram(x,bins)[0]
        nonzero_mask = np.logical_not(hist==0)       
        hist[hist==0] = 1
        bin_means_y = (np.histogram(x,bins,weights=y)[0] / hist)
        bin_means_x = (np.histogram(x,bins,weights=x)[0] / hist)
        return bin_means_x[nonzero_mask],bin_means_y[nonzero_mask]
    def single_line_read(fname):    
        g = nx.Graph()
        with open(fname, "r") as f:
            for line in f:
              a = map(int,line.strip().split(" "))
              g.add_edge(a[0], a[1])
        return g
    
    www = single_line_read("data/www.dat")
    ebk, k = ebkss(www, 3, 2.6)
    lk, lebk = log_binning(np.array(k,dtype=np.float64), np.array(ebk), bin_count=70)
    #print lk, lebk
    print "Slope", get_logslope(lk, lebk)
    plt.plot(lk,lebk/www.number_of_edges(),'r^')
    plt.xlabel(r'$k$', fontsize = 16)
    plt.ylabel(r'$E_b(k)$', fontsize = 16)
    plt.xscale('log')
    plt.yscale('log')
    plt.show()
    
    坡度0.162453554297

    原始纸张的坡度为0.15。通过查看论文中的图3(伽马ε图),我得到了伽马值2.6

    总之 我不知道为什么在论文的图表中Eb(k)比1小得多。我敢肯定,一些重新缩放正在进行,这在论文中没有明确说明。然而,我能够使用Eb(k)恢复正确的ε值。只要你能计算epsilo
    2.84571139756
    
    def log_binning(x, y, bin_count=50):
        max_x = np.log10(max(x))
        max_y = np.log10(max(y))
        max_base = max([max_x,max_y])
        xx = [i for i in x if i>0]
        min_x = np.log10(np.min(xx))
        bins = np.logspace(min_x,max_base,num=bin_count)
        hist = np.histogram(x,bins)[0]
        nonzero_mask = np.logical_not(hist==0)       
        hist[hist==0] = 1
        bin_means_y = (np.histogram(x,bins,weights=y)[0] / hist)
        bin_means_x = (np.histogram(x,bins,weights=x)[0] / hist)
        return bin_means_x[nonzero_mask],bin_means_y[nonzero_mask]
    def single_line_read(fname):    
        g = nx.Graph()
        with open(fname, "r") as f:
            for line in f:
              a = map(int,line.strip().split(" "))
              g.add_edge(a[0], a[1])
        return g
    
    www = single_line_read("data/www.dat")
    ebk, k = ebkss(www, 3, 2.6)
    lk, lebk = log_binning(np.array(k,dtype=np.float64), np.array(ebk), bin_count=70)
    #print lk, lebk
    print "Slope", get_logslope(lk, lebk)
    plt.plot(lk,lebk/www.number_of_edges(),'r^')
    plt.xlabel(r'$k$', fontsize = 16)
    plt.ylabel(r'$E_b(k)$', fontsize = 16)
    plt.xscale('log')
    plt.yscale('log')
    plt.show()