Python TensorBoardをJupyter上で使用する

 本記事では、TensorBoardを使う雛形コードを載せました。下図例はJupyterLab上で、tensorflowはv2.4.1で動作確認しています。

f:id:HK29:20210822235528p:plain

分析内容とそのコードの元は次のリンク先です。違いは、タイトル通りにJupyter上でインタラクティブに、そしてTensorBoardを使うようにしたことです。

hk29.hatenablog.jp

■本プログラム

#!/usr/bin/env python
# coding: utf-8

# In[1]:


# TensorBoard notebook extension を設定
get_ipython().run_line_magic('load_ext', 'tensorboard')


# In[2]:


import os, glob
import numpy as np
import tensorflow as tf
#print("Num GPUs:", len(tf.config.list_physical_devices('GPU')))
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.preprocessing.image import array_to_img, img_to_array, load_img
from tensorflow.keras.utils import to_categorical
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
plt.rcParams['font.size'] = 18
import datetime
now = datetime.datetime.now()
now = now.strftime("%y%m%d_%H%M%S")

# テンソルフローのver確認
print('tensorflow', tf.__version__)

# ログを保存するフォルダを作成する
os.makedirs("logs", exist_ok=True)


# In[3]:


# 分類器を作成するために、予め保存した教師画像を格納したフォルダパスの取得
dir_path_for_set_label = './trainingSet' # 親フォルダを指定

label_data_list = []
cnt = 0    
for dirpath, dirnames, fnames in os.walk(dir_path_for_set_label):
    parent_dirname = dirpath.split(os.path.sep) # リスト化
    if len(parent_dirname) >= 2: # 子ディレクトリの場合に処理
        dirpath = dirpath.replace('/', os.sep) 
        label_data_list.append((dirpath, cnt))
        cnt += 1
print(label_data_list)
myclasses = len(label_data_list) # 分類クラス数
print('classes', myclasses)


# In[4]:


# データセットの読み込みと前処理
test_size = 0.3

# 画像の読み込み設定
img_width = 28 # 横
img_height = 28 # 縦
img_ch = 3 # 3ch(RGB)

# 教師データと分類画像を読み込む
data_x = []
data_y = []
for label_data in label_data_list:
    # 各ラベルの画像のある親フォルダパスとラベル番号をアンパック代入
    label_path, label_no = label_data
    # 各ラベルの各画像ファイルパスをリストで取得
    file_path_list = glob.glob(label_path + '/*.jpg')

    # 各画像にラベルを設定する
    for file_path in file_path_list:
        # 画像をサイズ変換
        img = img_to_array(load_img(file_path, target_size=(img_width, img_height, img_ch)))
        data_x.append(img) # 画像
        data_y.append(label_no) # ラベルを設定
        
# numpyアレイ型へ変換
x_np = np.asarray(data_x)
y_np = np.asarray(data_y)

# 学習用とテスト用にデータを分割
x_train, x_test, y_train, y_test = train_test_split(x_np, y_np, test_size=test_size)

# 学習データをfloat32型に変換する。
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
# 正規化する(0~1)
x_train = x_train / 255.0
x_test = x_test / 255.0

# 正解ラベルをone hotエンコーディング
y_train = to_categorical(y_train, myclasses)
y_test = to_categorical(y_test, myclasses)

# データセットの個数を表示
print(r'x train, y_train')
print(x_train.shape, x_train.shape)
print(r'x test, y_test')
print(x_test.shape, y_test.shape)


# In[5]:


# ハイパーパラメータ
epochs = 5 # 世代数 default 200
batch_size = 16 # バッチサイズ default 32
drop_rate = 0.2 # ドロップアウト率

# モデルの構築
model = keras.Sequential([
    keras.layers.Conv2D(filters = 32, # 2次元フィルタの枚数
                        kernel_size = (3,3), # フィルタのサイズ(縦, 横)
                        padding = "same", # ゼロパンディング。フィルタリングによる画素数低下の防止
                        activation = "relu", # 活性化関数。Noneの場合は線形活性
                        input_shape = x_train.shape[1:]), # 読み込むデータ。28×28の1チャネル。前処理しないRGBの場合は3チャネル
    keras.layers.MaxPooling2D(pool_size=(2,2)), # プーリング層(2×2の最大プーリング手法)。座標ずれの感度を低くする
    keras.layers.Dropout(drop_rate), # ドロップアウト率
    keras.layers.Conv2D(64, 3, padding='same', activation='relu'),
    keras.layers.MaxPooling2D(pool_size=(2,2)),
    keras.layers.Conv2D(64, 3, padding='same', activation='relu'),
    keras.layers.MaxPooling2D(pool_size=(2,2)),
    keras.layers.Dropout(drop_rate),
    keras.layers.Flatten(), # 1次元に変換
    keras.layers.Dense(512, activation='relu'),
    keras.layers.Dense(myclasses, activation='sigmoid') # 指定数のクラスに分類する。
])
# モデル構造の表示
model.summary()


# In[6]:


# アルゴリズムの設定
model.compile(optimizer='adam', 
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# コールバックでログを取得する
log_dir = "logs/scalars/" + now
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)

# カスタムスカラーログを取得する
file_writer = tf.summary.create_file_writer(log_dir + "/metrics")
file_writer.set_as_default()

# 世代が進むにつれて学習率を変化させる関数
def lr_schedule(epoch):
    learning_rate = 0.2
    if epoch > 10:
        learning_rate = 0.02
    if epoch > 20:
        learning_rate = 0.01
    if epoch > 50:
        learning_rate = 0.005

    tf.summary.scalar('learning rate', data=learning_rate, step=epoch)
    return learning_rate

lr_callback = tf.keras.callbacks.LearningRateScheduler(lr_schedule)

# 学習過程をテンソルボードでリアルタイムにグラフ化
get_ipython().run_line_magic('tensorboard', '--logdir logs/ --bind_all --port 6006 --reload_multifile true')


# In[7]:


# 学習の実行
history = model.fit(x_train, 
                    y_train, 
                    batch_size=batch_size, 
                    epochs=epochs,
                    verbose=1, 
                    validation_split=0.3,
                    callbacks=[tensorboard_callback, lr_callback],
                   )


# ## ダッシュボード(トップナビゲーションバーのタブ)の簡単な説明
# ### ■1. Scalars:エポックごとの損失とメトリックの変化
# →トレーニング速度、学習率、およびその他のスカラー値をトラッキングすることもできます。
# 
# ### ■2. Graphs:モデルの可視化
# →レイヤーの構築を視覚的に確認できます。
# 
# ### ■3. Distributions と Histograms:経時的なテンソルの分布
# →重みとバイアスを視覚的に意図した変化をしてるかの確認ができます。

# In[8]:


# 分類学習器をjsonファイルで保存
open('model_' + now + '.json', 'w').write(model.to_json())  

# 学習器の重みをバイナリファイルで保存
model.save_weights('model_' + now + '_weight.hdf5')


# In[9]:


# テンソルボードで学習過程を可視化
get_ipython().run_line_magic('tensorboard', '--logdir logs/')


# In[ ]:

以上

<広告>