מדריך לאלגוריתם K-Nearest Neighbors ב-Python ו-Scikit-Learn PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

מדריך לאלגוריתם K-Nearest Neighbors ב-Python וב-Skikit-Learn

מבוא

השמיים K-nearest Neighbours (KNN) אלגוריתם הוא סוג של אלגוריתם למידת מכונה מפוקחת המשמש לסיווג, רגרסיה כמו גם זיהוי חריגים. זה קל מאוד ליישום בצורה הבסיסית ביותר שלו אבל יכול לבצע משימות מורכבות למדי. זהו אלגוריתם למידה עצלן מכיוון שאין לו שלב אימון מיוחד. במקום זאת, הוא משתמש בכל הנתונים לאימון תוך סיווג (או נסיגה) של נקודת נתונים או מופע חדש.

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

במדריך זה נראה כיצד ניתן ליישם את KNN עם ספריית Scikit-Learn של Python. לפני כן נחקור תחילה כיצד נוכל להשתמש ב-KNN ונסביר את התיאוריה שמאחוריה. לאחר מכן, נסתכל על מערך נתונים של קליפורניה דיור נשתמש כדי להמחיש את אלגוריתם KNN וכמה מהווריאציות שלו. קודם כל, נסקור כיצד ליישם את אלגוריתם KNN עבור הרגרסיה, ולאחר מכן יישומים של סיווג KNN וזיהוי חריגים. בסופו של דבר, נסיים עם כמה מהיתרונות והחסרונות של האלגוריתם.

מתי כדאי להשתמש ב-KNN?

נניח שרצית לשכור דירה וגילית לאחרונה שהשכנה של חברה שלך עשויה להשכיר את הדירה שלה להשכרה בעוד שבועיים. מכיוון שהדירה עדיין לא נמצאת באתר להשכרה, כיצד תוכל לנסות להעריך את שווי ההשכרה שלה?

נניח שהחבר שלך משלם 1,200 דולר שכר דירה. ערך השכירות שלך עשוי להיות סביב המספר הזה, אבל הדירות לא בדיוק זהות (כיוון, שטח, איכות ריהוט וכו'), אז יהיה נחמד לקבל יותר נתונים על דירות אחרות.

אם תשאלו שכנים אחרים והתבוננו בדירות מאותו בניין שהיו רשומות באתר להשכרה, שלושת הדירות השכנות הקרובות ביותר הן 1,200 דולר, 1,210 דולר, 1,210 דולר ו-1,215 דולר. הדירות האלה נמצאות באותו בלוק ובקומה כמו הדירה של חברך.

לדירות אחרות, שנמצאות רחוק יותר, באותה קומה, אבל בבלוק אחר, יש דמי שכירות של 1,400 דולר, 1,430 דולר, 1,500 דולר ו-1,470 דולר. נראה שהם יקרים יותר בגלל שיש להם יותר אור מהשמש בערב.

בהתחשב בסמיכות הדירה, נראה ששכר הדירה המוערך שלך יהיה בסביבות 1,210 דולר. זה הרעיון הכללי של מה K-Nearest Neighbours (KNN) האלגוריתם עושה זאת! הוא מסווג או מחזיר נתונים חדשים על סמך קרבתם לנתונים שכבר קיימים.

תרגם את הדוגמה לתיאוריה

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

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

בדוגמה שלנו, כבר ידענו את שכר הדירה של כל דירה, מה שאומר שהנתונים שלנו סומנו. KNN משתמש בנתונים שסומנו בעבר, מה שהופך אותו ל-a אלגוריתם למידה מפוקח.

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

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

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

הדמיית שימושים שונים ב-KNN

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

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

לאחר חישוב המרחק, KNN בוחר מספר נקודות נתונים הקרובות ביותר - 2, 3, 10, או בעצם כל מספר שלם. מספר נקודות זה (2, 3, 10 וכו') הוא K ב-K-Nearest Neighbours!

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

בואו נראה את האלגוריתם בפעולה בעזרת דוגמה פשוטה. שקול מערך נתונים עם שני משתנים ו-K של 3.

בעת ביצוע רגרסיה, המשימה היא למצוא את הערך של נקודת נתונים חדשה, בהתבסס על הסכום המשוקלל הממוצע של 3 הנקודות הקרובות ביותר.

KNN עם K = 3, כאשר משמש לרגרסיה:

מדריך לאלגוריתם K-Nearest Neighbors ב-Python ו-Scikit-Learn PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

אלגוריתם KNN יתחיל בחישוב המרחק של הנקודה החדשה מכל הנקודות. לאחר מכן הוא מוצא את 3 הנקודות עם המרחק הקטן ביותר לנקודה החדשה. זה מוצג באיור השני למעלה, שבו שלוש הנקודות הקרובות ביותר, 47, 58, ו 79 היו מוקפים. לאחר מכן, הוא מחשב את הסכום המשוקלל של 47, 58 ו 79 – במקרה זה המשקולות שווים ל-1 – אנו מחשיבים את כל הנקודות כשוות, אך נוכל גם להקצות משקלים שונים על סמך מרחק. לאחר חישוב הסכום המשוקלל, ערך הנקודה החדש הוא 61,33.

וכאשר מבצעים סיווג, משימת KNN לסווג נקודת נתונים חדשה, לתוך "Purple" or "Red" מעמד.

KNN עם K = 3, כאשר משמש לסיווג:

מדריך לאלגוריתם K-Nearest Neighbors ב-Python ו-Scikit-Learn PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.
מדריך לאלגוריתם K-Nearest Neighbors ב-Python ו-Scikit-Learn PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

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

תהליך זיהוי החריגים שונה משניהם לעיל, נדבר עליו יותר בעת הטמעתו לאחר יישום הרגרסיה והסיווג.

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

מערך הנתונים על דיור בקליפורניה של Scikit-Learn

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

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

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

מערך הנתונים מורכב מתשע תכונות:

  • MedInc – הכנסה חציונית בקבוצת בלוק
  • HouseAge – גיל בית חציוני בקבוצת בלוק
  • AveRooms - מספר החדרים הממוצע (המסופק לכל משק בית)
  • AveBedrms - המספר הממוצע של חדרי שינה (מסופק לכל משק בית)
  • Population - אוכלוסיית קבוצת החסימה
  • AveOccup - המספר הממוצע של בני משק בית
  • Latitude - חסום קו רוחב קבוצתי
  • Longitude – קו אורך קבוצת בלוק
  • MedHouseVal - ערך בית חציוני עבור מחוזות קליפורניה (מאות אלפי דולרים)

מערך הנתונים הוא כבר חלק מספריית Scikit-Learn, עלינו רק לייבא אותו ולטעון אותו כמסגרת נתונים:

from sklearn.datasets import fetch_california_housing

california_housing = fetch_california_housing(as_frame=True)

df = california_housing.frame

ייבוא ​​הנתונים ישירות מ-Scikit-Learn, מייבא יותר מאשר רק את העמודות והמספרים וכולל את תיאור הנתונים בתור Bunch אובייקט - אז זה עתה חילצנו את frame. פרטים נוספים על מערך הנתונים זמינים כאן.

בואו לייבא פנדות ולהציץ בשורות הנתונים הראשונות:

import pandas as pd
df.head()

הפעלת הקוד תציג את חמש השורות הראשונות של מערך הנתונים שלנו:

	MedInc  HouseAge  AveRooms  AveBedrms  Population  AveOccup   Latitude  Longitude  MedHouseVal
0 	8.3252 	41.0 	  6.984127 	1.023810   322.0 	   2.555556   37.88 	-122.23    4.526
1 	8.3014 	21.0 	  6.238137 	0.971880   2401.0 	   2.109842   37.86 	-122.22    3.585
2 	7.2574 	52.0 	  8.288136 	1.073446   496.0 	   2.802260   37.85 	-122.24    3.521
3 	5.6431 	52.0 	  5.817352 	1.073059   558.0 	   2.547945   37.85 	-122.25    3.413
4 	3.8462 	52.0 	  6.281853 	1.081081   565.0 	   2.181467   37.85 	-122.25    3.422

במדריך זה, נשתמש MedInc, HouseAge, AveRooms, AveBedrms, Population, AveOccup, Latitude, Longitude לחזות MedHouseVal. משהו דומה לנרטיב המוטיבציה שלנו.

בוא נקפוץ ישר לתוך היישום של אלגוריתם KNN עבור הרגרסיה.

רגרסיה עם K-Nearest Neighbors עם Scikit-Learn

עד כה, הכרנו את מערך הנתונים שלנו ועכשיו אנחנו יכולים להמשיך לשלבים אחרים באלגוריתם KNN.

עיבוד מוקדם של נתונים עבור רגרסיה של KNN

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

עבור הרגרסיה, עלינו לחזות ערך בית חציוני נוסף. לשם כך, נקצה MedHouseVal ל y וכל שאר העמודות ל X רק על ידי נפילה MedHouseVal:

y = df['MedHouseVal']
X = df.drop(['MedHouseVal'], axis = 1)

על ידי התבוננות בתיאורי המשתנים שלנו, אנו יכולים לראות שיש לנו הבדלים במידות. כדי להימנע מניחוש, הבה נשתמש ב- describe() שיטה לבדוק:


X.describe().T

זו התוצאה:

			count 	  mean 		   std 			min 		25% 		50% 		75% 		max
MedInc 		20640.0   3.870671 	   1.899822 	0.499900 	2.563400 	3.534800 	4.743250 	15.000100
HouseAge 	20640.0   28.639486    12.585558 	1.000000 	18.000000 	29.000000 	37.000000 	52.000000
AveRooms 	20640.0   5.429000 	   2.474173 	0.846154 	4.440716 	5.229129 	6.052381 	141.909091
AveBedrms 	20640.0   1.096675 	   0.473911 	0.333333 	1.006079 	1.048780 	1.099526 	34.066667
Population 	20640.0   1425.476744  1132.462122 	3.000000 	787.000000 	1166.000000 1725.000000 35682.000000
AveOccup 	20640.0   3.070655 	   10.386050 	0.692308 	2.429741 	2.818116 	3.282261 	1243.333333
Latitude 	20640.0   35.631861    2.135952 	32.540000 	33.930000 	34.260000 	37.710000 	41.950000
Longitude 	20640.0   -119.569704  2.003532    -124.350000 -121.800000 	-118.490000 -118.010000 -114.310000

כאן, אנו יכולים לראות כי mean ערך של MedInc הוא כ 3.87 ו mean ערך של HouseAge הוא על 28.64, מה שהופך אותו לגדול פי 7.4 מ MedInc. לתכונות אחרות יש גם הבדלים בממוצע ובסטיית תקן - כדי לראות זאת, תסתכל על mean ו std ערכים ולהתבונן כיצד הם מרוחקים זה מזה. ל MedInc std הוא כ 1.9, עבור HouseAge, std is 12.59 והוא הדין לגבי שאר התכונות.

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

כדי לבצע קנה מידה של תכונות, נשתמש ב-Skikit-Learn's StandardScaler כיתה מאוחר יותר. אם נחיל את קנה המידה עכשיו (לפני פיצול מבחן רכבת), החישוב יכלול נתוני בדיקה, למעשה דולף בדיקת מידע לשאר הצינור. מהסוג הזה דליפת מידע למרבה הצער, נפוץ לדלג, וכתוצאה מכך ממצאים בלתי ניתנים לשחזור או הזויים.

פיצול נתונים למערכות רכבת ובדיקות

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

דרך פשוטה ליצור פיצולי רכבת ומבחן היא train_test_split שיטה מבית Scikit-Learn. הפיצול אינו מתפצל ליניארי בשלב מסוים, אלא דוגמת X% ו-Y% באופן אקראי. כדי להפוך את התהליך הזה לשחזור (כדי שהשיטה תדגום תמיד את אותן נקודות נתונים), נגדיר את random_state טיעון מסוים SEED:

from sklearn.model_selection import train_test_split

SEED = 42
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=SEED)

פיסת קוד זו דוגמת 75% מהנתונים לאימון ו-25% מהנתונים לבדיקה. על ידי שינוי ה test_size ל-0.3, למשל, אתה יכול להתאמן עם 70% מהנתונים ולבדוק עם 30%.

על ידי שימוש ב-75% מהנתונים לאימון ו-25% לבדיקות, מתוך 20640 רשומות, ערכת ההדרכה מכילה 15480 וערכת הבדיקות מכילה 5160. אנו יכולים לבדוק את המספרים הללו במהירות על ידי הדפסת אורכי מערך הנתונים המלא ונתונים מפוצלים :

len(X)       
len(X_train) 
len(X_test)  

גדול! כעת נוכל להתאים את מדדי הנתונים ב- X_train להגדיר, ולהתאים את שניהם X_train ו X_test מבלי להדליף שום נתונים X_test אל תוך X_train.

שינוי קנה מידה עבור רגרסיה של KNN

על ידי ייבוא StandardScaler, הפעלתו, התאמתו בהתאם לנתוני הרכבת שלנו (מניעת דליפה), והפיכת מערכי הנתונים של הרכבת והבדיקה, אנו יכולים לבצע קנה מידה של תכונות:

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()

scaler.fit(X_train)


X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

הערה: מכיוון שלעתים קרובות אתה מתקשר scaler.fit(X_train) אחריו scaler.transform(X_train) - אתה יכול להתקשר לרווק scaler.fit_transform(X_train) אחריו scaler.transform(X_test) כדי לקצר את השיחה!

עכשיו הנתונים שלנו מותאמים! ה-scaler שומר רק על נקודות הנתונים, ולא את שמות העמודות, כאשר הוא מוחל על a DataFrame. בואו נארגן שוב את הנתונים לתוך DataFrame עם שמות עמודות ושימוש describe() לצפות בשינויים ב mean ו std:

col_names=['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude']
scaled_df = pd.DataFrame(X_train, columns=col_names)
scaled_df.describe().T

זה ייתן לנו:

			count 		mean 			std 		min 		25% 		50% 		75% 		max
MedInc 		15480.0 	2.074711e-16 	1.000032 	-1.774632 	-0.688854 	-0.175663 	0.464450 	5.842113
HouseAge 	15480.0 	-1.232434e-16 	1.000032 	-2.188261 	-0.840224 	0.032036 	0.666407 	1.855852
AveRooms 	15480.0 	-1.620294e-16 	1.000032 	-1.877586 	-0.407008 	-0.083940 	0.257082 	56.357392
AveBedrms 	15480.0 	7.435912e-17 	1.000032 	-1.740123 	-0.205765 	-0.108332 	0.007435 	55.925392
Population 	15480.0 	-8.996536e-17 	1.000032 	-1.246395 	-0.558886 	-0.227928 	0.262056 	29.971725
AveOccup 	15480.0 	1.055716e-17 	1.000032 	-0.201946 	-0.056581 	-0.024172 	0.014501 	103.737365
Latitude 	15480.0 	7.890329e-16 	1.000032 	-1.451215 	-0.799820 	-0.645172 	0.971601 	2.953905
Longitude 	15480.0 	2.206676e-15 	1.000032 	-2.380303 	-1.106817 	0.536231 	0.785934 	2.633738

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

אימון וחיזוי רגרסיה של KNN

ה-API האינטואיטיבי והיציב של Scikit-Learn הופך את האימון לרגררסורים ומסווגים לפשוטים מאוד. בואו לייבא את KNeighborsRegressor כיתה מה sklearn.neighbors מודול, הצג אותו והתאם אותו לנתוני הרכבת שלנו:

from sklearn.neighbors import KNeighborsRegressor
regressor = KNeighborsRegressor(n_neighbors=5)
regressor.fit(X_train, y_train)

בקוד לעיל, n_neighbors הוא הערך עבור K, או מספר השכנים שהאלגוריתם ייקח בחשבון לבחירת ערך בית חציוני חדש. 5 הוא ערך ברירת המחדל עבור KNeighborsRegressor(). אין ערך אידיאלי עבור K והוא נבחר לאחר בדיקה והערכה, עם זאת, כדי להתחיל, 5 הוא ערך נפוץ עבור KNN ולכן הוגדר כערך ברירת המחדל.

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

y_pred = regressor.predict(X_test)

כעת אנו יכולים להעריך עד כמה המודל שלנו מכליל לנתונים חדשים שיש לנו תוויות (אמת יסוד) עבורם - מערך הבדיקות!

הערכת האלגוריתם עבור רגרסיית KNN

מדדי הרגרסיה הנפוצים ביותר להערכת האלגוריתם הם שגיאה מוחלטת ממוצעת (MAE), שגיאה ממוצעת בריבוע (MSE), שגיאה ממוצעת בריבוע (RMSE) ומקדם קביעה (R)2):

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

$$
mae = (frac{1}{n})sum_{i=1}^{n}שמאל | בפועל – חזוי נכון |
$$

הערה: אתה יכול גם להיתקל ב y ו ŷ (קרא כ-y-hat) סימון במשוואות. ה y מתייחס לערכים בפועל ול- ŷ לערכים החזויים.

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

$$
mse = sum_{i=1}^{D}(בפועל - חזוי)^2
$$

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

$$
rmse = sqrt{ sum_{i=1}^{D}(Actual – Predicted)^2}
$$

השמיים mean_absolute_error() ו mean_squared_error() שיטות sklearn.metrics ניתן להשתמש כדי לחשב את המדדים הללו כפי שניתן לראות בקטע הבא:

from sklearn.metrics import mean_absolute_error, mean_squared_error

mae = mean_absolute_error(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = mean_squared_error(y_test, y_pred, squared=False)

print(f'mae: {mae}')
print(f'mse: {mse}')
print(f'rmse: {rmse}')

הפלט של הסקריפט לעיל נראה כך:

mae: 0.4460739527131783 
mse: 0.4316907430948294 
rmse: 0.6570317671884894

ה- R2 ניתן לחשב ישירות עם score() שיטה:

regressor.score(X_test, y_test)

אילו תפוקות:

0.6737569252627673

התוצאות מראות שהשגיאה הכוללת והשגיאה הממוצעת של אלגוריתם KNN שלנו קיימים 0.44, ו 0.43. כמו כן, ה-RMSE מראה שאנו יכולים לעבור מעל או מתחת לערך הנתונים בפועל על ידי הוספה 0.65 או חיסור 0.65. כמה טוב זה?

בואו נבדוק איך נראים המחירים:

y.describe()
count    20640.000000
mean         2.068558
std          1.153956
min          0.149990
25%          1.196000
50%          1.797000
75%          2.647250
max          5.000010
Name: MedHouseVal, dtype: float64

הממוצע הוא 2.06 וסטיית התקן מהממוצע היא 1.15 אז הציון שלנו של ~0.44 הוא לא ממש כוכב, אבל הוא לא רע מדי.

עם ה-R2, ככל שנגיע הכי קרוב ל-1 (או 100), כך ייטב. ה-R2 מספר כמה מהשינויים בנתונים, או בנתונים שונות מובנים או מוסבר מאת KNN.

$$
R^2 = 1 – frac{sum(Actual – Predicted)^2}{sum(Actual – Actual Mean)^2}
$$

עם ערך של 0.67, אנו יכולים לראות שהמודל שלנו מסביר 67% מהשונות בנתונים. זה כבר יותר מ-50%, וזה בסדר, אבל לא ממש טוב. האם יש דרך שנוכל להשתפר?

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

מציאת ה-K הטוב ביותר עבור רגרסיה של KNN

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

לשם כך, ניצור לולאת for ונפעיל מודלים שיש להם מ-1 עד X שכנים. בכל אינטראקציה, נחשב את ה-MAE ונתווה את מספר Ks יחד עם תוצאת ה-MAE:

error = []


for i in range(1, 40):
    knn = KNeighborsRegressor(n_neighbors=i)
    knn.fit(X_train, y_train)
    pred_i = knn.predict(X_test)
    mae = mean_absolute_error(y_test, pred_i)
    error.append(mae)

עכשיו, בואו נתווה את errors:

import matplotlib.pyplot as plt 

plt.figure(figsize=(12, 6))
plt.plot(range(1, 40), error, color='red', 
         linestyle='dashed', marker='o',
         markerfacecolor='blue', markersize=10)
         
plt.title('K Value MAE')
plt.xlabel('K Value')
plt.ylabel('Mean Absolute Error')

מדריך לאלגוריתם K-Nearest Neighbors ב-Python ו-Scikit-Learn PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

כשמסתכלים על העלילה, נראה שערך ה-MAE הנמוך ביותר הוא כאשר K הוא 12. בואו נסתכל מקרוב על העלילה כדי להיות בטוחים על ידי תכנון פחות נתונים:

plt.figure(figsize=(12, 6))
plt.plot(range(1, 15), error[:14], color='red', 
         linestyle='dashed', marker='o',
         markerfacecolor='blue', markersize=10)
plt.title('K Value MAE')
plt.xlabel('K Value')
plt.ylabel('Mean Absolute Error')

מדריך לאלגוריתם K-Nearest Neighbors ב-Python ו-Scikit-Learn PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

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

אתה יכול גם לקבל את השגיאה הנמוכה ביותר ואת האינדקס של אותה נקודה באמצעות המובנה min() פונקציה (עובדת על רשימות) או המרה את הרשימה למערך NumPy וקבל את argmin() (אינדקס של האלמנט בעל הערך הנמוך ביותר):

import numpy as np 

print(min(error))               
print(np.array(error).argmin()) 

התחלנו לספור שכנים על 1, בעוד שמערכים הם מבוססי 0, כך שהאינדקס ה-11 הוא 12 שכנים!

זה אומר שאנחנו צריכים 12 שכנים כדי להיות מסוגלים לחזות נקודה עם שגיאת ה-MAE הנמוכה ביותר. נוכל לבצע שוב את המודל והמדדים עם 12 שכנים כדי להשוות תוצאות:

knn_reg12 = KNeighborsRegressor(n_neighbors=12)
knn_reg12.fit(X_train, y_train)
y_pred12 = knn_reg12.predict(X_test)
r2 = knn_reg12.score(X_test, y_test) 

mae12 = mean_absolute_error(y_test, y_pred12)
mse12 = mean_squared_error(y_test, y_pred12)
rmse12 = mean_squared_error(y_test, y_pred12, squared=False)
print(f'r2: {r2}, nmae: {mae12} nmse: {mse12} nrmse: {rmse12}')

פלט הקוד הבא:

r2: 0.6887495617137436, 
mae: 0.43631325936692505 
mse: 0.4118522151025172 
rmse: 0.6417571309323467

עם 12 שכנים מודל ה-KNN שלנו מסביר כעת 69% מהשונות בנתונים, ואיבד קצת פחות, בעקבות 0.44 ל 0.43, 0.43 ל 0.41, ו 0.65 ל 0.64 עם המדדים המתאימים. זה לא שיפור גדול במיוחד, אבל זה שיפור בכל זאת.

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

כבר ראינו איך משתמשים ב-KNN לרגרסיה - אבל מה אם היינו רוצים לסווג נקודה במקום לחזות את ערכה? כעת, אנו יכולים להסתכל כיצד להשתמש ב-KNN לסיווג.

סיווג באמצעות K-Nearest Neighbors עם Scikit-Learn

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

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

עיבוד מוקדם של נתונים לסיווג

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


df["MedHouseValCat"] = pd.qcut(df["MedHouseVal"], 4, retbins=False, labels=[1, 2, 3, 4])

לאחר מכן, נוכל לפצל את מערך הנתונים שלנו לתכונות והתוויות שלו:

y = df['MedHouseValCat']
X = df.drop(['MedHouseVal', 'MedHouseValCat'], axis = 1)

מאז שהשתמשנו ב MedHouseVal עמודה כדי ליצור פחים, אנחנו צריכים להוריד את MedHouseVal טור ו MedHouseValCat עמודות מ X. בדרך זו, ה DataFrame יכיל את 8 העמודות הראשונות של מערך הנתונים (כלומר תכונות, תכונות) בעוד שלנו y יכיל רק את MedHouseValCat תווית שהוקצתה.

הערה: אתה יכול גם לבחור עמודות באמצעות .iloc() במקום להפיל אותם. בעת שחרור, רק שים לב שאתה צריך להקצות y ערכים לפני הקצאה X ערכים, מכיוון שאינך יכול להקצות עמודה שנשמטה של ​​a DataFrame לאובייקט אחר בזיכרון.

פיצול נתונים למערכות רכבת ובדיקות

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

from sklearn.model_selection import train_test_split

SEED = 42
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=SEED)

נשתמש בערך Scikit-Learn הסטנדרטי של 75% נתוני רכבת ו-25% נתוני בדיקה שוב. משמעות הדבר היא שיהיו לנו אותו רכבת ומספר בדיקות של שיאים כמו ברגרסיה שלפני כן.

שינוי קנה מידה עבור סיווג

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

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
scaler.fit(X_train)

X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

אימון וחיזוי לסיווג

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

from sklearn.neighbors import KNeighborsClassifier

classifier = KNeighborsClassifier()
classifier.fit(X_train, y_train)

לאחר התאמת ה KNeighborsClassifier, נוכל לחזות את המחלקות של נתוני המבחן:

y_pred = classifier.predict(X_test)

הגיע הזמן להעריך את התחזיות! האם חיזוי שיעורים תהיה גישה טובה יותר מאשר חיזוי ערכים במקרה זה? בואו נעריך את האלגוריתם כדי לראות מה קורה.

הערכת KNN לסיווג

להערכת מסווג KNN, נוכל גם להשתמש ב- score שיטה, אבל היא מבצעת מדד שונה מכיוון שאנו מציינים מסווג ולא רגרסור. המדד הבסיסי לסיווג הוא accuracy - הוא מתאר כמה תחזיות המסווג שלנו צדק. ערך הדיוק הנמוך ביותר הוא 0 והגבוה ביותר הוא 1. אנחנו בדרך כלל מכפילים את הערך הזה ב-100 כדי לקבל אחוז.

$$
דיוק = frac{טקסט{מספר תחזיות נכונות}}{טקסט{מספר כולל של התחזיות}}
$$

הערה: קשה מאוד להשיג דיוק של 100% על נתונים אמיתיים כלשהם, אם זה קורה, היו מודעים לכך שאולי מתרחשת דליפה כלשהי או משהו שגוי - אין הסכמה לגבי ערך דיוק אידיאלי והוא גם תלוי הקשר. תלוי ב עלות הטעות (כמה זה גרוע אם אנחנו סומכים על המסווג ומתברר שהוא שגוי), שיעור שגיאות מקובל עשוי להיות 5%, 10% או אפילו 30%.

בוא נקפוץ את המיון שלנו:

acc =  classifier.score(X_test, y_test)
print(acc) 

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

יש 4 מחלקות במערך הנתונים שלנו - מה אם המסווג שלנו קיבל 90% מהשיעורים 1, 2 ו-3 נכון, אבל רק 30% מכיתה 4 נכון?

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

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

  1. מטריקס בלבול: לדעת כמה צדקנו או טעינו כל כיתה. הערכים שהיו נכונים וחזויים כהלכה נקראים חיובי אמיתי אלה שנחזו כחיוביים אך לא היו חיוביים נקראים תוצאות חיוביות שגויות. אותה המינוח של שליליים אמיתיים ו שלילי שווא משמש לערכים שליליים;
  2. דיוק: להבין אילו ערכי חיזוי נכונים נחשבו נכונים על ידי המסווג שלנו. הדיוק יחלק את הערכים החיוביים האמיתיים האלה בכל מה שנחזה כחיובי;

$$
דיוק = frac{text{true positive}}{text{true positive} + text{false positive}}
$$

  1. להיזכר: כדי להבין כמה מהנקודות החיוביות האמיתיות זוהו על ידי המסווג שלנו. ההחזרה מחושבת על ידי חלוקת התוצאות החיוביות האמיתיות בכל מה שהיה צריך לחזות כחיובי.

$$
recall = frac{text{true positive}}{text{true positive} + text{false negative}}
$$

  1. ציון F1: האם המאוזן או ממוצע הרמוני של דיוק וזכירה. הערך הנמוך ביותר הוא 0 והגבוה ביותר הוא 1. מתי f1-score שווה ל-1, זה אומר שכל המחלקות חזו נכון - זה ציון שקשה מאוד להשיג עם נתונים אמיתיים (קיימים כמעט תמיד חריגים).

$$
text{f1-score} = 2* frac{text{precision} * text{recall}}{text{precision} + text{recall}}
$$

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

השמיים confusion_matrix() ו classification_report() שיטות של sklearn.metrics ניתן להשתמש במודול כדי לחשב ולהציג את כל המדדים הללו. ה confusion_matrix מוצג בצורה טובה יותר באמצעות מפת חום. דוח הסיווג כבר נותן לנו accuracy, precision, recall, ו f1-score, אבל תוכל גם לייבא כל אחד מהמדדים האלה sklearn.metrics.

כדי לקבל מדדים, בצע את הקטע הבא:

from sklearn.metrics import classification_report, confusion_matrix

import seaborn as sns


classes_names = ['class 1','class 2','class 3', 'class 4']
cm = pd.DataFrame(confusion_matrix(yc_test, yc_pred), 
                  columns=classes_names, index = classes_names)
                  

sns.heatmap(cm, annot=True, fmt='d');

print(classification_report(y_test, y_pred))

הפלט של הסקריפט לעיל נראה כך:

מדריך לאלגוריתם K-Nearest Neighbors ב-Python ו-Scikit-Learn PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

              precision    recall  f1-score   support

           1       0.75      0.78      0.76      1292
           2       0.49      0.56      0.53      1283
           3       0.51      0.51      0.51      1292
           4       0.76      0.62      0.69      1293

    accuracy                           0.62      5160
   macro avg       0.63      0.62      0.62      5160
weighted avg       0.63      0.62      0.62      5160

התוצאות מראות ש-KNN הצליחה לסווג את כל 5160 הרשומות במערך הבדיקות עם דיוק של 62%, שהוא מעל הממוצע. התמיכות שוות למדי (חלוקה שווה של מחלקות במערך הנתונים), כך שה-F1 המשוקלל וה-F1 הלא-משוקלל יהיו בערך אותו דבר.

אנו יכולים גם לראות את התוצאה של המדדים עבור כל אחת מ-4 הכיתות. מתוך כך, אנו יכולים להבחין בכך class 2 היה הדיוק הנמוך ביותר, הנמוך ביותר recall, והנמוך ביותר f1-score. Class 3 נמצא ממש מאחור class 2 על כך שיש לנו את הציונים הנמוכים ביותר, ואז יש לנו class 1 עם הציונים הטובים ביותר ואחריהם class 4.

על ידי התבוננות במטריצת הבלבול, אנו יכולים לראות כי:

  • class 1 טעה בעיקר class 2 ב-238 מקרים
  • class 2 ל class 1 ב-256 ערכים, ועבור class 3 ב-260 מקרים
  • class 3 טעה בעיקר על ידי class 2, 374 ערכים, ו class 4, ב-193 מקרים
  • class 4 סווג בטעות כ class 3 עבור 339 כניסות, וכמו class 2 ב-130 מקרים.

כמו כן, שימו לב שהאלכסון מציג את הערכים החיוביים האמיתיים, כאשר מסתכלים עליו, ברור לראות כי class 2 ו class 3 יש את הערכים החזויים הכי פחות נכונים.

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

נסה תמיד לבדוק את הנתונים עם מספר אחר של פחים כדי לראות מה קורה.

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

מציאת ה-K הטוב ביותר עבור סיווג KNN

בוא נחזור על מה שנעשה עבור רגרסיה ונתווה את הגרף של ערכי K ואת המדד המתאים לקבוצת הבדיקות. אתה יכול גם לבחור איזה מדד מתאים יותר להקשר שלך, כאן אנחנו נבחר f1-score.

בדרך זו, נתווה את f1-score עבור הערכים החזויים של ערכת הבדיקה עבור כל ערכי K בין 1 ל-40.

ראשית, אנו מייבאים את f1_score החל מ- sklearn.metrics ולאחר מכן חשב את הערך שלו עבור כל התחזיות של מסווג K-Nearest Neighbors, כאשר K נע בין 1 ל-40:

from sklearn.metrics import f1_score

f1s = []


for i in range(1, 40):
    knn = KNeighborsClassifier(n_neighbors=i)
    knn.fit(X_train, y_train)
    pred_i = knn.predict(X_test)
    
    f1s.append(f1_score(y_test, pred_i, average='weighted'))

השלב הבא הוא לתכנן את f1_score ערכים מול ערכי K. ההבדל מהרגרסיה הוא שבמקום לבחור בערך K שממזער את השגיאה, הפעם נבחר את הערך שממקסם את f1-score.

בצע את הסקריפט הבא כדי ליצור את העלילה:

plt.figure(figsize=(12, 6))
plt.plot(range(1, 40), f1s, color='red', linestyle='dashed', marker='o',
         markerfacecolor='blue', markersize=10)
plt.title('F1 Score K Value')
plt.xlabel('K Value')
plt.ylabel('F1 Score')

גרף הפלט נראה כך:

מדריך לאלגוריתם K-Nearest Neighbors ב-Python ו-Scikit-Learn PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

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

classifier15 = KNeighborsClassifier(n_neighbors=15)
classifier15.fit(X_train, y_train)
y_pred15 = classifier15.predict(X_test)
print(classification_report(y_test, y_pred15))

תפוקות אלה:

              precision    recall  f1-score   support

           1       0.77      0.79      0.78      1292
           2       0.52      0.58      0.55      1283
           3       0.51      0.53      0.52      1292
           4       0.77      0.64      0.70      1293

    accuracy                           0.63      5160
   macro avg       0.64      0.63      0.64      5160
weighted avg       0.64      0.63      0.64      5160

שימו לב שהמדדים שלנו השתפרו עם 15 שכנים, יש לנו דיוק של 63% ומעלה precision, recall, ו f1-scores, אבל אנחנו עדיין צריכים להסתכל עוד יותר על הפחים כדי לנסות להבין מדוע f1-score לשיעורים 2 ו 3 עדיין נמוך.

מלבד השימוש ב-KNN עבור רגרסיה וקביעת ערכי בלוק ולסיווג, לקביעת מחלקות בלוק – אנו יכולים גם להשתמש ב-KNN לזיהוי אילו ערכי בלוקים ממוצעים שונים מהרוב – אלו שלא עוקבים אחר מה שרוב הנתונים עושים. במילים אחרות, אנחנו יכולים להשתמש ב-KNN עבור זיהוי חריגים.

הטמעת KNN לזיהוי חריגים עם Scikit-Learn

זיהוי חריגים משתמש בשיטה אחרת השונה ממה שעשינו קודם עבור רגרסיה וסיווג.

כאן נראה כמה רחוק כל אחד מהשכנים מנקודת נתונים. בואו נשתמש ברירת המחדל של 5 שכנים. עבור נקודת נתונים, נחשב את המרחק לכל אחד מהשכנים הקרובים ביותר ל-K. לשם כך, נייבא אלגוריתם KNN אחר מ-Scikit-learn שאינו ספציפי עבור רגרסיה או סיווג שנקרא פשוט NearestNeighbors.

לאחר הייבוא, נבצע מופע א NearestNeighbors מחלקה עם 5 שכנים - אתה יכול גם ליצור אותו עם 12 שכנים כדי לזהות חריגים בדוגמה של הרגרסיה שלנו או עם 15, כדי לעשות את אותו הדבר עבור דוגמה לסיווג. לאחר מכן נתאים את נתוני הרכבת שלנו ונשתמש ב- kneighbors() שיטה למצוא את המרחקים המחושבים שלנו עבור כל נקודת נתונים ואינדקסים של שכנים:

from sklearn.neighbors import NearestNeighbors

nbrs = NearestNeighbors(n_neighbors = 5)
nbrs.fit(X_train)

distances, indexes = nbrs.kneighbors(X_train)

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

כדי להסתכל על צורת שלושת המרחקים הראשונים, בצע:

distances[:3], distances.shape
(array([[0.        , 0.12998939, 0.15157687, 0.16543705, 0.17750354],
        [0.        , 0.25535314, 0.37100754, 0.39090243, 0.40619693],
        [0.        , 0.27149697, 0.28024623, 0.28112326, 0.30420656]]),
 (3, 5))

שימו לב שיש 3 שורות עם 5 מרחקים כל אחת. אנחנו יכולים גם לעיין באינדקסים של השכנים:

indexes[:3], indexes[:3].shape

זו התוצאה:

(array([[    0,  8608, 12831,  8298,  2482],
        [    1,  4966,  5786,  8568,  6759],
        [    2, 13326, 13936,  3618,  9756]]),
 (3, 5))

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

dist_means = distances.mean(axis=1)
plt.plot(dist_means)
plt.title('Mean of the 5 neighbors distances for each data point')
plt.xlabel('Count')
plt.ylabel('Mean Distances')

מדריך לאלגוריתם K-Nearest Neighbors ב-Python ו-Scikit-Learn PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

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

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

dist_means = distances.mean(axis=1)
plt.plot(dist_means)
plt.title('Mean of the 5 neighbors distances for each data point with cut-off line')
plt.xlabel('Count')
plt.ylabel('Mean Distances')
plt.axhline(y = 3, color = 'r', linestyle = '--')

מדריך לאלגוריתם K-Nearest Neighbors ב-Python ו-Scikit-Learn PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

קו זה מסמן את המרחק הממוצע שמעליו כל הערכים משתנים. זה אומר שכל הנקודות עם א mean מרחק מעל 3 הם החריגים שלנו. אנו יכולים לגלות את האינדקסים של הנקודות הללו באמצעות np.where(). גם שיטה זו תפיק פלט True or False עבור כל מדד ביחס ל mean מעל 3 מַצָב:

import numpy as np


outlier_index = np.where(dist_means > 3)
outlier_index

פלט הקוד לעיל:

(array([  564,  2167,  2415,  2902,  6607,  8047,  8243,  9029, 11892,
        12127, 12226, 12353, 13534, 13795, 14292, 14707]),)

כעת יש לנו את מדדי הנקודות החריגים שלנו. בואו נאתר אותם במסגרת הנתונים:


outlier_values = df.iloc[outlier_index]
outlier_values

זו התוצאה:

		MedInc 	HouseAge AveRooms 	AveBedrms 	Population 	AveOccup 	Latitude 	Longitude 	MedHouseVal
564 	4.8711 	27.0 	 5.082811 	0.944793 	1499.0 	    1.880803 	37.75 		-122.24 	2.86600
2167 	2.8359 	30.0 	 4.948357 	1.001565 	1660.0 	    2.597809 	36.78 		-119.83 	0.80300
2415 	2.8250 	32.0 	 4.784232 	0.979253 	761.0 	    3.157676 	36.59 		-119.44 	0.67600
2902 	1.1875 	48.0 	 5.492063 	1.460317 	129.0 	    2.047619 	35.38 		-119.02 	0.63800
6607 	3.5164 	47.0 	 5.970639 	1.074266 	1700.0 	    2.936097 	34.18 		-118.14 	2.26500
8047 	2.7260 	29.0 	 3.707547 	1.078616 	2515.0 	    1.977201 	33.84 		-118.17 	2.08700
8243 	2.0769 	17.0 	 3.941667 	1.211111 	1300.0 	    3.611111 	33.78 		-118.18 	1.00000
9029 	6.8300 	28.0 	 6.748744 	1.080402 	487.0 		2.447236 	34.05 		-118.78 	5.00001
11892 	2.6071 	45.0 	 4.225806 	0.903226 	89.0 		2.870968 	33.99 		-117.35 	1.12500
12127 	4.1482 	7.0 	 5.674957 	1.106998 	5595.0 		3.235975 	33.92 		-117.25 	1.24600
12226 	2.8125 	18.0 	 4.962500 	1.112500 	239.0 		2.987500 	33.63 		-116.92 	1.43800
12353 	3.1493 	24.0 	 7.307323 	1.460984 	1721.0 		2.066026 	33.81 		-116.54 	1.99400
13534 	3.7949 	13.0 	 5.832258 	1.072581 	2189.0 		3.530645 	34.17 		-117.33 	1.06300
13795 	1.7567 	8.0 	 4.485173 	1.120264 	3220.0 		2.652389 	34.59 		-117.42 	0.69500
14292 	2.6250 	50.0 	 4.742236 	1.049689 	728.0 		2.260870 	32.74 		-117.13 	2.03200
14707 	3.7167 	17.0 	 5.034130 	1.051195 	549.0 		1.873720 	32.80 		-117.05 	1.80400

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

יתרונות וחסרונות של KNN

בחלק זה, נציג כמה מהיתרונות והחסרונות של השימוש באלגוריתם KNN.

Pros

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

חסרונות

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

הולך רחוק יותר - פרויקט יד מקצה לקצה

מדריך לאלגוריתם K-Nearest Neighbors ב-Python ו-Scikit-Learn PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

בפרויקט מודרך זה - תלמדו כיצד לבנות מודלים מסורתיים רבי עוצמה של למידת מכונה, כמו גם מודלים של למידה עמוקה, להשתמש ב-Ensemble Learning ולהכשיר מטא-לומדים לחזות מחירי בתים מתוך שקית של דגמי Scikit-Learn ו-Keras.

באמצעות Keras, API ללמידה עמוקה שנבנה על גבי Tensorflow, נתנסה בארכיטקטורות, נבנה אנסמבל של מודלים מוערמים ונאמן מטא-לומד רשת עצבית (מודל רמה 1) כדי להבין את התמחור של בית.

למידה עמוקה היא מדהימה - אבל לפני שניגשים אליה, מומלץ לנסות לפתור את הבעיה גם בטכניקות פשוטות יותר, כמו עם למידה רדודה אלגוריתמים. ביצועי הבסיס שלנו יתבססו על א רגרסיה אקראית של יער אַלגוֹרִיתְם. בנוסף - נחקור יצירת אנסמבלים של מודלים באמצעות Scikit-Learn באמצעות טכניקות כגון שקית ו הצבעה.

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

סיכום

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

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

במדריך זה – עברנו על רגרסיה, סיווג וזיהוי חריגים באמצעות היישום של Scikit-Learn של אלגוריתם K-Nearest Neighbor.

בול זמן:

עוד מ Stackabuse