読者です 読者をやめる 読者になる 読者になる

takeda_san’s blog

JavaFXとDeeplearning4jを頑張る方向。

サンプルプログラムをいじろう その2

前回のあらすじ

学習データを書き換えてうまくいくかと思ったが、そんなに甘くなかった。

takeda-san.hatenablog.com

やったこと

なぜ、出力がすべて1になったのか検討した。
まずはシグモイド関数を使ってるのに、出力に1以上の値を使っている点を直すべきだろう。
シグモイド関数は任意の実数を入力に、0から1の値を出力する。
出力の値を1000で割って1以下にしてみよう。
で、次が出力結果。

result0
 input  : 20,150,104.00
 output : 0.25
 answer : 0.25
result1
 input  : 20,150,106.00
 output : 0.25
 answer : 0.25
result2
 input  : 20,150,108.00
 output : 0.25
 answer : 0.25
result3
 input  : 20,150,108.00
 output : 0.25
 answer : 0.25

小数点以下2ケタまでしかなぜか出なくて詳しくはわからんが1以外の値が出た。
うまくいってるのかこれ。
どうやらgetDoubleやgetFloatでちゃんと出る模様。

result0
 input  : 2.0150104E7
 output : 0.24874994158744812
 answer : 0.25119999051094055
result1
 input  : 2.0150106E7
 output : 0.24874994158744812
 answer : 0.2467000037431717
result2
 input  : 2.0150108E7
 output : 0.24874994158744812
 answer : 0.24690000712871552
result3
 input  : 2.0150108E7
 output : 0.24874994158744812
 answer : 0.2502000033855438

毎回同じ数字やんけ。
学習データの出力を少し変えて、出力に変化がないか見てみる。

        INDArray    tIn     = Nd4j.create( new double[]{ 20150105 ,             // 入力1
                                                           20150106 ,             // 入力2
                                                           20150107 ,             // 入力3
                                                           20150108  },           // 入力4
                                           new int[]{ 4 , 1 } );            // サイズ
        INDArray    tOut    = Nd4j.create( new double[]{ 0.1512 , 0.8467 , 0.5469 , 0.7502} ,    // 出力1~4
result0
 input  : 2.0150104E7
 output : 0.6056897640228271
 answer : 0.15119999647140503
result1
 input  : 2.0150106E7
 output : 0.6056897640228271
 answer : 0.8467000126838684
result2
 input  : 2.0150108E7
 output : 0.6056897640228271
 answer : 0.5468999743461609
result3
 input  : 2.0150108E7
 output : 0.6056897640228271
 answer : 0.7501999735832214

同じやんけ。
入力値の違いが微々たるもの過ぎて、同じ数値だと勘違いしてるんかな?
営業日換算で1からカウントアップしてみよう。

        INDArray    tIn     = Nd4j.create( new double[]{ 1 ,             // 入力1
                                                           2 ,             // 入力2
                                                           3 ,             // 入力3
                                                           4  },           // 入力4
                                           new int[]{ 4 , 1 } );            // サイズ
        INDArray    tOut    = Nd4j.create( new double[]{ 0.2512 , 0.2467 , 0.2469 , 0.2502} ,    // 出力1~4
result0
 input  : 1.0
 output : 0.2483229637145996
 answer : 0.25119999051094055
result1
 input  : 2.0
 output : 0.24831531941890717
 answer : 0.2467000037431717
result2
 input  : 3.0
 output : 0.24835054576396942
 answer : 0.24690000712871552
result3
 input  : 4.0
 output : 0.24836908280849457
 answer : 0.2502000033855438

お、若干だけど数値が変わった。
変化が微妙すぎて違いが判らなかったということか?
ちなみに、学習回数を10倍の20000回にした結果。

result0
 input  : 1.0
 output : 0.24907267093658447
 answer : 0.25119999051094055
result1
 input  : 2.0
 output : 0.24896696209907532
 answer : 0.2467000037431717
result2
 input  : 3.0
 output : 0.2489119917154312
 answer : 0.24690000712871552
result3
 input  : 4.0
 output : 0.2488856166601181
 answer : 0.2502000033855438

それなりになってきたのかな?
学習回数こそパワーなのだろうか。
それって、脳みそ筋肉で良いと思います。

csvを読み込んでみる

それらしく動き出したので、扱うデータを増やしてみる。
csvを読み込むには次にようにするとよいらしい。 (手元の技術書から早くも仕様が変わった模様…)

// csvファイルから入力
RecordReader recordReader = new CSVRecordReader(0, ","); // 0行目から,をデミリタにして読む
recordReader.initialize(new FileSplit(new ClassPathResource("./9887_2015.csv").getFile())); // ファイルパスからcsvファイルを取得して初期化

int labelIndex = 0;  // 1カラム目が入力
int numClasses = 244;  // データ種類?
int batchSize = 50;  // バッチサイズ

DataSetIterator iterator = new RecordReaderDataSetIterator(recordReader, batchSize, labelIndex , numClasses);
DataSet csvData = iterator.next();

System.out.println("label: " + csvData.getLabels().toString());
System.out.println("features: " + csvData.getFeatures().toString());

実行結果

label: [[0.00, 1.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
~長いので略~
features: [2,512.00, 2,467.00, 2,469.00, 2,502.00, 2,540.00, 2,542.00, 2,528.00, 2,539.00, 2,507.00, 2,509.00, 2,507.00, 2,507.00, 2,500.00, 2,457.00, 2,388.00, 2,420.00, 2,446.00, 2,471.00, 2,471.00, 2,472.00, 2,441.00, 2,467.00, 2,441.00, 2,448.00, 2,451.00, 2,462.00, 2,472.00, 2,450.00, 2,456.00, 2,458.00, 2,460.00, 2,495.00, 2,499.00, 2,499.00, 2,514.00, 2,504.00, 2,515.00, 2,500.00, 2,491.00, 2,460.00, 2,452.00, 2,454.00, 2,447.00, 2,453.00, 2,451.00, 2,453.00, 2,457.00, 2,453.00, 2,450.00, 2,443.00]

何かは読み込まれているが、これで合っているのだろうか…
labelIndexには入力の列数を入れるらしい。値は0から始まる。
numClassesには、データの分類数を指定せよとのことなので、今回はcsvの行数(244)を指定した。
batchSizeには、バッチサイズを指定。データがあまりにも大きい場合はバッチ処理としていくつかの区切りで学習を区切るらしい。
この値は適当。

データをさしかえて実行。

Exception in thread "main" org.deeplearning4j.exception.DL4JInvalidInputException: Labels array numColumns (size(1) = 244) does not match output layer number of outputs (nOut = 1)

あっ、あっ… 次回へ続く。

次回の予定

・サンプルプログラムをいじる
・courseraの動画を見る
・Deep Learning Javaプログラミングを読む
・プログラミングのための線形代数を読む
Mavenのpomの読み方

サンプルプログラムをいじろう その1

前回のあらすじ

多層パーセプトロンプログラムを読んだ。

takeda-san.hatenablog.com

やったこと

今回からサンプルプログラムを少しいじって、何かデータを解析してみる。
どうせやるなら心躍る題材をということで、株価をデータとして扱います。

2015年の株価のデータで学習して2016年のデータで答え合わせをします。
日付を入力して株価(その日の終値)を出力するようなものを想定。

株価のデータは、ここから拝借しました。
何と便利な世の中か。

株価データ・株主優待情報・先物データ・ランキングデータ・CSVダウンロード無料 | 株式投資メモ・株価データベース

早速、csvを読み込んで…と行きたいが、こういうのは、まず小さく動作が確認できる機能を作ってそこから大きくしたほうがよいだろう。
数日分のデータを読んで、数日分の株価を出力するプログラムを書こう。

というわけでデータセットだけを挿げ替えたプログラム。

   public static void main(String[] args) throws Exception
    {
        // 変数定義
        int seed        = 123;          // 乱数シード
        int iterations  = 2000;         // 学習の試行回数
        int inputNum    = 1;            // 入力数
        int middleNum   = 10;           // 隠れ層のニューロン数
        int outputNum   = 1;            // 出力数

        INDArray    tIn     = Nd4j.create( new float[]{ 20150105 ,             // 入力1
                                                          20150106 ,             // 入力2
                                                          20150107 ,             // 入力3
                                                          20150108  },           // 入力4
                                           new int[]{ 4 , 1 } );            // サイズ
        INDArray    tOut    = Nd4j.create( new float[]{ 2512 , 2467 , 2469 , 2502} ,    // 出力1~4
                                           new int[]{ 4 , 1 } );            // サイズ
        DataSet     train   = new DataSet( tIn , tOut );                    // 入出力を対応付けたデータセット
        System.out.println( train );

        // ニューラルネットワークを定義
        MultiLayerConfiguration.Builder builder = new NeuralNetConfiguration.Builder()
                .seed(seed)
                .iterations(iterations)
                .learningRate(0.01)
                .weightInit(WeightInit.SIZE)
                .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
                .updater( Updater.NONE )
                .list()
                .layer(0, new DenseLayer.Builder()
                        .nIn(inputNum)
                        .nOut(middleNum)
                        .activation("sigmoid").build())
                .layer(1, new OutputLayer.Builder( LossFunctions.LossFunction.MSE )
                        .nIn(middleNum)
                        .nOut(outputNum)
                        .activation("sigmoid")
                        .build())
                .backprop(true).pretrain(false);

        // ニューラルネットワークを作成
        MultiLayerConfiguration conf        = builder.build();
        MultiLayerNetwork       perceptron  = new MultiLayerNetwork(conf);
        perceptron.init();

        // 確認用のリスナーを追加
        perceptron.setListeners( new ScoreIterationListener(1) );

        // 学習(fit)
        perceptron.fit( train );

        // パーセプトロンの使用
        for( int i=0 ; i<train.numExamples() ; i++ )
        {
            // i個目のサンプルについて、
            INDArray    input  = train.get(i).getFeatureMatrix();
            INDArray    answer = train.get(i).getLabels();
            INDArray    output = perceptron.output( input , false );
            System.out.println( "result" + i );
            System.out.println( " input  : " + input );
            System.out.println( " output : " + output );
            System.out.println( " answer : " + answer );
            System.out.flush();

        }

    }

動作結果

result0
 input  : 20,150,104.00
 output : 1.00
 answer : 2,512.00
result1
 input  : 20,150,106.00
 output : 1.00
 answer : 2,467.00
result2
 input  : 20,150,108.00
 output : 1.00
 answer : 2,469.00
result3
 input  : 20,150,108.00
 output : 1.00
 answer : 2,502.00

出力すべて1。
なんかそんな気はしてた。
楽して億万長者には、なれないのだ。

検討はまた次回。

次回の予定

・サンプルプログラムをいじる
・courseraの動画を見る
・Deep Learning Javaプログラミングを読む
・プログラミングのための線形代数を読む
Mavenのpomの読み方

多層パーセプトロンプログラムの理解

前回のあらすじ

パーセプトロンプログラムを最後まで読んだ。

takeda-san.hatenablog.com

やったこと

今回からは多層パーセプトロンプログラムを読んでいく。
courseraの機械学習動画や各種技術書で基礎をじっくりと…
と思っていたが結局プログラムを実際に動かした方が理解が早い。

Java DeepLearning4j 多層パーセプトロンの構築|軽Lab

早速プログラムを見ていく。

        INDArray    tIn     = Nd4j.create( new float[]{ 1 , 1 ,             // 入力1
                                                        1 , 0 ,             // 入力2
                                                        0 , 1 ,             // 入力3
                                                        0 , 0 },            // 入力4
                                           new int[]{ 4 , 2 } );            // サイズ
        INDArray    tOut    = Nd4j.create( new float[]{ 0 , 1 , 1 , 0} ,    // 出力1~4
                                           new int[]{ 4 , 1 } );            // サイズ
        DataSet     train   = new DataSet( tIn , tOut );                    // 入出力を対応付けたデータセット
        System.out.println( train );

このあたりは、パーセプトロンプログラムと同じ。
入力と出力のデータセットを生成している。

        // ニューラルネットワークを定義
        MultiLayerConfiguration.Builder builder = new NeuralNetConfiguration.Builder()
                .seed(seed)
                .iterations(iterations)
                .learningRate(0.01)
                .weightInit(WeightInit.SIZE)
                .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
                .updater( Updater.NONE )
                .list()
                .layer(0, new DenseLayer.Builder()
                        .nIn(inputNum)
                        .nOut(middleNum)
                        .activation("sigmoid").build())
                .layer(1, new OutputLayer.Builder( LossFunctions.LossFunction.MSE )
                        .nIn(middleNum)
                        .nOut(outputNum)
                        .activation("sigmoid")
                        .build())
                .backprop(true).pretrain(false);

次はニューラルネットワークの定義部分。
seed … 乱数生成 iteraions … 繰り返し回数 learningRate … 学習率   までは同じ。
waightInitだが、今回はWeightInit.SIZEが指定されている。

WeightInit.SIZEとは「最小および最大のシェイプを使用して、一定の一様分布からの得るサンプルウェイト」とあるが、シェイプとは?
グラフの形のことを言ってんのかな…?
この辺りはページに書いていることを、そういうもんだということで、とりあえず納得しておこう。

optimizationAlgo … 誤差関数には確率的勾配降下法を使う
updater … なし list … 層の数だが…これ、今回入力層含め3層だから引数に3を入れるべきでは?
と思ったが、手元の技術書のサンプルプログラムから仕様が変わったようだ。
何層でも引数なしが正しい。
layer … 各レイヤの定義。DenseLayerとは前のレイヤーと全接続するレイヤーのこと。
backprop … 誤差逆伝搬の有無を指定する。
pretrain … 事前学習の有無を指定する。

以降、まったく同じなので省略。

いくつかパラメータが変わっているが基本的にパーセプトロンと同じ。
ありがたいことに多層パーセプトロンプログラムの構造まで解説されているので、プログラムも難なく読むことができた。

次回の予定

・courseraの動画を見る
・Deep Learning Javaプログラミングを読む
・不明点の確認(乱数を指定する意味、確率的勾配降下法とは)
・プログラミングのための線形代数を読む
Mavenのpomの読み方

パーセプトロンプログラムの理解 その4

前回のあらすじ

学習率と重みについて、少し深堀り。

takeda-san.hatenablog.com

やったこと

学習の実行と結果表示部分のプログラムを読む。

        // 確認用のリスナーを追加
        perceptron.setListeners( new ScoreIterationListener(1) );
         
        // 学習(fit)
        perceptron.fit( train );
         
        // パーセプトロンの使用
        for( int i=0 ; i<train.numExamples() ; i++ )
        {
            // i個目のサンプルについて、
            INDArray    input  = train.get(i).getFeatureMatrix();
            INDArray    answer = train.get(i).getLabels();
            INDArray    output = perceptron.output( input , false );
            System.out.println( "result" + i );
            System.out.println( " input  : " + input );
            System.out.println( " output : " + output );
            System.out.println( " answer : " + answer );
            System.out.flush();
             
        }

perceptron.setListeners( new ScoreIterationListener(1) );
リスナを登録して、定期的にログを出力するようにするコード。
setListenersメソッドの引数で指定する。
ScoreIterationListener(1)で学習一回につきログを1回出力するようだ。

perceptron.fit( train );
学習を実行する。

train.numExamples()でデータセット内のサンプル数が取得できる。
INDArray input = train.get(i).getFeatureMatrix();、で入力値を取得できる。
INDArray answer = train.get(i).getLabels();、で入力値につけたラベル(回答)を取得できる。
INDArray output = perceptron.output( input , false );、で学習させたパーセプトロンに入力値を与えて出力を得る。
次の行からは学習データの答えと出力値をコンソール出力して確認している。

ようやく最後まで読み切った。
プログラムの内容自体はJavaDocソースコードをよーーーーく読めば何とか理解できるレベルだが、そもそもの機械学習ディープラーニングの知識が明らかに不足しているので、その寄り道に時間が恐ろしくかかってしまった。
一旦、Deeplearning4jのコードから離れて、基礎知識をかためていこうと思う。

その道の方には有名なこのサイトをとりあえず見ていこうと思う。
最初のほうだけちらっと見たが、これも無料でやってもらって申し訳ないという気持ちになるすばらしいコンテンツだ。
本編のほうは日本語字幕がついていて、感謝の気持ちしかない。

https://www.coursera.org/learn/machine-learning

あとは、挫折していたDeep Learning Javaプログラミングをもう一度読んでいく。
すこし賢くなったので、前よりは読み進められるだろう。

次回の予定

・courseraの動画を見る
・Deep Learning Javaプログラミングを読む
・不明点の確認(乱数を指定する意味、確率的勾配降下法とは)
・プログラミングのための線形代数を読む
Mavenのpomの読み方

学習率、重みってなんだ?

前回のあらすじ

ニューラルネットワークの定義、生成部分のコードを読んだ。

takeda-san.hatenablog.com

やったこと

重みってなんだ?

前回のニューラルネットワークの定義の中で重みというパラメータが登場した。
この重みは、以前にやった下記の数式におけるvの値のこと。
重みを適切に調整し、欲しい出力を得る。


\displaystyle f(x) = f( \sum_{i=0}^{N} v_i x_i - \theta )

takeda-san.hatenablog.com

プログラム内に登場したパラメータとしての重みは、各入力に対する重みの初期値を設定しているっぽい。
なぜ初期化が必要かというと、学習の進むスピードが変わるらしい。

kaeken.hatenablog.com

多層パーセプトロンにおいて、学習時の勾配消失が問題になっていたが、そのあたりと関係がありそう・・・?
初期値を設定する意味は分かったし、話がさらに深くなりそうなので、いったんこの辺で打ち切り。

学習率ってなんだ?

これまた、ニューラルネットワークの定義の中で登場した学習率。
この学習率とは、重みのパラメータを学習していく中で更新していくワケですが、その更新の幅を指しているようです。
1より小さくするのが普通らしい。
この値を小さくすればするほど更新幅が小さいから正確に学習できるが、計算回数が多くなる?
幅大きいと学習によるパラメータ調整が行ったり来たりで収束しない?
値を何を基準にすればよいのかは、また別途。

次回の予定

・不明点の確認(乱数を指定する意味、確率的勾配降下法とは) ・プログラミングのための線形代数を読む ・サンプルプログラム(Perceptron/LenetMnistExample)を読む ・Mavenのpomの読み方

パーセプトロンプログラムの理解 その3

前回のあらすじ

学習データの生成方法部分を読んだ。

takeda-san.hatenablog.com

やったこと

なんとも本丸感がある、このワンライナー。 落ち着いてひとずつ確認していきます。

        // ニューラルネットワークを定義
        MultiLayerConfiguration.Builder builder = new NeuralNetConfiguration.Builder()
                .seed(seed)
                .iterations(iterations)
                .learningRate(0.01)
                .weightInit(WeightInit.XAVIER)
                .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
                .updater( Updater.NONE )
                .list()
                .layer(0, new OutputLayer.Builder( LossFunctions.LossFunction.MSE )
                        .nIn(inputNum)
                        .nOut(outputNum)
                        .activation("sigmoid")
                        .build())
                .backprop(true).pretrain(false);

        // ニューラルネットワークを作成
        MultiLayerConfiguration conf        = builder.build();
        MultiLayerNetwork       perceptron  = new MultiLayerNetwork(conf);
        perceptron.init();

大きな流れとしては以下のようになっているようだ。

  1. NeuralNetConfiguration.Builder()でニューラルネットワークの設定し、buildメソッドで設定オブジェクトを生成
  2. 1.で作った設定を使用してモデルのインスタンスを生成
  3. 2.で作ったモデルを初期化する

MultiLayerConfiguration.Builderは、モデルの全体的な構造を定義するビルダークラス。
NeuralNetConfiguration.Builder()は、ニューラルネットワークのビルダーメソッド。
seed()は、乱数の種を指定するメソッド。
んー、なぜ乱数を生成する必要があるんだろうか…
別途調べよう。

深層学習(ディープラーニング)は自然現象であると考えると捉えやすい - WirelessWire News(ワイヤレスワイヤーニュース)

iterations()は、繰り返し回数を指定するメソッド。今回は1000回学習する。
learningRate()は、学習率を指定するメソッド。今回の学習率は0.01。
学習率とはモデルのパラメータを更新する幅らしい。
これも別途調べる。

weightInit()は、重みを指定するメソッド。
重みとは個々の神経細胞同士の繋がりの強さ(伝達物質の伝導しやすさ)を示す。らしい
これも…別途調べる。

optimizationAlgo()は、学習アルゴリズムを指定するメソッド。
確率的勾配降下法を使用する。
これも…・・・別途調べる。

updater()は、学習率の最適化など学習アルゴリズムの更新に使う。今回はNONEなので特に更新なし。
list()は、ニューラルネットワークの層の数を指定する。今回は1層なので指定なし。
 →入力層は数えない
layer()は、ニューラルネットワークのレイヤーを指定する。
 →活性化関数にシグモイド関数、誤差関数にMSE、入力が2つ、出力1つ(ORなので)
backprop()は、誤差逆伝搬の有無を指定するメソッド。
pretrain()は、事前学習の有無を指定するメソッド。

一通り技術書&JavaDocとにらめっこして調べてましたけど、下記記事に全部乗ってましたね。
ま、まぁ自分で調べることに意味があるから…

Java DeepLearning4j パラメータの設定|軽Lab

次回の予定

・不明点の確認(乱数を指定する意味、学習率とは、重みとは、確率的勾配降下法とは)
・プログラミングのための線形代数を読む
・サンプルプログラム(Perceptron/LenetMnistExample)を読む
Mavenのpomの読み方

パーセプトロンプログラムの理解 その2

前回のあらすじ

活性化関数として使われる、シグモイド関数
誤差関数として使われるMSEについてそれとなくわかった気になる。

takeda-san.hatenablog.com

やったこと

実際にプログラムを読んでいく。

INDArray    tIn     = Nd4j.create( new float[]{ 1 , 1 ,         // 入力1
                                                        1 , 0 ,         // 入力2
                                                        0 , 1 ,         // 入力3
                                                        0 , 0 },        // 入力4
                                           new int[]{ 4 , 2 } );        // サイズ

INDArrayとは、Deeplearning4jに含まれるND4j内に定義された行列を格納する型。
Nd4jのファクトリクラスで生成されたオブジェクトを格納する。
Nd4j.createメソッドの第一引数にfloatの配列、第二引数にintの配列を渡している。
JavaDocを読むと第一引数は「N次元配列」をメモリに連続して格納するために一つの配列にデータを格納したもの。
第二引数は行列の行, 列をしていするものらしい。
大量にあるテストデータで、いちいち多次元配列を作っていたのではメモリ効率が悪いというのは理解できる。

http://nd4j.org/doc/org/nd4j/linalg/factory/Nd4j.html#create-float:A-int:A-

つまり、ここは4行、2列の行列([[1,1],[1,0],[0,1],[0,0])のデータを作りますということ。

次の出力テストデータの生成も同様に4行1列のデータを作りますということ。

INDArray    tOut    = Nd4j.create( new float[]{ 1 , 1 , 1 , 0} ,
                                           new int[]{ 4 , 1 } );        // サイズ

次の行はコメント通り、入出力をワンセットとして扱うためのデータセットとして入力データ、出力データを格納している。

DataSet     train   = new DataSet( tIn , tOut );         // 入出力を対応付けたデータセット

しかしまぁ、Eclipseデフォルトのフォーマッタだとインデントをせっかくそろえても崩れて悲しい気持ちになる。 ちょっとカスタマイズしようか…

次回の予定

・プログラミングのための線形代数を読む
・サンプルプログラム(Perceptron/LenetMnistExample)を読む
Mavenのpomの読み方