Machine Learning: Откриване на аномалии сред обяви за имоти

Възможно е да попаднем в случаи, когато извадката, с която работим, съдържа отличителни стойности (outliers), т.е. наблюдения, различаващи се от останалите по стойностите на една или повече характеристики. Те може да са се получили в резултат на грешки (при въвеждане, измерване, обработка на данните, извличане от различни източници и др.) или в действителност стойностите да са такива. Подобни наблюдения се наричат още абнормални и е възможно да доведат до изкривяване на получените резултати от моделите за машинно обучение и да бъдат повод за притеснение.

Задачи, свързани с откриване на аномалии в данните (anomaly detection или outlier detection) намират широко приложение в различни области. Например при засичане на необичайни транзакции с банкови карти или при идентифициране на дефекти в машини. За откриване на аномалии могат да се използват множество различни методи. Точно кой ще изберем зависи от това дали търсим абнормални стойности в една или в повече характеристики. Ако ни интересува само една, можем да представим стойностите в нея визуално с хистограма или диаграма тип кутия, които биха ни дали представа за наличието на необичайно високи или ниски стойности.
Ако данните ни са с повече дименсии обаче, трябва да използваме някой по-сложен метод. Например k най-близки съседи (kNN), при който се изчисляват разстояния между отделните наблюдения или Isolation Forest, работещ на принципа на дърво за взимане на решения за изолиране на наблюденията, в които се срещат аномалии.

В тази статия ще разгледаме в контекста на практически пример как можем да идентифицираме аномалии с помощта на езика за програмиране Python и неговите библиотеки за анализ на данни и машинно обучение.

С какви данни ще работим?

Извадката съдържа 1177 реда и 33 колони. Данните са за обяви за имоти под наем от различни български сайтове.

5 случайно избрани реда изглеждат по следния начин:

typepricesizeheatingviewsagencycitylocap_floorb_floortime_createddaymonthyearfurnishednew_buildingnear_ptnear_parknear_grocery_storesnear_schoolsnear_mallnear_cinemarenovatednear_medicalpetsparkingsecuritylow_billslong_termnear_pharmacynear_gymnear_postpvc
926двустаен75065Не316НеСофияСтудентски град3613:064март2021НеНеДаНеДаНеНеНеНеНеНеДаНеНеНеНеНеНеНе
263тристаен58871Не2ДаВарнаБриз1513:2517март2021ДаНеДаНеНеДаНеНеНеНеНеНеНеНеНеНеНеНеНе
1136едностаен341.0440Не1006ДаСофияСтудентски град81610:2422февруари2021НеНеНеДаНеНеНеНеНеНеНеДаДаНеНеНеНеНеНе
455едностаен45050Не25ДаСофияКрасно село279:422март2021ДаНеНеНеНеНеНеНеНеНеНеНеНеНеНеНеНеНеНе
237многостаен300105Не96НеРусеДружба 11514:074март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.

Научете повече

Автор: Десислава Христова