見出し画像

モバイルアプリエンジニアのためのTensorFlow 2.x 入門 (6) - モデルの情報を得る

モバイルアプリエンジニアの方がTensorFlowに入門するための連載記事です。

今回はモデルの構造を可視化したり、中間層の値を確認する方法について説明します。

機械学習におけるモバイルアプリエンジニアの役割は、主に専門家が作ったモデルをアプリで動かすことだと思います。

アプリで動かせる形に変換するためには、モデルがどのような入出力で、どのような構造をしているのかといった情報を把握する必要があります。

同じ会社内でモデルを作っている場合は、仕様の情報としてもらえばいいのですが、どこかで見つけてきたモデルを使う場合は、外からそれを解析する必要があります。

ということで、今回はモデルを解析するためのツールを紹介したいと思います。

この入門は、Google Colaboratoryを使います。使い方は第1回にありますので、そちらをご覧下さい。

過去の記事はこちらからご覧下さい。

モデルの概要を得る方法

モデルの概要を得る簡単な方法は、summaryメソッドを使うことです。
既存モデルのMobileNetV2をダウンロードしてsummaryを出してみます。

import tensorflow as tf

# MobileNetV2をダウンロードする
mobile_net = tf.keras.applications.MobileNetV2(input_shape=(192, 192, 3), include_top=False)
mobile_net.summary()

# 出力結果
# Model: "mobilenetv2_1.00_192"
# __________________________________________________________________________________________________
# Layer (type)                    Output Shape         Param #     Connected to                     
# ==================================================================================================
# input_2 (InputLayer)            [(None, 192, 192, 3) 0                                            
# __________________________________________________________________________________________________
# Conv1 (Conv2D)                  (None, 96, 96, 32)   864         input_2[0][0]                    
# __________________________________________________________________________________________________
# bn_Conv1 (BatchNormalization)   (None, 96, 96, 32)   128         Conv1[0][0]                      
# __________________________________________________________________________________________________
# Conv1_relu (ReLU)               (None, 96, 96, 32)   0           bn_Conv1[0][0]                   
・
・(略)
・
# Conv_1 (Conv2D)                 (None, 6, 6, 1280)   409600      block_16_project_BN[0][0]        
# __________________________________________________________________________________________________
# Conv_1_bn (BatchNormalization)  (None, 6, 6, 1280)   5120        Conv_1[0][0]                     
# __________________________________________________________________________________________________
# out_relu (ReLU)                 (None, 6, 6, 1280)   0           Conv_1_bn[0][0]                  
# ==================================================================================================
# Total params: 2,257,984
# Trainable params: 2,223,872
# Non-trainable params: 34,112
# __________________________________________________________________________________________________

各層のShapeなどはこれで確認することが出来ますね。

モデルを図で表現する

モデルを図で表現するには、keras.utils.plot_modelを使います。

from tensorflow import keras
keras.utils.plot_model(mobile_net,  show_shapes=True)

こんな感じで出力されます。あまりにも巨大だったので冒頭部分以外は省略しています。

画像1

途中で統合したり分岐したりしているところも図だとわかりやすいですね。

画像2

TensorBoardでモデルの情報を図にする

TensorBoardを用いるとモデルの情報を図にしたり、トレーニングの状況をグラフにしたりと、さまざまな可視化をすることができます。

ここではモデルのグラフを手早く図にする方法を紹介します。

TensorBoardでグラフを表示する簡単な方法は、トレーニングするときに、fitメソッドにログを記録するコールバックを渡すことです。

ただ、ここではモデルのグラフを得たいだけで、トレーニングをしたいわけではないので、トレーニングのためのデータセットは手短に用意できるようにダミーのデータを作ります。

import numpy as np

# モデルへの入力のshapeを表示する
mobile_net.input.shape
# 出力結果
# TensorShape([None, 192, 192, 3])

# 入力のshapeにあわせたダミーのデータを作る
inputs = np.zeros(shape=(1,192,192,3))

# モデルの出力のshapeを表示する
mobile_net.output.shape
# 出力結果
# TensorShape([None, 192, 192, 3])
# TensorShape([None, 6, 6, 1280])

# 出力のshapeにあわせたダミーのデータを作る
outputs = np.zeros(shape=(1,6,6,1280))

# モデルをコンパイルする
mobile_net.compile(optimizer=tf.keras.optimizers.Adam(), 
             loss='categorical_crossentropy',
             metrics=["accuracy"])

# tensorboardが利用するログを記録するためのコールバックを作成する
tb_cb = keras.callbacks.TensorBoard(log_dir='./logs', histogram_freq=0, write_graph=True, write_grads=False, write_images=False, embeddings_freq=0, embeddings_layer_names=None, embeddings_metadata=None)

# モデルをトレーニングする
# ここではグラフを表示したいだけなので、epochsは1にしている
mobile_net.fit(inputs, outputs, batch_size=1, epochs=1, callbacks=[tb_cb])

# TensorBoardを有効にする
%load_ext tensorboard

# TensorBoardを起動する
%tensorboard --logdir ./logs

TensorBoardが起動したらGRAHSを選択して下さい。

画像4

こんな感じでグラフが出力されます。

画像3

一つ一つの要素をタップすると、入出力のshapeが確認できるようになっています。

モデルの入出力の情報を得る

モデルの全体の入出力についての情報を確認する方法を紹介します。

といっても先程のコードの中に出てきています。inputメソッド、outputメソッドを使うだけです。

# モデルへの入力を確認する
mobile_net.input
# 出力結果
# <KerasTensor: shape=(None, 192, 192, 3) dtype=float32 (created by layer 'input_2')>

# モデルの出力を確認する
mobile_net.output
# 出力結果
# <KerasTensor: shape=(None, 6, 6, 1280) dtype=float32 (created by layer 'out_relu')>

モデルの中間情報の情報を得る

モデルの中間レイヤーにある情報を確認する方法です。

まずは、layersで中間層の情報をすべて表示してみます。

# レイヤーの情報を得る
mobile_net.layers
# 出力結果
# [<tensorflow.python.keras.engine.input_layer.InputLayer at 0x7f1eb63877b8>,
#  <tensorflow.python.keras.layers.convolutional.Conv2D at 0x7f1e7c8324a8>,
#  <tensorflow.python.keras.layers.normalization_v2.BatchNormalization at 0x7f1e77ed55c0>,
・
・
・
#  <tensorflow.python.keras.layers.normalization_v2.BatchNormalization at 0x7f1e776c9c88>,
#  <tensorflow.python.keras.layers.convolutional.Conv2D at 0x7f1e77715048>,
#  <tensorflow.python.keras.layers.normalization_v2.BatchNormalization at 0x7f1e776c9b70>,
#  <tensorflow.python.keras.layers.advanced_activations.ReLU at 0x7f1e7770b320>]

layersはリストなので、任意のレイヤーを取り出せます。またinput,outputでそのレイヤーの入力、出力の情報を確認することが出来ます。

例えば後ろから2番目のレイヤーを取り出すには次のようにします。

# 後ろから2番目のレイヤーを得る
mobile_net.layers[-2]
# 出力結果
# <tensorflow.python.keras.layers.normalization_v2.BatchNormalization at 0x7f1e776c9b70>

# レイヤーの入力情報を得る
# 出力結果
# <KerasTensor: shape=(None, 6, 6, 1280) dtype=float32 (created by layer 'Conv_1')>

# レイヤーの出力情報を得る
# 出力結果
# <KerasTensor: shape=(None, 6, 6, 1280) dtype=float32 (created by layer 'Conv_1_bn')>

中間層は名前で抽出することも出来ます。get_layerメソッドを使います。

mobile_net.get_layer("block_15_expand_relu")
# 出力結果
# <tensorflow.python.keras.layers.advanced_activations.ReLU at 0x7f1e7770bf28>

中間層が実際にどんな値を出力するのかを確認したいことがあると思います。

その場合は出力用のモデルを作成します。

intermediate_layer_model = tf.keras.Model(inputs=mobile_net.input,
                                outputs=mobile_net.get_layer("block_15_expand_relu").output)
dummy_input = np.zeros(shape=(1,192,192,3))
intermediate_layer_model.predict(dummy_input)

# 出力結果
# array([[[[1.7100832 , 0.        , 0.815455  , ..., 1.0687747 ,
#           0.        , 2.3017585 ],
・
・
・
#          [0.10043466, 0.        , 0.76246464, ..., 0.6731817 ,
#           0.        , 1.5239002 ]]]], dtype=float32)

ただし、この方法はSubclassing APIを用いた方法ではうまく動作しないようです。詳しくはこちらをご覧ください。


最後に、若干宣伝ぽくて恐縮ですが、私はフリーランスエンジニアをしております。このような機械学習をiPhoneデバイス上で動作させるといったお仕事もできますので、お気軽にご相談下さい。

連絡先名:TokyoYoshida
連絡先: yoshidaforpublic@gmail.com




この記事が気に入ったらサポートをしてみませんか?