この Codelab について
1. 始める前に
この Codelab では、衣服のアイテムを TensorFlow で認識できるコンピュータ ビジョン モデルを作成します。
前提条件
- Python に関する確かな知識
- 基本的なプログラミング スキル
ラボの内容
この Codelab では次のことを学習します。
- 衣類の記事を認識するためのニューラル ネットワークをトレーニングする
- 一連の演習を行い、ネットワークのさまざまなレイヤを試す
作成するアプリの概要
- 衣服の記事を識別するニューラル ネットワーク
必要なもの
TensorFlow を使用したコンピュータ ビジョン用のニューラル ネットワークを作成したことがない場合は、必要なすべての依存関係を含むブラウザベースの環境である Colaboratory を使用できます。Colab で実行する Codelab の残りの部分のコードを確認できます。
それ以外の場合は、モデルのトレーニングに使用する主な言語は Python であるため、インストールする必要があります。上記に加えて、TensorFlow と NumPy ライブラリも必要です。TensorFlow の詳細については、こちらをご覧ください。ここで NumPy をインストールします。
2. コーディングを開始
まず、実行可能な Colab ノートブックを確認します。
まず、TensorFlow をインポートします。
import tensorflow as tf
print(tf.__version__)
Fashion MNIST という一般的なデータセットから服の種類を認識できるようにニューラル ネットワークをトレーニングします。10 種類の衣料 70,000 点の衣服が含まれます。衣料品の各アイテムは 28×28 のグレースケール画像です。以下の例をご覧ください。
データセットに関連付けられたラベルは次のとおりです。
ラベル | Description |
0 | T シャツ・トップス |
1 | ズボン |
2 | プル |
3 | ドレス |
4 | Coat |
5 | サンダル |
6 | Shirt |
7 | スニーカー |
8 | 袋 |
9 | 足首ブーツ |
Fashion MNIST データは、tf.keras.datasets
API で使用できます。次のように読み込みます。
mnist = tf.keras.datasets.fashion_mnist
そのオブジェクトに対して load_data
を呼び出すと、トレーニング値とテスト値の 2 つのリストができ、それぞれが衣料品とそのラベルを表すグラフィックを表します。
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
これらの値はどのように表示されますか。表示するトレーニング画像とトレーニング ラベルを出力します。配列内のさまざまなインデックスをテストできます。
import matplotlib.pyplot as plt
plt.imshow(training_images[0])
print(training_labels[0])
print(training_images[0])
アイテム 0
のデータの出力は次のようになります。
すべての値が 0 ~ 255 の整数であることがわかります。ニューラル ネットワークのトレーニングでは、すべての値を 0 ~ 1 の範囲で簡単に扱うことができます。これは正規化と呼ばれます。幸いなことに、Python ではループさせることなく、簡単にリストを正規化できます。
training_images = training_images / 255.0
test_images = test_images / 255.0
また、インデックス 0 とは異なるブートである 42 を確認することもできます。
ここで、トレーニングとテストの 2 つのデータセットがあるのではないでしょうか。
これは、トレーニングに使用するデータと、まだ検出されていないデータのセットを使用して、値をどれだけ適切に分類できるかを確認するためのものです。結局、完成したモデルは、これまでに見たことのないデータで使えるはずです。また、個別のテストデータがないと、ネットワークを一般化することなく、トレーニング データをのみ記憶するリスクが生じます。
3. モデルの設計
次に、モデルを設計します。3 つのレイヤがあります。レイヤを 1 つずつ詳しく調べて、さまざまな種類のレイヤと、各パラメータで使用されるパラメータを調べます。
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
Sequential
は、ニューラル ネットワークのレイヤのシーケンスを定義します。Flatten
は、正方形を 1 次元のベクトルに変換します。Dense
は、ニューロンのレイヤを追加します。Activation
関数は、ニューロンの各層に何を行うか指示します。多くのオプションがありますが、ここではこれらを使用します。Relu
は実質的に、X が 0 より大きい場合は X を返し、それ以外の場合は 0 を返します。これは、ネットワーク内の次のレイヤに 0 以上の値のみを渡します。Softmax
は一連の値を取り、最も大きい値を選択します。たとえば、最後のレイヤの出力が [0.1, 0.1, 0.05, 0.1, 9.5, 0.1, 0.05, 0.05, 0.05] のような場合、大きい値で並べ替える必要がなくなり、[0,0,0,0,1,0,0,0,0] が返されます。
4. モデルのコンパイルとトレーニング
モデルが定義されたので、次はそれを構築します。まず、optimizer
関数と loss
関数を使用してモデルをコンパイルしてから、トレーニング データとラベルでモデルをトレーニングします。ここでの目標は、モデルがトレーニング データとトレーニング ラベルの関係性を理解できるようにすることです。後で、トレーニング データに類似したデータをモデルで確認し、そのデータがどのようなものになるかを予測する必要があります。
metrics=
をパラメータとして使用していることに注意してください。これにより、TensorFlow は予測結果と既知の回答(ラベル)を比較することでトレーニングの精度をレポートできます。
model.compile(optimizer = tf.keras.optimizers.Adam(),
loss = 'sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)
model.fit
を実行すると、損失と精度が表示されます。
Epoch 1/5 60000/60000 [=======] - 6s 101us/sample - loss: 0.4964 - acc: 0.8247 Epoch 2/5 60000/60000 [=======] - 5s 86us/sample - loss: 0.3720 - acc: 0.8656 Epoch 3/5 60000/60000 [=======] - 5s 85us/sample - loss: 0.3335 - acc: 0.8780 Epoch 4/5 60000/60000 [=======] - 6s 103us/sample - loss: 0.3134 - acc: 0.8844 Epoch 5/5 60000/60000 [=======] - 6s 94us/sample - loss: 0.2931 - acc: 0.8926
モデルのトレーニングが完了すると、最後のエポックの最後に精度の値が表示されます。0.8926 のようになります。これは、トレーニング データの分類におけるニューラル ネットワークの精度が約 89% であることを示しています。つまり、画像とラベルのパターン マッチングは 89% の確率で達成されました。あまり良くありませんが、5 エポックのトレーニングが済んでいて、トレーニングもすぐに終了してしまいました。
5. モデルをテストする
モデルが見たことのないデータに対してどのようにモデルを実行するか。そのため、テストセットが用意されています。model.evaluate
を呼び出して 2 つのセットを渡すと、それぞれの損失が報告されます。次のように入力します。
model.evaluate(test_images, test_labels)
出力は次のとおりです。
10000/10000 [=====] - 1s 56us/sample - loss: 0.3365 - acc: 0.8789 [0.33648381242752073, 0.8789]
この例では、精度は 0.8789 であり、約 88% の精度でした。(値が若干異なる場合があります)。
予想どおり、モデルは未知のデータに対して、トレーニングされたデータほど正確ではありません。TensorFlow について学ぶ中で、その改善方法を見つけることができます。
さらに詳しく調べるには、次のステップの演習をお試しください。
6. データ探索の演習
演習 1
この最初の演習では、次のコードを実行します。
classifications = model.predict(test_images)
print(classifications[0])
テスト画像ごとに分類セットが作成され、分類の最初のエントリが出力されます。実行した後の出力は、数値のリストです。なぜでしょう。なぜでしょうか?
print(test_labels[0])
を実行すると、9 を取得します。リストがこのように見える理由を理解するのに役立ちますか?
モデルの出力は 10 個の数字のリストです。これらの数値は、分類される値が対応するラベルである確率です。たとえば、リストの最初の値は衣服がクラス 0 で、次は衣類が 1 である確率です。確率を除いてすべて低い確率であることに注目してください。また、Softmax
のため、リスト内のすべての確率の合計は 1.0 になります。
リストとラベルは 0 ベースであるため、ラベル 9 の足首ブーツは 10 個のクラスのうち 10 番目のクラスになります。10 番目に高い値を持つリストは、ニューラル ネットワークが分類されたアイテムがアンクルブートである可能性が高いとニューラル ネットワークが予測したことを意味します。
演習 2
モデルのレイヤを確認します。512 個のニューロンを使用して、高密度レイヤのさまざまな値をテストします。
損失とトレーニング時間でどのような結果が得られますか。その理由をお聞かせください。
たとえば、ニューロンを 1,024 個に増やすには計算量の増大が必要となり、処理が遅くなります。この場合は、モデルが正確なので良い結果が得られます。つまり、多ければ良いというわけではありません。返品はすぐに減らせるという法則にぶつかる可能性があります。
演習 3
Flatten()
レイヤを削除した場合の影響その理由をお聞かせください。
データの形に関するエラーが表示されます。エラーの詳細は現在は曖昧に見えるかもしれませんが、ネットワークの最初のレイヤがデータと同じ形状であるという経験則が強調されます。現時点では、データは 28 x 28 の画像であり、28 のニューロンの 28 の層は実現不可能であるため、その 28、28 を 784 x 1 にフラット化する方が理にかなっています。
すべてのコードを記述するのではなく、先頭に Flatten()
レイヤを追加します。後で配列がモデルに読み込まれると、配列は自動的にフラット化されます。
演習 4
最後の(出力)レイヤについて考えてみましょう。なぜ 10 種類あるのですか?10 より多い金額だとどうなるでしょうか。
5 でネットワークをトレーニングしてみてください。予期しない値が見つかるとすぐにエラーが発生します。別の経験則として、最後のレイヤのニューロンの数は分類するクラスの数と一致する必要があります。この場合は、0 ~ 9 の数字なので 10 個あり、最終レイヤに 10 個のニューロンが必要です。
演習 5
ネットワークに追加のレイヤの影響を考慮してください。512 のレイヤと 10 のレイヤの間に別のレイヤを追加するとどうなりますか?
これは比較的単純なデータであるため、大きな影響はありません。より複雑なデータの場合、多くの場合、追加のレイヤが必要になります。
演習 6
トレーニング前にデータを正規化し、0 ~ 255 の値を 0 ~ 1 の値にしました。削除した場合、どのような影響がありますか?試すための完全なコードを以下に示します(データを正規化する 2 行はコメントアウトされています)。
どのような結果が得られると思いますか?Stack Overflow で回答があります。
import tensorflow as tf
print(tf.__version__)
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
#training_images=training_images/255.0
#test_images=test_images/255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
model.fit(training_images, training_labels, epochs=5)
model.evaluate(test_images, test_labels)
classifications = model.predict(test_images)
print(classifications[0])
print(test_labels[0])
7. コールバックを探す
先ほど、追加のエポックのトレーニングをした場合、損失が変化する可能性のある問題がありました。トレーニングが完了するまで少し時間がかかる場合があります。95% の精度など、目的の値に達したときにトレーニングを停止できればよいと思ったかもしれません。3 回のエポックの後にこの数値に到達した場合、エポックが多くなるまで待つことにした方がいいのはなぜでしょうか。
他のプログラムと同様、コールバックをご利用いただけます。実例を見る:
import tensorflow as tf
class myCallback(tf.keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs={}):
if(logs.get('accuracy')>0.95):
print("\nReached 95% accuracy so cancelling training!")
self.model.stop_training = True
callbacks = myCallback()
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images/255.0
test_images=test_images/255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5, callbacks=[callbacks])
8. 完了
初めてのコンピュータ ビジョン モデルの作成コンピュータ ビジョン モデルを拡張する方法については、畳み込みとプーリングの実行をご覧ください。