ホーム » Keras » TensorFlow 2.4 : ガイド : Keras – シーケンシャル・モデル

TensorFlow 2.4 : ガイド : Keras – シーケンシャル・モデル

TensorFlow 2.4 : ガイド : Keras – シーケンシャル・モデル (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 01/09/2021

* 本ページは、TensorFlow org サイトの Guide – Keras の以下のページを翻訳した上で
適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

無料セミナー実施中 クラスキャット主催 人工知能 & ビジネス Web セミナー

人工知能とビジネスをテーマにウェビナー (WEB セミナー) を定期的に開催しています。スケジュールは弊社 公式 Web サイト でご確認頂けます。
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。
クラスキャットは人工知能・テレワークに関する各種サービスを提供しております :

人工知能研究開発支援 人工知能研修サービス テレワーク & オンライン授業を支援
PoC(概念実証)を失敗させないための支援 (本支援はセミナーに参加しアンケートに回答した方を対象としています。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/
Facebook: https://www.facebook.com/ClassCatJP/

 

ガイド : Keras – シーケンシャル・モデル

セットアップ

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

 

いつシーケンシャル・モデルを使用するべきか

シーケンシャル・モデルは 層の平易な (= plain) スタック のために適切です、そこでは各層は 正確に 1 つの入力 tensor と 1 つの出力 tensor を持ちます。

図式的には (= schematically)、次のシーケンシャル・モデルは :

# 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)))

シーケンシャル・モデルは以下の時には 適切ではありません :

  • モデルが複数の入力か複数の出力を持つ。
  • 層のいずれかが複数の入力か複数の出力を持つ。
  • 層共有を行なうことを必要とする。
  • 非線形トポロジーを望む (e.g. 残差接続、マルチ分岐 (= multi-branch) モデル)。

 

シーケンシャル・モデルを作成する

層のリストを Sequential コンストラクタに渡すことによりシーケンシャル・モデルを作成できます :

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

その層は層属性を通してアクセス可能です :

model.layers
[<tensorflow.python.keras.layers.core.Dense at 0x7f0b1d3b9898>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f0b1d3da278>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f0adf113978>]

add() メソッドを通してシーケンシャル・モデルを追加的に (= incrementally) 作成することもできます :

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

ちょうど Keras の任意の層やモデルのように、Sequential コンストラクタは 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"))

 

入力 shape を前もって指定する

一般に、Keras の総ての層はそれらの重みを作成できるように入力の shape を知る必要があります。そのためこのように層を作成するとき、初期には、それは重みを持ちません :

layer = layers.Dense(3)
layer.weights  # Empty
[]

それは最初に入力上で呼び出されたときその重みを作成します、何故ならば重みの shape は入力の shape に依拠するからです :

# 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.45486438,  0.38934755, -0.7173875 ],
        [-0.6566295 , -0.10407549,  0.5983287 ],
        [-0.05668062,  0.49586964,  0.66319096],
        [-0.85785586,  0.09025455,  0.5556363 ]], dtype=float32)>,
 <tf.Variable 'dense_6/bias:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>]

自然に、これはまたシーケンシャル・モデルにも適用されます。入力 shape なしに 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_6"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_16 (Dense)             (1, 2)                    10        
_________________________________________________________________
dense_17 (Dense)             (1, 3)                    9         
_________________________________________________________________
dense_18 (Dense)             (1, 4)                    16        
=================================================================
Total params: 35
Trainable params: 35
Non-trainable params: 0

けれども、Sequential モデルを追加的に構築するとき、現在の出力 shape も含めてそこまでのモデルの要約を表示できることは非常に有用である可能性があります。この場合、Input オブジェクトをモデルに渡すことにより最初から入力 shape を知るようにモデルを始めるべきです :

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

model.summary()
Model: "sequential_7"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_19 (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 0x7f446d8d1860>]

単純な代替は最初の層に 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
_________________________________________________________________

このように事前定義された入力 shape で構築されたモデルは (どのようなデータを見る前でさえも) 常に重みを持ちそして常に定義された出力 shape を持ちます。

一般には、シーケンシャル・モデルの入力 shape を (それが何か知るのであれば) 常に前もって指定することが推奨されるベストプラクティスです。

 

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

新しいシーケンシャル・アーキテクチャを構築するとき、add() で層を追加的にスタックして頻繁にモデル要約 (= summary) をプリントすることは有用です。例えば、これは 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 (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

Very practical, right?

 

ひとたびモデルを得たら何をするべきか

ひとたび貴方のモデル・アーキテクチャが準備できれば、以下を望むでしょう :

 

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

ひとたびシーケンシャル・モデルが構築されたならば、それは Functional API モデル のように動作します。これは総ての層が入力と出力属性を持つことを意味します。これらの属性はシーケンシャル・モデルの総ての中間層の出力を抽出するモデルを素早く作成するような、巧妙な (= neat) ことを行なうために利用できます :

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 つの一般的な転移学習ブループリント (設計図) があります。

最初に、貴方はシーケンシャル・モデルを持ち、そして総ての層を最後の 1 つを除いて凍結することを望むとします。この場合、model.layers に渡り単純に反復して (最後の 1 つを除いて) 各層で 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(...)

もう一つの一般的なブループリントは事前訓練モデルと幾つかの新たに初期化された分類層をスタックするためにシーケンシャル・モデルを利用することです。このようにです :

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

That’s about all you need to know about Sequential models!

 

以上



AI導入支援 #2 ウェビナー

スモールスタートを可能としたAI導入支援   Vol.2
[無料 WEB セミナー] [詳細]
「画像認識 AI PoC スターターパック」の紹介
既に AI 技術を実ビジネスで活用し、成果を上げている日本企業も多く存在しており、競争優位なビジネスを展開しております。
しかしながら AI を導入したくとも PoC (概念実証) だけでも高額な費用がかかり取組めていない企業も少なくないようです。A I導入時には欠かせない PoC を手軽にしかも短期間で認知度を確認可能とするサービの紹介と共に、AI 技術の特性と具体的な導入プロセスに加え運用時のポイントについても解説いたします。
日時:2021年10月13日(水)
会場:WEBセミナー
共催:クラスキャット、日本FLOW(株)
後援:働き方改革推進コンソーシアム
参加費: 無料 (事前登録制)
人工知能開発支援
◆ クラスキャットは 人工知能研究開発支援 サービスを提供しています :
  • テクニカルコンサルティングサービス
  • 実証実験 (プロトタイプ構築)
  • アプリケーションへの実装
  • 人工知能研修サービス
◆ お問合せ先 ◆
(株)クラスキャット
セールス・インフォメーション
E-Mail:sales-info@classcat.com