今回の目標は、スタンドアロンのDeep Learning JAVAファイルを生成することである。
DL4jのビルドに悪戦苦闘の週末を過ごす。結果、壁をなんとか乗り越えた。
以下、取り組んだ課題の整理をしておく。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
I. Maven pom.xml
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
pomは、Project Object Modelの意味であり、Apache Mavenで処理されるプロジェクトに関する情報を持つ重要なファイルであり、成果物作成に必要となる対象となる処理ファイルは、すべてsrcフォルダ以下の階層構造に置かれる。このpom.xmlのXML記述そのものが、Mavenに管理されるプログラムのコンパイル/ビルドの仕様である。逆に言えば、ライブラリーのリンクなど、複雑なプログラムの構築については、このpom.xmlファイルさえ、やり取りすればそれで良いということを意味する。したがってpom.xmlを大雑把にも理解する必要がある。
DeepLearning4JのExamplesのpom.xmLを覗いてみよう。日本語コメントを付記しておく。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>dl4j-examples</artifactId> <parent> //上位フォルダにあるはずの親POM.XMLの定義。以下${}で変数処理されている部分は、この上位のpom.xmlで定義されている。 <groupId>org.deeplearning4j</groupId> <artifactId>oreilly-book-deeplearning4j-examples-parent</artifactId> <version>0.7-SNAPSHOT</version> </parent> <name>DeepLearning4j Examples</name> <repositories> <repository> <id>snapshots-repo</id> <url>https://oss.sonatype.org/content/repositories/snapshots</url> <releases> <enabled>false</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> <distributionManagement> <snapshotRepository> <id>sonatype-nexus-snapshots</id> <name>Sonatype Nexus snapshot repository</name> <url>https://oss.sonatype.org/content/repositories/snapshots</url> </snapshotRepository> <repository> <id>nexus-releases</id> <name>Nexus Release Repository</name> <url>http://oss.sonatype.org/service/local/staging/deploy/maven2/</url> </repository> </distributionManagement> <dependencyManagement> <dependencies> <dependency> <groupId>org.nd4j</groupId> <artifactId>nd4j-native-platform</artifactId> <version>${nd4j.version}</version> </dependency> <dependency> <groupId>org.nd4j</groupId> <artifactId>nd4j-cuda-7.5-platform</artifactId> <version>${nd4j.version}</version> </dependency> <dependency> <groupId>org.nd4j</groupId> <artifactId>nd4j-cuda-8.0-platform</artifactId> <version>${nd4j.version}</version> </dependency> </dependencies> </dependencyManagement> <dependencies> //依存関係にあるライブラリーの記述 <!-- ND4J backend. You need one in every DL4J project. Normally define artifactId as either "nd4j-native-platform" or "nd4j-cuda-7.5-platform" --> <dependency> <groupId>org.nd4j</groupId> //DL4Jのライブラリ <artifactId>${nd4j.backend}</artifactId> //${nd4j.backend}は上位からでここでは0.7.2に置き換えられる。 </dependency> <!-- Core DL4J functionality --> <dependency> <groupId>org.deeplearning4j</groupId> //DL4Jのコアライブラリ <artifactId>deeplearning4j-core</artifactId> <version>${dl4j.version}</version> </dependency> <dependency> <groupId>org.deeplearning4j</groupId> <artifactId>deeplearning4j-nlp</artifactId> <version>${dl4j.version}</version> </dependency> <!-- deeplearning4j-ui is used for HistogramIterationListener + visualization: see http://deeplearning4j.org/visualization --> <dependency> <groupId>org.deeplearning4j</groupId> <artifactId>deeplearning4j-ui_2.10</artifactId> <version>${dl4j.version}</version> </dependency> <!-- Force guava versions for using UI/HistogramIterationListener --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>${guava.version}</version> </dependency> <!-- datavec-data-codec: used only in video example for loading video data --> <dependency> <artifactId>datavec-data-codec</artifactId> <groupId>org.datavec</groupId> <version>${datavec.version}</version> </dependency> <!-- Used in the feedforward/classification/MLP* and feedforward/regression/RegressionMathFunctions example --> <dependency> <groupId>jfree</groupId> <artifactId>jfreechart</artifactId> <version>${jfreechart.version}</version> </dependency> <dependency> <groupId>org.jfree</groupId> <artifactId>jcommon</artifactId> <version>${jcommon.version}</version> </dependency> <!-- Used for downloading data in some of the examples --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.3.5</version> </dependency> </dependencies> <build> <plugins> //プラグイン <plugin> <groupId>org.codehaus.mojo</groupId> //実行型の生成物を生成するプラグイン <artifactId>exec-maven-plugin</artifactId> <version>${exec-maven-plugin.version}</version> <executions> <execution> <goals> <goal>exec</goal> </goals> </execution> </executions> <configuration> <executable>java</executable> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>${maven-shade-plugin.version}</version> <configuration> <shadedArtifactAttached>true</shadedArtifactAttached> <shadedClassifierName>${shadedClassifier}</shadedClassifierName> <createDependencyReducedPom>true</createDependencyReducedPom> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>org/datanucleus/**</exclude> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>reference.conf</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> </transformer> </transformers> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> </plugins> </build> </project> |
参考までに上位のプロジェクトルートフォルダにある親pom.xmlに記述されたプロパティタグによるバージョンコントロール部分を以下に抽出しておく。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<properties> <!-- Change the nd4j.backend property to nd4j-cuda-7.5-platform or nd4j-cuda-8.0-platform to use CUDA GPUs --> <nd4j.backend>nd4j-native-platform</nd4j.backend> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <shadedClassifier>bin</shadedClassifier> <java.version>1.8</java.version> <nd4j.version>0.7.2</nd4j.version> <dl4j.version>0.7.2</dl4j.version> <datavec.version>0.7.2</datavec.version> <arbiter.version>0.7.2</arbiter.version> <guava.version>19.0</guava.version> <logback.version>1.1.7</logback.version> <jfreechart.version>1.0.13</jfreechart.version> <jcommon.version>1.0.23</jcommon.version> <maven-shade-plugin.version>2.4.3</maven-shade-plugin.version> <exec-maven-plugin.version>1.4.0</exec-maven-plugin.version> <maven.minimum.version>3.3.1</maven.minimum.version> </properties> |
さて、これからDL4JのDeepLearningプログラムをスタンドアロンで作動させるようにしていく。
そこで、以前のブログで調査記述したDL4JのExampleに含まれるCNNを用いたMNIST手書き数字画像の機械学習であるLenetMnistExampleを切り出して単独で動かすようにしてみる。
IntelliJから、ファイル>新規プロジェクト>Mavenを選択し、Group ID(ここでは例えばMyGroupとArtifact ID(ここでは例えばMyArtifact03)を入力して、OKボタンを押していく(アーキタイプの選択が可能となるチェックボックスが登場するが、とりあえず無視して進めると、必要なファイル構成が生成される。IntelliJの左コラムには、srcフォルダや以下のようなシンプルなpom.xmlが生成されている。
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>MyGroup</groupId> <artifactId>MyArtifac05</artifactId> <version>1.0-SNAPSHOT</version> </project> |
まずは、このpom.xmlファイルの以下に、上述のDL4J Exampleのpom.xmlファイルの以下の記述をコピペする。この際、バージョン変数は、親pom.xmlから具体的な数値(記述)に置き換えておく。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>MyGroup</groupId> <artifactId>MyArtifact05</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/org.deeplearning4j/deeplearning4j-core --> <dependency> <groupId>org.deeplearning4j</groupId> <artifactId>deeplearning4j-core</artifactId> <version>0.7.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.nd4j/nd4j-native --> <dependency> <groupId>org.nd4j</groupId> <artifactId>nd4j-native</artifactId> <version>0.7.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.nd4j/nd4j-api --> <dependency> <groupId>org.nd4j</groupId> <artifactId>nd4j-api</artifactId> <version>0.7.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.nd4j/nd4j-native-platform --> <dependency> <groupId>org.nd4j</groupId> <artifactId>nd4j-native-platform</artifactId> <version>0.7.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.datavec/datavec-api --> <dependency> <groupId>org.datavec</groupId> <artifactId>datavec-api</artifactId> <version>0.7.2</version> </dependency> <dependency> <groupId>org.deeplearning4j</groupId> <artifactId>deeplearning4j-nlp</artifactId> <version>0.7.2</version> </dependency> <!-- deeplearning4j-ui is used for HistogramIterationListener + visualization: see http://deeplearning4j.org/visualization --> <dependency> <groupId>org.deeplearning4j</groupId> <artifactId>deeplearning4j-ui_2.10</artifactId> <version>0.7.2</version> </dependency> <!-- Force guava versions for using UI/HistogramIterationListener --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>19.0</version> </dependency> <!-- datavec-data-codec: used only in video example for loading video data --> <dependency> <artifactId>datavec-data-codec</artifactId> <groupId>org.datavec</groupId> <version>0.7.2</version> </dependency> <!-- Used in the feedforward/classification/MLP* and feedforward/regression/RegressionMathFunctions example --> <dependency> <groupId>jfree</groupId> <artifactId>jfreechart</artifactId> <version>1.0.13</version> </dependency> <dependency> <groupId>org.jfree</groupId> <artifactId>jcommon</artifactId> <version>1.0.23</version> </dependency> <!-- Used for downloading data in some of the examples --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.3.5</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.4.0</version> <executions> <execution> <goals> <goal>exec</goal> </goals> </execution> </executions> <configuration> <executable>java</executable> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.4.3</version> <configuration> <shadedArtifactAttached>true</shadedArtifactAttached> <shadedClassifierName>bin</shadedClassifierName> <createDependencyReducedPom>true</createDependencyReducedPom> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>org/datanucleus/**</exclude> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>reference.conf</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project> |
すると、IntelliJは、ファイルが更新されたことを自動認識して、Mavenデポジットに追加されたライブラリーのダウンロードを進める。なるほど、これがMavenの仕組みかと、ここで納得することになるであろう。
次に、IntelliJの左コラムからファイル構造を開き、srcフォルダのもとに、main/java、main/resourcesが生成されてるが、javaのフォルダをハイライトして、「コマンド+N」で、JAVAクラス」の新規生成を行う。クラス名は、LenetMnistExampleとすると、以下のように表示される。
1 2 |
public class LenetMnistExample { } |
そこで、このファイルの記述を、DL4JのLenetMnistExampleの実際の記述に置き換える(コピペ記述内容はオリジナルから以前に少し弄って、テキストファイル出力させるようにしたもの)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
package org.deeplearning4j.examples.convolution; import org.deeplearning4j.datasets.iterator.impl.MnistDataSetIterator; import org.deeplearning4j.eval.Evaluation; import org.deeplearning4j.nn.api.OptimizationAlgorithm; import org.deeplearning4j.nn.conf.MultiLayerConfiguration; import org.deeplearning4j.nn.conf.NeuralNetConfiguration; import org.deeplearning4j.nn.conf.Updater; import org.deeplearning4j.nn.conf.inputs.InputType; import org.deeplearning4j.nn.conf.layers.ConvolutionLayer; import org.deeplearning4j.nn.conf.layers.DenseLayer; import org.deeplearning4j.nn.conf.layers.OutputLayer; import org.deeplearning4j.nn.conf.layers.SubsamplingLayer; import org.deeplearning4j.nn.multilayer.MultiLayerNetwork; import org.deeplearning4j.nn.weights.WeightInit; import org.deeplearning4j.optimize.listeners.ScoreIterationListener; import org.nd4j.linalg.activations.Activation; import org.nd4j.linalg.api.ndarray.INDArray; import org.nd4j.linalg.dataset.DataSet; import org.nd4j.linalg.dataset.api.iterator.DataSetIterator; import org.nd4j.linalg.lossfunctions.LossFunctions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; /** * Created by agibsonccc on 9/16/15. */ public class LenetMnistExample { private static final Logger log = LoggerFactory.getLogger(LenetMnistExample.class); public static void main(String[] args) throws Exception { int nChannels = 1; // Number of input channels int outputNum = 10; // The number of possible outcomes int batchSize = 64; // Test batch size int nEpochs = 1; // Number of training epochs int iterations = 1; // Number of training iterations int seed = 123; // /* Create an iterator using the batch size for one iteration */ log.info("Load data...."); DataSetIterator mnistTrain = new MnistDataSetIterator(batchSize,true,12345); DataSetIterator mnistTest = new MnistDataSetIterator(batchSize,false,12345); /* Construct the neural network */ log.info("Build model...."); MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder() .seed(seed) .iterations(iterations) // Training iterations as above .regularization(true).l2(0.0005) /* Uncomment the following for learning decay and bias */ .learningRate(.01)//.biasLearningRate(0.02) //.learningRateDecayPolicy(LearningRatePolicy.Inverse).lrPolicyDecayRate(0.001).lrPolicyPower(0.75) .weightInit(WeightInit.XAVIER) .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT) .updater(Updater.NESTEROVS).momentum(0.9) .list() .layer(0, new ConvolutionLayer.Builder(5, 5) //nIn and nOut specify depth. nIn here is the nChannels and nOut is the number of filters to be applied .nIn(nChannels) .stride(1, 1) .nOut(20) .activation(Activation.IDENTITY) .build()) .layer(1, new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX) .kernelSize(2,2) .stride(2,2) .build()) .layer(2, new ConvolutionLayer.Builder(5, 5) //Note that nIn need not be specified in later layers .stride(1, 1) .nOut(50) .activation(Activation.IDENTITY) .build()) .layer(3, new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX) .kernelSize(2,2) .stride(2,2) .build()) .layer(4, new DenseLayer.Builder().activation(Activation.RELU) .nOut(500).build()) .layer(5, new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD) .nOut(outputNum) .activation(Activation.SOFTMAX) .build()) .setInputType(InputType.convolutionalFlat(28,28,1)) //See note below .backprop(true).pretrain(false).build(); /* Regarding the .setInputType(InputType.convolutionalFlat(28,28,1)) line: This does a few things. (a) It adds preprocessors, which handle things like the transition between the convolutional/subsampling layers and the dense layer (b) Does some additional configuration validation (c) Where necessary, sets the nIn (number of input neurons, or input depth in the case of CNNs) values for each layer based on the size of the previous layer (but it won't override values manually set by the user) InputTypes can be used with other layer types too (RNNs, MLPs etc) not just CNNs. For normal images (when using ImageRecordReader) use InputType.convolutional(height,width,depth). MNIST record reader is a special case, that outputs 28x28 pixel grayscale (nChannels=1) images, in a "flattened" row vector format (i.e., 1x784 vectors), hence the "convolutionalFlat" input type used here. */ MultiLayerNetwork model = new MultiLayerNetwork(conf); model.init(); PrintStream sysOut = System.out; FileOutputStream fos = new FileOutputStream("out_pre.txt"); PrintStream ps = new PrintStream(fos); System.setOut(ps); System.out.println(model.paramTable()); ps.close(); fos.close(); System.setOut(sysOut); log.info("Train model...."); model.setListeners(new ScoreIterationListener(1)); for( int i=0; i<nEpochs; i++ ) { model.fit(mnistTrain); log.info("*** Completed epoch {} ***", i); FileOutputStream fos2 = new FileOutputStream("out_post.txt"); PrintStream ps2 = new PrintStream(fos2); System.setOut(ps2); System.out.println(model.paramTable()); ps2.close(); fos2.close(); System.setOut(sysOut); log.info("Evaluate model...."); Evaluation eval = new Evaluation(outputNum); while(mnistTest.hasNext()){ DataSet ds = mnistTest.next(); INDArray output = model.output(ds.getFeatureMatrix(), false); eval.eval(ds.getLabels(), output); } log.info(eval.stats()); mnistTest.reset(); } log.info("****************Example finished********************"); } } |
この段階でも、もしかすると「Mavenプロジェクトのインポートが必要です。」が登場し、自動インポートの使用可能が促される。
IntelliJの左コラム内にツリー構造src/main/java/org.deeplearning4j.examples.convolution/内にLenetMnistExample(.java)が出来上がっている。このファイルをハイライト+コントロールで、「緑の実行」すれば、プログラムが作動するはずである。
次に、コンパイルビルドして、Jarファイルを作成するために、IntelliJ ファイル>プロジェクト構造>左のコラムから「成果物」、そして真ん中コラムの+ボタンをクリックして、jarファイル>「依存関係を持つモジュールから」を選択すると、モジュール名(MyArtifact03)、メイン・クラス(LenetMnistExample)、に加えて、マニフェストMANIFEST.MFの入力をお求められて、OKボタン。
その結果、必要な関連ライブラリのリストに加えて、画面の下方にマニフェストファイルの位置やメインクラスが記載されたものが表示される。
あとは、IntelliJビルド>成果物ビルド>buildメニューでbuildをクリックで、コンパイルビルドが開始して、outフォルダに成果物たるMyArtifact05.jarが生成されるはず。
————————————————
ここから以下が、よくわからん。Javaのjarファイルを実行形式にするためには、javaフォルダにMETA-INFフォルダをおいて、その中にメイン・クラスの指定を行うマニフェストファイルMANIFECT.MFを置きておく必要がある。IntelliJでは、ほぼ自動でjavaフォルダ内に生成されるが、仮にも先に生成されていると「すでにありまっせ!」メッセージが現れて、先に進めない(この場合は、ファインダーからMETA-INFフォルダを削除する)。一方で、IntelliJでは、このMETA-INFはresourcesフォルダに置かないといけないという記述などもウェブ上のトラブルシュートには記載されておるが、よくわからん。いずれにせよ、IntelliJから、生成されたMyArtifact05.jarを直接ハイライトして、実行しても「メイン・クラスが見つかりません」とか云々のアラートで作動しない。
————————————————
仕方がないので、コンソールに移動して、mvnのコマンド打ちでパッケージビルド:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
MacBook-Pro-5:MyArtifact05 $ mvn clean package [INFO] Scanning for projects... [INFO] [INFO] ------------------------< MyGroup:MyArtifact03 >------------------------ [INFO] Building MyArtifact05 1.0-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ MyArtifact03 --- [INFO] Deleting /Users/*********/Ideajects/MyArtifact05/target [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ MyArtifact05 --- ............................ [INFO] Attaching shaded artifact. [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 35.773 s [INFO] Finished at: 2018-09-10T13:54:57+09:00 [INFO] ------------------------------------------------------------------------ |
すると、targetフォルダ内に、MyArtifact05-1.0-SNAPSHOT-bin.jarが生成された。
こそで、javaコマンドをクラスパスオプション付きで、このjarファイル指定し、第二引数でメイン・クラス”org.deeplearning4j.examples.convolution.LenetMnistExample”を指定して、実行させる。LenetMnistExampleが無事に動いた!
注意:実行はプロジェクトルートからで、第一引数jarの指定はプロジェクトルートからの相対パス、第二引数は、ダブルクォーテーション。
1 |
java -cp ./target/MyArtifact05-1.0-SNAPSHOT-bin.jar "org.deeplearning4j.examples.convolution.LenetMnistExample" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
MacBook-Pro-5:MyArtifact05 $ java -cp ./target/MyArtifact05-1.0-SNAPSHOT-bin.jar "org.deeplearning4j.examples.convolution.LenetMnistExample" 13:56:02.432 [main] INFO o.d.e.convolution.LenetMnistExample - Load data.... 13:56:02.794 [main] INFO o.d.e.convolution.LenetMnistExample - Build model.... 13:56:02.823 [main] INFO org.nd4j.linalg.factory.Nd4jBackend - Loaded [CpuBackend] backend 13:56:03.024 [main] INFO org.nd4j.nativeblas.NativeOpsHolder - Number of threads used for NativeOps: 4 13:56:03.068 [main] DEBUG org.reflections.Reflections - going to scan these urls: jar:file:/Users/*******/Ideajects/MyArtifact05/target/MyArtifact05-1.0-SNAPSHOT-bin.jar!/ 13:56:03.505 [main] INFO org.reflections.Reflections - Reflections took 422 ms to scan 1 urls, producing 29 keys and 176 values 13:56:03.925 [main] DEBUG org.reflections.Reflections - going to scan these urls: file:/Users/******/Ideajects/MyArtifact05/target/MyArtifact05-1.0-SNAPSHOT-bin.jar file:/Library/Java/Extensions/commons-math3-3.6.1-javadoc.jar file:/Library/Java/Extensions/commons-math3-3.6.1-sources.jar file:/Library/Java/Extensions/commons-math3-3.6.1.jar file:/Library/Java/Extensions/commons-math3-3.6.1-test-sources.jar file:/Library/Java/Extensions/commons-math3-3.6.1-tests.jar file:/Library/Java/Extensions/commons-math3-3.6.1-tools.jar file:/System/Library/Java/Extensions/MRJToolkit.jar 13:56:06.349 [main] INFO org.reflections.Reflections - Reflections took 2424 ms to scan 8 urls, producing 2128 keys and 14433 values 13:56:06.388 [main] DEBUG o.d.nn.conf.NeuralNetConfiguration - Registering class for JSON serialization: org.deeplearning4j.nn.conf.layers.DropoutLayer as subtype of org.deeplearning4j.nn.conf.layers.Layer 13:56:06.393 [main] DEBUG o.d.nn.conf.NeuralNetConfiguration - Registering class for JSON serialization: org.deeplearning4j.nn.conf.layers.DropoutLayer as subtype of org.deeplearning4j.nn.conf.layers.Layer 13:56:06.398 [main] WARN o.d.nn.conf.MultiLayerConfiguration - Warning: new network default sets pretrain to false. 13:56:06.398 [main] WARN o.d.nn.conf.MultiLayerConfiguration - Warning: new network default sets backprop to true. 13:56:06.445 [main] DEBUG org.reflections.Reflections - going to scan these urls: jar:file:/Users/******/Ideajects/MyArtifact05/target/MyArtifact05-1.0-SNAPSHOT-bin.jar!/ 13:56:06.679 [main] INFO org.reflections.Reflections - Reflections took 234 ms to scan 1 urls, producing 368 keys and 1424 values 13:56:08.479 [main] INFO o.d.e.convolution.LenetMnistExample - Train model.... ................... |
—————————————-
土日の夜を費やしてしまったこのプロジェクトのここまでの中間まとめ
—————————————-
1. Apache Mavenのpom.xmlを知る必要あり。
2. IntelliJ IDEAをある程度、使える必要あり:IntelliJ IDEAのプロジェクト構造>成果物、ビルド>成果物のビルド(結局、いまだ実行型のjarの生成に関しては解決できていない。というのも、オリジナルのExampleファイルは、色々なプログラムが詰め込まれた状態で、シェルスクリプトで動かしたいプログラム番号を指定して、作動させるようになっているので、スタンドアロンの実行型Jarではない。したがって、おそらくパッケージ化等のプラグインを導入する必要がありそう。
3.jarファイルを実行するには、メイン・クラスを指定する必要があり、マニフェストファイル(META-INF/MINIFEST.MFファイルが重要。このファイルを置いた状態でjarを生成する必要あり。
4. 最後の成果物の生成は、コマンドラインからMavenを操作したほうが簡単。
IntelliJから、実行型が生成できていない理由は、おそらくpom.xmlのプラグイン等がなにか足りないか余分な部分があるのではと思うが、いまだよくわからん状態だが、今の所、まあ良いか。。。
いずれにせよ、これでJarファイルから作動するDeep Learningプロジェクトを生成することが可能となった。
—————————————-
ということで、頭をクールダウンして、実行型jarに誘導するためのMaven Pluginを探索する。
参考:https://rx21.exblog.jp/238330755/
にして、buildタグの中身を入れ替える。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<build> <plugins> <plugin> <!-- このプラグインを使うのがお作法らしいです・・。 --> <artifactId>maven-assembly-plugin</artifactId> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> <configuration> <descriptorRefs> <!-- 依存するJARを含める場合 --> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>org.deeplearning4j.examples.convolution.LenetMnistExample</mainClass> </manifest> </archive> <!-- ファイル名を変更する場合 --> <finalName>DummyJar</finalName> </configuration> </plugin> </plugins> </build> |
でIntelliJでbuildしたいが、その前に、ファイル>プロジェクト構造>で出力先変更等を試みたが、
何か成果物のプロジェクト構造での出力指定が悪いのか、なかなかIntelliJの細かい設定がわからない。。。。
そこで、再びコマンドラインから、
1 |
mvn clean install |
で試してみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
MacBook-Pro-5:MyArtifact05 $ mvn clean install [INFO] Scanning for projects... [INFO] [INFO] ------------------------< MyGroup:MyArtifact05 >------------------------ [INFO] Building MyArtifact05 1.0-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ MyArtifact05 --- [INFO] Deleting /Users/*******/Ideajects/MyArtifact05/target [INFO] ....................... oup/MyArtifact05/1.0-SNAPSHOT/MyArtifact05-1.0-SNAPSHOT.pom [INFO] Installing /Users/******/Ideajects/MyArtifact05/target/DummyJar-jar-with-dependencies.jar to /Users/******/.m2/repository/MyGroup/MyArtifact05/1.0-SNAPSHOT/MyArtifact05-1.0-SNAPSHOT-jar-with-dependencies.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 01:02 min [INFO] Finished at: 2018-09-10T19:55:14+09:00 [INFO] ------------------------------------------------------------------------ |
ビルド成功! targetフォルダに成果物DummyJar-jar-with-dependencies.jarが生成されている。
1 2 3 4 5 |
MacBook-Pro-5:MyArtifact05 $ cd target/ MacBook-Pro-5:target $ ls DummyJar-jar-with-dependencies.jar classes MyArtifact03-1.0-SNAPSHOT.jar maven-archiver archive-tmp maven-status |
java -jar ****.jarで実行してみると、以下のようにCNN LenetMnistExampleが実行!
1 2 3 4 5 6 |
MacBook-Pro-5:target $ java -jar DummyJar-jar-with-dependencies.jar 19:55:43.459 [main] INFO o.d.e.convolution.LenetMnistExample - Load data.... 19:55:43.800 [main] INFO o.d.e.convolution.LenetMnistExample - Build model.... 19:55:43.830 [main] INFO org.nd4j.linalg.factory.Nd4jBackend - Loaded [CpuBackend] backend 19:55:44.044 [main] INFO org.nd4j.nativeblas.NativeOpsHolder - Number of threads used for NativeOps: |
コマンドラインで実行可能型jarができるということは、修正pom.xmlはOKということで、あとはIntelliJで実行型jarの出力がどうやってできるのか、もう少しIntelliJを弄くらないとわからん。
—————————————-
格言:Deep Learningの深層学習の意味は、プログラミングの深層学習でもあった!
—————————————-