社交网络分析课设实战:NetworkX图论、中心性与传播模型

发布时间:2026/10/11 22:59:17

社交网络分析课设实战:NetworkX图论、中心性与传播模型 简介这份资源是哈尔滨工业大学计算机课程实验中的社交网络分析项目面向高校计算机相关专业学生及需要完成课程设计的学习者帮助其将数据挖掘、图论与算法实现等理论落地为可运行代码。压缩包为zip格式整体约1.74MB内含源码与说明书源码可用于阅读和调试算法实现说明书则梳理实验目的、方法与结论便于对照理解整体思路。实验覆盖社交网络分析的核心内容包括数据预处理、图的遍历、社区检测、中心性分析以及数据可视化等环节读者可借助源码掌握NetworkX等工具的使用方式并理解度中心性、介数中心性等指标的计算逻辑。目前已有153人学习适合希望提升编程实践、数据分析与问题解决能力并需要一份完整课程实验参考的学习者。1. 从一份课设压缩包说起社交网络分析到底在算什么很多人第一次拿到「哈尔滨工业大学计算机课程实验-社交网络分析-内含源码和说明书.zip」这类压缩包第一反应是解压、找 README、跑 main。但真跑起来才发现社交网络分析不是把图读进来算个度就完事——它要回答的是「谁和谁关系近」「信息从哪条路径扩散最快」「哪个节点删掉会让整个网络裂开」。这套实验通常围绕图论基础、中心性指标、社区发现、传播模型四条主线展开配套源码多半是 Python NetworkX说明书负责交代数据集格式和实验步骤。它适合两类人一是正在做计算机课程实验、需要一份能跑通参考实现的学生二是想快速补齐图分析工程能力、把 NetworkX 用进真实业务的开发者。下面按「数据怎么进 → 指标怎么算 → 社区怎么分 → 传播怎么模拟 → 坑在哪」的顺序拆开讲每一步都给可复现的命令和参数。2. 把图读进来数据集格式与 NetworkX 建图的最小闭环2.1 先确认边表长什么样再决定用哪张图社交网络分析实验的数据集九成以上是边表edge list或邻接表。边表每行两个节点 ID用空格或逗号分隔邻接表则是「节点: 邻居1 邻居2」。拿到数据先别急着read_edgelist用head和wc -l看一眼规模和分隔符否则后面报的错全是格式问题。# 看前 5 行确认分隔符是空格还是逗号 head -5 edges.txt # 统计边数估算图规模 wc -l edges.txt # 看是否有表头或注释行 grep -n ^# edges.txt | head逻辑说明head决定后续delimiter参数wc -l让你心里有数——几千条边和几百万条边建图策略完全不同。参数上如果文件带表头read_edgelist要加comments#或先skiprows。常见翻车点是分隔符写成,但实际是制表符结果整行被当成一个节点 ID。2.2 用 NetworkX 建图并做第一轮体检确认格式后建图本身只有几行但体检不能省。孤立节点、自环、重复边这三样不处理后面中心性算出来全是噪声。import networkx as nx # 读边表nodetypeint 保证节点 ID 是整数而非字符串 G nx.read_edgelist(edges.txt, delimiter , nodetypeint, create_usingnx.Graph()) # 体检节点数、边数、是否连通、有无自环 print(节点数:, G.number_of_nodes()) print(边数:, G.number_of_edges()) print(自环数:, nx.number_of_selfloops(G)) print(连通分量数:, nx.number_connected_components(G)) # 去掉自环和孤立节点 G.remove_edges_from(nx.selfloop_edges(G)) G.remove_nodes_from(list(nx.isolates(G)))逻辑说明create_usingnx.Graph()建无向图如果实验要求有向图就换nx.DiGraph()。nodetypeint很关键不指定的话节点是字符串后面按 ID 排序会得到字典序而非数值序。参数上delimiter必须和 2.1 看到的一致。体检输出里连通分量数大于 1 说明图不连通算全局指标前要么取最大连通子图要么在报告里注明。提示最大连通子图用G.subgraph(max(nx.connected_components(G), keylen)).copy()直接切片会返回视图后续修改会污染原图。2.3 小图和大图的建图策略要分开实验数据通常不大但如果你拿真实社交数据练手几百万边用read_edgelist会吃满内存。常见做法是先用pandas读边表去重再转成 NetworkX或者直接用scipy.sparse存邻接矩阵只在需要图算法时转回来。import pandas as pd import networkx as nx # 大图pandas 去重后再建图省内存 df pd.read_csv(edges.txt, sep , headerNone, names[src, dst]) df df.drop_duplicates() G nx.from_pandas_edgelist(df, src, dst)逻辑说明drop_duplicates去掉重复边from_pandas_edgelist比逐行add_edge快一个量级。参数上names要和列数对上否则 pandas 会把第一行当表头。这一步的边界是如果边表超过内存就得换graph-tool或分块读NetworkX 本身不适合十亿级边。3. 中心性指标怎么选度、介数、接近度的适用边界3.1 三个中心性各回答什么问题度中心性degree看谁连接多介数中心性betweenness看谁在最短路径上卡位接近中心性closeness看谁到所有人平均距离短。实验里通常要求三个都算但报告里要能说清哪个指标对应哪个业务含义。度中心性适合找活跃用户介数适合找信息枢纽接近适合找传播起点。import networkx as nx deg nx.degree_centrality(G) btw nx.betweenness_centrality(G, k500, normalizedTrue) clo nx.closeness_centrality(G) # 按介数排序取前 10 top_btw sorted(btw.items(), keylambda x: x[1], reverseTrue)[:10] print(top_btw)逻辑说明degree_centrality是度除以 n-1betweenness_centrality的k参数是采样节点数大图必须设否则 O(nm) 跑不动。normalizedTrue让结果落在 0 到 1 之间便于比较。参数上k500是经验值图越大可以越小但太小会导致介数估计不稳。常见误用是拿介数中心性去衡量「影响力」其实介数高只说明它在路径上不代表它能影响别人。3.2 介数中心性的采样与精度权衡介数中心性是实验里最容易跑崩的一步。精确算法对每个节点做一次 BFS复杂度 O(nm)几千节点还能忍上万节点就得采样。# 精确算法小图用 btw_exact nx.betweenness_centrality(G, normalizedTrue) # 采样算法大图用k 越大越准 btw_approx nx.betweenness_centrality(G, k200, normalizedTrue, seed42) # 对比两者排名相关性 import numpy as np exact_rank [n for n, _ in sorted(btw_exact.items(), keylambda x: x[1], reverseTrue)] approx_rank [n for n, _ in sorted(btw_approx.items(), keylambda x: x[1], reverseTrue)] print(Top10 重合数:, len(set(exact_rank[:10]) set(approx_rank[:10])))逻辑说明seed固定采样随机性保证实验可复现。k的取值没有公式一般取min(500, n)然后看 Top10 重合数是否稳定。参数上如果重合数低于 7说明 k 太小要往上加。这一步的坑是采样后不同节点被选中的概率不同直接比较绝对数值没意义只能比排名。3.3 中心性结果的归一化与可视化算完指标要出图否则实验报告没说服力。NetworkX 自带draw但节点一多就糊成一团常见做法是按中心性调整节点大小和颜色。import matplotlib.pyplot as plt pos nx.spring_layout(G, seed42, k0.15) node_size [deg[n] * 3000 for n in G.nodes()] node_color [btw[n] for n in G.nodes()] plt.figure(figsize(12, 8)) nx.draw_networkx_edges(G, pos, alpha0.2) nx.draw_networkx_nodes(G, pos, node_sizenode_size, node_colornode_color, cmapYlOrRd) plt.axis(off) plt.savefig(network.png, dpi150, bbox_inchestight)逻辑说明spring_layout的k控制节点间距太小会挤在一起太大会散开。node_size乘 3000 是经验系数让度大的节点明显更大。cmapYlOrRd让介数高的节点偏红。参数上seed固定布局dpi决定输出清晰度。常见翻车是节点数超过 500 还画标签结果全叠在一起这时候要么只标 Top20要么换pyvis做交互图。4. 社区发现Louvain 与标签传播的落地差异4.1 Louvain 的模块度优化逻辑社区发现实验通常要求对比两种算法。Louvain 通过两阶段迭代最大化模块度 Q先局部移动节点再聚合社区成超节点。它的优点是快且结果稳定缺点是分辨率限制——小社区可能被合并。import networkx as nx import community as community_louvain # python-louvain 包 # Louvain 社区发现 partition community_louvain.best_partition(G, resolution1.0, random_state42) # 模块度 mod community_louvain.modularity(partition, G) print(模块度 Q:, mod) # 每个社区的大小 from collections import Counter sizes Counter(partition.values()) print(社区数:, len(sizes), 最大社区:, max(sizes.values()))逻辑说明best_partition返回节点到社区 ID 的字典。resolution大于 1 倾向更多小社区小于 1 倾向更少大社区。random_state固定随机种子。参数上resolution1.0是默认值实验里可以试 0.5 和 2.0 看社区数变化。常见误用是拿模块度当唯一评价标准模块度高不代表社区有业务意义。4.2 标签传播的随机性与多次投票标签传播LPA比 Louvain 更快但结果不稳定每次跑可能不一样。实验里通常跑多次取众数或者固定随机种子。from networkx.algorithms.community import label_propagation_communities # LPA 返回的是社区集合的迭代器 communities list(label_propagation_communities(G)) print(社区数:, len(communities)) # 转成节点到社区 ID 的字典 lpa_partition {} for cid, nodes in enumerate(communities): for n in nodes: lpa_partition[n] cid逻辑说明label_propagation_communities不接受seed参数所以结果天然随机。要稳定就多跑几次用Counter统计每个节点最常出现的社区。参数上LPA 没有可调参数这也是它不如 Louvain 可控的地方。边界是LPA 适合超大图快速粗分Louvain 适合需要可复现结果的实验报告。4.3 两种算法的对比表与选择建议维度Louvain标签传播 LPA时间复杂度O(n log n)O(n)结果稳定性高固定种子低随机可调参数resolution无模块度通常更高通常更低适用场景实验报告、需复现超大图、快速粗分选择建议课程实验优先 Louvain因为结果可复现、模块度可写进报告如果数据规模大到 Louvain 跑不动再用 LPA 做初筛。两者都跑一遍对比社区数是实验报告里常见的加分项。5. 传播模型模拟SI、SIR 与独立级联的参数设置5.1 SIR 模型的三个参数怎么定SIR 模型把节点分成易感 S、感染 I、恢复 R 三态。关键参数是感染概率 beta 和恢复概率 gamma基本再生数 R0 beta/gamma。R0 大于 1 疫情扩散小于 1 自然消亡。import networkx as nx import random def sir_simulation(G, beta0.3, gamma0.1, initial_infected5, steps50): # 初始化状态 status {n: S for n in G.nodes()} infected random.sample(list(G.nodes()), initial_infected) for n in infected: status[n] I history [] for _ in range(steps): new_infected [] new_recovered [] for n in G.nodes(): if status[n] I: # 恢复 if random.random() gamma: new_recovered.append(n) # 感染邻居 for nb in G.neighbors(n): if status[nb] S and random.random() beta: new_infected.append(nb) for n in new_infected: status[n] I for n in new_recovered: status[n] R history.append(sum(1 for s in status.values() if s I)) return history逻辑说明beta控制单次接触感染概率gamma控制恢复速度。initial_infected是初始感染人数steps是模拟轮数。参数上beta0.3, gamma0.1对应 R03属于强扩散。常见翻车是 beta 设太大一轮全感染曲线没有形状或者 gamma 设太大感染还没扩散就恢复完了。5.2 独立级联模型与影响力最大化独立级联IC模型里每个刚激活的节点有一次机会以概率 p 激活邻居。它更贴近信息传播场景常和影响力最大化实验一起出现。def ic_simulation(G, p0.1, seedsNone, steps50): if seeds is None: seeds random.sample(list(G.nodes()), 5) active set(seeds) newly_active set(seeds) history [len(active)] for _ in range(steps): next_active set() for n in newly_active: for nb in G.neighbors(n): if nb not in active and random.random() p: next_active.add(nb) if not next_active: break active | next_active newly_active next_active history.append(len(active)) return history逻辑说明p是单次激活概率seeds是初始种子节点。newly_active保证每个节点只尝试激活邻居一次。参数上p0.1是常见起点p 越大传播越快。边界是IC 模型假设激活机会只有一次和 SIR 可以反复感染不同实验报告里要写清用的是哪个模型。5.3 传播模拟的重复实验与置信区间单次模拟结果随机性大实验里通常跑 100 次取均值和标准差。import numpy as np results [sir_simulation(G, beta0.3, gamma0.1)[-1] for _ in range(100)] print(最终感染规模均值:, np.mean(results)) print(标准差:, np.std(results)) print(95% 置信区间:, np.percentile(results, [2.5, 97.5]))逻辑说明重复实验消除单次随机性np.percentile给出置信区间。参数上100 次是平衡精度和耗时的经验值图大可以降到 30 次。常见误用是只跑一次就下结论结果换个种子完全不一样。6. 避坑与排查课设跑不通时先看这五条6.1 现象read_edgelist报节点 ID 转换失败原因边表里有非整数节点 ID比如用户名或带字母的编号但代码写了nodetypeint。解决先head看数据如果 ID 是字符串就去掉nodetypeint或者用nodetypestr显式指定。6.2 现象介数中心性跑了一小时没结果原因图节点数上万精确介数复杂度 O(nm)内存和时间都扛不住。解决加k200走采样算法或者先取最大连通子图缩小规模。如果实验要求精确值就换小数据集。6.3 现象Louvain 社区数和预期差很多原因resolution参数没调默认 1.0 可能把该分开的社区合并了。解决试resolution0.5和2.0看社区数变化报告里注明用的分辨率。另外确认图是无向的Louvain 对有向图支持不好。6.4 现象SIR 模拟曲线一直是 0 或直接爆掉原因beta和gamma比例失衡。R0 beta/gamma 小于 1 时疫情自然消亡曲线贴地beta 接近 1 时一轮全感染曲线直上直下。解决先算 R0控制在 1.5 到 3 之间再微调steps让曲线完整。6.5 现象可视化图节点全挤在一起原因spring_layout的k参数太小或者节点数太多。解决调大k到 0.3 以上节点超过 500 就只画最大连通子图或者换pyvis做交互。标签只标 Top20别全标。7. 进阶技巧用模块度增量和 R0 反推实验结论跑通基础流程后真正拉开实验报告差距的是「用指标反推结论」。两个具体技巧一是用 Louvain 的模块度增量判断社区划分是否值得再调分辨率二是用 SIR 的 R0 反推传播阈值。模块度增量这样看先跑resolution1.0记下 Q 值再跑 0.8 和 1.2如果 Q 变化小于 0.01说明分辨率已经到平台期再调没意义如果变化大于 0.05说明还有优化空间可以继续二分逼近。这个技巧在实验报告里写出来比单纯贴一个 Q 值有说服力得多。import community as community_louvain for res in [0.6, 0.8, 1.0, 1.2, 1.5]: part community_louvain.best_partition(G, resolutionres, random_state42) q community_louvain.modularity(part, G) print(fresolution{res}, Q{q:.4f}, 社区数{len(set(part.values()))})逻辑说明resolution从小到大扫观察 Q 和社区数的变化趋势。参数上步长 0.2 是平衡精度和耗时的选择。如果 Q 在某点后下降说明分辨率过大把社区切碎了。R0 反推传播阈值SIR 模拟里R0 beta/gamma。如果实验要求找「传播临界点」就固定 gamma从小到大扫 beta看最终感染规模在哪跳变。跳变点对应的 beta 就是阈值和理论值 1/gamma 对比能验证模拟是否正确。import numpy as np gamma 0.1 for beta in np.arange(0.02, 0.3, 0.02): results [sir_simulation(G, betabeta, gammagamma)[-1] for _ in range(30)] print(fbeta{beta:.2f}, R0{beta/gamma:.2f}, 最终感染{np.mean(results):.1f})逻辑说明np.arange扫 beta每个 beta 跑 30 次取均值。参数上步长 0.02 足够看出跳变。理论阈值是 beta gamma 0.1模拟里感染规模应该在这附近明显上升。如果模拟阈值和理论差很远检查图是否连通、初始感染数是否太少。我自己的习惯是每跑完一个模型先把参数和结果存成 CSV再画图。这样调参时不用重跑直接读表对比。血泪经验是实验报告里最容易被问的不是「你用了什么算法」而是「你为什么选这个参数」——把扫描过程留下来比事后编理由靠谱得多。希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/11 22:59:17

冷却循环水反复结垢?清洗治标不治本,水质管理才是关键

不知道你有没有遇到过这样的怪事:一套冷却循环水系统,隔两三个月就得停下来请人清洗一次。清洗队前脚刚走,换热器的压差确实马上恢复正常,水温也压得住了。可没过多久,同样的问题又卷土重来,检修记录本上又…

2026/10/12 0:19:23

医疗AI架构选型:FastAPI+LangGraph与SpringAI实战对比与落地指南

还在纠结“该选Python还是Java”的时候,医疗AI项目的架构选型往往已经把交付节奏拖慢了一个月。这篇东西的起因是我最近同时接触了两个医疗场景项目——一个用FastAPI LangGraph搭问诊导诊Agent,一个用SpringAI做病历结构化与辅助决策服务。两边都跑通了…

2026/10/12 0:19:23

免费论文查重网站靠谱吗?底层逻辑、平台差异与避坑实操指南

免费论文查重网站,这几个字一搜能蹦出来几十个结果。但要说某一家免费工具能完全替代学校采购的那种正式查重系统,大概率是坑你。我平时帮项目组和身边同学审论文,被问得最多的就是“哪家免费查重靠谱”“为什么免费查出来20%,学校…

2026/10/12 0:19:23

雪球大V调仓数据爬取与量化因子构建实战

简介:本资源是一套面向Python初学者与金融数据爱好者的基础爬虫实践项目,聚焦雪球网投资组合调仓记录的自动化采集,解决个人投资者难以高效获取大神级用户历史操作数据的问题。压缩包为RAR格式,共2个Python源文件(约10…

2026/10/12 0:19:23

卫星导航抗干扰:MVDR空时阵列最佳旋转角MATLAB仿真

简介:这份MATLAB仿真代码面向卫星导航抗干扰方向的研究生、科研人员与工程技术人员,聚焦空时阵列处理中的最佳旋转角度方法,并在经典MVDR算法基础上进行改进。资源通过联合处理多天线接收数据,抑制多路径、电离层反射及人为干扰&a…

2026/10/12 0:14:22

claude-mem实战:用SQLite+向量检索为AI助手构建长期记忆层

先说一个让人抓狂的场景:你在对话框里花二十分钟描述一个模块的重构思路,AI 给出了相当具体的实现方案,还帮你理清了依赖关系。第二天你打开同一个会话,发现它已经忘了你是谁、昨天讨论的接口叫 lark-core 还是 core-lark。你只能…

2026/10/11 0:02:13

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/11 0:02:13

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/11 0:02:13

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/12 0:04:22

绝缘子缺陷检测数据集清洗与工业级训练实战指南

简介:本资源是面向电力AI研发人员、工业视觉工程师及智能巡检系统开发者的绝缘子缺陷检测专用YOLO格式数据集,解决无人机航拍场景下绝缘子破损、污闪、积雪等9类典型缺陷的精准识别与定位难题。数据集共2139张真实巡检图像(含训练/验证/测试集…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑