کا-ان-ان(kNN) یک الگوریتم یادگیری ماشین نظارت شده است که اغلب برای مسائل طبقه بندی (گاهی اوقات مسائل رگرسیون) در علم داده استفاده می شود. این یکی از سادهترین الگوریتمها و در عین حال پرکاربرد با موارد استفاده ای مانند سیستمهای توصیهکننده، برنامههای تشخیص چهره و... است.
فرض اساسی در خانواده الگوریتم های نزدیکترین همسایه این است که مشاهدات مشابه در مجاورت یکدیگر قرار دارند و مشاهدات پرت معمولاً مشاهدات تنهایی هستند که از مشاهدات مشابه دور هستند.
من به جزئیات بیشتر در مورد kNN نمی پردازم زیرا هدف این مقاله بحث در مورد استفاده از kNN برای تشخیص ناهنجاری است نه تشریح الگوریتم؛ اما اگر علاقه مند هستید نگاهی به مستندات sklearn برای انواع الگوریتم های نزدیکترین همسایه بیندازید و در این لینک میتوانید تشریح این الگوریتم را در وبسایت چیستیو بخوانید.
اگرچه kNN یک الگوریتم یادگیری ماشین تحت نظارت است، اما زمانی که به تشخیص ناهنجاری میرسد یک رویکرد بدون نظارت را اتخاذ میکند. این به این دلیل است که هیچ «یادگیری» واقعی در این فرآیند وجود ندارد و هیچ برچسب گذاری از پیش تعیینشده «داده های غیر-پرت» یا «داده های پرت» در مجموعه داده وجود ندارد، در عوض، این برچسب گذاری کاملا مبتنی بر مقادیر آستانه(threshold) است.
دانشمندان داده به طور دلخواه مقادیر آستانه را تعیین می کنند که مقادیر فراتر از آن، همه ی مشاهدات ناهنجاری نامیده می شوند (مانند سیستم های تشخیص نفوذ که لاگین های زیاد یا استفاده های مشکوک را به عنوان ناهنجاری و داده مشکوک تلقی میکنند). همچنین به همین دلیل است که هیچ train_test_splitی وجود ندارد و معیار دقت(accuracy score) کارایی نخواهد داشت.
حالا بیایید یک دمو از kNN با پایتون بنویسیم.
ما برای این دمو به کتابخانه های کمی احتیاج داریم : پانداس و نام-پای برای تنظیم داده ها، matplotlib برای تجسم داده ها(data visualization)، و از پیاده سازی kNN موجود در کتابخانه scikit-learn استفاده میکنیم.
# import libraries import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.neighbors import NearestNeighbors
من از مجموعه داده مشهور «Iris» یا همان «گل زنبق» استفاده میکنم و آن را از یک مخزن گیت هاب دانلود و وارد میکنیم:
# import data data = pd.read_csv("https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv") # input data df = data[["sepal_length", "sepal_width"]]
و حالا اجازه دهید این دو متغیر را که برای مدلسازی انتخاب شدهاند، را در نمودار نمایش دهیم :
# scatterplot of inputs data plt.scatter(df["sepal_length"], df["sepal_width"])
مرحله نهایی در آمادهسازی دادهها، تبدیل ستونهای ویژگی به آرایهها است:
# create arrays X = df.values
با وجود پیاده سازی های زیاد و بسیار خوبی که وجود دارد نیازی نیست یک مدل را از اول بنویسیم. ابتدا مدل را با پارامترهایی که انتخاب کرده ایم نمونه سازی و سپس مدل را با داده های خود برازش(fit) میکنیم، همین!
پارامتر کلیدی در کا-ان-ان، n_neighbors است که تعداد همسایه هایی را که برای محاسبه فاصله از نقطه، استفاده می شود، را تعیین می کند :
# instantiate model nbrs = NearestNeighbors(n_neighbors = 3) # fit model nbrs.fit(X)
اکنون که مدل را برازش(fit) کردهایم، زمان استخراج خروجی های مدل است،1- فواصل بین نقاط داده(distances) و 2- اندیس های نزدیک ترین نقاط در مجموعه داده، که میتوانند برای تشخیص ناهنجاری ها استفاده شوند.
# distances and indexes of k-neaighbors from model outputs distances, indexes = nbrs.kneighbors(X) # plot mean of k-distances of each observation plt.plot(distances.mean(axis =1))
میانگین فواصل را برای هر یک از مشاهدات رسم میکنیم :
همانطور که در نمودار بالا مشاهده میکنید، چندین گره میخی وجود دارد و به این معنی است که بعضی از داده های ما از خوشه های دیگر پرت هستند، در واقع هر چه میانگین بیشتر باشد(محور y) به این معنی است که داده های ما پرت تر هستند.
حال وقت یکی از مهم ترین تصمیمات دانشمندان داده است، یعنی انتخاب مرز بین داده های هنجار و داده های ناهنجار است(آستانه). اگر در نمودار بالا نگاه کنید میبینید که میانگین فواصل داده های پرت، بین بازه 0.15 به بالا هستند، و ما حداقل مقدار را انتخاب میکنیم تا داده های پرت بیشتری را فیلتر کنیم.
حال اندیس نمونه های پرت در مجموعه داده را بدست میاوریم :
# visually determine cutoff values > 0.15 outlier_index = np.where(distances.mean(axis = 1) > 0.15) outlier_index
و با اندیس های بدست آمده نمونه های پرت را میتوانیم دریافت کنیم :
# filter outlier values outlier_values = df.iloc[outlier_index] outlier_values
ما در مرحله ۴ نقاط پرت و ناهنجار را پیدا کردیم و حالا میتوانیم آنها را روی نمودار از نمونه های هنجار متمایز کنیم :
# plot data plt.scatter(df["sepal_length"], df["sepal_width"], color = "b", s = 65) # plot outlier values plt.scatter(outlier_values["sepal_length"], outlier_values["sepal_width"], color = "r")
در این مقاله نحوه پیاده سازی یک kNN برای شناسایی ناهنجاری ها توضیح داده شد. هدف ایجاد درکی از نحوه انجام این کار در چند گام ساده بود، اما در هنگام کار با یک مجموعه داده واقعی تر، نیاز داریم تا آزمایش های بیشتری انجام دهیم. یک دانشمند داده، بررسی های بیشتری را انجام میدهد، تا مطمئن شود مدلی که ساخته شده، ناهنجاری ها را به خوبی شناسایی میکند.
مرجع