Рубрики
Без рубрики

Анализ скорости клика с помощью Spark

В последние годы программная реклама захватывает индустрию онлайн-рекламы. Чтобы включить автоматическую продажу и покупку показов объявлений между рекламодателями и издателями…

Автор оригинала: Ayush Pandey.

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

В отличие от традиционного рынка онлайн-рекламы, где определенное количество показов продается по фиксированной ставке, RTB позволяет рекламодателям делать ставки на каждый показ индивидуально в режиме реального времени по стоимости, основанной на функциях уровня показов. Торги в режиме реального времени (RTB)-это способ проведения транзакций с медиа, который позволяет выставлять отдельные показы объявлений на торги в режиме реального времени. Это делается с помощью программного аукциона на месте , который аналогичен тому, как работают финансовые рынки. RTB позволяет использовать адресную рекламу; возможность показывать рекламу потребителям непосредственно на основе их демографических, психографических или поведенческих характеристик.

Многие DSP (Платформы со стороны спроса) выступают в качестве агентов для рекламодателей и принимают участие в аукционе в режиме реального времени от их имени. Для того, чтобы обеспечить ставки в режиме реального времени и предоставить рекламодателям клики по самой низкой цене, DSP разрабатывают свои собственные алгоритмы машинного обучения, используя такие методы, как трюк хеширования , комбинации функций, стохастический градиентный спуск и т.д.

Мотивация

Как и стандартная практика в большинстве случаев использования науки о данных, всякий раз, когда разрабатывается новый алгоритм, они подвергаются A/B-тестированию против уже существующего алгоритма в производстве (по крайней мере, в течение нескольких дней), чтобы определить, какой алгоритм лучше соответствует бизнес-метрикам.

Из-за огромного объема запросов на участие в торгах (около миллиона запросов на участие в торгах в секунду) объем данных, собранных во время AB, составляет порядка 100 Гб. Библиотека Python Pandas обладает практически всеми функциями, необходимыми для автономного анализа собранных данных с точки зрения CPC, расходов, кликов, CTR, AUC и т. Д.

Но у Pandas есть огромная проблема, она должна загрузить весь набор данных в память, чтобы выполнить на нем некоторые вычисления. По моему опыту, Pandas требует, чтобы размер оперативной памяти был в 3 раза больше размера набора данных , и он не может быть запущен в распределенную среду в качестве кластера машин a. Именно здесь Apache Spark полезен, поскольку он может обрабатывать наборы данных, размер которых превышает размер оперативной памяти. Этот блог не будет охватывать внутренние компоненты Apache Spark и то, как он работает, скорее я перейду к тому, как код анализа CTR Pandas может быть легко преобразован в анализ spark с небольшими изменениями синтаксиса.

Миграция в Искру от панд

В новых версиях Spark начал поддерживать фреймы данных, которые концептуально эквивалентны фрейму данных в R/Python. Поддержка фреймов данных в Spark позволила пользователям сравнительно легко переключаться на Spark из Pandas, используя очень похожий синтаксис. В этом разделе я бы перешел к кодированию и показал, как анализ CTR, выполняемый в Pandas, может быть перенесен в Spark.

Прежде чем я перейду к кодированию, я хотел бы представить некоторые ключевые слова, используемые в коде:

Эффективная цена за клик : Общее количество потраченных денег/Общее количество кликов

Метка : это либо 0, либо 1 (1 означает, что щелчок произошел, а 0 означает отсутствие щелчка)

Цена выигрыша : Цена, уплаченная за победу на аукционе на месте

Bid CPC : Цена, которую рекламодатель готов заплатить за показ

CTR : Количество кликов/Общее количество показов

Чем цена выигрыша отличается от цены предложения?

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

Настройка записной книжки и импорт библиотек

Панды
import pandas as pd
Искра
import os
import sys
os.environ['SPARK_HOME'] = "/home/spark-2.3.2-bin-hadoop2.7"
os.environ['JAVA_HOME'] = "/home/jdk1.8.0_181"
spark_home = os.environ.get("SPARK_HOME")
sys.path.insert(0, spark_home + "/python")
sys.path.insert(0, os.path.join(spark_home, "python/lib/py4j-0.10.7-src.zip")) 

from pyspark import SparkContext
from pyspark.conf import SparkConf
CLUSTER_URL = "spark://address:7077"
conf = SparkConf()
conf.setMaster(CLUSTER_URL).setAppName("CTR Analysis").set("spark.executor.memory", "120g")
sc = SparkContext(conf=conf)
print(sc.version)

Чтение CSV-файла

Панды
df = pd.read_csv(data_file_path, names=cols, error_bad_lines=False, warn_bad_lines=True, sep=',')
Искра
from pyspark.sql.types import StructType, StructField
from pyspark.sql.types import DoubleType, IntegerType, StringType
file_location = "hdfs://address:port/hadoop/dataNode/pyspark/data.csv"
df = spark.read.csv(file_location, header=False, schema=schema, sep=",")
# df = spark.read.csv(file_location, header=False, inferSchema=True, sep=",")
# df.cache()

Очистка данных

Панды
numeric_cols = ['label','win_price','ctr','bid_cpc']
df[numeric_cols] = df[numeric_cols].convert_objects(convert_numeric=True)
df.dropna(inplace=True, subset=numeric_cols)
Искра
numeric_cols = ['label','win_price','ctr','bid_cpc']
df = df.dropna(subset=numeric_cols)

Расчет Расходов, CTR, CPC На Algo

Панды
data = df.groupby(['algo']).agg({'win_price': np.sum, c_label:{'clicks':np.sum, 'wins':'count'}}).reset_index()
data[('win_price','sum')] = data[('win_price','sum')] / 1000.

data['ecpc'] = data[('win_price','sum')] / data[('label,'clicks')]
data = pd.DataFrame(data.to_records())
data.columns = ['', algo, 'spend', 'number of impressions', 'number of clicks', 'effective cpc']
Искра
from pyspark.sql.functions import udf
import pyspark.sql.functions as f 
def divide_by_1000(x): 
  return x/1000.0 
    
udf divide_by_1000 = udf(divide_by_1000, DoubleType()) 
data_wins = df.groupby(['algo']).agg( {'win_price': 'sum', 'label: 'count'})

data_clicks = df.groupby(['algo']).agg({'label: 'sum'})
# print data_wins.columns
# print data_clicks.columns
# Rename the columns
data_wins = data_wins.withColumnRenamed("sum(win_price)","win_price").withColumnRenamed("count(label)", "wins")

# print data_wins.schema
# data_wins['win_price'] = data_wins.win_price/1000.
data_wins = (data_wins.withColumn("win_price",udf divide_by_1000("win_price")))

data_clicks = data_clicks.withColumnRenamed("sum(label)", "clicks")
# print data_wins.columns
# print data_clicks.columns
data = data_wins.join(data\_clicks, on = 'algo', how='inner')
data = (data.withColumn("effective cpc", f.col("win_price")/100))