Интеграция предобученных нейросетей в Java-проектах: практический пример
При работе с нейросетями, не обязательно каждый раз писать свою модель заново, можно использовать предобученные модели, что позволяет значительно сократить время разработки, а развитие модели и поддержка сообществом позволяет повысить точность анализа текстов.
В данной статье приведен практический пример интеграции предобученной модели NER (Named Entity Recognition) для русского языка с использованием DeepPavlov и библиотеки ONNX Runtime в Java-проекте.
Что такое NER?
NER — это задача извлечения именованных сущностей из текста. Модель автоматически определяет имена людей, географические названия, даты и организации.
Пример текста:
»Иван Иванов работает в Название_Компании и живет в Москве.»
Результат модели:
Иван Иванов → B-PER (имя человека)
Москве → B-LOC (место)
Название_Компании → B-ORG (организация)
Вообще, существует множество предобученных моделей для извлечения именованных сущностей (NER) и других задач NLP. Вот некоторые из них:
Эти модели значительно сокращают время разработки, обеспечивая высокую точность распознавания сущностей. Например, в анализе пользовательских отзывов их можно использовать для извлечения ключевых слов, автоматизации ответов или построения рекомендаций.
Пример применения
Допустим, у вас есть база данных статей, и вы хотите извлечь из них информацию об упомянутых людях, местах и организациях. Автоматическое извлечение через модель NER позволяет:
Быстро анализировать тексты.
Строить базу знаний.
Улучшать поиск по ключевым именам или локациям.
Настройка проекта
Добавьте в ваш pom.xml
зависимость для ONNX Runtime:
com.microsoft.onnxruntime
onnxruntime
1.16.3
Скачайте предобученную модель NER для русского языка из DeepPavlov.
Пример модели: deeppavlov_ner_onnx_model.onnx
Пример кода
import ai.onnxruntime.*;
import java.util.*;
public class RussianNER {
public static void main(String[] args) throws OrtException {
// Путь к модели DeepPavlov в формате ONNX
String modelPath = "models/deeppavlov_ner_onnx_model.onnx";
// Создаем окружение ONNX Runtime
OrtEnvironment env = OrtEnvironment.getEnvironment();
OrtSession.SessionOptions options = new OrtSession.SessionOptions();
OrtSession session = env.createSession(modelPath, options);
// Ввод текста на русском языке
String text = "Иван Иванов работает в Название_Компании и живет в Москве.";
// Токенизация текста
String[] tokens = {"[CLS]", "Иван", "Иванов", "работает", "в", "Название_Компании", "и", "живет", "в", "Москве", "[SEP]"};
long[][] inputIds = {{101, 3621, 3623, 3180, 1051, 27654, 2309, 1051, 11292, 102}};
long[][] attentionMask = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
// Преобразование входных данных в тензоры
OnnxTensor inputTensor = OnnxTensor.createTensor(env, inputIds);
OnnxTensor attentionTensor = OnnxTensor.createTensor(env, attentionMask);
// Запуск модели
OrtSession.Result result = session.run(
Map.of("input_ids", inputTensor, "attention_mask", attentionTensor)
);
// Извлечение результатов (logits)
float[][][] logits = (float[][][]) result.get(0).getValue();
// Поиск максимального значения (argMax) для каждой позиции токена
int[] predictions = new int[logits[0].length];
for (int i = 0; i < logits[0].length; i++) {
predictions[i] = argMax(logits[0][i]);
}
// Интерпретация результатов
System.out.println("Токены: " + Arrays.toString(tokens));
System.out.println("Метки NER: " + Arrays.toString(predictions));
}
// Метод для нахождения индекса максимального значения
private static int argMax(float[] values) {
int maxIndex = 0;
for (int i = 1; i < values.length; i++) {
if (values[i] > values[maxIndex]) {
maxIndex = i;
}
}
return maxIndex;
}
}
Объяснение кода
Токенизация текста:
Мы используем простой массив токенов для демонстрации. На практике, вам нужно будет использовать токенизатор, чтобы получить правильные идентификаторы для модели (например, с помощью Hugging Face Tokenizer).
Текст преобразуется в последовательность числовых идентификаторов (inputIds), которые понимает модель.
101
— специальный токен [CLS] (начало),102
— [SEP] (конец).Маска внимания:
Указывает, какие токены нужно учитывать при обработке.Прогон модели:
Модель возвращает метки для каждого токена, например:B-PER — начало имени
B-LOC — начало названия места
B-ORG — начало названия организации
Вывод результатов:
Пример для текста «Иван Иванов работает в Название_Компаниии живет в Москве.»:
Преимущества использования DeepPavlov и ONNX Runtime
Оптимизация: DeepPavlov предоставляет высококачественные модели для русского языка.
Производительность: ONNX Runtime позволяет запускать модели эффективно на CPU и GPU.
Простота интеграции: Благодаря ONNX Runtime, предобученные модели легко использовать в Java-проектах.
1) Тензоры — это математические объекты, которые обобщают понятия скаляров, векторов и матриц. В контексте машинного обучения и нейросетей тензоры — это многомерные массивы чисел, используемые для представления данных (например, изображений, текста или звуков) и параметров моделей.
// Преобразование входных данных в тензоры
OnnxTensor inputTensor = OnnxTensor.createTensor(env, inputIds);
OnnxTensor attentionTensor = OnnxTensor.createTensor(env, attentionMask);
Пример структуры тензоров:
Скаляр (Тензор 0-го ранга):
Это отдельное число без направлений или дополнительных измерений. Например:Число: 5
Используется для представления одной величины, например, температуры в одном месте.
Вектор (Тензор 1-го ранга):
Одномерный массив чисел. Например:Вектор: [1, 2, 3]
Вектор может представлять координаты точки в пространстве или значения признаков объекта.
Матрица (Тензор 2-го ранга):
Двумерный массив чисел, с строками и столбцами. Например:Матрица: [[1, 2], [3, 4]]
Матрицы часто используются для представления изображений (где каждая ячейка — яркость пикселя) или данных в виде таблиц.
3D-тензор (Тензор 3-го ранга):
Массив, содержащий двумерные массивы (матрицы). Например:3D-Тензор: [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
Может представлять набор изображений или один цветной снимок, где каждое измерение — это слой RGB.
N-мерные тензоры (Тензоры выше 3-го ранга):
Массивы большей размерности. Например, 4D-тензоры применяются для представления видео, где измерения могут быть:Батч изображений,
Высота и ширина,
Цветовые каналы.
4D-тензор: [[[[1], [2]], [[3], [4]]], [[[5], [6]], [[7], [8]]]]
Важность тензоров:
Гибкость: Поддерживают любые данные, от скаляров до сложных наборов.
Оптимизация вычислений: Все операции в нейросетях сводятся к манипуляциям с тензорами, что эффективно реализуется на GPU/TPU.
Универсальность: Тензоры применимы к любым задачам — от обработки изображений до анализа временных рядов.
Тензоры важны, так как нейросети выполняют математические операции над ними, такие как умножение, сложение и применение функций активации. В Java, с ONNX Runtime или библиотекой DL4J, данные преобразуются в тензоры для обработки предобученными моделями.
2) Токен BERT
// Токенизация текста
String[] tokens = {"[CLS]", "Иван", "Иванов", "работает", "в", "Название_Компании", "и", "живет", "в", "Москве", "[SEP]"};
long[][] inputIds = {{101, 3621, 3623, 3180, 1051, 27654, 2309, 1051, 11292, 102}};
long[][] attentionMask = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
При необходимости вводе строки, например через консоль, можно осуществить токенизацию, то есть найти необходимый токен к нашему слову в библиотеке или создать собственный токенизатор.
DeepPavlov Tokenizer: Можно вызвать через REST API из Java, если модель запущена на сервере.
Итак, пример в статье показывает, как предобученные модели на Java позволяют решать реальные задачи NLP, такие как извлечение именованных сущностей. Интеграция таких решений в приложения улучшает обработку данных и автоматизирует рутинные задачи, а использование предобученных моделей экономит массу времени.