ホーム » Keras » TensorFlow 2.0 : 上級 Tutorials : カスタマイズ :- カスタム層

TensorFlow 2.0 : 上級 Tutorials : カスタマイズ :- カスタム層

TensorFlow 2.0 : 上級 Tutorials : カスタマイズ :- カスタム層 (翻訳/解説)

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

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

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

 

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

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

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

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

 

カスタマイズ :- カスタム層

ニューラルネットワークを構築するために tf.keras を高位 API として使用することを推奨します。とは言うものの、殆どの TensorFlow API は eagar execution とともに利用可能です。

from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf

 

層: 有用な演算の一般的なセット

機械学習モデルのためのコードを書く際の時間の殆どで個々の演算と個々の変数の操作よりも抽象度の高いレベルで操作することを望むでしょう。

多くの機械学習モデルは比較的単純な層の組み合わせとスタックとして表現可能で、そして TensorFlow は多くの一般的な層のセットに加えて貴方自身のアプリケーション固有の層をスクラッチからあるいは既存の層の組み合わせとして書くための容易な方法の両者を提供します。

TensorFlow は tf.keras パッケージで完全な Keras API を含み、そして Keras 層は貴方自身のモデルを構築するとき非常に有用です。

# In the tf.keras.layers package, layers are objects. To construct a layer,
# simply construct the object. Most layers take as a first argument the number
# of output dimensions / channels.
layer = tf.keras.layers.Dense(100)
# The number of input dimensions is often unnecessary, as it can be inferred
# the first time the layer is used, but it can be provided if you want to
# specify it manually, which is useful in some complex models.
layer = tf.keras.layers.Dense(10, input_shape=(None, 5))

事前の既存の層の完全なリストは ドキュメント で見ることができます。それは Dense (完全結合層), Conv2D, LSTM, BatchNormalization, Dropout そして多くのその他を含みます。

# To use a layer, simply call it.
layer(tf.zeros([10, 5]))
<tf.Tensor: id=29, shape=(10, 10), dtype=float32, numpy=
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)>
# Layers have many useful methods. For example, you can inspect all variables
# in a layer using `layer.variables` and trainable variables using
# `layer.trainable_variables`. In this case a fully-connected layer
# will have variables for weights and biases.
layer.variables
[<tf.Variable 'dense_1/kernel:0' shape=(5, 10) dtype=float32, numpy=
 array([[ 0.51294535,  0.39046746,  0.5169707 , -0.50724113,  0.20505047,
          0.3687951 ,  0.31146628,  0.14512777,  0.17081863,  0.46950692],
        [-0.41236007, -0.44020796, -0.18911147,  0.4183591 ,  0.16210389,
          0.02787369, -0.3171257 ,  0.04602218, -0.33665502, -0.31346938],
        [ 0.18812859,  0.19958586,  0.13240266, -0.34834057,  0.22317702,
         -0.4768321 , -0.3115183 ,  0.31428623, -0.25364092, -0.21017173],
        [ 0.16382337, -0.6286906 ,  0.18086797, -0.08836156,  0.2523052 ,
         -0.41885728,  0.26864457,  0.44391626, -0.07597739, -0.5618839 ],
        [-0.33893436,  0.31044286, -0.10406214,  0.04485041,  0.1952014 ,
          0.38055784, -0.45492256,  0.3415655 ,  0.39259988, -0.42731035]],
       dtype=float32)>,
 <tf.Variable 'dense_1/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>]
# The variables are also accessible through nice accessors
layer.kernel, layer.bias
(<tf.Variable 'dense_1/kernel:0' shape=(5, 10) dtype=float32, numpy=
 array([[ 0.51294535,  0.39046746,  0.5169707 , -0.50724113,  0.20505047,
          0.3687951 ,  0.31146628,  0.14512777,  0.17081863,  0.46950692],
        [-0.41236007, -0.44020796, -0.18911147,  0.4183591 ,  0.16210389,
          0.02787369, -0.3171257 ,  0.04602218, -0.33665502, -0.31346938],
        [ 0.18812859,  0.19958586,  0.13240266, -0.34834057,  0.22317702,
         -0.4768321 , -0.3115183 ,  0.31428623, -0.25364092, -0.21017173],
        [ 0.16382337, -0.6286906 ,  0.18086797, -0.08836156,  0.2523052 ,
         -0.41885728,  0.26864457,  0.44391626, -0.07597739, -0.5618839 ],
        [-0.33893436,  0.31044286, -0.10406214,  0.04485041,  0.1952014 ,
          0.38055784, -0.45492256,  0.3415655 ,  0.39259988, -0.42731035]],
       dtype=float32)>,
 <tf.Variable 'dense_1/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>)

 

カスタム層を実装する

貴方自身の層を実装する最善の方法は tf.keras.Layer クラスを拡張して以下を実装することです : * __init__ , そこでは総ての入力独立な初期化を行なうことができます * build, そこでは入力 tensor の shape を知って初期化の残りを行なうことができます * call, そこでは forward 計算を行ないます。

貴方の変数を作成するために build が呼び出されるまで待たなくても構わないことに注意してください、それらを __init__ で作成することもできます。けれども、それらを build で作成する優位点は (層がその上で操作する) 入力の shape を基にそれが遅延変数作成を可能にすることです。他方、__init__ で変数を作成することは変数を作成するために必要な shape が明示的に指定される必要があることを意味します。

class MyDenseLayer(tf.keras.layers.Layer):
  def __init__(self, num_outputs):
    super(MyDenseLayer, self).__init__()
    self.num_outputs = num_outputs

  def build(self, input_shape):
    self.kernel = self.add_variable("kernel",
                                    shape=[int(input_shape[-1]),
                                           self.num_outputs])

  def call(self, input):
    return tf.matmul(input, self.kernel)

layer = MyDenseLayer(10)
_ = layer(tf.zeros([10, 5])) # Calling the layer `.builds` it.
WARNING:tensorflow:From :9: Layer.add_variable (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.
Instructions for updating:
Please use `layer.add_weight` method instead.
print([var.name for var in layer.trainable_variables])
['my_dense_layer/kernel:0']

全体的なコードが可能なときには標準的な層を使用すれば、他の読み手は標準的な層の動作に馴染みがありますので、読みやすく維持しやすくなります。tf.keras.layers にない層を使用することを望む場合には、github issue を提出することを考えるか、更に良いことは pull リクエストを送ることです!

 

モデル: 層を構成する

機械学習モデルの多くの興味深い層-like なものは既存の層を組み合わせることにより実装されます。例えば、resnet の各残差ブロックは畳み込み、バッチ正規化とショートカットの組み合わせです。層は他の層の内部にネストできます。

次のようなモデル・メソッド : Model.fit, Model.evaluateModel.save を必要とするとき典型的には tf.keras.Model から継承します (詳細については Custom Keras layers and models 参照)。

(keras.layers.Layer の代わりに) keras.Model により提供される一つの他の特徴は変数を追跡することに加えて、keras.Model はまたその内部層を追跡し、それを調査することを容易にします。

例えばここに ResNet ブロックがあります :

class ResnetIdentityBlock(tf.keras.Model):
  def __init__(self, kernel_size, filters):
    super(ResnetIdentityBlock, self).__init__(name='')
    filters1, filters2, filters3 = filters

    self.conv2a = tf.keras.layers.Conv2D(filters1, (1, 1))
    self.bn2a = tf.keras.layers.BatchNormalization()

    self.conv2b = tf.keras.layers.Conv2D(filters2, kernel_size, padding='same')
    self.bn2b = tf.keras.layers.BatchNormalization()

    self.conv2c = tf.keras.layers.Conv2D(filters3, (1, 1))
    self.bn2c = tf.keras.layers.BatchNormalization()

  def call(self, input_tensor, training=False):
    x = self.conv2a(input_tensor)
    x = self.bn2a(x, training=training)
    x = tf.nn.relu(x)

    x = self.conv2b(x)
    x = self.bn2b(x, training=training)
    x = tf.nn.relu(x)

    x = self.conv2c(x)
    x = self.bn2c(x, training=training)

    x += input_tensor
    return tf.nn.relu(x)


block = ResnetIdentityBlock(1, [1, 2, 3])
_ = block(tf.zeros([1, 2, 3, 3])) 
block.layers
[<tensorflow.python.keras.layers.convolutional.Conv2D at 0x7fd04c20a780>,
 <tensorflow.python.keras.layers.normalization_v2.BatchNormalization at 0x7fd04c20ac18>,
 <tensorflow.python.keras.layers.convolutional.Conv2D at 0x7fd04c20af60>,
 <tensorflow.python.keras.layers.normalization_v2.BatchNormalization at 0x7fd04c20e470>,
 <tensorflow.python.keras.layers.convolutional.Conv2D at 0x7fd04c20e7b8>,
 <tensorflow.python.keras.layers.normalization_v2.BatchNormalization at 0x7fd04c20ec88>]
len(block.variables)
18
block.summary()
Model: "resnet_identity_block"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              multiple                  4         
_________________________________________________________________
batch_normalization (BatchNo multiple                  4         
_________________________________________________________________
conv2d_1 (Conv2D)            multiple                  4         
_________________________________________________________________
batch_normalization_1 (Batch multiple                  8         
_________________________________________________________________
conv2d_2 (Conv2D)            multiple                  9         
_________________________________________________________________
batch_normalization_2 (Batch multiple                  12        
=================================================================
Total params: 41
Trainable params: 29
Non-trainable params: 12
_________________________________________________________________

けれども大抵の時は、多くの層を構成するモデルは単純に他の (層の) 後に一つの層を呼び出します。これは tf.keras.Sequential を使用して非常に小さいなコードから成されます。

my_seq = tf.keras.Sequential([tf.keras.layers.Conv2D(1, (1, 1),
                                                    input_shape=(
                                                        None, None, 3)),
                             tf.keras.layers.BatchNormalization(),
                             tf.keras.layers.Conv2D(2, 1,
                                                    padding='same'),
                             tf.keras.layers.BatchNormalization(),
                             tf.keras.layers.Conv2D(3, (1, 1)),
                             tf.keras.layers.BatchNormalization()])
my_seq(tf.zeros([1, 2, 3, 3]))
<tf.Tensor: id=744, shape=(1, 2, 3, 3), dtype=float32, numpy=
array([[[[0., 0., 0.],
         [0., 0., 0.],
         [0., 0., 0.]],

        [[0., 0., 0.],
         [0., 0., 0.],
         [0., 0., 0.]]]], dtype=float32)>
my_seq.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_3 (Conv2D)            (None, None, None, 1)     4         
_________________________________________________________________
batch_normalization_3 (Batch (None, None, None, 1)     4         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, None, None, 2)     4         
_________________________________________________________________
batch_normalization_4 (Batch (None, None, None, 2)     8         
_________________________________________________________________
conv2d_5 (Conv2D)            (None, None, None, 3)     9         
_________________________________________________________________
batch_normalization_5 (Batch (None, None, None, 3)     12        
=================================================================
Total params: 41
Trainable params: 29
Non-trainable params: 12
_________________________________________________________________
 

以上






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