Fast Newman-FN算法以及模块度定义介绍
一、社区的定义
Newman第一次提出模块度定义就是在2004年发表的这篇文章“fast algorithm for community structure in networks”,第一次用量化的公式来确定社区划分。
首先,我们来看Newman如何定义社区的:the vertices in networks are often found to cluster into tightly knit groups with a high density of within-group edges and a lower density of between -group edges。
用大白话说就是:社区内部的边尽可能地多,但是社区之间的边尽可能地少
(一些定义):i、j指社区i和社区j;
n是网络中节点的数量;
m是网络中边的数量。一条边上连接两个节点,和明显,2m即网络中所有节点度之和
二、如何量化到模快度?
我们先用eij表示社区i和社区j之间连接的边的数量比整个网络边的数量,eii表示社区i内部边的数量比整个网络边的数量,既然这样的话我们只要使∑ieii尽可能大就好了,但是问题又来了,最大肯定就是1咯,所有节点归为一个社区,那这样很明显就没有意义了。
于是他有提出,网络中连接两个同种类型的边(即社区内部的边的比例eii)减去在相同结构下任意连接这两个节点边的比例的期望,于是模块度登场
Q=∑i(eii-ai2)
其中,ai=∑jeij 表示与社区i中节点相连的边占所有边的比例。如果社团内部边的比例不大于社团内部边随机连接的期望,那么Q=0,最大时为1。一般来说,Q值最大对应的社团结构就是网络中的社团结构
三、如何变成算法可操作性?
意思来了,我们只要优化Q就好了,但是如何把n个节点划分多少个社区?每个社区多少个节点?作者指出有2n-1种可能,这样的话根本无法将Q推广在高于20节点以上的网络?为了减少时间复杂度,作者提出一种贪婪策略
FN:(1)首先将网络中每个节点自定义成一个社区
(2)计算出两两社区结合是Q的值,找到Q增加最大的或者减少最少的合并方式进行社区合并
(3)直到所有社区合并成一个大社区时停止,找出合并过程中最大的Q是的社区划分结果
这个时候,Newman有注意到,当两个社区合并时,模块度的增量detaQ=(eji+eij-2ai*aj)=2(eij-2ai*aj)
四、代码来了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | clear all close all clc % load preprocess.mat % E=e; load ( 'dolphin.mat' ); E=A; % E(find(E>0))=1;%建立邻接矩阵 tic ; e=E; e(e==1)=1/ sum (E(:)); a= sum (e); n= size (A,2); b=[1:n]; b= num2cell (b); %用来存储社团元素的变量 c={}; k=1; while length (e)>1 lg= length (e); detaQ=-(10^9)* ones (n-k+1); %△Q for i =1:lg-1 for j = i +1:lg if e( i , j )~=0 detaQ( i , j )=2*(e( i , j )-a( i )*a( j )); %计算△Q end end end if sum (detaQ+(10^9))==0 break end % Q(k)=max(detaQ(:));%寻找△Q的最大值,并把它存储进Q(k)矩阵 %-----------------------------寻找最大△Q对应的两个社团,并将其合并,并改变e矩阵 [I,J]= find (detaQ== max (detaQ(:))); for ii=1: length (I) e(J(ii),:)=e(I(ii),:)+e(J(ii),:); e(I(ii),:)=0; e(:,J(ii))=e(:,I(ii))+e(:,J(ii)); e(:,I(ii))=0; % e(I,I)=e(I,I)/2; %—————————记录△Q最大所对应的社团以及各社团中的元素 b{J(ii)}=[b{I(ii)} b{J(ii)}]; b{I(ii)}=0; end e(I,:)=[]; e(:,I)=[]; b(I)=[]; c(k,:)= num2cell ( zeros (1,n)); c(k,1: length (b))=b; for kk=1: length (b) c2= cell2mat (c(k,kk)); c2(c2==0)=[]; c{k,kk}=c2; c2=[]; end a= sum (e); k=k+1; tmp=0; for jj=1: length (e) tmp=tmp+(e(jj,jj)-a(jj)*a(jj)); end Q(k)=tmp; end max_k= find (Q== max (Q(:)))-1; ll=0; for i =1: length (c(max_k,:)) if sum (c{max_k, i })~=0 ll=ll+1; c{max_k, i }=c{max_k, i }(c{max_k, i }~=0); end end c_newman=c(max_k,1:ll); label= zeros (n,1); for i =1:ll label(c{max_k, i }')= i ; end |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!