DEEP LEARNING : IntelliJ+MavenでCNN LenetMnistExampleをStandalone作動:AI-Anesth 8

今回の目標は、スタンドアロンの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を覗いてみよう。日本語コメントを付記しておく。

参考までに上位のプロジェクトルートフォルダにある親pom.xmlに記述されたプロパティタグによるバージョンコントロール部分を以下に抽出しておく。

さて、これからDL4JのDeepLearningプログラムをスタンドアロンで作動させるようにしていく。
そこで、以前のブログで調査記述したDL4JのExampleに含まれるCNNを用いたMNIST手書き数字画像の機械学習であるLenetMnistExampleを切り出して単独で動かすようにしてみる。
IntelliJから、ファイル>新規プロジェクト>Mavenを選択し、Group ID(ここでは例えばMyGroupとArtifact ID(ここでは例えばMyArtifact03)を入力して、OKボタンを押していく(アーキタイプの選択が可能となるチェックボックスが登場するが、とりあえず無視して進めると、必要なファイル構成が生成される。IntelliJの左コラムには、srcフォルダや以下のようなシンプルなpom.xmlが生成されている。

まずは、このpom.xmlファイルの以下に、上述のDL4J Exampleのpom.xmlファイルの以下の記述をコピペする。この際、バージョン変数は、親pom.xmlから具体的な数値(記述)に置き換えておく。

すると、IntelliJは、ファイルが更新されたことを自動認識して、Mavenデポジットに追加されたライブラリーのダウンロードを進める。なるほど、これがMavenの仕組みかと、ここで納得することになるであろう。

次に、IntelliJの左コラムからファイル構造を開き、srcフォルダのもとに、main/java、main/resourcesが生成されてるが、javaのフォルダをハイライトして、「コマンド+N」で、JAVAクラス」の新規生成を行う。クラス名は、LenetMnistExampleとすると、以下のように表示される。

そこで、このファイルの記述を、DL4JのLenetMnistExampleの実際の記述に置き換える(コピペ記述内容はオリジナルから以前に少し弄って、テキストファイル出力させるようにしたもの)。

この段階でも、もしかすると「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のコマンド打ちでパッケージビルド:

すると、targetフォルダ内に、MyArtifact05-1.0-SNAPSHOT-bin.jarが生成された。
こそで、javaコマンドをクラスパスオプション付きで、このjarファイル指定し、第二引数でメイン・クラス”org.deeplearning4j.examples.convolution.LenetMnistExample”を指定して、実行させる。LenetMnistExampleが無事に動いた!
注意:実行はプロジェクトルートからで、第一引数jarの指定はプロジェクトルートからの相対パス、第二引数は、ダブルクォーテーション。

—————————————-
土日の夜を費やしてしまったこのプロジェクトのここまでの中間まとめ
—————————————-
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タグの中身を入れ替える。

でIntelliJでbuildしたいが、その前に、ファイル>プロジェクト構造>で出力先変更等を試みたが、
何か成果物のプロジェクト構造での出力指定が悪いのか、なかなかIntelliJの細かい設定がわからない。。。。
そこで、再びコマンドラインから、

で試してみる。

ビルド成功! targetフォルダに成果物DummyJar-jar-with-dependencies.jarが生成されている。

java -jar ****.jarで実行してみると、以下のようにCNN LenetMnistExampleが実行!

コマンドラインで実行可能型jarができるということは、修正pom.xmlはOKということで、あとはIntelliJで実行型jarの出力がどうやってできるのか、もう少しIntelliJを弄くらないとわからん。
—————————————-
格言:Deep Learningの深層学習の意味は、プログラミングの深層学習でもあった!
—————————————-