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

ไบพล็อต PCAPCA Biplot

ยุบหลายมิติเหลือสองโดยยังบอกได้ว่าแกนคืออะไร

5
เฉพาะทางควรรู้ก่อน · เข้าใจแนวคิดความแปรปรวนและการลดมิติ
ลองเล่น

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

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

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

เหมือนถ่ายรูปวัตถุสามมิติจากมุมที่เห็นรูปร่างได้ชัดที่สุด ซึ่งก็ยังเสียข้อมูลบางส่วนไปเสมอ

ใช้ที่ไหนบ้าง — สำรวจข้อมูลที่มีตัวแปรหลายสิบตัว หาว่าตัวแปรไหนสัมพันธ์กัน หรือดูว่ากลุ่มตัวอย่างแยกกันได้หรือไม่

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

  1. ขั้นที่ 1★ ทำให้ทุกตัวแปรเป็นมาตรฐานก่อน
  2. ขั้นที่ 2คำนวณองค์ประกอบหลักสองตัวแรก
  3. ขั้นที่ 3ฉายข้อมูลและวาดลูกศรของตัวแปรเดิม
  4. ขั้นที่ 4★ รายงานสัดส่วนความแปรปรวนที่อธิบายได้

ตัวอย่างคลาสสิก · PCA ในการวิเคราะห์ความหลากหลายทางพันธุกรรมของประชากร

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

Wikipedia · Principal component analysis

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

เมื่อข้อมูลมีตัวแปรยี่สิบตัว เราวาดมันไม่ได้ และดูทีละคู่ก็ต้องดูถึงร้อยเก้าสิบคู่ ซึ่งไม่ไหว

PCA หาทางออกด้วยการมองหาทิศทางที่ข้อมูลกระจายตัวมากที่สุด แล้วใช้สองทิศแรกเป็นแกนใหม่ เพราะทิศที่กระจายมากคือทิศที่มีข้อมูลมาก

ส่วนที่ทำให้ biplot ต่างจากการฉายแบบอื่นคือลูกศร ซึ่งบอกว่าตัวแปรเดิมแต่ละตัวชี้ไปทางไหนบนแกนใหม่ ทำให้ตีความได้ว่าแกนที่หนึ่งหมายถึงอะไร

ลูกศรที่ชี้ไปทางเดียวกันแปลว่าตัวแปรนั้นสัมพันธ์กันทางบวก ชี้ตรงข้ามคือสัมพันธ์ทางลบ และตั้งฉากกันคือแทบไม่สัมพันธ์

สิ่งที่ต้องรายงานเสมอคือสองแกนนี้อธิบายความแปรปรวนได้กี่เปอร์เซ็นต์ ถ้าได้เจ็ดสิบเปอร์เซ็นต์ก็ถือว่าภาพน่าเชื่อถือพอสมควร แต่ถ้าได้แค่สามสิบ ภาพนั้นก็ทิ้งข้อมูลไปเจ็ดสิบเปอร์เซ็นต์

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

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

รูปทรงของข้อมูลตารางแบบกว้าง (หนึ่งแถวหนึ่ง entity)
จำนวนมิติที่เข้ารหัสได้5 มิติ
จำนวนแถวที่เหมาะ50–2,000 แถว กับ 4–30 ตัวแปรขั้นต่ำ 10 แถว
เส้นฐานศูนย์ไม่เกี่ยวข้องแกนคือองค์ประกอบหลัก ศูนย์คือค่าเฉลี่ยของข้อมูล

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
itemตัวอย่างหมวดหมู่text20–5,000 ตัวอย่างแต่ละแถวเป็นหนึ่งจุด
group
ไม่บังคับ
กลุ่มหมวดหมู่color2–8 กลุ่มใช้สีเพื่อดูว่ากลุ่มแยกกันไหม
ราคาตัวแปรเชิงปริมาณตัวเลขต่อเนื่องx3–100 ตัวแปร★ ต้องทำให้เป็นมาตรฐานก่อน

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

  1. ★ ทำให้ทุกตัวแปรเป็นมาตรฐาน
  2. จัดการค่าที่หายไปก่อนเพราะ PCA ทนไม่ได้
  3. ตรวจว่าตัวแปรทั้งหมดเป็นเชิงปริมาณ

ค่าที่หายไป — PCA รับค่าที่หายไปไม่ได้เลย ต้องเติมหรือตัดแถวออกและรายงานจำนวน

สเกลของแกน — สองแกนควรมีสเกลเท่ากันเพื่อไม่ให้ระยะบิด และลูกศรควรปรับขนาดพอดีกับกลุ่มของจุด

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

ตัวแปรมากกว่าจำนวนตัวอย่าง ผลลัพธ์จะไม่เสถียร

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

item,group,ราคา,ความเร็ว,ความจุ,น้ำหนัก,คะแนนรีวิว
รุ่น A,รุ่นประหยัด,167,48.5,17.6,30.9,3.17
รุ่น B,รุ่นมาตรฐาน,301,55.7,30.4,20,4.09

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

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

  • กลุ่มของตัวอย่างที่แยกจากกันในพื้นที่ที่ลดมิติแล้ว
  • ตัวแปรที่สัมพันธ์กันจากทิศของลูกศร
  • ตัวแปรที่มีอิทธิพลมากที่สุดจากความยาวลูกศร
  • ตัวอย่างผิดปกติที่อยู่ไกลจากกลุ่ม

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

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

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

  1. ★ อ่านเปอร์เซ็นต์ความแปรปรวนที่แกนอธิบายได้ก่อนทุกครั้ง
  2. ดูทิศของลูกศรเพื่อตีความว่าแกนหมายถึงอะไร
  3. ดูว่ากลุ่มสีแยกกันหรือทับกัน

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

  • ข้อมูลแบ่งเป็นกลุ่มไหม
  • ตัวแปรไหนสัมพันธ์กัน
  • อะไรคือแกนหลักของความแตกต่าง

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

  • ไม่รายงานเปอร์เซ็นต์ความแปรปรวน
  • ไม่ทำให้ตัวแปรเป็นมาตรฐานก่อน
  • ตีความแกนโดยไม่ดูลูกศร
  • สองแกนใช้สเกลต่างกัน

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

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

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

  1. ★ เขียนเปอร์เซ็นต์ความแปรปรวนไว้ที่ชื่อแกนทั้งสองแกน
  2. ติดชื่อตัวแปรที่ปลายลูกศรทุกเส้น
  3. อธิบายเป็นคำว่าแกนที่หนึ่งน่าจะหมายถึงอะไร

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

การฉาย <จำนวน> ตัวแปรลงสองแกนที่อธิบายความแปรปรวนได้ <เปอร์เซ็นต์>

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

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

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

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

df = pd.read_csv("pca-biplot-sample.csv")
df["ราคา"] = pd.to_numeric(df["ราคา"], errors="coerce")
df["ความเร็ว"] = pd.to_numeric(df["ความเร็ว"], errors="coerce")
df["ความจุ"] = pd.to_numeric(df["ความจุ"], errors="coerce")
df["น้ำหนัก"] = pd.to_numeric(df["น้ำหนัก"], errors="coerce")
df["คะแนนรีวิว"] = pd.to_numeric(df["คะแนนรีวิว"], errors="coerce")
NOTE = "arrows"   # ← ค่าจาก Playground

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

dims = ["ราคา", "ความเร็ว", "ความจุ", "น้ำหนัก", "คะแนนรีวิว"]
X = StandardScaler().fit_transform(df[dims])          # ★ ทำมาตรฐานก่อนเสมอ
pca = PCA(n_components=2).fit(X)
Y = pca.transform(X)
ev = pca.explained_variance_ratio_ * 100              # ★ ต้องรายงาน
for i, g in enumerate(df["group"].unique()):
    mask = df["group"].values == g
    ax.scatter(Y[mask, 0], Y[mask, 1], s=48, color=PALETTE[i], label=g, alpha=0.8)
scale = np.abs(Y).max() * 0.85
for j, dim in enumerate(dims):                        # ลูกศรของตัวแปรเดิม
    ax.arrow(0, 0, pca.components_[0, j] * scale, pca.components_[1, j] * scale,
             color="#22201c", width=0.012, head_width=0.16, alpha=0.75)
    ax.text(pca.components_[0, j] * scale * 1.12, pca.components_[1, j] * scale * 1.12,
            dim, fontsize=9, ha="center")
ax.set_xlabel(f"PC1 ({ev[0]:.0f}% ของความแปรปรวน)")
ax.set_ylabel(f"PC2 ({ev[1]:.0f}%)")
ax.legend(frameon=False)

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

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

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

ข้อมูลตัวอย่าง · 12 แถว · seed 197● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
ลูกศรบอกความหมายของแกน
รุ่นประหยัดรุ่นมาตรฐานรุ่นพรีเมียม
-1.00-0.500.000.501.00องค์ประกอบหลักที่ 2-3.00-2.00-1.000.001.002.003.00องค์ประกอบหลักที่ 1รุ่น Aรุ่น Bรุ่น Cรุ่น Dรุ่น Eรุ่น Fรุ่น Gรุ่น Hรุ่น Iรุ่น Jรุ่น Kรุ่น Lราคาราคาความเร็วความเร็วความจุความจุน้ำหนักน้ำหนักคะแนนรีวิวคะแนนรีวิว

แกนที่ได้ไม่มีหน่วยและไม่มีชื่อในตัวเอง — ต้องตีความจากทิศของลูกศรตัวแปรเท่านั้น

จำนวนตัวแปรตั้งต้น5
ตัวแปรที่มีน้ำหนักสุดบน PC1ราคา
จำนวนจุด12
ดูข้อมูลเป็นตาราง (5 แถว)
PCA biplot 5 ตัวแปร 12 จุด
ตัวแปรน้ำหนักบน PC1น้ำหนักบน PC2
ราคา0.453-0.035
ความเร็ว0.4410.610
ความจุ0.4490.399
น้ำหนัก-0.4470.490
คะแนนรีวิว0.447-0.476

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

  • สังเกตอะไร: ลูกศรที่ชี้ทางเดียวกันแปลว่าตัวแปรนั้นสัมพันธ์กัน และทิศของลูกศรคือสิ่งเดียวที่ทำให้แกนที่คำนวณขึ้นมาตีความได้

ข้อควรระวัง

  1. ★ ไม่รายงานว่าสองแกนอธิบายความแปรปรวนได้กี่เปอร์เซ็นต์
  2. ไม่ทำให้ตัวแปรเป็นมาตรฐาน ทำให้ตัวแปรที่หน่วยใหญ่ครองผลลัพธ์
  3. ตีความแกนเป็นตัวแปรจริงทั้งที่เป็นแกนที่คำนวณขึ้นมา
  4. ใช้กับความสัมพันธ์ที่ไม่เป็นเชิงเส้น ซึ่ง PCA จับไม่ได้

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

  • มีตัวแปรน้อยกว่า 4 ตัวใช้แทน: scatter-matrix
  • ความสัมพันธ์ไม่เป็นเชิงเส้นใช้แทน: embedding-projection
  • สนใจแค่ความสัมพันธ์รายคู่ใช้แทน: correlation-heatmap

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

เทคนิคถัดไป · กราฟแท่ง