
总结
k-clique渗透算法,是一种用于社区发现的算法, 属于可重叠社区发现算法.
该算法通过寻找完全子图(任意2个节点之间都存在边关系),节点数为k的完全子图,称为k-clique。
然后通过相邻的k-clique构成最大的集合来形成社区。
在k-clique渗透算法中,如果2个k-clique完全子图,有k-1个共同的节点,
那么就称这2个k-clique是相邻的。
彼此相邻的k-clique完全子图可以构成更大的集合,就可以称为一个社区。
该算法的具体步骤包括:
1. 初始化:选择一个初始的k-clique(k个节点的完全子图)
2. 扩展:在已找到的k-clique周围尽可能找到其他更多的k-clique。
3. 优化:对所有找到的k-clique进行优化,确保它们之间有足够的连接。
4. 重复步骤2和3,直到无法找到更多的k-clique或达到预设的停止条件。
最后,选择割集规模最小的状态作为最优解。该算法可以帮助揭示图中隐藏的社区结构和模式,在社交网络分析、生物信息学、推荐系统等领域有广泛应用。
什么是渗透算法
该算法是networkx包自带的算法
该算法发现的社区是可重叠社区,即一个节点可以同时属于不同的社区,
5个人6个群,这就是重叠社区。
在一张网络图中,如果其中有一个完全子图,节点数是k,其中任意两个节点之间均存在边,
这就是一张完全子图,称为k-clique。
进而,如果两个k-clique之间存在k-1个共同的节点,那么就称这两个k-clique是“相邻”的。
彼此相邻的这样一串k-clique构成最大集合,就可以称为一个社区,
而且这样的社区是可以重叠的,就是说有些节点可以同时属于多个社区。
下面第一组图表示两个3-clique形成了一个社区,第二组图是一个重叠社区的示意图。
实战
1/生成模拟社交数据
import random
import csv
# 生成虚拟社交网络数据
def generate_social_network_data(num_nodes=50, num_edges=150, communities=3):
edges = set()
# 确保图是连通的
for i in range(1, num_nodes):
edges.add((i-1, i))
# 生成社区内部连接
community_size = num_nodes // communities
for c in range(communities):
start = c * community_size
end = (c + 1) * community_size if c < communities - 1 else num_nodes
# 增加社区内部的连接密度
for i in range(start, end):
for j in range(i+1, end):
if random.random() < 0.4: # 社区内部连接概率较高
edges.add((i, j))
# 生成随机连接,直到达到目标边数
while len(edges) < num_edges:
u = random.randint(0, num_nodes-1)
v = random.randint(0, num_nodes-1)
if u != v:
edges.add((min(u, v), max(u, v)))
return list(edges)
# 保存为CSV文件
def save_to_csv(edges, filename='social_network.csv'):
with open(filename, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['node1', 'node2'])
for edge in edges:
writer.writerow(edge)
if __name__ == "__main__":
edges = generate_social_network_data()
save_to_csv(edges)
print(f"生成了{len(edges)}条边的社交网络数据,保存到social_network.csv")
生成的模拟输入格式如下:
2/k-clique渗透算法挖掘社区
import networkx as nx
import csv
# 从CSV文件加载社交网络数据
def load_social_network(filename='social_network.csv'):
G = nx.Graph()
with open(filename, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
node1 = int(row['node1'])
node2 = int(row['node2'])
G.add_edge(node1, node2)
return G
# 使用k-clique算法进行社区检测
def detect_communities(G, k=3):
# 使用NetworkX的k_clique_communities函数
communities = list(nx.community.k_clique_communities(G, k))
return communities
# 保存社区检测结果到CSV文件
def save_communities(communities, filename='community_results.csv'):
with open(filename, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['node', 'community'])
for i, community in enumerate(communities):
for node in community:
writer.writerow([node, i])
# 主函数
def main():
# 加载数据
G = load_social_network()
print(f"加载了社交网络数据,包含{G.number_of_nodes()}个节点和{G.number_of_edges()}条边")
# 检测社区
k = 3 # 设置k值
communities = detect_communities(G, k)
print(f"检测到{len(communities)}个社区")
# 打印社区信息
for i, community in enumerate(communities):
print(f"社区{i}包含{len(community)}个节点: {sorted(community)}")
# 保存结果
save_communities(communities)
print("社区检测结果已保存到community_results.csv")
if __name__ == "__main__":
main()
挖掘结果如下所示:
加载了社交网络数据,包含50个节点和177条边
检测到3个社区
社区0包含16个节点: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
社区1包含16个节点: [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
社区2包含18个节点: [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
社区检测结果已保存到community_results.csv