Points Clés
- Les développeurs peuvent créer, former et déployer des modèles d'apprentissage automatique machine learning (ML) et deep learning (DL) à l'aide de Java et de leur IDE préféré
- DJL simplifie l'utilisation des frameworks de deep learning (DL) et prend actuellement en charge Apache MXNet
- La nature open-source de DJL devrait être mutuellement bénéfique pour la boîte à outils et ses utilisateurs
- DJL est indépendant du moteur, ce qui signifie que les développeurs peuvent écrire du code une fois et l'exécuter sur n'importe quel moteur
- Les développeurs Java doivent avoir une compréhension du cycle de vie ML et des termes ML courants avant d'essayer d'utiliser DJL
DJL d'Amazon est une boîte à outils pour le deep learning utilisée pour développer nativement en Java des modèles de type machine learning (ML) et deep learning (DL) tout en simplifiant l'utilisation des frameworks d'apprentissage. Une boîte à outils mise en open source juste à temps pour re:Invent 2019, DJL fournit un ensemble d'API de haut niveau pour former, tester et exécuter l'inférence. Les développeurs Java peuvent développer leurs propres modèles ou utiliser des modèles pré-formés développés par des data scientists en Python à partir de leur code Java.
DJL reste fidèle à la devise de Java, "write once, run anywhere (WORA)" soit "écrire une fois, exécuter n'importe où", en étant indépendant du moteur et du framework de deep learning. Les développeurs peuvent écrire du code une fois qui s'exécute sur n'importe quel moteur. DJL fournit actuellement une implémentation pour Apache MXNet, un moteur ML qui facilite le développement de réseaux de neurones profonds (deep neural networks). Les API de DJL utilisent JNA, Java Native Access, pour appeler les opérations d'Apache MXNet correspondantes. DJL orchestre la gestion de l'infrastructure en fournissant une détection automatique de CPU/GPU basée sur la configuration matérielle pour assurer de bonnes performances.
Les API DJL proposent une abstraction des fonctions couramment utilisées pour développer des modèles, permettant aux développeurs Java de tirer parti des connaissances existantes pour faciliter la transition vers ML. Pour voir DJL en action, utilisons un exemple de développement d'un modèle de classification de chaussures.
Le cycle de vie en Machine Learning
Le cycle de vie de machine learning est suivi pour produire le modèle de classification des chaussures. Le cycle de vie en ML est différent du cycle de vie de développement logiciel traditionnel et se compose de six étapes concrètes :
- Obtenir les données
- Nettoyer et préparer les données
- Générez le modèle
- Évaluez le modèle
- Déployer le modèle
- Obtenir une prédiction (ou inférence) à partir du modèle
Le résultat final du cycle de vie est un modèle d'apprentissage automatique qui peut être consulté et renvoie une réponse (ou prédiction).
Un modèle est tout simplement une représentation mathématique des tendances et des modèles que l'on retrouve dans les données. De bonnes données sont la base de tous les projets de ML.
À l'étape 1, les données sont obtenues à partir d'une source fiable. À l'étape 2, les données sont nettoyées, transformées et mises dans un format à partir duquel une machine peut apprendre. Le processus de nettoyage et de transformation est souvent l'élément le plus long du cycle de vie du machine learning. DJL facilite ce processus pour les développeurs en offrant la possibilité de prétraiter des images à l'aide de traducteurs (translators). Les traducteurs peuvent effectuer des tâches telles que redimensionner les images en fonction des paramètres attendus ou convertir des images de couleur en niveaux de gris.
Les développeurs qui passent au machine learning sous-estiment souvent le temps nécessaire pour nettoyer et transformer les données, les traducteurs sont donc un excellent moyen de relancer le processus. Au cours du processus de formation, étape 3, un algorithme d'apprentissage automatique effectue plusieurs passages ou époques (epochs) sur les données, les étudie, essaye d'apprendre les différents types de chaussures. Les tendances et les modèles trouvés, en ce qui concerne les chaussures, sont stockés dans le modèle. L'étape 4 intervient dans le cadre de la formation lorsque le modèle est évalué pour déterminer dans quelle mesure il identifie les chaussures; si des erreurs sont découvertes, elles sont corrigées. À l'étape 5, le modèle est déployé dans un environnement de production. Une fois le modèle en production, l'étape 6 permet au modèle d'être consommé par d'autres systèmes.
En règle générale, les modèles peuvent être chargés dynamiquement dans votre code ou accessibles via un endpoint HTTPS basé sur REST.
Les données
Le modèle de classification des chaussures est un modèle de classification multiclasses par vision de l'ordinateur (computer vision ou CV), formé à l'aide d'un apprentissage supervisé, qui classe les chaussures dans l'une des quatre étiquettes de classe : bottes, sandales, chaussures ou pantoufles. L'apprentissage supervisé doit inclure des données déjà étiquetées avec la cible (target) désignée aussi réponse (answer) que vous essayez de prédire; c'est ainsi que la machine apprend.
La source de données pour le modèle de classification des chaussures est le UTZappos50k jeu de données fourni par l'Université du Texas à Austin et est disponible gratuitement pour une utilisation académique et non commerciale. L'ensemble de données sur les chaussures se compose de 50 025 images du catalogue étiquetées recueillies auprès de Zappos.com.
Les données sur les chaussures ont été enregistrées localement et chargées à l'aide du dataset ImageFolder de DJL, qui récupère les images d'un dossier local.
// identify the location of the training data
String trainingDatasetRoot = "src/test/resources/imagefolder/train";
// identify the location of the validation data
String validateDatasetRoot = "src/test/resources/imagefolder/validate";
//create training data ImageFolder dataset
ImageFolder trainingDataset = initDataset(trainingDatasetRoot);
//create validation data ImageFolder dataset
ImageFolder validateDataset = initDataset(validateDatasetRoot);
Lors de la structuration des données localement, je ne suis pas descendu au niveau le plus granulaire identifié des étiquettes de classification des bottes par l'ensemble de données UTZappos50k, comme la cheville, la hauteur du genou, la mi-mollet, le genou, etc... Mes données locales sont conservées au plus haut niveau de classification, qui comprend uniquement les bottes, les sandales, les chaussures et les pantoufles.
En termes DJL, un ensemble de données contient simplement les données d'entraînement. Il existe des implémentations d'ensembles de données qui peuvent être utilisées pour télécharger des données (en fonction de l'URL que vous fournissez), extraire des données et séparer automatiquement les données en ensembles d'apprentissage et de validation.
La séparation automatique est une fonctionnalité utile car il est important de ne jamais utiliser les mêmes données avec lesquelles le modèle a été formé pour valider les performances du modèle. L'ensemble de données d'entraînement est utilisé par le modèle pour trouver des tendances et des modèles dans les données sur les chaussures. L'ensemble de données de validation est utilisé pour qualifier les performances du modèle en fournissant une estimation impartiale de la précision du modèle lors de la classification des chaussures.
Si le modèle était validé à l'aide des mêmes données avec lesquelles il avait été formé, notre confiance dans la capacité du modèle à classer les chaussures serait beaucoup plus faible, car le modèle est testé avec des données qu'il a déjà vues. Dans le monde réel, un enseignant ne testerait pas un élève en utilisant exactement les mêmes questions que celles fournies dans un guide d'étude, car cela ne mesurerait pas la véritable connaissance ou la compréhension par un élève; le même concept s'applique aux modèles de machine learning.
Formation
Maintenant que les données sur les chaussures sont séparées en ensembles de formation et de validation, utilisons un réseau de neurones pour former (ou produire) le modèle.
public final class Training extends AbstractTraining {
. . .
@Override
protected void train(Arguments arguments) throws IOException {
// identify the location of the training data
String trainingDatasetRoot = "src/test/resources/imagefolder/train";
// identify the location of the validation data
String validateDatasetRoot = "src/test/resources/imagefolder/validate";
//create training data ImageFolder dataset
ImageFolder trainingDataset = initDataset(trainingDatasetRoot);
//create validation data ImageFolder dataset
ImageFolder validateDataset = initDataset(validateDatasetRoot);
. . .
try (Model model = Models.getModel(NUM_OF_OUTPUT, NEW_HEIGHT, NEW_WIDTH)) {
TrainingConfig config = setupTrainingConfig(loss);
try (Trainer trainer = model.newTrainer(config)) {
trainer.setMetrics(metrics);
trainer.setTrainingListener(this);
Shape inputShape = new Shape(1, 3, NEW_HEIGHT, NEW_WIDTH);
// initialize trainer with proper input shape
trainer.initialize(inputShape);
//find the patterns in data
fit(trainer, trainingDataset, validateDataset, "build/logs/training");
//set model properties
model.setProperty("Epoch", String.valueOf(EPOCHS));
model.setProperty("Accuracy", String.format("%.2f", getValidationAccuracy()));
// save the model after done training for inference later
//model saved as shoeclassifier-0000.params
model.save(Paths.get(modelParamsPath), modelParamsName);
}
}
}
}
La première étape consiste à obtenir une instance de modèle en appelant Models.getModel(NUM_OF_OUTPUT, NEW_HEIGHT, NEW_WIDTH). Deep learning, une forme de machine learning, utilise un réseau de neurones pour former le modèle. Un réseau de neurones est modelé sur les neurones du cerveau humain; les neurones sont des cellules qui transmettent des informations (ou des données) à d'autres cellules.
ResNet-50 est un réseau neuronal souvent utilisé avec la classification d'images; les 50 indiquent qu'il y a 50 couches d'apprentissage (ou neurones) entre les données d'entrée originales et la prédiction finale. La méthode getModel() crée un modèle vide, construit un réseau neuronal ResNet-50 et définit le réseau neuronal sur le modèle.
public class Models {
public static ai.djl.Model getModel(int numOfOutput, int height, int width) {
//create new instance of an empty model
ai.djl.Model model = ai.djl.Model.newInstance();
//Block is a composable unit that forms a neural network; combine them
//like Lego blocks to form a complex network
Block resNet50 =
//construct the network
new ResNetV1.Builder()
.setImageShape(new Shape(3, height, width))
.setNumLayers(50)
.setOutSize(numOfOutput)
.build();
//set the neural network to the model
model.setBlock(resNet50);
return model;
}
}
L'étape suivante consiste à installer et configurer un Trainer en appelant la méthode model.newTrainer(config). L'objet config a été initialisé en appelant la méthode setupTrainingConfig(loss), qui définit la configuration de la formation (ou hyperparameters) pour déterminer comment le réseau est formé.
Les étapes suivantes nous permettent d'ajouter des fonctionnalités au Trainer en définissant :
- Metrics utilisant
trainer.setMetrics(metrics)
- un listener de formation utilisant
trainer.setTrainingListener(this)
- la forme d'entrée appropriée à l'aide de
trainer.initialize(inputShape)
Les Metrics
collectent et rapportent des indicateurs clés de performance (key performance indicators ou KPI) pendant la formation qui peuvent être utilisés pour analyser et surveiller les performances et la stabilité de la formation. L'étape suivante consiste à lancer le processus de formation en appelant la méthode fit(trainer, trainingDataset, validateDataset, "build/logs/training"), qui réitère la formation des données et stocke les patterns trouvés dans le modèle. À la fin de la formation, un artefact de modèle validé et performant est enregistré localement avec ses propriétés à l'aide de la méthode model.save(Paths.get(modelParamsPath), modelParamsName).
Les mesures rapportées au cours du processus de formation sont présentées ci-dessous. Notez qu'à chaque époque (epoch ou pass) la précision du modèle s'améliore; la précision d'entraînement finale pour l'époque 9 est de 90%.
Inférence
Maintenant que nous avons généré le modèle, il peut être utilisé pour effectuer l'inférence (ou la prédiction) sur de nouvelles données dont nous ne connaissons pas la classification (ou la cible).
private Classifications predict() throws IOException, ModelException, TranslateException {
//the location to the model saved during training
String modelParamsPath = "build/logs";
//the name of the model set during training
String modelParamsName = "shoeclassifier";
// the path of image to classify
String imageFilePath = "src/test/resources/slippers.jpg";
//Load the image file from the path
BufferedImage img = BufferedImageUtils.fromFile(Paths.get(imageFilePath));
//holds the probability score per label
Classifications predictResult;
try (Model model = Models.getModel(NUM_OF_OUTPUT, NEW_HEIGHT, NEW_WIDTH)) {
//load the model
model.load(Paths.get(modelParamsPath), modelParamsName);
//define a translator for pre and post processing
Translator<BufferedImage, Classifications> translator = new MyTranslator();
//run the inference using a Predictor
try (Predictor<BufferedImage, Classifications> predictor = model.newPredictor(translator)) {
predictResult = predictor.predict(img);
}
}
return predictResult;
}
Après avoir défini les chemins nécessaires vers le modèle et l'image à classer, obtenez une instance de modèle vide en utilisant la méthode Models.getModel(NUM_OF_OUTPUT, NEW_HEIGHT, NEW_WIDTH) et initialisez-la à l'aide de la méthode model.load(Paths.get(modelParamsPath), modelParamsName). Cela charge le modèle qui a été formé à l'étape précédente.
Ensuite, initialisez un Predictor, avec un Translator spécifié, en utilisant la méthode model.newPredictor (Translator). En termes DJL, un Translator fournit des fonctionnalités de prétraitement et de post-traitement des modèles. Par exemple, avec les modèles CV, les images doivent être remodelées en niveaux de gris; un traducteur peut le faire. Le Predictor nous permet d'effectuer une inférence sur le modèle chargé en utilisant la méthode Predictor.predict(img), en passant l'image à classer.
Cet exemple montre une seule prédiction, mais DJL prend également en charge les prédictions par lots. L'inférence est stockée dans PredictResult, qui contient l'estimation de probabilité par étiquette.
Les inférences (par image) sont présentées ci-dessous avec leurs scores de probabilité correspondants.
Image | Score de probabilité |
---|---|
[INFO ] - [ |
|
[INFO ] - [ |
|
[INFO ] - [ |
|
[INFO ] - [ |
DJL fournit une expérience de développement Java native et fonctionne comme toute autre bibliothèque Java. Les API sont conçues pour guider les développeurs avec les meilleures pratiques pour accomplir des tâches de deep learning. Avant de commencer avec DJL, une bonne compréhension du cycle de vie de ML est nécessaire. Si vous êtes nouveau à ML, lisez un aperçu ou commencez avec la série d'articles d'InfoQ, une introduction au machine learning pour les développeurs de logiciels. Après avoir compris le cycle de vie et les termes communs de ML, les développeurs peuvent rapidement se familiariser avec les API de DJL.
Amazon a mis en open source DJL, où des informations plus détaillées sur la boîte à outils peuvent être trouvées sur les pages DJL website et Java Library API Specification. Le code pour le modèle de classification des chaussures peut être examiné pour explorer davantage les exemples.
A propos de l'auteur
Kesha Williams est une ingénieure logiciel primée, une praticienne du machine learning et une instructrice technique chez A Cloud Guru avec 24 ans d'expérience. Elle a formé et encadré des milliers d'ingénieurs en logiciel Java aux États-Unis, en Europe et en Asie tout en enseignant au niveau universitaire. Elle dirige régulièrement des équipes d'innovation pour tester des technologies émergentes et partage ses connaissances lors de conférences à travers le monde. Elle a parlé de machine learning sur la scène du TED en tant que gagnante de la Spotlight Presentation Academy du TED. En outre, son travail de pionnière dans le domaine de l'intelligence artificielle lui a valu la distinction d'Alexa Champion et de AWS Machine Learning Hero d'Amazon. Pendant son temps libre, elle est mentor pour les femmes dans le domaine de la technologie par le biais de son site de réseautage social en ligne Colors of STEM.