Большинство специалистов по данным строят свои модели на Python и R. Только в очень специфических случаях необходимо использовать другой язык (более эффективный). Например, если вы хотите сделать очень быстрые выводы (прогнозы) для потока данных.

Здесь мы увидим простой пример того, как мы можем настроить конвейер для модели машинного обучения, реализованной с помощью Java. От извлечения данных из ZIP-файлов до оценки результатов. Кроме того, вы увидите различия между Java и Python при построении модели.

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

Что мы будем делать?

Мы возьмем набор данных Dry Bean (ссылка здесь) и построим модель XGboost, чтобы предсказать, к какому классу принадлежит каждый компонент с учетом набора функций. Мы сделаем это с помощью Java и Maven.

Вкратце: Maven — это инструмент сборки, который позволяет нам управлять Java-приложениями в разных IDE. По сути, он определяет конкретный способ установки и импорта всех библиотек, структуру нашего приложения и т. д. Если вы используете IntelliJ или Eclipse для разработки своих Java-проектов, они уже интегрированы.

Кроме того, мы не собираемся тратить много времени на исследовательский анализ, разработку функций, оптимизацию модели и т. д. Цель этой статьи — показать и продемонстрировать, как создавать процессы машинного обучения с помощью Java.

Обзор приложений

Здесь вы можете увидеть структуру нашего приложения. Обратите внимание на файл pom.xml со всеми инструкциями, необходимыми Maven для создания нашего приложения. Не беспокойтесь, если вы не привыкли к Maven, вам не нужно знать его, чтобы понять остальную часть код. Эта статья не о работе с Maven. Причина, по которой я решил использовать Maven, заключается в том, что если вы привыкли работать с Java, скорее всего, вы знаете Maven. Это облегчит вам копирование кода и воспроизведение результатов.

Помимо файла pom.xml, давайте посмотрим на структуру. Сначала вы увидите, что в папке src/main/java у вас есть три разные папки и основной класс. Вот их краткое описание:

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

  1. RawDatasource: для хранения обучающих данных, о которых мы упоминали выше.
  2. ProcessedData: для сохранения результатов после определения типа компонента.
  3. ResultData: для хранения сводных данных результатов.

mlModels. Вот наши классы моделей машинного обучения. Для этого примера есть только один.

  1. BasicXGBoostModel: простая реализация модели XGBoost.

utils: Здесь у нас есть все вспомогательные функции, которые понадобятся для нашего приложения:

  1. Проверки данных. Этот общий класс позволит нам реализовать различные проверки данных. Например, он проверяет нулевые значения. Если у нас есть строки с нулевыми значениями, они удаляются.
  2. Кодировщик: этот класс позволяет нам кодировать любой категориальный признак или метку в числа. Кроме того, он создает файл Json, чтобы позже можно было декодировать эти значения.
  3. JsonReader: этот класс позволяет нам читать файлы Json и преобразовывать их в словари для доступа к значениям.
  4. ModelEvaluation: этот класс запускает тесты на модели после того, как она обучена оценивать ее производительность. Для данных обучения и тестирования он оценивает общую производительность, а также производительность по типу компонента.
  5. Reader: этот класс позволяет нам читать файлы как CSV-файлы.
  6. TrainTestSplit: этот класс позволяет нам разделить имеющиеся у нас данные между данными обучения и данными тестирования.
  7. TransformToLibsvm: этот класс позволяет нам преобразовывать наши данные в формат Libsvm. Библиотека XGBoost требует, чтобы данные были в этом формате.
  8. Распаковать. Этот класс позволяет извлекать данные из файлов .zip.

Main.java: основной класс, который запускает все приложение.

С другой стороны, у вас есть папка ресурсов, в которой у нас есть все необходимые нам данные, которые не являются классами Java или файлом pom.xml. Здесь вы найдете:

  1. basicXGBoostModelConfig: файл Json со всеми параметрами, необходимыми для модели XGBoost.
  2. набор данных: мы будем хранить все данные, над которыми мы работаем, в этой папке.
  3. DryBeanDataset: ZIP-файл с начальными обучающими данными.

Приложение

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

Все приложение управляется основным классом Main.java.

Main.java

Мы рассмотрим различные части класса Main, чтобы шаг за шагом понять, что делает это приложение. Ниже вы можете найти код. Как вы могли заметить, это приложение принимает только два параметра:

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

Распаковать.java

Первое, что делает это приложение, это берет ZIP-файл с данными и извлекает его в файл CSV. Это единственная часть кода, которую я не писал сам, так что заслуга исходного автора. Вы можете увидеть ссылки в коде.

Reader.java

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

Но как только мы это сделали, возникает вопрос, в каком формате мы обрабатываем данные внутри нашего приложения? Чтобы решить эту проблему, у нас есть класс RawDatasource.

Reader.java

Мы будем читать каждую строку CSV-файла, используя экземпляр класса RawDatasource. Все эти экземпляры будут храниться внутри массиваList. Найдите ниже структуру этих экземпляров.

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

DataChecks.java

Как только это будет сделано, наше приложение сможет работать с данными. Наиболее распространенной задачей является выполнение проверок данных. Здесь я создал класс, который мы могли бы использовать для многих проверок. Чтобы быть кратким, я применил только быструю проверку, чтобы увидеть, есть ли какие-либо нулевые значения. Эти строки будут удалены.

Кодировщик.java

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

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

TrainTestSplit.java

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

В этом случае мы разделили наши данные на 80% для обучения и 20% для тестирования.

TransformToLibsvm.java

Обычно в этот момент мы обучаем модель с нашими данными. Но библиотека xgboost4j, которую мы используем для обучения модели XGBoost, требует, чтобы данные имели определенный формат, который называется Libsvm.

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

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

Используя это, мы создадим два файла libsvm, один для данных обучения, а другой для данных тестирования.

BasicXGBoostModel.java

Теперь, с правильным форматом, мы можем двигаться вперед и обучать модель. Параметры модели находятся в файле Json, как мы сказали выше. Мы не пытаемся здесь оптимизировать параметры, это тема для отдельной статьи. Но не стесняйтесь копировать код, настраивать модель и экспериментировать с параметрами, чтобы проверить другие параметры. Эти параметры находятся в файле с именем basicXGBoostModelConfig.

Учитывая эти параметры, мы передадим все это в класс модели вместе с данными для обучения модели.

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

Наконец, когда модель обучена, мы сохраняем ее как bin-файл, чтобы иметь к ней доступ позже. Это в основном то, что произошло бы в реальном сценарии.

Вы найдете эту модель как model.bin после ее запуска.

ModelEvaluation.java

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

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

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

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

Наконец, вы увидите, что модель возвращает нам имя класса компонента, а не связанное с ним значение, полученное путем кодирования. Это связано с тем, что мы сохранили в файле Json отношения кодирования, что позволяет нам декодировать данные. Функция вызывает этот Json и переводит закодированное значение обратно в имя типа компонента.

Заключение

Создание модели машинного обучения с помощью Java занимает гораздо больше времени, чем с использованием Python или R. Кроме того, у нас будет меньше ресурсов, чем мы привыкли с Python, все базовые библиотеки, такие как pandas, scikit-learn, и т. д. для управления данными и облегчения обработки данных не предусмотрены, мы должны создавать свои собственные инструменты. Но в некоторых случаях Java, потому что его скорость может быть правильным выбором для наших нужд.

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

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

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