天天看點

tensorflow2.0 最詳細的模型訓練步驟 直接上代碼

import  os
import  tensorflow as tf
from    tensorflow import keras
from    tensorflow.keras import layers, optimizers, datasets
import numpy as np
import matplotlib.pyplot as plt
import datetime

def prepare_mnist_features_and_labels(x, y):
  x = tf.cast(x, tf.float32) / 255.0
  y = tf.cast(y, tf.int64)

  return x, y

def mnist_dataset():
  (x, y), (x_val, y_val) = datasets.fashion_mnist.load_data()
  x, x_val = np.expand_dims(x, axis=3), np.expand_dims(x_val, axis=3)

  y = tf.one_hot(y, depth=10)
  y_val = tf.one_hot(y_val, depth=10)
  ds = tf.data.Dataset.from_tensor_slices((x, y))
  ds = ds.map(prepare_mnist_features_and_labels)
  ds = ds.shuffle(60000).batch(100)


  ds_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))
  ds_val = ds_val.map(prepare_mnist_features_and_labels)
  ds_val = ds_val.shuffle(10000).batch(100)
  return ds,ds_val

class LearningRateExponentialDecay:
    def __init__(self,initial_learning_rate,decay_epochs,decay_rate):
        self.initial_learning_rate=initial_learning_rate
        self.decay_epochs=decay_epochs
        self.decay_rate=decay_rate
    def __call__(self,epoch):
        dtype =type(self.initial_learning_rate)
        decay_epochs=np.array(self.decay_epochs).astype(dtype)
        decay_rate=np.array(self.decay_rate).astype(dtype)
        epoch = np.array(epoch).astype(dtype)
        p = epoch/decay_epochs
        lr = self.initial_learning_rate*np.power(decay_rate,p)
        return lr

def save_log():
    log_dir = os.path.join( "C:/Users/byroot/Desktop/test1/model_output", 'logs_{}'.format(datetime.datetime.now().strftime("%Y%m%d-%H%M%S")))
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)
    return log_dir

def callbackfunc():
    # 模型儲存格式預設是saved_model,可以自己定義更改原有類來儲存hdf5
    ckpt = tf.keras.callbacks.ModelCheckpoint(filepath=path, monitor='val_loss',
                                              save_best_only=False, save_weights_only=False)

    # 當模型訓練不符合我們要求時停止訓練,連續5個epoch驗證集精度沒有提高0.001%停
    earlystop = tf.keras.callbacks.EarlyStopping(monitor='val_accuracy', min_delta=0.0001, patience=52)

    lr_schedule = LearningRateExponentialDecay(initial_learning_rate=0.001, decay_epochs=1, decay_rate=0.96)
    lr = tf.keras.callbacks.LearningRateScheduler(lr_schedule)

    # 定義當loss出現nan或inf時停止訓練的callback
    terminate = tf.keras.callbacks.TerminateOnNaN()

    # 降低學習率(要比學習率自動周期變化有更大變化和更長時間監控)
    reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=3,
                                                     min_delta=0.0001, min_lr=0)

    # 儲存訓練過程中大數标量名額,與tensorboard同一個檔案
    csv_logger = tf.keras.callbacks.CSVLogger(os.path.join(log_dir, 'logs.log'), separator=',')

    # 還要加入tensorboard的使用,這種方法記錄的内容有限
    tensorboard = tf.keras.callbacks.TensorBoard(log_dir=log_dir,
                                                 histogram_freq=1,  # 對參數和激活做直方圖,一定要有測試集
                                                 write_graph=True,  # 模型結構圖
                                                 write_images=True,  # 把模型參數做為圖檔形式存到
                                                 update_freq='epoch',  # epoch,batch,整數,太頻的話會減慢速度
                                                 profile_batch=2,  # 記錄模型性能
                                                 embeddings_freq=1,
                                                 embeddings_metadata=None  # 這個還不太清楚如何使用
                                                 )

    callback = [ckpt, earlystop, lr, tensorboard, terminate, reduce_lr, csv_logger]
    return callback

def saveModel():
    model_json = model.to_json()
    with open(os.path.join(log_dir, 'model_json.json'), 'w') as json_file:
        json_file.write(model_json)

if __name__ == '__main__':
    path = "C:/Users/byroot/Desktop/test1/" + "ckpt_epoch{epoch:02d}_val_acc{val_loss:.2f}.hdf5"

    """1.參數配置"""
    log_dir = save_log()
    os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'  # or any {'0', '1', '2'}

    """2.資料處理"""
    train_dataset, test_dataset = mnist_dataset()
    """3.設定模型"""
    model = keras.Sequential([
        layers.Reshape(target_shape=(28 * 28,), input_shape=(28, 28, 1 )),
        layers.Dense(200, activation='relu'),
        layers.Dense(200, activation='relu'),
        layers.Dense(200, activation='relu'),
        layers.Dense(10)])
    # no need to use compile if you have no loss/optimizer/metrics involved here.
    model.compile(optimizer=optimizers.Adam(0.001),
                  loss=tf.losses.CategoricalCrossentropy(from_logits=True),
                  metrics=['accuracy'])


    """4.畫出模型結構圖并儲存"""
    tf.keras.utils.plot_model(model,to_file=os.path.join('C:/Users/byroot/Desktop/test1/','model.png'),show_shapes=True,show_layer_names=True)
    """5.配置回調函數"""
    callback = callbackfunc()
    """6.開始訓練"""
    model.fit(train_dataset.repeat(), epochs=1, steps_per_epoch=10,
              validation_data=test_dataset.repeat(),
              validation_steps=2,
              callbacks = callback
              )
    """7.列印模型結構"""
    model.summary()
    """8.儲存模型結構及配置參數"""
    saveModel()
    """9.對模型在測試集上進行評估"""
    metrics = model.evaluate(test_dataset)
    print("val_loss:", metrics[0], "val_accuracy:", metrics[1])