Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/ja/tutorials/images/classification.ipynb
25118 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Image classification

このチュートリアルでは、tf.keras.Sequential モデルを使用して花の画像を分類し、tf.keras.utils.image_dataset_from_directory を使用してデータを読み込む方法を示します。このチュートリアルでは、次の概念を実際に見ていきます。

  • ディスク上のデータセットを効率的に読み込みます。

  • 過学習を識別し、データ拡張やドロップアウトなどテクニックを使用して過学習を防ぎます。

このチュートリアルは、基本的な機械学習のワークフローに従います。

  1. データの調査及び理解

  2. 入力パイプラインの構築

  3. モデルの構築

  4. モデルの学習

  5. モデルのテスト

  6. モデルの改善とプロセスの繰り返し

さらに、このノートブックは、保存されたモデルを、モバイルデバイス、組み込みデバイス、IoT デバイスでのオンデバイス機械学習用の TensorFlow Lite モデルに変換する方法を実演します。

セットアップ

TensorFlow とその他の必要なライブラリをインポートします。

import matplotlib.pyplot as plt import numpy as np import PIL import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers from tensorflow.keras.models import Sequential

データセットをダウンロードして調査する

このチュートリアルでは、約3,700枚の花の写真のデータセットを使用します。データセットには、クラスごとに1つずつ、5 つのサブディレクトリが含まれています。

flower_photo/ daisy/ dandelion/ roses/ sunflowers/ tulips/
import pathlib dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz" data_dir = tf.keras.utils.get_file('flower_photos.tar', origin=dataset_url, extract=True) data_dir = pathlib.Path(data_dir).with_suffix('')

ダウンロード後、データセットのコピーが利用できるようになります。合計3,670枚の画像があります。

image_count = len(list(data_dir.glob('*/*.jpg'))) print(image_count)

バラの画像です。

roses = list(data_dir.glob('roses/*')) PIL.Image.open(str(roses[0]))
PIL.Image.open(str(roses[1]))

チューリップの画像です。

tulips = list(data_dir.glob('tulips/*')) PIL.Image.open(str(tulips[0]))
PIL.Image.open(str(tulips[1]))

Keras ユーティリティを使用してデータを読み込む

次に、便利な image_dataset_from_directory ユーティリティを使用して、これらの画像をディスクから読み込みます。これにより、数行のコードでディスク上の画像のディレクトリから tf.data.Datasetに移動します。また、画像を読み込んで前処理するチュートリアルにアクセスして、独自のデータ読み込みコードを最初から作成することもできます。

データセットを作成する

ローダーのいくつかのパラメーターを定義します。

batch_size = 32 img_height = 180 img_width = 180

モデルを開発するときは、検証分割を使用することをお勧めします。ここでは、画像の 80% をトレーニングに使用し、20% を検証に使用します。

train_ds = tf.keras.utils.image_dataset_from_directory( data_dir, validation_split=0.2, subset="training", seed=123, image_size=(img_height, img_width), batch_size=batch_size)
val_ds = tf.keras.utils.image_dataset_from_directory( data_dir, validation_split=0.2, subset="validation", seed=123, image_size=(img_height, img_width), batch_size=batch_size)

クラス名は、これらのデータセットのclass_names属性にあります。 これらはアルファベット順にディレクトリ名に対応します。

class_names = train_ds.class_names print(class_names)

データを視覚化する

以下はトレーニングデータセットの最初の 9 枚の画像です。

import matplotlib.pyplot as plt plt.figure(figsize=(10, 10)) for images, labels in train_ds.take(1): for i in range(9): ax = plt.subplot(3, 3, i + 1) plt.imshow(images[i].numpy().astype("uint8")) plt.title(class_names[labels[i]]) plt.axis("off")

これらのデータセットを Keras Model.fit に渡すことで、モデルをトレーニングできます(このチュートリアルの後の方で説明しています)。また、手動でデータセットを反復し、画像のバッチを取得することもできます。

for image_batch, labels_batch in train_ds: print(image_batch.shape) print(labels_batch.shape) break

image_batchは、形状(32, 180, 180, 3)のテンソルです。これは、形状180x180x3の 32 枚の画像のバッチです(最後の次元はカラーチャンネル RGB を参照します)。label_batchは、形状(32,)のテンソルであり、これらは 32 枚の画像に対応するラベルです。

image_batchおよびlabels_batchテンソルで.numpy()を呼び出して、それらをnumpy.ndarrayに変換できます。

データセットを構成してパフォーマンスを改善する

I/O がブロックされることなくディスクからデータを取得できるように、必ずバッファ付きプリフェッチを使用します。これらは、データを読み込むときに使用する必要がある 2 つの重要な方法です。

  • Dataset.cache()は、最初のエポック中に画像をディスクから読み込んだ後、メモリに保持します。これにより、モデルのトレーニング中にデータセットがボトルネックになることを回避できます。データセットが大きすぎてメモリに収まらない場合は、この方法を使用して、パフォーマンスの高いオンディスクキャッシュを作成することもできます。

  • Dataset.prefetch はトレーニング中にデータの前処理とモデルの実行をオーバーラップさせます。

以上の 2 つの方法とデータをディスクにキャッシュする方法についての詳細は、データパフォーマンスガイドプリフェッチを参照してください。

AUTOTUNE = tf.data.AUTOTUNE train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE) val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

データを標準化する

RGB チャネル値は [0, 255] の範囲にあり、ニューラルネットワークには理想的ではありません。一般に、入力値は小さくする必要があります。

ここでは、tf.keras.layers.Rescaling を使用して、値を [0, 1] の範囲に標準化します。

normalization_layer = layers.Rescaling(1./255)

このレイヤーを使用するには 2 つの方法があります。Dataset.map を呼び出すことにより、データセットに適用できます。

normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y)) image_batch, labels_batch = next(iter(normalized_ds)) first_image = image_batch[0] # Notice the pixel values are now in `[0,1]`. print(np.min(first_image), np.max(first_image))

または、モデル定義内にレイヤーを含めることができます。これにより、デプロイメントを簡素化できます。 ここでは 2 番目のアプローチを使用します。

注意: 以前は、tf.keras.utils.image_dataset_from_directoryimage_size 引数を使用して画像のサイズを変更しました。モデルにサイズ変更ロジックも含める場合は、tf.keras.layers.Resizing レイヤーを使用できます。

基本的な Keras モデル

モデルを作成する

Sequential モデルは、それぞれに最大プールレイヤー (tf.keras.layers.MaxPooling2D)を持つ 3 つの畳み込みブロック(tf.keras.layers.Conv2D)で構成されます。ReLU 活性化関数('relu')により活性化されたユニットが 128 個ある完全に接続されたレイヤー (tf.keras.layers.Dense)があります。このチュートリアルの目的は、標準的なアプローチを示すことなので、このモデルは高精度に調整されていません。

num_classes = len(class_names) model = Sequential([ layers.Rescaling(1./255, input_shape=(img_height, img_width, 3)), layers.Conv2D(16, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(32, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(64, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Flatten(), layers.Dense(128, activation='relu'), layers.Dense(num_classes) ])

モデルをコンパイルする

このチュートリアルでは、tf.keras.optimizers.Adam オプティマイザとtf.keras.losses.SparseCategoricalCrossentropy 損失関数を選択します。各トレーニングエポックのトレーニングと検証の精度を表示するには、Model.compilemetrics 引数を渡します。

model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy'])

モデルの概要

Keras の Model.summary メソッドを使用して、ネットワークのすべてのレイヤーを表示します。

model.summary()

モデルをトレーニングする

Keras Model.fit メソッドを使用して、10 エポックのモデルをトレーニングします。

epochs=10 history = model.fit( train_ds, validation_data=val_ds, epochs=epochs )

トレーニングの結果を視覚化する

トレーニングセットと検証セットで損失と精度のプロットを作成します。

acc = history.history['accuracy'] val_acc = history.history['val_accuracy'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs_range = range(epochs) plt.figure(figsize=(8, 8)) plt.subplot(1, 2, 1) plt.plot(epochs_range, acc, label='Training Accuracy') plt.plot(epochs_range, val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.title('Training and Validation Accuracy') plt.subplot(1, 2, 2) plt.plot(epochs_range, loss, label='Training Loss') plt.plot(epochs_range, val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.title('Training and Validation Loss') plt.show()

プロットには、トレーニングの精度と検証の精度は大幅にずれており、モデルは検証セットで約 60% の精度しか達成していないことが示されています。

以下のチュートリアルセクションでは、問題の原因を調べ、モデルの全体的なパフォーマンスを向上させる方法を示します。

過学習

上記のプロットでは、トレーニングの精度は時間の経過とともに直線的に増加していますが、検証の精度はトレーニングプロセスで約60%のままです。また、トレーニングと検証の精度に大きな違いがあり、これは過学習の兆候を示しています。

トレーニングサンプルの数が少ない場合、モデルは、トレーニングサンプルのノイズや不要な詳細から学習し、新しいサンプルでのモデルのパフォーマンスに悪影響を及ぼすことがあります。 この現象は過学習として知られています。 これは、モデルが新しいデータセットで一般化する上で問題があることを意味します。

トレーニングプロセスで過学習を回避する方法は複数あります。このチュートリアルでは、データ拡張を使用して、モデルにドロップアウトを追加します。

データ拡張

過学習は、一般に、トレーニングサンプルの数が少ない場合に発生します。データ拡張は、既存のサンプルに対してランダムな変換を使用してサンプルを拡張することにより、追加のトレーニングデータを生成します。これにより、モデルをデータのより多くの側面でトレーニングし、より一般化することができます。

tf.keras.layers.RandomFliptf.keras.layers.RandomRotation、および tf.keras.layers.RandomZoom の前処理レイヤーを使用して、データ拡張を実装します。これらは、他のレイヤーと同様にモデル内に含めて、GPU で実行できます。

data_augmentation = keras.Sequential( [ layers.RandomFlip("horizontal", input_shape=(img_height, img_width, 3)), layers.RandomRotation(0.1), layers.RandomZoom(0.1), ] )

同じ画像にデータ拡張を数回適用して、いくつかの拡張されたデータがどのようになるかを視覚化してみましょう。

plt.figure(figsize=(10, 10)) for images, _ in train_ds.take(1): for i in range(9): augmented_images = data_augmentation(images) ax = plt.subplot(3, 3, i + 1) plt.imshow(augmented_images[0].numpy().astype("uint8")) plt.axis("off")

次のステップでトレーニングする前に、モデルにデータ拡張を追加します。

ドロップアウト

過学習を回避するもう 1 つの方法は、ドロップアウト{:.external} 正則化をネットワークに導入することです。

ドロップアウトをレイヤーに適用すると、トレーニングプロセス中にレイヤーからいくつかの出力ユニットがランダムにドロップアウトされます(アクティベーションをゼロに設定することにより)。ドロップアウトは、0.1、0.2、0.4 などの形式で、入力値として小数を取ります。これは、適用されたレイヤーから出力ユニットの 10%、20%、または 40% をランダムにドロップアウトすることを意味します。

拡張された画像を使用してトレーニングする前に、tf.keras.layers.Dropout を使用して新しいニューラルネットワークを作成します。

model = Sequential([ data_augmentation, layers.Rescaling(1./255), layers.Conv2D(16, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(32, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(64, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Dropout(0.2), layers.Flatten(), layers.Dense(128, activation='relu'), layers.Dense(num_classes, name="outputs") ])

モデルをコンパイルしてトレーニングする

model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy'])
model.summary()
epochs = 15 history = model.fit( train_ds, validation_data=val_ds, epochs=epochs )

トレーニングの結果を視覚化する

データ拡張と tf.keras.layers.Dropout を適用した後は、以前よりも過学習が少なくなり、トレーニングと検証がより高精度に調整されます。

acc = history.history['accuracy'] val_acc = history.history['val_accuracy'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs_range = range(epochs) plt.figure(figsize=(8, 8)) plt.subplot(1, 2, 1) plt.plot(epochs_range, acc, label='Training Accuracy') plt.plot(epochs_range, val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.title('Training and Validation Accuracy') plt.subplot(1, 2, 2) plt.plot(epochs_range, loss, label='Training Loss') plt.plot(epochs_range, val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.title('Training and Validation Loss') plt.show()

新しいデータを予測する

モデルを使用して、トレーニングセットまたは検証セットに含まれていなかった画像を分類します。

注意: データ拡張レイヤーとドロップアウトレイヤーは、推論時に非アクティブになります。

sunflower_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/592px-Red_sunflower.jpg" sunflower_path = tf.keras.utils.get_file('Red_sunflower', origin=sunflower_url) img = tf.keras.utils.load_img( sunflower_path, target_size=(img_height, img_width) ) img_array = tf.keras.utils.img_to_array(img) img_array = tf.expand_dims(img_array, 0) # Create a batch predictions = model.predict(img_array) score = tf.nn.softmax(predictions[0]) print( "This image most likely belongs to {} with a {:.2f} percent confidence." .format(class_names[np.argmax(score)], 100 * np.max(score)) )

TensorFlow Lite を使用する

TensorFlow Lite は、オンデバイスの機械学習を可能にする一連のツールで、開発者がモバイルデバイス、組み込みデバイス、エッジデバイスでモデルを実行できるようにします。

Keras Sequential モデルを TensorFlow Lite モデルに変換する

トレーニング済みのモデルをオンデバイスのアプリケーションで使用するには、まず TensorFlow Lite モデルと呼ばれる、より小さく効率的なモデル形式に変換します。

この例では、トレーニング済みの Keras Sequential モデルを取得し、tf.lite.TFLiteConverter.from_keras_model を使用して TensorFlow Lite モデルを生成します。

# Convert the model. converter = tf.lite.TFLiteConverter.from_keras_model(model) tflite_model = converter.convert() # Save the model. with open('model.tflite', 'wb') as f: f.write(tflite_model)

前のステップで保存した TensorFlow Lite モデルには、複数の関数シグネチャを含めることができます。Keras モデルコンバーター API は、デフォルトのシグネチャを自動的に使用します。詳細は TensorFlow Lite シグネチャを参照してください。

TensorFlow Lite モデルを実行する

tf.lite.Interpreter クラスを介して、Python で TensorFlow Lite の保存されたモデルシグネチャにアクセスできます。

Interpreter を使用してモデルを読み込みます。

TF_MODEL_FILE_PATH = 'model.tflite' # The default path to the saved TensorFlow Lite model interpreter = tf.lite.Interpreter(model_path=TF_MODEL_FILE_PATH)

変換されたモデルからシグネチャを出力して、入力 (および出力) の名前を取得します。

interpreter.get_signature_list()

この例では、serving_default という名前のデフォルトシグネチャが 1 つあります。さらに、'inputs' の名前は 'sequential_1_input' であり、'outputs' の名前は 'outputs' です。このチュートリアルで前に示したように、Model.summary を実行すると、これらの最初と最後の Keras レイヤー名を検索できます。

次のようにシグネチャ名を渡すことで、tf.lite.Interpreter.get_signature_runner を使用してサンプル画像で推論を実行し、読み込まれた TensorFlow モデルをテストできます。

classify_lite = interpreter.get_signature_runner('serving_default') classify_lite

チュートリアルの前半で行ったように、TensorFlow Lite モデルを使用して、トレーニングセットまたは検証セットに含まれていない画像を分類できます。

画像は既にテンソル化され、img_array として保存されています。次に、読み込まれた TensorFlow Lite モデル (predictions_lite)の最初の引数 ('inputs' の名前)に渡し、ソフトマックス活性化を計算し、計算された確率が最も高いクラスの予測を出力します。

predictions_lite = classify_lite(sequential_1_input=img_array)['outputs'] score_lite = tf.nn.softmax(predictions_lite)
print( "This image most likely belongs to {} with a {:.2f} percent confidence." .format(class_names[np.argmax(score_lite)], 100 * np.max(score_lite)) )

Lite モデルが生成した予測は、元のモデルが生成した予測とほぼ同一になります。

print(np.max(np.abs(predictions - predictions_lite)))

モデルは画像が 5 つのクラス、'daisy''dandelion''roses''sunflowers'、および 'tulips' のうちヒマワリに属すると予測する必要があります。これは TensorFlow Lite 変換前と同じ結果です。

次のステップ

このチュートリアルでは、画像分類用のモデルをトレーニングしてテストし、オンデバイスのアプリケーション(画像分類アプリケーションなど)用の TensorFlow Lite 形式に変換し、Python API を使用して TensorFlow Lite モデルで推論を実行する方法を示しました。

TensorFlow Lite についての詳細は、チュートリアルガイドを参照してください。