Классификация объявлений о сдаче квартир по типу арендодателя: частные объявления и агентств на основе объявлений Авито
В своей работе я ставил задачу научиться классифицировать текстовые данные на основе анализа текста. Я решил работать с объявлениями на авито: все они уже распределены на две категории на самом сайте: объявления частные (поданные собственниками), и объялвения, поданные агентами. Учитывая то, что у нас уже есть “лейблы”, анализ этих объявлений становится просто задачей обучения с учителем. Может показаться (я слышал такие мнения), что раз объявления уже распределены, зачем еще их учиться разделять? Многие объявления в частном разделе поданы, на самом деле, агентами, действующими недобросовестно, зная, что частные объявления популярнее. Различие для пользователей существенно: агенты требуют комиссии, значит, услуга обходится дороже. Попадая на агента в разделе частных объявлений, пользователь теряет свое время, испытывает неудовольствие, теряет доверие к сервису. Поэтому, задача определния фальшивых частных объявлений важна для таких сервисов. В этом заключается практическое значение моей работы.
Ход проектаСначала я собрал данные (тексты объявлений о сдаче квартир на сайте Авито), привел их в нужную мне форму, и пропустил через алгоритмы классификации. Я применил классический алгоритм дерева решений и xgboost (Extra Gradient Boosting). Я выбрал второй алгоритм, потому что меня не устраивали результаты работы дерева решений и я искал что-нибудь, чтобы улучшить свои результаты. Тогда я узнал о xgboost, работа которого мне в итоге понравилась больше обычных деревьев.
ДанныеДанные с Авито я собрал 29 октября (Код доступен в скрипте collection_script_v3.R). Собраны были описания квартир из всех размещенных объявлений для обеих категорий: частные и агентские. Я написал скрипт, суть работы которого сводится к тому, что он шаг за шагом скачивает странички объявлений из каталога, вынимает оттуда описание квартиры и добавляет его к вектору описаний. Таким образом я получил два вектора с текстами объявлений: один для агентов (2554 объявления) и один для собственников (2061 объявление). (С этого момента код находится в скрипте data_processing.R)
Затем я добавил лэйблы к объявлениям: 0 для частных объявлений и 1 для агентских. Все это было объединено и преобразовано в дата фрейм.
ПрепроцессингПолучив датафрейм, я начал его препроцессинг: удалил все неалфавитные символы из документов, убрал стопслова, большие буквы и излишние пробелы. После этого я провел стемминг слов в документах, так получив итоговый корпус. Из него была создана матрица термов-документов. На названия колонк матрицы (т.е. стеммированные слова из документов) был применен stem completion, для того, чтобы привести слова к более удобной и понятной форме.
Классификация Дерево решенийЗатем я перешел к собственно классификации. Документы были разделены на две части: тренировочную и тестовую в соотношении 4 к 1. Первая модель, которую я построил – дерево решений. Без особого тюнинга результаты от нее получились не очень впечатляющими.
Точность выше случайной модели всего лишь на 12 процентов, каппа статистика – 21,9%, что по всем меркам считается низким результатом, P-Valuе не очень низкое. В матрице ошибок видно, что модели свойственна фальшотрицательная ошибка: определение частных объявлений как агентских. В целом, модель была достаточно простая и этого можно было ждать от нее, тем не менее, результат неудовлетворительный, едва ли его можно рассматривать и применять всреьез.
Посмотрим самые важные характеристики для модели:
Их оказалось всего 6. Опять же этос связано с тем, что я не настраивал модель.
Дерево строится всего по двум словам.
Я пробовал также применить модель рэндом форестс, но с ней у меня не заладилось, и я никак не мог заставить ее правильно работать, а другие модели из caret также не давали значительного прироста в результате. Тогда я оставил свою разработку, до тех пор, пока недавно не услышал о XGBoost и о том, какие чудеса он творит с данными и не решил попробовать применить его к своим данным.
XGBoost(Код для этой части находится в скрипте xgb.R)
Сперва пришлось немного приспособить данные к работе с этой моделью: перекодирование лэйблов, создание матриц, которые требует модель.
Затем я полез разбираться в том, как работает модель, и, хотя я не до конца все еще понял суть бустинга, я смог устроить небольшой перебор возможных параметров модели, в итоге остановившись на этом:
Максимальная глубина дерева: 8 уровней, маленькое eta (предотвращает оверфиттинг), соответственно (из-за ета) большое количество проходов, даже с запасом, watchlist дает возможность контролировать в ходе выполнения модели ее эффективность не только на тренировочном датасете, но и сразу на тестовом, оценк амодели ведется именно по тренировочному датасету. Если модель не улучшается в течение 200 проходов, то работа алгоритма останавливается.
Практически сырая, не настраиваемая глубоко модель показывает впечатляющие результаты:
Ошибка составляет всего 27,7%, улучшение на 10% по сравнению с обычным деревом.
Пакет xgboost дает возможности анализировать результативность модели и другими способами, в том числе с помощью графиков полезности переменных, но по какой-то причине (скорее всего, из-за большого объема данных) у меня они не строятся.
Тут также есть одно не очень хорошо прорисовываемое дерево для представления о том, как работает модель. К сожалению, оно не подружилось с маркдауном.
Финальный штрих, конфьюжен матрикс:
Ура! Модель действительно показывает себя значительно лучше, в самой матрице ошибок зрительно меньше, точность – 72,2%, каппа 0,436, что тоже не слишком много, но уже определенно лучше. P-value маленькое. Все было не зря!
ИтогиВ своей работе мне удалось достичь минимально поставленной планки: создать рабочую модель классификации объявлений от агентов и от собственников. Естественно, она не идеальна, но и различия между ними не такие явные и задача стоит непростая. На данном этапе точность в 72% при каппе 0.436 мне кажется приемлемой. Мне понравилось работать с xgboost, учитывая то, что проект еще находится в разработке, у него еще широкие круг применений и поле перспектив. Важно также, что у меня есть готовый скрипт полного цикла, с помощью которого можно напрямую спарсить данные, обработать и проанализировать их.
Планы на будущееЯ планирую продолжать развивать этот проект и довести его до максимально возможной эффективности в классификации объявлений недвижимости. В первую очередь, я хочу включить другие фичерз в свою модель, в том числе нетекстовые: наличие спец. символов (номера телефонов?), длина объявления, пунктуация, сенситивная оценка текста. Кроме того, я хочу доработать свои модели: выжать максимум из xgboost, найти лучшие для задачи параметры, методы оценки модели, разобраться с дополнительными функциями: например, мне не удалось заставить cross-validation из пакета улучшать результаты анализа. Я уверен, что этому проекту еще есть куда расти.