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

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

Одним из решений, разработанных в Feedzai, был движок OpenML. Это решение позволяет интегрировать модели машинного обучения, созданные вне нашей платформы. Таким образом, вам не нужно начинать с нуля при переходе на нашу платформу. Вместо этого вы можете продолжить работу с моделями, которые вы создали на других платформах, например в H2O.

Почему именно H2O?

H2O - платформа машинного обучения и искусственного интеллекта с открытым исходным кодом, популярная среди специалистов по данным.

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

Провайдер H2O OpenML

OpenML Engine был разработан для поддержки двух типов провайдеров.

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

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

  • Обычные старые объекты Java (POJO) - поддерживаются практически всеми моделями H2O. POJO - это файлы / классы java, которые должен компилировать провайдер при загрузке. Он не поддерживает исходные файлы размером более 1 ГБ.
  • Оптимизированный объект модели (MOJO) - это альтернатива H2O POJO, она поддерживается большинством моделей классификаторов и проста в использовании. У него нет ограничений по размеру. Модели MOJO меньше на диске и быстрее во время скоринга по сравнению с моделями POJO.

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

Если вы предпочитаете обучать новую модель прямо с платформы, вы можете использовать тот же процесс, что и для обучения собственных моделей Feedzai. H2O поддерживает три типа моделей: классификатор, регрессор и неконтролируемые модели. На данный момент все модели классификаторов, кроме Пропорциональных опасностей Кокса и Составных ансамблей, поддерживаются провайдером H2O OpenML. Перед тем, как мы начали работать над этой функцией, был проведен обзор требований к моделям H2O. Эти две модели классификатора не были идентифицированы как обязательные, потому что они, похоже, не соответствуют сценариям использования платформы Feedzai.

Везде, где вы импортируете или тренируете модель H2O, вы можете позже использовать эту модель внутри платформы Feedzai для оценки событий в режиме реального времени.

Хотите попробовать? Здесь вы можете найти провайдера H2O OpenML.

История провайдера

Первые версии этого провайдера были разработаны с использованием H2O’s REST API. Хотя он предлагал все возможности H2O, не беспокоясь об управлении жизненным циклом процесса H2O, у него был недостаток, заключающийся в том, что для его использования вам нужно было установить и запустить H2O на всех машинах, которые взаимодействуют с моделями H2O. Другими словами, вам нужно будет установить H2O на всех машинах, на которых работает платформа Feedzai, а если среда содержит кластер Spark, вам также потребуется установить H2O на всех рабочих узлах. Чтобы решить эту проблему, начиная с версии 0.3.0, мы больше не зависим от REST API, и вместо этого мы используем Java API, который подключается непосредственно к встроенному экземпляру H2O. Встроенный экземпляр инициализируется поставщиком, поэтому вам больше не нужно беспокоиться об установке H2O.

В версии 0.5.0 провайдер начал использовать другие функции H2O, кроме импорта и загрузки моделей. Функции важности функций платформы Feedzai были расширены с помощью алгоритма машины повышения градиента. В модели его можно использовать только в процессе AutoML.

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

Проблемы, с которыми пришлось столкнуться во время разработки

При разработке провайдера H2O OpenML мы столкнулись с парой интересных проблем. Чтобы привести примеры некоторых из них, давайте рассмотрим простейший способ инициализировать экземпляр H2O. Вы можете узнать, как инициализируется экземпляр на провайдере H2O, в объекте Feedzai H2OApp.

import water.H2OApp;
public class InitH2O {
   public InitH2O() {
      H2OApp.main(new String[0]);
   }
}

Отсутствие документации

Одна из самых больших проблем была вызвана скудной документацией по общедоступному API H2O. Можно найти документацию и примеры для API R и Python, но немного по API Java. REST API также задокументирован, но для объектов привязки REST API документация отсутствует. Объекты привязки позволяют взаимодействовать с REST API из программы Java.

К счастью, H2O была разработана на Java, и ее исходный код общедоступен. Лучший способ понять, как использовать Java API, - это погрузиться в исходный код, что также было непросто из-за отсутствия комментариев. К счастью, их набор тестов позволил нам лучше понять код и направил нас на правильный путь, чтобы найти объекты, которые нам нужно было принять во внимание.

Экземпляр Singleton H2O

После создания экземпляра H2O невозможно запустить другой из того же процесса ОС. Эту проблему можно решить, и можно избежать повторения использования одноэлементного шаблона, который допускает только один экземпляр.

Кроме того, когда H2O инициализируется значениями по умолчанию, он инициализирует несколько служб, таких как веб-интерфейс, которые не используются поставщиком. Это вызовет ошибки, если мы попытаемся инициализировать несколько экземпляров H2O на одном компьютере, даже если они инициализированы из разных процессов ОС. Первый экземпляр будет связывать порты машины, что приведет к сбою следующих экземпляров. Решение этой проблемы - инициализировать только те сервисы, которые использует провайдер.

import water.ExtensionManager;
import water.H2O;
public class InitH2O {
   public InitH2O() {
      H2O.main(new String[0]);
      ExtensionManager.getInstance().registerRestApiExtensions();
   }
}

Невозможно закрыть экземпляр H2O

После инициализации экземпляра H2O его невозможно закрыть, по крайней мере, без остановки процесса, который его инициализировал.

Единственный способ выключить H2O - вызвать «H2O.shutdown (0)», который вызывает «System.exit (int)», вызывая процесс, ответственный за создание экземпляр H2O, который нужно выключить.

В платформе Feedzai это означало бы, что JVM приложения будет остановлена.

Значения по умолчанию вызывают непредвиденное поведение

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

Если вы хотите изолировать свои экземпляры H2O, вы должны дать им уникальные имена и установить их адреса на localhost. Таким образом, они не будут искать другие экземпляры за пределами локального компьютера и будут искать локально уникальное имя, используемое только этим экземпляром.

Статические переменные

Экземпляр H2O инициализируется с использованием статических переменных, и инициализация не создает никаких локальных переменных, к которым можно получить доступ в программе Java. Взаимодействие с экземпляром происходит по той же схеме. Например, следующая строка используется для определения уровня журнала экземпляра H2O.

water.util.Log.setLogLevel("WARN", true);

На первый взгляд неясно, взаимодействует ли этот метод с экземпляром H2O, поскольку ни один из параметров не относится к экземпляру. Если вы посмотрите на исходный код объекта журнала, вы увидите, что он снова использует статические переменные, что затрудняет понимание побочных эффектов изменения этих переменных.

Заключение

После решения проблем, указанных выше, запуск экземпляра H2O был преобразован в следующий код.

import water.ExtensionManager;
import water.H2O;
import java.util.UUID;
public class InitH2O {
   private final static Object instanceLock = new Object();
   private static volatile InitH2O instance;
   public static InitH2O getInstance() {
      if (instance == null) {
         synchronized (instanceLock) {
            if (instance == null) {
               instance = new InitH2O();
            }
         }
      }
   }
   private InitH2O() {
       H2O.main(new String[] {"-name", UUID.randomUUID(), "-ip", "localhost"});
       ExtensionManager.getInstance().registerRestApiExtensions();
       water.util.Log.setLogLevel("WARN", true);
   }
}

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

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