Эта статья подходит для людей с основами Java
автор:DJL-Keerthan&Lanking
от HelloGitHub«Объяснение проектов с открытым исходным кодом»ряд. Эта проблема от инженеров Amazon:Keerthan Vasist, четвертый в серии о DJL, платформе глубокого обучения, полностью построенной на Java.
Введение
Java уже давно является популярным языком программирования для бизнеса. Благодаря богатой экосистеме и хорошо поддерживаемым пакетам и платформам Java имеет огромное сообщество разработчиков. Несмотря на непрерывную эволюцию и внедрение приложений глубокого обучения, Java-разработчикам не хватает фреймворков и библиотек. Большинство популярных сегодня моделей глубокого обучения компилируются и обучаются на Python. Для Java-разработчиков вход в мир глубокого обучения требует повторного изучения и принятия нового языка программирования, а также изучения тонкостей глубокого обучения. Это затрудняет для большинства разработчиков Java изучение и переход к глубокому обучению.
Чтобы снизить стоимость изучения глубокого обучения для разработчиков Java, AWS создала Deep Java Library (DJL) — платформу глубокого обучения с открытым исходным кодом, адаптированную для разработчиков Java. Он предоставляет разработчикам Java мост для подключения к основным средам глубокого обучения.
В этом посте мы попытаемся построить модель глубокого обучения с помощью DJL и использовать ее для обучения задаче распознавания рукописных цифр MNIST.
2. Что такое глубокое обучение?
Прежде чем мы начнем, давайте сначала разберемся с основными понятиями машинного обучения и глубокого обучения.
Машинное обучение — это процесс использования статистических знаний для ввода данных в компьютер для его обучения и выполнения конкретной целевой задачи. Этот метод индуктивного обучения позволяет компьютерам изучать некоторые функции и выполнять ряд сложных задач, таких как распознавание объектов на фотографиях. Эти задачи трудно решить в традиционных областях вычислительной науки из-за необходимости писать сложную логику и метрики.
Глубокое обучение — это отрасль машинного обучения, которая фокусируется на разработке искусственных нейронных сетей. Искусственная нейронная сеть — это набор вычислительной логики, полученный в процессе изучения того, как человеческий мозг учится и достигает целей. Он реализует различные сложные задачи, моделируя процесс передачи информации между частями человеческого мозга. «Глубина» глубокого обучения связана с тем, что мы будем сплетать и строить множество слоев в искусственной нейронной сети для дальнейшей более глубокой передачи информации о данных. Технология глубокого обучения имеет широкий спектр приложений и в настоящее время используется в различных реальных приложениях, таких как обнаружение объектов, распознавание действий, машинный перевод и семантический анализ.
3. Обучение MNIST распознаванию рукописных цифр
3.1 Конфигурация проекта
Вы можете использовать следующиеgradle
Настройте импорт зависимостей. В этом случае мы используем пакет API DJL (основной компонент DJL) и пакет basicdataset (набор данных DJL) для построения нейронной сети и набора данных. В этом случае мы используем MXNet в качестве механизма глубокого обучения, поэтому мы представимmxnet-engine
иmxnet-native-auto
две пачки. Этот кейс также может работать под движком PyTorch, просто замените его соответствующим пакетом.
plugins {
id 'java'
}
repositories {
jcenter()
}
dependencies {
implementation platform("ai.djl:bom:0.8.0")
implementation "ai.djl:api"
implementation "ai.djl:basicdataset"
// MXNet
runtimeOnly "ai.djl.mxnet:mxnet-engine"
runtimeOnly "ai.djl.mxnet:mxnet-native-auto"
}
3.2 NDArray и NDManager
NDArray — это базовая структура DJL для хранения структур данных и математических операций. NDArray представляет собой многомерный массив фиксированной длины. NDArray используется как в Pythonnumpy.ndarray
.
NDManager является боссом NDArray. Он отвечает за управление процессом генерации и повторного использования NDArray, что может помочь нам лучше оптимизировать память Java. Каждый NDArray будет создан NDManager, и они будут закрыты при закрытии NDManager. И NDManager, и NDArray построены на основе Java AutoClosable, что обеспечивает своевременный сбор данных в конце выполнения. Чтобы узнать больше об их использовании и практике, см. нашу предыдущую статью:
HelloGitHub DJL: Java от DJL работает с многомерными массивами, как NumPy
Model
В DJL и обучение, и логический вывод строятся на основе класса Model. Здесь речь в основном идет о методе построения в тренировочном процессе. Затем мы создаем новую цель для модели. Поскольку Model также наследует структуру AutoClosable, мы реализуем ее с помощью блока try:
try (Model model = Model.newInstance()) {
...
// 主体训练代码
...
}
Подготовить данные
База данных MNIST (Modified National Institute of Standards and Technology) содержит большое количество графов рукописных цифр и часто используется для обучения систем обработки изображений. DJL включил набор данных MNIST в набор данных базового набора данных, и размер каждого графика MNIST составляет28 x 28
. Если у вас есть собственный набор данных, вы также можете импортировать его в свою тренировочную задачу с помощью руководства по импорту набора данных DJL.
Учебное пособие по импорту набора данных:docs. CTR. LOVE /docs/ VELO…
int batchSize = 32; // 批大小
Mnist trainingDataset = Mnist.builder()
.optUsage(Usage.TRAIN) // 训练集
.setSampling(batchSize, true)
.build();
Mnist validationDataset = Mnist.builder()
.optUsage(Usage.TEST) // 验证集
.setSampling(batchSize, true)
.build();
Этот код создает наборы для обучения и проверки отдельно. В то же время мы также случайным образом расположили набор данных для лучшего обучения. В дополнение к этим конфигурациям вы также можете добавить к изображению дополнительную обработку, такую как установка размера изображения, нормализация изображения и т. д.
Сделать модель (построить блок)
Когда ваш набор данных будет готов, мы можем построить нейронную сеть. В DJL нейронная сеть состоит из блоков (кодовых блоков). Блок — это структура с различными свойствами нейронной сети. Они могут представлять операцию, часть нейронной сети или даже целую нейронную сеть. Затем блоки могут выполняться последовательно или параллельно. При этом сам Блок также может иметь параметры и подблоки. Эта вложенная структура может помочь нам построить сложную, но удобную в сопровождении нейронную сеть. В процессе обучения параметры, прикрепленные к каждому блоку, обновляются в режиме реального времени, включая соответствующие им подблоки. Этот рекурсивный процесс обновления гарантирует, что вся нейронная сеть полностью обучена.
Когда мы строим эти блоки, проще всего вложить их один за другим. Непосредственно используя типы блоков, готовые для DJL, мы можем быстро создавать различные типы нейронных сетей.
Мы предоставляем несколько вариантов Блока, основанных на нескольких основных режимах работы нейронной сети. SequentialBlock предназначен для обработки последовательного выполнения каждого подблока. Он будет продолжать выполнять вывод предыдущего подблока в качестве ввода следующего блока. Соответственно, ParallelBlock используется для параллельного ввода входных данных в каждый подблок и объединения выходных результатов в соответствии с конкретным уравнением слияния. Наконец, давайте поговорим о LambdaBlock — блоке, помогающем пользователям выполнять быстрые операции, он не имеет никаких параметров, поэтому в процессе обучения никакая часть не обновляется.
Давайте попробуем создать базовую нейронную сеть многослойного персептрона (MLP). Многослойный персептрон — это простая нейронная сеть с прямой связью, которая содержит всего несколько полностью связанных слоев (LinearBlock). Затем, чтобы построить эту сеть, мы можем напрямую использовать SequentialBlock.
int input = 28 * 28; // 输入层大小
int output = 10; // 输出层大小
int[] hidden = new int[] {128, 64}; // 隐藏层大小
SequentialBlock sequentialBlock = new SequentialBlock();
sequentialBlock.add(Blocks.batchFlattenBlock(input));
for (int hiddenSize : hidden) {
// 全连接层
sequentialBlock.add(Linear.builder().setUnits(hiddenSize).build());
// 激活函数
sequentialBlock.add(activation);
}
sequentialBlock.add(Linear.builder().setUnits(output).build());
Конечно, DJL также предоставляет блок MLP, который можно использовать напрямую:
Block block = new Mlp(
Mnist.IMAGE_HEIGHT * Mnist.IMAGE_WIDTH,
Mnist.NUM_CLASSES,
new int[] {128, 64});
тренироваться
Когда у нас есть набор данных и нейронная сеть, мы можем начать обучение модели. В глубоком обучении процесс обучения обычно завершается следующими этапами:
- Инициализация: мы инициализируем параметры каждого блока, и функция для инициализации каждого параметра определяется набором инициализаторов.
- Прямое распространение: этот шаг пропускает входные данные через нейронную сеть слой за слоем, а затем создает выходные данные.
- Рассчитайте потери: мы рассчитываем отклонение выхода и помеченного результата в соответствии с определенной функцией потерь Loss.
- Обратное распространение: на этом этапе вы можете рассчитать градиент каждого параметра, используя обратное вычисление потерь.
- Обновить веса: мы будем обновлять значение каждого параметра в блоке в соответствии с выбранным оптимизатором.
DJL использует структуру Trainer для упрощения процесса. Разработчикам нужно только создать Trainer и указать соответствующие Initializer, Loss и Optimizer. Все эти параметры задаются с помощью TrainingConfig. Давайте посмотрим на конкретные настройки параметров:
-
TrainingListener
: Это прослушиватель, установленный для процесса обучения. Он может отображать результаты обучения на каждом этапе в режиме реального времени. Эти результаты можно использовать для документирования процесса обучения или для отладки проблем во время обучения нейронной сети. Пользователи также могут настроить свой собственный TrainingListener для наблюдения за процессом обучения.
DefaultTrainingConfig config = new DefaultTrainingConfig(Loss.softmaxCrossEntropyLoss())
.addEvaluator(new Accuracy())
.addTrainingListeners(TrainingListener.Defaults.logging());
try (Trainer trainer = model.newTrainer(config)){
// 训练代码
}
Когда тренер сгенерирован, мы можем определить форму ввода. После этого вы можете вызвать функцию подгонки для обучения. Функция подгонки будет обучаться на входных данных для нескольких эпох и, наконец, сохранять результаты в локальном каталоге.
/*
* MNIST 包含 28x28 灰度图片并导入成 28 * 28 NDArray。
* 第一个维度是批大小, 在这里我们设置批大小为 1 用于初始化。
*/
Shape inputShape = new Shape(1, Mnist.IMAGE_HEIGHT * Mnist.IMAGE_WIDTH);
int numEpoch = 5;
String outputDir = "/build/model";
// 用输入初始化 trainer
trainer.initialize(inputShape);
TrainingUtils.fit(trainer, numEpoch, trainingSet, validateSet, outputDir, "mlp");
Вот и все для тренировочного процесса! Легко ли по-прежнему тренироваться с DJL? Затем посмотрите на вывод результатов обучения для каждого шага. Если бы вы использовали наш прослушиватель по умолчанию, вывод был бы похож на изображение ниже:
[INFO ] - Downloading libmxnet.dylib ...
[INFO ] - Training on: cpu().
[INFO ] - Load MXNet Engine Version 1.7.0 in 0.131 ms.
Training: 100% |████████████████████████████████████████| Accuracy: 0.93, SoftmaxCrossEntropyLoss: 0.24, speed: 1235.20 items/sec
Validating: 100% |████████████████████████████████████████|
[INFO ] - Epoch 1 finished.
[INFO ] - Train: Accuracy: 0.93, SoftmaxCrossEntropyLoss: 0.24
[INFO ] - Validate: Accuracy: 0.95, SoftmaxCrossEntropyLoss: 0.14
Training: 100% |████████████████████████████████████████| Accuracy: 0.97, SoftmaxCrossEntropyLoss: 0.10, speed: 2851.06 items/sec
Validating: 100% |████████████████████████████████████████|
[INFO ] - Epoch 2 finished.NG [1m 41s]
[INFO ] - Train: Accuracy: 0.97, SoftmaxCrossEntropyLoss: 0.10
[INFO ] - Validate: Accuracy: 0.97, SoftmaxCrossEntropyLoss: 0.09
[INFO ] - train P50: 12.756 ms, P90: 21.044 ms
[INFO ] - forward P50: 0.375 ms, P90: 0.607 ms
[INFO ] - training-metrics P50: 0.021 ms, P90: 0.034 ms
[INFO ] - backward P50: 0.608 ms, P90: 0.973 ms
[INFO ] - step P50: 0.543 ms, P90: 0.869 ms
[INFO ] - epoch P50: 35.989 s, P90: 35.989 s
Когда результаты обучения будут готовы, мы можем использовать модель прямо сейчас, чтобы выполнить вывод для распознавания рукописных цифр. Если содержание только что не очень ясно, вы можете попробовать обучение напрямую, перейдя по следующим двум ссылкам.
Обучение рукописному набору данных:docs.CTR.love/examples/do…
Вывод по рукописным наборам данных:docs. CTR. Информация о любви/страхе/Тотем…
Четвертый, последний
В этой статье мы представили основные концепции глубокого обучения и то, как элегантно использовать DJL для создания и обучения моделей глубокого обучения. DJL также предоставляет более разнообразные наборы данных и нейронные сети. Если вы заинтересованы в изучении глубокого обучения, вы можете обратиться к нашей книге по глубокому обучению Java.
Книга по глубокому изучению Java:zh.d2l.ai/
Библиотека Deep Java (DJL) — это платформа глубокого обучения на основе Java, которая поддерживает как обучение, так и логические выводы. DJL учится у других и построен на нескольких фреймворках глубокого обучения (TensorFlow, PyTorch, MXNet и т. д.), а также обладает превосходными функциями нескольких фреймворков. Вы можете легко использовать DJL для обучения и развертывания вашей модели.
Он также имеет мощную поддержку библиотеки моделей: вы можете легко читать различные предварительно обученные модели всего одной строкой. Библиотека моделей DJL теперь поддерживает до 70+ моделей от GluonCV, HuggingFace, TorchHub и Keras одновременно.
адрес проекта:GitHub.com/AWS labs/CTR…