5D Library › 社会网络拓扑、结构洞与复杂传染的数学模型 · English
第一章 弱连带的力量与小世界
格兰诺维特的论证
1973 年,社会学家马克·格兰诺维特发表了社会网络研究中被引用最多的论文之一《弱连带的力量》。他把两个人之间连带的强度定义为几方面的组合:一起度过的时间、情感的强度、亲密程度(彼此倾诉)以及相互提供的帮助 (M. S. Granovetter 1973)。
论证的关键是一个关于三角形的观察。如果 A 与 B、A 与 C 之间都是强连带,那么 B 与 C 之间很可能至少存在一条弱连带:A 花很多时间和他们在一起,他们很可能见过面;他们都和 A 相似,也很可能彼此相似。格兰诺维特把「A 与 B、A 与 C 都是强连带,而 B 与 C 毫无关系」称为「被禁止的三元组」:它不是不可能,而是少见。由此可以推出一个结构性的结论:强连带很少是桥。所谓桥(更准确地说是「局部桥」),是连接两个本来不会通过短路径相连的人的那条边;如果 A—B 是强连带,那么 A 的其他强连带朋友多半也认识 B,从 A 到 B 就有别的短路径,A—B 不再是唯一的通道。能够连接两个不同圈子的,往往是弱连带。
证据
找工作的数据。 格兰诺维特在波士顿郊区牛顿市调查了近五年内换过工作的专业、技术与管理人员。在通过私人关系找到工作的一个 54 人子样本中,16.7% 的人在换工作时「经常」见到这位联系人(每周至少两次),55.6% 的人「偶尔」见到(多于一年一次、少于每周两次),27.8% 的人「很少」见到(一年一次或更少) (M. S. Granovetter 1973)。也就是说,在这个子样本中,帮上忙的大多不是关系最密切的人。完整的研究结果后来发表在专著《找工作》中 (M. Granovetter 1974)。
这组数字常被引用为「弱连带更有用」的证据,但它本身只说明了「帮上忙的人中,弱连带占多数」。这有两种可能的解释:每一条弱连带确实更有用;或者只是因为弱连带的数量远多于强连带。区分这两种解释,需要后来几十年才出现的大规模数据(见本章后半部分)。
闭合的三角形与冗余的信息
格兰诺维特的论证可以写成一个可以计算的量。对一条连带 —,邻域重叠定义为两人共同联系人的数目除以两人其他联系人的总数:
其中 、 是两人的联系人数, 是共同联系人数。 接近 1,说明这条连带嵌在闭合的三角形中,对方认识的人你也大多认识,他能带来的信息很可能你早已知道; 接近 0,说明这条连带是一座桥。
证据
手机通话网络。 奥内拉等人分析了一个欧洲国家数百万手机用户的通话记录,以通话总时长作为连带强度。他们发现,连带越强,两人的邻域重叠越大,这与格兰诺维特的假说一致;更重要的是,如果从最弱的连带开始逐一删除,网络会在某个比例上突然碎裂成许多小块(一种渗流相变),而从最强的连带开始删除,网络只是逐渐缩小 (Onnela et al. 2007)。弱连带维系着整个网络的连通,强连带维系着局部的社群。
推导
用一个合成网络说明这个结构。600 人分成 30 个 20 人的小组,组内任意两人以 0.4 的概率相识,组与组之间另有 150 条随机连带。分别计算组内连带与组间连带的平均重叠,以及「新颖性」:对方的其他联系人中,有多大比例是你不认识的。然后按重叠从低到高、随机、从高到低三种顺序删除连带,看最大连通分量还剩多少人。
# Bridges, closed triangles and redundant information (Granovetter 1973;
# Onnela et al. 2007). Synthetic network: 30 groups of 20 people, dense inside
# each group (tie probability 0.4) plus 150 random ties between groups.
# Neighbourhood overlap of tie i-j: shared contacts / (k_i - 1 + k_j - 1 - shared).
# "Novelty" of j for i: share of j's other contacts that i does not know.
# Then ties are removed in order of overlap (lowest first or highest first)
# and the largest connected component is tracked. Illustrative parameters.
import random
rng = random.Random(2)
G, S, P_IN, N_BETWEEN = 30, 20, 0.4, 150
N = G * S
nb = [set() for _ in range(N)]
for g in range(G):
m = range(g * S, (g + 1) * S)
for a in m:
for b in m:
if a < b and rng.random() < P_IN:
nb[a].add(b); nb[b].add(a)
added = 0
while added < N_BETWEEN:
a, b = rng.randrange(N), rng.randrange(N)
if a // S != b // S and b not in nb[a]:
nb[a].add(b); nb[b].add(a); added += 1
edges = [(a, b) for a in range(N) for b in nb[a] if a < b]
def overlap(a, b):
sh = len(nb[a] & nb[b]); den = len(nb[a]) - 1 + len(nb[b]) - 1 - sh
return sh / den if den > 0 else 0.0
def novelty(a, b): # share of b's other contacts unknown to a
others = nb[b] - {a}
return len(others - nb[a]) / len(others) if others else 0.0
inside = [e for e in edges if e[0] // S == e[1] // S]
across = [e for e in edges if e[0] // S != e[1] // S]
mean = lambda xs: sum(xs) / len(xs)
print(f"{N} people, {len(edges)} ties: {len(inside)} inside groups,"
f" {len(across)} between")
print(" mean overlap novelty of the contact's other contacts")
for name, es in (("inside-group ties", inside), ("between-group ties", across)):
nov = mean([novelty(a, b) for a, b in es] + [novelty(b, a) for a, b in es])
print(f" {name:18s} {mean([overlap(*e) for e in es]):10.3f} {nov:8.3f}")
def giant(keep):
par = list(range(N))
def find(x):
while par[x] != x:
par[x] = par[par[x]]; x = par[x]
return x
for a, b in keep:
ra, rb = find(a), find(b)
if ra != rb: par[ra] = rb
size = {}
for x in range(N):
r = find(x); size[r] = size.get(r, 0) + 1
return max(size.values()) / N
order = sorted(edges, key=lambda e: (overlap(*e), rng.random()))
shuffled = edges[:]; rng.shuffle(shuffled)
print("largest component (share of people) after removing a share of ties:")
print(" removed low overlap first random high overlap first")
for f in (0.0, 0.03, 0.06, 0.08, 0.1, 0.2, 0.4):
k = int(f * len(edges))
low, rnd = giant(order[k:]), giant(shuffled[k:])
high = giant(order[:len(edges) - k])
print(f" {f:4.0%} {low:6.2f} {rnd:6.2f} {high:6.2f}")
# 600 people, 2405 ties: 2255 inside groups, 150 between
# mean overlap novelty of the contact's other contacts
# inside-group ties 0.230 0.627
# between-group ties 0.001 0.998
# largest component (share of people) after removing a share of ties:
# removed low overlap first random high overlap first
# 0% 1.00 1.00 1.00
# 3% 1.00 1.00 1.00
# 6% 0.99 1.00 1.00
# 8% 0.93 1.00 1.00
# 10% 0.26 1.00 1.00
# 20% 0.03 1.00 1.00
# 40% 0.03 1.00 0.99组间连带只占全部连带的约 6%,但它们的平均重叠几乎为 0(0.001),对方的其他联系人中 99.8% 是你不认识的;组内连带的平均重叠为 0.23,对方的联系人中只有约 63% 是新面孔。删除连带时,三种顺序的结果截然不同:从低重叠的连带删起,只删去 10% 的连带,最大连通分量就从全部人缩小到约四分之一(0.26),删去 20% 后只剩一个小组那么大(3%);随机删除或从高重叠的连带删起,删去 40% 的连带后网络依然几乎完整。这个合成网络中的组间连带恰好也是低重叠的连带,所以结果比真实数据更干净;真实网络中重叠与强度只是相关,并不完全对应。
小世界
另一个与「桥」有关的现象是小世界:在一个很大的网络中,任意两人之间往往只隔着几步。瓦茨与斯托加茨在 1998 年用一个简单的模型解释了它为什么能与「朋友的朋友也是朋友」(高聚类)同时存在 (Watts and Strogatz 1998)。
推导
瓦茨—斯托加茨模型: 个人围成一圈,每人与左右各 位最近的邻居相连;然后以概率 把每条边的一端改接到随机的另一个人。 是任意两人之间最短路径的平均长度(用广度优先搜索计算), 是平均聚类系数(一个人的联系人之间实际存在的连带,占所有可能连带的比例)。这里 、,与原文相同;每个 重复 3 次,路径长度从 100 个随机起点估计。
# Watts & Strogatz (1998) small-world model, standard library only.
# Ring of N nodes, each tied to its K nearest neighbours (K/2 on each side).
# Each lattice edge is rewired with probability p to a random new endpoint
# (no self-loops, no duplicate edges). L = mean shortest path (BFS from a
# random sample of sources), C = mean local clustering coefficient.
import math, random
from collections import deque
N, K = 1000, 10
def ws_graph(p, rng):
nb = [set() for _ in range(N)]
for i in range(N):
for j in range(1, K // 2 + 1):
a, b = i, (i + j) % N
nb[a].add(b); nb[b].add(a)
for j in range(1, K // 2 + 1): # rewire lap by lap, as in the paper
for i in range(N):
b = (i + j) % N
if b in nb[i] and rng.random() < p:
new = rng.randrange(N)
while new == i or new in nb[i]:
new = rng.randrange(N)
nb[i].discard(b); nb[b].discard(i)
nb[i].add(new); nb[new].add(i)
return nb
def mean_path(nb, sources):
tot = cnt = 0
for s in sources:
dist = {s: 0}; q = deque([s])
while q:
u = q.popleft()
for v in nb[u]:
if v not in dist:
dist[v] = dist[u] + 1; q.append(v)
tot += sum(dist.values()); cnt += len(dist) - 1
return tot / cnt
def clustering(nb):
c = 0.0
for i in range(N):
ns = list(nb[i]); k = len(ns)
if k < 2:
continue
links = sum(1 for a in range(k) for b in range(a + 1, k)
if ns[b] in nb[ns[a]])
c += 2 * links / (k * (k - 1))
return c / N
def curve(ps, reps=3, n_src=100, seed=1):
rng = random.Random(seed)
out = []
for p in ps:
L = C = 0.0
for _ in range(reps):
g = ws_graph(p, rng)
L += mean_path(g, rng.sample(range(N), n_src)); C += clustering(g)
out.append((p, L / reps, C / reps))
return out
if __name__ == "__main__":
ps = [0, 0.0003, 0.001, 0.003, 0.01, 0.02, 0.05, 0.1, 0.3, 1.0]
res = curve(ps)
L0, C0 = res[0][1], res[0][2]
print(f"N = {N}, K = {K}: lattice L(0) = {L0:.1f}, C(0) = {C0:.3f}")
print(" p L(p)/L(0) C(p)/C(0)")
for p, L, C in res:
print(f" {p:<7} {L / L0:8.3f} {C / C0:9.3f}")
lr = math.log(N) / math.log(K)
print(f"random-graph benchmarks: L ~ ln N / ln K = {lr:.2f},"
f" C ~ K / N = {K / N:.3f}")
# N = 1000, K = 10: lattice L(0) = 50.5, C(0) = 0.667
# p L(p)/L(0) C(p)/C(0)
# 0 1.000 1.000
# 0.0003 0.734 0.999
# 0.001 0.492 0.997
# 0.003 0.326 0.990
# 0.01 0.183 0.972
# 0.02 0.136 0.942
# 0.05 0.106 0.872
# 0.1 0.089 0.747
# 0.3 0.071 0.352
# 1.0 0.065 0.012
# random-graph benchmarks: L ~ ln N / ln K = 3.00, C ~ K / N = 0.010规则的环形网络中,任意两人平均相隔约 50 步,聚类系数为 0.667。只要把 1% 的边改接成随机的「捷径」(),平均路径长度就降到原来的 18%,而聚类系数仍有原来的 97%; 时,路径长度降到 11%,聚类系数仍有 87%。要让聚类系数也明显下降,需要 达到 0.1 以上; 时网络接近完全随机,路径长度约为原来的 6.5%(接近随机图的估计 步),聚类系数只剩 1% 左右。也就是说,存在一个很宽的区间,网络既像小圈子一样紧密,又像随机图一样「小」。原因在于:每一条捷径都同时缩短了许多对人之间的距离,但只拆掉一个局部三角形。
瓦茨与斯托加茨在原文中指出,好莱坞电影演员的合作网络、美国西部电网与线虫的神经网络都同时具有很短的路径和远高于随机图的聚类 (Watts and Strogatz 1998)。模型中的「捷径」,在社会网络中对应的正是格兰诺维特所说的桥。
后来的检验:哪一种连带真正有用?
格兰诺维特的数据只能告诉我们帮上忙的人中弱连带占多数。要回答「一条弱连带是否比一条强连带更有用」,需要知道每个人所有的连带,以及每条连带是否带来了工作。
证据
脸书。 吉、琼斯与伯克用约 600 万美国脸书用户的数据,把「后来与某位原有好友在同一家雇主工作」作为得到工作帮助的代理指标,以互动频率衡量连带强度。他们发现,单独来看,一条较强的连带在边际上明显更有价值;但由于弱连带的数量多得多,大多数得到帮助的人是通过某一条弱连带得到的 (Gee, Jones, and Burke 2017)。这说明,「弱连带的力量」主要是数量的力量。
证据
领英的随机实验。 拉杰库马尔等人分析了领英「你可能认识的人」推荐算法在五年间的多项大规模随机实验,涉及约 2,000 万用户,期间产生了 20 亿条新连带和 60 万次换工作。由于推荐算法的不同版本是随机分配的,用户得到的弱连带与强连带的比例也随之随机变化,这使研究者可以估计因果效应。他们发现,以共同联系人数衡量时,连带强度与换工作之间呈倒 U 形关系:中等偏弱的连带最有用,最弱和最强的都较差;以互动强度衡量时,最弱的连带带来最多的换工作。在数字化程度较高的行业,弱连带的作用更大;在数字化程度较低的行业,强连带的作用更大 (Rajkumar et al. 2022)。
这两项研究是对格兰诺维特假说迄今最有力的检验,结论比「越弱越好」更细致:连带的价值取决于用什么衡量强度、问的是每条连带的价值还是总体的价值,以及行业的性质。领英的实验在用户不知情的情况下改变了推荐给他们的人,发表后也引起了关于平台实验知情同意的讨论;第八章的伦理一节会回到这个问题。
两项研究合起来说明,「弱连带有用」「中等强度的连带最有用」「单条强连带更有用」三种说法可以同时成立:强连带更愿意帮忙,但它们知道的多半是你已经知道的事;弱连带带来的信息更新,但每一条帮忙的意愿较低,只是数量多得多。哪一种说法成立,取决于问的是每条连带的价值、还是全部连带加起来的价值。
假说 · 尚未验证
跨界连带与新颖方案(尚未确立)。在需要新信息的任务中(例如为一个陌生问题提出方案),一个人的联系人中「彼此不相识」的比例越高,他提出的、被不知其身份的评审评为新颖的方案越多;在需要隐性知识或高度信任的任务中(例如交接一项复杂的工作),这种关系减弱甚至反转。可以检验的预测:在同一组人中,有效规模(见第二章)与新颖方案数之间的相关,在前一类任务中显著为正,在后一类任务中接近零。如果两类任务中的相关没有差别,这一假说就被削弱。
本章小结
格兰诺维特的论证从「被禁止的三元组」推出强连带很少是桥,桥多半是弱连带;他的找工作数据来自 54 人的子样本,显示帮上忙的人多数是不常见面的熟人。邻域重叠把这一论证变成可以计算的量:低重叠的连带带来新颖的信息,并维系着整个网络的连通。瓦茨—斯托加茨模型显示,少量捷径就能让路径长度大降而聚类几乎不变。脸书与领英的大规模研究表明,弱连带的总体作用主要来自数量,单条连带最有用的是中等强度。下一章从连带转向位置:站在圈子之间的空隙上意味着什么。
参考文献
Fan, Y. (2026). Social Network Topology, Structural Holes and Complex Contagion: From the Strength of Weak Ties and Preferential Attachment to Information Cascades, Read Beside Classical Chinese Diplomacy [社会网络拓扑、结构洞与复杂传染的数学模型] (Version 1.0.0). 5D Library. https://doi.org/10.5281/zenodo.23764990 · Licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0).