このページは Cloud Translation API によって翻訳されました。
Switch to English

シーケンシャルモデル

TensorFlow.orgで表示 GoogleColabで実行 GitHubでソースを表示ノートブックをダウンロード

セットアップ

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

シーケンシャルモデルを使用する場合

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モデルを作成できます。

model = keras.Sequential(
    [
        layers.Dense(2, activation="relu"),
        layers.Dense(3, activation="relu"),
        layers.Dense(4),
    ]
)

そのレイヤーには、 layers属性を介してアクセスできます。

model.layers
[<tensorflow.python.keras.layers.core.Dense at 0x7f7d1d5c7898>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f7d2f6e0a20>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f7d16beb9b0>]

add()メソッドを使用してシーケンシャルモデルを段階的に作成することもできます。

model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.add(layers.Dense(4))

レイヤーを削除するための対応するpop()メソッドもあることに注意してください。シーケンシャルモデルは、レイヤーのリストと非常によく似た動作をします。

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.06262648,  0.36915624, -0.27826005],
        [-0.6703571 , -0.03467071,  0.80370367],
        [-0.00725174,  0.19120002,  0.34244013],
        [-0.20762473, -0.31104177, -0.26624495]], dtype=float32)>,
 <tf.Variable 'dense_6/bias:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>]

当然、これはシーケンシャルモデルにも当てはまります。入力シェイプなしでシーケンシャルモデルをインスタンス化すると、「ビルド」されません。ウェイトがありません( 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
Trainable params: 35
Non-trainable params: 0
_________________________________________________________________

ただし、シーケンシャルモデルを段階的に構築する場合は、現在の出力形状を含む、これまでのモデルの概要を表示できると非常に便利です。この場合、 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
Trainable params: 10
Non-trainable params: 0
_________________________________________________________________

Inputオブジェクトはレイヤーではないため、 model.layers一部として表示されないことに注意してください。

model.layers
[<tensorflow.python.keras.layers.core.Dense at 0x7f7d16b870f0>]

簡単な代替方法は、 input_shape引数を最初のレイヤーに渡すこと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
Trainable params: 10
Non-trainable params: 0
_________________________________________________________________

このような事前定義された入力形状で構築されたモデルには、常に重みがあり(データが表示される前であっても)、常に定義された出力形状があります。

一般に、シーケンシャルモデルの入力形状がわかっている場合は、それを事前に指定しておくことをお勧めします。

一般的なデバッグワークフロー: add() + summary()

新しいシーケンシャルアーキテクチャを構築するときは、 add()を使用してレイヤーを段階的にスタックしadd()モデルの概要を頻繁に出力add()と便利です。例えば、これは、スタックどのように監視することができますConv2DMaxPooling2D層は画像特徴マップをダウンサンプリングされています。

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 (MaxPooling2D) (None, 40, 40, 32)        0         
=================================================================
Total params: 11,680
Trainable params: 11,680
Non-trainable params: 0
_________________________________________________________________
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 (MaxPooling2D) (None, 40, 40, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 38, 38, 32)        9248      
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 36, 36, 32)        9248      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 12, 12, 32)        0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 10, 10, 32)        9248      
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 8, 8, 32)          9248      
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 4, 4, 32)          0         
=================================================================
Total params: 48,672
Trainable params: 48,672
Non-trainable params: 0
_________________________________________________________________

とても実用的ですよね?

モデルができたらどうするか

モデルアーキテクチャの準備ができたら、次のことを行います。

シーケンシャルモデルによる特徴抽出

シーケンシャルモデルが構築されると、それは機能APIモデルのように動作します。これは、すべてのレイヤーにinput属性とoutput属性があることを意味します。これらの属性は、シーケンシャルモデルのすべての中間レイヤーの出力を抽出するモデルをすばやく作成するなど、きちんとしたことを行うために使用できます。

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)

シーケンシャルモデルによる転移学習

転移学習は、モデルの最下層を凍結し、最上層のみをトレーニングすることで構成されます。慣れていない場合は、学習を移行するためのガイドを必ずお読みください。

これは、シーケンシャルモデルを含む2つの一般的な転移学習の青写真です。

まず、シーケンシャルモデルがあり、最後のレイヤーを除くすべてのレイヤーをフリーズするとします。この場合、 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つの一般的な青写真は、シーケンシャルモデルを使用して、事前にトレーニングされたモデルといくつかの新しく初期化された分類レイヤーをスタックすることです。このような:

# 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つのパターンを頻繁に使用していることに気付くでしょう。

シーケンシャルモデルについて知っておく必要があるのはこれだけです。

Kerasでモデルを構築する方法の詳細については、以下を参照してください。