複雜網路系統普遍存在於現實生活中,從社交網路到交通網路,理解其結構和行為至關重要。本文利用 Python 的 NetworkX 函式庫,深入研究小世界網路、優先依附網路和組態模型等常見網路模型,並探討社會學習如何在不同網路結構中傳播。同時,文章也分析了空間網路的特性,以機場航班網路為例,展示如何利用重力模型和空間資料進行網路分析,並探討如何在 NetworkX 中處理和視覺化空間網路資料。
小世界網路與優先依附網路的模擬分析
在複雜網路的研究中,小世界網路和優先依附網路是兩個重要的模型,它們能夠幫助我們理解許多現實世界中的網路結構和行為。
小世界網路
小世界網路是一種介於規則網路和隨機網路之間的網路結構,它具有較短的平均路徑長度和較高的叢集係數。Watts-Strogatz模型是一種典型的用於生成小世界網路的方法。
Watts-Strogatz模型的實作
以下程式碼使用NetworkX函式庫中的watts_strogatz_graph()函式生成Watts-Strogatz小世界網路:
import networkx as nx
import matplotlib.pyplot as plt
plt.figure(figsize=(7.5, 2.25))
for i, p in enumerate([0.0, 0.1, 1.0]):
# 生成圖
G = nx.watts_strogatz_graph(12, 6, p)
# 建立佈局並繪製
plt.subplot(1, 3, i + 1)
pos = nx.circular_layout(G)
nx.draw_networkx(G, pos=pos)
plt.title("p = {:0.1f}".format(p))
內容解密:
watts_strogatz_graph(12, 6, p):生成一個具有12個節點、每個節點初始連線到6個鄰居、並以機率p重新連線邊的Watts-Strogatz小世界網路。circular_layout(G):將節點佈局在一個圓形上,以便於視覺化。draw_networkx(G, pos=pos):根據指定的佈局繪製網路。
Newman-Watts-Strogatz模型的實作
Newman-Watts-Strogatz模型是Watts-Strogatz模型的一個變體,它保證了生成的網路是連通的。
plt.figure(figsize=(7.5, 2.25))
for i, p in enumerate([0.0, 0.1, 1.0]):
# 生成圖
G = nx.newman_watts_strogatz_graph(12, 6, p)
# 建立佈局並繪製
plt.subplot(1, 3, i + 1)
pos = nx.circular_layout(G)
nx.draw_networkx(G, pos=pos)
plt.title("p = {:0.1f}".format(p))
內容解密:
newman_watts_strogatz_graph(12, 6, p):生成一個Newman-Watts-Strogatz小世界網路,保持了網路的連通性。
優先依附網路
優先依附網路是一種具有重尾分佈特性的網路,Barabási-Albert模型是生成這種網路的典型方法。
Barabási-Albert模型的實作
以下程式碼使用NetworkX函式庫中的barabasi_albert_graph()函式生成Barabási-Albert優先依附網路:
G_preferential_35 = nx.barabasi_albert_graph(35, 1)
pos = nx.spring_layout(G_preferential_35, k=0.1)
nx.draw_networkx(G_preferential_35, pos)
內容解密:
barabasi_albert_graph(35, 1):生成一個具有35個節點的Barabási-Albert優先依附網路,每新增一個節點就與1個現有節點連線。spring_layout(G_preferential_35, k=0.1):使用彈簧佈局演算法對網路進行佈局。
度分佈分析
優先依附網路的度分佈遵循冪律分佈,這意味著網路在不同尺度上具有相似的結構。
def plot_degree_hist(G, title):
"""繪製節點度的直方圖"""
plt.hist(dict(nx.degree(G)).values(), bins=range(1, 11))
# 標記坐標軸
plt.xlabel('度')
plt.ylabel('計數')
plt.title(title)
plt.figure(figsize=(7.5, 3.75))
ax = plt.subplot(1,2,1)
plot_degree_hist(G_preferential_35, '35 節點')
for spine in ax.spines.values():
spine.set_visible(True)
ax = plt.subplot(1,2,2)
for spine in ax.spines.values():
spine.set_visible(True)
plot_degree_hist(G_preferential_500, '500 節點')
plt.tight_layout()
內容解密:
plot_degree_hist(G, title):繪製指定網路的度分佈直方圖。dict(nx.degree(G)).values():取得網路中所有節點的度。
組態模型
組態模型是一種用於生成與給定網路具有相同節點度和隨機連線的合成網路的方法。
# 取得空手道俱樂部網路的節點度
G_karate = nx.karate_club_graph()
degree_sequence = dict(nx.degree(G_karate)).values()
# 生成具有相同節點度的隨機網路
G_configuration = nx.degree_seq.configuration_model(degree_sequence)
nx.draw_networkx(G_configuration)
內容解密:
configuration_model(degree_sequence):根據指定的度序列生成一個組態模型網路。
綜上所述,這些模型和方法為我們提供了強大的工具來理解和模擬複雜網路的結構和行為。無論是小世界網路、優先依附網路還是組態模型,都能夠幫助我們深入研究複雜系統的特性,並對現實世界中的問題提供有價值的見解。
社會學習過程中的根據主體的模擬技術
在複雜系統的研究中,根據主體的建模(Agent-based modeling)是一種常見的技術,用於模擬多個稱為主體(agents)的物件。每個主體由其狀態(state)描述,狀態可以是一個簡單的數值或複雜的資料結構。隨著模擬的進行,每個主體與其他主體互動,並根據這些互動更新其狀態。在網路環境中,主體是網路中的節點,並且只允許與其鄰居互動。
社會學習過程模擬
社會學習是指個體透過與他人交流來改進對某個量的估計的過程。例如,一群人對某個數量(如溫度)進行了有噪聲的觀測,並希望估計該數量的真實值。在最簡單的方法中,每個主體對其鄰居的估計進行平均,並將該平均值用作新的估計。
初始化信念值
def initial_beliefs(G, true_value=0, std=15):
"""生成具有正態分佈誤差的真實值的估計。"""
beliefs = dict((v, random.gauss(true_value, std)) for v in G.nodes())
return beliefs
社會學習步驟
def learning_step(G, beliefs):
"""根據鄰居的信念更新每個節點的信念。"""
new_beliefs = dict()
for v in G.nodes():
total = beliefs[v]
count = 1
for w in G.neighbors(v):
total += beliefs[w]
count += 1
new_beliefs[v] = total / count
return new_beliefs
內容解密:
initial_beliefs函式為網路中的每個節點生成一個初始信念值,該值是真實值加上一個正態分佈的隨機誤差。learning_step函式實作了一輪社會學習過程,每個節點根據其鄰居的信念值更新自己的信念值。- 更新規則是將自身信念值與鄰居信念值進行平均,從而得到新的信念值。
模擬與視覺化
def plot_beliefs(G, initial_beliefs, true_value=0, steps=10):
"""繪製信念隨時間變化的圖表。"""
current_beliefs = dict(initial_beliefs)
beliefs = [current_beliefs]
x = dict((v, list()) for v in G.nodes())
y = dict((v, list()) for v in G.nodes())
for i in range(steps + 1):
for v in G.nodes():
x[v].append(i)
y[v].append(current_beliefs[v])
if i < steps:
current_beliefs = learning_step(G, current_beliefs)
beliefs.append(current_beliefs)
for v in G.nodes():
plt.plot(x[v], y[v], 'b-', alpha=0.3, linewidth=2)
mean_value = sum(initial_beliefs.values()) / len(initial_beliefs)
plt.plot([0, steps], [mean_value, mean_value], 'k:')
ax = plt.gca()
for spine in ax.spines.values():
spine.set_visible(True)
plt.xlim([0, steps])
plt.ylim([22, 62])
內容解密:
plot_beliefs函式模擬多輪社會學習過程,並繪製每個節點信念值隨時間變化的曲線。- 該函式還繪製了初始信念值的平均值,以便比較收斂效果。
- 圖表的 x 軸表示時間步,y 軸表示信念值。
不同網路結構下的社會學習
networks = {
'Karate Club': G_karate,
'Configuration Model': G_configuration,
'Preferential Attachment': nx.barabasi_albert_graph(34, 1),
'Ring': nx.watts_strogatz_graph(34, 6, 0),
'Watts-Strogatz (p=0.3)': nx.watts_strogatz_graph(34, 6, 0.1),
'Watts-Strogatz (p=1)': nx.watts_strogatz_graph(34, 6, 1)
}
for i, (title, G) in enumerate(networks.items()):
plt.subplot(3, 2, i + 1)
plt.title(title)
plot_beliefs(G, beliefs, 42)
plt.tight_layout()
圖表翻譯:
此圖展示了在不同網路結構下,社會學習過程的收斂情況。每個子圖對應一種網路結構,展示了所有節點信念值隨時間的變化。
結果分析
不同的網路結構對社會學習過程的收斂速度和結果有顯著影響:
- Karate Club 網路和 Configuration Model 網路收斂到略微偏離初始平均值的位置,因為某些節點具有更高的影響力。
- Preferential Attachment 網路收斂速度較慢,並且允許錯誤的信念持續存在,如果這些信念被高度中心化的節點持有。
- Ring 網路收斂速度較慢,但均勻地收斂到大約正確的值。
- Watts-Strogatz 網路(p=1) 也收斂到大約正確的值,但速度更快。
網路在空間與時間中的應用
在前面的章節中,我們探討了網路的基本概念和特性,但大多數情況下,節點(nodes)被視為存在於抽象空間中,沒有特定的時間或空間屬性。然而,在許多實際應用中,節點和邊(edges)都具有特定的空間或時間屬性。本章將介紹如何分析和視覺化具有空間和時間屬性的網路,並以機場網路和維基百科連結為例進行實證分析。
空間與事件的網路表示
網路可以用來表示幾乎任何型別的關係,包括時間或空間之間的關係。在這兩種情況下,網路的屬性都會受到現實世界中時間和空間約束的影響。同樣,這些網路的視覺化也可以利用螢幕或頁面的空間來傳達有關空間和時間關係的有用資訊。
空間中的網路
許多重要的網路中,節點都與特定的地理位置相關聯,例如:
- 電網
- 道路網路
- 由直飛航班連線的機場
- 電信線路
這些網路中的邊是物理物件,具有物理屬性,可以影響由網路表示的系統的行為。單一的權重衡量標準往往不足夠。例如,當一條邊代表一條光纖電信纜時,纜線的物理長度和頻寬(容量)都是重要的考量。前者影響訊號沿著纜線傳輸的時間,而後者則影響它可以處理的資料量(這兩者都會影響成本!)。此外,一條電信纜只有在連線兩個有通訊需求的物理位置時才是有用的。
重力模型
在空間網路中,長度往往與成本相關,無論是鋪設纜線的貨幣成本,還是長途飛行的時間成本。因此,這些網路往往由許多短邊和較少的長邊構成。同樣,一些型別的網路表現出邊權重隨邊長度減少的特性。例如,在兩個機場之間直接旅行的乘客數量通常隨著距離的增加而減少。因此,如果一條邊具有高權重,可能只是因為它很短,也可能是因為有一些更有趣的事情正在發生。可以使用稱為重力模型的技術來糾正長度對邊權重的影響。
重力模型假設,平均而言,兩個點之間的互動作用強度將與它們之間的距離平方成反比。它們被稱為重力模型,是因為在物理學中,兩個物體之間的引力遵循類別似的定律(至少在你讀到研究生階段之前是這樣)。互動作用的強度也被假設為與每個節點的一些類別似品質的屬性成正比,例如透過機場的總流量。下面將演示如何將簡單的重力模型應用於機場流量。
使用空間資料進行分析
本文將給出在NetworkX中使用空間資料的例子。特別是,這些例子分析了2018年美國大陸地區的直飛航班。在這個網路中,節點代表機場,邊代表這些機場之間的乘客流量。這是一個空間網路,因為機場對應於地理位置,每條邊所跨越的距離在分析網路時是相關的。下面的程式碼逐行載入了網路資料:
# 將資料檔案載入到網路中
from pathlib import Path
data_dir = Path('.') / 'data'
G_air = nx.Graph()
with open(data_dir / 'BTS2018' / 'carrier.csv') as f:
# 跳過標頭
next(f)
# 迴圈遍歷資料行
for row in f:
count, v, w, year, month = row.strip().split(',')
count = int(count)
if count == 0 or v == w:
continue
try:
G_air.edges[v, w]['count'] += count
except KeyError:
G_air.add_edge(v, w, count=count)
內容解密:
- 匯入必要的模組:使用
pathlib中的Path類別來處理檔案路徑。 - 初始化一個空圖:
G_air = nx.Graph()建立了一個新的空無向圖。 - 開啟並讀取資料檔案:
with open(...) as f:開啟了包含航班資料的檔案,並逐行讀取。 - 跳過標頭:
next(f)跳過了CSV檔案的第一行,通常是標頭。 - 解析每一行資料:對於每一行,將其分割成不同的欄位,包括乘客數量、起飛機場程式碼、抵達機場程式碼等。
- 過濾無效資料:如果乘客數量為0或是同一機場之間的航班,則跳過不處理。
- 更新或新增邊:如果兩個機場之間的邊已經存在,則累加乘客數量;否則,新增一條邊並設定初始乘客數量。
airport_lat_long = {}
with open(data_dir / 'partow' / 'GlobalAirportDatabase.txt') as f:
for row in f:
columns = row.strip().split(':')
code = columns[1]
lat = float(columns[14])
long = float(columns[15])
airport_lat_long[code] = (lat, long)
內容解密:
- 建立一個空字典:
airport_lat_long = {}用於儲存機場程式碼與其經緯度的對映。 - 讀取全球機場資料函式庫:開啟包含全球機場資料的檔案,並逐行讀取。
- 解析每行資料:將每行資料按照特定分隔符號分割成多個欄位,並提取機場程式碼、緯度和經度。
- 儲存機場的經緯度資訊:將機場程式碼作為鍵,經緯度作為值儲存在字典中。
for v in list(G_air.nodes()):
try:
lat, long = airport_lat_long[v]
內容解密:
- 遍歷圖中的所有節點:對於
G_air中的每個節點(機場),嘗試從airport_lat_long字典中查詢其經緯度。 - 取得機場的經緯度:如果機場程式碼存在於字典中,則取得其對應的經緯度。
本章介紹瞭如何處理和分析具有空間屬性的網路,包括使用重力模型來理解節點之間的互動作用,以及如何利用NetworkX處理和分析空間資料。透過這些技術,可以更好地理解和分析現實世界中的複雜網路系統。