Привет! Я Айрат Рахматуллин — senior аналитик в команде Seller experience (SX) Авито, мы отвечаем за опыт продавцов площадки. В этой статье рассказываю, как мы создали ML-модель, которая помогает исполнителям услуг повышать ликвидность объявлений, то есть получать больше заказов от клиентов.

Что внутри статьи:
Контекст: исполнители с небольшим количеством заказов уходили с площадки
Логистическая регрессия, WoE и IV: как применять на практике
Как мы реализовали AutoWoE в Авито Услугах
Как нашли немонотонную зависимость с помощью ML-модели
В чём преимущества работы со скор-картой
Контекст: исполнители с небольшим количеством заказов уходили с площадки
На Авито пользователи могут предлагать свои услуги — от маникюра до строительства домов. Мы заметили, что среди исполнителей есть те, у кого много сделок, и те, у кого клиентов мало или нет совсем. Это чревато двумя проблемами.
Для исполнителей:
Как ни банально, но малое количество клиентов предполагает низкий доход. Для некоторых пользователей оказание услуг — это фул-тайм работа, поэтому им нужен постоянный поток заказчиков.
Для площадки Авито:
Отток пользователей. Если человеку не удаётся продать свои услуги, он может уйти с Авито и пойти пользоваться другими площадками для размещения объявлений. А когда уходят исполнители, то и заказчики тоже могут уйти с площадки, не найдя нужную услугу.
Мы решили создать инструмент, который будет помогать пользователям привлекать к своим объявлениям больше внимания и, как следствие, больше потенциальных клиентов. Расскажу, как устроена эта модель, как она работает с точки зрения пользователя, и поделюсь результатами, которые мы получили на A/B-тестах.
Коротко про модель
Чтобы не допускать оттока исполнителей и повышать ликвидность их объявлений, мы внедрили подсказки, которые помогают делать объявления продавцов более привлекательными. Для решения этой задачи мы использовали интерпретируемую ML-модель. Вот как это работает:
Выделили факторы, которые отличают продавцов с большим количеством сделок от тех, кто получает мало или не получает заказы вовсе. Например, заметили, что в категории «Ремонт техники» успехом пользуются исполнители, которые отвечают на сообщение в течение 5 минут. А мало сделок получают те, кто отвечает дольше двух часов.
В качестве таргета для обучения ML-модели использовали количество целевых контактов,то есть звонков и сообщений в чате от потенциальных заказчиков. Так как Авито работает по классифайдной модели, мы точно не знаем, привёл ли контакт к покупке. Но у нас есть аналитические выверенная метрика целевых контактов, которая очень близка к фактическому количеству сделок, поэтому мы используем её в качестве таргетной.
Проанализировали, как разные инструменты влияют на успешность исполнителя услуг. Например, скорость ответов клиентам в чате, количество фотографий в объявлении, подключение платных услуг продвижения или корректировка цены относительно рынка.
Для всех услуг одинаковые инструменты работают по-разному. Например, мастеру маникюра важнее быстро отвечать на сообщения, строителю — добавить побольше фото, а клинеру — установить цену ниже медианной. Для каждой подкатегории модель строит свою скор-карту с топом инструментов, где оценивает степень их влияния на результат.
Перевели полученные от ML-модели скор-карты в конкретные рекомендации для продавцов: что поменять в объявлении, продвижении, коммуникациях. И стали отправлять их пользователям.

Результат: А/Б-тест показал рост метрики целевых контактов — звонков и сообщений в чат. Выполняя рекомендации, исполнители получают больше сделок. Например, в подкатегории бизнес-услуг количество целевых звонков от заказчиков выросло на 13,9%.
Расскажу подробнее, как устроена модель.
Логистическая регрессия, WoE и IV: как применять на практике
Немного математики для понимания контекста.
Логистическая регрессия — это взвешенная сумма наших фичей, переведённая в вероятность. Мы берём все инструменты — они же фичи — и умножаем их на коэффициенты, которые подберёт ML-модель. А дальше видим сумму баллов, которая отражает вероятность того, что наш объект принадлежит какому-то из классов: Y=1 или Y=0.
В нашем случае есть такие классы:
Y=1 — класс, который нас интересует. Сюда входят объявления, которые получают много ликвидности.
Y=0 — противоположный класс. В нём объявления, которые получают мало ликвидности или не получают её вовсе.
И такие параметры модели:
X1, X2… — фичи, которые помогают селлерам получать больше сделок. Например, время ответа на сообщение или количество фотографий в объявлении.
w0, w1, w2… — коэффициенты, которые подбирает ML-модель.
p — вероятность, что наш объект принадлежит к классу 1.
(1-p) — вероятность, что наш объект принадлежит к классу 0.
Классическая логистическая регрессия выглядит так:

Формула расчёта логистической регрессии
Чтобы получить вероятности принадлежности к классу, то есть предположить, что у объявления будет хорошая ликвидность, полученную сумму заводим под сигмоиду. Если число положительное — значит, наш объект с какой-то вероятностью принадлежит к классу один и использование конкретной фичи увеличивает ликвидность объявления.
В случае отрицательного числа — чем больше оно по модулю, тем меньше вероятность, что наш объект с конкретными фичами относится к классу один.

Взяли не исходные фичи, а преобразовали их. Weight of Evidence или WoE — один из способов преобразования таргет-энкодинга. Он показывает предсказательную силу независимой переменной по отношению к зависимой переменной,то есть кодирует наши бины по отношению к таргету.
Поскольку WoE произошел из мира кредитного скоринга, его обычно описывают как меру разделения хороших и плохих клиентов. «Плохие клиенты» — те, кто не смог выплатить кредит, а «хорошие клиенты» — те, кто вернул деньги банку.
Считается этот показатель по такой формуле:

Формула расчёта WOE на примере задачи кредитного скоринга. Логарифм в формуле помогает убрать длинный хвост.
Суть в том, чтобы взять фичу и разбить её на бины / бакеты. Разбивать можно по-разному, например, в первом приближении мы равномерно разделили фичи на 10 бинов. В данном случае фича принимает значения от нуля до плюс бесконечности.
Далее мы считаем, сколько объектов Y=0 и Y=1 попало в бин. А потом рассчитываем доли нулей и единиц во всём нашем датасете. В сумме они дают 100%. Напомню, что Y=1 — класс, куда входят объявления, которые получают много ликвидности, Y=0 — противоположный класс.

Значение показателя WoE говорит нам, насколько в конкретном бине больше нулей (Y=0) или единиц (Y=1), чем в других.
Дальше если мы построим зависимость WoE от бина, то увидим, что некоторые бины очень близки друг к другу и их можно объединить в один бин, потому что у них примерно одинаковое влияние на таргетную метрику. Это видно на графике:

Объединяем диапазоны, которые близки по степени влияния на таргет (WoE). Вот что это даёт:
Было |
Стало |
Фича либо полностью влияет на таргет только положительно, то есть увеличивает вероятность приближения к единице (W1>0), либо только отрицательно и уменьшает его (W1<0). С ростом X1 на delta_X1 «баллы» растут на W1*delta_X1. То есть если в обычной логистической регрессии у нас, например, Х1 равен 50, 100 или 150, то через коэффициент, кратный этому значению, мы увеличиваем количество баллов, которые добавим или убавим. Сложно объяснить продакту, какие значения фичи можно считать «хорошими», а какие «плохими». |
Можно найти нелинейное и немонотонное влияние на таргет. При одних бинах фича будет «ролять» в плюс, а при других в минус. Можно закодировать одинаковое влияние на таргет для разных значений фичи (X1) в нужном нам диапазоне. Весь диапазон фичи удобно бьётся на «плохо», «хорошо», «отлично» — это удобно для продактов. |
Покажу, как выглядит объединение близких диапазонов на абстрактном примере:

Так выглядят таблицы после того, как мы объединили диапазоны, близкие по степени влияния на таргет.
Использовали метрику Information Value, чтобы оценивать ценность фичи. Information Value (IV) считается так:

Именно для максимизации этой метрики идёт разбиение на бины. Сумма всех значений в столбце IV показывает, насколько эта фича полезна. Принято следующее условное разделение IV:

Как мы реализовали AutoWoE в Авито Услугах
Одна из удобных библиотек, которая позволяет обучить бинарную классификацию с разбиением фичей на диапазоны по WoE — это библиотека AutoWoE от Сбера. Она требует минимум усилий по написанию кода и подходит для задач, где важна интерпретируемость факторов.
Библиотека AutoWoE от Сбера — это AutoML, в которую встроено всё необходимое. Вот что умеет эта модель:
отбирает фичи по разным критериям;
выбирает оптимальное разбиение каждой фичи;
работает с дисбалансом классов из коробки;
автоматически строит отчёты: метрики, скор-карту с разбиением фичей на диапазоны, влияние каждой фичи и диапазона;
автоматически генерирует SQL-код для реализации модели в проде.
Полезные материалы:
Библиотека AutoWoE можно на GitHub. Там же найдёте тьюториалы с кодом обучения.
Видео-разбор библиотеки на Rutube.
Основные этапы обучения AutoWoE:
1. Инициализируем объект класса. Тут много параметров, из важных можно выделить:
ограничения на монотонность — monotonic;
максимальное количество бинов, на которые можно разбить фичу — max_bin_count.
Вы либо задаёте монотонность фичи: допускаете, что фича влияет на таргет только положительно или только отрицательно. Либо говорите, что в зависимости от диапазона фича может влиять как в положительную, так и в отрицательную сторону.
Объясню на примере из задачи кредитного скоринга.
Если возраст клиента небольшой — до 22 лет — то, скорее всего, вероятность одобрения кредита будет низкой. С увеличением возраста вероятность одобрения будет повышаться, а когда дойдём до 50 лет, вероятность снова пойдёт к снижению. Это случай немонотонного влияния фичи на таргетный показатель — вероятность получить кредит.
А вот пример кода, где мы ожидаем, что фичи влияют на таргет монотонно: monotonic=True. И позволяем модели разбивать фичу максимум на 4 бина: max_bin_count=4:
from autowoe import ReportDeco, AutoWoE
auto_woe = AutoWoE (interpreted_model=True,
monotonic=True,
max_bin_count=4,
select_type=None,
pearson_th=0.9,
auc_th=.505,
vif_th=10.,
imp_th=0,
th_const=32,
force_single_split=True,
th_nan=0.01,
th_cat=0.005,
auc_tol=1e-4,
cat_alpha=100,
cat_merge_to="to_woe_0",
nan_merge_to="to_woe_0",
imp_type="feature_imp",
regularized_refit=False,
p_val=0.05,
verbose=2 )
2. Дальше фитим модель, предварительно собрав датасет с фичами и таргетом. А также считаем метрику качества бинарной классификации — ROC_AUC. Она показывает, насколько хорошего качества получилась модель.
auto_woe.fit(train[features+['target']], target_name='target')
pred = auto_woe.predict_proba(test[features+['target']])
print('roc_auc_score на test: ', roc_auc_score(test['target'], pred)
3. А затем формируем и анализируем отчёт. Я советую создать папку, куда он будет генерироваться, потому что там будет много разной информации. После выгрузки отчёт будет выглядеть так:

Выгруженный HTML-отчёт
В нём будет общее саммари: описание датасета, например, доля таргета в train и test выборки, а также главный артефакт — скор-карта. Это таблица, состоящая из фичей, бинов и показателей WoE, COEF и POINTS. Выглядит она так:
Расшифровка фичи |
feature |
Bins |
WoE |
COEFF |
POINTS |
Медианное время ответа в чате |
median_reply_time |
('-inf', '15.75') |
-1,02 |
-0,63 |
0,65 |
median_reply_time |
('15.75', '28.25') |
-0,73 |
-0,63 |
0,46 |
|
median_reply_time |
('28.25', '57.25') |
-0,48 |
-0,63 |
0,31 |
|
median_reply_time |
('57.25', '118.25') |
-0,17 |
-0,63 |
0,11 |
|
median_reply_time |
('118.25', 'inf') |
0,52 |
-0,63 |
-0,33 |
|
median_reply_time |
__NaN__ |
2,41 |
-0,63 |
-1,52 |
|
Доля позитивных отзывов |
share_active_extra_positive_reviews |
('-inf', 'inf') |
-2,21 |
-0,65 |
1,43 |
share_active_extra_positive_reviews |
__NaN__ |
0,77 |
-0,65 |
-0,50 |
|
Количество слов в описании объявления |
num_description_words |
('237.50', 'inf') |
-0,81 |
-0,21 |
0,17 |
num_description_words |
('107.50', '237.50') |
-0,34 |
-0,21 |
0,07 |
|
num_description_words |
('58.50', '107.50') |
0,03 |
-0,21 |
-0,01 |
|
num_description_words |
('36.50', '58.50') |
0,31 |
-0,21 |
-0,06 |
|
num_description_words |
('-inf', '36.50') |
0,79 |
-0,21 |
-0,16 |
|
Количество подписчиков |
num followers |
('11.50', 'inf') |
-0,44 |
-0,61 |
0,27 |
num followers |
('6.50', '11.50') |
-0,19 |
-0,61 |
0,11 |
|
num followers |
('4.50', '6.50') |
0,02 |
-0,61 |
-0,01 |
|
num followers |
('1.50', '4.50') |
0,38 |
-0,61 |
-0,23 |
|
num followers |
('-inf', '1.50') |
1,03 |
-0,61 |
-0,62 |
|
Количество фото |
num_photos |
('9.50', 'inf') |
-0,30 |
-0,12 |
0,04 |
num_photos |
('8.50', '9.50') |
-0,10 |
-0,12 |
0,01 |
|
num_photos |
('6.50', '8.50') |
0,24 |
-0,12 |
-0,03 |
|
num_photos |
('3.50', '6.50') |
0,45 |
-0,12 |
-0,05 |
|
num_photos |
('-inf', '3.50') |
0,79 |
-0,12 |
-0,10 |
|
Рейтинг селлера |
avg_seller_rating |
('4.02', 'inf') |
-0,20 |
-0,09 |
0,02 |
avg_seller_rating |
('3.27', '4.02') |
0,48 |
-0,09 |
-0,04 |
|
avg_seller_rating |
('-inf', '3.27') |
1,10 |
-0,09 |
-0,10 |
|
avg_seller_rating |
__NaN__ |
1,38 |
-0,09 |
-0,13 |
Часть скор-карты из отчёта
В таблице мы видим фичи, например, median_reply_time. Она разбита на бины: median_reply_time <=15.75. И содержит значение метрики WoE -1.02 — это степень влияния на таргет.
Также у каждой фичи есть заданные параметры коэффициента (COEF) и баллы (POINTS).
COEF — это коэффициент, при каждой фиче. Он один для фичи, как и при любой логистической регрессии.
POINTS — это баллы, которые мы получаем, когда перемножаем значения метрики WoE и коэффициента. Их можно сравнивать между собой и понимать, какие значения приближают нас к таргету больше, какие меньше, а какие и вовсе тянут вниз.
Объясню, как интерпретировать эту скор-карту на примере.
В нашем отчёте можно заметить, что, если исполнитель будет отвечать на сообщения заказчиков в течение 15 минут (median_reply_time <= 15.75) — это приблизит его сделке на 0.65 балла.
А если пользователь будет отвечать на сообщение больше 118 минут (median_reply_time >= 118.25) — это ухудшит его шансы получить сделку на 0.33 балла.
Следовательно: чем быстрее исполнитель отвечает на сообщение, тем больше шансов, что заказчик решит купить его услугу. При этом у нас появляются пороги для рекомендации и в совете мы можем отправить человеку временные рамки: «Отвечайте в течение 15 минут и вы повысите шансы получить сделку».
После применения сигмоиды к полученным показателям можно узнать вероятность получения успешной сделки в каждом случае.
4. Дальше одной командой мы генерируем SQL-скрипт, который даёт все случаи разбиения (case when):
print (auto_woe.get_sql_inference_query('table_name'))
На выходе получаем готовый SQL-код для внедрения в продакшен уже без самой ML-модели. Показываю код с частью фичей:

Мы один раз обучили модель, прогнали её в Python и потом можем применить её с помощью SQL-скрипта.
Как нашли немонотонную зависимость с помощью ML-модели
На первой итерации стоит задать параметр monotonic=False и посмотреть, будут ли интересные кейсы. Например, мы обнаружили, что, если цена в объявлении продавца сильно занижена — это влияет на ликвидность объявления так же плохо, как и завышенная цена.
Обычная линейная модель не нашла подобную зависимость — мы увидели это, только когда применили подход с WoE. Так это выглядит на нашей скор-карте:

Расшифровка фичи |
feature |
Bins |
WoE |
COEFF |
POINTS |
Отклонение цены от рынка |
price_diff |
('-inf', '-1.00') |
0,44 |
-0,80 |
-0,35 |
price_diff |
('-1.00', '-0.92') |
-0,88 |
-0,80 |
0,70 |
|
price_diff |
('-0.92', '0.63') |
-0,31 |
-0,80 |
0,25 |
|
price_diff |
('0.63', '1.09') |
0,05 |
-0,80 |
-0,04 |
|
price_diff |
('1.09', 'inf') |
0,88 |
-0,80 |
-0,70 |
Таблица, на которой видна нелинейная зависимость ликвидности, количества сделок от цены
В чём преимущества работы со скор-картой
С помощью неё мы видим оптимальные разбиения: бакеты, пороги и наилучший бакет по каждой фиче. Например, рекомендуемое время ответа заказчику отличается для разных категорий услуг. Когда заказчику нужен эвакуатор для транспорта, оптимальное время ответа жёстко ограничено. А в других случаях исполнитель может отвечать в течение часа и это не будет снижать ликвидность.
В одной таблице можем сравнивать силу влияния бакета по параметру POINTS и понимать, что исполнителю стоит улучшать в первую очередь. Например, добавлять больше фотографий, менять цену или быстрее отвечать потенциальным клиентам.
Советы по работе с AutoWoE
Ставьте библиотеку AutoWoE в отдельном виртуальном окружении — venv. Рекомендуемая версия для Python 3.10 - 0.3.8b1:

Смотрите, откалиброваны ли вероятности, то есть выходы predict_proba модели. Если нет — то можно использовать разные методы, чтобы откалибровать выход модели и фактические вероятности единичек (Y=1) в датасете.
Стройте разные модели для отдельных сегментов, кластеров. Один глобальный минус AutoWoE — с помощью него не получится построить два абсолютно разных решения двух подклассов или сегментов, которые есть в вашей выборке.
То есть, если вы решите построить модели для двух принципиально разных типов данных с разными зависимостями и смешаете их в один датасет — ничего хорошего, скорее всего, не получится. Я рекомендую делать бизнесовое разбиение, например, на понятные вам сегменты или категории — на их основе строить отдельные модели и получать разные скор-карты.
Если не знаете, что у вас за выборка, и какие сегменты могут в ней содержаться, — постройте простую модель дерева решений (Decision Tree) и посмотрите, по каким фичам идёт разбиение ближе к корню дерева. Если ветки сильно отличаются (в одной ветке используется один набор фичей и разбиений, а в другой ветке иной набор) — возможно, это кандидаты, по которым можно строить разные модели AutoWoE.
Вся статья в пяти пунктах
Решили внедрить модель для повышения ликвидности объявлений. На Авито есть исполнители услуг, у которых немного сделок. Чтобы они получили возможность увеличивать число продаж, мы внедрили систему рекомендаций, которые помогут сделать объявления более привлекательными и повысить вероятность сделки. Подсказки формируются с помощью интерпретируемой ML-модели.
Модель анализирует опыт успешных продавцов и даёт на основе этого рекомендации тем, у кого мало или вовсе нет заказов. Мы анализируем, как использование разных инструментов влияет на целевой таргет — количество звонков или сообщений в чат. Под инструментами имеем в виду, например, время ответа на сообщение от потенциального заказчика, количество фотографий в объявлении, соответствие цены услуги рыночным показателям, использование платных инструментов продвижения.
Для реализации идеи мы использовали библиотеку AutoWoE от Сбера. С помощью WoE можно разбивать фичи на бины и вычислять вероятность влияния каждого бина на таргет. Библиотека отбирает фичи по разным критериям, выбирает оптимальное разбиение каждой фичи на бины, автоматически строит отчёты и генерирует SQL-код для реализации в продакшене.
На выходе модель формирует скор-карту инструментов, где оценивает степень их влияния на таргет. Эти скор-карты дальше можно использовать для ваших целей. Например, мы оцениваем влияние разных инструментов на ликвидность объявлений, а потом переводим эти показатели в рекомендации для пользователей нашей площадки. К примеру, предлагаем отвечать на сообщения в течение определённого времени или советуем добавить в объявление больше фотографий.
После проведения А/Б-теста мы убедились, что модель помогает растить метрики целевых контактов — звонков и сообщений в чат. Выполняя рекомендации, исполнители получают больше сделок.
Спасибо вам за уделенное статье время! На вопросы готов ответить в комментариях.
Узнать больше о том, как инженерам живется в Авито, вы можете здесь, в нашем хабраблоге, на сайте AvitoTech и в телеграм-канале.
Комментарии (10)
Roland21
05.02.2025 16:43Отличная идея сделать и включить по умолчанию без спроса бота, который от имени продавца пообщался с покупателем в чатике. А ты даже не в курсе, если тебя за тупые ответы уже заслуженно обложили...
Badsanta83
05.02.2025 16:43А как насчет того что у вас на площадке куча бомбил, которые накручивают отзывы 5 звезд и приезжают не сами, а сбрасывают заказы. В профиле допустим имя Сергей - а в комментариях приехал Армен, Арсен и прочие. Вы не хотите написать модель, которая будет понижать в выдаче таких ловкачей?
Или проанализировать кучу отзывов 5 звезд в один день - ага плиточник десяток объектов за день закрыл.
Или я вообще молчу про приколы когда цена 4 тысячи, чтобы внимание привлечь , а в объявлении потом к примеру 40. И авито доставка отключена чтобы заказать по этой обманной цене не смогли.
Пора дорогуши подумать о пользователях, а не о том, как продавцов удержать.
grigr
05.02.2025 16:43На счёт продавца и как его удержать:
Уберите ограничение на количество бесплатных объявлений.
Хотел продать игрушки ставшие не нужными ребёнку. 1-2 объявления разместил, а дальше плати, причём вперёд.
И это чудное нововведение оказывается во многих категориях.
Разумеется я уйду на другие площадки, зачем тратить время на вас?
gofat
05.02.2025 16:43А как обновляются пороги? Если мы жестко "прибили гвоздями" константы, то со временем они могут устареть. И качество модели упадет.
Сюда же чуть более сложный вопрос. Предположим, что наши подсказки в моменте улучшили метрики. Но что, если мы просто временно сдвинули равновесие условного "рынка"? Что, если более успешные исполнители решат добавить еще что-то, что будет улучшать их метрики. Получим частичный возврат к исходному состоянию. Какие-то решения для этой проблемы продумывали?Ayrat_Rakhmatullin Автор
05.02.2025 16:43Спасибо за вопросы!
Как и с любой ML моделью есть этап мониторинга ее качества после ввода в прод. От того, что ее можно заинферить в виде SQL-кода не меняет общего подхода к мониторингу. Следим за качеством модели, если начинает деградировать - переобучаем модель. Причины могут быть разные:
1) поменялись пороги (теперь нужно отвечать быстрее)
2) поменялся вес фичи (раньше было важно отвечать быстрее, сейчас важнее понизить цену)
3) добавились новые фичи, которые значимо влияют на успешность исполнителей услуг (тут сложнее, но на уровне мониторинга мы увидим ухудшение ее качества). В таком случае надо собрать новый тестовый датасет с расширенным набор фичей-кандидатов. Как вариант - опросы/исследования исполнителей, просмотры "глазами" данных успешных селлеров (профили, диалоги), чтобы нагенерить новые фичи-кандидаты
wapskill
Авито никак не может исправить баг. Делаешь запрос в поисковой строке, а тебе сначала показывают карточки из других регионов. Зачем? Логичнее сначала показывать карточки товаров из твоего города.
Уже несколько раз так было, готов был приехать и забрать товар, а в переписке оказалось что человек из другой части страны.
Artur_Averin
Что-то мне кажется, что это не баг))
Ощущаю в этом нотку навязчивости в использовании их услуги доставки
suniverse
Там есть тумблер по поиском, показыаать сначала из моего региона.