לדלג לתוכן

טיוטה:ניתוח אשכולות ספקטרלי

מתוך ויקיפדיה, האנציקלופדיה החופשית
הערך נמצא בשלבי עבודה במסגרת מיזם "עבודות ויקידמיות". נא לא לערוך ערך זה עד להסרת התבנית. הערות לערך נא להוסיף בדף השיחה.
העבודה על הערך עתידה להסתיים בתאריך 1 אוקטובר 2024. ניתן להסיר את התבנית משחלפו שלושה שבועות מן התאריך הנקוב.
הערך נמצא בשלבי עבודה במסגרת מיזם "עבודות ויקידמיות". נא לא לערוך ערך זה עד להסרת התבנית. הערות לערך נא להוסיף בדף השיחה.
העבודה על הערך עתידה להסתיים בתאריך 1 אוקטובר 2024. ניתן להסיר את התבנית משחלפו שלושה שבועות מן התאריך הנקוב. שיחה


ניתוח אשכולות ספקטרלי הוא שיטה לפתרון בעיית ניתוח אשכולות באמצעות שימוש בערכים העצמיים (ספקטרום) של מטריצת הלפלסיאן המתארת את המידע. במקרה ובו הקלט ניתן כגרף, מטריצת הלפלסיאן נחשבת כקלט של האלגוריתם (מאחר וקיימת התאמה אחת ויחידה בין גרף בעל צמתים לבין מטריצת לפלסיאן מסדר ), אמנם במקרים רבים הקלט אינו מתקבל כך, (אלא למשל אוסף נקודות במימד ) ונדרשת בניית גרף כשלב מקדים לשימוש באלגוריתם. קודקודי הגרף מייצגים את המידע אותו רוצים לנתח, וקשתות הגרף מייצגות את הקשר בין הפרטים בגרף.

הגדרת הבעיה

[עריכת קוד מקור | עריכה]

תיאור הבעיה

[עריכת קוד מקור | עריכה]

ניתוח המידע לאשכולות שקול לחלוקת הגרף לתתי קבוצות זרות זו לזו, נרצה למצוא חלוקה שאכן מחלקת את המידע בצורה "טבעית" כלשהי, כלומר אינטואיטיבית קל להבין כי נרצה למצוא חלוקה כזו שבה הקשרים בין חברי קבוצות שונות רופפים עד לא קיימים, ובנוסף הקשרים שבין חברי כל קבוצה זה לזה חזקים, דרך נוספת שעל פיה ניתן לחלק את המידע היא אוסף קבוצות אשר הקשרים ביניהן רופפים, וכן גודלן דומה זה לזה.

הקשת הירוקה מחלקת את הגרף על פי חתך מינימלי, הקשת הכתומה מחלקת לשתי קבוצות טבעיות יותר

יש לשים לב כי בעוד התנאי הראשון הינו בעצם בעיית החתך המינימלי, אשר ידועה כבעיה הניתנת לפתרון בזמן ריצה פולינומיאלי, קיומו אינו מספיק לפתרון אופטימלי לבעיית הניתוח מאחר ופעמים רבות תוצאתו הינה פיצול קודקוד אחד (או קבוצה קטנה של קודקודים) משאר הגרף, ובהוספת התנאי השני מתקבלת בעיה np-קשה[1]. קירוב לפתרון בעיה זו ניתן להיעשות על ידי שימוש במטריצת הלפלסיאן של הגרף.

הגדרה פורמלית

[עריכת קוד מקור | עריכה]

בצורה פורמלית ניתן לתאר את הבעיה באחת מהדרכים הבאות - בהינתן גרף ממושקל ולא מכוון , ומספר נרצה למצוא חלוקה המביאה למינימום את אחת משתי פונקציות המטרה הבאות:

כאשר מגדירים:

  • הינה תת קבוצה של צמתים בגרף, מתקיים ,
  • הוא מספר הצמתים ברכיב .
  • הוא סכום ערכי הקשתות המחברות את צמתי זה לזה.
  • הוא סכום ערכי הקשתות המחברות בין הקבוצה לבין שאר הגרף.
  • הוא מספר האשכולות, כלומר מספר תתי הקבוצות שאליהן נחלק את הגרף.

ההבדל בין שתי הפונקציות הוא שבעוד "מענישה" רכיבי קשירות בעלי מספר צמתים נמוך, ובשימוש בה נצפה לתוצאה של אשכולות בעלי מספר צמתים דומה, "מענישה" רכיבי קשירות בעלי סכום קשתות נמוך, ולכן נצפה לקשרים חזקים בתוך כל אשכול.

הקו האדום מחלק על פי nCut והקו הירוק על פי RatioCut

בדוגמה שבתמונה ניתן להראות על ידי חישוב כי שתי פונקציות המטרה יביאו לחלוקה שונה, שימוש בפונקציה יוביל ל"שבירת" הקשת שערכה 14, לצורך חלוקת הגרף לשתי הקבוצות (השוות בגודלן) . לעומת זאת, השימוש בפונקציה יוביל לחלוקה לקבוצות , מאחר וגודל הקבוצות לא רלוונטי אלא סכום הקשתות, ותחת חישוב זה שבירת הקשת בעלת משקל 13 עדיפה על הקשת הכבדה יותר.

ניתן להניח כי ההבדלים בין הגישות נובעים מסיבות היסטוריות, פורסמה בהקשר של חלוקה של רכיבי מעגל חשמלי לתתי קבוצות[2] אשר נוח "לטפל" בכל אחת בפני עצמה, בהקשר זה חשוב לדאוג שהקבוצות תהיינה בעלות גודל דומה וכן שלא יהיו קשרים חזקים בין קבוצה לקבוצה (לדוגמה, כדי שיהיה אפשר למקם כל תת קבוצה במקום בלתי תלוי ככל האפשר בשאר המעגל החשמלי). לעומתה, פורסמה בהקשר של סגמנטציה[3], ובהקשר זה חשוב לשים לב לכלול באותו אשכול אך ורק פרטים הקשורים זה לזה.

הגדרת מטריצת הלפלסיאן

[עריכת קוד מקור | עריכה]

מטריצת הלפלסיאן מוגדרת בצורה הבאה:

כאשר הינה מטריצה השכנות של הגרף (במקרה של גרף לא ממושקל) או מטריצת הדמיון של הגרף (במקרה של גרף ממושקל), וכן הינה מטריצה אלכסונית שבה האיבר הינו הדרגה של האיבר ה, כלומר מתקיים

למטריצת הלפלסיאן קיימות שתי גרסאות מנורמלות:

מטריצת לפלסיאן סימטרית מנורמלת (symmetric normalized Laplacian matrix) מוגדרת כך:

מטריצת לפלסיאן מנורמלת של מהלך אקראי (random-walk normalized Laplacian matrix) מוגדרת כך:תוצאת הנרמול הינה מטריצה שבה ערכי האלכסון הינם 1, והשימוש במטריצה מנורמלת ייעשה כדי להביא למינימום את פונקציית המטרה , יש לציין כי בגרף רגולרי בדרך כלל לא נדרש נרמול, שכן תוצאת השימוש מטריצה הלא מנורמלת יהיה דומה מאוד למנורמלת.

שימוש במטריצת הלפלסיאן

[עריכת קוד מקור | עריכה]

מתכונות מטריצת הלפלסיאן הלא מנורמלת, ניתן להוכיח[4] כי בהינתן תת הגרף וכן וקטור אינדיקטור מנורמל של תת גרף זה:

מתקיים השוויון הבא:

ובאופן כללי, עבור מטריצה מגודל אשר עמודותיה הן וקטורים אינדיקטורים נקבל את השיוויון הבא:כלומר, מציאת מינימום לפונקציה שקולה למציאת מינימום לביטוי תחת ההנחה שעמודות הן וקטורים אינדיקטורים וכן שהן אורתונורמליות זו לזו.

בעיה זו אמנם עדיין np-קשה, אך ניתן למצוא פתרון מקורב לבעיה זו אם מסירים את הדרישה שהעמודות הינן אינדיקטורים, ומניחים רק שהן אורתונורמליות, וזוהי כבר בעיה ידועה אשר פתרונה נתון על ידי הוקטורים העצמיים המתאימים ל- הערכים העצמיים הקטנים ביותר של המטריצה , וסיבוכיות החישוב שלה פולינמיאלית. באופן דומה ניתן למצוא את הוקטורים העצמיים המתאימים ל- הערכים העצמיים הקטנים ביותר של מטריצת הלפלסיאן המנורמלת כדי לקרב את פונקציית המטרה [5].

ניתן להבין קירוב זה בצורה אינטואיטיבית - קל להראות כי עבור גרף בעל רכיבי קשירות, הפתרון האופטימלי עבור אשכולות יהיה חלוקת הגרף לאותם רכיבי קשירות, והוקטורים העצמיים המתאימים לערך העצמי 0 הם אינדיקטורים של רכיבי הקשירות[6], כמו כן אלו הם הערכים העצמיים הקטנים ביותר, מאחר וידוע כי הערכים העצמיים של מטריצת הלפלסיאן אינם שליליים. כעת עבור גרף דומה המכיל בנוסף "רעש קטן", כלומר קשתות מעטות בין רכיב קשירות אחד למשנהו, נוכל לצפות שהערכים העצמיים ישתנו מעט, והמרחב הוקטורי הנפרש על ידי הוקטורים העצמיים המתאימים להם ישתנה מעט אף הוא, כלומר ניתן להבין כי בהינתן רעש קטן, קירוב הפתרון יהיה בסביבת הפתרון המקורי[7].

חשוב לציין כי אין ערובה לכך שקירוב זה אכן יניב את הפתרון לבעיה המקורית (המניחה שהוקטורים הינם אינדיקטורים), דוגמאות קלאסיות לכך נסקרו בספרות במהלך השנים[8]. ובנוסף, בעוד פתרון הבעיה המקורית הוא אוסף אינדיקטורים המחלק את המידע ל קבוצות בצורה מפורשת, קירוב הפתרון כבר מכריח אותנו לנתח את הוקטורים העצמיים בעזרת אלגוריתם נוסף (למשל בעזרת אלגוריתם k-מרכזים).

להלן דוגמה לגרף בעלי 2 רכיבי קשירות, וכן גרף זהה עם תוספת של רעש ההופך אותו לבעל רכיב קשירות אחד,


גרף מטריצת לפלסיאן 2 וקטורים עצמיים ראשונים
גרף מטריצת לפלסיאן 2 וקטורים עצמיים ראשונים

ניתן לראות בגרף השני את הקשת המחברת את הצומת הראשון והשלישי כרעש קטן, ואכן הוקטורים העצמיים פורשים מרחב קרוב למרחב הנפרש על ידי האינדיקטורים של "רכיבי הקשירות" שכן מתקיים:

הוקטור העצמי הראשון

[עריכת קוד מקור | עריכה]

חשוב לציין כי במרבית המקרים הקלט המתקבל הינו גרף קשיר, ומכאן 0 הוא ערך עצמי מריבוי 1, והוקטור העצמי המתאים לו יהיה וקטור אינדיקטור של כל צמתי הגרף, כלומר - .

שימוש בוקטור זה לא מוסיף מידע על הקשר בין צמתי הגרף, ולכן ניתן לא להשתמש בו כאשר מחלקים את הגרף לאשכולות. לדוגמה, עבור חלוקה לשני אשכולות, ניתן להסתכל ישירות על הוקטור העצמי השני הקטן ביותר (הנקרא Fiedler Vector), ולחלק את הגרף על פיו, אשכול אחד יהיה קבוצת הצמתים בעלי ערך חיובי בוקטור, והאשכול השני יהיו קבוצת הצמתים בעלי ערך שלילי.

אלגוריתם בסיסי

[עריכת קוד מקור | עריכה]

כפי שהוזכר, בגרף בעל רכיבי קשירות, הפתרון המתקבל עבור הוקטורים העצמיים הראשונים פורש את אותו המרחב הנפרש גם כן על ידי האינדיקטורים של רכיבי הקשירות, ועל כן מציאת האשכולות תתקבל על ידי יצירת מטריצה בגודל מהוקטורים העצמיים, והבאתה לצורתה הקנונית.

אמנם בדרך כלל הגרף יכיל רעש, או שמראש מספר האשכולות לא יהיה ידוע, ועל כן מספר רכיבי הקשירות יהיה שונה ממספר האשכולות ויידרש עיבוד נוסף של המידע, דרך נפוצה אחת היא שימוש באלגוריתם k-מרכזים. בנוסף, במקרים רבים קלט המערכת אינו מטריצת לפלסיאן אלא, למשל, אוסף נקודות במימד גבוה כלשהו, במקרה כזה נדרש להגדיר פונקציית סמיכות המציינת את עוצמת הקשר בין כל שני איברים כדי ליצור את מטריצת הלפלסיאן. האלגוריתם השלם יכלול את השלבים הבאים:

  • יצירת גרף ומטריצת לפלסיאן מהמידע
  • חישוב הוקטורים העצמיים הראשונים של המטריצה
  • הטלת מטריצת הוקטורים הללו למרחב , השורה ה של מטריצה זו היא הטלת הצומת בגרף אל
  • הפעלת אלגוריתם לניתוח אשכולות במרחב זה (לדוגמה אלגוריתם k-מרכזים).

להלן קטע קוד המממש את האלגוריתם המתואר[9]

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_circles, make_blobs
from sklearn.cluster import KMeans
from sklearn.neighbors import NearestNeighbors
from scipy.linalg import eigh

# Step 0: Generate a dataset (Circles + Blobs)
np.random.seed(42)
X_circles, y_circles = make_circles(n_samples=400, factor=0.5, noise=0.05)
X_blobs, y_blobs = make_blobs(n_samples=100, centers=[(-1.5, -1.5)], cluster_std=0.1)
X = np.vstack((X_circles, X_blobs))
y_true = np.hstack((y_circles, y_blobs + 2))  # Adjust labels for clarity

# Step 1: Create the graph Laplacian matrix using epsilon-neighborhood
epsilon = 0.2
nbrs = NearestNeighbors(radius=epsilon).fit(X)
adj_matrix = nbrs.radius_neighbors_graph(X, mode='connectivity').toarray()
D = np.diag(np.sum(adj_matrix, axis=1))
L = D - adj_matrix

# Step 2: Compute the eigenvectors of the Laplacian matrix
eigenvalues, eigenvectors = eigh(L)
eigenvectors = eigenvectors[:, 0:3]

# Step 3+4: Analyze the data with k-means
kmeans = KMeans(n_clusters=3, random_state=42)
labels = kmeans.fit_predict(eigenvectors)

# Draw the original labels and clustering labels
plt.figure(figsize=(14, 6))

plt.subplot(1, 2, 1)
plt.scatter(X[:, 0], X[:, 1], c=y_true)
plt.title('Original Data (True Labels)')


plt.subplot(1, 2, 2)
plt.scatter(X[:, 0], X[:, 1], c=labels)
plt.title('Spectral Clustering Result')


plt.tight_layout()
plt.show()

מעבר מדאטה במימד גבוה למטריצת שכנות

[עריכת קוד מקור | עריכה]

קיימות מספר שיטות ליצור גרף בהינתן אוסף נקודות, הבולטות שבהן הינן:

  • גרסה של אלגוריתם שכן קרוב - נגדיר קשת אם הוא אחד מ השכנים הקרובים של , חשוב לציין כי:
    • הערך נתון לבחירה, ככל שיהיה גדול יותר כך הגרף יכיל יותר קשתות.
    • הגרף המתקבל בדרך זו הוא מכוון, וזו תופעה שאיננה רצויה, לכן ניתן לבחור האם להגדיר קשת רק במקרים שבהם שתי הקשתות , קיימות (אלגוריתם שכן קרוב הדדי), או גם במקרים שבהם לפחות אחת משתי הקשתות קיימות.
    • הגרף המתקבל איננו ממושקל
  • סביבת - נגדיר קשת אם המרחק בין שני הצמתים קטן או שווה ל-, נשים לב כי:
    • הערך נתון לבחירה, ככל שיהיה גדול יותר כך הגרף יכיל יותר קשתות.
    • הגרף המתקבל בדרך זו איננו מכוון ואיננו ממושקל.
  • שימוש במטריקת מרחק המודדת קרבה בין שתי נקודות, פונקציה שכיחה בהקשר זה הינה - , בשימוש במטריקה זו:
    • הערך נתון לבחירה, ככל שיהיה גדול יותר כך נקודות בסביבה רחוקה יותר יחוברו בקשת בעלת משקל גבוה.
    • הגרף המתקבל הינו ממושקל ואיננו מכוון.
    • הגרף המתקבל הינו שלם, ועל כן מטריצת הלפלסיאן לא תהיה דלילה, וזמני החישוב יהיו ארוכים יותר.

מאפיינים מרכזיים בהשוואה לשיטות שונות

[עריכת קוד מקור | עריכה]

חשוב לשים לב כי האלגוריתם מתבסס על דמיון וקירבה בין איברים, ולכן ניתן להשתמש בקלט בעל אופי מגוון. בניגוד לאלגוריתם k-מרכזים או DBSCAN לדוגמה, אשר מתאימים יותר לקלט ממימד , כאן ניתן להשתמש גם בערכים בוליאנים (כאשר ניתן להגדיר מטריקת מרחק המסתמכת על מרחק ג'אקרד לדוגמה).

אופן החישוב

[עריכת קוד מקור | עריכה]

השלבים ה"כבדים" הם יצירת מטריצת הלפלסיאן, וחישוב הוקטורים העצמיים. עבור נקודות קלט, בניית מטריצת לפלסיאן מלאה פרופורציונלית למספר הקשתות - כלומר סיבוכיות של , ומספר פעולות החישוב עבור כל הוקטורים העצמיים במדויק פרופורציונלי ל.

חשוב לציין כי לשימוש מעשי נדרש רק קירוב של הוקטורים העצמיים, ובנוסף ביישומים רבים, תחת הנחות ריאליות של ידע מקדים על הקלט ניתן להגביל את מספר הקשתות של כל צומת, ובכך עבור וקטורים עצמיים ניתן להוריד את הסיבוכיות עד לסדר גודל של בעזרת שימוש באלגוריתם לנצוש[10][11]. לכן זמן הריצה תלוי מאוד באופי הקלט ואופן מימוש האלגוריתם.

עוד יש לציין כי מספר המימדים של הקלט איננו משפיע על זמני הריצה של שלבים אלה בצורה ישירה, מה שמבדיל אותו מאלגוריתמים רבים אשר יעילותם פוחתת וזמני הריצה שלהם עולים משמעותית תחת קלט של מידע ממימד גבוה.

התפלגות הקלט

[עריכת קוד מקור | עריכה]

אחד היתרונות המרכזיים הוא העובדה שאין הנחות יסוד על האשכולות. בניגוד לk-מרכזים המניח שכל אשכול הוא בעל צורה כללית של ספירה, או DBSCAN המניח צפיפות אחידה באשכול, כאן פונקציית המטרה לא מתייחסת בצורה ישירה לתכונות גלובליות אלה של האשכול.

ניתוח אשכולות

מטריצת לפלסיאן

קישורים חיצוניים

[עריכת קוד מקור | עריכה]

הערות שוליים

[עריכת קוד מקור | עריכה]
  1. ^ Wagner, D. and Wagner, F. (1993). Between min cut and graph bisection
  2. ^ Hagen and Kahng, 1992
  3. ^ Shi and Malik, 2000
  4. ^ להוכחה המלאה ראו A Tutorial on Spectral Clustering by Ulrike von Luxburg בפרק 5.2
  5. ^ להוכחה המלאה ראו A Tutorial on Spectral Clustering by Ulrike von Luxburg בפרק 5.3
  6. ^ ליתר דיוק יש לומר כי המרחב הנפרש על ידי הוקטורים העצמיים זהה למרחב הנפרש על ידי אינדיקטורים, מאחר ולא ניתן לשייך וקטור עצמי אחד מסויים אל ערך עצמי בעל ריבוי גיאומטרי גדול מאחד אלא יש לדבר על המרחב הוקטורי המתאים לערך העצמי
  7. ^ davis and kahan, 1970
  8. ^ ראו לדוגמה Guattery and Miller, 1978
  9. ^ קוד זה עוקב אחר השלבים המרכזיים של האלגוריתם התיאורטי, ברמה המעשית ניתן להשתמש בספריות ייעודיות כגון sklearn.cluster.SpectralClustering
  10. ^ למעשה השילוב של הסתפקות בקירוב הוקטורים העצמיים עם הגבלת מספר הקשתות המחוברות לכל צומת הוא שהופך את השימוש באלגוריתם לנצוש לאטרקטיבי מאחר וזמן החישוב של אלגוריתם זה יורד משמעותית עבור מטריצות דלילות, בהיעדר הנחה זו ניתן להגיע לסיבוכיות של עבור הוקטורים העצמיים הראשונים
  11. ^ ראו בהרחבה בshi and malik, 2000, פרק 3.1