บทนำ
พื้นที่ K-เพื่อนบ้านที่ใกล้ที่สุด (KNN) อัลกอริธึมเป็นประเภทของอัลกอริธึมการเรียนรู้ของเครื่องภายใต้การดูแลที่ใช้สำหรับการจำแนกประเภท การถดถอย และการตรวจจับค่าผิดปกติ มันง่ายมากที่จะนำไปใช้ในรูปแบบพื้นฐานที่สุด แต่สามารถทำงานที่ค่อนข้างซับซ้อนได้ เป็นอัลกอริธึมการเรียนรู้ที่ขี้เกียจเนื่องจากไม่มีขั้นตอนการฝึกอบรมเฉพาะทาง แต่จะใช้ข้อมูลทั้งหมดสำหรับการฝึกอบรมในขณะที่จัดประเภท (หรือถดถอย) จุดข้อมูลหรืออินสแตนซ์ใหม่
KNN เป็น อัลกอริธึมการเรียนรู้แบบไม่อิงพารามิเตอร์ซึ่งหมายความว่าไม่ถือเอาอะไรเกี่ยวกับข้อมูลพื้นฐาน นี่เป็นคุณสมบัติที่มีประโยชน์อย่างยิ่ง เนื่องจากข้อมูลในโลกแห่งความเป็นจริงส่วนใหญ่ไม่เป็นไปตามสมมติฐานทางทฤษฎีใดๆ เช่น การแยกตัวเชิงเส้น การแจกแจงแบบสม่ำเสมอ เป็นต้น
ในคู่มือนี้ เราจะมาดูกันว่า KNN สามารถนำไปใช้กับไลบรารี Scikit-Learn ของ Python ได้อย่างไร ก่อนหน้านั้น เราจะมาสำรวจกันก่อนว่าเราจะใช้ KNN และอธิบายทฤษฎีเบื้องหลังได้อย่างไร หลังจากนั้นเราจะมาดูที่ ชุดข้อมูลที่อยู่อาศัยในแคลิฟอร์เนีย เราจะใช้เพื่อแสดงอัลกอริทึม KNN และรูปแบบต่างๆ ก่อนอื่น เราจะมาดูวิธีการใช้อัลกอริทึม KNN สำหรับการถดถอย ตามด้วยการใช้งานการจัดประเภท KNN และการตรวจจับค่าผิดปกติ ในท้ายที่สุด เราจะสรุปข้อดีและข้อเสียของอัลกอริทึม
คุณควรใช้ KNN เมื่อใด
สมมติว่าคุณต้องการเช่าอพาร์ตเมนต์และเพิ่งพบว่าเพื่อนบ้านของเพื่อนของคุณอาจปล่อยอพาร์ตเมนต์ของเธอให้เช่าใน 2 สัปดาห์ เนื่องจากอพาร์ตเมนต์ยังไม่มีเว็บไซต์ให้เช่า คุณจะลองประเมินราคาเช่าได้อย่างไร
สมมติว่าเพื่อนของคุณจ่ายค่าเช่า 1,200 ดอลลาร์ ค่าเช่าของคุณอาจใกล้เคียงตัวเลขนั้น แต่อพาร์ทเมนท์ไม่เหมือนกันทุกประการ (การวางแนว พื้นที่ คุณภาพของเฟอร์นิเจอร์ ฯลฯ) ดังนั้น จะเป็นการดีถ้ามีข้อมูลเพิ่มเติมเกี่ยวกับอพาร์ทเมนท์อื่น
โดยการถามเพื่อนบ้านคนอื่นๆ และดูอพาร์ตเมนต์จากอาคารเดียวกันกับที่ระบุไว้ในเว็บไซต์ให้เช่า ค่าเช่าอพาร์ตเมนต์ใกล้เคียงที่สุดสามแห่งคือ $1,200, $1,210, $1,210 และ $1,215 อพาร์ทเมนท์เหล่านั้นอยู่ในบล็อกและชั้นเดียวกับอพาร์ตเมนต์ของเพื่อนคุณ
อพาร์ทเมนท์อื่นที่อยู่ไกลออกไป บนชั้นเดียวกัน แต่ในบล็อกอื่นมีค่าเช่า $1,400, $1,430, $1,500 และ $1,470 ดูเหมือนว่าจะมีราคาแพงกว่าเนื่องจากมีแสงจากดวงอาทิตย์มากขึ้นในตอนเย็น
เมื่อพิจารณาจากความใกล้ชิดของอพาร์ตเมนต์แล้ว ดูเหมือนว่าค่าเช่าของคุณจะอยู่ที่ประมาณ 1,210 ดอลลาร์ นั่นคือความคิดทั่วไปของสิ่งที่ K-เพื่อนบ้านที่ใกล้ที่สุด (KNN) อัลกอริทึมไม่! มันจัดประเภทหรือถดถอยข้อมูลใหม่ตามความใกล้ชิดกับข้อมูลที่มีอยู่แล้ว
แปลตัวอย่างเป็นทฤษฎี
เมื่อค่าประมาณเป็นตัวเลขต่อเนื่อง เช่น มูลค่าค่าเช่า KNN ใช้สำหรับ ถดถอย. แต่เรายังสามารถแบ่งอพาร์ทเมนท์ออกเป็นหมวดหมู่ตามค่าเช่าขั้นต่ำและสูงสุดได้ เป็นต้น เมื่อค่าไม่ต่อเนื่องทำให้เป็นหมวดหมู่ KNN ใช้สำหรับ การจัดหมวดหมู่.
นอกจากนี้ยังมีความเป็นไปได้ในการประเมินว่าเพื่อนบ้านรายใดแตกต่างจากที่อื่นมากจนอาจหยุดจ่ายค่าเช่า ซึ่งก็เหมือนกับการตรวจจับว่าจุดข้อมูลใดอยู่ไกลจนไม่เข้ากับค่าหรือหมวดหมู่ใดๆ เมื่อนั้นเกิดขึ้น KNN จะถูกใช้สำหรับ การตรวจจับค่าผิดปกติ.
ในตัวอย่างของเรา เรายังทราบค่าเช่าอพาร์ตเมนต์แต่ละห้องอยู่แล้ว ซึ่งหมายความว่าข้อมูลของเรามีป้ายกำกับ KNN ใช้ข้อมูลที่มีป้ายกำกับก่อนหน้านี้ ซึ่งทำให้เป็น อัลกอริทึมการเรียนรู้ภายใต้การดูแล.
KNN ใช้งานได้ง่ายมากในรูปแบบพื้นฐานที่สุด แต่ยังดำเนินการจำแนกประเภท การถดถอย หรือการตรวจจับค่าผิดปกติที่ค่อนข้างซับซ้อน
ทุกครั้งที่มีการเพิ่มจุดใหม่ในข้อมูล KNN จะใช้ข้อมูลเพียงส่วนเดียวในการตัดสินค่า (การถดถอย) หรือคลาส (การจัดประเภท) ของจุดที่เพิ่มนั้น เนื่องจากไม่ต้องดูจุดทั้งหมดอีกครั้งจึงทำให้ อัลกอริทึมการเรียนรู้ที่ขี้เกียจ.
KNN ไม่ได้คาดเดาอะไรเกี่ยวกับคุณลักษณะของข้อมูลพื้นฐาน และไม่คาดหวังว่าข้อมูลจะพอดีกับการกระจายบางประเภท เช่น สม่ำเสมอ หรือแยกออกเชิงเส้นได้ ซึ่งหมายความว่ามันเป็น อัลกอริธึมการเรียนรู้แบบไม่อิงพารามิเตอร์. นี่เป็นคุณลักษณะที่มีประโยชน์อย่างยิ่ง เนื่องจากข้อมูลในโลกแห่งความเป็นจริงส่วนใหญ่ไม่เป็นไปตามสมมติฐานทางทฤษฎีใดๆ
การแสดงภาพการใช้งานต่างๆ ของ KNN
ดังที่แสดงให้เห็นแล้ว สัญชาตญาณที่อยู่เบื้องหลังอัลกอริทึม KNN เป็นหนึ่งในอัลกอริธึมการเรียนรู้ของเครื่องที่ควบคุมได้ตรงที่สุด อัลกอริทึมจะคำนวณ .ก่อน ระยะทาง ของจุดข้อมูลใหม่ไปยังจุดข้อมูลการฝึกอื่นๆ ทั้งหมด
หมายเหตุ สามารถวัดระยะทางได้หลายวิธี คุณสามารถใช้ Minkowski, ยุคลิด, สูตรแมนฮัตตัน, มหาลาโนบิสหรือแฮมมิง เพื่อระบุชื่อตัวชี้วัดสองสามตัว ด้วยข้อมูลที่มีมิติสูง ระยะทางแบบยุคลิดมักเริ่มล้มเหลว (มิติที่สูงคือ… แปลก) และใช้ระยะทางแมนฮัตตันแทน
หลังจากคำนวณระยะทางแล้ว KNN จะเลือกจุดข้อมูลที่ใกล้ที่สุดจำนวนหนึ่ง – 2, 3, 10 หรือจำนวนเต็มใดๆ จำนวนแต้มนี้ (2, 3, 10 เป็นต้น) คือ K ใน K-Nearest Neighbors!
ในขั้นตอนสุดท้าย หากเป็นงานถดถอย KNN จะคำนวณผลรวมถ่วงน้ำหนักเฉลี่ยของจุดที่ใกล้ที่สุด K สำหรับการทำนาย ถ้าเป็นงานการจัดประเภท จุดข้อมูลใหม่จะถูกกำหนดให้กับคลาสที่จุดที่ใกล้ที่สุด K ที่เลือกส่วนใหญ่อยู่
ลองนึกภาพอัลกอริทึมที่ใช้งานจริงโดยใช้ตัวอย่างง่ายๆ พิจารณาชุดข้อมูลที่มีตัวแปรสองตัวและค่า K เท่ากับ 3
เมื่อทำการถดถอย ภารกิจคือการหาค่าของจุดข้อมูลใหม่ โดยพิจารณาจากผลรวมถ่วงน้ำหนักเฉลี่ยของจุดที่ใกล้ที่สุด 3 จุด
KNN กับ K = 3
เมื่อ ใช้สำหรับการถดถอย:
อัลกอริทึม KNN จะเริ่มต้นด้วยการคำนวณระยะทางของจุดใหม่จากจุดทั้งหมด จากนั้นจะพบจุด 3 จุดที่มีระยะทางน้อยที่สุดไปยังจุดใหม่ ดังแสดงในรูปที่สองด้านบน ซึ่งจุดที่ใกล้ที่สุดสามจุด 47
, 58
และ 79
ถูกล้อมไว้แล้ว หลังจากนั้นจะคำนวณผลรวมถ่วงน้ำหนักของ 47
, 58
และ 79
– ในกรณีนี้ น้ำหนักจะเท่ากับ 1 – เรากำลังพิจารณาคะแนนทั้งหมดเท่ากับ แต่เราสามารถกำหนดน้ำหนักที่แตกต่างกันตามระยะทางได้ หลังจากคำนวณผลรวมถ่วงน้ำหนัก ค่าจุดใหม่คือ 61,33
.
และเมื่อทำการจำแนกประเภทงาน KNN เพื่อจำแนกจุดข้อมูลใหม่ลงใน "Purple"
or "Red"
ชั้นเรียน
KNN กับ K = 3
เมื่อ ใช้สำหรับจำแนก:
อัลกอริธึม KNN จะเริ่มแบบเดิม โดยคำนวณระยะทางของจุดใหม่จากจุดทั้งหมด หาจุดที่ใกล้ที่สุด 3 จุด ที่มีระยะห่างน้อยที่สุดไปยังจุดใหม่ แล้วจึงกำหนดแทนการคำนวณตัวเลข จุดใหม่ไปยังคลาสที่จุดที่ใกล้ที่สุดสามจุดส่วนใหญ่อยู่ คือ คลาสสีแดง ดังนั้นจุดข้อมูลใหม่จะถูกจัดประเภทเป็น "Red"
.
กระบวนการตรวจจับค่าผิดปกติจะแตกต่างจากทั้งสองข้างต้น เราจะพูดถึงมันมากขึ้นเมื่อนำไปใช้หลังจากการถดถอยและการจัดหมวดหมู่
หมายเหตุ: รหัสที่ให้ไว้ในบทช่วยสอนนี้ได้รับการทดสอบและทดสอบแล้วดังต่อไปนี้ สมุดบันทึก Jupyter.
ชุดข้อมูลที่อยู่อาศัย Scikit-Learn California
พวกเราจะไปใช้ ชุดข้อมูลที่อยู่อาศัยในแคลิฟอร์เนีย เพื่อแสดงให้เห็นว่าอัลกอริธึม KNN ทำงานอย่างไร ชุดข้อมูลนี้ได้มาจากการสำรวจสำมะโนประชากรของสหรัฐอเมริกาในปี 1990 หนึ่งแถวของชุดข้อมูลแสดงถึงสำมะโนของกลุ่มบล็อกหนึ่งกลุ่ม
ในส่วนนี้ เราจะพูดถึงรายละเอียดของชุดข้อมูลที่อยู่อาศัยในแคลิฟอร์เนีย เพื่อให้คุณเข้าใจข้อมูลที่เราจะใช้งานโดยสัญชาตญาณ สิ่งสำคัญคือต้องทำความรู้จักกับข้อมูลของคุณก่อนที่จะเริ่มทำงาน
A ปิดกั้น กลุ่มคือหน่วยทางภูมิศาสตร์ที่เล็กที่สุดที่สำนักสำรวจสำมะโนสหรัฐเผยแพร่ข้อมูลตัวอย่าง นอกจากกลุ่มบล็อกแล้ว อีกคำหนึ่งที่ใช้คือครัวเรือน ครัวเรือนคือกลุ่มคนที่อาศัยอยู่ภายในบ้าน
ชุดข้อมูลประกอบด้วยคุณลักษณะเก้าประการ:
MedInc
– รายได้เฉลี่ยในกลุ่มบล็อคHouseAge
– อายุบ้านเฉลี่ยในกลุ่มบล็อคAveRooms
– จำนวนห้องเฉลี่ย (ต่อครัวเรือน)AveBedrms
– จำนวนห้องนอนเฉลี่ย (ต่อครัวเรือน)Population
– บล็อกประชากรกลุ่มAveOccup
– จำนวนสมาชิกในครัวเรือนโดยเฉลี่ยLatitude
– ละติจูดของกลุ่มบล็อกLongitude
– กลุ่มบล็อกลองจิจูดMedHouseVal
– มูลค่าบ้านเฉลี่ยสำหรับเขตแคลิฟอร์เนีย (หลายแสนดอลลาร์)
ชุดข้อมูลคือ เป็นส่วนหนึ่งของห้องสมุด Scikit-Learn แล้วเราต้องนำเข้าและโหลดเป็น dataframe เท่านั้น:
from sklearn.datasets import fetch_california_housing
california_housing = fetch_california_housing(as_frame=True)
df = california_housing.frame
การนำเข้าข้อมูลโดยตรงจาก Scikit-Learn นำเข้ามากกว่าเฉพาะคอลัมน์และตัวเลข และรวมคำอธิบายข้อมูลเป็น Bunch
ออบเจ็กต์ – เราก็เลยแยก frame
. มีรายละเอียดเพิ่มเติมของชุดข้อมูล โปรดคลิกที่นี่เพื่ออ่านรายละเอียดเพิ่มเติม.
มานำเข้า Pandas และดูข้อมูลสองสามแถวแรกกัน:
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 กับ 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
และเช่นเดียวกันกับคุณสมบัติอื่นๆ
เรากำลังใช้อัลกอริทึมที่อิงตาม ระยะทาง และอัลกอริธึมตามระยะทางได้รับผลกระทบอย่างมากจากข้อมูลที่ไม่ได้อยู่ในระดับเดียวกัน เช่น ข้อมูลนี้ มาตราส่วนของจุด (และในทางปฏิบัติ เกือบทุกครั้ง) บิดเบือนระยะห่างที่แท้จริงระหว่างค่า
ในการทำ Feature Scaling เราจะใช้ Scikit-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%
โดยใช้ข้อมูล 75% สำหรับการฝึกอบรมและ 25% สำหรับการทดสอบ จาก 20640 บันทึก ชุดฝึกอบรมประกอบด้วย 15480 และชุดทดสอบประกอบด้วย 5160 เราสามารถตรวจสอบตัวเลขเหล่านั้นได้อย่างรวดเร็วโดยการพิมพ์ความยาวของชุดข้อมูลทั้งหมดและแยกข้อมูล :
len(X)
len(X_train)
len(X_test)
ยอดเยี่ยม! ตอนนี้เราสามารถใส่ data scaler บน 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)
เพื่อให้การโทรสั้นลง!
ตอนนี้ข้อมูลของเราถูกปรับขนาดแล้ว! ตัวปรับมาตราส่วนจะรักษาเฉพาะจุดข้อมูล ไม่ใช่ชื่อคอลัมน์ เมื่อนำไปใช้กับ 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) และสัมประสิทธิ์การกำหนด (R2):
- หมายถึงข้อผิดพลาดแอบโซลูท (MAE): เมื่อเราลบค่าที่คาดการณ์ออกจากค่าจริง ให้หาข้อผิดพลาด รวมค่าสัมบูรณ์ของข้อผิดพลาดเหล่านั้นและรับค่าเฉลี่ย ตัวชี้วัดนี้ให้แนวคิดของข้อผิดพลาดโดยรวมสำหรับการทำนายแต่ละแบบจำลอง ยิ่งเล็ก (ใกล้ 0) ยิ่งดี:
$$
mae = (frac{1}{n})sum_{i=1}^{n}left | จริง – ถูกทำนาย |
$$
หมายเหตุ คุณยังอาจพบกับ y
และ ŷ
(อ่านว่า y-hat) สัญกรณ์ในสมการ ดิ y
หมายถึงค่าจริงและ ŷ
ถึงค่าที่คาดการณ์ไว้
- ค่าเฉลี่ยกำลังสองข้อผิดพลาด (MSE): คล้ายกับเมตริก MAE แต่จะยกกำลังสองค่าสัมบูรณ์ของข้อผิดพลาด เช่นเดียวกับ MAE ยิ่งเล็กหรือใกล้ 0 ยิ่งดี ค่า MSE ถูกยกกำลังสองเพื่อให้เกิดข้อผิดพลาดขนาดใหญ่ยิ่งขึ้นไปอีก สิ่งหนึ่งที่ต้องให้ความสนใจเป็นพิเศษ คือ โดยปกติแล้วจะเป็นตัววัดที่ตีความได้ยากเนื่องจากขนาดของค่าและข้อเท็จจริงที่ว่าพวกเขาไม่ได้อยู่ในระดับเดียวกับข้อมูล
$$
mse = sum_{i=1}^{D}(จริง – คาดการณ์)^2
$$
- รูท Mean Squared Error (RMSE): พยายามแก้ปัญหาการตีความที่เกิดจาก MSE โดยการหาค่ารากที่สองของค่าสุดท้าย เพื่อที่จะปรับขนาดกลับไปเป็นหน่วยเดียวกันของข้อมูล ง่ายต่อการตีความและดีเมื่อเราต้องการแสดงหรือแสดงค่าที่แท้จริงของข้อมูลที่มีข้อผิดพลาด ซึ่งแสดงให้เห็นว่าข้อมูลอาจแตกต่างกันไปมากน้อยเพียงใด ดังนั้น หากเรามี RMSE เท่ากับ 4.35 แบบจำลองของเราอาจทำให้เกิดข้อผิดพลาดได้ เนื่องจากได้เพิ่ม 4.35 ให้กับค่าจริง หรือต้องใช้ 4.35 เพื่อให้ได้ค่าจริง ยิ่งเข้าใกล้ 0 ยิ่งดีเช่นกัน
$$
rmse = sqrt{ sum_{i=1}^{D}(จริง – คาดการณ์ไว้)^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) ยิ่งดี เดอะ อาร์2 บอกจำนวนการเปลี่ยนแปลงของข้อมูลหรือ data ความแปรปรวน กำลังถูกเข้าใจหรือ อธิบาย โดย เคเอ็นเอ็น.
$$
R^2 = 1 – frac{sum(Actual – Predicted)^2}{sum(Actual – Actual Mean)^2}
$$
ด้วยค่า 0.67
เราจะเห็นว่าแบบจำลองของเราอธิบายความแปรปรวนของข้อมูลได้ 67% มันเกิน 50% แล้ว ซึ่งก็โอเค แต่ไม่ค่อยดีนัก มีวิธีใดที่เราสามารถทำได้ดีกว่านี้หรือไม่?
เราได้ใช้ K ที่กำหนดไว้ล่วงหน้าด้วยค่าของ 5
ดังนั้นเราจึงใช้เพื่อนบ้าน 5 รายในการคาดการณ์เป้าหมายซึ่งไม่จำเป็นต้องเป็นตัวเลขที่ดีที่สุด เพื่อทำความเข้าใจว่าจำนวน K ใดในอุดมคติ เราสามารถวิเคราะห์ข้อผิดพลาดของอัลกอริทึมและเลือก K ที่ลดการสูญเสียน้อยที่สุด
ค้นหา K ที่ดีที่สุดสำหรับการถดถอย KNN
ตามหลักการแล้ว คุณจะเห็นว่าเมตริกใดเหมาะสมกับบริบทของคุณมากกว่า แต่โดยทั่วไปแล้ว การทดสอบเมตริกทั้งหมดเป็นเรื่องที่น่าสนใจ เมื่อใดก็ตามที่คุณสามารถทดสอบได้ทั้งหมด ให้ทำ ในที่นี้ เราจะแสดงวิธีการเลือก K ที่ดีที่สุดโดยใช้ค่าคลาดเคลื่อนสัมบูรณ์เฉลี่ยเท่านั้น แต่คุณสามารถเปลี่ยนเป็นเมตริกอื่นๆ และเปรียบเทียบผลลัพธ์ได้
ในการทำเช่นนี้ เราจะสร้าง for loop และรันโมเดลที่มีเพื่อนบ้านตั้งแต่ 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)
ทีนี้มาพลอต error
s:
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')
ดูพล็อตแล้วดูเหมือนว่าค่า 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')
ดูคู่มือเชิงปฏิบัติสำหรับการเรียนรู้ Git ที่มีแนวทางปฏิบัติที่ดีที่สุด มาตรฐานที่ยอมรับในอุตสาหกรรม และเอกสารสรุปรวม หยุดคำสั่ง Googling Git และจริงๆ แล้ว เรียน มัน!
คุณยังสามารถรับข้อผิดพลาดต่ำสุดและดัชนีของจุดนั้นโดยใช้ built-in 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
ปัจจุบันโมเดล KNN ของเรามีเพื่อนบ้าน 12 แห่งอธิบายความแปรปรวนของข้อมูล 69% และสูญเสียน้อยลงเล็กน้อย โดยเริ่มจาก 0.44
ไปยัง 0.43
, 0.43
ไปยัง 0.41
และ 0.65
ไปยัง 0.64
ด้วยตัวชี้วัดที่เกี่ยวข้อง มันไม่ใช่การปรับปรุงที่ใหญ่มาก แต่ก็เป็นการปรับปรุงอยู่ดี
หมายเหตุ การวิเคราะห์เพิ่มเติมในการวิเคราะห์นี้ การทำ Exploratory Data Analysis (EDA) ร่วมกับการวิเคราะห์ที่เหลืออาจช่วยในการเลือกคุณลักษณะและได้ผลลัพธ์ที่ดีขึ้น
เราได้เห็นวิธีการใช้ KNN สำหรับการถดถอย - แต่ถ้าเราต้องการจำแนกจุดแทนที่จะทำนายค่าของมันล่ะ ตอนนี้ มาดูวิธีการใช้ KNN ในการจำแนกประเภท
การจำแนกโดยใช้ K-Nearest Neighbors กับ Scikit-Learn
ในงานนี้ แทนที่จะคาดการณ์ค่าต่อเนื่อง เราต้องการคาดการณ์คลาสที่กลุ่มบล็อกเหล่านี้อยู่ ในการทำเช่นนั้น เราสามารถแบ่งค่าบ้านเฉลี่ยสำหรับเขตออกเป็นกลุ่มที่มีช่วงมูลค่าบ้านที่แตกต่างกันหรือ ถังขยะ.
เมื่อคุณต้องการใช้ค่าต่อเนื่องสำหรับการจัดประเภท คุณมักจะสามารถเก็บข้อมูลได้ ด้วยวิธีนี้ คุณสามารถคาดการณ์กลุ่ม แทนที่จะเป็นค่า
การประมวลผลข้อมูลล่วงหน้าสำหรับการจำแนกประเภท
มาสร้าง data bins เพื่อแปลงค่าต่อเนื่องของเราเป็นหมวดหมู่:
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_
class โดยไม่มีข้อโต้แย้งใด ๆ และจะใช้เพื่อนบ้าน 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% ค่อนข้างจะกระจายอย่างสม่ำเสมอ นอกจากนี้ บ่อยครั้งที่ชุดข้อมูลไม่สมดุล ดังนั้นเราจึงกลับมาที่จุดแรกด้วยความแม่นยำซึ่งเป็นตัวชี้วัดที่ไม่เพียงพอ
เราสามารถมองลึกลงไปในผลลัพธ์โดยใช้ตัวชี้วัดอื่นเพื่อให้สามารถระบุได้ ขั้นตอนนี้แตกต่างจากการถดถอย เราจะใช้:
- เมทริกซ์ความสับสน: ให้รู้ว่าเราถูกหรือผิดไปมากแค่ไหน แต่ละชั้น. ค่าที่ถูกทำนายอย่างถูกต้องเรียกว่า แง่บวกที่แท้จริง ที่ทำนายว่าเป็นผลบวกแต่ไม่เป็นบวกเรียกว่า บวกเท็จ. ศัพท์เดียวกันของ เชิงลบที่แท้จริง และ เชิงลบเท็จ ใช้สำหรับค่าลบ
- ความแม่นยำ: เพื่อทำความเข้าใจว่าค่าการทำนายที่ถูกต้องใดที่ตัวแยกประเภทของเราพิจารณาว่าถูกต้อง ความแม่นยำจะแบ่งค่าบวกที่แท้จริงเหล่านั้นด้วยค่าใดก็ตามที่คาดการณ์ว่าเป็นค่าบวก
$$
ความแม่นยำ = frac{text{true positive}}{text{true positive} + text{false positive}}
$$
- จำ: เพื่อทำความเข้าใจว่าตัวแยกประเภทของเราระบุถึงผลบวกที่แท้จริงจำนวนเท่าใด การเรียกคืนคำนวณโดยการหารผลบวกที่แท้จริงด้วยสิ่งที่ควรคาดการณ์ว่าเป็นบวก
$$
เรียกคืน = frac{text{true positive}}{text{true positive} + text{false negative}}
$$
- คะแนน F1: คือความสมดุลหรือ ฮาร์โมนิก ของความแม่นยำและการเรียกคืน ค่าต่ำสุดคือ 0 และค่าสูงสุดคือ 1 เมื่อ
f1-score
เท่ากับ 1 หมายความว่าทุกคลาสได้รับการทำนายอย่างถูกต้อง – นี่เป็นคะแนนที่ยากมากที่จะได้รับจากข้อมูลจริง (มีข้อยกเว้นเกือบทุกครั้ง)
$$
ข้อความ{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))
ผลลัพธ์ของสคริปต์ด้านบนมีลักษณะดังนี้:
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
forclass 1
ใน 256 รายการและสำหรับclass 3
ใน 260 กรณีclass 3
ส่วนใหญ่เข้าใจผิดโดยclass 2
, 374 รายการ, และclass 4
, ใน 193 กรณีclass 4
ถูกจำแนกผิดเป็นclass 3
สำหรับ 339 รายการและ asclass 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')
กราฟผลลัพธ์มีลักษณะดังนี้:
จากผลลัพธ์จะเห็นว่า 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 for การตรวจจับค่าผิดปกติ.
การใช้ KNN สำหรับการตรวจจับค่าผิดปกติด้วย Scikit-Learn
การตรวจจับค่าผิดปกติ ใช้วิธีการอื่นที่แตกต่างจากที่เราเคยทำมาก่อนหน้านี้สำหรับการถดถอยและการจำแนกประเภท
ที่นี่เราจะดูว่าเพื่อนบ้านแต่ละแห่งอยู่ห่างจากจุดข้อมูลมากแค่ไหน ลองใช้เพื่อนบ้านเริ่มต้น 5 รายการ สำหรับจุดข้อมูล เราจะคำนวณระยะทางไปยังเพื่อนบ้านที่ใกล้ที่สุด K แต่ละตัว ในการทำเช่นนั้น เราจะนำเข้าอัลกอริทึม KNN อื่นจาก Scikit-learn ซึ่งไม่ได้เจาะจงสำหรับการถดถอยหรือการจำแนกประเภทที่เรียกว่าง่ายๆ NearestNeighbors
.
หลังจากนำเข้าแล้ว เราจะยกตัวอย่าง a NearestNeighbors
class กับ 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')
สังเกตว่ามีส่วนหนึ่งของกราฟที่ระยะทางเฉลี่ยมีค่าเท่ากัน จุดแกน 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 = '--')
เส้นนี้ระบุระยะทางเฉลี่ยที่ค่าทั้งหมดจะแตกต่างกันไป ซึ่งหมายความว่าทุกจุดที่มี a 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]),)
ตอนนี้เรามีดัชนีจุดนอกรีตแล้ว ลองหาพวกเขาใน dataframe:
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
ข้อดี
- ง่ายต่อการปฏิบัติ
- เป็นอัลกอริธึมการเรียนรู้ที่ขี้เกียจ ดังนั้นจึงไม่จำเป็นต้องมีการฝึกอบรมในจุดข้อมูลทั้งหมด (ใช้ K-Nearest เพื่อนบ้านเท่านั้นในการทำนาย) สิ่งนี้ทำให้อัลกอริทึม KNN เร็วกว่าอัลกอริธึมอื่น ๆ ที่ต้องการการฝึกอบรมกับชุดข้อมูลทั้งหมด เช่น สนับสนุนเครื่องเวกเตอร์, การถดถอยเชิงเส้นฯลฯ
- เนื่องจาก KNN ไม่ต้องการการฝึกอบรมใดๆ ก่อนทำการคาดคะเน จึงสามารถเพิ่มข้อมูลใหม่ได้อย่างลงตัว
- มีเพียงสองพารามิเตอร์ที่จำเป็นในการทำงานกับ KNN นั่นคือค่าของ K และฟังก์ชันระยะทาง
จุดด้อย
- อัลกอริธึม KNN ทำงานได้ไม่ดีกับข้อมูลที่มีมิติข้อมูลสูง เนื่องจากมีมิติข้อมูลจำนวนมาก ระยะห่างระหว่างจุดต่างๆ จะ "แปลก" และเมตริกระยะทางที่เราใช้ไม่รองรับ
- สุดท้าย อัลกอริธึม KNN ทำงานได้ไม่ดีกับคุณลักษณะที่เป็นหมวดหมู่ เนื่องจากเป็นการยากที่จะหาระยะห่างระหว่างมิติข้อมูลกับคุณลักษณะที่จัดหมวดหมู่
ก้าวต่อไป - โครงการ End-to-End แบบใช้มือถือ
ในโครงการแนะนำนี้ คุณจะได้เรียนรู้วิธีสร้างโมเดลการเรียนรู้ของเครื่องแบบดั้งเดิมที่มีประสิทธิภาพ ตลอดจนโมเดลการเรียนรู้เชิงลึก ใช้การเรียนรู้ของ Ensemble และฝึกอบรมผู้เรียนเมตาเพื่อคาดการณ์ราคาบ้านจากโมเดล Scikit-Learn และ Keras
การใช้ Keras ซึ่งเป็น API การเรียนรู้เชิงลึกที่สร้างขึ้นบน Tensorflow เราจะทำการทดลองกับสถาปัตยกรรม สร้างชุดของโมเดลที่ซ้อนกัน และฝึก ผู้เรียนเมตา โครงข่ายประสาทเทียม (รุ่นระดับ 1) เพื่อหาราคาบ้าน
การเรียนรู้เชิงลึกนั้นน่าทึ่งมาก – แต่ก่อนที่จะหันไปใช้ ขอแนะนำให้พยายามแก้ปัญหาด้วยเทคนิคที่ง่ายกว่า เช่น การเรียนรู้ที่ตื้น อัลกอริทึม ประสิทธิภาพพื้นฐานของเราจะขึ้นอยู่กับ a การถดถอยของป่าแบบสุ่ม อัลกอริทึม นอกจากนี้ – เราจะสำรวจการสร้างชุดโมเดลผ่าน Scikit-Learn ผ่านเทคนิคต่างๆ เช่น การห่อ และ การออกเสียง.
นี่เป็นโปรเจ็กต์แบบ end-to-end และเช่นเดียวกับโปรเจ็กต์ Machine Learning ทั้งหมด เราจะเริ่มด้วย การวิเคราะห์ข้อมูลเชิงสำรวจ, ติดตามโดย การประมวลผลข้อมูลล่วงหน้า และในที่สุดก็ อาคารตื้น และ โมเดลการเรียนรู้เชิงลึก เพื่อให้พอดีกับข้อมูลที่เราได้สำรวจและทำความสะอาดก่อนหน้านี้
สรุป
KNN เป็นอัลกอริธึมที่เรียบง่ายแต่ทรงพลัง สามารถใช้กับงานหลายอย่าง เช่น การถดถอย การจำแนกประเภท หรือการตรวจจับค่าผิดปกติ
KNN ถูกใช้อย่างกว้างขวางเพื่อค้นหาความคล้ายคลึงของเอกสารและการจดจำรูปแบบ นอกจากนี้ยังใช้สำหรับการพัฒนาระบบผู้แนะนำและสำหรับการลดขนาดและขั้นตอนก่อนการประมวลผลสำหรับการมองเห็นด้วยคอมพิวเตอร์ โดยเฉพาะงานจดจำใบหน้า
ในคู่มือนี้ – เราได้ผ่านการถดถอย การจำแนกประเภท และการตรวจจับค่าผิดปกติโดยใช้อัลกอริทึม K-Nearest Neighbor ของ Scikit-Learn