Почему обычная модель отклика не отвечает на главный вопрос
Во многих маркетинговых и продуктовых задачах хочется понять не просто, кто купит или кто нажмет кнопку, а на кого вообще стоит воздействовать. Это не один и тот же вопрос. Обычная модель отклика может отлично найти людей, которые и так склонны к целевому действию. Но если мы отправим им дорогую коммуникацию, мы не увеличим эффект — мы просто потратим ресурс на тех, кто и без нас сделал бы то же самое.
Uplift modeling пытается предсказать не абсолютную вероятность события, а разницу между поведением с воздействием и без него. То есть модель ищет именно причинный прирост, а не просто склонность к действию.
Как выглядит сама идея эффекта
$$ uplift(x) = P(Y=1 \mid T=1, x) - P(Y=1 \mid T=0, x) $$Uplift для объекта x — это разница между вероятностью целевого события при наличии воздействия и вероятностью того же события без воздействия. Именно эта разница и показывает, стоит ли вмешиваться.
uplift(x)— ожидаемый прирост эффекта для объекта xY=1— наступление целевого событияT=1— наличие воздействия или treatmentT=0— отсутствие воздействия, контрольx— признаки объекта или пользователя
Это и есть главное отличие от обычной классификации. Классификатор говорит: «этот человек похож на тех, кто купил». Uplift-модель пытается сказать: «у этого человека покупка становится более вероятной именно из-за нашего действия».
Почему это сложно и почему это важно
Проблема в том, что для одного и того же пользователя мы не можем одновременно наблюдать два мира: с воздействием и без него. Поэтому uplift всегда опирается на экспериментальные или квазиэкспериментальные данные. Именно здесь качество рандомизации и корректность treatment/control играют решающую роль. Если группы собраны плохо, uplift превращается в красивую, но ненадежную цифру.
Но если постановка правильная, выигрыш огромный: можно перестать тратить бюджет на тех, кого воздействие не меняет, и сосредоточиться на тех, где действительно возникает прирост.
Как посмотреть на это на Python
import pandas as pd # создаем маленький пример с treatment и control группами
frame = pd.DataFrame({ # задаем наблюдения по пользователям
'segment': ['A', 'A', 'A', 'B', 'B', 'B'], # сегмент пользователя
'treatment': [1, 1, 0, 1, 0, 0], # был ли показан оффер
'converted': [1, 0, 0, 1, 1, 0], # случилась ли конверсия
})
agg = frame.groupby(['segment', 'treatment'])['converted'].mean().unstack(fill_value=0) # считаем конверсию отдельно для treatment и control
agg['uplift'] = agg[1] - agg[0] # измеряем прирост эффекта в каждом сегменте
print(agg.round(3)) # сравниваем, где воздействие действительно дает плюсЭтот пример намеренно простой. Но он очень полезен, потому что помогает перестроить взгляд на задачу. Мы больше не ищем просто «лучших клиентов». Мы ищем тех, чье поведение реально меняется из-за нашего решения.