{"id":1731,"date":"2019-12-16T01:00:00","date_gmt":"2019-12-16T01:00:00","guid":{"rendered":"https:\/\/www.javaadvent.com\/?p=1731"},"modified":"2019-12-15T07:49:05","modified_gmt":"2019-12-15T07:49:05","slug":"how-to-do-deep-learning-for-java","status":"publish","type":"post","link":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html","title":{"rendered":"How to do Deep Learning for Java?"},"content":{"rendered":"\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/miro.medium.com\/max\/960\/0%2AEGp8SiIzvsbCPkRG.jpg?w=600&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"6eb6\">Introduction<\/h1>\n\n\n\n<p>Some time ago I came across this life-cycle management tool (or cloud service) called <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a>\n and I was quite impressed by its user-interface and simplicity of \ndesign and layout. I had a good chat about the service at that time with\n one of the members of <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a> and was given a demo. Previous to that I had written a simple pipeline using <a href=\"https:\/\/www.gnu.org\/software\/parallel\/\" target=\"_blank\" rel=\"noreferrer noopener\">GNU Parallel<\/a>, JavaScript, Python and Bash \u2014 and another one purely using <a href=\"https:\/\/www.gnu.org\/software\/parallel\/\" target=\"_blank\" rel=\"noreferrer noopener\">GNU Parallel<\/a>,\n and Bash. Also thought about replacing the moving parts with \nready-to-use task\/workflow management tools like Jenkins X, Jenkins \nPipeline, Concourse or Airflow but due to various reasons, I did not \nproceed with the idea.<\/p>\n\n\n\n<p>Coming back to our original conversation, I noticed a lot of the examples and docs on <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a>\n were based on Python, R and the respective frameworks and libraries. \nThere was a lack of Java\/JVM based examples or docs. So I took this \nopportunity to do something about that.<\/p>\n\n\n\n<p>I was encouraged by <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a> to implement something using the famous Java library called <a href=\"https:\/\/deeplearning4j.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">DL4J \u2014 Deep Learning for Java<\/a>.<\/p>\n\n\n\n<p>My initial experience with <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a>\n already gave me a good impression after getting an understanding of its\n design, layout and workflow. That it was developer-friendly and the \nmakers already took into consideration various facets of both developer \nand infrastructure workflows. In our worlds, the latter is mostly run by\n DevOps or SysOps teams and we know the nuances and pain-points attached\n to it. You can find out more about its features from the <a href=\"https:\/\/valohai.com\/features\/\" target=\"_blank\" rel=\"noreferrer noopener\">Features section<\/a> of the site.<\/p>\n\n\n\n<p><strong>Achtung!<\/strong>\n Just to let you know that from here onwards the post will be a bit more\n technical and may contain code snippets and mention of deep \nlearning\/machine learning and infrastructure-related terminologies.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"dda1\">What do we need and how?<\/h1>\n\n\n\n<p>For\n any machine learning or deep learning project or initiative, these days\n the two important components (from a high-level perspective) are code \nthat will create and serve the model and infrastructure where this whole\n life-cycle will be executed.<\/p>\n\n\n\n<p>Of\n course, there are going to be steps and components needed before, \nduring and after the above, but to keep things simple let\u2019s say we need \ncode and infrastructure.<\/p>\n\n\n\n<p><strong>Code<\/strong><\/p>\n\n\n\n<p>For code I have chosen a modified example using DL4J, it\u2019s an <a href=\"https:\/\/en.wikipedia.org\/wiki\/MNIST_database\" target=\"_blank\" rel=\"noreferrer noopener\">MNist project<\/a>\n with a training set of 60,000 images and test set of 10,000 images of \nhand-written digits. This dataset is available via the DL4J library \n(just like <a href=\"https:\/\/keras.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Keras<\/a> provides a stock of them). Look for the <a href=\"https:\/\/github.com\/eclipse\/deeplearning4j\/blob\/master\/deeplearning4j\/deeplearning4j-data\/deeplearning4j-datasets\/src\/main\/java\/org\/deeplearning4j\/datasets\/iterator\/impl\/MnistDataSetIterator.java\" target=\"_blank\" rel=\"noreferrer noopener\">MnistDataSetIterator<\/a> under <a href=\"https:\/\/github.com\/eclipse\/deeplearning4j\/blob\/master\/nd4j\/nd4j-backends\/nd4j-api-parent\/nd4j-api\/src\/main\/java\/org\/nd4j\/linalg\/dataset\/api\/iterator\/DataSetIterator.java\" target=\"_blank\" rel=\"noreferrer noopener\">DatasetIterators<\/a> in the <a href=\"https:\/\/deeplearning4j.org\/docs\/latest\/deeplearning4j-cheat-sheet\" target=\"_blank\" rel=\"noreferrer noopener\">DL4J Cheatsheet<\/a> for further details on this particular dataset.<\/p>\n\n\n\n<p>Have a look at the source code we will be using before getting started, the main Java class is called <a href=\"https:\/\/github.com\/neomatrix369\/awesome-ai-ml-dl\/blob\/master\/examples\/cloud-devops-infra\/valohai\/MLPMnist\/src\/main\/java\/org\/deeplearning4j\/feedforward\/mnist\/MLPMnistSingleLayerRunner.java\" target=\"_blank\" rel=\"noreferrer noopener\">org.deeplearning4j.feedforward.mnist.MLPMnistSingleLayerRunner<\/a>.<\/p>\n\n\n\n<p><strong>Infrastructure<\/strong><\/p>\n\n\n\n<p>As it is obvious by now, we have decided to try out the Java example using <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a> as our infrastructure to run our experiments (training and evaluation of the model). <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a>\n recognizes git repositories and directly hooks into them and allows \nexecution of our code, irrespective of platform or language \u2014 we will \nsee how this works. This also means if you are a strong supporter of \nGitOps or Infrastructure-As-Code you will appreciate the workflow.<\/p>\n\n\n\n<p>For this we just need an account on <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a>, we can avail a <a href=\"https:\/\/valohai.com\/pricing\/\" target=\"_blank\" rel=\"noreferrer noopener\">Free-tier account<\/a> and have access to several instances of various configurations when we <a href=\"https:\/\/app.valohai.com\/accounts\/signup\/\" target=\"_blank\" rel=\"noreferrer noopener\">sign up<\/a>. See Free-tier under <a href=\"https:\/\/valohai.com\/pricing\/\" target=\"_blank\" rel=\"noreferrer noopener\">Plans and Pricing<\/a> and the comparison chart for more details. For what we would like to do, the Free-tier is more than enough for now.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"864d\">Deep Learning for Java and Valohai<\/h1>\n\n\n\n<p>As\n we agreed, we\u2019re going to use these two technologies to achieve our \ngoal of training a single layer model and evaluating it, as well as \nseeing what the end-to-end experience is like on <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a>.<\/p>\n\n\n\n<p>We\n will bundle the necessary build and run-time dependencies into the \nDocker image and use it to build our Java app, train a model and \nevaluate it on the <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a> platform via a simple <a href=\"https:\/\/github.com\/valohai\/mlpmnist-dl4j-example\/blob\/master\/valohai.yaml\" target=\"_blank\" rel=\"noreferrer noopener\">valohai.yaml<\/a> file which is placed in the root folder of the project repository.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"92da\">Deep Learning for Java: DL4J<\/h1>\n\n\n\n<p>The\n easy part is, we won\u2019t need to do much here, just build the jar and \ndownload the dataset into the Docker container. We have a pre-built \nDocker image that contains all the dependencies needed to build a Java \napp. We have pushed this image into <a href=\"https:\/\/hub.docker.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Docker Hub<\/a>, you can find it by searching for <a href=\"https:\/\/hub.docker.com\/r\/neomatrix369\/dl4j-mnist-single-layer\" target=\"_blank\" rel=\"noreferrer noopener\">dl4j-mnist-single-layer<\/a> (we will be using a specific tag as defined in the YAML file). We have chosen to use <a href=\"https:\/\/github.com\/oracle\/graal\" target=\"_blank\" rel=\"noreferrer noopener\">GraalVM 19.1.1<\/a> as our Java build and runtime for this project, and so it is embedded into the Docker image (see <a href=\"https:\/\/github.com\/valohai\/mlpmnist-dl4j-example\/blob\/master\/Dockerfile\" target=\"_blank\" rel=\"noreferrer noopener\">Dockerfile<\/a> for the definition of the Docker image). To learn more about GraalVM check out the resources at the official site of <a href=\"https:\/\/www.graalvm.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">graalvm.org<\/a> and <a href=\"https:\/\/github.com\/neomatrix369\/awesome-graal\" target=\"_blank\" rel=\"noreferrer noopener\">Awesome Graal<\/a>.<\/p>\n\n\n\n<p><strong>Orchestration<\/strong><\/p>\n\n\n\n<p>When the uber jar is invoked from the command-line, we land into the <code>MLPMnistSingleLayerRunner<\/code> class which directs us to the intended action depending on the parameters passed in:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public static void main(String[] args) throws Exception {\n    MLPMnistSingleLayerRunner mlpMnistRunner = new MLPMnistSingleLayerRunner();\n\n    JCommander.newBuilder()\n            .addObject(mlpMnistRunner)\n            .build()\n            .parse(args);\n\n    mlpMnistRunner.execute();\n}<\/code><\/pre>\n\n\n\n<p>The parameters passed into the uber jar are received by this class and handled by the <code>execute()<\/code> method.<\/p>\n\n\n\n<p>We can create a model via the <code>--action train<\/code> parameter and evaluate the created model via the <code>--action evaluate<\/code> parameter respectively passed to the Java app (uber jar).<\/p>\n\n\n\n<p>The main parts of the Java app that does this work can be found in the two Java classes mentioned in the sections below.<\/p>\n\n\n\n<p><strong>Train a model<\/strong><\/p>\n\n\n\n<p>Can be invoked from the command-line via:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/runMLPMnist.sh --action train --output-dir ${VH_OUTPUTS_DIR}\n\nor\n\njava -Djava.library.path=\"\"             \\\n     -jar target\/MLPMnist-1.0.0-bin.jar \\\n     --action train --output-dir ${VH_OUTPUTS_DIR}<\/code><\/pre>\n\n\n\n<p>This creates the model (when successful, at the end of the execution) by the name <code>mlpmnist-single-layer.pb<\/code> in the folder specified by the <code>--output-dir<\/code> passed in at the beginning of the execution. From the perspective of <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a>, it should be placed into the ${VH_OUTPUTS_DIR} which is what we do (see <a href=\"https:\/\/github.com\/valohai\/mlpmnist-dl4j-example\/blob\/master\/valohai.yaml\" target=\"_blank\" rel=\"noreferrer noopener\">valohai.yaml<\/a> file).<\/p>\n\n\n\n<p>For source code, see class <a href=\"https:\/\/github.com\/valohai\/mlpmnist-dl4j-example\/blob\/master\/src\/main\/java\/org\/deeplearning4j\/feedforward\/mnist\/MLPMnistSingleLayerTrain.java\" target=\"_blank\" rel=\"noreferrer noopener\">MLPMNistSingleLayerTrain.java<\/a>.<\/p>\n\n\n\n<p><strong>Evaluate a model<\/strong><\/p>\n\n\n\n<p>Can be invoked from the command-line via:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/runMLPMnist.sh --action evaluate --input-dir ${VH_INPUTS_DIR}\/model\n\nor\n\njava -Djava.library.path=\"\"             \\\n     -jar target\/MLPMnist-1.0.0-bin.jar \\\n     --action evaluate --input-dir ${VH_INPUTS_DIR}\/model<\/code><\/pre>\n\n\n\n<p>This expects a model (created by the training step) by the name <code>mlpmnist-single-layer.pb<\/code> to be present in the folder specified by the <code>--input-dir<\/code> passed in when the app has been called.<\/p>\n\n\n\n<p>For source code, see class <a href=\"https:\/\/github.com\/valohai\/mlpmnist-dl4j-example\/blob\/master\/src\/main\/java\/org\/deeplearning4j\/feedforward\/mnist\/MLPMnistSingleLayerEvaluate.java\" target=\"_blank\" rel=\"noreferrer noopener\">MLPMNistSingleLayerEvaluate.java<\/a>.<\/p>\n\n\n\n<p>I hope this short illustration makes it clear how the Java app that trains and evaluates the model works in general.<\/p>\n\n\n\n<p>That\u2019s all is needed of us, but feel free to play with the rest of the <a href=\"https:\/\/github.com\/valohai\/mlpmnist-dl4j-example\" target=\"_blank\" rel=\"noreferrer noopener\">source<\/a> (along with the <a href=\"https:\/\/github.com\/valohai\/mlpmnist-dl4j-example#mlpmnist-dl4j-example-mlpmnist-single-layer-\" target=\"_blank\" rel=\"noreferrer noopener\">README.md<\/a>\n and bash scripts) and satisfy your curiosity and understanding on how \nthis is done! Further resources on how to use DL4J has been provided in \nthe <strong>Resources<\/strong> section at the end of the post.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"fe5d\">Valohai<\/h1>\n\n\n\n<p><a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a>\n as a platform allows us to loosely couple our runtime environment, our \ncode, and our dataset, as you can see from the structure of the YAML \nfile below. That way the different components can evolve independently \nwithout impeding or being dependent on one another. Hence our Docker \ncontainer only has the build and runtime time components packed into it.\n At execution time we build the uber jar in the Docker container, upload\n it to some internal or external storage, and then via another execution\n step download the uber jar and dataset from storage (or another \nlocation) to run the training. This way the two execution steps are \ndecoupled; we can e.g. build the jar once and run hundreds of training \nsteps on the same jar. As the build and runtime environments should not \nchange that often we can cache them and the code, dataset and model \nsources can be made dynamically available during execution time.<\/p>\n\n\n\n<p><a href=\"https:\/\/docs.valohai.com\/valohai-yaml\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>valohai.yaml<\/strong><\/a><\/p>\n\n\n\n<p>The heart of integrating our Java project with the <a rel=\"noreferrer noopener\" href=\"https:\/\/valohai.com\/\" target=\"_blank\">Valohai<\/a> infrastructure is defining the steps of <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.valohai.com\/core-concepts\/executions.html\" target=\"_blank\">execution<\/a> of the steps in the <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.valohai.com\/valohai-yaml\/index.html\" target=\"_blank\">valohai.yaml<\/a> file placed in the root of your project folder. Our <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/valohai\/mlpmnist-dl4j-example\/blob\/master\/valohai.yaml\" target=\"_blank\">valohai.yaml<\/a> looks like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n---\n\n- step:\n    name: Build-dl4j-mnist-single-layer-java-app\n    image: neomatrix369\/dl4j-mnist-single-layer:v0.5\n    command:\n      - cd ${VH_REPOSITORY_DIR}\n      - .\/buildUberJar.sh\n      - echo &quot;~~~ Copying the build jar file into ${VH_OUTPUTS_DIR}&quot;\n      - cp target\/MLPMnist-1.0.0-bin.jar ${VH_OUTPUTS_DIR}\/MLPMnist-1.0.0.jar\n      - ls -lash ${VH_OUTPUTS_DIR}\n    environment: aws-eu-west-1-g2-2xlarge\n- step:\n    name: Run-dl4j-mnist-single-layer-train-model\n    image: neomatrix369\/dl4j-mnist-single-layer:v0.5\n    command:\n      - echo &quot;~~~ Unpack the MNist dataset into ${HOME} folder&quot;\n      - tar xvzf ${VH_INPUTS_DIR}\/dataset\/mlp-mnist-dataset.tgz -C ${HOME}\n      - cd ${VH_REPOSITORY_DIR}\n      - echo &quot;~~~ Copying the build jar file from ${VH_INPUTS_DIR} to current location&quot;\n      - cp ${VH_INPUTS_DIR}\/dl4j-java-app\/MLPMnist-1.0.0.jar .\n      - echo &quot;~~~ Run the DL4J app to train model based on the the MNist dataset&quot;\n      - .\/runMLPMnist.sh {parameters}\n    inputs:\n      - name: dl4j-java-app\n        description: DL4J Java app file (jar) generated in the previous step 'Build-dl4j-mnist-single-layer-java-app'\n      - name: dataset\n        default: https:\/\/github.com\/neomatrix369\/awesome-ai-ml-dl\/releases\/download\/mnist-dataset-v0.1\/mlp-mnist-dataset.tgz\n        description: MNist dataset needed to train the model\n    parameters:\n      - name: --action\n        pass-as: '--action {v}'\n        type: string\n        default: train\n        description: Action to perform i.e. train or evaluate\n      - name: --output-dir\n        pass-as: '--output-dir {v}'\n        type: string\n        default: \/valohai\/outputs\/\n        description: Output directory where the model will be created, best to pick the Valohai output directory\n    environment: aws-eu-west-1-g2-2xlarge\n\n- step:\n    name: Run-dl4j-mnist-single-layer-evaluate-model\n    image: neomatrix369\/dl4j-mnist-single-layer:v0.5\n    command:\n      - cd ${VH_REPOSITORY_DIR}\n      - echo &quot;~~~ Copying the build jar file from ${VH_INPUTS_DIR} to current location&quot;\n      - cp ${VH_INPUTS_DIR}\/dl4j-java-app\/MLPMnist-1.0.0.jar .\n      - echo &quot;~~~ Run the DL4J app to evaluate the trained MNist model&quot;\n      - .\/runMLPMnist.sh {parameters}\n    inputs:\n      - name: dl4j-java-app\n        description: DL4J Java app file (jar) generated in the previous step 'Build-dl4j-mnist-single-layer-java-app'    \n      - name: model\n        description: Model file generated in the previous step 'Run-dl4j-mnist-single-layer-train-model'\n    parameters:\n      - name: --action\n        pass-as: '--action {v}'\n        type: string\n        default: evaluate\n        description: Action to perform i.e. train or evaluate\n      - name: --input-dir\n        pass-as: '--input-dir {v}'\n        type: string\n        default: \/valohai\/inputs\/model\n        description: Input directory where the model created by the previous step can be found created\n    environment: aws-eu-west-1-g2-2xlarge\n<\/pre><\/div>\n\n\n<p><strong>Explanation of the step Build-dl4j-mnist-single-layer-java-app<\/strong><\/p>\n\n\n\n<p>From\n the YAML file, we can see that we define this step by first using the \nDocker image and then run the build script to build the uber jar. Our \ndocker image has the build environment dependencies setup (i.e. GraalVM \nJDK, Maven, etc\u2026) to build a Java app. We do not specify any inputs or \nparameters as this is the build step. Once the build will be successful \nwe want to copy the uber jar called <code>MLPMnist-1.0.0-bin.jar<\/code> (original name) to the <code>\/valohai\/outputs<\/code> folder (represented by <code>${VH_OUTPUTS_DIR}<\/code>).\n Everything within this folder automatically gets persisted within your \nproject&#8217;s storage, e.g. an AWS S3 bucket. Finally, we define our job to \nrun in the AWS environment.<\/p>\n\n\n\n<p>Note: <em>The <\/em><a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\"><em>Valohai<\/em><\/a><em>\n free tier does not have network access from inside the Docker container\n (this is disabled by default), please contact support to enable this \noption (I had to do the same), or else we cannot download our Maven and \nother dependencies during build time.<\/em><\/p>\n\n\n\n<p><strong>Explanation of the step Run-dl4j-mnist-single-layer-train-model<\/strong><\/p>\n\n\n\n<p>The semantics of the definition is similar to the previous step except we specify two inputs one for the uber jar (<code>MLPMnist-1.0.0.jar<\/code>) and the other for the dataset (to be unpacked into the<code>${HOME}\/.deeplearning4j<\/code> folder). We will be passing the two parameters <code>--action train<\/code> and <code>--output-dir \/valohai\/outputs<\/code>. The model created from this step is collected into the <code>\/valohai\/outputs\/model<\/code> folder (represented by <code>${VH_OUTPUTS_DIR}\/model<\/code>).<\/p>\n\n\n\n<p>Note: <em>In\n the Input fields in the Executions tab of the Valohai Web UI, we can \nselect the outputs from previous executions by using the execution \nnumber i.e. <\/em><code><em>#1<\/em><\/code><em> or <\/em><code><em>#2<\/em><\/code><em>\n , in addition to using datum:\/\/ or http:\/\/ URLs. Typing in the few \nletters of the name of the file also helps search through the whole \nlist.<\/em><\/p>\n\n\n\n<p><strong>Explanation of the step Run-dl4j-mnist-single-layer-evaluate-model<\/strong><\/p>\n\n\n\n<p>Again, this step is similar to the previous step, except that we will be passing in the two parameters <code>--action evaluate<\/code> and <code>--input-dir \/valohai\/inputs\/model<\/code>. Also, we have again specified two <code>inputs:<\/code> sections defined in the YAML file called <code>dl4j-java-app<\/code> and <code>model<\/code> with no <code>default<\/code>\n set for both of them. This will allow us to select the uber jar and the\n model we wish to evaluate &#8211; that was created by the step <strong>Run-dl4j-mnist-single-layer-train-model<\/strong>, using the web interface.<\/p>\n\n\n\n<p>Hope\n this explains the steps in the above definition file but if you require\n further help, please do not hesitate to look at the <a href=\"https:\/\/docs.valohai.com\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\">docs<\/a> and <a href=\"https:\/\/docs.valohai.com\/tutorials\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\">tutorials<\/a>.<\/p>\n\n\n\n<p>Once we have an account, we can <a href=\"https:\/\/app.valohai.com\/accounts\/login\/\" target=\"_blank\" rel=\"noreferrer noopener\">sign-in<\/a> and continue with creating a project by the name <code>mlpmnist-single-layer<\/code> and link the git repo <a href=\"https:\/\/github.com\/valohai\/mlpmnist-dl4j-example\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/valohai\/mlpmnist-dl4j-example<\/a> to the project and save the project, have a quick look at the tutorials to see <a href=\"https:\/\/docs.valohai.com\/tutorials\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\">how to create a project using the web interface<\/a>.<\/p>\n\n\n\n<p>Now you can execute a step and see how it pans out!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"7ec0\">Building the DL4J Java app step<\/h2>\n\n\n\n<p>Go to the <strong>Executions<\/strong> tab in the web interface, either copy an existing or create a new execution using the <strong>[Create execution]<\/strong> button, all the necessary default options will be populated, select Step <strong>Build-dl4j-mnist-single-layer-java-app.<\/strong><\/p>\n\n\n\n<p>For <em>Environment<\/em> I would select <em>AWS eu-west-1 g2.2xlarge<\/em> and click on the <strong>[Create execution]<\/strong> button at the bottom of the page, to see the execution kick-off.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/miro.medium.com\/max\/1274\/0%2A7t0fjo-_p-Doo09u.png?w=600&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"69fc\">Training the model step<\/h2>\n\n\n\n<p>Go to the <strong>Executions<\/strong> tab in the web interface, and do the same as the previous step and select Step <strong>Run-dl4j-mnist-single-layer-train-model<\/strong>.  You will have to select the Java app (just type jar in the field) built  in the previous step, the dataset has already been pre-populated via  the <strong>valohai.yaml<\/strong> file:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/miro.medium.com\/max\/1220\/0%2ACyy14Lb8JSfJZrdz.png?w=600&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>Click on<strong> [Create execution]<\/strong> to kick off this step.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/miro.medium.com\/max\/1272\/0%2AA8BZUz7_k5MG371Y.png?w=600&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>You will see the model summary fly by in the log console:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[&lt;--- snipped --->]\n11:17:05 =========================================================================\n11:17:05 LayerName (LayerType) nIn,nOut TotalParams ParamsShape\n11:17:05 =========================================================================\n11:17:05 layer0 (DenseLayer) 784,1000 785000 W:{784,1000}, b:{1,1000}\n11:17:05 layer1 (OutputLayer) 1000,10 10010 W:{1000,10}, b:{1,10}\n11:17:05 -------------------------------------------------------------------------\n11:17:05  Total Parameters: 795010\n11:17:05  Trainable Parameters: 795010\n11:17:05  Frozen Parameters: 0\n11:17:05 =========================================================================\n[&lt;--- snipped --->]<\/code><\/pre>\n\n\n\n<p>The models created can be found under the <strong>Outputs<\/strong> sub-tab in the <strong>Executions<\/strong> main tab, during and at the end of the execution:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/miro.medium.com\/max\/1271\/0%2AMgtDO7qLplEnTAVS.png?w=600&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>You might have noticed several artifacts in the <strong>Outputs<\/strong> sub-tab. That\u2019s because we save a checkpoint at the end of each epoch! Look out for these in the execution logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[&lt;--- snipped --->]\n11:17:14 o.d.o.l.CheckpointListener - Model checkpoint saved: epoch 0, iteration 469, path: \/valohai\/outputs\/checkpoint_0_MultiLayerNetwork.zip\n[&lt;--- snipped --->]<\/code><\/pre>\n\n\n\n<p>The checkpoint zip contains the state of the model training at that point, saved in three of these files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>configuration.json\ncoefficients.bin\nupdaterState.bin<\/code><\/pre>\n\n\n\n<p><strong>Training the model &gt; Metadata<\/strong><\/p>\n\n\n\n<p>You might have noticed these notations fly by in the execution logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[&lt;--- snipped --->]\n11:17:05 {\"epoch\": 0, \"iteration\": 0, \"score (loss function)\": 2.410047}\n11:17:07 {\"epoch\": 0, \"iteration\": 100, \"score (loss function)\": 0.613774}\n11:17:09 {\"epoch\": 0, \"iteration\": 200, \"score (loss function)\": 0.528494}\n11:17:11 {\"epoch\": 0, \"iteration\": 300, \"score (loss function)\": 0.400291}\n11:17:13 {\"epoch\": 0, \"iteration\": 400, \"score (loss function)\": 0.357800}\n11:17:14 o.d.o.l.CheckpointListener - Model checkpoint saved: epoch 0, iteration 469, path: \/valohai\/outputs\/checkpoint_0_MultiLayerNetwork.zip\n[&lt;--- snipped --->]<\/code><\/pre>\n\n\n\n<p>These notations trigger <a rel=\"noreferrer noopener\" href=\"https:\/\/valohai.com\/\" target=\"_blank\">Valohai<\/a>  to pickup these values (in JSON format) to be used to plot execution  metrics, which can be seen during and after the execution under the <strong>Metadata<\/strong> sub-tab in the <strong>Executions<\/strong> main tab:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/miro.medium.com\/max\/1269\/0%2ASwM_Lc3efuH7h_9P.png?w=600&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>We were able to do this by hooking a listener class (called <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/neomatrix369\/awesome-ai-ml-dl\/blob\/master\/examples\/cloud-devops-infra\/valohai\/MLPMnist\/src\/main\/java\/org\/deeplearning4j\/feedforward\/mnist\/ValohaiMetadataCreator.java\" target=\"_blank\">ValohaiMetadataCreator<\/a>)  into the model, such that during training attention is passed on to  this listener class at the end of each iteration. In the case of this  class, we print the <strong>epoch count<\/strong>, <strong>iteration count<\/strong> and <strong>the score (the loss function value)<\/strong>, here is a code snippet from the class:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    public void iterationDone(Model model, int iteration, int epoch) {\n        if (printIterations &amp;lt;= 0)\n            printIterations = 1;\n        if (iteration % printIterations == 0) {\n            double score = model.score();\n            System.out.println(String.format(\n                    &quot;{\\&quot;epoch\\&quot;: %d, \\&quot;iteration\\&quot;: %d, \\&quot;score (loss function)\\&quot;: %f}&quot;,\n                    epoch,\n                    iteration,\n                    score)\n            );\n        }\n    }\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"028a\">Evaluating the model step<\/h2>\n\n\n\n<p>Once  the model has been successfully created via the previous step, we are  ready to evaluate it. We create a new execution just like we did  previously but this time select the <strong>Run-dl4j-mnist-single-layer-evaluate-model<\/strong> step. We will need to select the Java app (<strong>MLPMnist-1.0.0.jar<\/strong>) again and the created model (<strong>mlpmnist-single-layer.pb<\/strong>) before kicking off the execution (as shown below):<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/miro.medium.com\/max\/1270\/0%2AX9kILtQUEgZtY-91.png?w=600&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>After selecting the desired model as input, click on the <strong>[Create execution]<\/strong> button. It is a quicker execution step than the previous one and we will see the following output:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/miro.medium.com\/max\/1218\/0%2Aazaua3UlAyVkPSPX.png?w=600&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>The <strong>Evaluation Metrics<\/strong> and <strong>Confusion Matrix<\/strong> post model analysis will be displayed in the console logs.<\/p>\n\n\n\n<p>We can see our training activity has resulted in the model that is near <strong>97%<\/strong> accurate <em>based on the test dataset<\/em>.\n The confusion matrix helps point out the instances a digit has been \nincorrectly predicted as another digit. Maybe this is good feedback to \nthe creator of the model and maintainer of the dataset to do some \nfurther investigations.<\/p>\n\n\n\n<p>The question remains (and is outside the scope of this post) \u2014 how good is the model when faced with <em>real-world data<\/em>?<\/p>\n\n\n\n<p>It\u2019s easy to install and get started with the CLI tool, see <a href=\"https:\/\/docs.valohai.com\/valohai-cli\/installation.html?highlight=cli\" target=\"_blank\" rel=\"noreferrer noopener\">Command-line Usage<\/a>.<\/p>\n\n\n\n<p>If you haven\u2019t yet cloned the git repository then here\u2019s what to do:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ git clone <a href=\"https:\/\/github.com\/valohai\/mlpmnist-dl4j-example\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/valohai\/mlpmnist-dl4j-example<\/a><\/pre>\n\n\n\n<p>We then need to link our <a rel=\"noreferrer noopener\" href=\"https:\/\/valohai.com\/\" target=\"_blank\">Valohai<\/a>  project created via the web interface in the above section to the  project stored on our local machine (the one we just cloned). Run the  below commands to do that:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ cd mlpmnist-dl4j-example\n$ vh project --help   ### to see all the project-specific options we have for Valohai\n$ vh project link <\/code><\/pre>\n\n\n\n<p>You will be shown something like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[  1] mlpmnist-single-layer\n...\nWhich project would you like to link with \/path\/to\/mlpmnist-dl4j-example?\nEnter [n] to create a new project.:<\/code><\/pre>\n\n\n\n<p>Select 1 (or the selection appropriate for you) and you should see this message:<\/p>\n\n\n\n<p><code>\ud83d\ude01 Success! Linked \/path\/to\/mlpmnist-dl4j-example to mlpmnist-single-layer.<\/code><\/p>\n\n\n\n<p>The quickest way to know of all the CLI options with the CLI tool is:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ vh \u2014 help<\/pre>\n\n\n\n<p>One more thing, before going any further ensure that your <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a> project is in sync with the latest git project, by doing this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ vh project fetch<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/miro.medium.com\/max\/1279\/0%2A9b0OmE6SelZXsvZ6.png?w=600&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>(on the top right side in your web interface, shown with the two-arrows-pointing-to-each-other icon).<\/p>\n\n\n\n<p>Now we can execute the steps from the CLI with:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ vh exec run Build-dl4j-mnist-single-layer-java-app<\/pre>\n\n\n\n<p>Once the execution is on, we can inspect and monitor it via:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ vh exec info\n$ vh exec logs\n$ vh exec watch<\/code><\/pre>\n\n\n\n<p>We can also see the above updates via the web interface at the same time.<\/p>\n\n\n\n<p>Further resources on how to go about with <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a>\n has been provided in the Resources section at the end of the post, \nthere are a couple of blog posts on how to use the CLI tool, see <a href=\"https:\/\/blog.valohai.com\/from-zero-to-hero-with-valohai-cli\" target=\"_blank\" rel=\"noreferrer noopener\">[1]<\/a> | <a href=\"https:\/\/blog.valohai.com\/from-zero-to-hero-with-valohai-part-2\" target=\"_blank\" rel=\"noreferrer noopener\">[2]<\/a>.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"8346\">Conclusion<\/h1>\n\n\n\n<p>As you have seen both <a href=\"https:\/\/deeplearning4j.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">DL4J<\/a> and <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a>\n individually or combined are fairly easy to get started with. Further, \nwe can develop on the different components that make up our experiments \ni.e. build\/runtime environment, code, and dataset and integrate them \ninto an execution in a loosely coupled manner.<\/p>\n\n\n\n<p>The\n template examples used in this post are a good way to get started to \nbuild more complex projects. That you can use either the web interface \nor the CLI to get your job done with <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a>! With the CLI you can also integrate it with your setup and scripts (or even with CRON or CI\/CD jobs).<\/p>\n\n\n\n<p>Also, it\u2019s clear that if I\u2019m working on an AI\/ML\/DL related project <em>I don\u2019t need to concern myself with creating and maintaining<\/em> an end-to-end pipeline (which many others and I have had to do in the past) \u2014 thanks to the good work by the folks at <a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valohai<\/a>.<\/p>\n\n\n\n<p><em>Thanks to both <\/em><a href=\"https:\/\/skymind.ai\/\" target=\"_blank\" rel=\"noreferrer noopener\"><em>Skymind<\/em><\/a><em> (the startup behind <\/em><a href=\"https:\/\/deeplearning4j.org\/\" target=\"_blank\" rel=\"noreferrer noopener\"><em>DL4J<\/em><\/a><em>, for creating, maintaining and keeping free) and <\/em><a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\"><em>Valohai<\/em><\/a><em> for making this tool and cloud-service available for both free and commercial use.<\/em><\/p>\n\n\n\n<p><em>Please do let me know if this is helpful by dropping a line in the comments below or by tweeting at <\/em><a href=\"https:\/\/twitter.com\/theNeomatrix369\" target=\"_blank\" rel=\"noreferrer noopener\"><em>@theNeomatrix369<\/em><\/a><em>, and I would also welcome feedback.<\/em><\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"2b0e\">Resources<\/h1>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/valohai\/mlpmnist-dl4j-example\" target=\"_blank\" rel=\"noreferrer noopener\">mlpmnist-dl4j-examples project on GitHub<\/a><\/li><li><a href=\"https:\/\/github.com\/neomatrix369\/awesome-ai-ml-dl\/\" target=\"_blank\" rel=\"noreferrer noopener\">Awesome AI\/ML\/DL resources<\/a><\/li><li><a href=\"https:\/\/github.com\/neomatrix369\/awesome-ai-ml-dl\/blob\/master\/README-details.md#java\" target=\"_blank\" rel=\"noreferrer noopener\">Java AI\/ML\/DL resources<\/a><\/li><li><a href=\"https:\/\/github.com\/neomatrix369\/awesome-ai-ml-dl\/blob\/master\/README-details.md#deep-learning\" target=\"_blank\" rel=\"noreferrer noopener\">Deep Learning and DL4J Resources<\/a><\/li><\/ul>\n\n\n\n<p><strong>Additional DL4J resources<\/strong><\/p>\n\n\n\n<p>Loss functions<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/deeplearning4j.org\/api\/latest\/org\/nd4j\/linalg\/lossfunctions\/ILossFunction.html\" target=\"_blank\" rel=\"noreferrer noopener\">Loss function Interface by DL4J<\/a><\/li><li><a href=\"https:\/\/heartbeat.fritz.ai\/5-regression-loss-functions-all-machine-learners-should-know-4fb140e9d4b0\" target=\"_blank\" rel=\"noreferrer noopener\">5 Regression Loss Functions All Machine Learners Should Know<\/a><\/li><\/ul>\n\n\n\n<p>Evaluation<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/deeplearning4j.org\/docs\/latest\/deeplearning4j-nn-evaluation\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/deeplearning4j.org\/docs\/latest\/deeplearning4j-nn-evaluation<\/a><\/li><\/ul>\n\n\n\n<p><strong>Valohai resources<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">valohai <\/a>| <a href=\"https:\/\/docs.valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">docs<\/a> | <a href=\"https:\/\/blog.valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">blogs<\/a> | <a href=\"https:\/\/github.com\/valohai\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub<\/a> | <a href=\"https:\/\/www.youtube.com\/channel\/UCiR8Fpv6jRNphaZ99PnIuFg\" target=\"_blank\" rel=\"noreferrer noopener\">Videos<\/a> | <a href=\"https:\/\/valohai.com\/showcase\/\" target=\"_blank\" rel=\"noreferrer noopener\">Showcase<\/a> | <a href=\"https:\/\/github.com\/neomatrix369\/awesome-ai-ml-dl\/blob\/master\/data\/about-Valohai.md#valohai\" target=\"_blank\" rel=\"noreferrer noopener\">About Valohai<\/a> | <a href=\"http:\/\/community-slack.valohai.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Slack<\/a> | <a href=\"http:\/\/twitter.com\/valohaiai\" target=\"_blank\" rel=\"noreferrer noopener\">@valohaiai<\/a><\/li><li>Blog posts on how to use the CLI tool: <a href=\"https:\/\/blog.valohai.com\/from-zero-to-hero-with-valohai-cli\" target=\"_blank\" rel=\"noreferrer noopener\">[1]<\/a> | <a href=\"https:\/\/blog.valohai.com\/from-zero-to-hero-with-valohai-part-2\" target=\"_blank\" rel=\"noreferrer noopener\">[2]<\/a><\/li><\/ul>\n\n\n\n<p><strong>Other resources<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/neomatrix369\/awesome-graal\" target=\"_blank\" rel=\"noreferrer noopener\">Awesome Graal<\/a> | <a href=\"https:\/\/www.graalvm.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">graalvm.org<\/a><\/li><\/ul>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"7ba0\">Originally published at <a href=\"https:\/\/blog.valohai.com\/how-to-do-deep-learning-for-java-on-the-valohai-platform?from=3oxenia9mtr6\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/blog.valohai.com<\/a>.<\/h1>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Some time ago I came across this life-cycle management tool (or cloud service) called Valohai and I was quite impressed by its user-interface and simplicity of design and layout. I had a good chat about the service at that time with one of the members of Valohai and was given a demo. Previous to [&hellip;]<\/p>\n","protected":false},"author":30,"featured_media":1733,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[381,365,385,183,367,390,391,393,11,29,148,366,67],"tags":[378,418,406,400,419,260,401,293,251,262,413,422,425],"coauthors":[329],"class_list":["post-1731","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-christmas-2019-is-coming","category-artificial-intelligence","category-awesome-graal","category-cloud","category-deep-learning","category-docker","category-docker-image","category-graalvm","category-java","category-jdk","category-jdk-8","category-machine-learning","category-pipelines","tag-378","tag-artificial-intelligence","tag-awesome-graal","tag-cloud","tag-deep-learning","tag-docker","tag-docker-image","tag-graalvm","tag-java","tag-jdk","tag-jdk-8","tag-machine-learning","tag-pipelines"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>How to do Deep Learning for Java? - JVM Advent<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to do Deep Learning for Java? - JVM Advent\" \/>\n<meta property=\"og:description\" content=\"Introduction Some time ago I came across this life-cycle management tool (or cloud service) called Valohai and I was quite impressed by its user-interface and simplicity of design and layout. I had a good chat about the service at that time with one of the members of Valohai and was given a demo. Previous to [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html\" \/>\n<meta property=\"og:site_name\" content=\"JVM Advent\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Java-Advent-Calendar-229536173843473\/\" \/>\n<meta property=\"article:published_time\" content=\"2019-12-16T01:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javaadvent.com\/content\/uploads\/2019\/12\/Cover-image.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"960\" \/>\n\t<meta property=\"og:image:height\" content=\"720\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Mani Sarkar\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@http:\/\/www.twitter.com\/theNeomatrix369\" \/>\n<meta name=\"twitter:site\" content=\"@javaadvent\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mani Sarkar\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"17 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html\"},\"author\":{\"name\":\"Mani Sarkar\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#\\\/schema\\\/person\\\/ef90e14a50b57942fce9b7e0f30d84c6\"},\"headline\":\"How to do Deep Learning for Java?\",\"datePublished\":\"2019-12-16T01:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html\"},\"wordCount\":2789,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2019\\\/12\\\/Cover-image.jpg?fit=960%2C720&ssl=1\",\"keywords\":[\"2019\",\"Artificial Intelligence\",\"awesome graal\",\"Cloud\",\"Deep Learning\",\"docker\",\"Docker Image\",\"graalvm\",\"java\",\"jdk\",\"jdk 8\",\"machine learning\",\"pipelines\"],\"articleSection\":[\"2019\",\"Artificial Intelligence\",\"awesome graal\",\"Cloud\",\"Deep Learning\",\"Docker\",\"Docker Image\",\"graalvm\",\"java\",\"jdk\",\"jdk 8\",\"Machine Learning\",\"pipelines\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html\",\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html\",\"name\":\"How to do Deep Learning for Java? - JVM Advent\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2019\\\/12\\\/Cover-image.jpg?fit=960%2C720&ssl=1\",\"datePublished\":\"2019-12-16T01:00:00+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#\\\/schema\\\/person\\\/ef90e14a50b57942fce9b7e0f30d84c6\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2019\\\/12\\\/Cover-image.jpg?fit=960%2C720&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2019\\\/12\\\/Cover-image.jpg?fit=960%2C720&ssl=1\",\"width\":960,\"height\":720},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2019\\\/12\\\/how-to-do-deep-learning-for-java.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javaadvent.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to do Deep Learning for Java?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/\",\"name\":\"JVM Advent\",\"description\":\"The JVM Programming Advent Calendar\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javaadvent.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#\\\/schema\\\/person\\\/ef90e14a50b57942fce9b7e0f30d84c6\",\"name\":\"Mani Sarkar\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/44623d32b3dda3f364a89f2a8ea0043ce5d0bb089789b9682c1f00d2153a3243?s=96&d=retro&r=gb763b17d06410c1b9f4eaa6155c32585\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/44623d32b3dda3f364a89f2a8ea0043ce5d0bb089789b9682c1f00d2153a3243?s=96&d=retro&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/44623d32b3dda3f364a89f2a8ea0043ce5d0bb089789b9682c1f00d2153a3243?s=96&d=retro&r=g\",\"caption\":\"Mani Sarkar\"},\"description\":\"I have been posting articles on the Java Advent calendar for some years. A passionate developer mainly in the Java\\\/JVM space, based out of London, UK. A JCP Member, OpenJDK contributor, involved with LJC and other developer communities, @adoptopenjdk and other F\\\/OSS projects. Writes code, not just in Java\\\/JVM hence likes to call himself a polyglot developer. He sees himself working in the areas of core Java, JVM, JDK, Hotspot, Graal, GraalVM, Truffle, VMs, and Performance Tuning. An advocate of a number of agile and software craftsmanship practices and a regular at many talks, conferences and hands-on-workshops - speaks, participates, organises and helps out at many of them. Expresses his thoughts often via blog posts, microblogs (tweets) and other forms of social media. ----- Twitter: @theNeomatrix369 Slideshare: http:\\\/\\\/www.slideshare.net\\\/neomatrix369\\\/ -----\",\"sameAs\":[\"http:\\\/\\\/neomatrix369.wordpress.com\",\"http:\\\/\\\/uk.linkedin.com\\\/pub\\\/mani-sarkar\\\/71\\\/a77\\\/39b\",\"https:\\\/\\\/x.com\\\/http:\\\/\\\/www.twitter.com\\\/theNeomatrix369\"],\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/author\\\/mani_sarkar\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to do Deep Learning for Java? - JVM Advent","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html","og_locale":"en_US","og_type":"article","og_title":"How to do Deep Learning for Java? - JVM Advent","og_description":"Introduction Some time ago I came across this life-cycle management tool (or cloud service) called Valohai and I was quite impressed by its user-interface and simplicity of design and layout. I had a good chat about the service at that time with one of the members of Valohai and was given a demo. Previous to [&hellip;]","og_url":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html","og_site_name":"JVM Advent","article_publisher":"https:\/\/www.facebook.com\/Java-Advent-Calendar-229536173843473\/","article_published_time":"2019-12-16T01:00:00+00:00","og_image":[{"width":960,"height":720,"url":"https:\/\/www.javaadvent.com\/content\/uploads\/2019\/12\/Cover-image.jpg","type":"image\/jpeg"}],"author":"Mani Sarkar","twitter_card":"summary_large_image","twitter_creator":"@http:\/\/www.twitter.com\/theNeomatrix369","twitter_site":"@javaadvent","twitter_misc":{"Written by":"Mani Sarkar","Est. reading time":"17 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html#article","isPartOf":{"@id":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html"},"author":{"name":"Mani Sarkar","@id":"https:\/\/www.javaadvent.com\/#\/schema\/person\/ef90e14a50b57942fce9b7e0f30d84c6"},"headline":"How to do Deep Learning for Java?","datePublished":"2019-12-16T01:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html"},"wordCount":2789,"commentCount":0,"image":{"@id":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2019\/12\/Cover-image.jpg?fit=960%2C720&ssl=1","keywords":["2019","Artificial Intelligence","awesome graal","Cloud","Deep Learning","docker","Docker Image","graalvm","java","jdk","jdk 8","machine learning","pipelines"],"articleSection":["2019","Artificial Intelligence","awesome graal","Cloud","Deep Learning","Docker","Docker Image","graalvm","java","jdk","jdk 8","Machine Learning","pipelines"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html","url":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html","name":"How to do Deep Learning for Java? - JVM Advent","isPartOf":{"@id":"https:\/\/www.javaadvent.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html#primaryimage"},"image":{"@id":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2019\/12\/Cover-image.jpg?fit=960%2C720&ssl=1","datePublished":"2019-12-16T01:00:00+00:00","author":{"@id":"https:\/\/www.javaadvent.com\/#\/schema\/person\/ef90e14a50b57942fce9b7e0f30d84c6"},"breadcrumb":{"@id":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html#primaryimage","url":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2019\/12\/Cover-image.jpg?fit=960%2C720&ssl=1","contentUrl":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2019\/12\/Cover-image.jpg?fit=960%2C720&ssl=1","width":960,"height":720},{"@type":"BreadcrumbList","@id":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-do-deep-learning-for-java.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javaadvent.com\/"},{"@type":"ListItem","position":2,"name":"How to do Deep Learning for Java?"}]},{"@type":"WebSite","@id":"https:\/\/www.javaadvent.com\/#website","url":"https:\/\/www.javaadvent.com\/","name":"JVM Advent","description":"The JVM Programming Advent Calendar","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javaadvent.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.javaadvent.com\/#\/schema\/person\/ef90e14a50b57942fce9b7e0f30d84c6","name":"Mani Sarkar","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/44623d32b3dda3f364a89f2a8ea0043ce5d0bb089789b9682c1f00d2153a3243?s=96&d=retro&r=gb763b17d06410c1b9f4eaa6155c32585","url":"https:\/\/secure.gravatar.com\/avatar\/44623d32b3dda3f364a89f2a8ea0043ce5d0bb089789b9682c1f00d2153a3243?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/44623d32b3dda3f364a89f2a8ea0043ce5d0bb089789b9682c1f00d2153a3243?s=96&d=retro&r=g","caption":"Mani Sarkar"},"description":"I have been posting articles on the Java Advent calendar for some years. A passionate developer mainly in the Java\/JVM space, based out of London, UK. A JCP Member, OpenJDK contributor, involved with LJC and other developer communities, @adoptopenjdk and other F\/OSS projects. Writes code, not just in Java\/JVM hence likes to call himself a polyglot developer. He sees himself working in the areas of core Java, JVM, JDK, Hotspot, Graal, GraalVM, Truffle, VMs, and Performance Tuning. An advocate of a number of agile and software craftsmanship practices and a regular at many talks, conferences and hands-on-workshops - speaks, participates, organises and helps out at many of them. Expresses his thoughts often via blog posts, microblogs (tweets) and other forms of social media. ----- Twitter: @theNeomatrix369 Slideshare: http:\/\/www.slideshare.net\/neomatrix369\/ -----","sameAs":["http:\/\/neomatrix369.wordpress.com","http:\/\/uk.linkedin.com\/pub\/mani-sarkar\/71\/a77\/39b","https:\/\/x.com\/http:\/\/www.twitter.com\/theNeomatrix369"],"url":"https:\/\/www.javaadvent.com\/author\/mani_sarkar"}]}},"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2019\/12\/Cover-image.jpg?fit=960%2C720&ssl=1","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":1717,"url":"https:\/\/www.javaadvent.com\/2019\/12\/how-to-build-graal-enabled-jdk8-on-circleci.html","url_meta":{"origin":1731,"position":0},"title":"How to build Graal-enabled JDK8 on CircleCI?","author":"Mani Sarkar","date":"December 5, 2019","format":false,"excerpt":"Citation: feature image on the blog can be found on flickr and created by Luca Galli. The image in one of the below sections can be also found on flickr and created by fklv (Obsolete hipster). The GraalVM compiler is a replacement to HotSpot\u2019s server-side JIT compiler widely known as\u2026","rel":"","context":"In &quot;2019&quot;","block_context":{"text":"2019","link":"https:\/\/www.javaadvent.com\/category\/christmas-2019-is-coming"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2018\/12\/graal.jpg?fit=717%2C444&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2018\/12\/graal.jpg?fit=717%2C444&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2018\/12\/graal.jpg?fit=717%2C444&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2018\/12\/graal.jpg?fit=717%2C444&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":2212,"url":"https:\/\/www.javaadvent.com\/2019\/12\/exploring-nlp-concepts-using-apache-opennlp-inside-a-java-enabled-jupyter-notebook.html","url_meta":{"origin":1731,"position":1},"title":"Exploring NLP concepts using Apache OpenNLP inside a Java-enabled Jupyter notebook","author":"Mani Sarkar","date":"December 23, 2019","format":false,"excerpt":"Introduction I have been exploring and playing around with the\u00a0Apache OpenNLP\u00a0library after a bit of convincing. For those who are not aware of it, it\u2019s an\u00a0Apache\u00a0project, supporters of F\/OSS Java projects for the last two decades or so (see\u00a0Wikipedia). I found their command-line interface pretty simple to use and it\u2026","rel":"","context":"In &quot;2019&quot;","block_context":{"text":"2019","link":"https:\/\/www.javaadvent.com\/category\/christmas-2019-is-coming"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2019\/12\/cover-page-jupiter.jpg?fit=500%2C500&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1737,"url":"https:\/\/www.javaadvent.com\/2019\/12\/applying-nlp-in-java-all-from-the-command-line.html","url_meta":{"origin":1731,"position":2},"title":"Applying NLP in Java, all from the command-line","author":"Mani Sarkar","date":"December 18, 2019","format":false,"excerpt":"Introduction We are all aware of Machine Learning tools and cloud services that work via the browser and give us an interface we can use to perform our day-to-day data analysis, model training, and evaluation, and other tasks to various degrees of efficiencies. But what would you do if you\u2026","rel":"","context":"In &quot;2019&quot;","block_context":{"text":"2019","link":"https:\/\/www.javaadvent.com\/category\/christmas-2019-is-coming"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2019\/11\/nlp-post-feature-image-smaller.jpeg?fit=675%2C1200&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2019\/11\/nlp-post-feature-image-smaller.jpeg?fit=675%2C1200&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2019\/11\/nlp-post-feature-image-smaller.jpeg?fit=675%2C1200&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":1626,"url":"https:\/\/www.javaadvent.com\/2018\/12\/apache-zeppelin-stairway-to-notes-haven.html","url_meta":{"origin":1731,"position":3},"title":"Apache Zeppelin: stairway to notes* haven!","author":"Mani Sarkar","date":"December 15, 2018","format":false,"excerpt":"*notes is for notebooks in Zeppelin lingo Introduction Continuing from the previous post, Two years in the life of AI, ML, DL and Java, where I had expressed my motivation. I mentioned our discussions, one of the discussions was, that you can write in languages like Python, R, Julia in\u2026","rel":"","context":"In &quot;2018&quot;","block_context":{"text":"2018","link":"https:\/\/www.javaadvent.com\/category\/2018"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1362,"url":"https:\/\/www.javaadvent.com\/2018\/12\/docker-and-the-jvm.html","url_meta":{"origin":1731,"position":4},"title":"Docker and the JVM","author":"Cesar Tron-Lozai","date":"December 7, 2018","format":false,"excerpt":"Even though Docker was a 2016 thing, it is still relevant today. It is the foundation of Kubernetes, the most popular Orchestration platform, that has become the go-to solution for cloud deployment. Docker is the defacto standard solution to containerise applications\/(micro)services. If you run Java application you need to beaware\u2026","rel":"","context":"In &quot;2018&quot;","block_context":{"text":"2018","link":"https:\/\/www.javaadvent.com\/category\/2018"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2018\/12\/image-300x161.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":1744,"url":"https:\/\/www.javaadvent.com\/2019\/12\/exploring-nlp-concepts-using-apache-opennlp.html","url_meta":{"origin":1731,"position":5},"title":"Exploring NLP concepts using Apache OpenNLP","author":"Mani Sarkar","date":"December 21, 2019","format":false,"excerpt":"Introduction After looking at a lot of Java\/JVM based NLP libraries listed on Awesome AI\/ML\/DL I decided to pick the Apache OpenNLP library. One of the reasons comes from the fact another developer (who had a look at it previously) recommended it. Besides, it\u2019s an Apache project, they have been\u2026","rel":"","context":"In &quot;2019&quot;","block_context":{"text":"2019","link":"https:\/\/www.javaadvent.com\/category\/christmas-2019-is-coming"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2019\/11\/cover-page-open.jpeg?fit=500%2C333&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]}],"jetpack_likes_enabled":true,"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts\/1731","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/users\/30"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/comments?post=1731"}],"version-history":[{"count":2,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts\/1731\/revisions"}],"predecessor-version":[{"id":1734,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts\/1731\/revisions\/1734"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/media\/1733"}],"wp:attachment":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/media?parent=1731"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/categories?post=1731"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/tags?post=1731"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/coauthors?post=1731"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}