Chuyển đến nội dung chính

Phân tích Mạng Xã hội trong Python

Ngày nay, các mạng là một phần của đời sống thường nhật. Hãy học cách trực quan hóa và hiểu một mạng xã hội trong Python bằng Networks.
· 12 phút đọc

Khám phá cùng AI

Nếu bạn muốn học về Phân tích Mạng, hãy tham gia khóa học Network Analysis in Python (Phần 1) của DataCamp.

Mạng lưới có ở khắp mọi nơi: mạng lưới đường sá, mạng bạn bè và người theo dõi trên mạng xã hội, hay mạng đồng nghiệp trong văn phòng. Chúng đóng vai trò quan trọng trong cuộc sống hằng ngày của chúng ta, từ việc lan truyền thông tin hữu ích đến ảnh hưởng các cuộc bầu cử quốc gia. Khả năng phân tích các mạng này và đưa ra quyết định dựa trên chúng là một kỹ năng quan trọng với bất kỳ nhà phân tích dữ liệu nào.

Trọng tâm của hướng dẫn này là dạy phân tích mạng xã hội (SNA) bằng Python và NetworkX, một thư viện Python dùng để nghiên cứu cấu trúc, động lực và chức năng của các mạng phức tạp. Hướng dẫn này giả định người đọc đã quen với cú pháp cơ bản của Python, không yêu cầu kiến thức SNA trước đó.

Giới thiệu

Trước hết, hãy bắt đầu với khái niệm Mạng xã hội là gì. Bên dưới bạn thấy một mạng gồm các diễn viên Bollywood là các nút. Họ được kết nối bằng các đường thẳng nếu đã cùng tham gia ít nhất một bộ phim.

bollywood actors

Vì vậy, ta có thể thấy cả Amitabh Bachchan và Abhishek Bachchan đều đã diễn cùng tất cả diễn viên trong mạng, trong khi Akshay Kumar chỉ làm việc với hai Bachchan. Thú vị phải không!

Đây cũng là một mạng xã hội. Bất kỳ mạng nào có các kết nối giữa các cá nhân, trong đó kết nối thể hiện mối quan hệ giữa họ, đều là mạng xã hội. Phân tích các mạng này có thể mang lại những hiểu biết sâu sắc về những người trong mạng, như ai là người có sức ảnh hưởng thực sự, ai kết nối nhiều nhất, v.v.

Mỗi mạng gồm có:

  • Nút (Nodes): Các cá nhân mà ta đang xây dựng mạng của họ. Trong ví dụ trên là các diễn viên.
  • Cạnh (Edges): Kết nối giữa các nút. Nó biểu diễn mối quan hệ giữa các nút trong mạng. Trong ví dụ của chúng ta, mối quan hệ là các diễn viên đã làm việc cùng nhau.

Tạo một mạng bằng NetworkX

Có nhiều loại mạng khác nhau. Chúng ta sẽ dùng NetworkX để xây dựng và phân tích các mạng này. Để bắt đầu, bạn cần cài đặt NetworkX: Bạn có thể dùng:

pip install networkx

hoặc nếu làm việc trong Anaconda

conda install -c anaconda networkx

Điều này sẽ cài đặt phiên bản mới nhất của networkx. Mã trong hướng dẫn này được thực hiện trên Python=3.5, NetworkX = phiên bản 2.0.

Mạng đối xứng

Mạng diễn viên mà ta tạo ở trên là một mạng đối xứng vì mối quan hệ "cùng làm việc trong một bộ phim" là mối quan hệ đối xứng. Nếu A có liên hệ với B, thì B cũng có liên hệ với A. Hãy tạo mạng như trên trong NetworkX.

Chúng ta sẽ dùng phương thức Graph() để tạo một mạng mới và add_edge() để thêm một cạnh giữa hai nút.

import networkx as nx
G_symmetric = nx.Graph()
G_symmetric.add_edge('Amitabh Bachchan','Abhishek Bachchan')
G_symmetric.add_edge('Amitabh Bachchan','Aamir Khan')
G_symmetric.add_edge('Amitabh Bachchan','Akshay Kumar')
G_symmetric.add_edge('Amitabh Bachchan','Dev Anand')
G_symmetric.add_edge('Abhishek Bachchan','Aamir Khan')
G_symmetric.add_edge('Abhishek Bachchan','Akshay Kumar')
G_symmetric.add_edge('Abhishek Bachchan','Dev Anand')
G_symmetric.add_edge('Dev Anand','Aamir Khan')

Bây giờ hãy trực quan hóa mạng vừa xây dựng bằng nx.draw_networkx(G_symmetric).

visualized network

Mạng bất đối xứng

Nếu mối quan hệ giữa các nút là 'con của', thì mối quan hệ không còn đối xứng nữa. Nếu A là con của B, thì B không phải là con của A. Một mạng trong đó mối quan hệ bất đối xứng (A có liên hệ với B không nhất thiết có nghĩa là B có liên hệ với A) được gọi là mạng bất đối xứng. Ta có thể xây dựng mạng bất đối xứng trong NetworkX bằng phương thức DiGraph, viết tắt của Đồ thị có hướng. Hãy tạo một đồ thị bất đối xứng.

G_asymmetric = nx.DiGraph()
G_asymmetric.add_edge('A','B')
G_asymmetric.add_edge('A','D')
G_asymmetric.add_edge('C','A')
G_asymmetric.add_edge('D','E')

Bây giờ ta trực quan hóa nó. Có thể dùng hàm draw_networkx() như trước. Tuy nhiên, có khả năng các nút không tách biệt và hiển thị rõ ràng trong mạng được vẽ. Để xử lý điều này, ta có thể dùng hàm ép bố cục, giúp định vị các nút theo cách có thể nhìn rõ ràng. Ta thực hiện điều này bằng hàm spring_layout(), sau đó gọi hàm draw_networkx().

nx.spring_layout(G_asymmetric)
nx.draw_networkx(G_asymmetric)

Bên dưới bạn có thể thấy mạng khi có và không dùng lệnh bố cục. Bản sử dụng lệnh bố cục rõ ràng hơn.

visualized network 2

Mạng có trọng số

Cho đến giờ chúng ta có các mạng không có trọng số, nhưng cũng có thể xây dựng mạng có trọng số, ví dụ trong mạng ban đầu nếu ta xem số lượng phim đã đóng cùng nhau là một trọng số, ta sẽ có một Mạng có trọng số. Hãy tạo lại mạng của các diễn viên, nhưng lần này ta thêm trọng số vào mạng, mỗi cạnh có một trọng số biểu thị số phim họ đã đóng cùng nhau.

G_weighted = nx.Graph()
G_weighted.add_edge('Amitabh Bachchan','Abhishek Bachchan', weight=25)
G_weighted.add_edge('Amitabh Bachchan','Aaamir Khan', weight=8)
G_weighted.add_edge('Amitabh Bachchan','Akshay Kumar', weight=11)
G_weighted.add_edge('Amitabh Bachchan','Dev Anand', weight=1)
G_weighted.add_edge('Abhishek Bachchan','Aaamir Khan', weight=4)
G_weighted.add_edge('Abhishek Bachchan','Akshay Kumar',weight=7)
G_weighted.add_edge('Abhishek Bachchan','Dev Anand', weight=1)
G_weighted.add_edge('Dev Anand','Aaamir Khan',weight=1)
weighted network

Hình trên cho thấy mạng có trọng số của các diễn viên trong bố cục circular. Độ dày của cạnh biểu thị trọng số giữa hai nút.

Multigraph

Ta có thể gán các thuộc tính khác nhau cho các cạnh. Ví dụ, ta có thể định nghĩa quan hệ hàng xóm giữa hai nút 'A' và 'B' bằng thuộc tính relation. Nếu trong một mạng, hai nút được nối với hai cạnh (quan hệ) khác nhau, ta có một multigraph. Ta có thể tạo một multigraph bằng lớp MultiGraph.

G = nx.MultiGraph()
G.add_edge('A','B',relation ='neighbor')
G.add_edge('A','B',relation='friend)
G.add_edge('B','C', relation='neighbor')
G.add_edge('D','C',relation='friend')

Đoạn mã này sẽ tạo một đồ thị với hai cạnh giữa A và B. Ta có thể kiểm tra các kết nối bằng G.edges(), đầu ra sẽ hiển thị:

MultiEdgeDataView([('A', 'B', {'relation': 'neighbor'}), ('A', 'B', {'relation': 'friend'}), ('B', 'C', {'relation': 'neighbor'}), ('B', 'D', {'relation': 'neighbor'}), ('C', 'D', {'relation': 'friend'})])

Khả năng kết nối mạng

Giờ mạng đã được tạo, liệu chúng ta có thể biết thêm về một nút cụ thể trong mạng không? Câu trả lời là có, hãy cùng khám phá một vài khía cạnh.

Bậc (Degree)

Bậc của một nút là số lượng kết nối mà nút đó có. NetworkX có hàm degree mà ta có thể dùng để xác định bậc của một nút trong mạng.

nx.degree(G_symmetric, 'Dev Anand`)

Hàm này sẽ trả về giá trị 3, vì Dev Anand chỉ làm việc với ba diễn viên trong mạng.

Hệ số gom cụm

Quan sát thấy rằng những người có chung kết nối trong mạng xã hội thường có xu hướng hình thành liên kết với nhau. Nói cách khác, mạng xã hội có xu hướng hình thành các cụm. Ta có thể xác định cụm của một nút, tức Hệ số gom cụm cục bộ, là tỷ lệ các cặp bạn của nút (tức các kết nối) có kết nối với nhau. Để xác định hệ số gom cụm cục bộ, ta sử dụng hàm nx.clustering(Graph, Node).

Trong mạng diễn viên đối xứng, bạn sẽ thấy rằng Dev Anand có hệ số gom cụm cục bộ bằng 1 và Abhishek Bachchan có hệ số gom cụm cục bộ là 0,67.

Hệ số gom cụm trung bình (tổng tất cả hệ số gom cụm cục bộ chia cho số nút) của mạng diễn viên đối xứng là 0,867. Ta có thể lấy giá trị này bằng:

nx.average_clustering(G_symmetric)

Khoảng cách

Ta cũng có thể xác định đường đi ngắn nhất giữa hai nút và độ dài của nó trong NetworkX bằng các hàm nx.shortest_path(Graph, Node1, Node2) và nx.shortest_path_length(Graph, Node1, Node2) tương ứng.

Chạy

nx.shortest_path(G_symmetric, 'Dev Anand', 'Akshay Kumar')

Trả về

['Dev Anand', 'Amitabh Bachchan', 'Akshay Kumar']

Ta có thể tìm khoảng cách của một nút tới mọi nút khác trong mạng bằng thuật toán tìm kiếm theo chiều rộng (BFS), bắt đầu từ nút đó. NetworkX cung cấp hàm bfs_tree để làm điều này. Vì vậy nếu bạn thử T = nx.bfs_tree(G_symmetric, 'Dev Anand') rồi vẽ cây này, bạn sẽ nhận được một cấu trúc mạng cho biết cách đi đến các nút khác trong mạng bắt đầu từ Dev Anand

nodes

Độ lệch tâm (Eccentricity)

Độ lệch tâm của một nút A được định nghĩa là khoảng cách lớn nhất giữa A và tất cả các nút khác. Có thể tìm bằng hàm nx.eccentricity(). Trong mạng diễn viên đối xứng, Dev Anand có độ lệch tâm bằng 2, và Abhishek Bachchan có độ lệch tâm bằng 1 (vì kết nối với tất cả).

Những người ảnh hưởng trong mạng

Ở trên chúng ta đã học một số thước đo khoảng cách trong mạng, hữu ích để biết thông tin sẽ lan truyền như thế nào qua mạng. Trong phần này, chúng ta sẽ học cách tìm các nút (cá nhân) quan trọng nhất trong mạng. Các tham số này được gọi là thước đo trung tâm (centrality).

Bạn còn nhớ cô gái nổi tiếng hồi trung học hay vận động viên bóng chày chủ chốt của trường không? Họ là những người có thể khiến trải nghiệm trung học của bạn trở nên tệ hại hoặc tuyệt vời. Điều gì mang lại cho họ sức mạnh đó? Các thước đo trung tâm có thể giúp chúng ta xác định mức độ nổi tiếng, được yêu thích nhất và những người có ảnh hưởng lớn nhất trong mạng.

Độ trung tâm theo bậc (Degree Centrality)

Những người nổi tiếng hoặc được yêu thích hơn thường là những người có nhiều bạn bè hơn. Độ trung tâm theo bậc đo lường số lượng kết nối mà một nút cụ thể có trong mạng. Nó dựa trên thực tế rằng các nút quan trọng có nhiều kết nối. NetworkX có hàm degree_centrality() để tính độ trung tâm theo bậc cho tất cả các nút trong mạng.

Độ trung tâm riêng (Eigenvector Centrality)

Không chỉ số lượng người mà một cá nhân kết nối, mà cả kiểu người họ kết nối cũng có thể quyết định tầm quan trọng của một nút. Ở các con đường Delhi, mỗi khi cảnh sát giao thông bắt một người vi phạm, câu đầu tiên họ nghe thường là "Anh có biết tôi quen ai không?".

Độ trung tâm riêng đo lường chính điều này. Nó xác định một nút là quan trọng nếu nó kết nối với các nút quan trọng khác. Ta có thể dùng hàm eigenvector_centrality() của NetworkX để tính độ trung tâm riêng cho tất cả các nút trong một mạng.

Thuật toán Pagerank của Google là một biến thể của thuật toán độ trung tâm riêng.

Độ trung tâm trung gian (Betweenness Centrality)

Độ trung tâm trung gian là độ trung tâm của quyền kiểm soát. Nó biểu diễn tần suất một điểm xuất hiện trên các đường địa trắc (đường đi ngắn nhất) nối các cặp điểm. Nó định lượng số lần một nút cụ thể nằm trên đường đi ngắn nhất được chọn giữa hai nút khác. Những nút có độ trung tâm trung gian cao đóng vai trò quan trọng trong luồng liên lạc/thông tin trong mạng. Các nút có độ trung tâm trung gian cao có thể có quyền kiểm soát chiến lược và ảnh hưởng đến những người khác. Một cá nhân ở vị trí chiến lược như vậy có thể ảnh hưởng đến cả nhóm, bằng cách giữ lại hoặc làm sai lệch thông tin trong quá trình truyền tải.

NetworkX có hàm betweenness_centrality() để đo lường chỉ số này cho mạng. Nó có các tùy chọn để chọn việc chuẩn hóa giá trị betweenness hay không, có đưa trọng số vào tính toán trung tâm hay không, và có tính cả các điểm cuối trong số đếm đường đi ngắn nhất hay không.

Kết hợp tất cả

Hãy bắt đầu với dữ liệu Facebook; cho phân tích ở đây chúng ta sẽ dùng bộ dữ liệu mạng ego kết hợp của Facebook, chứa mạng tổng hợp danh sách bạn bè Facebook của mười cá nhân. Bạn có thể tải tệp facebook_combined.txt cần thiết từ trang của Đại học Stanford.

Bạn có thể lấy dữ liệu Facebook/Twitter của riêng mình bằng các API của Facebook/Twitter. Hãy đón xem hướng dẫn sắp tới, nơi chúng ta sẽ học cách dùng API Facebook và Twitter để lấy dữ liệu và áp dụng các kiến thức ở đây để phân tích.

Chúng ta đọc tệp và dựng đồ thị:

G_fb = nx.read_edgelist("facebook_combined.txt", create_using = nx.Graph(), nodetype=int)

Mạng gồm 4.039 nút, được kết nối qua 88.234 cạnh! Vâng, đó là một mạng lớn. Bạn có thể lấy thông tin này bằng hàm info().

[In]: print(nx.info(G_fb))


[Out]: Name:
       Type: Graph
       Number of nodes: 4039
       Number of edges: 88234
       Average degree:  43.6910

Bên dưới bạn có thể thấy mạng:

network

Ta cũng có thể trực quan hóa mạng sao cho màu của nút thay đổi theo Bậc (Degree) và kích thước nút theo Độ trung tâm trung gian (Betweenness Centrality). Mã để làm điều này là:

pos = nx.spring_layout(G_fb)
betCent = nx.betweenness_centrality(G_fb, normalized=True, endpoints=True)
node_color = [20000.0 * G_fb.degree(v) for v in G_fb]
node_size =  [v * 10000 for v in betCent.values()]
plt.figure(figsize=(20,20))
nx.draw_networkx(G_fb, pos=pos, with_labels=False,
                 node_color=node_color,
                 node_size=node_size )
plt.axis('off')

Và đồ thị thu được là:

resulting graph

Bạn cũng có thể biết nhãn của các nút có độ trung tâm trung gian cao nhất bằng cách:

sorted(betCent, key=betCent.get, reverse=True)[:5]

Bảng dưới đây liệt kê năm nhãn nút có giá trị các thước đo trung tâm cao nhất.

Độ trung tâm theo bậcĐộ trung tâm riêngĐộ trung tâm trung gian
1071912107
168422661684
191222063437
343722331912
024641085

Ta có thể thấy một số nút xuất hiện ở cả Độ trung tâm theo bậc, là thước đo về bậc, và Độ trung tâm trung gian, vốn kiểm soát luồng thông tin. Điều này là tự nhiên vì các nút kết nối nhiều hơn cũng thường nằm trên các đường đi ngắn nhất giữa những nút khác. Nút 1912 là một nút quan trọng vì nó then chốt theo cả ba thước đo trung tâm mà chúng ta đã xét.

Tài liệu tham khảo

  • Dữ liệu diễn viên được lấy từ trang IMDB
  • Nơi tốt nhất để tìm hiểu thêm về NetworkX và các hàm của nó là tài liệu của thư viện

Nếu bạn muốn tìm hiểu thêm về Phân tích Mạng Xã hội trong Python, hãy tham gia khóa học Analyzing Social Media Data in Python của DataCamp.

Chủ đề

Liên quan