เทคนิคที่ 081 · PYTHON / JAVASCRIPT

กราฟกลุ่มย่อยCommunity Graph

ให้อัลกอริทึมบอกว่ามีกี่กลุ่ม แทนที่จะให้ตาเดา

5
เฉพาะทางควรรู้ก่อน · เข้าใจ force-directed graph และแนวคิดการจัดกลุ่ม
ลองเล่น

01ภาพรวมของกราฟนี้

Community graph คือ force-directed graph ที่เพิ่มขั้นตอนคำนวณกลุ่มย่อยด้วยอัลกอริทึมก่อนแล้วระบายสีตามกลุ่ม จุดแข็งคือขอบเขตของกลุ่มมาจากการคำนวณไม่ใช่จากตำแหน่งที่ตาเห็น แต่ผลลัพธ์ขึ้นกับอัลกอริทึมและพารามิเตอร์ที่เลือกอย่างมาก

เปรียบเทียบให้เห็นภาพ

เหมือนให้เครื่องนับคะแนนบอกว่าผู้สมัครแบ่งเป็นกี่ขั้ว แทนที่จะดูจากภาพที่นั่งในสภาแล้วเดาเอง

ใช้ที่ไหนบ้าง — หาชุมชนในเครือข่ายสังคม แบ่งกลุ่มลูกค้าตามพฤติกรรมที่เชื่อมโยงกัน หรือหาขอบเขตของระบบย่อยในสถาปัตยกรรมซอฟต์แวร์

สร้างอย่างไร

  1. ขั้นที่ 1รันอัลกอริทึมหาชุมชน เช่น Louvain หรือ Leiden
  2. ขั้นที่ 2ตรวจค่า modularity ว่ากลุ่มที่ได้มีความหมายจริง
  3. ขั้นที่ 3วางโหนดด้วยการจำลองแรง
  4. ขั้นที่ 4ใช้สีบอกกลุ่มและรายงานจำนวนกลุ่มที่พบ

ตัวอย่างคลาสสิก · การหาชุมชนในเครือข่ายการอ้างอิงงานวิจัย

นักวิเคราะห์เครือข่ายใช้อัลกอริทึม Louvain กับเครือข่ายการอ้างอิงงานวิจัย แล้วพบว่ากลุ่มที่ได้ตรงกับสาขาย่อยที่นักวิจัยรู้จักกันอยู่แล้วเป็นส่วนใหญ่ ซึ่งเป็นการยืนยันว่าวิธีนี้ใช้ได้ และกลุ่มที่ไม่ตรงก็กลายเป็นจุดเริ่มต้นของการค้นพบสาขาใหม่

Wikipedia · Louvain method

02อธิบายภาษาคนเข้าใจง่าย ๆ

เวลาดู force-directed graph คนมักเห็นกระจุกแล้วสรุปว่านั่นคือกลุ่ม ซึ่งอันตราย เพราะกระจุกอาจเกิดจากการจำลองแรงล้วน ๆ ไม่ได้สะท้อนโครงสร้างจริง

Community graph แก้ด้วยการเพิ่มขั้นตอนคำนวณ อัลกอริทึมหาชุมชนจะมองหาการแบ่งที่ทำให้เส้นเชื่อมภายในกลุ่มมีมากกว่าที่คาดจากการสุ่มมากที่สุด

ผลคือสีที่เห็นมาจากโครงสร้างของข้อมูลจริง ไม่ใช่จากตำแหน่งบนภาพ ซึ่งแปลว่าถ้าอัลกอริทึมบอกว่าสองโหนดอยู่กลุ่มเดียวกัน มันก็จริงแม้ทั้งสองจะอยู่คนละมุมของภาพ

ราคาที่จ่ายอย่างแรกคืออัลกอริทึมหาชุมชนคืนกลุ่มมาให้เสมอ แม้เครือข่ายนั้นจะไม่มีโครงสร้างกลุ่มจริง ๆ เลย จึงต้องดูค่า modularity ควบคู่ไปด้วย ถ้าต่ำกว่าราวสามส่วนสิบก็แปลว่ากลุ่มที่ได้แทบไม่มีความหมาย

อย่างที่สองคืออัลกอริทึมคนละตัวหรือพารามิเตอร์คนละค่าให้จำนวนกลุ่มต่างกันได้มาก จึงต้องระบุเสมอว่าใช้อะไรและตั้งค่าอย่างไร

03ข้อมูลที่ต้องใช้

รูปทรงของข้อมูลรายการเส้นเชื่อม source–target–value
จำนวนมิติที่เข้ารหัสได้3 มิติ
จำนวนแถวที่เหมาะ40–300 เส้นเชื่อมขั้นต่ำ 10 แถว
เส้นฐานศูนย์ไม่เกี่ยวข้องไม่มีแกนค่า

คอลัมน์ที่ต้องเตรียม

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
sourceโหนดต้นทางโหนดpath20–200 โหนดต้องมีเส้นเชื่อมมากพอให้หากลุ่มได้
targetโหนดปลายทางโหนดpathชุดเดียวกับ sourceเครือข่ายต้องไม่เบาบางเกินไป
value
ไม่บังคับ
น้ำหนักความสัมพันธ์ตัวเลขต่อเนื่องsizeบวกเท่านั้นอัลกอริทึมส่วนใหญ่ใช้น้ำหนักได้

ต้องเตรียมข้อมูลอย่างไรก่อนวาด

  1. ★ รันอัลกอริทึมหาชุมชนและบันทึกค่า modularity
  2. ยุบกลุ่มที่มีสมาชิกน้อยกว่าสามเป็นกลุ่มอื่น ๆ
  3. ล็อกค่าเริ่มต้นของการสุ่มทั้งของอัลกอริทึมและของการจำลองแรง

ค่าที่หายไป — โหนดโดดเดี่ยวจะถูกจัดเป็นกลุ่มของตัวเอง ควรแยกออกและรายงานจำนวน

สเกลของแกน — ใช้สีเชิงหมวดหมู่ตามลำดับคงที่ ไม่เกิน 8 กลุ่ม และสีต้องผูกกับกลุ่มไม่ใช่กับอันดับขนาด

กราฟจะเริ่มพังเมื่อไร

เกิน 8 กลุ่ม สีแยกไม่ออกแล้ว ต้องยุบกลุ่มเล็กเป็นอื่น ๆ

หน้าตาไฟล์ที่ต้องเตรียม

source,target,value
เข้าชมเว็บ,ดูสินค้า,7975
เข้าชมเว็บ,ออกทันที,4078

04อ่านแล้วเห็นอะไร

สิ่งที่เห็นได้จากภาพ

  • จำนวนกลุ่มย่อยที่อัลกอริทึมพบ
  • ขนาดของแต่ละกลุ่ม
  • โหนดสะพานที่เชื่อมสองกลุ่มเข้าด้วยกัน
  • กลุ่มที่แยกตัวจากส่วนอื่นโดยสิ้นเชิง

สิ่งที่กราฟนี้ตอบไม่ได้

  • ★ อัลกอริทึมคืนกลุ่มมาเสมอแม้ไม่มีโครงสร้างกลุ่มจริง จึงต้องดูค่า modularity ควบคู่
  • อัลกอริทึมต่างกันให้จำนวนกลุ่มต่างกัน จึงไม่มีคำตอบเดียวที่ถูก
  • ตำแหน่งของโหนดยังคงไม่มีความหมายเหมือน force-directed

อ่านตามลำดับนี้

  1. อ่านค่า modularity ก่อนว่ากลุ่มมีความหมายจริงไหม
  2. นับจำนวนสีเพื่อรู้จำนวนกลุ่ม
  3. มองหาโหนดที่มีเส้นออกไปหลายสี ซึ่งคือสะพาน

คำถามที่ตอบได้

  • เครือข่ายนี้แบ่งเป็นกี่กลุ่มจริง ๆ
  • กลุ่มไหนใหญ่ที่สุด
  • ใครทำหน้าที่เชื่อมระหว่างกลุ่ม

สัญญาณว่ามีอะไรผิด

  • ไม่รายงานค่า modularity หรืออัลกอริทึมที่ใช้
  • กลุ่มมากเกิน 8 จนสีแยกไม่ออก
  • สีเปลี่ยนเมื่อกรองข้อมูล ทำให้กลุ่มเดิมกลายเป็นสีอื่น

05เหมาะกับการนำเสนอแบบไหน

ผู้ชมที่เหมาะนักวิเคราะห์ที่ต้องการหลักฐานเชิงปริมาณของการแบ่งกลุ่ม
เวลาที่ผู้ชมต้องใช้ต้องอธิบาย
ขนาดเล็กสุดที่ยังอ่านได้440×380 px
รายงานเชิงวิเคราะห์
สื่อสารกับคนทั่วไป
สิ่งพิมพ์
สไลด์ผู้บริหารต้องอธิบายว่ากลุ่มมาจากอัลกอริทึมอะไร
dashboard ที่อัปเดตตลอดกลุ่มอาจเปลี่ยนทุกครั้งที่ข้อมูลอัปเดต

ทำอย่างไรให้คนอ่านได้ข้อสรุปโดยไม่ต้องบรรยาย

  1. ★ ระบุอัลกอริทึม พารามิเตอร์ และค่า modularity ในคำอธิบายเสมอ
  2. ตั้งชื่อกลุ่มตามลักษณะร่วมของสมาชิก ไม่ใช่เรียกว่ากลุ่มที่ 1 2 3
  3. ทำเครื่องหมายโหนดสะพานให้เด่น

รูปแบบชื่อกราฟที่ควรใช้

เครือข่ายแบ่งเป็น <จำนวน> กลุ่ม (modularity <ค่า>) โดยกลุ่ม <ชื่อ> ใหญ่ที่สุด

06เอาไปใช้ต่อ

โค้ดทุกชิ้นอ่านไฟล์ community-graph-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง

# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด community-graph-sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์
import matplotlib
matplotlib.use("Agg")   # รันแบบไม่มีหน้าจอ ถ้ารันในเครื่องตัวเองลบบรรทัดนี้ได้
import matplotlib.pyplot as plt
import pandas as pd
import networkx as nx

C1, C2, C3 = "#2a78d6", "#eb6834", "#1baf7a"   # palette ของคลัง เปลี่ยนเป็นสีองค์กรได้
INK, SURFACE = "#0b0b0b", "#fcfcfb"

df = pd.read_csv("community-graph-sample.csv")
df["value"] = pd.to_numeric(df["value"], errors="coerce")
NOTE = "color"   # ← ค่าจาก Playground

fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)

G = nx.from_pandas_edgelist(df, "source", "target", edge_attr="value")
comms = nx.community.louvain_communities(G, seed=42)       # seed ล็อกเพื่อให้ผลซ้ำได้
q = nx.community.modularity(G, comms)                      # < 0.3 = กลุ่มแทบไม่มีความหมาย
cid = {n: i for i, c in enumerate(comms) for n in c}
pos = nx.spring_layout(G, seed=42)
nx.draw_networkx_edges(G, pos, ax=ax, edge_color="#c9c6bd", width=1.2)
nx.draw_networkx_nodes(G, pos, ax=ax, node_size=180,
                       node_color=[PALETTE[cid[n] % len(PALETTE)] for n in G])
nx.draw_networkx_labels(G, pos, ax=ax, font_size=8)
ax.set_title(f"{len(comms)} กลุ่ม · modularity = {q:.2f}", loc="left")
ax.set_axis_off()

ax.spines[["top", "right"]].set_visible(False)   # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("community-graph.png", dpi=160)
print("เขียน community-graph.png แล้ว ·", len(df), "แถว")

ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*" · ทดสอบกับเวอร์ชัน 3.10

07ลองเล่นเพื่อเข้าใจ

ข้อมูลตัวอย่าง · 8 แถว · seed 239● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
สีมาจากการคำนวณ
กลุ่มย่อยที่ 1กลุ่มย่อยที่ 2กลุ่มย่อยที่ 3
เข้าชมเว็บเข้าชมเว็บ · เชื่อมกับ 2 โหนดดูสินค้าดูสินค้า · เชื่อมกับ 3 โหนดออกทันทีออกทันที · เชื่อมกับ 1 โหนดใส่ตะกร้าใส่ตะกร้า · เชื่อมกับ 3 โหนดออกกลางทางออกกลางทาง · เชื่อมกับ 1 โหนดกรอกที่อยู่กรอกที่อยู่ · เชื่อมกับ 3 โหนดทิ้งตะกร้าทิ้งตะกร้า · เชื่อมกับ 1 โหนดชำระเงินสำเรชำระเงินสำเร็จ · เชื่อมกับ 1 โหนดชำระไม่สำเร็ชำระไม่สำเร็จ · เชื่อมกับ 1 โหนด

ตำแหน่งของโหนดไม่มีความหมายในตัวเอง ระยะห่างบนภาพไม่ใช่ระยะจริงในเครือข่าย

จำนวนโหนด9
จำนวนเส้นเชื่อม8
โหนดที่เชื่อมมากที่สุดดูสินค้า · 3 เส้น
ดูข้อมูลเป็นตาราง (9 แถว)
กราฟเครือข่าย 9 โหนด 8 เส้นเชื่อม
โหนดจำนวนเส้นเชื่อม
ดูสินค้า3
ใส่ตะกร้า3
กรอกที่อยู่3
เข้าชมเว็บ2
ออกทันที1
ออกกลางทาง1
ทิ้งตะกร้า1
ชำระเงินสำเร็จ1
ชำระไม่สำเร็จ1

ลองแล้วจะเห็นอะไร

  • สังเกตอะไร: สังเกตว่าโหนดสีเดียวกันบางตัวอยู่ห่างกันบนภาพ — นั่นคือหลักฐานว่าสีมาจากโครงสร้างของข้อมูล ไม่ใช่จากตำแหน่ง

ข้อควรระวัง

  1. ★ เชื่อกลุ่มที่ได้โดยไม่ดูค่า modularity ทั้งที่อัลกอริทึมคืนกลุ่มมาเสมอ
  2. ไม่ระบุอัลกอริทึมและพารามิเตอร์ ทำให้คนอื่นทำซ้ำไม่ได้
  3. ให้สีตามอันดับขนาดกลุ่ม ทำให้สีเปลี่ยนเมื่อกรองข้อมูล
  4. แสดงเกิน 8 กลุ่มพร้อมกันจนสีแยกไม่ออก

เมื่อไหร่ไม่ควรใช้กราฟนี้

  • เครือข่ายเบาบางไม่มีโครงสร้างกลุ่มใช้แทน: force-directed-graph ธรรมดา
  • เครือข่ายหนาแน่นมากใช้แทน: adjacency-matrix เรียงด้วยการจัดกลุ่ม
  • รู้กลุ่มอยู่แล้วจากข้อมูลจริงใช้แทน: hive-plot ที่จัดตำแหน่งตามกลุ่มนั้น

กราฟที่เกี่ยวข้อง

เทคนิคถัดไป · ผังกระบวนการ