Русский
Русский
English
Статистика
Реклама

Причинно-следственные связи

Анализируем причинно-следственные связи метрик ВКонтакте

11.09.2020 14:12:59 | Автор: admin
Всем привет, меня зовут Анвер, я работаю в команде Core ML ВКонтакте. Одна из наших задач создавать и улучшать алгоритмы ранжирования для ленты новостей. В этой статье расскажу о том, как можно применять для этого причинно-следственный анализ чтобы в результате сделать сервис интереснее для пользователей. Поговорим про преимущества такого подхода по сравнению с корреляционным анализом, и я предложу модификации существующих алгоритмов.




Что такое короткие и долгие метрики?


Модели ранжирования пытаются оценить вероятность того, что пользователь повзаимодействует с новостью (постом): задержит на ней внимание, поставит отметку Нравится, напишет комментарий. Затем модель распределяет записи по убыванию этой вероятности. Поэтому, улучшая ранжирование, мы можем получить рост CTR (click-through rate) пользовательских действий: лайков, комментов и других. Эти метрики очень чувствительны к изменениям модели ранжирования. Я буду называть их короткими.

Но есть и другой тип метрик. Считается, например, что время, проведённое в приложении, или количество сессий пользователя намного лучше отражают его отношение к сервису. Будем называть такие метрики долгими.

Оптимизировать долгие метрики непосредственно через алгоритмы ранжирования нетривиальная задача. С короткими метриками это делать намного проще: CTR лайков, например, напрямую связан с тем, насколько хорошо мы оцениваем их вероятность. Но если мы знаем причинно-следственные (или каузальные) связи между короткими и долгими метриками, то можем сфокусироваться на оптимизации лишь тех коротких метрик, которые должны предсказуемо влиять на долгие. Я попытался извлечь такие каузальные связи и написал об этом в своей работе, которую выполнил в качестве диплома на бакалавриате ИТМО (КТ). Исследование мы проводили в лаборатории Машинное обучение ИТМО совместно с ВКонтакте.

Ссылки на код, датасет и песочницу


Весь код вы можете найти здесь: AnverK.

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

В песочнице можно посмотреть, как пользоваться предложенной обёрткой: на синтетических данных.
А здесь как применять алгоритмы к датасету: на предложенном датасете.

Боремся с ложными корреляциями


Может показаться, что для решения нашей задачи достаточно посчитать корреляции между метриками. Но это не совсем так: корреляция это не всегда причинно-следственная связь. Допустим, мы измеряем всего четыре метрики и их причинно-следственные связи выглядят так:


Не умаляя общности, предположим, что в направлении стрелки идёт положительное влияние: чем больше лайков, тем больше SPU. В таком случае можно будет установить, что комментарии к фото положительно влияют на SPU. И решить, что если наращивать эту метрику, увеличится SPU. Такое явление называют ложной корреляцией: коэффициент корреляции достаточно высокий, но причинно-следственной связи нет. Ложная корреляция проявляется не только у двух следствий одной причины. Из этого же графа можно было бы сделать неверный вывод и о том, что лайки положительно влияют на количество открытий фото.

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

Классические алгоритмы вывода связей


Мы рассматривали несколько методов вывода связей (causal inference): PC (Peter and Clark), FCI (Fast Causal Inference) и FCI+ (похож на FCI с теоретической точки зрения, но намного быстрее). Почитать о них подробно можно в этих источниках:

  • Causality (J. Pearl, 2009),
  • Causation, Prediction and Search (P. Spirtes et al., 2000),
  • Learning Sparse Causal Models is not NP-hard (T. Claassen et al., 2013).

Но важно понимать: первый метод (PC) предполагает, что мы наблюдаем все величины, влияющие на две метрики или более, такая гипотеза называется Causal Sufficiency. Другие два алгоритма учитывают, что могут существовать ненаблюдаемые факторы, которые влияют на отслеживаемые метрики. То есть во втором случае каузальное представление считается более естественным и допускает наличие ненаблюдаемых факторов $U_1, \dots U_k$:



Все реализации этих алгоритмов представлены в библиотеке pcalg. Она прекрасная и гибкая, но с одним недостатком написана на R (при разработке самых вычислительно тяжёлых функций используется пакет RCPP). Поэтому для перечисленных выше методов я написал обёртки в классе CausalGraphBuilder, добавив примеры его использования.

Опишу контракты функции вывода связей, то есть интерфейс и результат, который можно получить на выходе. Можно передать функцию тестирования на условную независимость. Это такой тест, который возвращает $p_{value}$ при нулевой гипотезе, что величины $X$ и $Y$ условно независимы при известном множестве величин $Z$. По умолчанию используется тест, основанный на частной корреляции. Я выбрал функцию с этим тестом, потому что она используется по умолчанию в pcalg и реализована на RCPP это делает её быстрой на практике. Также можно передать $p_{value}$, начиная с которого вершины будут считаться зависимыми. Для алгоритмов PC и FCI также можно задать количество CPU-ядер, если не нужно писать лог работы библиотеки. Для FCI+ такой опции нет, но я рекомендую использовать именно этот алгоритм он выигрывает по скорости. Ещё нюанс: FCI+ на данный момент не поддерживает предложенный алгоритм ориентации рёбер дело в ограничениях библиотеки pcalg.

По итогам работы всех алгоритмов строится PAG (partial ancestral graph) в виде списка рёбер. При алгоритме PC его стоит интерпретировать как каузальный граф в классическом понимании (или байесовскую сеть): ребро, ориентированное из $A$ в $B$, означает влияние $A$ на $B$. Если ребро ненаправленное или двунаправленное, то мы не можем однозначно его ориентировать, а значит:

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

Результатом работы FCI-алгоритмов будет тоже PAG, но в нём появится новый тип рёбер с о на конце. Это означает, что стрелка там может как быть, так и отсутствовать. При этом важнейшее отличие FCI-алгоритмов от PC в том, что двунаправленное (с двумя стрелками) ребро даёт понять, что связываемые им вершины следствия некой ненаблюдаемой вершины. Соответственно, двойное ребро в PC-алгоритме теперь выглядит как ребро с двумя о на концах. Иллюстрация для такого случая есть в песочнице с синтетическими примерами.

Модифицируем алгоритм ориентации рёбер


У классических методов есть один существенный недостаток. Они допускают, что могут быть неизвестные факторы, но при этом опираются на ещё одно слишком серьёзное предположение. Его суть в том, что функция тестирования на условную независимость должна быть идеальной. Иначе алгоритм за себя не отвечает и не гарантирует ни корректность, ни полноту графа (то, что больше рёбер сориентировать нельзя, не нарушая корректность). Много ли вы знаете идеальных тестов на условную независимость при конечной выборке? Я нет.

Несмотря на этот недостаток, скелеты графов строятся довольно убедительно, но ориентируются слишком агрессивно. Поэтому я предложил модификацию к алгоритму ориентации рёбер. Бонус: она позволяет неявным образом регулировать количество ориентированных рёбер. Чтобы понятно объяснить её суть, пришлось бы подробно говорить здесь о самих алгоритмах вывода каузальных связей. Поэтому теорию по этому алгоритму и предложенной модификации я приложу отдельно ссылка на материал будет в конце поста.

Сравниваем модели 1: оценка правдоподобия графа


Одну из серьёзных трудностей при выводе каузальных связей представляет, как ни странно, сравнение и оценка моделей. Как так вышло? Дело в том, что обычно истинное каузальное представление реальных данных неизвестно. И тем более мы не можем знать его с точки зрения распределения настолько точно, чтобы генерировать из него реальные данные. То есть неизвестен ground truth для большинства наборов данных. Поэтому возникает дилемма: использовать (полу-) синтетические данные с известным ground truth или пытаться обходиться без ground truth, но тестировать на реальных данных. В своей работе я попробовал реализовать два подхода к тестированию.

Первый из них оценка правдоподобия графа:



Здесь $PA_G(X)$ множество родителей вершины $X$, $I(X, Y)$ совместная информация величин $X$ и $Y$, а $H(X)$ энтропия величины $X$. На самом деле второе слагаемое не зависит от структуры графа, поэтому считают, как правило, только первое. Но можно заметить, что правдоподобие не убывает от добавления новых рёбер это необходимо учитывать при сравнении.

Важно понимать, что такая оценка работает только для сравнения байесовских сетей (выхода алгоритма PC), потому что в настоящих PAG (выход алгоритмов FCI, FCI+) у двойных рёбер совсем иная семантика.

Поэтому я сравнил ориентацию рёбер моим алгоритмом и классическим PC:



Модифицированная ориентация рёбер позволила значительно увеличить правдоподобие по сравнению с классическим алгоритмом. Но теперь важно сравнить количество рёбер:



Их стало даже меньше это ожидаемо. Так что даже с меньшим числом рёбер удаётся восстанавливать более правдоподобную структуру графа! Здесь вы можете возразить, что правдоподобие не убывает с увеличением количества рёбер. Дело в том, что полученный граф в общем случае это не подграф графа, полученного классическим PC-алгоритмом. Двойные рёбра могут появиться вместо одиночных, а одиночные изменить направление. Так что никакого рукомашества!

Сравниваем модели 2: используем подход из классификации


Перейдём ко второму способу сравнения. Будем строить PC-алгоритмом каузальный граф и выбирать из него случайный ациклический граф. После этого сгенерируем данные в каждой вершине как линейную комбинацию значений в родительских вершинах с коэффициентами $\pm[0,2, 0,8]$ с добавлением гауссова шума. Идею для такой генерации я взял из статьи Towards Robust and Versatile Causal Discovery for Business Applications (Borboudakis et al., 2016). Вершины, которые не имеют родителей, генерировались из нормального распределения с параметрами, как в наборе данных для соответствующей вершины.

Когда данные получены, применяем к ним алгоритмы, которые хотим оценить. При этом у нас уже есть истинный каузальный граф. Осталось только понять, как сравнивать полученные графы с истинным. В Robust reconstruction of causal graphical models based on conditional 2-point and 3-point information (Affeldt et al., 2015) предложили использовать терминологию классификации. Будем считать, что проведённое ребро это Positive-класс, а непроведённое Negative. Тогда True Positive ($TP$) это когда мы провели то же ребро, что и в истинном каузальном графе, а False Positive ($FP$) если провели ребро, которого в истинном каузальном графе нет. Оценивать эти величины будем с точки зрения скелета.

Чтобы учитывать направления, введём $TP_{misorient}$ для рёбер, которые выведены верно, но с неправильно выбранным направлением. После этого будем считать так:

  • $TP' = TP - TP_{misorient}$
  • $FP' = FP + TP_{misorient}$

Затем можно считать $F_1$-меру как для скелета, так и с учётом ориентации (очевидно, в этом случае она будет не выше такой меры для скелета). Однако в случае PC-алгоритма двойное ребро добавляет к $TP_{misorient}$ только $0.5$, а не $1$, потому что одно из реальных рёбер всё-таки выведено (без Causal Sufficiency это было бы неверно).

Наконец, сравним алгоритмы:



Первые два графика это сравнение скелетов PC-алгоритма: классического и с новой ориентацией рёбер. Они нужны, чтобы показывать верхнюю границу $F_1$-меры. Вторые два сравнение этих алгоритмов с учётом ориентации. Как видим, выигрыша нет.

Сравниваем модели 3: выключаем Causal Sufficiency


Теперь закроем некоторые переменные в истинном графе и в синтетических данных после генерации. Так мы выключим Causal Sufficiency. Но сравнивать результаты надо будет уже не с истинным графом, а с полученным следующим образом:

  • рёбра от родителей скрытой вершины будем проводить к её детям,
  • всех детей скрытой вершины соединим двойным ребром.

Сравнивать уже будем алгоритмы FCI+ (с модифицированной ориентацией рёбер и с классической):



И теперь, когда Causal Sufficiency не выполняется, результат новой ориентации становится значительно лучше.

Появилось ещё одно важное наблюдение алгоритмы PC и FCI строят на практике почти одинаковые скелеты. Поэтому я сравнил их выход с той ориентацией рёбер, которую предложил в своей работе.



Получилось, что алгоритмы практически не отличаются по качеству. При этом PC шаг алгоритма построения скелета внутри FCI. Таким образом, использование алгоритма PC с ориентацией, как в FCI-алгоритме, хорошее решение, чтобы увеличить скорость вывода связей.

Вывод


Сформулирую кратко, о чём мы поговорили в этой статье:

  1. Как задача вывода каузальных связей может возникнуть в крупной IT-компании.
  2. Что такое ложные корреляции и как они могут мешать Feature Selection.
  3. Какие алгоритмы вывода связей существуют и используются наиболее часто.
  4. Какие трудности могут возникать при выводе каузальных графов.
  5. Что такое сравнение каузальных графов и как с этим бороться.


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

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru