TensorFlow.org で実行 | Google Colabで実行 | GitHubでソースを表示 | ノートブックをダウンロード |
MNIST モデルをビルドする
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
2024-01-11 19:46:58.726279: E external/local_xla/xla/stream_executor/cuda/cuda_dnn.cc:9261] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered 2024-01-11 19:46:58.726330: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:607] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered 2024-01-11 19:46:58.727948: E external/local_xla/xla/stream_executor/cuda/cuda_blas.cc:1515] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered
Sequential モデルの使用が適している場合
Sequential
モデルは、各レイヤーに** 1 つの入力テンソルと 1 つの出力テンソルのみがあるレイヤーのプレーンスタック**に適しています。
概略的には、以下のSequential
モデルを参照してください。
# Define Sequential model with 3 layers
model = keras.Sequential(
[
layers.Dense(2, activation="relu", name="layer1"),
layers.Dense(3, activation="relu", name="layer2"),
layers.Dense(4, name="layer3"),
]
)
# Call model on a test input
x = tf.ones((3, 3))
y = model(x)
上記は次の関数と同じです。
# Create 3 layers
layer1 = layers.Dense(2, activation="relu", name="layer1")
layer2 = layers.Dense(3, activation="relu", name="layer2")
layer3 = layers.Dense(4, name="layer3")
# Call layers on a test input
x = tf.ones((3, 3))
y = layer3(layer2(layer1(x)))
以下の場合、Sequential モデルは適切ではありません。
- モデルに複数の入力または複数の出力がある場合
- レイヤーに複数の入力または複数の出力がある場合
- レイヤーの共有を行う必要がある場合
- 非線形トポロジーが必要な場合(残差を用いた接続、複数の分岐点をもつモデルなど)
Sequential モデルの作成
レイヤーのリストを Sequential コンストラクタに渡すことにより、Sequential モデルを作成できます。
model = keras.Sequential(
[
layers.Dense(2, activation="relu"),
layers.Dense(3, activation="relu"),
layers.Dense(4),
]
)
そのレイヤーには、layers
属性を介してアクセスできます。
model.layers
[<keras.src.layers.core.dense.Dense at 0x7f046032cd90>, <keras.src.layers.core.dense.Dense at 0x7f046032c910>, <keras.src.layers.core.dense.Dense at 0x7f05ac669940>]
また、add()
メソッドを使用して Sequential モデルを作成することもできます。
model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.add(layers.Dense(4))
また、レイヤーを削除するには、 pop()
メソッドが対応します。Sequential モデルは、レイヤーのリストのように動作します。
model.pop()
print(len(model.layers)) # 2
2
また、Sequential コンストラクタは、Keras のレイヤーやモデルと同様に、name
引数を受け入れます。これは、セマンティックに意味のある命名で TensorBoard グラフに注釈を付けるのに役立ちます。
model = keras.Sequential(name="my_sequential")
model.add(layers.Dense(2, activation="relu", name="layer1"))
model.add(layers.Dense(3, activation="relu", name="layer2"))
model.add(layers.Dense(4, name="layer3"))
事前に入力形状を指定
一般的に、Keras のすべてのレイヤーは、重みを作成できるようにするために、入力の形状を知る必要があります。このようなレイヤーを作成する場合、当初は重みがありません。
layer = layers.Dense(3)
layer.weights # Empty
[]
重みの形状は入力の形状に依存するため、入力時に最初に呼び出されたときに重みが作成されます。
# Call layer on a test input
x = tf.ones((1, 4))
y = layer(x)
layer.weights # Now it has weights, of shape (4, 3) and (3,)
[<tf.Variable 'dense_6/kernel:0' shape=(4, 3) dtype=float32, numpy= array([[ 0.634882 , 0.9207603 , 0.0239647 ], [-0.46164373, -0.35514814, -0.01446551], [ 0.04140419, -0.15481418, 0.5575298 ], [-0.25708675, 0.59739923, -0.04356736]], dtype=float32)>, <tf.Variable 'dense_6/bias:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>]
これは Sequential モデルでも同じです。入力形状なしで Sequential モデルをインスタンス化すると、重みがないために「構築」されません (model.weights
を呼び出すと、これを示すエラーが発生します)。重みは、モデルが最初に入力データを確認したときに作成されます。
model = keras.Sequential(
[
layers.Dense(2, activation="relu"),
layers.Dense(3, activation="relu"),
layers.Dense(4),
]
) # No weights at this stage!
# At this point, you can't do this:
# model.weights
# You also can't do this:
# model.summary()
# Call the model on a test input
x = tf.ones((1, 4))
y = model(x)
print("Number of weights after calling the model:", len(model.weights)) # 6
Number of weights after calling the model: 6
モデルが「構築」されたら、そのsummary()
メソッドを呼び出して、その内容を表示できます。
model.summary()
Model: "sequential_3" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_7 (Dense) (1, 2) 10 dense_8 (Dense) (1, 3) 9 dense_9 (Dense) (1, 4) 16 ================================================================= Total params: 35 (140.00 Byte) Trainable params: 35 (140.00 Byte) Non-trainable params: 0 (0.00 Byte) _________________________________________________________________
ただし、Sequential モデルを段階的に構築する場合、その時点の出力形状を含め、それまでのモデルの概要を表示できると非常に便利です。 この場合、モデルにInput
オブジェクトを渡してモデルを開始し、最初から入力形状がわかるようにする必要があります。
model = keras.Sequential()
model.add(keras.Input(shape=(4,)))
model.add(layers.Dense(2, activation="relu"))
model.summary()
Model: "sequential_4" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_10 (Dense) (None, 2) 10 ================================================================= Total params: 10 (40.00 Byte) Trainable params: 10 (40.00 Byte) Non-trainable params: 0 (0.00 Byte) _________________________________________________________________
Input
オブジェクトはレイヤーではないため、model.layers
の一部として表示されないことに注意してください。
model.layers
[<keras.src.layers.core.dense.Dense at 0x7f04602dd130>]
簡単な代替手段として、最初のレイヤーにinput_shape
引数を渡すこともできます。
model = keras.Sequential()
model.add(layers.Dense(2, activation="relu", input_shape=(4,)))
model.summary()
Model: "sequential_5" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_11 (Dense) (None, 2) 10 ================================================================= Total params: 10 (40.00 Byte) Trainable params: 10 (40.00 Byte) Non-trainable params: 0 (0.00 Byte) _________________________________________________________________
このような事前定義された入力形状で構築されたモデルは、常に (データが確認される前でも) 重みを持ち、常に定義された出力形状をもっています。
一般的に、Sequential モデルの入力形状がわかっている場合は、常に事前に指定しておくことをお勧めします。
一般的なデバッグワークフロー:add()
+ summary()
新しい Sequential アーキテクチャを構築する場合、add()
を使用して段階的にレイヤーを積み重ね、モデルの概要を頻繁に出力することをお勧めします。これにより、Conv2D
レイヤーとMaxPooling2D
レイヤーのスタックが画像特徴量マップをどのようにダウンサンプリングしているかを監視できます。
model = keras.Sequential()
model.add(keras.Input(shape=(250, 250, 3))) # 250x250 RGB images
model.add(layers.Conv2D(32, 5, strides=2, activation="relu"))
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.MaxPooling2D(3))
# Can you guess what the current output shape is at this point? Probably not.
# Let's just print it:
model.summary()
# The answer was: (40, 40, 32), so we can keep downsampling...
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.MaxPooling2D(3))
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.MaxPooling2D(2))
# And now?
model.summary()
# Now that we have 4x4 feature maps, time to apply global max pooling.
model.add(layers.GlobalMaxPooling2D())
# Finally, we add a classification layer.
model.add(layers.Dense(10))
Model: "sequential_6" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 123, 123, 32) 2432 conv2d_1 (Conv2D) (None, 121, 121, 32) 9248 max_pooling2d (MaxPooling2 (None, 40, 40, 32) 0 D) ================================================================= Total params: 11680 (45.62 KB) Trainable params: 11680 (45.62 KB) Non-trainable params: 0 (0.00 Byte) _________________________________________________________________ Model: "sequential_6" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 123, 123, 32) 2432 conv2d_1 (Conv2D) (None, 121, 121, 32) 9248 max_pooling2d (MaxPooling2 (None, 40, 40, 32) 0 D) conv2d_2 (Conv2D) (None, 38, 38, 32) 9248 conv2d_3 (Conv2D) (None, 36, 36, 32) 9248 max_pooling2d_1 (MaxPoolin (None, 12, 12, 32) 0 g2D) conv2d_4 (Conv2D) (None, 10, 10, 32) 9248 conv2d_5 (Conv2D) (None, 8, 8, 32) 9248 max_pooling2d_2 (MaxPoolin (None, 4, 4, 32) 0 g2D) ================================================================= Total params: 48672 (190.12 KB) Trainable params: 48672 (190.12 KB) Non-trainable params: 0 (0.00 Byte) _________________________________________________________________
これは、非常に実用的なワークフローです。
モデルの準備ができたら
モデルアーキテクチャの準備ができたら、以下を行います。
- モデルをトレーニング、評価し、推論を実行します。「トレーニングと組み込みループを使用した評価のガイド」をご覧ください。
- モデルをディスクに保存して復元します。「シリアル化と保存のガイド」をご覧ください。
- 複数の GPU を活用してモデルを迅速にトレーニングします。「マルチ GPU と分散トレーニングのガイド」をご覧ください。
Sequential モデルによる特徴量の抽出
Sequential モデルが構築されると、Functional API モデルのように動作します。つまり、すべてのレイヤーにinput
およびoutput
属性があります。これらの属性を使用すると、Sequential モデルのすべての中間層の出力を抽出するモデルを迅速に作成したりできます。
initial_model = keras.Sequential(
[
keras.Input(shape=(250, 250, 3)),
layers.Conv2D(32, 5, strides=2, activation="relu"),
layers.Conv2D(32, 3, activation="relu"),
layers.Conv2D(32, 3, activation="relu"),
]
)
feature_extractor = keras.Model(
inputs=initial_model.inputs,
outputs=[layer.output for layer in initial_model.layers],
)
# Call feature extractor on test input.
x = tf.ones((1, 250, 250, 3))
features = feature_extractor(x)
以下の例では、1 つのレイヤーからのみ特徴量を抽出します。
initial_model = keras.Sequential(
[
keras.Input(shape=(250, 250, 3)),
layers.Conv2D(32, 5, strides=2, activation="relu"),
layers.Conv2D(32, 3, activation="relu", name="my_intermediate_layer"),
layers.Conv2D(32, 3, activation="relu"),
]
)
feature_extractor = keras.Model(
inputs=initial_model.inputs,
outputs=initial_model.get_layer(name="my_intermediate_layer").output,
)
# Call feature extractor on test input.
x = tf.ones((1, 250, 250, 3))
features = feature_extractor(x)
Sequential モデルによる転移学習
転移学習では、モデルの最下層を凍結し、最上層のみをトレーニングします。転移学習の詳細については、転移学習のガイドを参照してください。
以下は、Sequential モデルを含む 2 つの一般的な転移学習の例です。
まず、Sequential モデルで、最後のレイヤーを除くすべてのレイヤーを凍結するとします。この場合、model.layers
を繰り返し処理し、最後のレイヤーを除く各レイヤーに layer.trainable = False
を設定します。 以下に例を示します。
model = keras.Sequential([
keras.Input(shape=(784)),
layers.Dense(32, activation='relu'),
layers.Dense(32, activation='relu'),
layers.Dense(32, activation='relu'),
layers.Dense(10),
])
# Presumably you would want to first load pre-trained weights.
model.load_weights(...)
# Freeze all layers except the last one.
for layer in model.layers[:-1]:
layer.trainable = False
# Recompile and train (this will only update the weights of the last layer).
model.compile(...)
model.fit(...)
もう 1 つの一般的な例は、Sequential モデルを使用して、事前にトレーニングされたモデルといくつかの新しく初期化された分類レイヤーをスタックすることです。以下に例を示します。
# Load a convolutional base with pre-trained weights
base_model = keras.applications.Xception(
weights='imagenet',
include_top=False,
pooling='avg')
# Freeze the base model
base_model.trainable = False
# Use a Sequential model to add a trainable classifier on top
model = keras.Sequential([
base_model,
layers.Dense(1000),
])
# Compile & train
model.compile(...)
model.fit(...)
転移学習を行う場合、おそらくこれら 2 つのパターンを頻繁に使用されていることに気付くでしょう。
Sequential モデルについての説明は以上です。
Keras でのモデル構築の詳細については、以下を参照してください。