TensorFlowのデータのフォーマット
このブログシリーズのパート1では、リレーショナルデータベースを使用して、単純なSQLステートメントを使用して画像のデータ探索を保存および実行することの利点を示しました。このチュートリアル、パート2では、パート1で使用されるデータは、MariaDBサーバーデータベースからアクセスされ、TensorFlowに必要なデータ構造に変換されます。モデルを適用して新しい画像を分類した結果は、さらに分析するためにリレーショナルテーブルに保存されます。
これは、TensorFlowプログラムの簡単なチュートリアルであり、詳細を説明します。基本的な概念に精通していない場合は、このTensorFlowチュートリアル「基本的な分類:衣服の画像の分類」から始めることをお勧めします。ここでは、チュートリアルの例とコードの一部を使用しています。
必要な追加パッケージ
画像分類モデルの構築とトレーニングには、いくつかの追加パッケージが必要です。
- ピクルス Pythonオブジェクト構造をシリアル化および逆シリアル化するためのバイナリプロトコルを実装します。
- NumPy これらの配列を操作するための高レベルの数学関数とともに、大規模な多次元配列と行列のサポートを提供します。
- TensorFlow 高速数値計算用のPythonライブラリです。これは、ディープラーニングモデルを直接作成するため、またはTensorFlow上に構築されたプロセスを簡素化するラッパーライブラリを使用して使用できる基盤ライブラリです。
- ケラス Pythonで書かれたオープンソースのニューラルネットワークライブラリです。
import pickle import numpy as np import tensorflow as tf from tensorflow import keras print('Tensorflow version: ', tf.__version__) print('Numpy version: ', np.__version__) Tensorflow version: 2.0.0 Numpy version: 1.16.2
画像の取得
パッケージがインポートされたら、次のステップはデータベースからトレーニング画像を取得し、データを2つの numpyに分割することです。 アレイ。まず、トレーニング画像(train_images)とトレーニングラベル(train_labels)の配列を初期化する必要があります。すでに画像をベクトル化したので、img_vector属性を使用して、train_images配列に以下のSQLステートメントを入力できます。
# Initialize the numpy arrays train_images = np.empty((60000,28,28), dtype='uint8') train_labels = np.empty((60000), dtype='uint8') # Retrieve the training images from the database sql="SELECT img_label, img_vector, img_idx \ FROM tf_images INNER JOIN img_use ON img_use = use_id \ WHERE use_name = 'Training'" cur.execute(sql) result = cur.fetchall() # Populate the numpy arrays. row[2] contains the image index for row in result: nparray = pickle.loads(row[1]) train_images[row[2]] = nparray train_labels[row[2]] = row[0]
同様の方法で、テスト用の画像をデータベースから取得できます。 numpy この場合に使用される配列は、test_imagesとtest_labelsです。この場合、テストデータは28×28ピクセルの解像度で10,000枚の画像です。
# Initialize the numpy arrays test_images = np.empty((10000,28,28), dtype='uint8') test_labels = np.empty((10000), dtype='uint8') # Retrieve the testing images from the database sql="SELECT img_label, img_vector, img_idx \ FROM tf_images INNER JOIN img_use ON img_use = use_id \ WHERE use_name = 'Testing'" cur.execute(sql) result = cur.fetchall() # Populate the numpy arrays. row[2] contains the image index for row in result: nparray = pickle.loads(row[1]) test_images[row[2]] = nparray test_labels[row[2]] = row[0]
最後に、各画像は単一のラベルにマッピングされます。ラベル名はcategoriesテーブルに保存され、class_names配列にロードされます:
sql="SELECT class_name FROM categories" cur.execute(sql) class_names = cur.fetchall()
データの前処理
ネットワークをトレーニングする前に、データを前処理する必要があります。トレーニングセットの最初の画像を調べると、ピクセル値が0〜255の範囲にあることがわかります。
plt.figure() plt.imshow(train_images[0]) plt.colorbar() plt.grid(False) plt.show()
上記:fashion_mnistデータセットからの画像
画像をニューラルネットワークモデルにフィードする前に、値を0〜1の範囲にスケーリングする必要があります。そのためには、値を255で除算します。トレーニングセットとテストセットを同じ方法で前処理することが重要です。 。
matplotlibを使用できます 最初の25枚の画像を表示して、データが正しい形式であり、ネットワークを構築およびトレーニングする準備ができていることを確認します。
train_images = train_images / 255.0 test_images = test_images / 255.0 plt.figure(figsize=(10,10)) for i in range(25): plt.subplot(5,5,i+1) plt.xticks([]) plt.yticks([]) plt.grid(False) plt.imshow(train_images[i], cmap=plt.cm.binary) plt.xlabel(class_names[train_labels[i]]) plt.show()
上記:fashion_mnistデータセットからの画像
モデルの構築
データが2つのサブセットに前処理された後、モデルのトレーニングに進むことができます。このプロセスでは、アルゴリズムにトレーニングデータを「フィード」する必要があります。アルゴリズムはデータを処理し、新しいデータでターゲット値(属性)を見つけることができるモデルを出力します。つまり、ニューラルネットワークに提示された画像を分類します。
ほとんどの深層学習ニューラルネットワークは、単純なレイヤーを連鎖させることによって生成されます。
ネットワークの最初のレイヤーは、画像形式を2次元配列(28 x 28ピクセル)から1次元配列(28 * 28 =784ピクセル)に変換します。このレイヤーには学習するパラメーターがありません。データを再フォーマットするだけです。
ピクセルが平坦化された後、ネットワークはアクティブ化する必要がある2つの完全に接続されたレイヤーで構成されます。ニューラルネットワークでは、活性化関数は、ノードからの加重入力の合計を、ノードまたはその入力の出力のアクティブ化に変換する役割を果たします。
最初の密な層には128個のノード(またはニューロン)があり、Rectified Linear Unit(ReLU)アクティベーションメソッドを使用しています。整流された線形活性化関数は区分的線形関数であり、正の場合は入力を直接出力し、そうでない場合はゼロを出力します。
2番目(そして最後)の層は10ノードのsoftmax層です。ソフトマックス関数は、潜在的な結果のリストの確率分布を表すベクトルを出力します。合計が1になる10個の確率スコアの配列を返します。各ノードには、現在の画像が10個のクラスの1つに属する確率を示すスコアが含まれています。
tf.keras.layers.Denseなどのほとんどのレイヤーには、トレーニング中に学習されるパラメーターがあります。
model = keras.Sequential([ keras.layers.Flatten(input_shape=(28, 28)), keras.layers.Dense(128, activation='relu'), keras.layers.Dense(10, activation='softmax') ])
モデルのコンパイル
モデルのコンパイル手順は、トレーニングの準備が整う前に、さらにいくつかの設定を追加するために使用されます。この場合、以下の設定が有効になります。
- オプティマイザー-表示されるデータとその損失関数に基づいてモデルを更新します(以下を参照)。
- 損失関数-トレーニング中のモデルの精度を測定します。この関数を最小化して、モデルを正しい方向に「操縦」する必要があります。
- メトリクス-トレーニングとテストの手順を監視します。次の例では、正確に分類された画像の割合である精度を使用しています。
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
モデルのトレーニング
ニューラルネットワークモデルのトレーニングには、次の手順が必要です。
- トレーニングデータをモデルにフィードします。
- モデルは画像とラベルの関連付けを学習します。
- テストセットについて予測します。
- 予測がtest_labels配列のラベルと一致することを確認します。
トレーニングを開始するには、model.fitメソッドを呼び出します。これは、モデルをトレーニングデータに「適合」させるために呼び出されます。
model.fit(train_images, train_labels, epochs=10) Train on 60000 samples Epoch 1/10 60000/60000 [==============================] - 5s 83us/sample - loss: 0.4964 - accuracy: 0.8236 Epoch 2/10 60000/60000 [==============================] - 4s 65us/sample - loss: 0.3735 - accuracy: 0.8642 Epoch 3/10 60000/60000 [==============================] - 3s 55us/sample - loss: 0.3347 - accuracy: 0.8773 Epoch 4/10 60000/60000 [==============================] - 3s 56us/sample - loss: 0.3106 - accuracy: 0.8861 Epoch 5/10 60000/60000 [==============================] - 3s 58us/sample - loss: 0.2921 - accuracy: 0.8924s - loss: 0.2928 - accura - ETA: 0s - loss: 0.2925 - accuracy Epoch 6/10 60000/60000 [==============================] - 3s 57us/sample - loss: 0.2796 - accuracy: 0.8969s Epoch 7/10 60000/60000 [==============================] - 4s 70us/sample - loss: 0.2659 - accuracy: 0.9007 Epoch 8/10 60000/60000 [==============================] - 4s 61us/sample - loss: 0.2548 - accuracy: 0.9042 Epoch 9/10 60000/60000 [==============================] - 4s 61us/sample - loss: 0.2449 - accuracy: 0.9084 Epoch 10/10 60000/60000 [==============================] - 5s 76us/sample - loss: 0.2358 - accuracy: 0.9118
各エポックの終わりに、ニューラルネットワークは検証セットに対して評価されます。これが損失と精度の意味です。
精度を評価して予測する
モデルの全体的な精度を推定するには、精度値の10回の出現すべての平均を計算します。この場合は88%です。
次に、 model.evaluateを実行します テストセットで、これまでに見られなかったデータでトレーニングされたニューラルネットワークの予測精度を取得します。
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2) 10000/1 - 0s - loss: 0.2766 - accuracy: 0.8740
テストデータセットは、トレーニングデータセットよりも精度が低くなります。この場合、トレーニング精度とテスト精度の間のこのギャップは、過剰適合を表します。反対は不十分です。このトピックについて詳しく知りたい場合は、過剰適合と過適合:WillKoehrsenによる概念的な説明をお勧めします。
この時点で、トレーニングデータセット内の画像についていくつかの予測を行うことができます。
predictions = model.predict(test_images) predictions[0] array([1.90860412e-08, 8.05085235e-11, 1.56402713e-08, 1.66699390e-10, 7.86950158e-11, 4.33062996e-06, 2.49049066e-08, 1.20656565e-02, 3.80084719e-09, 9.87929940e-01], dtype=float32)
model.predictの出力 は、各クラスに属するインスタンスの確率を持つ10個の数値の配列です。さらなる分析とレポートのために結果をMariaDBデータベースに保持することは良い考えです。以下は、予測配列を反復処理してタプルを作成し、それを prediction_resultsに挿入する方法の例です。 テーブル。
sql = "INSERT INTO prediction_results ( img_idx , img_use , T_shirt_Top , Trouser , Pullover , Dress , Coat , Sandal , Shirt , Sneaker , Bag , Ankle_boot , label) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);" i = 0 for row in predictions: insert_tuple = (str(i), str(2) , str(row[0]), str(row[1]), str(row[2]), str(row[3]), str(row[4]) , str(row[5]), str(row[6]), str(row[7]), str(row[8]), str(row[9]) , str(test_labels[i])) cur.execute(sql, insert_tuple) conn.commit() i += 1
ここでも、単純なSQLステートメントを使用して、データがロードされたことを確認できます。
sql = "SELECT T_shirt_Top , Trouser , Pullover , Dress , Coat , Sandal , Shirt , Sneaker , Bag , Ankle_boot , class_name as 'Test Label' FROM prediction_results JOIN categories ON label = class_idx WHERE img_idx = 1" display( pd.read_sql(sql,conn) )
T_shirt_Top | ズボン | プルオーバー | ドレス | コート | サンダル | シャツ | スニーカー | バッグ | Ankle_boot | テストラベル |
0.00001 | 0.0 | 0.997912 | 0.0 | 0.001267 | 0.0 | 0.00081 | 0.0 | 0.0 | 0.0 | プルオーバー |
予測のプロット
予測を表示するためのいくつかのプロット関数を以下に定義します(グラフ関数)。
テストセットから新しい画像を取得し、予測確率に基づいてニューラルネットの分類を表示しましょう。
sql = "SELECT img_idx, label FROM prediction_results WHERE img_idx = 1" cur.execute(sql) result = cur.fetchone() plt.figure(figsize=(6,3)) plt.subplot(1,2,1) plot_image(result[0], predictions[result[0]], test_labels, test_images) plt.subplot(1,2,2) plot_value_array(result[0], predictions[result[0]], test_labels) plt.show()
上記:fashion_mnistデータセットからの画像
この場合、モデルは100%の精度で画像を正しく分類することができました。次に、クエリを実行して、テストセットから最初の15枚の画像を取得し、分類します。
sql = "SELECT img_idx, label FROM prediction_results LIMIT 15" num_rows = 5 num_cols = 3 plt.figure(figsize=(2*2*num_cols, 2*num_rows)) cur.execute(sql) result = cur.fetchall() for row in result: plt.subplot(num_rows, 2*num_cols, 2*row[0]+1) plot_image(row[0], predictions[row[0]], test_labels, test_images) plt.subplot(num_rows, 2*num_cols, 2*row[0]+2) plot_value_array(row[0], predictions[row[0]], test_labels) plt.tight_layout() plt.show()
上記:fashion_mnistデータセットからの画像
ご覧のとおり、最後の行の左の列に示されているように、モデルが間違っている場合があります。この場合、スニーカーはサンダル(赤)に分類されました。
まとめ
TensorFlowとMariaDBServerの統合は簡単ですが、この統合のメリットはかなりのものです。
- 機械学習内でリレーショナルデータを使用すると、実装の複雑さを軽減できます。データサイエンティストとデータエンジニアは同様に、共通の言語を使用してデータのラングリングと探索のタスクを実行できます。
- データへのアクセス、更新、挿入、操作、変更を効率化することで、市場投入までの時間を短縮できます。
- モデルの結果をデータベースに保存する機能により、エンドユーザーとアナリストはTableauなどの使いやすいレポートツールを使用してクエリとレポートを実行できます。
MITライセンス
このブログで利用されているFashionMNIST(fashion_mnist)データセットは、MITライセンスの下でライセンスされています。Copyright©2017 Zalando SE、https://tech.zalando.com
このブログで利用されているソースコードは、MIT License、Copyright(c)2017FrançoisCholletの下でライセンスされている「基本的な分類:衣類の画像の分類」チュートリアルから採用されています。
これにより、このソフトウェアおよび関連するドキュメントファイル(「ソフトウェア」)のコピーを取得するすべての人に、使用、コピー、変更、マージの権利を含むがこれに限定されない制限なしにソフトウェアを取り扱う許可が無料で付与されます。 、ソフトウェアのコピーを公開、配布、サブライセンス、および/または販売し、以下の条件に従って、ソフトウェアが提供された人にそうすることを許可する:
上記の著作権表示およびこの許可通知は、ソフトウェアのすべてのコピーまたは大部分に含まれるものとします。
本ソフトウェアは「現状有姿」で提供され、商品性、特定目的への適合性、および非侵害の保証を含むがこれらに限定されない、明示または黙示を問わず、いかなる種類の保証もありません。いかなる場合も、作者または著作権所有者は、契約、不法行為、またはその他の行為にかかわらず、ソフトウェアまたはソフトウェアの使用またはその他の取引に起因する、または関連する、いかなる請求、損害、またはその他の責任についても責任を負わないものとします。ソフトウェア。
参考資料
自分の画像をMNISTの画像に変換する
matplotlib:画像チュートリアル
AIがカスタマーエクスペリエンスを変革する5つの方法
デジタル化はビジネスを再発明する
画像分類とは
Pythonの概要ディープラーニングライブラリTensorFlow
グラフ関数
def plot_image(i, predictions_array, true_label, img): predictions_array, true_label, img = predictions_array, true_label[i], img[i] plt.grid(False) plt.xticks([]) plt.yticks([]) plt.imshow(img, cmap=plt.cm.binary) predicted_label = np.argmax(predictions_array) if predicted_label == true_label: color = 'blue' else: color = 'red' plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label], 100*np.max(predictions_array), class_names[true_label]), color=color) def plot_value_array(i, predictions_array, true_label): predictions_array, true_label = predictions_array, true_label[i] plt.grid(False) plt.xticks(range(10)) plt.yticks([]) thisplot = plt.bar(range(10), predictions_array, color="#777777") plt.ylim([0, 1]) predicted_label = np.argmax(predictions_array) thisplot[predicted_label].set_color('red') thisplot[true_label].set_color('blue')