Семантичний аналіз на основі Deeplearning4j для JVM

Всім привіт, мене звати Олександр, і я інженер-програміст. У цій статті розгляну використання фреймворку Deeplearning4j, інтегрованого в застосунок на Java для створення NLP-моделі та подальшого семантичного пошуку. Розберу налаштування нейромереж Word2vec та Doc2vec та їхню інтеграцію в застосунок.
Даний проєкт є прикладом використання AI для обробки технічного тексту, тренування мереж і побудови моделі для пришвидшення релевантного пошуку інформації й параметрів для подальшого застосування. Наприклад, для діагностування та виправлення несправностей і недоліків системи.
Детальніше про проєкт читайте за посиланням: JavaFX, Word2Vec, Doc2Vec.
Коротко про Deeplearning4j, Word2vec, Doc2vec
Бібліотека Deeplearning4j належить до підгалузі ML deep learning (глибоке навчання), яке представлено нейронними мережами або обчислювальними моделями, які складаються з взаємопов’язаних шарів і вузлів. Нижче розглянуто обробку природної мови NLP (Natural Language Processing).
Використані нейронні мережі:
- Word2Vec — для передбачення ймовірності слова відносно контексту або контексту відносно слова, залежно від архітектури моделі skip-gram або CBOW.
- Doc2Vec або ParagraphVectors — розширення word2vec, що дозволяє представити документи або набір речень у векторній формі. Використовує архітектуру двох основних моделей: Distributed Memory (PV-DM) — аналогічна CBOW та Distributed Bag of Words (PV-DBOW) — аналогічна підходу Skip-gram.
Архітектура «Вектори абзаців» в основному передбачає додавання унікального «ідентифікатора документа» або «мітки» як додаткових вхідних даних до моделі під час навчання.
Результатом навчання цих мереж є моделі, які складаються зі слів, речень або документів (далі — токенів), переведених у векторну форму, де кожен вектор — це набір чисел для представлення токенів в багатовимірному просторі. Їх розташування одне до одного залежить від семантичної близькості.
Нижче приклад представлення слів у векторній формі через набір чисел в моделі Word2vec.
аварійна 0.04098435118794441 -0.04435385763645172 -0.04439297690987587 … 0.008383741602301598
імпульс 0.028727758675813675 -0.032653313130140305 0.0042037065140903 … 0.009559465572237968
Структура проєкту на JavaFX. Основні складові
Ядром застосунку є Deeplearning4j, який відповідає за NLP. За графічну частину, тобто інтерфейс, відповідає openjfx. Підключаємо всі необхідні бібліотеки в pom.xml. Детальніше дивіться у проєкті.
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>22-ea+9</version>
</dependency>
……..
<dependency>
<groupId>org.deeplearning4j</groupId>
<artifactId>deeplearning4j-datasets</artifactId>
<version>${dl4j-master.version}</version>
</dependency>
………
Нижче скрін структури проєкту.

В теці resources розташований словникML.txt, що є основним файлом для машинного навчання, куди заноситься вся інформація для подальшого аналізу та семантичного пошуку. Текст може бути будь-якого направлення. Решта файлів відповідає за графіку.
Тека ap_impulse містить класи з основним алгоритмом.
WordSearch.java and DocSearch.java — опис і робота з нейромережами Word2vec і Doc2vec відповідно. WordSearchController.java — контролер для роботи з графікою, обробка подій тощо. Main.java — основний метод для запуску класу з застосунком JavaFX. WordSearchMain.java — запуск графіки.
Файли pathToWritetoWord.zip та pathToWriteto.zip — збережена модель мережі Word2Vec та Doc2vec відповідно. pathToWritetoWord.txt — стара версія моделі мережі Word2Vec.
Нижче скрін Runnable JAR версії програми та основні файли для її запуску. Бібліотеки, fxml та jar є основними в корені застосунку. Словник та батнік заповнюємо на свій розсуд. Моделі — похідна після запуску застосунку та навчання мереж.

Обробка тексту. Ітерація та токенізація
Налаштування мережі та підготовка тексту відбувається наступним чином.
Перед навчанням мережі текст, що знаходиться в словнику, який ще має назву «корпус», має пройти ітерацію та токенізацію. Ітерація виконує розділення речень по рядках. Код нижче.
iter.setPreProcessor(new SentencePreProcessor() {
public String preProcess(String sentence) {
if (sentence!= null) lst_buffer.add(sentence.toLowerCase());
System.out.println("iter "+ sentence);
return sentence.toLowerCase();
}
});
Токенізація розбиває строку послівно. Для кожного маркера (слова) застосовується регулярний вираз за замовченням [\d\.:,«’\(\)\[\]|/?!;], де всі цифри, знаки пунктуації та деякі спеціальні символи видаляються. Код нижче.
t.setTokenPreProcessor(new CommonPreprocessor() {
public String preProcess(String token) {
System.out.println("t "+ StringCleaning.stripPunct(token).toLowerCase());
return StringCleaning.stripPunct(token).toLowerCase();
}
});
Нижче результат роботи коду: ітерації та токенізації.
iter Масштаб струму виставлений ...
t масштаб
t струму
t виставлений
…
Мережа Word2Vec і її налаштування
Мережа приймає на вхід корпус тексту з файлу бібліотеки та створює векторний простір, де кожен вектор це унікальне слово. Дане створення відбувається коштом контекстного вікна. Код нижче.
Першим параметром minWordFrequency регулюємо чистоту моделі, наприклад, для великих корпусів доцільно ставити цифру понад 5. Тобто за словами, які зустрічаються менш як п’ять разів, не буде відбуватися навчання. Слова повинні з’являтися в кількох контекстах, щоб вивчити корисні ознаки про них.
Інший значущий параметр — це розмір вікна windowSize (ковзне вікно) для створення пар і далі для навчання моделі Skip-Gram. Наприклад, windowSize дорівнює 2, тоді формується наступний масив: W(i) — вхідні дані (центральне слово), далі контекстні слова W(i-2), W(i-1), W(i+1) та W(i+2). Нижче малюнок прикладу створення пар з розміром контекстного вікна = 2.

Інші параметри. Iterations — число дозволів на оновлення мережею своїх коефіцієнтів для однієї партії даних (ітерації). layerSize — розмір простору, де представлені вектори, де розмір це кількість ознак у вектору слів. Iterate — партія набору даних — це речення. tokenizerFactory — передача слів з цієї партії. Seed — випадкове початкове значення для генератора випадкових чисел.
Word2Vec vec = new Word2Vec.Builder( .minWordFrequency(1) .iterations(6) .layerSize(100) // 100 - вимірний простір. .seed(42) .windowSize(5) .iterate(iter) .tokenizerFactory(t) .build(); vec.fit(); // Почати навчання.
Нижче приклад роботи застосунку на основі технічного контексту.
Задаємо слово «струм» та знаходимо подібні або наближені слова відносно словника і моделі за допомогою методу wordsNearest.
Collection<String> lst = vec.wordsNearest(i_news, 5);
Застосунок виведе наступні наближені слова до слова «струм»:
Words closest to струм: [if, збудження, if#-поточне, ud-ном-дн, випрямлена]

В контексті технічної літератури if — це струм збудження обмотки двигуна, if#-поточне — теж співвідноситься зі струмом як параметр регулювання.
Дані слова можемо проглянути на такий собі коефіцієнт, як косинусна подібність, що частково відображає ваги для нейронної мережі, котрі можна представити в просторі як близькість векторів один до одного.
Отримуємо коефіцієнт якості семантичної подібності за допомогою методу similarity.
double cosSim = vec.similarity(i_news, i_news1);
Коефіцієнт cosSim між словами «струм» і «if» = 0.6019960045814514.

Мережа Doc2vec або ParagraphVectors
Doc2vec співвідносить мітки та документи або речення, тобто перетворює речення в векторний вигляд — мітку. Принцип використання схожий: ітерація, токенізація та налаштування. Доповнимо опис нових налаштувань: epochs є ознакою кількості ітерацій по корпусу. learningRate — розмір кроку для кожного оновлення коефіцієнтів, коли слова переміщуються в просторі ознак. labelsSource — приєднання попередньо визначеного джерела міток до ParagraphVectors. Код нижче.
LabelsSource source = new LabelsSource("DOC_");
ParagraphVectors vec = new ParagraphVectors.Builder()
.minWordFrequency(1)
.iterations(6)
.epochs(19)
.layerSize(100)
.learningRate(0.025)
.labelsSource(source)
.windowSize(5)
.iterate(iter)
.tokenizerFactory(t)
.sampling(0)
.build();
Для прикладу, нижче обчислена подібність між реченнями за допомогою методу getWordVectorsMean, який повертає вектор середнього значення, побудованого із переданих слів/міток.
Transforms.cosineSim(vector.getWordVectorsMean(label1), vector.getWordVectorsMean(label2));
Нижче скрін та результат порівняння введеного речення з наявними в словнику.

Найбільш релевантна відповідь для програми 0.7052888, для нас 0.35149997.
0.7052888 f2-налаштування режими налаштування
0.46898076 ан зупинене! авто налаштування зупинене
0.35149997 для налаштування рн необхідно спочатку включитися …..
Нижче представлений інший спосіб обчислення вихідного вектору за допомогою методу inferVector, який обчислює вихідний вектор для заданого тексту з параметрами за замовчуванням для швидкості навчання та ітерацій.
INDArray inferredVectorA1 = vec.inferVector(i_news); INDArray inferredVectorB1 = vec.inferVector(doc_number); key = (float)Transforms.cosineSim(inferredVectorA1, inferredVectorB1);
Відмінність цього обчислення від середнього вектора в тому, що відбувається запуск навчальних алгоритмів PV-DROW та SkipGram кожен раз під час порівняння речень.
10:59:15.364 [JavaFX Application Thread] INFO o.d.m.s.SequenceVectors - Building learning algorithms:
10:59:15.364 [JavaFX Application Thread] INFO o.d.m.s.SequenceVectors - building SequenceLearningAlgorithm: [PV-DBOW]
10:59:15.365 [JavaFX Application Thread] INFO o.d.m.s.SequenceVectors - building ElementsLearningAlgorithm: [SkipGram]
Нижче скрін та результат порівняння.

Рядок, який нас цікавить,
0.4110898 для налаштування рн необхідно спочатку включитися рс
Навчання моделі та її якість є трудомістким процесом, що потребує великого та підготовленого до навчання корпусу, налаштувань мереж та правильного промпту (запиту).
Висновок
Фреймворк Deeplearning4j з широким набором інструментів дає можливість інтегрувати глибоке навчання на JVM у свої застосунки. Бібліотека містить багато прикладів застосування різнотипних мереж і технік, як-от word2vec, Doc2vec, RNN, LDA, LSTM та багато інших. Також такі корисні доповнення як паралельне навчання, нейронний зоопарк, активна спільнота підтримки, інтеграція з Keras та Graf API пришвидшать та полегшать розробку та інтеграцію. Детальніше про Eclipse Deeplearning4j та набір інструментів для запуску глибокого навчання на JVM дивіться тут.
Дані мережі стануть в пригоді при написанні програми та навчанні моделі для вузькоспеціалізованого направлення. Що в підсумку можливо залучити як базу даних для аналізу інформації та швидкого пошуку рішень.
Сподобалась стаття? Підписуйтесь на автора, щоб отримувати сповіщення про нові публікації на пошту.
1 коментар
Додати коментар Підписатись на коментаріВідписатись від коментарів