JavaFX + ND4J〜数学への挑戦6:グラフの土台を作る〜

イントロダクション

前回は、LineChartを使用して折れ線グラフを作成しました。他にも〜Chartクラスを漁ってみましたが適当なものが見つからなかったのでCanvasクラスを使用しようと思います。

<漁ってみたクラス>

  1. JavaFX グラフ描画〜AreaChartを使う〜
  2. JavaFX LineChart 〜グラフを描く、ワンポイントレッスン的な〜

Canvasを使う

ラップされたクラスを使用すると楽にできます。。。駄菓子菓子「細かい調節が効かない」という欠点を持っています。これはJavaに限らずPthon, Ruby, JavaSriptなどの高レベルAPIと呼ばれるプログラミング言語では潜在するものです。その代わり、楽に作れるのがポイント!

そして、Javaはちょっと特殊で「高レベルAPI」と呼ばれるものと「低レベルAPI」と呼ばれるものが混在します。Pythonでも似た様なことをいうときがありますが。。。

早い話が

画面上のグラフの土台から全部描いてしまおうというわけです。

GraphcContextを使う

結論から言うとこんな感じでグラフの土台を作成しました。

X軸とY軸はちょいと太めの線で描画しています。そして、補助線は薄い色で描画しています。現状では、4分割する様な形で補助線を引いていますが、これはいじれるようになっています。

<コード>

public class Graphics2DView extends Parent implements MathKitView {

	/* (non-Javadoc)
	 * @see zenryokuservice.mathkit.MathKitView#loadView(javafx.scene.layout.VBox)
	 */
	@Override
	public Parent loadView(VBox root) {
		Canvas canvas = new Canvas(600, 600);
		GraphicsContext ctx = canvas.getGraphicsContext2D();
		// グラフの土台を作る
		drawGraphBase(ctx, root);
		root.getChildren().add(canvas);
		return root;
	}

	/**
	 * グラフの土台になる部分を描画します。
	 * @param ctx Canvasから取得したクラス
	 * @param root レイアウトクラス(シーン追加する)
	 */
	private void drawGraphBase(GraphicsContext ctx, VBox root) {
		ctx.setStroke(Color.BLACK);
		ctx.setLineWidth(2.0);
		// X軸
		ctx.strokeLine(0, 250, 500, 250);
		// Y軸
		ctx.strokeLine(250, 0, 250, 500);
		// マスを作る
		double span = 500 / 4;
		ctx.setLineWidth(0.5);
		for (int i = 0; i <= 4; i++) {
			if (i == 0 || i == 2 || i == 4) {
				continue;
			}
			// 縦の補助線
			ctx.strokeLine(i * span, 0, i * span, 500);
			// 横の補助線
			ctx.strokeLine(0, i * span, 500, i * span);
		}
	}
}

※上のコードだけで描画できるのはそう言う仕組みを作ったからです。その仕組みはこちらを参照ください。Gitからダウンロードもできます。(ここはファイルの差分を表示しています。)

次回は、関数を描画しようと思います。

でわでわ。。。

 








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

イントロダクション

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

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

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

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

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

ポイント

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

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

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

グラフはこんな感じ

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




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

イントロダクション

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

グラフを描画する

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

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

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

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

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

まずは設計

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

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

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

しかし問題が。。。

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

次は、

滑らかなグラフを描く!

でわでわ。。。



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)









JavaFX + ND4J〜数学への挑戦2: 行列の計算〜

イントロダクション

前回は、ND4JのインストールとンD4J版ハローワールドをやりました。

なので次のステップ、下の本は「2.9ベクトル」から始めます。

Javaの基本的なことは下の部分にリンクがありますのでわからない部分があれば参照してください。

ND4Jによる行列計算

ぶっちゃけて、ちょいとコードをかくだけで頭で計算する必要はありません。

なぜなら

パソコンは計算機だからです。

ジョークはさておき。。。行列(英語ではMatrix(マトリクス))はプログラム的には数値の配列です、これは「ベクトル」と呼んだり「配列」と呼んだり自分は混乱しました。参考にした、本なども初めの部分にある文言を読まなければ「???」となりました。※初めは読み飛ばしました(笑)

さて、コードです。このサイトを参考にしました。下の式をプログラムで表現すると次のようになります。

ソース(Gitにあります)

public static void main(String[] args) {
	/*
	 * 配列の計算をする
	 * x=(1.0, 2.0), y=(5.0, 7.0)を計算する
	 */
	INDArray x = Nd4j.create(new double[] {1.0, 2.0}, new int[] {2, 1});
	INDArray y = Nd4j.create(new double[] {5.0, 7.0}, new int[] {2, 1});
	// 行列の足し算「x + y」
	INDArray answer = x.add(y);
	System.out.println("行列の足し算: x + y = " + answer);
	// 行列の引き算「x + y」
	answer = x.sub(y);
	System.out.println("行列の引き算: x - y = " + answer);
	/* 下の計算はまた別の機会にします。ちょっとややこしい(笑) */
//	// 行列のかけ算「x * y」
//	answer = x.mmul(y);
//	System.out.println("行列の引き算: x * y = " + answer);
//	// 行列のわり算「x / y」
//	answer = x.div(y);
//	System.out.println("行列の引き算: x / y = " + answer);
}

<実行結果>

<掛け算と割り算>

上のキャプチャでは掛け算部分をコメントアウトしています。この部分が中途半端になっていたので、そいつらにけりをつけます。

ちなみに、上記のコードではコメントアウトしていますが、このコードを実行すると以下のようなエラーメッセージが出力されます。

Exception in thread "main" org.nd4j.linalg.exception.ND4JIllegalStateException: Cannot execute matrix multiplication: [2, 1]x[2, 1]: Column of left array 1 != rows of right 2
at org.nd4j.linalg.util.LinAlgExceptions.assertMultiplies(LinAlgExceptions.java:90)
at org.nd4j.linalg.api.ndarray.BaseNDArray.mmuli(BaseNDArray.java:2946)
at org.nd4j.linalg.api.ndarray.BaseNDArray.mmul(BaseNDArray.java:2812)
at jp.zenryoku.ml.nd4j.FirstNd4j.main(FirstNd4j.java:27)

キーワードは「Cannot execute matrix multiplication: [2, 1]x[2, 1]」の部分です。

なので、コードを以下のように修正して再実行して見ます。

/*
* 配列の計算をする
* x=(1.0, 2.0), y=(5.0, 7.0)を計算する
*/
INDArray x = Nd4j.create(new double[] {1.0, 2.0, 1.5, 2,5}, new int[] {2, 2});
INDArray y = Nd4j.create(new double[] {5.0, 7.0, 5.5, 7.5}, new int[] {2, 2});

初めのコードとの違いは行列の列の数が違うということです。

初めのコード→

ROWのサイズが2、COLのサイズが1

次のコード→

ちょっとあれですが。。。ROWのサイズが2、COLのサイズが2

このような違いがあります。

この状態だと「行列の演算で[2, 1] x [2, 1]はできません」というエラーは出ませんでした。

基本的な計算はこんなくらいかな?というところです。

感想

んー「NumPy」そックリだ。。。これならPythonで書かれた機械学習の本をJavaで学習できそうだ!

しかも、行列の列数など細かい調整が効くというところがNumPyと違うところだ。

関連ページ一覧

Java Basic

  1. Java Basic Level 1 Hello Java
  2. Java Basic Level2 Arithmetic Calculate
  3. Java Basic Level3 About String class
  4. Java Basic Level 4Boolean
  5. Java Basic Level 5If Statement
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 Traning of If statement
  8. Java Basic Level8 How to use for statement
  9. Java Basic Level 8.5 Array
  10. Java Basic Level 9Training of for statement
  11. Java Basic Level 10 While statement 
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1
  17. Java Basic JUnit 〜テストスイートの作り方〜

TensorFLowを学ぶ(Python)

  1. Tensorflow Keras 〜初めてのKeras
  2. Tensorflow Keras Errors”python is not installed as a framework.”
  3. Python Tensorflow 〜初めての人工知能(TensorFlowインストール)
  4. Tensorflow Keras〜初めのトレーニング_1
  5. Tensorflow Keras〜初めのトレーニング_2:前処理〜
  6. TensorFlow Keras〜テキストの分類〜
    1. TensorFlow Keras 実行結果〜テキストの分類〜
  7. Python TensorFlow tutorial〜チュートリアルを進めるコツ、ワンポイント〜
  8. TensorFlow Keras〜回帰、準備から予測まで〜
  9. TensorFlow Java 環境構築〜JavaでもTensorFlow〜



JavaFX + ND4J〜数学への挑戦1:ND4Jのインストール〜

イントロダクション

機械学習を理解するために「どうしたら良いか?」を考えていたらちょうど持っている本がありました。

今回ではないですが、ゲームのマッピングにもND4Jを使って見ました。

この本の内容は「Python」で書かれているので。。。「ソース読むだけでいいや!」となっておりましたが「PythonでできるならJavaでもできるじゃん?」と気がついたのでそのようにします。

ND4Jのインストール

Mavenで。。。

こちらのサイトを参考にしました。下のようにPOMファイルに追記します。

<peoperties>   <nd4j.version>0.7.2</nd4j.version></properties>                     

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

ちなみにプロジェクトのMaven化は下のような感じです。

Mavenのサイトで詳細な情報が観れます。ちなみに参考サイトのND4Jのバージョンは7.xでしたが、最新(2019/02/14現在)のバージョンは0.9.1でした(安定版)

https://mvnrepository.com/artifact/org.nd4j/nd4j-api

ちなみにここから「JAR」ファイルをダウンロードできます。

ダウンロードしたらEclipseのビルドパスに追加します。下のような感じです。

ND4Jをインストールし終わると以下のような感じになります。

ND4Jを動かしてみる

public class FirstNd4j {
   public static void main(String[] args) {
      INDArray arr = Nd4j.zeros(3);
      System.out.println(arr);
   }
}

ND4J版のハローワールドです。

でわでわ。。。

JavaFXでハローワールド〜

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

 



TensorFlow Keras〜回帰、準備から予測まで〜

イントロダクション

今までは、データセットの準備やデータの中身を見ることに注力していたようですが今回は全体的な処理の流れをチュートリアルでやるようです。参考サイト

そしてもう1つ、前回までは「分類」を行なっていたのに対し今回は「回帰分析」を行うようです。実際にチュートリアルをやってみましたが「回帰分析」がよくわからなかったので今回の学習もよくわからず終いでした。

あとで回帰分析も理解したいと思います。

<今までのチュートリアル>

  1. Tensorflow Keras〜初めのトレーニング_1〜
  2. Tensorflow Keras〜初めのトレーニング_2:前処理〜
  3. TensorFlow Keras〜テキストの分類〜

本題

初めに「seaborn」パッケージをインストールします。

# Use seaborn for pairplot
!pip install -q seaborn

しかし、自分の端末では上のコマンドでインストールできなかったので

pip install seaborn

でインストールしました。

そして、ハローワールド的にバージョン情報の表示、以下のソースを実行 ※チュートリアルのページからコピーできるやつ!

from __future__ import absolute_import, division, print_function

import pathlib

import pandas as pd
import seaborn as sns

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

print(tf.__version__)

この後のコードも同様にコピペでいけます。ただし、tail()はprintしないと表示しないようです。

print(dataset.tail())

そして、下のグラフの表示に関しても同様で下のコードを追加してやる必要がありました。

import matplotlib.pyplot as plt
・
・
・
plt.show()

<実行結果>

<全体的な統計の出力結果>

# 初めの表
      MPG  Cylinders  Displacement  ...    USA  Europe  Japan
393  27.0          4         140.0  ...    1.0     0.0    0.0
394  44.0          4          97.0  ...    0.0     1.0    0.0
395  32.0          4         135.0  ...    1.0     0.0    0.0
396  28.0          4         120.0  ...    1.0     0.0    0.0
397  31.0          4         119.0  ...    1.0     0.0    0.0

[5 rows x 10 columns]

# 全体的な統計の出力結果
              count         mean         std   ...       50%      75%     max
Cylinders     314.0     5.477707    1.699788   ...       4.0     8.00     8.0
Displacement  314.0   195.318471  104.331589   ...     151.0   265.75   455.0
Horsepower    314.0   104.869427   38.096214   ...      94.5   128.00   225.0
Weight        314.0  2990.251592  843.898596   ...    2822.5  3608.00  5140.0
Acceleration  314.0    15.559236    2.789230   ...      15.5    17.20    24.8
Model Year    314.0    75.898089    3.675642   ...      76.0    79.00    82.0
USA           314.0     0.624204    0.485101   ...       1.0     1.00     1.0
Europe        314.0     0.178344    0.383413   ...       0.0     0.00     1.0
Japan         314.0     0.197452    0.398712   ...       0.0     0.00     1.0

[9 rows x 8 columns]

引き続きコピペでプログラムを組んでいきます。下は実行結果
.summaryメソッドを使用してモデルの簡単な説明を印刷する

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 64)                640       
_________________________________________________________________
dense_1 (Dense)              (None, 64)                4160      
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 65        
=================================================================
Total params: 4,865
Trainable params: 4,865
Non-trainable params: 0
_________________________________________________________________

それではモデルを試してみてください。10トレーニングデータから試験のバッチを取り、model.predictそれを呼び出します。

<実行結果>

array([[0.08682194]、
       [0.0385334]、
       [0.11662665]、
       [ -  0.22370592]、
       [0.1239757]、
       [0.1349103]、
       [0.41427213]、
       [0.19710071]、
       [0.01540279 
       ]、dtype = float32)

しかし、NumPyが出力されてもよくわからん。。。と言うのは前回と同じです。

モデルを訓練する

ここもやっぱりコピペでプログラムを書きます。最後に以下のコードを追加してください。

plt.show()

<実行結果>

自動的にトレーニングを停止するようにメソッドを更新

微妙な差分ですが。。。その良し悪しは「あなた次第」らしいです。

モデルがどのように機能したのか?

これまでと同様にコピペでコードを追加します。実行結果です。

Testing set Mean Abs Error:  2.03 MPG

テストの平均誤差が「2.03MPG」ある。。。

予測を行う

ここもやっぱりコピペで下が実行結果、参考サイトと違う結果になりました。どこかが間違っているように思える。。。

 

ソースを見直しました。グラフ表示の設定がまずかったようです。初めの方にある「plot_history(history)」をコメントアウトしました。

結論

「データセットの用意→モデル作成→トレーニング→予測」を行いその結果に対してどのような判断をするか?

 

でも、前提になるこれらの処理の結果がなんなのか?を理解しないと今までやってきたことも水の泡になりそうです(笑)







TensorFlow Keras〜テキストの分類〜

イントロダクション

前回までは、基本的な画像識別をやってきました。(Basic Classification)

<まとめ>

  1. テストデータと学習用データを用意する
  2. 学習用のモデルを構築する
  3. コンパイルしてモデルの訓練(トレーニング)を行う
  4. 訓練の結果を見て精度が想定以上出るのを確認する
  5. 分類したいデータを分類する

今回はテキストの分類を行います。参考サイトはこちら

映画のレビューを分類する

今回はテストデータの映画のレビューを「ポジティブか?ネガティブか?」の判定を行います。

参考サイトは以下のような項目に分かれていました

  1. データを調べる
  2. 整数を単語に戻す
  3. データを準備する
  4. モデルを構築する
  5. 隠しユニット
  6. 損失関数とオプティマイザ
  7. 検証セットを作成する
  8. モデルを訓練する
  9. モデルを評価する
  10. 経時的な精度と損失のグラフを作成する

このような項目になっていますが基本は、前回にやったのと同じです。

  1. 前処理を行う
  2. 機械学習のモデル構築
  3. 同様にコンパイル
  4. 結果の表示(学習処理、学習の評価、予測)

1.データを調べる

tensorflow.keras.datasets.imdbでデータを取得して中身を確認する

2.整数を単語に戻す

「1」で取得したデータは整数なので「1, 14,...」

それを文字列にしてみる処理が記載されていました。

3.データを準備する

pad_sequences」関数を使用してデータの整理などを行い

学習・評価する準備を行います。

4.モデルを構築する

4つの層(レイヤー)を重ねて分類機を作成します。※細かいことはソースで!

  1. Embedding層」
  2. 「GlobalAveragePooling1D」
  3. 「固定長出力ベクトル」
  4. 「単一​​の出力ノードと密接に接続されている」

少しややこしくなってきたのでソースコードで整理します。

# TensorFlow, Kerasをインポート
import tensorflow as tf
from tensorflow import keras

import numpy as np

### Difinition of methods ###
def decode_review(text):
    return ' '.join([reverse_word_index.get(i, '?') for i in text])
#############################
# TensorFlowのバージョンを確認
print(tf.__version__) 

# データセットの取得
imdb = keras.datasets.imdb

# データセット(映画のレビューをロード
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

# 単語とインデックス(整数)を変換するためのディクショナリ
# A dictionary mapping words to an integer index
word_index = imdb.get_word_index()

# The first indices are reserved
word_index = {k:(v+3) for k,v in word_index.items()}
word_index[""] = 0
word_index[""] = 1
word_index[""] = 2  # unknown
word_index[""] = 3

reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])
#print(decode_review(train_data[0]))

# テストデータ(トレーニングデータ)を標準化する処理
train_data = keras.preprocessing.sequence.pad_sequences(train_data,
                                                        value=word_index[""],
                                                        padding='post',
                                                        maxlen=256)
# テストデータ(テストデータ)を標準化する処理
test_data = keras.preprocessing.sequence.pad_sequences(test_data,
                                                       value=word_index[""],
                                                       padding='post',
                                                       maxlen=256)

# input shape is the vocabulary count used for the movie reviews (10,000 words)
vocab_size = 10000

# モデルの作成
model = keras.Sequential()
# Embeddingレイヤーの追加
model.add(keras.layers.Embedding(vocab_size, 16))
# 
model.add(keras.layers.GlobalAveragePooling1D())
model.add(keras.layers.Dense(16, activation=tf.nn.relu))
model.add(keras.layers.Dense(1, activation=tf.nn.sigmoid))

model.summary()

レイヤーの構成

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, None, 16)          160000    
_________________________________________________________________
global_average_pooling1d (Gl (None, 16)                0         
_________________________________________________________________
dense (Dense)                (None, 16)                272       
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 17        
=================================================================
Total params: 160,289
Trainable params: 160,289
Non-trainable params: 0

「dense」は前回の基本的な分類で使用しました。

今回使用したレイヤーに関してはリンク先を参照します。

  1. Embedding
  2. global_average_pooling1d
  3. dense

現状の理解度では、上にあるようなレイヤーを組み合わせて「学習モデル」を作成している。と言う状態です。

モデルのコンパイル

このコンパイルもせって処理が含まれています。それは「最適化関数(オプティマイザ)」と「損失関数」を設定することです。

# モデルのコンパイル
model.compile(optimizer=tf.train.AdamOptimizer(),
              loss='binary_crossentropy',
              metrics=['accuracy'])

損失関数に設定しているのは「binary_crossentropy」です。

検証用のデータセットを作成する

# 検証用のデータセットを作成する
x_val = train_data[:10000]
partial_x_train = train_data[10000:]

y_val = train_labels[:10000]
partial_y_train = train_labels[10000:]

ここは特に注意する点はないと思います。

訓練する

history= model.fit(partial_x_train,
                    partial_y_train,
                    epochs=40,
                    batch_size=512,
                    validation_data=(x_val, y_val),
                    verbose=1)

fit()で学習処理を行います。

評価する

results = model.evaluate(test_data, test_labels)

print(results)

最後にグラフに表示します。

fit()の返り値の「historyオブジェクト」が実行結果を保持しているようです。

 評価の結果をグラフに表示します。
import matplotlib.pyplot as plt

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(acc) + 1)

# "bo" is for "blue dot"
plt.plot(epochs, loss, 'bo', label='Training loss')
# b is for "solid blue line"
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()

<実行結果(出力内容)>

この特定のケースでは、20回程度のエポックの後に単純にトレーニングを中止することで、過剰適合を防ぐことができます。

作成したコードはGITからダウンロードできます。

レビューの判定

上の実行した結果は検証するモデルの評価を行うもので目的の「文章を分類する」と言うところとは全く関係のない話です。そして判定の結果をどのように出力するのか→予測の結果をどのように出力するのか?を調べると・・・

ここのサイトを見て「迷宮入りしそうだな。。。」と思ったので課題として残すことにしました。

はっきりしていること

予測の結果はpredict()で表示すると言うことです。しかし、これは予測結果としてNumPy配列を返却するので意味がわからない。。。と言うところです。

使用している関数としては、以下のようなものがあることは調べがついています。

# 2値(0 or 1) 
model.predict_classes(np.array([[1,1]]), batch_size=1) 
# 学習の程度(0.0~1.0) 
model.predict_proba(np.array([[1,1]]), batch_size=1) 
# もしくは 
model.predict(np.array([[1,1]]), batch_size=1)


感想

現状の理解としてはTensorFlowでの学習処理は、以下の通り

  1. データセットを用意する
  2. データセット、テストデータでの学習モデルを作る(レイヤー作成)
  3. 学習処理を行う(fit())
  4. 評価を行う

ここまでできたら、あとは実戦に投入する→画像判定や、文章の判定を行うことができるようです。まだまだ根深そうだなぁ。。。

関連ページ一覧

  1. Tensorflow Keras 〜初めてのKeras〜
  2. Tensorflow Keras Errors〜”python is not installed as a framework.”〜
  3. Python Tensorflow 〜初めての人工知能(TensorFlowインストール)〜
  4. Tensorflow Keras〜初めのトレーニング_1〜

TensorFlow Keras 実行結果〜テキストの分類〜

イントロダクション

下のページでの学習処理の実行結果を表示します。※わかりづらいので分けました。

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, None, 16)          160000    
_________________________________________________________________
global_average_pooling1d (Gl (None, 16)                0         
_________________________________________________________________
dense (Dense)                (None, 16)                272       
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 17        
=================================================================
Total params: 160,289
Trainable params: 160,289
Non-trainable params: 0
_________________________________________________________________
Train on 15000 samples, validate on 10000 samples
Epoch 1/40
15000/15000 [==============================] - 1s 86us/step - loss: 0.6917 - acc: 0.5697 - val_loss: 0.6895 - val_acc: 0.6231
Epoch 2/40
15000/15000 [==============================] - 1s 55us/step - loss: 0.6849 - acc: 0.7046 - val_loss: 0.6800 - val_acc: 0.7423
Epoch 3/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.6701 - acc: 0.7631 - val_loss: 0.6614 - val_acc: 0.7574
Epoch 4/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.6441 - acc: 0.7736 - val_loss: 0.6330 - val_acc: 0.7681
Epoch 5/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.6068 - acc: 0.7985 - val_loss: 0.5935 - val_acc: 0.7907
Epoch 6/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.5607 - acc: 0.8163 - val_loss: 0.5495 - val_acc: 0.8059
Epoch 7/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.5106 - acc: 0.8359 - val_loss: 0.5043 - val_acc: 0.8228
Epoch 8/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.4616 - acc: 0.8520 - val_loss: 0.4619 - val_acc: 0.8381
Epoch 9/40
15000/15000 [==============================] - 1s 53us/step - loss: 0.4173 - acc: 0.8644 - val_loss: 0.4254 - val_acc: 0.8460
Epoch 10/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.3787 - acc: 0.8781 - val_loss: 0.3958 - val_acc: 0.8550
Epoch 11/40
15000/15000 [==============================] - 1s 55us/step - loss: 0.3471 - acc: 0.8847 - val_loss: 0.3745 - val_acc: 0.8595
Epoch 12/40
15000/15000 [==============================] - 1s 55us/step - loss: 0.3215 - acc: 0.8910 - val_loss: 0.3537 - val_acc: 0.8666
Epoch 13/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.2982 - acc: 0.8993 - val_loss: 0.3397 - val_acc: 0.8710
Epoch 14/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.2790 - acc: 0.9049 - val_loss: 0.3273 - val_acc: 0.8743
Epoch 15/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.2625 - acc: 0.9095 - val_loss: 0.3180 - val_acc: 0.8771
Epoch 16/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.2484 - acc: 0.9132 - val_loss: 0.3103 - val_acc: 0.8788
Epoch 17/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.2346 - acc: 0.9191 - val_loss: 0.3041 - val_acc: 0.8797
Epoch 18/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.2227 - acc: 0.9236 - val_loss: 0.2990 - val_acc: 0.8817
Epoch 19/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.2115 - acc: 0.9274 - val_loss: 0.2951 - val_acc: 0.8827
Epoch 20/40
15000/15000 [==============================] - 1s 59us/step - loss: 0.2017 - acc: 0.9315 - val_loss: 0.2917 - val_acc: 0.8839
Epoch 21/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.1922 - acc: 0.9345 - val_loss: 0.2892 - val_acc: 0.8841
Epoch 22/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.1834 - acc: 0.9391 - val_loss: 0.2876 - val_acc: 0.8849
Epoch 23/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.1754 - acc: 0.9426 - val_loss: 0.2868 - val_acc: 0.8851
Epoch 24/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.1674 - acc: 0.9464 - val_loss: 0.2854 - val_acc: 0.8846
Epoch 25/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.1604 - acc: 0.9493 - val_loss: 0.2850 - val_acc: 0.8855
Epoch 26/40
15000/15000 [==============================] - 1s 53us/step - loss: 0.1533 - acc: 0.9521 - val_loss: 0.2855 - val_acc: 0.8868
Epoch 27/40
15000/15000 [==============================] - 1s 53us/step - loss: 0.1474 - acc: 0.9545 - val_loss: 0.2864 - val_acc: 0.8855
Epoch 28/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.1412 - acc: 0.9575 - val_loss: 0.2865 - val_acc: 0.8866
Epoch 29/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.1355 - acc: 0.9583 - val_loss: 0.2874 - val_acc: 0.8874
Epoch 30/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.1305 - acc: 0.9612 - val_loss: 0.2890 - val_acc: 0.8867
Epoch 31/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.1245 - acc: 0.9632 - val_loss: 0.2908 - val_acc: 0.8874
Epoch 32/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.1199 - acc: 0.9657 - val_loss: 0.2930 - val_acc: 0.8852
Epoch 33/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.1145 - acc: 0.9677 - val_loss: 0.2952 - val_acc: 0.8854
Epoch 34/40
15000/15000 [==============================] - 1s 60us/step - loss: 0.1101 - acc: 0.9689 - val_loss: 0.2982 - val_acc: 0.8855
Epoch 35/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.1061 - acc: 0.9708 - val_loss: 0.3001 - val_acc: 0.8851
Epoch 36/40
15000/15000 [==============================] - 1s 56us/step - loss: 0.1013 - acc: 0.9726 - val_loss: 0.3034 - val_acc: 0.8836
Epoch 37/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.0975 - acc: 0.9739 - val_loss: 0.3065 - val_acc: 0.8838
Epoch 38/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.0940 - acc: 0.9739 - val_loss: 0.3103 - val_acc: 0.8830
Epoch 39/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.0898 - acc: 0.9767 - val_loss: 0.3129 - val_acc: 0.8837
Epoch 40/40
15000/15000 [==============================] - 1s 54us/step - loss: 0.0861 - acc: 0.9785 - val_loss: 0.3167 - val_acc: 0.8816
25000/25000 [==============================] - 1s 30us/step
[0.3381449136734009, 0.872]

[0.3381449136734009, 0.872]※「赤字の部分 * 100」=パーセンテージ


関連ページ一覧

  1. Tensorflow Keras 〜初めてのKeras〜
  2. Tensorflow Keras Errors〜”python is not installed as a framework.”〜
  3. Python Tensorflow 〜初めての人工知能(TensorFlowインストール)〜
  4. Tensorflow Keras〜初めのトレーニング_1〜

Tensorflow Keras〜初めのトレーニング_2:前処理〜

イントロダクション

前回はトレーニングの準備として、MNISTのデータを調べました。今回は前処理を行います。参考サイトは前回と同じです

関連ページ一覧

  1. Tensorflow Keras 〜初めてのKeras〜
  2. Tensorflow Keras Errors〜"python is not installed as a framework."〜
  3. Python Tensorflow 〜初めての人工知能(TensorFlowインストール)〜
  4. Tensorflow Keras〜初めのトレーニング_1〜

処理概要

  1. 前処理を行う
  2. 機械学習のモデル構築
  3. 同様にコンパイル
  4. 結果の表示(学習処理、学習の評価、予測)

とりあえずは、データをグラフ表示してみます。

<コード>

# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras

# Helper libraries
import numpy as np
import matplotlib.pyplot as plt

print(tf.__version__)

# Get MINST data
fashion_minst = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_minst.load_data()

# Chcke MINST data
print("トレーニングイメージ数(train_images.shape):%s " % (train_images.shape,))
print("トレーニングラベル数(len(train_labels)): %d" % len(train_labels))
print("トレーニングラベルの中身: %d" % train_labels[0])

# First Check IMG
plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()

前処理

参考サイトによると以下のように記載があります。

ニューラルネットワークモデルにフィードする前に、
これらの値を0から1の範囲にスケーリングします。
  これには、画像コンポーネントのデータ型を整数からfloatにキャストし、
  255で割ります。これは、画像を前処理する関数です。

どうやら0〜1の範囲に値を置き換える必要があるようです。

そして変更してから実行します。表示はできたけどスクロールするとMacではクラッシュしてしまうようです。(自分はしました。)今回は機械学習をやるのでグラフ表示は後回しにします。

【追伸】グラフはTensorBordで表示したいと思っています。

結局

データが0-255の範囲で設定されているのでそれを0-1の範囲に変更するということをしました。

機械学習モデルの構築

# Create Model set layers
model = keras.Sequential([
 keras.layers.Flatten(input_shape=(28, 28)),
 keras.layers.Dense(128, activation=tf.nn.relu),
 keras.layers.Dense(10, activation=tf.nn.softmax)
])

機械学習モデルのコンパイル

レイヤーを設定する
ニューラルネットワークの基本的な構成要素はレイヤーです。レイヤーは、そこに送られたデータから表現を抽出します。そして、うまくいけば、これらの表現は当面の問題にとってより意味があります。

ディープラーニングの大部分は、単純なレイヤーを連鎖させることから成ります。同様にtf.keras.layers.Dense、ほとんどのレイヤーにはトレーニング中に学習されるパラメータがあります。

学習結果の1つを表示します。上が実行結果です。

モデルの訓練

コードとしては1行で終わります。 

model.fit(train_images, train_labels, epochs=5)

ここで渡しているのはイメージラベルを渡しています、最後の「epocks」はこのサイトで調べました。

単にepochsという指標に試行が達するまで訓練します

ということのようです。※意味はわかっていません。

とりあえずは上の画像が予測の結果です。

そして、テストデータの中の1つを取得してその予測結果を表示しました。

注意点としては

model.predictデータのバッチ内の各画像に対して1つずつ、リストのリストを返します。バッチ内の(唯一の)画像の予測を取得します

ということです。コードで書くと下のようにやってくださいということでした。

# Add the image to a batch where it's the only member.
img = (np.expand_dims(img,0))

print(img.shape)

predictions_single = model.predict(img)

print(predictions_single)

なんだかわかったような、わからないような。。。釈然としませんが今回はここまでにしておきます。