圖論與圖學習(一):圖的基本概念

選自towardsdatascience

作者:Mal Fabien

機器之心編譯

參與:熊貓

圖(graph)近來正逐漸變成機器學習的一大核心領域,比如你可以透過預測潛在的連線來理解社交網路的結構、檢測欺詐、理解汽車租賃服務的消費者行為或進行實時推薦。近日,資料科學家 Mal Fabien 在其部落格上釋出了涉及圖論、圖演算法和圖學習的系列文章《圖論與圖學習》。

本文是其中第一篇,介紹了圖的一些基礎知識並給出了 Python 示例。更多文章和對應程式碼可訪問:https://github。com/maelfabien/Machine_Learning_Tutorials。

本文涵蓋以下主題:

圖是什麼?

如何儲存圖?

圖的型別和性質

Python 示例

首先進行一些準備工作,開啟 Jupyter Notebook,匯入以下軟體包:

後面的文章會使用 networkx 最新的 2。0 版本。networkx 是一個用於複雜網路的結構、動態和功能的建立、操作和研究的 Python 軟體包。

import numpy as np

import random

import networkx as nx

from IPython。display import Image

import matplotlib。pyplot as plt

我會盡量以實用為目標,努力闡釋每個概念。

圖是什麼?

圖是互連節點的集合。

舉個例子,一個簡單的圖可能是這樣:

圖論與圖學習(一):圖的基本概念

節點(node)用紅色標出,透過黑色的邊(edge)連線。

圖可用於表示:

社交網路

網頁

生物網路

我們可以在圖上執行怎樣的分析?

研究拓撲結構和連線性

群體檢測

識別中心節點

預測缺失的節點

預測缺失的邊

過幾分鐘你就能明白所有這些概念。

我們首先在我們的筆記本中匯入第一個預構建的圖:

# Load the graph

G_karate = nx。karate_club_graph()

# Find key-values for the graph

pos = nx。spring_layout(G_karate)

# Plot the graph

nx。draw(G_karate, cmap = plt。get_cmap(‘rainbow’), with_labels=True, pos=pos)

圖論與圖學習(一):圖的基本概念

空手道圖

這個「空手道」圖表示什麼?Wayne W。 Zachary 在 1970 到 1972 年這三年中研究的一個空手道俱樂部的社交網路。該網路包含了這個空手道俱樂部的 34 個成員,成員對之間的連線表示他們在俱樂部之外也有聯絡。在研究期間,管理員 JohnA 與教練 Mr。Hi(化名)之間出現了衝突,導致俱樂部一分為二。一半成員圍繞 Mr。Hi 形成了一個新的俱樂部,另一半則找了一個新教練或放棄了空手道。基於收集到的資料,除了其中一個成員,Zachary 正確分配了所有成員在分裂之後所進入的分組。

圖的基本表示方法

圖 G=(V, E) 由下列要素構成:

一組節點(也稱為 verticle)V=1,…,n

一組邊 EV×V

邊 (i,j) ∈ E 連線了節點 i 和 j

i 和 j 被稱為相鄰節點(neighbor)

節點的度(degree)是指相鄰節點的數量

圖論與圖學習(一):圖的基本概念

節點、邊和度的示意圖

如果一個圖的所有節點都有 n-1 個相鄰節點,則該圖是完備的(complete)。也就是說所有節點都具備所有可能的連線方式。

從 i 到 j 的路徑(path)是指從 i 到達 j 的邊的序列。該路徑的長度(length)等於所經過的邊的數量。

圖的直徑(diameter)是指連線任意兩個節點的所有最短路徑中最長路徑的長度。

舉個例子,在這個案例中,我們可以計算出一些連線任意兩個節點的最短路徑。該圖的直徑為 3,因為沒有任意兩個節點之間的最短路徑的長度超過 3。

圖論與圖學習(一):圖的基本概念

一個直徑為 3 的圖

測地路徑(geodesic path)是指兩個節點之間的最短路徑。

如果所有節點都可透過某個路徑連線到彼此,則它們構成一個連通分支(connected component)。如果一個圖僅有一個連通分支,則該圖是連通的(connected)。

舉個例子,下面是一個有兩個不同連通分支的圖:

圖論與圖學習(一):圖的基本概念

一個有兩個連通分支的圖

如果一個圖的邊是有順序的配對,則該圖是有向的(directed)。i 的入度(in-degree)是指向 i 的邊的數量,出度(out-degree)是遠離 i 的邊的數量。

圖論與圖學習(一):圖的基本概念

有向圖

如果可以回到一個給定節點,則該圖是有環的(cyclic)。相對地,如果至少有一個節點無法回到,則該圖就是無環的(acyclic)。

圖可以被加權(weighted),即在節點或關係上施加權重。

如果一個圖的邊數量相比於節點數量較小,則該圖是稀疏的(sparse)。相對地,如果節點之間的邊非常多,則該圖是密集的(dense)。

Neo4J 的關於圖演算法的書給出了清晰明瞭的總結:

圖論與圖學習(一):圖的基本概念

總結(來自 Neo4J Graph Book)

我們看看如何用 Python 檢索一個圖的這些資訊:

n=34

G_karate。degree()

。degree() 屬性會返回該圖的每個節點的度(相鄰節點的數量)的列表:

DegreeView({0: 16, 1: 9, 2: 10, 3: 6, 4: 3, 5: 4, 6: 4, 7: 4, 8: 5, 9: 2, 10: 3, 11: 1, 12: 2, 13: 5, 14: 2, 15: 2, 16: 2, 17: 2, 18: 2, 19: 3, 20: 2, 21: 2, 22: 2, 23: 5, 24: 3, 25: 3, 26: 2, 27: 4, 28: 3, 29: 4, 30: 4, 31: 6, 32: 12, 33: 17})

然後,隔離度的值:

# Isolate the sequence of degrees

degree_sequence = list(G_karate。degree())

計算邊的數量,但也計算度序列的度量:

nb_nodes = n

nb_arr = len(G_karate。edges())

avg_degree = np。mean(np。array(degree_sequence)[:,1])

med_degree = np。median(np。array(degree_sequence)[:,1])

max_degree = max(np。array(degree_sequence)[:,1])

min_degree = np。min(np。array(degree_sequence)[:,1])

最後,列印所有資訊:

print(“Number of nodes : ” + str(nb_nodes))

print(“Number of edges : ” + str(nb_arr))

print(“Maximum degree : ” + str(max_degree))

print(“Minimum degree : ” + str(min_degree))

print(“Average degree : ” + str(avg_degree))

print(“Median degree : ” + str(med_degree))

得到:

Number of nodes : 34

Number of edges : 78

Maximum degree : 17

Minimum degree : 1

Average degree : 4。588235294117647

Median degree : 3。0

平均而言,該圖中的每個人都連線了 4。6 個人。

我們可以繪出這些度的直方圖:

degree_freq = np。array(nx。degree_histogram(G_karate))。astype(‘float’)

plt。figure(figsize=(12, 8))

plt。stem(degree_freq)

plt。ylabel(“Frequence”)

plt。xlabel(“Degre”)

plt。show()

圖論與圖學習(一):圖的基本概念

度的直方圖

我們後面會看到,度的直方圖相當重要,可用於確定我們看到的圖的種類。

如何儲存圖?

你可能會好奇我們如何儲存複雜的圖結構?

儲存圖的方式有三種,取決於你想用它做什麼:

儲存為邊列表:

1 2

1 3

1 4

2 3

3 4

。。。

我們儲存有邊連線的每一對節點的 ID。

使用鄰接矩陣,這通常是在記憶體中載入的方式:

圖論與圖學習(一):圖的基本概念

鄰接矩陣

對於圖中的每一個可能的配對,如果兩個節點有邊相連,則設為 1。如果該圖是無向圖,則 A 是對稱的。

使用鄰接列表:

1 : [2,3, 4]

2 : [1,3]

3: [2, 4]

。。。

最好的表示方式取決於用法和可用的記憶體。圖通常可存為 。txt 檔案。

圖可能包含一些擴充套件:

加權的邊

節點/邊上加標籤

加上與節點/邊相關的特徵向量

圖的型別

在這一節,我們將介紹兩種主要的圖型別:

Erdos-Rényi

Barabasi-Albert

Erdos-Rényi 模型

定義

在 Erdos-Rényi 模型中,我們構建一個帶有 n 個節點的隨機圖模型。這個圖是透過以機率 p 獨立地在節點 (i,j) 對之間畫邊來生成的。因此,我們有兩個引數:節點數量 n 和機率 p。

圖論與圖學習(一):圖的基本概念

Erdos-Rényi 圖

在 Python 中,networkx 軟體包有用於生成 Erdos-Rényi 圖的內建函式。

# Generate the graph

n = 50

p = 0。2

G_erdos = nx。erdos_renyi_graph(n,p, seed =100)

# Plot the graph

plt。figure(figsize=(12,8))

nx。draw(G_erdos, node_size=10)

這會得到類似於下圖的結果:

圖論與圖學習(一):圖的基本概念

生成的圖

度分佈

令 pk 為隨機選取的節點的度為 k 的機率。由於圖構建所使用的隨機方式,這種圖的度的分佈是二項式的:

圖論與圖學習(一):圖的基本概念

二項式節點度分佈

每個節點的度數量的分佈應該非常接近於均值。觀察到高數量節點的機率呈指數下降。

degree_freq = np。array(nx。degree_histogram(G_erdos))。astype(‘float’)

plt。figure(figsize=(12, 8))

plt。stem(degree_freq)

plt。ylabel(“Frequence”)

plt。xlabel(“Degree”)

plt。show()

為了視覺化該分佈,我將所生成的圖中的 n 增大到了 200。

圖論與圖學習(一):圖的基本概念

度分佈

描述性統計

平均度由 n×p 給出。在 p=0。2 和 n=200 時,中心在 40 左右

度期望由 (n1)×p 給出

平均值附近的度最多

我們用 Python 來檢索這些值:

# Get the list of the degrees

degree_sequence_erdos = list(G_erdos。degree())

nb_nodes = n

nb_arr = len(G_erdos。edges())

avg_degree = np。mean(np。array(degree_sequence_erdos)[:,1])

med_degree = np。median(np。array(degree_sequence_erdos)[:,1])

max_degree = max(np。array(degree_sequence_erdos)[:,1])

min_degree = np。min(np。array(degree_sequence_erdos)[:,1])

esp_degree = (n-1)*p

print(“Number of nodes : ” + str(nb_nodes))

print(“Number of edges : ” + str(nb_arr))

print(“Maximum degree : ” + str(max_degree))

print(“Minimum degree : ” + str(min_degree))

print(“Average degree : ” + str(avg_degree))

print(“Expected degree : ” + str(esp_degree))

print(“Median degree : ” + str(med_degree))

會得到類似這樣的結果:

Number of nodes : 200

Number of edges : 3949

Maximum degree : 56

Minimum degree : 25

Average degree : 39。49

Expected degree : 39。800000000000004

Median degree : 39。5

這裡的平均度和期望度非常接近,因為兩者之間只有很小的因子。

Barabasi-Albert 模型

定義

在 Barabasi-Albert 模型中,我們構建一個有 n 個節點的隨機圖模型,其有一個優先連線(preferential attachment)分量。這種圖可透過以下演算法生成:

步驟 1:以機率 p 執行步驟 2,否則執行步驟 3

步驟 2:將一個新節點連線到隨機均勻選取的已有節點

步驟 3:以與 n 個已有節點成比例的機率將這個新節點連線到這 n 個已有節點

這個圖的目標是建模優先連線(preferential attachment),真實世界網路中常會觀察到這一點。(注:優先連線是指根據各個個體或物件已有的量來分配某個量,這通常會進一步加大優勢個體的優勢。)

在 Python 中,networkx 軟體包有用於生成 Barabasi-Albert 圖的內建函式。

# Generate the graph

n = 150

m = 3

G_barabasi = nx。barabasi_albert_graph(n,m)

# Plot the graph

plt。figure(figsize=(12,8))

nx。draw(G_barabasi, node_size=10)

這會得到類似下圖的結果:

圖論與圖學習(一):圖的基本概念

Barabasi-Albert 圖

可以看到,某些節點的度顯然比其它節點多很多!

度分佈

令 pk 為隨機選取的節點的度為 k 的機率。則這個度分佈遵循冪律:

圖論與圖學習(一):圖的基本概念

冪律度分佈

這個分佈是重尾分佈。其中有很多節點的度都很小,但也有相當數量的節點有較高的度。

degree_freq = np。array(nx。degree_histogram(G_barabasi))。astype(‘float’)

plt。figure(figsize=(12, 8))

plt。stem(degree_freq)

plt。ylabel(“Frequence”)

plt。xlabel(“Degree”)

plt。show()

圖論與圖學習(一):圖的基本概念

度分佈

據說這個分佈是無標度的(scale-free),平均度不能提供什麼資訊。

描述性統計

如果 α≤2,平均度為一個常量,否則就會發散。

最大度遵照以下順序:

圖論與圖學習(一):圖的基本概念

# Get the list of the degrees

degree_sequence_erdos = list(G_erdos。degree())

nb_nodes = n

nb_arr = len(G_erdos。edges())

avg_degree = np。mean(np。array(degree_sequence_erdos)[:,1])

med_degree = np。median(np。array(degree_sequence_erdos)[:,1])

max_degree = max(np。array(degree_sequence_erdos)[:,1])

min_degree = np。min(np。array(degree_sequence_erdos)[:,1])

esp_degree = (n-1)*p

print(“Number of nodes : ” + str(nb_nodes))

print(“Number of edges : ” + str(nb_arr))

print(“Maximum degree : ” + str(max_degree))

print(“Minimum degree : ” + str(min_degree))

print(“Average degree : ” + str(avg_degree))

print(“Expected degree : ” + str(esp_degree))

print(“Median degree : ” + str(med_degree))

會得到類似以下的結果:

Number of nodes : 200

Number of edges : 3949

Maximum degree : 56

Minimum degree : 25

Average degree : 39。49

Expected degree : 39。800000000000004

Median degree : 39。5

總結

我們介紹了主要的圖型別以及用於描述圖的最基本的屬性。下一篇文章我們將深入圖分析/演算法以及用於分析圖的不同方法。圖可用於:

實時欺詐檢測

實時推薦

精簡法規遵從性

複雜網路的管理和監控

身份和訪問管理

社交應用/功能

擴充套件閱讀:

Neo4j 的圖演算法全面指南,Mark Needham & Amy E。 Hodler:https://go。neo4j。com/rs/710-RRC-335/images/Comprehensive-Guide-to-Graph-Algorithms-in-Neo4j-ebook-EN-US。pdf

Networkx 文件:https://networkx。github。io/documentation/stable/

原文連結:https://towardsdatascience。com/introduction-to-graphs-part-1-2de6cda8c5a5