Deep Learning en AI zijn al jaren meer dan alleen buzz words. Deep Learning ondersteunt een groot aantal van de services, die we dagelijks gebruiken om het leven makkelijker of leuker te maken. Het is dan ook merkwaardig dat AI en Deep Learning vooral worden toegepast in Python. Is er een toekomst voor Deep Learning op de JVM? En hoe ziet dat er dan uit?

Deeplearning4j is een open source Deep Learning library voor Java en de JVM. Deeplearning4j biedt een moderne API aan om neural networks op te bouwen en te trainen in een gedistribueerde omgeving. Hierbij wordt gebruikt gemaakt van Apache Hadoop en Apache Spark. In 2017 is het open source project gedoneerd aan de Eclipse Foundation en commerciële support wordt geleverd door de startup Skymind.

Deep Learning is een vorm van Machine Learning, die gebruikt wordt voor het werken met neurale netwerken (neural networks). Een neural network is geïnspireerd op de werking van het brein en bestaat uit een aantal lagen aan neuronen (ook wel neurons of nodes). Deze techniek wordt veel gebruikt voor classificatie. Wanneer een neural network ingezet wordt voor de classificatie van data, dan wordt deze data gekoppeld aan een bepaalde groep (ook wel label). De classificatie van de data wordt beïnvloed door patronen, die herkend zijn uit sample data waarmee het netwerk opgezet is. Deep Learning gaat specifiek over diepe neural networks, waarbij altijd 1 input laag, 1 output laag en 1 of meerdere “hidden” lagen zijn. Een neural network kan aan de hand van voorbeelden leren hoe de relaties tussen de neurons/nodes geconfigureerd moet worden om zo dicht mogelijk bij het gewenste antwoord uit te komen.

De maintainers van Deeplearning4j zijn zich er van bewust dat data scientists veelal gebruik maken van Python, met behulp van een van de vele Python machine learning frameworks. Dit komt omdat de meest bekende frameworks voor machine learning voor Python ontwikkeld zijn, en de taal relatief makkelijk te begrijpen is in vergelijking met alternatieven. Daar tegenover gebruiken de meeste enterprise Big Data applicaties Java en vaak zijn bedrijven afhankelijk van het Java ecosysteem om consistente instellingen, monitoring en security toe te passen. Om er voor te zorgen dat deze partijen toch met elkaar kunnen samenwerken, is het mogelijk om een model te importeren vanuit Keras, een high-level neural network API voor Python. Keras draait die modellen bovenop TensorFlow, CNTK of Theano. Als je een model uit Keras importeert, is het mogelijk om het te trainen op een Hadoop cluster via Spark. Bij het trainen van een netwerk gebruik je voorbeelden uit een datasource, die al geclassificeerd zijn om het netwerk te kalibreren. Daarna kun je het in productie uitvoeren op bestaande Java technologieën, die veel worden gebruikt in de enterprise wereld.

Met Deeplearning4j is het dus mogelijk om een netwerk zowel in Java als in Python te configureren en te prototypen. Deeplearning4j kan vervolgens toegepast worden om het uit te rollen in productie of gedistribueerd te trainen op een cluster.

Hoe Deeplearning4j werkt

De API van Deeplearning4j is beschikbaar voor Java en Scala. De API van Deeplearning4j bestaat uit een aantal builders voor het samenstellen van neural network configuraties en implementaties voor de veelgebruikte algoritmes en functies in Deep Learning. Verder heeft Deeplearning4j nog een aantal componenten, waaronder een evaluatie API om de nauwkeurigheid van een netwerk te berekenen, DataVec voor het serializeren van data naar vectors (meer hierover later), Arbiter voor het automatisch optimaliseren van netwerk parameters en Word2Vec voor het verwerken van tekst.

 

Supported platforms en performance

Het eerste vraagstuk waar je wellicht tegenaan loopt, gaat over de beperkingen van N-dimensionale arrays in Java. Helaas zit er een limiet aan het aantal waardes in een N- dimensionale array. Deze limiet is te laag voor het uitvoeren van matrix-operaties op neurale netwerken met vele en grote lagen. Daarnaast is het uitvoeren van deze berekeningen niet snel. Om dit probleem op te lossen, heeft Deeplearning4j een onderliggende wiskunde library in het leven geroepen, genaamd ND4J.

ND4J is een Java API voor wetenschappelijke berekeningen met N-dimensionale arrays. De syntax emuleert die van Numpy en MATLAB, twee interfaces die veel worden gebruikt voor wiskundige berekeningen. ND4J wordt gebruikt voor het uitvoeren van lineaire algebra en grootschalige matrix berekeningen. Het nd4j-api component heeft een aantal implementaties. Op dit moment is er een C++ en CUDA (NVIDIA GPU) backend en in de toekomst zal er waarschijnlijk ook een backend zijn voor OpenCL en Power8. ND4J is snel en als resultaat biedt Deeplearning4j competitieve snelheid in vergelijking met andere bekende machine learning libraries. Op de site van Deeplearning4j kun je instructies vinden voor het runnen van benchmarks en het tunen van de performance.

DataVec

DataVec is Deeplearning4j’s oplossing voor het omgaan met data. Neural networks werken exclusief met vectoren, een genormaliseerde reeks aan decimalen, die de input data representeren. Als je data in CSV-formaat is opgeslagen of een folder met gelabelde plaatjes, dan kan DataVec ervoor zorgen dat deze data wordt omgezet in vectoren waar je neurale netwerk mee kan werken. DataVec kan ook worden gebruikt voor de visualisatie en analyse van datasets. Het is bijvoorbeeld mogelijk om een HTML-analyse of plot te genereren voor een DataVec schema.

Mobile (Android)

Meestal wordt het trainen van een neuraal netwerk uitgevoerd op krachtige computers met veel GPU’s. Dit komt omdat bij het trainen vaak grote aantallen aan voorbeelden in batches geëvalueerd worden, waarmee vervolgens het netwerk gekalibreerd wordt. Maar het is ook mogelijk om netwerken te gebruiken of trainen op smartphones. Omdat Deeplearning4j in Java geschreven is, kan het gebruikt worden op een Android device om voorspellingen te doen met een getraind of ongetraind netwerk. Op de site van Deeplearning4j staan voorbeelden voor het ontwikkelen van een afbeeldingsclassificator, waarbij volledig op de achtergrond en zonder internetverbinding voorspellingen kunnen worden uitgevoerd met Deeplearning4j.

Deeplearning4j in actie

DeepLearning4j biedt een builder API aan voor het configureren van een neural network setup. Vervolgens kun je dit netwerk trainen en voorspellingen doen voor bepaalde waarden. Hierbij produceert het netwerk een aantal labels en voor elke label een waarschijnlijkheid dat de inputwaarde onder deze label valt. Het aantal labels is dus gelijk aan het aantal output nodes van een netwerk.

 

Met de NeuralNetConfigurationBuilder, kan je een aantal globale netwerkinstellingen aanpassen en standaardwaardes uitkiezen voor de lagen uit het netwerk. In dit geval is de standaard activation function geconfigureerd als RELU. Wat RELU precies doet is hier niet heel erg relevant. Vervolgens worden de lagen van het netwerk gespecificeerd. Een invoerlaag is altijd present; de grootte hiervan is gelijk aan de nIn waarde van de eerste hidden layer. De eerste hidden layer wordt geïnitialiseerd met een Dense Layer en de laatste laag als Output Layer. Elke laag uit het netwerk heeft zijn eigen builder, met instellingen die afhankelijk zijn van het soort laag. In de output laag wordt de activation function aangepast naar Softmax. Hierbij wordt de standaardwaarde van RELU overschreven. Als laatst wordt met deze configuratie een nieuw netwerk opgebouwd en geïnitialiseerd.

 

In Listing 2 wordt het netwerk getraind met voorbeelden. Dit wordt gedaan door het netwerk te fitten op de data. In de praktijk wordt dit vaak in meerdere iteraties gedaan. Het doel is om een hoge nauwkeurigheid te behalen op de voorbeelden. Uiteraard kun je met Deeplearning4j ook een bestaand netwerk evalueren. Bij het evalueren wordt vaak andere data gebruikt dan bij het trainen om te valideren dat het netwerk ook goed om kan gaan met data, die het nog niet eerder gezien heeft. Het kan namelijk zijn dat een netwerk heel erg goed werkt op de gegeven voorbeeld data, maar niet de juiste patronen herkent om onbekende data te kunnen classificeren. Dit heet “overfitting”. Omdat je niet veel inzicht hebt op hoe de relaties in een netwerk precies in elkaar zitten, is het erg lastig om de juiste verhouding hierin op te zoeken. Deeplearning4j biedt de mogelijkheid om Early Stopping toe te passen, waarbij het netwerk tussen training iteraties door geëvalueerd wordt om op overfitting te controleren en de training vroegtijdig te stoppen.

 

In Listing 3 wordt Deeplearning4j’s DataVec ImageLoader gebruikt om een plaatje om te zetten in een vector, die gebruikt kan worden als inputwaarde voor het netwerk. Vervolgens wordt er een voorspelling gedaan voor het plaatje en de uitkomst hiervan is een nieuwe vector met de waarschijnlijkheid dat de input onder de gegeven label valt. Uit deze vector kun je de index van de meest waarschijnlijke label en de bijbehorende waarde ophalen. Deze waardes heten in het voorbeeld bestPredictionLabelIndex en bestPredictionConfidence. De confidence geeft aan hoe zeker het netwerk is dat de input onder het gegeven label valt.

Naast het handmatig opbouwen van een configuratie voor een netwerk is het ook mogelijk om een netwerk te importeren vanuit Keras. Deeplearning4j kan modellen importeren uit Keras HDF5 bestanden met model en training gegevens, of losse tekstbestanden met JSON netwerk configuratie. Importeren vanuit Keras staat uitgebreid uitgelegd op de site van Deeplearning4j.

Deeplearning4j & Spark

Voor complexe netwerken met extreem veel data, kan het handig zijn om met Deeplearning4j gedistribueerd te trainen. Dit kan met Apache Spark. Deeplearning4j ondersteunt neural network training op een cluster aan CPU- of GPU-machines met  Apache Spark. Spark is een analytics engine voor grootschalige geclusterde verwerking van data. Spark kan bovenop Hadoop, Amazon EC2, YARN, Mesos of Kubernetes draaien en data verwerken uit HDFS, Cassandra, HBase, Hive en vele anderen.

Apache Spark maakt het mogelijk om dataverwerking op zeer grote schaal efficiënt en snel uit te voeren op een cluster. Het wordt door velen gebruikt voor analyse op Big Data Warehouses. Deeplearning4j kan deze technologie gebruiken om aan te sluiten op je bestaande databronnen en hierop trainen in parallel, op een bestaand cluster. Voor bestaande gebruikers van deze softwareoplossingen is dit een hele makkelijke manier om grootschalige deep learning mogelijk te maken. Het is wel belangrijk om af te wegen of het gebruiken van een gedistribueerde training setup nodig is voor een specifiek netwerk. Dit hangt af van de complexiteit van het netwerk en de beschikbare data om mee te trainen.

Deeplearning4j’s integratie met Apache Spark maakt gebruik van Resilient Distributed Datasets (RDD’s). Een RDD is een fout-tolerante collectie aan elementen, die in parallel verwerkt kunnen worden in een cluster. Het doel van een RDD is om een high-level API beschikbaar te stellen, zodat het makkelijker is voor de programmeur om te focussen op het algoritme in plaats van het managen van gedistribueerde systemen. Deeplearning4j kan data uit RDD’s ophalen en in parallel verwerken met een Spark job.

In het bovenstaande minimale voorbeeld wordt een Spark training master gebruikt. De training master bepaalt hoe gedistribueerde training wordt uitgevoerd. Op het moment zijn hier twee implementaties van. De meest simpele variant is de Parameter Averaging methode, waarbij de training gedistribueerd wordt en de training master vervolgens de parameters samenvoegt om het netwerk te configureren. De methode die echter tegenwoordig wordt aangeraden is de Gradient Sharing methode, gebaseerd op de Strom 2015 neural network paper door Nikko Strom van Amazon (http://nikkostrom.com/publications/interspeech2015/strom_interspeech2015.pdf). Een uitgebreide uitleg over deze implementaties is beschikbaar op de site van Deeplearning4j.

Conclusie

De API van Deeplearning4j is intuïtief en voelt fijn aan als Java developer. Het is immers gebaseerd op moderne patterns, die veel voorkomen in moderne Java interfaces. De integratie met Spark is een mooie toevoeging op deze machine learning library, waardoor Deeplearning4j goed in bestaande Java stacks past. Het wordt je gemakkelijk gemaakt om Deeplearning4j aan te sluiten op bestaande databases en DataVec zorgt ervoor dat je niet na hoeft te denken over hoe veelgebruikte datasoorten omgezet moeten worden naar een genormaliseerde vector. Deeplearning4j maakt het mogelijk om Deep Learning te implementeren in bestaande applicaties, zonder dat je daarbij van de Java taal af hoeft te stappen, en dat zonder een groot verlies in performance en zonder dat je zelf wiskundige functies hoeft te implementeren.

Voor voorbeelden van Deeplearning4j kan je kijken op de Github repository “dl4j-examples” (https://github.com/deeplearning4j/dl4j-examples). Met name de MNIST single layer example (https://github.com/deeplearning4j/dl4j-examples/blob/master/dl4j-examples/src/main/java/org/deeplearning4j/examples/feedforward/mnist/MLPMnistSingleLayerExample.java) en andere feedforward voorbeelden (https://github.com/deeplearning4j/dl4j-examples/blob/master/dl4j-examples/src/main/java/org/deeplearning4j/examples/feedforward/mnist/MLPMnistSingleLayerExample.java ) zijn een goed startpunt.

De afbeelding over Deeplearning4j technieken is afkomstig van Deeplearning4j.org.