ML Advertising
1.21K subscribers
137 photos
13 videos
2 files
193 links
Пишу про AdTech, AI и разработку

Для связи: @evgenii_munin
Download Telegram
Привет! Если вы интересуетесь внутренней кухней и инсайтами Avito.Tech, то рекомендую вам канал big_ledovsky.

Его ведет Александр Ледовский, Team Lead команды монетизации Avito.

У себя в постах я уже рассказывал о его выступлении на DataFest'е, например по дискуссии на тему рекламных аукционов с ребятами из Яндекс Директ и Ozon. Несмотря на то, что бизнесы маркетплейса и display-рекламы отличаются друг от друга, многие технические задачи и модели очень схожи, например,

- предсказание кликабельности слотов и их ранжирование в выдаче
- или механизмы монетизации инвентаря и аукционы

Поэтому, читая канал Александра, я подчерпываю полезную информацию, которую напрямую могу применять в своей работе, к примеру по метрикам моделей предсказания кликов.

Кроме технической части здесь вы сможете узнать о буднях DS команд в Avito.Tech, актуальные вакансии, а также полезные советы о том, как сохранять work-life баланс, будучи менеджером команды.

Го подписываться! 🔥
👍3🔥2
Ранее я рассказывал про метод Adversarial Validation. Он помогает проверять, приходятся ли фичи из train/ test из одного распределение. Эта задача также называется ковариационный сдвиг между фичами в выборках

Несмотря на то, что это очевидный недостаток в данных, мы можем попробовать использовать его в свою пользу
- С помощью классификатора Adversarial Validation на train/ test для каждого объекта трен. выборки возьмем его вероятность принадлежности к тесту P(y=1)
- Далее будем использовать полученную вероятность как вес сэмпла при обучении модели
- Модель при обучении будет обращать больше внимания на примеры, схожие с тестовой выборкой

Такой метод заходит на Каггле, где наша цель - это заточиться под приватный лидерборд с долей тестовой выборки. В индустриальных проектах с такими финтами нужно быть осторожней, поскольку появляется риск переобучения, но в целом метод докидывает в модель
🔥5👍2
Как работает SSP?

# Part2

Итак, в прошлом посте о работе SSP мы остановились на отправке RTB запросов на DSP после их предварительной фильтрации.

▶️ Auction Resolution
Допустим, мы получили ответ от некоторых DSP, и теперь можем разрешить аукцион и выбрать победителя. Внутренний аукцион, как правило, первой цены, значит победитель платит свою ставку.

На этом же этапе происходят следующие вещи
- SSP создает xml файл VAST, в котором прописываются ставка, ссылка на креатив, его формат, и tracking ивенты (это более актуально для видео, где трекаются inview, start, midpoint, complete)
- Если SSP закупает инвентарь у паблишера напрямую, и цель рекламной кампании забидевшего рекламодателя CPM, т.е. branding показа, то мы минуем Prebid аукцион. И в этот же момент триггериться биллинг ивент, и SSP платит паблишеру.
- Также проверяем креатив на наличие ошибок error-vast перед тем, как его отправить паблишеру (например, формат креатива не соответствует заявленному на слоте, или ломаная ссылка в VAST)

Ниже приведен пример, как может выглядеть VAST файл

<VAST version="3.0">
<Ad id="20001" sequence="1">
<InLine>
<AdSystem version="1.0">Criteo</AdSystem>
<AdTitle>Adidas Video Ad</AdTitle>
<Description>VAST 3.0 compliant video ad</Description>
<Advertiser>Adidas</Advertiser>
<Pricing model="CPM" currency="USD">25.00</Pricing>
<Impression><![CDATA[https://criteo.com/impression]]></Impression>
<Creatives>
<Creative sequence="1" AdID="20001">
<Linear>
<Duration>00:00:30</Duration>
<TrackingEvents>
<Tracking event="complete"><![CDATA[https://sample-ssp.com/tracking/complete]]></Tracking>
</TrackingEvents>
<MediaFiles>
<MediaFile delivery="progressive" type="video/mp4" bitrate="500" width="640" height="360" scalable="true" maintainAspectRatio="true">
<![CDATA[https://sample-ssp.com/mediafile.mp4]]>
</MediaFile>
</MediaFiles>
</Linear>
</Creative>
</Creatives>
</InLine>
</Ad>
</VAST>



▶️ Header Bidding SSP Bid Response
В случае, если SSP бидит на Prebid, то она прокидывает полученную ранее ставку DSP с модификаторами и вычтенной маржой. Формулу ставки SSP можно представить в следующем виде


ssp_price = clearing_price * (1 - margin) * P(impression|auction_resolved) * bid_modifier


Если после применения модификаторов, ssp_price стала меньше флора, то бидится флор. bid_modifier подбирается таким образом, чтобы максимизировать маржу или взвешенную сумму маржи и выручки. По тому, как считается модификатор бида я рассказывал в посте про монетизацию


▶️ SSP Header Bidding Win
Если SSP победила в HB аукционе, то триггерится ивент ssp_hb_win. Prebid отсылает уведомление о победе, а SSP отправляет ему tag VAST с креативом. В этот момент SSP оплачивает инвентарь паблишера в размере своей ставки.


▶️ Impression
Собственно, сам ивент показа. Он триггерится в момент, когда пользователь доскролил до Ad слота и ему виден пиксель, заранее размещенный на слот. На показе DSP платит SSP clearing_price. Из этой цены аккумулируется средний CPM, который можно видеть в Yandex Direct или Google DV360 при отслеживании кампании

Также на моменте показа тригеррятся ML модели предсказывающие полноту показа (для видео) и клики для performance кампаний. В зависимости от цели кампании ее биллинг ивенты смещаются соответсвенно на complete или click
- Viewability: P(inview | impression)
- Compeltion: P(complete | impression)
- CTR: P(click | impression)

#adtech
🔥4👍2
▶️ Разбираем форматы рекламы на YouTube

In-Stream рекламные слоты YouTub'а, это отдельная эко-система форматов, которая почти всегда закупается через DV360 DSP Гугла. Сегодня разберем эти форматы, их назначение и эффективность.

Среди нашей аудитории есть ребята, работающие в AdOps, поэтому этот материал будет интересен для вас.

Заодно поэкспериментирую с новыми постами

Форматы In-Stream рекламы
- Trueview Skippable
- Trueview Unskippable
- Bumper
- Short
- In-Feed

Каждый адаптирован под разные KPI цели кампании CPM (показы + охват) или CPCV (полнота досмотров). Также можно закупать пакеты форматов


Video Reach Campaign = bumper + skippable + shorts + in-feed
Video Views Campaign = skippable + shorts + in-feed


На skippable формате удобно применять модификаторы ставки, которая выставляется в DV360, чтобы рулить скоростью расхода суточного бюджета кампании. На других форматах, заточенных больше на показы модификаторы также работают, но не так эффективно.
👍2🔥2
Немного инфографики. Подкапотное описание команд Docker для образов и контейнеров вдобавок к шпаргалке.

Сохраняем к себе!
👍5
ONNXRuntime для ускорения ML моделей ⚡️

Сегодня речь пойдет про формат ONNX. Он помогает портировать ML модели в стандартном формате на другие языки, например на JVM. Для запуска моделей в этом формате используется фреймворк ONNXRuntime. Кроме того ONNXRuntime позволяет ускорить инференс. Об этом мы сегодня и поговорим. В качестве примера возьмем модель на PyTorch и сравним скорость инференса до и после конвертация в ONNX.

Как работает ускорение?

В PyTorch обработка данных ленивая, т.е. команды сначала добавляются в очередь и потом из нее выполняются. Для выполнения всех запланированных вычислений нужен torch.cuda.synchronize(). Запустим torch модель на входном массиве (1,3,224,224) , запишем время инференса и оценим FPS. Также удалим, из результатов первые 20 запусков, которые как правило уходят на прогрев.


n_steps = 200
n_warmup_steps = 20
times = []
data = torch.ones((1,3,224,224), device="cuda")

torch.cuda.synchronize()

for step in range(nsteps):
start_inference = time.time()
result = model(data)
torch.cuda.synchronize()
end_inference = time.time()
times.append(end_inference - start_inference)
times = times[n_warmup_steps:]
print(np.mean(times), np.std(times))


PyTorch выдает 400 FPS. Этот результат получился в следствие того, что граф модели PyTorch - динамический, что ограничивает его скорость инференса. Теперь скастуем из динамического графа torch'а статический граф и запишем в формат ONNX


torch.onnx.export(
model,
torch.randn(1, 224, 224).to(device),
'mobilenet_v2.onnx',
input_names = ['input'],
output_names = ['output'],
)


Для того, чтобы подгрузить ONNX модель, нам нужно создать InferenceSession. Далее читаем модель и запускаем инференс на ONNXRuntime. Также засечем время инференса, чтобы проверить ускорение.


import onnxruntime as ort
import numpy as np

providers = [('CUDAExecutionProvider', {'device_id': 0})]
ort_sess = ort.InferenceSession("mobilenet_v2.onnx", providers=providers)

n_steps = 200
n_warmup_steps = 20
times = []
image_as_numpy = np.ones((1,3,224,224))

for step in range(n_steps):
start_inference = time.time()
outputs = ort_sess.run(None, {'input': image_as_numpy})
end_inference = time.time()
times.append(end_inference - start_inference)

times = times[n_warmup_steps:]
print(np.mean(times), np.std(times))


ONNXRuntime выдает 630 FPS, т.е. мы получаем прирост скорости инференса в полтора раза. Здесь запуск проводился на CUDA, но ONNX также поддерживает и запуски на CPU
👍4🔥2
Мы собрали папку тг каналов про AdTech

Что вы здесь найдете
- Авторские мнения, дайджесты новостей: Сookie, Connected TV, Direct Sold контракты в обход SSP и многое другое
- Инженерная часть: как технически устроены SSP/DSP, как работает Prebid, как применять ML модели в программатике
- Монетизация: какими метриками измерять, как влиять на ставки в Header Bidding, настройки форматов в рекламной сети Яндекса
- Инфографика, разбор отчетности крупных игроков, и что происходит в мире AI-based стартапов в рекламе и ecomm
- Sales в маркетинге и рекламе, как обрабатывать лиды и закрывать сделки

В общем, подборка закрывает примерно весь спектр задач по рекламе. Каждый, интересующийся темой, сможет найти для себя полезное
3🔥2👍1
Ранее я уже писал про функционал Optun'ы, что ее можно использовать, как для оптимизации параметров модели, так и для препроцессинга

Сегодня обсудим прунинг экспериментов с Optuna. Прунинг здесь - это прерывание эксперимента, по какой-либо метрике, когда она уже вышла на плато и перестала значимо менятсья. Т.е. если мы поставили CatBoost модель обучаться на 500 шагов и видим, что после 50 шагов лучший скор уже получен и его не превзойти, то логично обучение остановить и тестировать следующую итерацию параметров

Какие Pruner'ы есть в Оптуне?
- MedianPruner: останавливает испытание, если скор ниже медианы скоров с предыдущих шагов
- PercentilePruner: останавливает испытание, если скор находится в нижних персентилях с предыдущих шагов
- SuccessiveHalvingPruner: прунер на основе многоруких бандитов. Помогает не только во время остановить обучение, но и выбрать лучшую комбинацию гиперпараметров
- ThresholdPruner: останавливает испытание по пороговому значению

Лучший вариант для классических моделей SuccessiveHalvingPruner. Здесь пример, как его можно реализовать

X, y = load_iris(return_X_y=True)
X_train, X_valid, y_train, y_valid = train_test_split(X, y)
classes = np.unique(y)


def objective(trial):
alpha = trial.suggest_float("alpha", 0.0, 1.0)
clf = SGDClassifier(alpha=alpha)
n_train_iter = 100

for step in range(n_train_iter):
clf.partial_fit(X_train, y_train, classes=classes)

intermediate_value = clf.score(X_valid, y_valid)
trial.report(intermediate_value, step)

if trial.should_prune():
raise optuna.TrialPruned()

return clf.score(X_valid, y_valid)


study = optuna.create_study(
direction="maximize", pruner=optuna.pruners.SuccessiveHalvingPruner()
)
study.optimize(objective, n_trials=20)
👍8🔥31
Сегодня у нас минутка новостей

Программатик платформа Outbrain покупает Teads за $1B. Как заявлено в официальном пресс релизе это поможет создать единую площадку, покрывающую все рекламные форматы, основанную на ИИ и ведущих решениях для видео и брендинга

▶️ Что я про это думаю?
Мотивация, зачем для Outbrain нужен Teads, вполне понятна
- Основная выручка Outbrain - это perf кампании на клик. Они монетизируются как правило на низкокачественных Made For Advertsing сайтах, которые скорее заточены под арбитраж. Поскольку Teads обладает пулом премиум паблишеров, то интеграция с ними поможет дистанцировать Outbrain от MFA в глазах рекламодателей
- Outbrain нужен доступ к более дорогому CTV инвентарю. Этот инвентарь можно покупать для CPM кампаний и таким образом повышать охват. Также настройка интеграций Connected TV технически сложна, и вместо того, чтобы строить ее с нуля, проще купить готовую платформу

В Teads изменения также напрашивались уже давно.
- Этому предшествовала попытка заявка на IPO для выхода на биржу в 2021, которая была отозвана группой Altice, в которую входит Teads
- Манипуляции с делением и закрытием направлений, постепенный сдвиг приоритета на Teads Ad Manager (TAM, ad server, аналог Google Ad Manager) и отказ от новых Deal ID контрактов с внешними DSP

▶️ Как покупка повлияет на команды и сервисы?
Поскольку данная покупка - это не столько поглощение крупной компанией более мелкой, а скорее слияние двух компаний одинакового размера, то предстоит сложный процесс интеграции команд друг с другом. Если на уровне директоров все уже решено, то многим менеджерам среднего звена и лидам команд придется потесниться. Это может вызвать терки и напряженности на первых порах

В плане команд, которых изменения коснуться в первую очередь, скорее всего, это будут Performance и Teads Ad Manager. Поскольку Outbrain специализируется на perf трафике (закупкам по кликам CPC), то они будут навязывать в первую очередь свои практики

Касательно Teads SSP, где мне довелось поработать, то считаю, что изменения организации коснуться платформы в меньшей степени по двум причинам.
- Во-первых, это критическая инфраструктура, без которой просто нарушится цепочка покупки инвентаря и поставки рекламы
- Во-вторых, Outbrain нацелена в первую очередь на CTV инвентарь закупаемый по CPM для branding кампаний. А это именно то, что реализовано в Teads SSP с интеграциями с Publica, FreeWheel и Spring-Serve

Как будут развиваться события, будем мониторить и держать руку на пульсе
👍5
Ранее я уже рассказывал о формате ONNX и о том, как его использовать для ускорения моделей на предсказании. Сегодня речь пойдет про портирование питонячих моделей на Java. Из своей практики Real Time Bidding платформы (SSP и DSP), как правило, реализованы на языках под JVM и стандартные ML фреймворки (кроме разве что Apache Spark'а) становятся недоступными. Выхода здесь два

- либо пробовать делать рукописные модели сразу на Java
- прибегать к конвертации в форматы совместимые с JVM

О том, как портировать Sklearn модель на Java, и пойдет речь в статье, которую я подготовил

Буду рад вашим реакциям и фидбеку 🔥
🔥8👍1
👍1
Продолжаем тему портирования и оптимизации ML моделей на проде. Сегодня речь пойдет про TensorRT

TensorRT — это фреймворк от Nvidia, который позволяет учитывать нюансы аппаратного устройства вычислителей. В нём модель оптимизируется перед запуском таким образом, чтобы для вычисления каждой операции использовались самые быстрые алгоритмы на конкретном железе с определённым количеством свободной памяти.

Чтобы отправить модель в TensorRT, ее сперва нужно конвертировать в ONNX (про ONNX я уже писал в постах раз, два).

TensorRT поддерживает и динамическое построение модели через создание NetworkDefinition. Также у ONNX моделей на TensorRT есть преимущества

- Во-первых, это применение оптимизаций из onnx-simplifier или onnx-graphsurgeon. Если мы портируем модель на PyTorch, то он конвертирует модель в ONNX операция за операцией, а последний распознает их паттерны, заменяют на более простые аналоги, не нарушая семантику вычислительного графа.

- Во-вторых, при оптимизации модели TensorRT заменяет операции в ONNX на соответствующие CUDA-ядра. Чаще всего более мелкие операции сплавляются между собой, а ветки несколько параллельных веток заменяются на одну.

- В-третьих, доступно квантование, т.е. при оптимизации можно изменить тип данных, используемый для вычислений. Стандарт здесь — применение FP16 вместо обычного FP32.
🔥3👍1
Минутка новостей про Connected TV

Объем рекламного трафика CTV нехило растет. Также растут и бюджеты рекламодателей.

Почему так?
На CTV, как правило, attention метрики креативах выше (не путать с attention'ом в сеточках в DL), чем на аналогичных показах в inStream в вэбе или inApp, соответсвенно выше и viewability и досмотры. Также в CTV есть такое понятие, как co-viewing, когда одну и ту же рекламы смотрят сразу несколько человек, поскольку телик смотрят обычно вечером всей семьей.

По third-party cookie, здесь у CTV преимущество, поскольку UserAgent данные о пользователе можно получать даже не из кук, а через API самих девайсов, например, Samsung Tizen или LG webOS API.

В плане монетизации CTV инвентарь как правило более дороже, чем Web, поскольку на паблишеров порог входа выше (создать ТВ канал сложнее, чем создать сайт). По этой же причине на ТВ меньше проблем с Brand Safety.

В общем будем наблюдать, но в этот и следующий год мы точно увидим значительный рост CTV интеграций

source link
🔥2👍1