Deeplearning 4 j実戦(1):Deeplearning 4 j手書きデジタル認識


Eclipse Deeplearning 4 j GiChatコース:https://gitbook.cn/gitchat/column/5bfb6741ae0e5f436e35cd9fEclipseDeeplearning 4 jシリーズブログ:https://blog.csdn.net/wangongxiEclipse Deeplearning4j Github:https://github.com/eclipse/deeplearning4j 
ここ数年、深さの勉强はとても火がついて、自分を含む多くの机械の勉强に対してまだ半分理解している白も深さの勉强でいくつかの応用をし始めました.シロはレベルが高くなく、アルゴリズム自体が書けないので、オープンソースライブラリを使いました.Deep Learningのオープンソースライブラリが多く、言語で区切るとpythonシリーズのtensowflow、theano、keras、C/C++シリーズのCaffe、Luaシリーズのtorchなどがあります.しかし、うちの会社はJavaを中心にしていて、ほとんどのプロジェクトは最終的にJava Webのサービスを作ったので、私は最終的にDeeplearning 4 jを選びました.
Deeplearning 4 jは海外の創業会社Skymindの製品です.現在、最新バージョンは0.7.2に更新されています.ソースコードはすべて公開されgithubに管理されています(https://github.com/deeplearning4j/deeplearning4j).このライブラリの名前から分かるように、Javaプログラマーが書いたDeep Learningライブラリに移行しています.実はこのライブラリが魅力的なのはJavaをサポートするだけでなく、Sparkをサポートできることです.Deep Learningモデルの訓練には大量のメモリが必要であり,元のデータの記憶にも大きな外部メモリが必要な場合があるため,クラスタを利用して処理できるとよい.もちろん、Deeplearning 4 jのほかにも、yahoo/CaffeOnSpark、AMPLab/SparkNet、Intelの最近オープンソースのBigDLなどのDeep Learningのライブラリがあります.これらのライブラリは自分ではあまり使ったことがないので、あまり言わないで、ここではDeeplearning 4 jの使用に重点を置いて話します.
一般的に他の人のコードライブラリを使うようになると、まずdemoを走ったり、Hello Worldの例を言ったりします.プログラミング言語を勉強するように、最初のコードはHello Worldを印刷します.Deep LearningのHello Worldの例は一般的に2つで、1つはMnistデータセットの分類で、もう1つはWord 2 Vecが類似語を探すことです.Word 2 Vecは厳密な意味での深さニューラルネットワークではないため,ここではDeep LearningのHello WorldとしてMnistデータセットをLenetネットワークで処理する.Mnistはオープンソースの28 x 28の白黒手書きデジタルピクチャセット(http://yann.lecun.com/exdb/mnist/6 Wのトレーニング画像と1 Wのテスト画像が含まれています.Lenetの関連構造の説明については、このリンクを参照してください.http://yann.lecun.com/exdb/publis/pdf/lecun-98.pdf.以下では,Deeplearning 4 jを用いてモデリング,トレーニング,予測評価をどのように行うかについて詳細に述べる.
まず、mavenプロジェクトを構築します.それからpomファイルにDeeplearning 4 jのいくつかの関連依存を加えます.最も主要なのは3つあります:deeplearning 4 j-core,datavec,nd 4 j.deeplearning 4 j-coreはニューラルネットワーク構造で実現されるコードであり、nd 4 jはテンソル演算を行うためのライブラリであり、JavaCPPを介してコンパイルされたC++ライブラリ(オプション:ATAL、MKL、OpenBLAS)を呼び出し、datavecは主にデータのETLを担当する.具体的な表示コード:
 
  
    UTF-8
    0.7.1
    0.7.1
    0.7.1
    2.10
  
  
	 
	     org.nd4j
	     nd4j-native 
	     ${nd4j.version}
	 
	 
	     org.deeplearning4j
	     dl4j-spark_2.11
	     ${dl4j.version}
	 
   	 
            org.datavec
            datavec-spark_${scala.binary.version}
            ${datavec.version}
     	
        
	    org.deeplearning4j
	    deeplearning4j-core
	    ${dl4j.version}
	 
  

これらの依存にはSparkに関連するものがあり,主にSparkを走るために用いられる.でも大丈夫です.先に引き入れればいいです.
次に、次のコードについて説明します.まず、分類された個数(outputNum)、mini-batchの数(batchSize)などの具体的なパラメータを定義し、具体的には図に注釈を付けた.説明が必要なのはMnistDataSetIteratorという反復器クラスです.このクラスは実はバイナリMnistデータセットを読み出すhigh-levelのパッケージです.Debugにより,ネットワークからMnistデータセットをダウンロードし,データと寸法を読み出し,反復器を構築するプロセスが含まれることが分かった.ソースコードでは、ダウンロードしたファイルはデフォルトでシステムのuserに配置されます.ホームディレクトリの下では、具体的には人によって違います.私自身が置かれている環境ネットワークはあまりよくないので、このようなhigh-levelのインタフェースを利用している間に、Mnistデータのダウンロードに失敗して異常を投げ出し、最終的に訓練できない可能性が高い.だから、まず自分でこれらのデータをダウンロードして、それからソースコードの要求に従って、相応のディレクトリの下に置いて、ソースコードに基づいてファイルを正しく命名することができて、それでは依然としてこのようなhigh-levelのインタフェースを利用することができます.具体的にはMnistDataFetcherクラスの関連コードを参照してください.
 
        int nChannels = 1;      //black & white picture, 3 if color image
        int outputNum = 10;     //number of classification
        int batchSize = 64;     //mini batch size for sgd
        int nEpochs = 10;       //total rounds of training
        int iterations = 1;     //number of iteration in each traning round
        int seed = 123;         //random seed for initialize weights

        log.info("Load data....");
        DataSetIterator mnistTrain = null;
        DataSetIterator mnistTest = null;

        mnistTrain = new MnistDataSetIterator(batchSize, true, 12345);
        mnistTest = new MnistDataSetIterator(batchSize, false, 12345);

データを正しく読み取ると、具体的なニューラルネットワーク構造を定義する必要があります.ここではLenet、Deeplearning 4 jの実装を使用して公式サイト(https://github.com/deeplearning4j/dl4j-examples)も参照してください.具体的なコードは以下の通りです.
 
        MultiLayerConfiguration.Builder builder = new NeuralNetConfiguration.Builder()
                .seed(seed)
                .iterations(iterations)
                .regularization(true).l2(0.0005)
                .learningRate(0.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("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("identity")
                        .build())
                .layer(3, new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX)
                        .kernelSize(2,2)
                        .stride(2,2)
                        .build())
                .layer(4, new DenseLayer.Builder().activation("relu")
                        .nOut(500).build())
                .layer(5, new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
                        .nOut(outputNum)
                        .activation("softmax")
                        .build())
                .backprop(true).pretrain(false)
                .cnnInputSize(28, 28, 1);
        // The builder needs the dimensions of the image along with the number of channels. these are 28x28 images in one channel
        //new ConvolutionLayerSetup(builder,28,28,1);

        MultiLayerConfiguration conf = builder.build();
        MultiLayerNetwork model = new MultiLayerNetwork(conf);
        model.init();        
        model.setListeners(new ScoreIterationListener(1));         // a listener which can print loss function score after each iteration

ニューラルネットワークは多くの超パラメータを定義する必要があり,学習率,正規化係数,ボリュームコアの大きさ,励起関数などは人為的に設定する必要があることが分かった.異なるスーパーパラメータは,結果に大きな影響を及ぼすが,実際には後でデータ処理とパラメータ調整に多くの時間を費やすことが分かった.結局、自分でネットを設計する能力は限られていて、一般的には大牛の論文を参考にして、それから自分でひょうたんを描いて実現します.ここで実装されるLenetの構造は、ボリューム-->ダウンサンプリング-->ボリューム-->ダウンサンプリング-->フル接続です.原論文の構造とほぼ一致している.ボリュームコアの大きさも参考にした原論文である.具体的な詳細は、前に送った論文のリンクを参照してください.ここではScoreのリスニングイベントを設定し,主に訓練時に重み更新後の損失関数の収束状況を取得できるようにした.後でスクリーンショットがあります.
ネットワーク構造を定義した後,以前に読み取ったデータの訓練と分類の正確性評価を行うことができる.コードを見てみましょう.
 
        for( int i = 0; i < nEpochs; ++i ) {
            model.fit(mnistTrain);
            log.info("*** Completed epoch " + i + "***");

            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();
        }

 
この部分は理解しやすいと信じています.トレーニングが完了するたびに、テストセットを評価し、次のような結果を印刷します.図の前半は具体的な分類の統計であり、ペアとエラーのピクチャ数を含めて見ることができる.そして、しばらく待っていると、10回の訓練を受けたLenetのMnistデータセットの分類精度が99%に達したことがわかります.
 
Examples labeled as 0 classified by model as 0: 974 times
Examples labeled as 0 classified by model as 6: 2 times
Examples labeled as 0 classified by model as 7: 2 times
Examples labeled as 0 classified by model as 8: 1 times
Examples labeled as 0 classified by model as 9: 1 times
Examples labeled as 1 classified by model as 0: 1 times
Examples labeled as 1 classified by model as 1: 1128 times
Examples labeled as 1 classified by model as 2: 1 times
Examples labeled as 1 classified by model as 3: 2 times
Examples labeled as 1 classified by model as 5: 1 times
Examples labeled as 1 classified by model as 6: 2 times
Examples labeled as 2 classified by model as 2: 1026 times
Examples labeled as 2 classified by model as 4: 1 times
Examples labeled as 2 classified by model as 6: 1 times
Examples labeled as 2 classified by model as 7: 3 times
Examples labeled as 2 classified by model as 8: 1 times
Examples labeled as 3 classified by model as 0: 1 times
Examples labeled as 3 classified by model as 1: 1 times
Examples labeled as 3 classified by model as 2: 1 times
Examples labeled as 3 classified by model as 3: 998 times
Examples labeled as 3 classified by model as 5: 3 times
Examples labeled as 3 classified by model as 7: 1 times
Examples labeled as 3 classified by model as 8: 4 times
Examples labeled as 3 classified by model as 9: 1 times
Examples labeled as 4 classified by model as 2: 1 times
Examples labeled as 4 classified by model as 4: 973 times
Examples labeled as 4 classified by model as 6: 2 times
Examples labeled as 4 classified by model as 7: 1 times
Examples labeled as 4 classified by model as 9: 5 times
Examples labeled as 5 classified by model as 0: 2 times
Examples labeled as 5 classified by model as 3: 4 times
Examples labeled as 5 classified by model as 5: 882 times
Examples labeled as 5 classified by model as 6: 1 times
Examples labeled as 5 classified by model as 7: 1 times
Examples labeled as 5 classified by model as 8: 2 times
Examples labeled as 6 classified by model as 0: 4 times
Examples labeled as 6 classified by model as 1: 2 times
Examples labeled as 6 classified by model as 4: 1 times
Examples labeled as 6 classified by model as 5: 4 times
Examples labeled as 6 classified by model as 6: 945 times
Examples labeled as 6 classified by model as 8: 2 times
Examples labeled as 7 classified by model as 1: 5 times
Examples labeled as 7 classified by model as 2: 3 times
Examples labeled as 7 classified by model as 3: 1 times
Examples labeled as 7 classified by model as 7: 1016 times
Examples labeled as 7 classified by model as 8: 1 times
Examples labeled as 7 classified by model as 9: 2 times
Examples labeled as 8 classified by model as 0: 1 times
Examples labeled as 8 classified by model as 3: 1 times
Examples labeled as 8 classified by model as 5: 2 times
Examples labeled as 8 classified by model as 7: 2 times
Examples labeled as 8 classified by model as 8: 966 times
Examples labeled as 8 classified by model as 9: 2 times
Examples labeled as 9 classified by model as 3: 1 times
Examples labeled as 9 classified by model as 4: 2 times
Examples labeled as 9 classified by model as 5: 4 times
Examples labeled as 9 classified by model as 6: 1 times
Examples labeled as 9 classified by model as 7: 5 times
Examples labeled as 9 classified by model as 8: 3 times
Examples labeled as 9 classified by model as 9: 993 times


==========================Scores========================================
 Accuracy:        0.9901
 Precision:       0.99
 Recall:          0.99
 F1 Score:        0.99
========================================================================
[main] INFO cv.LenetMnistExample - ****************Example finished********************

絵が伝わらないので、私は直接結果を貼りました.そこから最終的な精度を見ると、どの画像が分類が正しいのか、分類が間違っているのかがわかります.もちろん、トレーニングのラウンドを増やしたり、オーバーパラメータを調整したりすることでさらに最適化することができますが、実際にはこのような結果は生産的に使用することができます.
まとめてみます.実は私自身も含めて多くの人が深さの勉強について知らないので、csdnに書いてある深さの勉強に関するブログを見たとき、自分がそのレベルに達することができないと思っていたのを覚えています.しかし、実は、私たちは少し無視して、深さの学習自身は更に複雑で、それはアルゴリズムモデルで、機械の学習でもあります.感知機、論理回帰などのモデルより複雑であるが(実際には論理回帰はニューラルネットワークのニューロンと見なされ、励起関数の役割を果たし、tanh、reluなどの類似の励起関数が多い)、結局その目的は依然として回帰、分類、圧縮データなどの任務を完成することである.最初の試みは重要ですもちろん,複雑なモデルから始めることは不可能であり,最初から現在最も流行しているモデルに従うことはできないので,Mnist識別の例から感覚を探している.後でDeeplearning 4 jをSparkに使うケースを書きますが、Mnistから始まります.分かち合いながら自分も復習してみます...