Colaboratoryで、機械学習済みのModelを使い予測値を算出する。

機械学習をやり初めのときに疑問だったことは、
Colaboratoryなり、Anacondaなり使って、モデルを作ることが出来るんだけども、
どうやって、アプリケーションするのか?ということでした。

結論から言ってしまうと、modelデータを保存→ダウンロードして、他のアプリケーションに組み込むです。modelはmodelの形式や、重み・バイアスが、バイナリーデータとして格納されています。
他のアプリケーションで利用する際には、学習時に成形した入力形式が定まっているので、入力する際には注意が必要かと思います。

■Colaboratoryで、機械学習済みのModelを使う

それでは、簡単ではありますが、実際に使ってみます。
色々とやり方はあるかと思いますが、
今回は機械学習済みModelの、重み・バイアスを抽出して、予測値を算出していきます。

大まかな流れとしては、
・学習済みModelをUpload(ディレクトリへ格納)
・モデルの定義
・重み、バイアスのロード
・予測を実行

まずは、学習したModelをUploadします。

/content/model_data/ ディレクトリ配下に
modelDone.hdf5 というファイル名にてUploadする。

Modelを定義します。
これは、機械学習をした際と同じModelを定義します。
Kerasを活用するとします。(Libraryはimport済み)

#modelの定義
model = tf.keras.models.Sequential()
model.add(Flatten(input_shape=(28, 28)))
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(10, activation='softmax'))

Modelに対して、重み・バイアスを読み込ませます。

model.load_weights('/content/model_data/modelDone.hdf5')

これで、学習した状態と同じ状態になります。

予測値を算出するには、学習したときと同じ入力形式で、データを入力し、予測を実行させて上げればよいのです。

predicted = model.predict(入力データ)
#変数 predicted に予測値が出力される。

KerasのCallbackをColaboratoryで試してみる

本日は、機械学習の学習中に操作をするCallbackについてです。

機械学習を勉強し初めの時に、混乱していたことの1つが、どんなデータのやり取りが行われているのか、分からない。と、言ったことでした。

特に、モデルの学習中には、一度学習をスタートすると、何だか分からないけれども指定したエポック数だけ処理されている。といった感覚でした。

そんな、中でモデルの学習中に、操作を行うことが出来る関数の集合がCallbackです。
詳細は、Kerasのオフィシャルで

■コールバック
https://keras.io/ja/callbacks/#modelcheckpoint

Callbackは、幾つかの目的の為に使われます。
・学習途中に、過学習を抑制するために、操作を停止したり、学習率を低下させる
・学習途中の内部の処理情報を可視化 or 保存させる

■KerasでCallbackをモデル学習にセットする方法

kerasでモデル学習する際には、
・model.fit()
・model.fit_generator()

2つのどちらかを利用すると思いまします。

2つの違いにはついては下記を参照

KerasでCallbackをモデル学習にセットさせる方法は、シンプルで
model.fit( callbacks= ) / model.fit_generator(callbacks=) の引数 callbacks= に対して、Keras.callbacks.Callback にあるインスタンスのリストを記載します。

例えば、よく使うのでいうと
ModelCheckpoint:学習中のモデルを保存することが出来る
EarlyStopping:学習中に値の変化が停止した時に訓練を終了出来る
TensorBoard:TensorBoardで可視化

■ColaboratoryでCallbackを用いて、学習中のモデルを保存

ModelCheckpointを使用して、学習中のモデルを保存してみましょう。

Colaboratoryで新規のフォルダを作成します。
フォルダ名称をlogとします。 パス : ‘/content/log’
このlogフォルダの中に格納していきます。

#保存するファイル名称の設定
ckpt_name = 'weights-{epoch:02d}-{loss:.2f}-{accuracy:.2f}-{val_loss:.2f}-{val_accuracy:.2f}-.hdf5'

log_dir='/content/log' # modelのデータ格納場所

#ModelCheckpointのインスタンス化
cbcheck = ModelCheckpoint(os.path.join(log_dir, ckpt_name),
                               monitor='val_acc', verbose=0,
                               save_best_only=False,
                               save_weights_only=True,
                               mode='auto', period=1)

この、ModelCheckpointをインスタンス化した、cbcheckを、fitの引数に設定します。

#色々と省略して
model.fit(callbacks= cbcheck)

そうすると、
log_dir=’/content/log’ # modelのデータ格納場所
の箇所にエポック毎に(period=1で設定)モデルが保存されております。

学習のモデルを操作できたり、可視化出来たりすることで
機械学習への距離感が少し縮まりました。
途中経過のモデルを活用して、predictしてみるのも面白いかと思います。

GANでデータセットを作るために、Numpyのreshapeを使う方法

画像pngデータを活用して、データセットを作るために必要だったreshapeの使い方を紹介したいと思います。(違うやり方もあると思います。)

以前、reshapeの基本的な使い方は下記で記載しました。

本記事の操作としては、下記記事で作成したデータセットを基に話を進めていきます。

画像データは、1つの画像に対して、( 350 × 350 ) の配列に格納された画像データが生成出来ました。

しかし、機械学習をしていく際に、
1つの画像が1つのndarray型に入っている必要があります。

(もしかしたら、行と列が別々の配列でも良い可能性がありますが、今のところ学習させる際には、1つの画像が、1つの配列に入っている方がススメやすいと思います。)

もう少し説明します。
上記で作ったデータを見ていきます。

training_data.shape

(3, 350, 350)

3枚の画像が、350×350のサイズデータとして存在している。ということですね。

機械学習していく際には、( 画像個数, X )といったデータ型にする必要があります。
ここで Numpy reshapeを使います。
※X = 1次元の画像データ

batchdata = training_data.reshape(3,122500)
#122500 = 350 × 350
batchdata.shape

(3, 122500)

こういったカタチで、機械学習する際に必要なデータ型になりました。

このデータって、変換されてしまったら画像データとして存在しないのでは?と思うかもしれません。確認してみましょう。

一度、reshapeして、変換したデータを、元に戻してみます。

batchReverse = batchdata.reshape(3,350, 350)

for p in batchReverse:
  plt.imshow(p, cmap="gray")
  plt.show()

実行してみると、元の画像が表示されます。

ここで、疑問なのは、データの変換される順番とかが決まっているのか?
ということです。
いま試してみたのは、同じ操作をもとに戻しただけですが、これが複雑な操作の後に、戻そうと思った際に、どうなるのか。疑問は深まるばかりです。

Google Colaboratory で 画像データを読み込んでデータセットを作る方法

Google Colaboratory便利ですね。
Google Colaboratoryで、データセットを作成したく、色々と試してみました。

正直、これで良いのかまだ、不明なところがあるのですが、ひとまず、紹介です。
やることをざっくりと分けると、下記フローでした。

(1):画像データ一覧をZipファイルに圧縮
(2):ZipファイルをGoogle Colaboratoryへアップロード
(3):Google Colaboratoryで、zipファイルを解凍
(4):Zipファイル内の画像データのファイルパス一覧を取得
(5):画像のFilePathを個別に取得
(6):画像データをNumPy配列ndarrayとして取得
(7):画像のリサイズ
(8):NumPy配列ndarrayとして、データセットとして保存

(1):画像データ一覧をZipファイルに圧縮

これは、普通にやってください。
※犬の画像を3枚取得して。ファイル名を(a.png, b.png, c.png)としました。
※Zipファイル名をdataset_vol2.zipとしました

(2):ZipファイルをGoogle Colaboratoryへアップロード

ZipファイルをGoogle Colaboratoryへアップロードします。
Colaboratoryファイルの、左部を開くとアップロードという箇所があるので、ここから、zipファイルをアップロードします。

(3):Google Colaboratoryで、zipファイルを解凍

Colaboratoryで、Zipファイルを解凍する際はZipファイルがある場所まで移動しましょう。
まずは、自分が何処の階層にいるのかを確認しましょう。

!ls

dataset_vol2.zip
sample_data

dataset_vol2.zip がある階層です。
それでは、解凍していきましょう。
解凍するコマンドは、!unzip です。

!unzip dataset_vol2.zip

Archive: dataset_vol2.zip
creating: dataset_vol2/
inflating: dataset_vol2/b.png
creating: __MACOSX/
creating: __MACOSX/dataset_vol2/
inflating: __MACOSX/dataset_vol2/._b.png
inflating: dataset_vol2/c.png
inflating: __MACOSX/dataset_vol2/._c.png
inflating: dataset_vol2/a.png
inflating: __MACOSX/dataset_vol2/._a.png

これで、Zipファイルが解凍されました。

(4):Zipファイル内の画像データのファイルパス一覧を取得

解凍したファイルの中へ移動していきましょう。

#ファイル移動
%cd dataset_vol2
!ls

a.png b.png c.png

(5):画像のFilePathを個別に取得

必要なライブラリをimportします。

import matplotlib.pyplot as plt
import os
import cv2
import glob
import numpy as np

フォルダの中のファイルPath一覧を取得する方法として、
Pythonのglobモジュールを活用しました。 詳しくは、下記を参考にしてます。
ワイルドカード(*)などを使って柔軟にFilePathを取得できるので、便利ですね。

Pythonで条件を満たすパスの一覧を再帰的に取得するglobの使い方
https://note.nkmk.me/python-glob-usage/

また、現在位置は、dataset_vol2の中にいるので、
このままでも問題ないですが、globを使う際には、取得したいファイルの中に移動してあげるのがいいでしょう。

そのために、コマンドじゃなく、ファイル階層を移動できる下記を使いました。
os.chdir(“Path名称”)

#階層移動
os.chdir("/content/dataset_vol2")
#階層内のPathを全取得
path = glob.glob("*")
print(path)

[‘a.png’, ‘c.png’, ‘b.png’]

もちろん、今回はファイル名を(a.png, b.png, c.png)にしたので、
当たり前の結果ですが、データ個数が多くなれば必要な作業です。

(6):画像データをNumPy配列ndarrayとして取得
(7):画像のリサイズ
(8):NumPy配列ndarrayとして、データセットとして保存

ここからは、一気にデータセット作成までいきましょう。

#データセットを格納する変数
training_data = []
#リサイズ後のサイズ
IMG_SIZE = 350

#個別のFilePathに対して処理していきます。
for p in path:
   pathEach = p
   print(pathEach)

  #NumPy配列ndarrayとして読み込まれ、ndarrayを画像として保存
   imageTTTT = cv2.imread(pathEach,cv2.IMREAD_GRAYSCALE)
  #画像のりサイズ
   img_resize_array = cv2.resize(imageTTTT, (IMG_SIZE, IMG_SIZE))
   print(imageTTTT)
   print(img_resize_array.dtype)
   training_data.append(img_resize_array)
   plt.imshow(img_resize_array, cmap="gray")
   plt.show()
   print("=============")

cv2.imreadを解説します。
OpenCVライブラリでは、様々なことができます。
imreadメソッドで、画像ファイルを読み込み、
NumPy配列ndarrayとして読み込まれ、ndarrayを画像として保存することができます。

ndarray型については、下記記事にも書きましたので参照下さい。
Numpyのarray・ndarrayって何。 簡単に説明します。
http://prglog.info/home/?p=29

imreadの詳細については、下記参考

▼Python, OpenCVで画像ファイルの読み込み、保存
https://note.nkmk.me/python-opencv-imread-imwrite/

print(training_data)

[array([[ 36, 36, 36, …, 191, 193, 193],
[ 36, 36, 36, …, 191, 192, 192],
[ 36, 36, 36, …, 190, 190, 190],
…,
[223, 221, 220, …, 225, 226, 228],
[225, 223, 222, …, 226, 228, 230],
[227, 225, 224, …, 228, 230, 232]], dtype=uint8), array([[ 84, 83, 82, …, 29, 27, 27],
[ 93, 92, 91, …, 34, 33, 32],
[102, 102, 101, …, 38, 37, 36],
…,
[126, 117, 110, …, 128, 133, 121],
[123, 117, 116, …, 134, 138, 127],
[119, 118, 122, …, 138, 142, 132]], dtype=uint8), array([[158, 158, 158, …, 142, 144, 147],
[158, 158, 158, …, 144, 146, 148],
[158, 158, 157, …, 146, 148, 149],
…,
[211, 208, 208, …, 212, 212, 211],
[219, 217, 217, …, 208, 207, 206],
[224, 223, 223, …, 205, 203, 203]], dtype=uint8)]

ここで、完了かなと思います。
ただ、他の記事を見てみると、ここからarrayメソッドを使って、ndarray型にデータを変換していたりします。

training_data = np.array(training_data)
print(training_data)

[[[ 36 36 36 … 191 193 193]
[ 36 36 36 … 191 192 192]
[ 36 36 36 … 190 190 190]

[223 221 220 … 225 226 228]
[225 223 222 … 226 228 230]
[227 225 224 … 228 230 232]]

[[ 84 83 82 … 29 27 27]
[ 93 92 91 … 34 33 32]
[102 102 101 … 38 37 36]

[126 117 110 … 128 133 121]
[123 117 116 … 134 138 127]
[119 118 122 … 138 142 132]]

[[158 158 158 … 142 144 147]
[158 158 158 … 144 146 148]
[158 158 157 … 146 148 149]

[211 208 208 … 212 212 211]
[219 217 217 … 208 207 206]
[224 223 223 … 205 203 203]]]

これで、ndarray型のデータが出来上がったということなのでしょうか。
ここは少し理解が浅いところですので、調べてみます。

Google Collaboratory で tensorflowのバージョンを変更する方法

非常に簡単です。
基本的には、Tensorflowのサイトに記載している通りです。

https://www.tensorflow.org/install/gpu

!pip install tensorflow==1.15

一つだけ注意する点は、
Collaboratory上で、pip する際には、 !pip とする必要があります。

バージョンが変更されたかを確認しましょう。

import tensorflow as tf
print(tf.__version__)

1.15.0

このように指定した、バージョンに変更されたら完了です。

一度、既存のバージョンで、import tensorflow as tfしてしまった場合には、
新しいCollaboratoryファイルでやり直すか、下記のように、uninstallした後に、指定のバージョンをinstallしましょう。

!pip uninstall -y tensorflow
!pip install tensorflow==1.15

tensorflowはバージョン違いで、エラーが起きるので、柔軟に使用しましょう。