Възможно е да попаднем в случаи, когато извадката, с която работим, съдържа отличителни стойности (outliers), т.е. наблюдения, различаващи се от останалите по стойностите на една или повече характеристики. Те може да са се получили в резултат на грешки (при въвеждане, измерване, обработка на данните, извличане от различни източници и др.) или в действителност стойностите да са такива. Подобни наблюдения се наричат още абнормални и е възможно да доведат до изкривяване на получените резултати от моделите за машинно обучение и да бъдат повод за притеснение.
Задачи, свързани с откриване на аномалии в данните (anomaly detection или outlier detection) намират широко приложение в различни области. Например при засичане на необичайни транзакции с банкови карти или при идентифициране на дефекти в машини. За откриване на аномалии могат да се използват множество различни методи. Точно кой ще изберем зависи от това дали търсим абнормални стойности в една или в повече характеристики. Ако ни интересува само една, можем да представим стойностите в нея визуално с хистограма или диаграма тип кутия, които биха ни дали представа за наличието на необичайно високи или ниски стойности.
Ако данните ни са с повече дименсии обаче, трябва да използваме някой по-сложен метод. Например k най-близки съседи (kNN), при който се изчисляват разстояния между отделните наблюдения или Isolation Forest, работещ на принципа на дърво за взимане на решения за изолиране на наблюденията, в които се срещат аномалии.
В тази статия ще разгледаме в контекста на практически пример как можем да идентифицираме аномалии с помощта на езика за програмиране Python и неговите библиотеки за анализ на данни и машинно обучение.
С какви данни ще работим?
Извадката съдържа 1177 реда и 33 колони. Данните са за обяви за имоти под наем от различни български сайтове.
5 случайно избрани реда изглеждат по следния начин:
type | price | size | heating | views | agency | city | loc | ap_floor | b_floor | time_created | day | month | year | furnished | new_building | near_pt | near_park | near_grocery_stores | near_schools | near_mall | near_cinema | renovated | near_medical | pets | parking | security | low_bills | long_term | near_pharmacy | near_gym | near_post | pvc | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
926 | двустаен | 750 | 65 | Не | 316 | Не | София | Студентски град | 3 | 6 | 13:06 | 4 | март | 2021 | Не | Не | Да | Не | Да | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не |
263 | тристаен | 588 | 71 | Не | 2 | Да | Варна | Бриз | 1 | 5 | 13:25 | 17 | март | 2021 | Да | Не | Да | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не |
1136 | едностаен | 341.04 | 40 | Не | 1006 | Да | София | Студентски град | 8 | 16 | 10:24 | 22 | февруари | 2021 | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Да | Да | Не | Не | Не | Не | Не | Не |
455 | едностаен | 450 | 50 | Не | 25 | Да | София | Красно село | 2 | 7 | 9:42 | 2 | март | 2021 | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не |
237 | многостаен | 300 | 105 | Не | 96 | Не | Русе | Дружба 1 | 1 | 5 | 14:07 | 4 | март | 2021 | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не |
5 от характеристиките са числови, а останалите 28 са категорийни.
Визуален преглед на данните
За да се запознаем по-подробно с данните, ще създадем няколко основни визуализации – стълбовидни диаграми и диаграми на разсейването. С тях ще видим какви обяви за имоти имаме, колко на брой са те според тип на имота и града, в който се намира, както и каква е връзката между отделните числови характеристики.
Тази визуализация представя броя обяви според типа на имота. Най-голям е за тристайните апартаменти – 284, а най-малък за мезонетите – 31.
На следната визуализация можете да видите броя обяви според града, в който е разположен имотът. Най-голям брой от обявите в извадката са за град София – 694, а най-малко за Пазарджик – 1.
Обявите са създадени в периода 4 януари – 3 април 2021 година, като най-много от тях са от края на месец март и най-малко през месец януари.
От визуализациите можем да достигнем до извода, че има положителна зависимост между променливите цена и големина на имота, както и между етажа, на който е имотът и броя етажи на сградата.
Откриване на аномалии чрез библиотеката PyOD
Библиотеката PyOD предоставя множество модели за откриване на аномалии в данните. За нашия пример ще използваме kNN, тъй като начина му на работа е разбираем и резултатите са лесни за интерпретация.
Необходимо е първо да кодираме категорийните променливи и след това да стандартизираме данните преди да използваме kNN.
# Кодиране на променливите
data = pd.get_dummies(df[['type','city','loc']])
# Създаване на нов DataFrame с числовите променливи
df_numerics = df.select_dtypes(['int', 'float'])
# Премахване на колоните за ден и година
df_numerics.drop(['day','year'], axis=1, inplace=True)
# Създаване на нов DataFrame с кодираните стойности
df_coded = pd.concat([data,df_numerics], axis=1)
# Създаване на модела за откриване на аномалии
alg = KNN(n_neighbors=5, metric='euclidean')
# Стандартизиране на данните
scaling = StandardScaler().fit(df_coded)
df_coded_ss = scaling.transform(df_coded)
# Прилагане на KNN за откриване на аномалии
knn = alg.fit(df_coded_ss)
Кои наблюдения са с аномалии?
# Създаване на нова колона с данни дали обавята е с отличителни стойности
df['outlier'] = knn.labels_
# Създаване на нова колона с данни за оценка за отличителност
df['outlier_score'] = knn.decision_scores_
# Извеждане на праг на отличителност
knn.threshold_
Свойството labels_ ни позволява да видим кои редове моделът е определил като абнормални, decisionscores дава информация за оценката за отличителност, a threshold_ ни показва прага на отличителност.
Оценката за отличителност при KNN е разстоянието на дадения обект от неговия k на брой съсед. В нашият случай това е 5-тият съсед.
Прагът на отличителност е 20.48, т.е. всеки обект на разстояние над праговата стойност от 5-тия си съсед се счита от модела като отличителен.
Колко обяви с отличителни стойности е открил моделът?
Моделът е определил, че в 118 обяви има аномалии. Това са 10% от всички данни. Ако искаме да намерим по-голям процент, е необходимо да зададем по-висока стойност на параметъра contamination. По подразбиране тя е 0.10.
Анализ на получените резултати
Със следващите визуализации ще анализираме резултатите, получени от модела за откриване на аномалии. Ще видим какви обяви са определени като отличителни, какво е разпределението на променливата оценка за отличителност, както и кои са по-важните характеристики, които определят дали в една обява има аномалии и каква е връзката между тях.
Най-много обяви има с оценка за отличителност между 5 и 8. Сред обявите с аномалии повечето са със стойности около 25 и 34.
Кои са по-важните характеристики, които определят дали обявата е с отличителни стойности?
С помощта на класа SelectKBest на библиотеката Scikit-learn, ще открием кои са 3-те характеристики, които оказват най-голямо влияние при определяне дали обявата е с отличителни стойности. Той получава като параметър определен статистически тест (chi2 и f_classif при задачи за класификация или f_regression, когато имаме регресионна задача) и извежда k на брой характеристики, получили най-висок резултат от теста.
# Разделяне на данните
X = df_coded.drop(['outlier'], axis=1)
y = df_coded['outlier']
# Прилагане на SelectKBest
skb = SelectKBest(chi2, k=3)
skb.fit(X, y)
X_skb = skb.transform(X)
# Извеждане на оценките за променливите
feat_importances = pd.Series(skb.scores_, index=X.columns)
# Откриване на 3-те най-значими променливи
importances = feat_importances.nlargest(3).sort_values().reset_index()
Цената е най-важната характеристика, по-която се определя дали дадена обява е с отличителни стойности.
Каква е връзката между цената и големината на имот?
На визуализацията е представена връзката между променливите цена и големина на имота. Големината на точките се определя от броя гледания на съответните обяви, а цветът от степента на отличителност. Прагът е 20.48, т.е. отличителните стойности са оранжеви и жълти на цвят. При нарастване на големината на имота се увеличава и неговата цената.
Как изглежда връзката им според типа на имота?
Също както на предната графика се съпоставят цената и големината на имота само че този път има отделни визуализации според типа на имота.
На следващите 2 графики ще видим какво е разпределението на цената за обявите с и без отличителни стойности.
При обявите без отличителни стойности има цени, които достигат до 9000 лв., но не са открити аномалии от модела, най-вероятно заради стойностите на останалите характеристики. При обявите с отличителни стойности най-много са в диапазона на по-ниските цени от 200 до 399 лв. (33 обяви) и от 400 до 599 лв (38 обяви). При обявите без отличителни стойности има най-много имоти на стойност между 400 и 600 лв.
Какво е разпределението на цената според тип имот на обяви с отличителни стойности?
Има най-големи разлики в цените на по-големите имоти – мезонети, многостайни и 4-стайни апартаменти.
Колко на брой обяви за имоти с отличителни стойности има според типа?
Най-много обяви с отличителни стойности са открити сред тези, които предлагат едностайни апартаменти – 35 на брой.
За следващата визуализация ще добавим и града, в който се намират имотите.
Най-много имоти с отличителни стойности са едностайни апартаменти в София.
Тъй като цената е най-важната характеристика за определяне дали в една обява има аномалии, нека да видим диаграмата на разсейването, където я съпоставяме с оценката за отличителност. Ще оцветим също така и точките с различни цветове според типа имот.
За тези обяви, които са с оценка за отличителност по-близо до праговата стойност, аномалиите са съвсем малки, а тези, които са с по-високи стойностии на оценка на отличителност, са обяви с много високи аномалии.
Кода на визуализациите можете да намерите в цялостния пример.
Извод
В този практически пример успяхме да идентифицираме обяви за имоти, в които има необичайно високи или ниски стойности. Това обаче не означава, че със съответната обява има някакъв проблем. За да се разбере това, е необходимо да се направи доста по-задълбочен анализ.
Искате да научите повече за машинното обучение?
Включете се в курса по машинно обучение и анализ на данни с Python.
Автор: Десислава Христова