Deeplearning4jへのガイド

Deeplearning4jのガイド

1. 前書き

この記事では、deeplearning4j(dl4j)ライブラリを使用して単純なニューラルネットワークを作成します。これは、機械学習のための最新の強力なツールです。

始める前に、このガイドでは、線形代数、統計、機械学習理論、および十分な知識を持つMLエンジニアに必要なその他の多くのトピックに関する深い知識は必要ありません。

2. ディープラーニングとは何ですか?

ニューラルネットワークは、相互接続されたノードの層で構成される計算モデルです。

ノードは、ニューロンのような数値データのプロセッサです。 入力からデータを取得し、これらのデータに重みと関数を適用して、結果を出力に送信します。 このようなネットワークは、ソースデータのいくつかの例でトレーニングできます。

トレーニングは基本的に、後で計算に影響を与えるいくつかの数値状態(重み)をノードに保存します。 トレーニングの例には、機能を備えたデータ項目とこれらの項目の特定の既知のクラスが含まれる場合があります(たとえば、「この16×16ピクセルのセットには手書き文字「a」が含まれます)」。

トレーニングが終了したら、a neural network canderive information from new data, even if it has not seen these particular data items before。 よくモデル化され、よく訓練されたネットワークは、画像、手書きの文字、音声を認識し、統計データを処理してビジネスインテリジェンスの結果を生成することができます。

近年、高性能で並列コンピューティングの進歩により、ディープニューラルネットワークが可能になりました。 Such networks differ from simple neural networks in thatthey consist of multiple intermediate (or hidden) layers。 この構造により、ネットワークはより複雑な方法で(再帰的、反復的、畳み込みなど)データを処理し、そこからより多くの情報を抽出できます。

3. プロジェクトのセットアップ

ライブラリを使用するには、少なくともJava 7が必要です。 また、一部のネイティブコンポーネントにより、64ビットJVMバージョンでのみ動作します。

ガイドを開始する前に、要件が満たされているかどうかを確認しましょう。

$ java -version
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

まず、必要なライブラリをMavenpom.xmlファイルに追加しましょう。 ライブラリのバージョンをプロパティエントリに抽出します(ライブラリの最新バージョンについては、Maven Centralリポジトリを確認してください)。


    0.9.1




    
        org.nd4j
        nd4j-native-platform
        ${dl4j.version}
    

    
        org.deeplearning4j
        deeplearning4j-core
        ${dl4j.version}
    

nd4j-native-platformの依存関係は、利用可能ないくつかの実装の1つであることに注意してください。

多くの異なるプラットフォーム(macOS、Windows、Linux、Androidなど)で利用可能なネイティブライブラリに依存しています。 CUDAプログラミングモデルをサポートするグラフィックカードで計算を実行したい場合は、バックエンドをnd4j-cuda-8.0-platformに切り替えることもできます。

4. データの準備

4.1. DataSetファイルの準備

機械学習の「HelloWorld」、つまりiris flower data setの分類について説明します。 これは、さまざまな種(Iris setosaIris versicolor、およびIris virginica)の花から収集されたデータのセットです。

これらの種は、花びらとがく片の長さと幅が異なります。 入力データ項目を分類する(つまり、特定の花がどの種に属するかを決定する)正確なアルゴリズムを作成するのは難しいでしょう。 しかし、よく訓練されたニューラルネットワークは、それを迅速に、そしてほとんど間違いなく分類できます。

このデータのCSVバージョンを使用します。列0..3には種のさまざまな特徴が含まれ、列4には値0、1または2でコード化されたレコードのクラスまたは種が含まれます。

5.1,3.5,1.4,0.2,0
4.9,3.0,1.4,0.2,0
4.7,3.2,1.3,0.2,0
…
7.0,3.2,4.7,1.4,1
6.4,3.2,4.5,1.5,1
6.9,3.1,4.9,1.5,1
…

4.2. データのベクトル化と読み取り

ニューラルネットワークは数字で動作するため、クラスを数字でエンコードします。 Transforming real-world data items into series of numbers (vectors) is called vectorization – deeplearning4jはdatavecライブラリを使用してこれを行います。

まず、このライブラリを使用して、ベクトル化されたデータを含むファイルを入力します。 CSVRecordReaderを作成するときに、スキップする行数(たとえば、ファイルにヘッダー行がある場合)と区切り記号(この場合はコンマ)を指定できます。

try (RecordReader recordReader = new CSVRecordReader(0, ',')) {
    recordReader.initialize(new FileSplit(
      new ClassPathResource("iris.txt").getFile()));

    // …
}

レコードを反復処理するために、DataSetIteratorインターフェースの複数の実装のいずれかを使用できます。 データセットは非常に大規模になる可能性があり、値をページングまたはキャッシュする機能が役立つ場合があります。

ただし、小さなデータセットには150レコードしかないため、iterator.next()を呼び出して、すべてのデータを一度にメモリに読み込みます。

We also specify the index of the class column。この場合は機能数(4)and the total number of classes(3)と同じです。

また、we need to shuffle the dataset to get rid of the class ordering in the original file.に注意してください

シャッフルの結果が常に同じになるように、デフォルトのSystem.currentTimeMillis()呼び出しの代わりに定数ランダムシード(42)を指定します。 これにより、プログラムを実行するたびに安定した結果を得ることができます。

DataSetIterator iterator = new RecordReaderDataSetIterator(
  recordReader, 150, FEATURES_COUNT, CLASSES_COUNT);
DataSet allData = iterator.next();
allData.shuffle(42);

4.3. 正規化と分割

トレーニングの前にデータを使用する必要があるもう1つのことは、データを正規化することです。 正規化は2段階のプロセスです。

  • データに関するいくつかの統計の収集(適合)

  • 何らかの方法でデータを変更(変換)して均一にする

正規化は、データの種類によって異なる場合があります。

たとえば、さまざまなサイズの画像を処理する場合、最初にサイズ統計を収集してから、画像を均一なサイズにスケーリングする必要があります。

しかし、数値の場合、正規化とは通常、いわゆる正規分布に変換することを意味します。 NormalizerStandardizeクラスはそれを助けることができます:

DataNormalization normalizer = new NormalizerStandardize();
normalizer.fit(allData);
normalizer.transform(allData);

データの準備ができたので、セットを2つの部分に分割する必要があります。

最初の部分は、トレーニングセッションで使用されます。 データの2番目の部分(ネットワークにはまったく表示されない)を使用して、トレーニングされたネットワークをテストします。

これにより、分類が正しく機能することを確認できます。 トレーニングにはデータの65%(0.65)を使用し、残りはテストに35%を使用します。

SplitTestAndTrain testAndTrain = allData.splitTestAndTrain(0.65);
DataSet trainingData = testAndTrain.getTrain();
DataSet testData = testAndTrain.getTest();

5. ネットワーク構成の準備

5.1. Fluent Configuration Builder

流なビルダーを使用して、ネットワークの構成を作成できます。

MultiLayerConfiguration configuration
  = new NeuralNetConfiguration.Builder()
    .iterations(1000)
    .activation(Activation.TANH)
    .weightInit(WeightInit.XAVIER)
    .learningRate(0.1)
    .regularization(true).l2(0.0001)
    .list()
    .layer(0, new DenseLayer.Builder().nIn(FEATURES_COUNT).nOut(3).build())
    .layer(1, new DenseLayer.Builder().nIn(3).nOut(3).build())
    .layer(2, new OutputLayer.Builder(
      LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
        .activation(Activation.SOFTMAX)
        .nIn(3).nOut(CLASSES_COUNT).build())
    .backprop(true).pretrain(false)
    .build();

ネットワークモデルを構築するこの単純化された流fluentな方法を使用しても、多くのダイジェストと微調整するパラメーターがあります。 このモデルを分解しましょう。

5.2. ネットワークパラメータの設定

iterations()ビルダーメソッドは、最適化の反復回数を指定します。

反復最適化とは、ネットワークが良好な結果に収束するまで、トレーニングセットで複数のパスを実行することを意味します。

通常、実際の大規模なデータセットでトレーニングを行う場合、複数のエポック(ネットワークを介したデータの完全なパス)と各エポックに対して1つの反復を使用します。 ただし、最初のデータセットは最小限であるため、1つのエポックと複数の反復を使用します。

activation()は、ノード内で実行されてその出力を決定する関数です。

最も単純な活性化関数は線形f(x) = x.ですが、ネットワークがいくつかのノードを使用して複雑なタスクを解決できるのは非線形関数だけであることがわかります。

org.nd4j.linalg.activations.Activation列挙型で調べることができる利用可能なさまざまな活性化関数がたくさんあります。 必要に応じて、アクティベーション関数を記述することもできます。 ただし、提供されている双曲線タンジェント(tanh)関数を使用します。

The weightInit() method specifies one of the many ways to set up the initial weights for the network.正しい初期重みは、トレーニングの結果に大きな影響を与える可能性があります。 計算にあまり踏み込まずに、ガウス分布の形式(WeightInit.XAVIER)に設定しましょう。これは、通常、開始に適しています。

他のすべての重み初期化メソッドは、org.deeplearning4j.nn.weights.WeightInit列挙型で検索できます。

Learning rateは、ネットワークの学習能力に大きく影響する重要なパラメーターです。

より複雑なケースでは、このパラメーターの調整に多くの時間を費やすことができます。 ただし、単純なタスクでは、かなり重要な値0.1を使用し、learningRate()ビルダーメソッドを使用して設定します。

ネットワークがトレーニングデータを「記憶」するときのOne of the problems with training neural networks is a case of overfitting

これは、ネットワークがトレーニングデータに過度に高い重みを設定し、他のデータに悪い結果をもたらす場合に発生します。

To solve this issue, we’re going to set up l2 regularizationと行.regularization(true).l2(0.0001)。 正則化は、大きすぎる重みに対してネットワークに「ペナルティを課し」、過剰適合を防ぎます。

5.3. ネットワーク層の構築

次に、密な(完全接続とも呼ばれる)レイヤーのネットワークを作成します。

最初のレイヤーには、トレーニングデータの列と同じ量のノードが含まれている必要があります(4)。

2番目の高密度レイヤーには3つのノードが含まれます。 これは可変の値ですが、前のレイヤーの出力の数は同じでなければなりません。

最終出力層には、クラスの数に一致するノードの数が含まれている必要があります(3)。 ネットワークの構造は図に示されています:

image

トレーニングが成功すると、入力を介して4つの値を受け取り、3つの出力の1つに信号を送信するネットワークができあがります。 これは単純な分類子です。

最後に、ネットワークの構築を完了するために、バックプロパゲーション(最も効果的なトレーニング方法の1つ)を設定し、行.backprop(true).pretrain(false)を使用した事前トレーニングを無効にします。

6. ネットワークの作成とトレーニング

次に、構成からニューラルネットワークを作成し、初期化して実行します。

MultiLayerNetwork model = new MultiLayerNetwork(configuration);
model.init();
model.fit(trainingData);

これで、残りのデータセットを使用してトレーニング済みモデルをテストし、3つのクラスの評価メトリックで結果を検証できます。

INDArray output = model.output(testData.getFeatureMatrix());
Evaluation eval = new Evaluation(3);
eval.eval(testData.getLabels(), output);

ここでeval.stats()を出力すると、クラス1とクラス2を3回間違えたものの、ネットワークはアイリスの花の分類に非常に優れていることがわかります。

Examples labeled as 0 classified by model as 0: 19 times
Examples labeled as 1 classified by model as 1: 16 times
Examples labeled as 1 classified by model as 2: 3 times
Examples labeled as 2 classified by model as 2: 15 times

==========================Scores========================================
# of classes: 3
Accuracy: 0.9434
Precision: 0.9444
Recall: 0.9474
F1 Score: 0.9411
Precision, recall & F1: macro-averaged (equally weighted avg. of 3 classes)
========================================================================

Fluent Configuration Builderを使用すると、ネットワークのレイヤーをすばやく追加または変更したり、他のパラメーターを微調整してモデルを改善できるかどうかを確認したりできます。

7. 結論

この記事では、deeplearning4jライブラリーを使用して、シンプルかつ強力なニューラルネットワークを構築しました。

いつものように、記事のソースコードはover on GitHubで入手できます。