JavaFX グラフ描画〜AreaChartを使う〜

イントロダクション

ND4Jでグラフを描いて、2次関数とかを描画するのに良い方法はないかと探しておりました。そんなわけでこのグラフはどうだろうか?

AreaChart

実際に写経して動かしてみました。追加で作成したコードは以下の様にやりました。

<実装コード>

public class AreaChartView extends Parent implements MathKitView {

	/* (non-Javadoc)
	 * @see zenryokuservice.mathkit.MathKitView#loadView(javafx.scene.layout.VBox)
	 */
	@Override
	public Parent loadView(VBox root) {
        final NumberAxis xAxis = new NumberAxis(1, 31, 1);
        final NumberAxis yAxis = new NumberAxis();
        final AreaChart<Number,Number> ac = 
            new AreaChart<Number,Number>(xAxis,yAxis);
        ac.setTitle("Temperature Monitoring (in Degrees C)");
 
        XYChart.Series seriesApril= new XYChart.Series();
        seriesApril.setName("April");
        seriesApril.getData().add(new XYChart.Data(1, 4));
        seriesApril.getData().add(new XYChart.Data(3, 10));
        seriesApril.getData().add(new XYChart.Data(6, 15));
        seriesApril.getData().add(new XYChart.Data(9, 8));
        seriesApril.getData().add(new XYChart.Data(12, 5));
        seriesApril.getData().add(new XYChart.Data(15, 18));
        seriesApril.getData().add(new XYChart.Data(18, 15));
        seriesApril.getData().add(new XYChart.Data(21, 13));
        seriesApril.getData().add(new XYChart.Data(24, 19));
        seriesApril.getData().add(new XYChart.Data(27, 21));
        seriesApril.getData().add(new XYChart.Data(30, 21));
        
        XYChart.Series seriesMay = new XYChart.Series();
        seriesMay.setName("May");
        seriesMay.getData().add(new XYChart.Data(1, 20));
        seriesMay.getData().add(new XYChart.Data(3, 15));
        seriesMay.getData().add(new XYChart.Data(6, 13));
        seriesMay.getData().add(new XYChart.Data(9, 12));
        seriesMay.getData().add(new XYChart.Data(12, 14));
        seriesMay.getData().add(new XYChart.Data(15, 18));
        seriesMay.getData().add(new XYChart.Data(18, 25));
        seriesMay.getData().add(new XYChart.Data(21, 25));
        seriesMay.getData().add(new XYChart.Data(24, 23));
        seriesMay.getData().add(new XYChart.Data(27, 26));
        seriesMay.getData().add(new XYChart.Data(31, 26));
        root.getChildren().add(ac);
        ac.getData().add(seriesMay);
        ac.getData().add(seriesApril);
        return root;
	}
}

実行結果

うーん、データの表示には使えそうだが、今は2次関数を描きたいので別なものを探さないとだな。。。

このソースだけでグラフが表示できるのは以前作成した仕組みがあるのでそちらを参照ください。

  1. JavaFX + ND4J 〜グラフ作成の準備〜
  2. JavaFX + ND4J 〜グラフ作成:とりあえず表示〜

でわでわ。。。

関連ページ一覧

  1. Java 初めてでも大丈夫〜ステップアッププログラミングのススメ〜
  2. ステップアッププログラミング〜Java FxでHelloWorld解説〜
  3. Java StepUpPrograming〜JavaFX で四則計算〜
  4. Java StepUpPrograming〜JavaFXで画面切り替えを作る1〜
  5. Java StepUpPrograming〜JavaFXで画面切り替え2ボタン作成〜
  6. Java StepUpPrograming〜JavaFXで画面切り替え3アクション〜
  7. Java StepUpPrograming〜JavaFXで画面切り替え4Pane切り替え〜
  8. Java StepUpPrograming〜JavaFXで画面切り替え5WebEngine

JavaFX + ND4Jで機械学習準備

  1. JavaFX + ND4J〜数学への挑戦1:ND4Jのインストール〜
  2. JavaFX + ND4J〜数学への挑戦2: 行列の計算〜
  3. Java + ND4J 〜数学への挑戦3: ベクトル(配列)の作成方法〜









JavaFX + ND4J 〜グラフ作成:とりあえず表示〜

イントロダクション

前回は、作成するアプリ→「グラフ量産アプリケーション」の概要=クラス図を作成しました。

実はこのクラス図は、足りない部分があります。クラスの関係図は描けているのですが、他に必要なものがあります。これを実装するのには

画面クラスを呼び出す仕組みが必要

なので、今回はこの機能を追加します。

まぁNoteを追加しただけですが。。。

ポイント

メインメソッドを起動してからプロパティファイルを参照してMathKitViewを表示する様な仕組みを作ります。※クラス図は、クラスの関係を記載しただけなのでこの様な実装になるかどうかはわかりませんが、自分はこの様なイメージで作成しました。

そして、実装した結果クラスの一覧をEclipseで一覧すると以下の様になります。

そして、実行してみます。

グラフはこんな感じ

左にある赤い字は、ND4Jを起動した時にデルログです。実行するたびに違う値のグラフができます。※データはND4Jでランダムに生成しています。




JavaFX + ND4J 〜グラフ作成の準備〜

イントロダクション

前回は、ベクトル(配列)の生成を行いました。そして、ベクトルの基本的な扱いに関してはだいたい理解できたので次のステップ「グラフの作成」に入りたいと思います。

グラフをたくさん作るには?

Javaでのプログラムソースの量産はとても簡単にできます。正直に言うとちゃんと考えないと余計なプログラムソースで埋もれてしまいます。

どーするか?

ちょいとした仕組みを作ります。初めは土台から作成しようかと思ったのですが、やってみないとわからないこと(どんなグラフをどのように作るか?など)が多いため、ちょっとずつ作成して行こうと言う結論に至りました。

  1. JavaFXの画面をロードする(Main処理)部分の部品を作る(MarthKitクラス)
  2. グラフを表示する部分(コンテンツ部分)を作る部品を作る(LineChartViewクラス)
  3. グラフを表示する部分を切り替えるセレクタを作る ※次回以降に実装します

大雑把にこんな感じで作成します。

ポイント

「2」の部分でグラフを表示する部分を量産したいので、ここを少し工夫します。

<工夫の内容>

グラフをたくさん作るためには上記の「1」「3」の部分を固定(1つの処理に)して「2」の部分を動的にする必要があります。

具体的には以下のような部品を用意します。

<用意する部品>

  • 表示するグラフ(クラス)を登録するためのコンテナ(Mapクラス)
  • グラフを描画するためのクラスをロードするためのプロパティファイル
  • 描画するグラフ(クラス) を1つのクラスのように扱うためのインターフェース

上記の3つを用意します。

具体的にどうやるか?

ここまで、読んでくれた方は「?マーク」が浮いていると思います。もし浮いていなかったら、あなたは間違いなく自分よりも頭がいいです。

余談はさテオ気にして、文字が並びすぎて「早い話がなんののよ?」ってのがわからなくなってきましたのでまとめると

クラス図を描けばわかりやすいじゃん?

と言うわけで、UMLでクラス図を描きました。

ちなみに「StartUML」と言うアプリ(無料)を使用しました。自分はこのサイトに気がつかず、英語版でやってますが。。。

こんな感じでUML(クラス図)を作成しました。クラス図

こんな風に、クラスの連携を組み上げるのが図にするとわかりやすいと言うわけです。

実際に作成した、プロジェクトはこちらに(Git)アップしてあります。

でわでわ。。。



Java Maven 〜POMファイルの${xxx.xxx}の値〜

「{$XXX.XXX}」の値に関して

以下のPOMファイルの赤い字の部分の値は何を指すのかわかりませんでした。

  <build>  ....  </build>
  <dependencies>
   <dependency>
      <groupId>org.nd4j</groupId>
      <artifactId>nd4j-native-platform</artifactId>
      <version>${nd4j.version}</version>
    </dependency>
</dependencies>

{$XXX.XXX}の様な記載はどこかのプロパティを参照するのはわかっていたのですが、プロジェクトが大きくなるとどこにそのプロパティがあるかわからなくなります。今回はND4Jを使用してプロジェクトを作成していたのでその時に気がつきましたのでここにメモしておきます。

MavenBuildのエラー

[ERROR] 'dependencies.dependency.version'
        for org.nd4j:nd4j-native-platform:jar
      must be a valid version but is 
        '${nd4j.version}'. @ line 40, column 15

 上の様な絵エラーが出てビルドができませんでした。そしてうまくいく方との比較で以下の記載がないことに気がつきました。

  <properties>
   <nd4j.version>0.9.1</nd4j.version>
  </properties>

なんとかビルドに成功。

つまるところ。。。

POMファイルの参照関係(親子関係)のあるファイル内に「${XXX.XXX}」が存在するはず、大きいプロジェクトの時はJARなどのファイル内にあるかも?









Eclipse Modeling Framework 〜失敗:UMLツールのインストール〜

ワンポイントレッスン的な記事です。

Eclipse Modeling Framework(EMF)

こいつでアプリケーションを作る時の設計をやろうと思います。

  1. クラスの構成を一覧できるので仕組みをどう作るか考えやすい
  2. 実際にプログラムをどのように組むか?必要なIFクラスなどまとめやすい
  3. パッケージングも同様にやりやすい

上のようなメリットがあります。一言で言うと「図で一覧できるから」一例として上のようなメリットがあります。

もちろん、プログラム設計する人のインスピレーションによって「こんなメリットもあるな!」と発見などもあると思います。

IBMのページにチュートリアル的な記述がありました。

インストールする

参考にしたサイトはこちら

 

これはうまく行きそうにないので諦めます。

 



Eclipseと連動する必要がないので別個にインストールしました(笑)

 

Java Properties 〜プロパティファイルが読めない〜

プロパティファイルのロードができない!こんな感じでつまづきました。

<ソース>

Properties prop = new Properties();
try {
	prop.load(getClass().getResourceAsStream(PROPERTIES_FILE_PATH));
} catch (IOException ie) {
	ie.printStackTrace();
	System.exit(-1);
}

このソースで「PROPERTIES_FILE_PATH」に「resources/views.properties」と指定していたのですが、ロードできない。。。

「views.properties」でもダメだった。。。

/views.properties」ならオッケーだった。









Java エラー: メイン・クラス〜EclipseでMainメソッドが動かない〜

以下のようなエラーメッセージが出ました。

エラー: メイン・クラスzenryokuservice.mathkit.MathKitが見つからなかったかロードできませんでした

パッケージ名もあってるし、メインメソッドの書き方も間違っていない。。。

犯人はお前だぁ!

コンパイル後のパッケージ名と起動しようとしているクラスのパッケージが違っているためだと思ったが、それでもダメでした。

とりあえずEclipse再起動

治りました(笑)

でもbinフォルダを削除したまま再作成されていない。。。

  1. JavaFXプロジェクトで作成した時には「bin」フォルダがあった
  2. Mavenプロジェクトに変更
  3. Mainクラスを作成(MathKit.java)し起動
  4. エラー
  5. Eclipse再起動
  6. 治った!!

こんな感じの流れでした。JavaFXプロジェクトとMavenプロジェクトの変換の時の問題であろう。。。









JavaFX + ND4J 〜数学への挑戦:5グラフを描く〜

イントロダクション

前回は、ND4Jで色々なベクトル(配列)を生成するプログラムを作成しました。(GitにUPしているサンプルコードです)、ここでわかったのは機械学習で扱うデータ→ベクトルを扱うためのプログラム方法を理解した。。。というところです。

グラフを描画する

ここにきてようやく「JavaFX」の出番です。グラフを描くのに、参考にしている本はPythonを使用しているのでJavaでは理解できません。。。

しかし、Javaは色んなところで役に立ちます。JavaFXを使えば画面などはチョチョイのチョイ?で作ることができます。

LineChartを使って見る〜ワンポイントレッスン的な〜

Oracleのページを参照して実装してみました。※上のものは自分が作ってものではありません。

そして、参考にしている本にはグラフが沢山あるので、必然的に沢山のグラフを描く必要があります。なので、グラフの土台を作りこの本の続きをやろうと考えました。

まずは設計

どの様な仕組みを作ってグラフの量産をして、行列の計算や数学の関数を表現するか?を考えて作成します。とりあえずは下の様な感じで作りました。

設計内容など、オブジェクト指向的に作成しました、詳細は下のリンク先に記載しております。

  1. JavaFX + ND4J 〜グラフ作成の準備〜
  2. JavaFX + ND4J 〜グラフ作成:とりあえず表示〜

しかし問題が。。。

上のプログラムで使用したクラス「LineChart」は滑らかな曲線が描けないのです。「折れ線グラフ」として申し分ないのですが、機械学習では「2次関数〜」も使用するので、滑らかなグラフも必要です。そんなわけでグラフの量産アプリを作成しました。

次は、

滑らかなグラフを描く!

でわでわ。。。



ND4J ベクトル生成〜ワンポイントレッスン的な〜

ベクトルの生成

ND4Jで配列(ベクトル)の初期化を行う(ベクトルの生成)方法です。

参考にするサイトはこちらです。(本家家元のドキュメント)英語なので翻訳して見ました。

実行結果

上のキャプチャのように、Nd4jクラスの性的メソッドで簡単に作成できます。

サンプルコード> ※Gitからダウンロード可能

public class FirstNd4j {
	public static void main(String[] args) {
		// クラスのインスタンス化
		FirstNd4j test = new FirstNd4j();
		
		INDArray zeros5 = Nd4j.zeros(5);
		System.out.print("Nd4j.zeros(5) -> ");
		System.out.println(zeros5);
		// 自分で作成したメソッドを使います。
		INDArray zero5_3 = test.createZeroINDArray(5, 3);
		System.out.print("Nd4j.zeros(5, 3) -> ");
		System.out.println(zero5_3);

		// 生成したNDArrayを3で埋める
		INDArray add3 = zero5_3.add(3);
		// 自作メソッドで表示します。
		printArray("INDArray.add(3)", add3);

		System.out.println("*** 0-1の間で乱数を生成する(2次元配列) ***");
		printArray("Nd4j.rand(2, 3)", Nd4j.rand(2, 3));

		System.out.println("*** 3次元以上 ***"); 
		printArray("Nd4j.rand(new int[] {1, 2, 3}])", Nd4j.rand(new int[] {1, 2, 3}));

		System.out.println("*** 平均ゼロ、標準偏差1のガウス乱数を生成する ***");
		printArray("Nd4j.randn(2, 3)", Nd4j.randn(2, 3));
		printArray("Nd4j.randn(new int[] {1, 2, 3}])", Nd4j.randn(new int[] {1, 2, 3}));
	}

	/**
	 * 静的メソッドです。(staticがつきます)
	 * このクラスを起動するときに他の読み込むクラスに同じメソッドは定義できません。
	 * 実行時エラーになります。
	 * 
	 * @param formula 表示する計算式
	 * @param vector ベクトル(配列)
	 */
	public static void printArray(String formula, INDArray vector) {
		System.out.print(formula + " -> ");
		System.out.println(vector);
	}
	/**
	 * このクラスのインスタンスメソッドです。
	 * 0のベクトルを生成します。
	 * 
	 * @param row 行の数
	 * @param col 列の数
	 * @return 生成された行列
	 */
	private INDArray createZeroINDArray(int row, int col) {
		return Nd4j.zeros(row, col);
	}
	・
	・
	・
}



関連ページ一覧

Java + ND4J 〜数学への挑戦3: ベクトル(配列)の作成方法〜

イントロダクション

前回は、ND4Jによる、行列の演算を行いました。

単純に計算処理を行うだけなので、ハローワールド的な感じです。ポイントは行列の形(ROWx?, COLx?)を指定できるのがNumpyとの違いです。

<実行結果はこんな感じでした。>

そして、参考にしている本は下の本です。

2.9.5:連続した整数のベクトル生成

参考にしている本の項番を参照してください。本の39ページから始めます。

<補足>

Javaでの配列(ベクトル)への値を参照するには以下のようにやります。メソッド経由でアクセスできます。

今回の配列(ベクトル)は2次元配列なので下のように取得します。配列の位置は次のような感じです。配列の(0, 0) → [[0.20,  0.29], [0.27,  0.27]]※太字の部分が(0, 0)の位置にある値です。

"割り算の答えの0番目(INT)" + answer.getInt(0, 0)); 
"割り算の答えの0番目(INT)" + answer.getInt(0, 1)); 
"割り算の答えの0番目(Double)" + answer.getDouble(1, 0)); 
"割り算の答えの0番目(Double)" + answer.getDouble(1, 1)); 

詳細部分はJavaDocを見る

実装したコードはこちら(GIT)