Оценка CTR интернет-рекламы

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

Оценка CTR - это проблема бинарной классификации. Когда пользователь просматривает рекламу, он либо нажимает (y=1), либо не нажимает (y=0). Имея только два возможных результата, мы используем логистическую регрессию в качестве нашей модели. Логистическая регрессия применяется для оценки любого количества дискретных классов в отличие от линейной регрессии, которая используется для вывода непрерывных переменных. Я привел простую визуализацию, которая дает правильную модель для трех основных проблем Data Science:

В этой истории я хочу сначала познакомить вас с техническими деталями логистической регрессии, а затем применить все, что вы узнали, к задаче «Прогнозирование рейтинга кликов» в Kaggle¹.

Бинарная логистическая регрессия: теория

Логистическая регрессия характеризуется логистической функцией для моделирования условной вероятности метки Y переменных X

В нашем случае Y принимает состояние, по которому щелкнули или не щелкнули, а X будет наблюдаемым из функций, которые мы хотим выбрать (например, тип устройства).

Мы будем работать с m наблюдениями, каждое из которых содержит n функций. Для каждого из них у нас будет m векторов-строк xᵢ размерности n + 1. Наши метки Y могут быть только нулем или единицей. Параметры будут заданы в векторе-столбце Θ размерности n + 1.

Условная вероятность того, что пользователь щелкнет по данному наблюдению X, затем может быть смоделирована как функция сигмоида.

Ядром логистической регрессии является сигмовидная функция. Сигмоидальная функция отображает непрерывную переменную в замкнутое множество [0, 1], которое затем можно интерпретировать как вероятность. Каждая точка данных в правой части интерпретируется как y=1, а каждая точка данных в левой части интерпретируется как y=0.

Вывод (необязательно)

Сигмовидная функция появляется естественным образом при выводе условной вероятности. Мы можем выразить P (Y | X) с помощью теоремы Байеса

Из байесовской интерпретации мы имеем

  • P (Y | X) как задний,
  • P (Y) как предыдущий,
  • и P (X) как коэффициент нормализации.

Мы подгоним апостериорное и апостериорное к нашим данным и должны избавиться от неизвестной вероятности P (X). Это можно сделать, используя условную вероятность дополнения.

При делении апостериорной вероятности на условную вероятность дополнения и логарифмировании мы получаем логарифм-шансы (логит)

Здесь мы предположили, что логит является линейной функцией от X! Теперь нам просто нужно отменить логарифм и решить апостериорную функцию, чтобы получить сигмовидную функцию.

Оценка максимального правдоподобия

До сих пор мы моделировали апостериор с набором параметров Θ. Как определить лучший выбор Θ? Условная вероятность того, что пользователь щелкнет, равна сигмовидной функции. Сумма вероятностей всех случаев должна составлять единицу. Поскольку у нас всего два случая, мы можем найти элегантный способ выразить обе вероятности в одном выражении:

Правая часть называется функцией массы вероятности (PMF) распределения Бернулли. Распределение Бернулли описывает случайную переменную, которая может иметь один из двух результатов, например, щелкнули или не нажали наши ярлыки. Теперь, чтобы определить наши параметры Θ нам нужно максимизировать вероятность воспроизведения распределения нашей популяции, пока нам будет предоставлена ​​только выборка. Этот метод называется оценкой максимального правдоподобия (MLE). Мы принципиально объединяем все вероятности каждого отдельного события в нашей выборке. Эта совместная вероятность называется правдоподобием, которая имеет много общего с вероятностью, но сосредоточена на параметрах

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

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

Производная сигмовидной функции (необязательно)

В последнем результате мы использовали производную по сигмоидной функции. Вывод выглядит следующим образом

Ньютон-Рафсон

Чтобы выполнить MLE, мы должны найти корень первой производной логарифмической вероятности. Мы можем использовать алгоритм поиска корней Ньютона-Рафсона³ для этой задачи. Ньютон-Рафсон - стандартный метод максимизации логарифмической вероятности. Требуется вычислить вторую производную. В нашем случае мы можем определить это аналитически. В других случаях, когда вторая производная требует больших вычислительных ресурсов, мы могли бы использовать для оптимизации градиентный спуск (подъем). Вторая производная дается формулой

а затем метод Ньютона-Рафсона сообщает нам, как обновлять параметры для каждой итерации.

Оценка CTR

Во второй части этой истории мы хотим написать код нашей собственной реализации логистической регрессии. Созданный мной блокнот Jupyter был опубликован под названием Gist. Мы будем работать с данными конкурса Kaggle Прогнозирование рейтинга кликов. После загрузки данных мы распаковываем их и готовим выборку из 10000 строк перед обучением на полном наборе.

unzip avazu-ctr-prediction.zip
gunzip train.gz
head -n10000 train > train_sample.csv

Затем мы загружаем CSV во фрейм данных panda и разделяем его на обучающий и тестовый набор.

df = pd.read_csv('train_sample.csv')
msk = np.random.rand(len(df)) < 0.8
train = df[msk]
test = df[~msk]

Теперь вам следует сосредоточиться на исследовании функций, но для простоты я выбрал столбцы device_type, C1, C15 и C16 в качестве столбцов функций. Затем я могу подготовить свою матрицу характеристик X и использовать столбец щелкнуть в качестве метки.

m = len(train)
X_train = np.ones((m, 5))
X_train[:,1] = train.device_type.to_numpy()
X_train[:,2] = train.C1.to_numpy()
X_train[:,3] = train.C15.to_numpy()
X_train[:,4] = train.C16.to_numpy()
y_train = train.click.to_numpy()

Чтобы наш алгоритм работал, нам нужны ранее полученные первая и вторая производные логарифма правдоподобия, которые можно закодировать следующим образом

def DLogLikelihood(X, y, theta):
    res = np.zeros(theta.shape[0])
    for i in range(0, X.shape[0]):
        x_i = X[i]
        y_i = y[i]
        res += x_i * (y_i - sigmoid(np.dot(theta, x_i)) )
    return res
def DDLogLikelihood(X, theta):
    res = np.zeros((theta.shape[0], theta.shape[0]))
    for i in range(0, X.shape[0]):
        x_i = X[i]
        sigma = sigmoid(np.dot(theta, x_i))
        res += np.outer(x_i, x_i) * sigma * ( 1 - sigma ) 
    return -res

Затем выполняются итерационные шаги Нетвона-Рафона и наш алгоритм логистической регрессии.

def NewtonRaphsonTheta(X, y, theta):
    return theta - np.dot(
        np.linalg.inv(DDLogLikelihood(X, theta)),
        DLogLikelihood(X, y, theta))
def logisticRegression(X, y, epochs=100):
    theta = np.zeros(X.shape[1])
    for i in range(epochs):
        theta = NewtonRaphsonTheta(X, y, theta)
    return theta

Вызывая logisticRegression(X, y), мы итеративно вычислим параметры Θ, которые затем можно использовать для прогнозирования вероятности клика пользователя.

def predict(X, theta):
    res = np.zeros(X.shape[0])
    for i in range(len(res)):
        x = X[i]
        res[i] = sigmoid(np.dot(theta, x))
    return res

Для тестового прогона мы получаем следующие вероятности

theta = logisticRegression(X_train, y_train, epochs=100)
y_pred = predict(X_test, theta)
print(y_pred)
[0.18827126 0.16229901 … 0.16229901 0.16229901 0.16229901]

Чтобы оценить модель, я сравнил прогнозы из набора тестов с их фактическим значением, которое показало, что модель довольно плохая. Для улучшения мы могли бы потратить больше времени на выбор функций и обучение на большем количестве данных, при этом постоянно измеряя производительность модели с помощью таких оценочных показателей, как логарифмические потери или ROC кривая.

Резюме

  • Логистическая регрессия используется в задачах множественной классификации
  • Бинарная логистическая регрессия используется, если у нас всего два класса
  • P (Y | X) моделируется сигмоидной функцией, которая отображает из (-∞, ∞) в (0, 1)
  • Мы предположили, что логит можно моделировать как линейную функцию
  • Чтобы оценить параметры Θ, мы максимизируем логарифмическое правдоподобие
  • Распределение Бернулли - это дискретное распределение, имеющее два возможных результата, которое используется в бинарной классификации.
  • Мы используем Ньютона-Рафсона в качестве средства поиска корней, потому что мы можем легко вычислить вторую производную логарифмической вероятности

[1]: Kaggle, прогнозирование рейтинга кликов https://www.kaggle.com/c/avazu-ctr-prediction

[2]: Элементы статистического обучения, Т. Хасти, Р. Тибширани, Дж. Фридман https://web.stanford.edu/~hastie/ElemStatLearn/

[3]: Метод Ньютона-Рафсона https://en.wikipedia.org/wiki/Newton%27s_method