In [ ]:
#@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.
このチュートリアルでは、MNIST の数の分類をするための、シンプルな畳み込みニューラルネットワーク (CNN: Convolutional Neural Network) の学習について説明します。このシンプルなネットワークは MNIST テストセットにおいて、99%以上の精度を達成します。このチュートリアルでは、Keras Sequential APIを使用するため、ほんの数行のコードでモデルの作成と学習を行うことができます。
Note: GPU を使うことで CNN をより早く学習させることができます。もし、このノートブックを Colab で実行しているならば、編集 -> ノートブックの設定 -> ハードウェアアクセラレータ -> GPU から無料のGPUを有効にすることができます。
In [ ]:
!pip install tensorflow-gpu==2.0.0-rc1
import tensorflow as tf
from tensorflow.keras import datasets, layers, models
In [ ]:
(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()
train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))
# ピクセルの値を 0~1 の間に正規化
train_images, test_images = train_images / 255.0, test_images / 255.0
下記の6行のコードは、一般的なパターンで畳み込みの基礎部分を定義しています: Conv2D と MaxPooling2D レイヤーのスタック。
入力として、CNN はバッチサイズを無視して、shape (image_height, image_width, color_channels) のテンソルをとります。color channels について、MNIST は1つ (画像がグレースケールのため) の color channels がありますが、カラー画像には3つ (R, G, B) があります。この例では、MNIST 画像のフォーマットである shape (28, 28, 1) の入力を処理するように CNN を構成します。これを行うには、引数 input_shape
を最初のレイヤーに渡します。
In [ ]:
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
ここまでのモデルのアーキテクチャを表示してみましょう。
In [ ]:
model.summary()
上記より、すべての Conv2D と MaxPooling2D レイヤーの出力は shape (height, width, channels) の 3D テンソルであることがわかります。width と height の寸法は、ネットワークが深くなるにつれて縮小する傾向があります。各 Conv2D レイヤーの出力チャネルの数は、第一引数 (例: 32 または 64) によって制御されます。通常、width とheight が縮小すると、各 Conv2D レイヤーにさらに出力チャネルを追加する余裕が (計算上) できます。
In [ ]:
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
これが私たちのモデルの完全なアーキテクチャです。
In [ ]:
model.summary()
ご覧のとおり、2 つの Dense レイヤーを通過する前に、(3, 3, 64) の出力は shape (576) のベクターに平滑化されました。
In [ ]:
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=5)
In [ ]:
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
In [ ]:
print(test_acc)
ご覧のとおり、我々のシンプルな CNN は 99% 以上のテスト精度を達成しています。数行のコードにしては悪くありません!違うスタイルでの CNN の書き方 (Keras Subclassing API や GradientTape を使ったもの) についてはここを参照してください。