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