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

takeda_san’s blog

JavaFXとDeeplearning4jを頑張る方向。

プログラミングのための線形代数「1.1 ベクトルと空間」

読書感想文

やったこと

プログラミングのための線形代数「1.1 ベクトルと空間」を読む。

表紙の主な対象読者の記述にぐっときたので買ってしまいました。
『研究・仕事で信号処理なりデータ解析なりをやろうとして、その方面の本を読んだら、線形代数が出てきた。どうにもよくわからないから勉強したい(し直したい)けど、証明ばかりの数学の教科書や、わかった気にしかならない入門書しかなくて困る。』
素晴らしい。
空いた時間に少しずつ読んでいきます。

ベクトルって何?おいしいの?から解説してくれるので大変ありがたい。
また、整数と実数も怪しい私のような読者向けにコラムまで用意してくれる親切ぶりであった。
この節の内容は、大学でやった内容でまだ覚えている範囲。

随所で数学派の皆さんとRubyユーザにおびえてる記述があるのは何なんですかね。
聞きつけると肩パットのお兄さん達が、乗り込んでくるんですかね。

平均二乗誤差について少しだけ理解した話

機械学習

前回のあらすじ

分類とラベルについて、今更理解した。

takeda-san.hatenablog.com

やったこと

統計学の入門書を読んでいる。

www.kyoritsu-pub.co.jp

要するにやる夫で学ぶ統計学的なものである。
半分ぐらいまで読んだが、今のところ躓くことなく読めている。
(題名については、漢字に長々とルビが振ってあるところが素敵だと思った)

以前に誤差関数に平均二乗誤差(MSE)を使ったサンプルプログラムを読んで、中途半端な理解のまま放置していた。

takeda-san.hatenablog.com

ちょっとばかり入門書で自信がついたので再び見てみよう。


\displaystyle MSE( \sum (t-o) ^ 2 )

相変わらず威圧感ある数式である。
サンプルプログラムの解説ページでは上記の表記であったが、わかりやすく書くと次のような数式らしい。


\displaystyle MSE(c) = \frac{1}{n} \sum_{i=1}^{n} (x_i - c) ^ 2

今回の場合、xが学習データの出力値(正解の値)、cがとあるパラメータでの出力値(予測値)と考えて、分散として求める。


\displaystyle \sum_{i=1}^{n} (x_i - c) ^ 2

それをデータの個数で割るとばらつきの平均値が求められる。
これを誤差の度合いとして小さくしていきましょうというのが、誤差関数に平均二乗誤差を使うということなのだろう。
前よりは納得。

しかし、courseraの機械学習コースでも、統計学の入門書でも分散の絶対値ではなく、2乗する意味については
「だって、こっちのほうが便利だろ?な。そうだろ?」
というばかりで一切解説してくれない。
業界のタブー的なものなのだろうか。

次回の予定

未実施

クラスタリングのサンプルプログラムを読む
Mavenのpomの読み方

実施中

統計学の入門書一冊読む
・courseraの機械学習の動画を見る
・Deep Learning Javaプログラミングを読む
・プログラミングのための線形代数を読む

分類とラベルについて理解した話

機械学習

前回のあらすじ

ようやく、csvからデータを読み込み想定通りの出力を得る。

takeda-san.hatenablog.com

やったこと

前々回、ハマったラベルとクラスの概念。
下記のページが非常にわかりやすかった。

やる夫で学ぶ機械学習 - 序章 - · けんごのお屋敷

クラス(分類:Classification)とは、判別の種類がいくつあるのかその種類数を表す。
メールが「スパムである」、「スパムでない」の2種類に分けられるときに、Classificationは2。
前回のプログラムでは、株価が翌日…「上がる」、「下がる」、「そのまま」の3種類にしたのでClassificationは3ということだった。
最初は翌日の終値を予想しようとしていたが、これを分類として扱うと1円刻みで分類しないといけないので大変だっただろうな。

ラベル(ラベル:Label)とは、教師データの正解データのこと。
株価が翌日…「上がる」、「下がる」、「そのまま」がラベルだ。
最初は日付データ(入力データ)をラベルとしていたので、これは間違い。

今回作成したプログラムは教師データありの分類について、触れた。
次は教師データなしのクラスタリングについて、サンプルプログラムの理解から始めていこうと思う。

統計わからん

損失関数と活性化関数に使われる各種関数を理解するのに、そもそもの前提知識が足りていない気がする。
前回でてきて後回しにした対数尤度関数、softmax関数だが、優しく書いてあるであろうページを読んでも、まったくわからん。
そもそも、ご存じない記号が出てきてて、歯が立たない。
(平均。偏差の概念もおぼつかないのに、その先を理解するというのは無理なのかも)

引き続きプログラムも書いていくが、統計学の入門書を読んだほうがよさそう。
すでにcourseraの機械学習の動画、線形代数の本で手いっぱいだが、趣味のプログラムなのでゆっくり少しずつ進めていこうと思う。

次回の予定

未実施

クラスタリングのサンプルプログラムを読む
統計学の入門書一冊読む
Mavenのpomの読み方

実施中

・courseraの機械学習の動画を見る
・Deep Learning Javaプログラミングを読む
・プログラミングのための線形代数を読む

setResizableをfalseにすると、不要な余白が生じる問題

Java JavaFX

唐突に始まるJavaFX記事。

事象

Scene Builder上でのFXMLプレビューと実際にコントローラーを実装して起動したときの画面サイズが違う気がする。

もともと、この事象に気が付いたのはStageが保持しているSceneを別のSceneで差し替えて画面を切り替えるような処理を書いているとき。
なぜか差し替え処理の後に画面サイズが一回り小さくなる。
デバッグしていくうちに原因が分かった。

原因

Stageが持つ、resizablePropertyをfalseにしているとSceneの外側に余白ができるっぽい。

Stage (JavaFX 8)

問題が再現するコードは以下の通り。
ボタンを押したときに、ステージのサイズをSceneの大きさに合わせるメソッドを走らせる。
不要な余白(マージン)があればステージ幅が小さくなるはずだ。

わかりやすくするためにボタンの大きさとSceneの大きさは同じにしている。

package application;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            HBox root = new HBox();

            // Sceneと同じ大きさのボタンを作る
            Button button = new Button("sizeToScene");
            button.setPrefWidth(400); // 幅400px
            button.setPrefHeight(400); // 高さ400px

            // ステージのサイズをシーンの大きさに合わせる
            button.setOnAction(event -> {
                primaryStage.sizeToScene();
            });
            root.getChildren().add(button);

            // シーンとステージの表示
            Scene scene = new Scene(root, 400, 400);
            primaryStage.setScene(scene);
            primaryStage.setResizable(false);
            primaryStage.show();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

実行結果がこちら。

sizeToScene実行前

f:id:takeda_san:20170227222120p:plain

sizeToScene実行後

f:id:takeda_san:20170227222125p:plain

起動時に右下に12~3pxぐらいの余白があるが、sizeToSceneをすると消えている。
ちなみに「primaryStage.setResizable(false);」をtrueにすると余白はできない。

対応策

ここにもある通り、面倒だが毎回、sizeToSceneで余白を消すしかないようだ。
しかもこの件、バグらしく前から要望が出ているものの直されてないとのこと。
(この質問自体、結構前のものだ)

stackoverflow.com

レイアウトの都合上、リサイズされたくない画面って結構あるとおもうんですけどね。
Java 9では直っていることを祈っています。
ちなみに実行環境はWindows + JRE 1.8.0_121でした。

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

機械学習 Deeplearning4j Java

前回のあらすじ

そもそも、教師データの想定が間違っていたのだな。

takeda-san.hatenablog.com

やったこと

まずは、教師データの見直し。
今使っている株価のデータはこんなデータが入っている。

日付,始値,高値,安値,終値,出来高,終値調整値
"2015-01-05","2507","2538","2491","2512","37300","2512"

これにラベルを付けて教師データとして使えるようにしたい。 結果、こうなった。

営業日,始値,高値,安値,終値,出来高,終値調整値,Label
1,2507,2538,2491,2512,37300,2512,0

日付は入力値が数値しか受け付けないので、営業日にした。
Labelと書いてあるところは、翌日株価が上がったら2、下がったら0、変化なしなら1を入れるようにしている。

営業日,始値,高値,安値,終値,出来高,終値調整値 … 入力
Label … 出力

にしようという考えだ。
もちろん普通に考えて前日の取引データで翌日の株価が決まるわけがないが、今回は実験だ。
そういうもんだということにする。

そしてプログラムを書きからコピペしてくる。

dl4j-examples/CSVExample.java at master · deeplearning4j/dl4j-examples · GitHub

書き換えるのはこの部分。

int labelIndex = 7;
int numClasses = 3;
int batchSize = 244; 

ラベルは文字通りLabel列。0から数えて7番目。
クラスの数は、上がった場合の2、下がった場合の0、変化なしの1の3種類。
バッチサイズは1回ですべて読み込むので、ファイル行数の244。

とりあえず、実行してみる。

==========================Scores========================================
 Accuracy:        0.3837
 Precision:       0.4039
 Recall:          0.2851
 F1 Score:        0.3343
========================================================================

お、結果が出力された。
ちなみに、
 Acuracy … 正解率
 Preision … 精度
 Recall … 再現率
 F1 Score … 精度と再現率の調和平均 とのこと。
つまり、38%しか正解してないということは大損ですね。
数値的には非常に残念な結果だが、どうやら正しく動いているらしい。

せっかくなので出力値を見てみよう。

21:36:52.547 [main] INFO  sample.d4j.Gyudon - actual [0.00, 0.00, 1.00]vs predited [0.45, 0.02, 0.52]
21:36:52.548 [main] INFO  sample.d4j.Gyudon - actual [0.00, 0.00, 1.00]vs predited [0.36, 0.03, 0.61]
21:36:52.548 [main] INFO  sample.d4j.Gyudon - actual [1.00, 0.00, 0.00]vs predited [0.57, 0.02, 0.41]
21:36:52.556 [main] INFO  sample.d4j.Gyudon - actual [0.00, 0.00, 1.00]vs predited [0.57, 0.02, 0.41]
21:36:52.557 [main] INFO  sample.d4j.Gyudon - actual [0.00, 0.00, 1.00]vs predited [0.55, 0.02, 0.43]

actual [0.00, 0.00, 1.00]が、テストのラベル。
つまりは正解の値。
predited [0.45, 0.02, 0.52]が、予測のラベル。
つまりは学習した結果の値。

うーん、正解しているものあるが差が微妙すぎる。
興味本位で、学習回数を10倍に。

==========================Scores========================================
 Accuracy:        0.5233
 Precision:       0.5356
 Recall:          0.3702
 F1 Score:        0.4378
========================================================================

お、50%超えた。
これで、億万長者やん。

冗談はさておき、前回まで使っていたプログラムとの差異を見ていく。

allData.shuffle();
SplitTestAndTrain testAndTrain = allData.splitTestAndTrain(0.65);  //Use 65% of data for training

DataSet trainingData = testAndTrain.getTrain();
DataSet testData = testAndTrain.getTest();

allData.shuffle(); csvから読み込んだデータセットのレコードの並び順をシャッフルする。
SplitTestAndTrain testAndTrain = allData.splitTestAndTrain(0.65); データセットをトレーニングデータと学習後に使うテストデータに分ける。
コメントの通り、トレーニングデータに65%割り振られる。
DataSet trainingData = testAndTrain.getTrain(); トレーニングデータとして割り振られたデータセットを取得する。
DataSet testData = testAndTrain.getTest(); テストデータとして割り振られたデータセットを取得する。

//We need to normalize our data. We'll use NormalizeStandardize (which gives us mean 0, unit variance):
DataNormalization normalizer = new NormalizerStandardize();
normalizer.fit(trainingData);           //Collect the statistics (mean/stdev) from the training data. This does not modify the input data
normalizer.transform(trainingData);     //Apply normalization to the training data
normalizer.transform(testData);         //Apply normalization to the test data. This is using statistics calculated from the *training* set

データの正規化を行っているらしい。
データの正規化とは、「学習に関係ないデータ間の差異を,学習に影響を及ぼさないように取り除くこと」らしい。
具体的な手法など、今は深入りせず、そういうものだと思っておこう。

sig.tsg.ne.jp

MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder()
            .seed(seed)
            .iterations(iterations)
            .activation(Activation.TANH)
            .weightInit(WeightInit.XAVIER)
            .learningRate(0.1)
            .regularization(true).l2(1e-4)
            .list()
            .layer(0, new DenseLayer.Builder().nIn(numInputs).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(outputNum).build())
            .backprop(true).pretrain(false)
            .build();

ニューラルネットワークの定義部分。
活性化関数にtanhを使っている。
でもlayerメソッド内ではないぞ…。

deeplearning4j.org

どうやら、出力層以外の層の活性化関数は各層でも、その前の段階どちらでも定義できるらしい。

損失関数に負の対数尤度関数を使っている。
対数尤度関数って何だろうか。
そもそも読めない…

qiita.com

ゆうどって読むのね。
こ、これは高度な知能が求められそう…
後ほどゆっくり読もう…な。

出力層の活性化関数にはsoftmax関数を使用している。

hiro2o2.hatenablog.jp

後ほどゆっくり読もう…な。
あとは今までと同じかな。

前回のプログラムでは、活性化関数を文字列で指定していたが、非推奨になっていたようで警告が出ていた。 「.activation(“sigmoid”)」の部分。 ここはActivationというenumクラスを使って指定すると良い。

.layer(0, new DenseLayer.Builder()
                        .nIn(inputNum)
                        .nOut(middleNum)
                        .activation("sigmoid").build())
.layer(0, new DenseLayer.Builder()
                        .nIn(inputNum)
                        .nOut(middleNum)
                        .activation(Activation.SIGMOID).build())

というわけで、後回しになっているもろもろを次回見ていく。
あと、当初目的の2015年データのすべてで学習して、2016年データでテストするのもやりたい。

次回の予定

・対数尤度関数、softmax関数とは
・courseraの動画を見る
・Deep Learning Javaプログラミングを読む
・プログラミングのための線形代数を読む
Mavenのpomの読み方

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

機械学習 Deeplearning4j Java

前回のあらすじ

csvからのデータ読み込みができない。

takeda-san.hatenablog.com

やったこと

参考になる情報がないなら公式にいけばいいじゃない。

dl4j-examples/CSVExample.java at master · deeplearning4j/dl4j-examples · GitHub

というわけで、csvを読み込んでいる、サンプルコードを見てみる。

//Second: the RecordReaderDataSetIterator handles conversion to DataSet objects, ready for use in neural network
int labelIndex = 4;     //5 values in each row of the iris.txt CSV: 4 input features followed by an integer label (class) index. Labels are the 5th value (index 4) in each row
int numClasses = 3;     //3 classes (types of iris flowers) in the iris data set. Classes have integer values 0, 1 or 2
int batchSize = 150;    //Iris data set: 150 examples total. We are loading all of them into one DataSet (not recommended for large data sets)

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

iris.txtというのはよく使うサンプルデータセットらしい。

https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data

3種類(Iris-setosa、Iris-versicolor、Iris-virginica)のデータが150行格納されている。
サンプルコードと照らし合わせてみよう。

int labelIndex = 4;     //5 values in each row of the iris.txt CSV: 4 input features followed by an integer label (class) index. Labels are the 5th value (index 4) in each row

iris.txtには1行あたり5つの値が含まれている。
5つめの値がラベルなので、0開始の5番目の値である4を指定する。

int numClasses = 3;     //3 classes (types of iris flowers) in the iris data set. Classes have integer values 0, 1 or 2

iris.txtには3種類の値が含まれる。
この種類のことをクラスと呼ぶらしい。
なのでここの値は3。(これは0から数えないんだ…配列じゃないから?)

int batchSize = 150;    //Iris data set: 150 examples total. We are loading all of them into one DataSet (not recommended for large data sets)

iris.txtには150行のデータが格納されている。
batchSizeには一度に読み込むデータを指定できる。
今回はデータの数が少ないので一度にすべて読み込む。
なので、150。

なるほど、公式のサンプルが一番わかりやすい。
次から各種クラスの使い方に困ったら見にこよう。

つづいて、このルールに沿って前回のプログラムを修正してみる。

int labelIndex = 0;  // 1カラム目がラベル
int numClasses = 244;  //    データの種類は244
int batchSize = 244;  // バッチサイズ。一度にすべて読み込む

あれ?バッチサイズ以外は前回と変わらないような。

Exception in thread "main" org.deeplearning4j.exception.DL4JInvalidInputException: Invalid classification data: expect label value (at label index column = 0) to be in range 0 to 243 inclusive (0 to numClasses-1, with numClasses=244); got label value of 244

うーん。問題は別の場所にありそう。
とりあえず、CSVExample.javaを丸コピーで動かしてみよう。

Exception in thread "main" java.lang.NumberFormatException: For input string: "Iris-setosa"

データは数値型しか受け付けないようだ。
リポジトリをあさってみると、文字列を数値に置換したデータがあった。
3種類の文字列を0~2に置き換えているようだ。
これもなぜか0から始めないといけない模様。

deeplearning4j/iris.dat at master · deeplearning4j/deeplearning4j · GitHub

これにデータを置き換えて、再度実行。

===========INPUT===================
[[5.10, 3.50, 1.40, 0.20],
~長いので略~
 [5.90, 3.00, 5.10, 1.80]]
=================OUTPUT==================
[[1.00, 0.00, 0.00],
~長いので略~
 [0.00, 0.00, 1.00]]

お、いけてるっぽい。
次にこの謎の出力の読み方を考えてみる。
まずは、前回のプログラム上にデータセットを書いていたころの出力。

===========INPUT===================
[1.00, 2.00, 3.00, 4.00]
=================OUTPUT==================
[0.25, 0.25, 0.25, 0.25]

値が丸まっていて出力データが区別がつかないが、入力と出力が対応していることがわかる。
つぎに今回のirisデータセット

===========INPUT===================
[[5.10, 3.50, 1.40, 0.20],
 [4.90, 3.00, 1.40, 0.20],
 [4.70, 3.20, 1.30, 0.20],
 [4.60, 3.10, 1.50, 0.20],
 [5.00, 3.60, 1.40, 0.20],
~略~
=================OUTPUT==================
[[1.00, 0.00, 0.00],
 [1.00, 0.00, 0.00],
 [1.00, 0.00, 0.00],
 [1.00, 0.00, 0.00],
 [1.00, 0.00, 0.00],

この5行と対応するcsvの行が次のとおり。

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
4.6,3.1,1.5,0.2,0
5.0,3.6,1.4,0.2,0

なるほど、1~4列目までが入力になっていると。
つまりCSVExample.javaでやりたいことは、1~4列目の4つの入力を使って、どのラベルが出力されるかを見ていたということらしい。
となると、今回の指定は入力と出力が逆となっていたようだ。
csvファイルが、1列目に営業日、2列目に株価なのでラベルは2列目ということになる。

ここまでくると、一度コードを全部捨ててCSVExample.javaを元にやり直したほうが良い気がしてきた。 一からの再出発は、また次回。

次回の予定

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

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

機械学習 Deeplearning4j Java

前回のあらすじ

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

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の読み方