目錄
- 1.一般的模型構(gòu)造、訓練、測試流程
- 2.自定義損失和指標
- 3.使用tf.data構(gòu)造數(shù)據(jù)
- 4.樣本權(quán)重和類權(quán)重
- 5.多輸入多輸出模型
- 6.使用回 調(diào)
- 6.1回調(diào)使用
- 6.2創(chuàng)建自己的回調(diào)方法
- 7.自己構(gòu)造訓練和驗證循環(huán)
1.一般的模型構(gòu)造、訓練、測試流程
# 模型構(gòu)造
inputs = keras.Input(shape=(784,), name='mnist_input')
h1 = layers.Dense(64, activation='relu')(inputs)
h1 = layers.Dense(64, activation='relu')(h1)
outputs = layers.Dense(10, activation='softmax')(h1)
model = keras.Model(inputs, outputs)
# keras.utils.plot_model(model, 'net001.png', show_shapes=True)
model.compile(optimizer=keras.optimizers.RMSprop(),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()])
# 載入數(shù)據(jù)
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') /255
x_test = x_test.reshape(10000, 784).astype('float32') /255
x_val = x_train[-10000:]
y_val = y_train[-10000:]
x_train = x_train[:-10000]
y_train = y_train[:-10000]
# 訓練模型
history = model.fit(x_train, y_train, batch_size=64, epochs=3,
validation_data=(x_val, y_val))
print('history:')
print(history.history)
result = model.evaluate(x_test, y_test, batch_size=128)
print('evaluate:')
print(result)
pred = model.predict(x_test[:2])
print('predict:')
print(pred)
2.自定義損失和指標
自定義指標只需繼承Metric類, 并重寫一下函數(shù)
_init_(self),初始化。
update_state(self,y_true,y_pred,sample_weight = None),它使用目標y_true和模型預測y_pred來更新狀態(tài)變量。
result(self),它使用狀態(tài)變量來計算最終結(jié)果。
reset_states(self),重新初始化度量的狀態(tài)。
# 這是一個簡單的示例,顯示如何實現(xiàn)CatgoricalTruePositives指標,該指標計算正確分類為屬于給定類的樣本數(shù)量
class CatgoricalTruePostives(keras.metrics.Metric):
def __init__(self, name='binary_true_postives', **kwargs):
super(CatgoricalTruePostives, self).__init__(name=name, **kwargs)
self.true_postives = self.add_weight(name='tp', initializer='zeros')
def update_state(self, y_true, y_pred, sample_weight=None):
y_pred = tf.argmax(y_pred)
y_true = tf.equal(tf.cast(y_pred, tf.int32), tf.cast(y_true, tf.int32))
y_true = tf.cast(y_true, tf.float32)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, tf.float32)
y_true = tf.multiply(sample_weight, y_true)
return self.true_postives.assign_add(tf.reduce_sum(y_true))
def result(self):
return tf.identity(self.true_postives)
def reset_states(self):
self.true_postives.assign(0.)
model.compile(optimizer=keras.optimizers.RMSprop(1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[CatgoricalTruePostives()])
model.fit(x_train, y_train,
batch_size=64, epochs=3)
# 以定義網(wǎng)絡(luò)層的方式添加網(wǎng)絡(luò)loss
class ActivityRegularizationLayer(layers.Layer):
def call(self, inputs):
self.add_loss(tf.reduce_sum(inputs) * 0.1)
return inputs
inputs = keras.Input(shape=(784,), name='mnist_input')
h1 = layers.Dense(64, activation='relu')(inputs)
h1 = ActivityRegularizationLayer()(h1)
h1 = layers.Dense(64, activation='relu')(h1)
outputs = layers.Dense(10, activation='softmax')(h1)
model = keras.Model(inputs, outputs)
# keras.utils.plot_model(model, 'net001.png', show_shapes=True)
model.compile(optimizer=keras.optimizers.RMSprop(),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()])
model.fit(x_train, y_train, batch_size=32, epochs=1)
# 也可以以定義網(wǎng)絡(luò)層的方式添加要統(tǒng)計的metric
class MetricLoggingLayer(layers.Layer):
def call(self, inputs):
self.add_metric(keras.backend.std(inputs),
name='std_of_activation',
aggregation='mean')
return inputs
inputs = keras.Input(shape=(784,), name='mnist_input')
h1 = layers.Dense(64, activation='relu')(inputs)
h1 = MetricLoggingLayer()(h1)
h1 = layers.Dense(64, activation='relu')(h1)
outputs = layers.Dense(10, activation='softmax')(h1)
model = keras.Model(inputs, outputs)
# keras.utils.plot_model(model, 'net001.png', show_shapes=True)
model.compile(optimizer=keras.optimizers.RMSprop(),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()])
model.fit(x_train, y_train, batch_size=32, epochs=1)
# 也可以直接在model上面加
# 也可以以定義網(wǎng)絡(luò)層的方式添加要統(tǒng)計的metric
class MetricLoggingLayer(layers.Layer):
def call(self, inputs):
self.add_metric(keras.backend.std(inputs),
name='std_of_activation',
aggregation='mean')
return inputs
inputs = keras.Input(shape=(784,), name='mnist_input')
h1 = layers.Dense(64, activation='relu')(inputs)
h2 = layers.Dense(64, activation='relu')(h1)
outputs = layers.Dense(10, activation='softmax')(h2)
model = keras.Model(inputs, outputs)
model.add_metric(keras.backend.std(inputs),
name='std_of_activation',
aggregation='mean')
model.add_loss(tf.reduce_sum(h1)*0.1)
# keras.utils.plot_model(model, 'net001.png', show_shapes=True)
model.compile(optimizer=keras.optimizers.RMSprop(),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()])
model.fit(x_train, y_train, batch_size=32, epochs=1)
處理使用validation_data傳入測試數(shù)據(jù),還可以使用validation_split劃分驗證數(shù)據(jù)
ps:validation_split只能在用numpy數(shù)據(jù)訓練的情況下使用
model.fit(x_train, y_train, batch_size=32, epochs=1, validation_split=0.2)
3.使用tf.data構(gòu)造數(shù)據(jù)
def get_compiled_model():
inputs = keras.Input(shape=(784,), name='mnist_input')
h1 = layers.Dense(64, activation='relu')(inputs)
h2 = layers.Dense(64, activation='relu')(h1)
outputs = layers.Dense(10, activation='softmax')(h2)
model = keras.Model(inputs, outputs)
model.compile(optimizer=keras.optimizers.RMSprop(),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()])
return model
model = get_compiled_model()
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)
# model.fit(train_dataset, epochs=3)
# steps_per_epoch 每個epoch只訓練幾步
# validation_steps 每次驗證,驗證幾步
model.fit(train_dataset, epochs=3, steps_per_epoch=100,
validation_data=val_dataset, validation_steps=3)
4.樣本權(quán)重和類權(quán)重
“樣本權(quán)重”數(shù)組是一個數(shù)字數(shù)組,用于指定批處理中每個樣本在計算總損失時應具有多少權(quán)重。 它通常用于不平衡的分類問題(這個想法是為了給予很少見的類更多的權(quán)重)。 當使用的權(quán)重是1和0時,該數(shù)組可以用作損失函數(shù)的掩碼(完全丟棄某些樣本對總損失的貢獻)。
“類權(quán)重”dict是同一概念的更具體的實例:它將類索引映射到應該用于屬于該類的樣本的樣本權(quán)重。 例如,如果類“0”比數(shù)據(jù)中的類“1”少兩倍,則可以使用class_weight = {0:1.,1:0.5}。
# 增加第5類的權(quán)重
import numpy as np
# 樣本權(quán)重
model = get_compiled_model()
class_weight = {i:1.0 for i in range(10)}
class_weight[5] = 2.0
print(class_weight)
model.fit(x_train, y_train,
class_weight=class_weight,
batch_size=64,
epochs=4)
# 類權(quán)重
model = get_compiled_model()
sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0
model.fit(x_train, y_train,
sample_weight=sample_weight,
batch_size=64,
epochs=4)
# tf.data數(shù)據(jù)
model = get_compiled_model()
sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train,
sample_weight))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)
model.fit(train_dataset, epochs=3, )
5.多輸入多輸出模型
image_input = keras.Input(shape=(32, 32, 3), name='img_input')
timeseries_input = keras.Input(shape=(None, 10), name='ts_input')
x1 = layers.Conv2D(3, 3)(image_input)
x1 = layers.GlobalMaxPooling2D()(x1)
x2 = layers.Conv1D(3, 3)(timeseries_input)
x2 = layers.GlobalMaxPooling1D()(x2)
x = layers.concatenate([x1, x2])
score_output = layers.Dense(1, name='score_output')(x)
class_output = layers.Dense(5, activation='softmax', name='class_output')(x)
model = keras.Model(inputs=[image_input, timeseries_input],
outputs=[score_output, class_output])
keras.utils.plot_model(model, 'multi_input_output_model.png'
, show_shapes=True)
# 可以為模型指定不同的loss和metrics
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=[keras.losses.MeanSquaredError(),
keras.losses.CategoricalCrossentropy()])
# 還可以指定loss的權(quán)重
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss={'score_output': keras.losses.MeanSquaredError(),
'class_output': keras.losses.CategoricalCrossentropy()},
metrics={'score_output': [keras.metrics.MeanAbsolutePercentageError(),
keras.metrics.MeanAbsoluteError()],
'class_output': [keras.metrics.CategoricalAccuracy()]},
loss_weight={'score_output': 2., 'class_output': 1.})
# 可以把不需要傳播的loss置0
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=[None, keras.losses.CategoricalCrossentropy()])
# Or dict loss version
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss={'class_output': keras.losses.CategoricalCrossentropy()})
6.使用回 調(diào)
Keras中的回調(diào)是在訓練期間(在epoch開始時,batch結(jié)束時,epoch結(jié)束時等)在不同點調(diào)用的對象,可用于實現(xiàn)以下行為:
- 在培訓期間的不同時間點進行驗證(超出內(nèi)置的每個時期驗證)
- 定期檢查模型或超過某個精度閾值
- 在訓練似乎平穩(wěn)時改變模型的學習率
- 在訓練似乎平穩(wěn)時對頂層進行微調(diào)
- 在培訓結(jié)束或超出某個性能閾值時發(fā)送電子郵件或即時消息通知等等。
可使用的內(nèi)置回調(diào)有
- ModelCheckpoint:定期保存模型。
- EarlyStopping:當訓練不再改進驗證指標時停止培訓。
- TensorBoard:定期編寫可在TensorBoard中顯示的模型日志(更多細節(jié)見“可視化”)。
- CSVLogger:將丟失和指標數(shù)據(jù)流式傳輸?shù)紺SV文件。
- 等等
6.1回調(diào)使用
model = get_compiled_model()
callbacks = [
keras.callbacks.EarlyStopping(
# Stop training when `val_loss` is no longer improving
monitor='val_loss',
# "no longer improving" being defined as "no better than 1e-2 less"
min_delta=1e-2,
# "no longer improving" being further defined as "for at least 2 epochs"
patience=2,
verbose=1)
]
model.fit(x_train, y_train,
epochs=20,
batch_size=64,
callbacks=callbacks,
validation_split=0.2)
# checkpoint模型回調(diào)
model = get_compiled_model()
check_callback = keras.callbacks.ModelCheckpoint(
filepath='mymodel_{epoch}.h5',
save_best_only=True,
monitor='val_loss',
verbose=1
)
model.fit(x_train, y_train,
epochs=3,
batch_size=64,
callbacks=[check_callback],
validation_split=0.2)
# 動態(tài)調(diào)整學習率
initial_learning_rate = 0.1
lr_schedule = keras.optimizers.schedules.ExponentialDecay(
initial_learning_rate,
decay_steps=10000,
decay_rate=0.96,
staircase=True
)
optimizer = keras.optimizers.RMSprop(learning_rate=lr_schedule)
# 使用tensorboard
tensorboard_cbk = keras.callbacks.TensorBoard(log_dir='./full_path_to_your_logs')
model.fit(x_train, y_train,
epochs=5,
batch_size=64,
callbacks=[tensorboard_cbk],
validation_split=0.2)
6.2創(chuàng)建自己的回調(diào)方法
class LossHistory(keras.callbacks.Callback):
def on_train_begin(self, logs):
self.losses = []
def on_epoch_end(self, batch, logs):
self.losses.append(logs.get('loss'))
print('\nloss:',self.losses[-1])
model = get_compiled_model()
callbacks = [
LossHistory()
]
model.fit(x_train, y_train,
epochs=3,
batch_size=64,
callbacks=callbacks,
validation_split=0.2)
7.自己構(gòu)造訓練和驗證循環(huán)
# Get the model.
inputs = keras.Input(shape=(784,), name='digits')
x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
x = layers.Dense(64, activation='relu', name='dense_2')(x)
outputs = layers.Dense(10, activation='softmax', name='predictions')(x)
model = keras.Model(inputs=inputs, outputs=outputs)
# Instantiate an optimizer.
optimizer = keras.optimizers.SGD(learning_rate=1e-3)
# Instantiate a loss function.
loss_fn = keras.losses.SparseCategoricalCrossentropy()
# Prepare the training dataset.
batch_size = 64
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(batch_size)
# 自己構(gòu)造循環(huán)
for epoch in range(3):
print('epoch: ', epoch)
for step, (x_batch_train, y_batch_train) in enumerate(train_dataset):
# 開一個gradient tape, 計算梯度
with tf.GradientTape() as tape:
logits = model(x_batch_train)
loss_value = loss_fn(y_batch_train, logits)
grads = tape.gradient(loss_value, model.trainable_variables)
optimizer.apply_gradients(zip(grads, model.trainable_variables))
if step % 200 == 0:
print('Training loss (for one batch) at step %s: %s' % (step, float(loss_value)))
print('Seen so far: %s samples' % ((step + 1) * 64))
# 訓練并驗證
# Get model
inputs = keras.Input(shape=(784,), name='digits')
x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
x = layers.Dense(64, activation='relu', name='dense_2')(x)
outputs = layers.Dense(10, activation='softmax', name='predictions')(x)
model = keras.Model(inputs=inputs, outputs=outputs)
# Instantiate an optimizer to train the model.
optimizer = keras.optimizers.SGD(learning_rate=1e-3)
# Instantiate a loss function.
loss_fn = keras.losses.SparseCategoricalCrossentropy()
# Prepare the metrics.
train_acc_metric = keras.metrics.SparseCategoricalAccuracy()
val_acc_metric = keras.metrics.SparseCategoricalAccuracy()
# Prepare the training dataset.
batch_size = 64
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(batch_size)
# Prepare the validation dataset.
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)
# Iterate over epochs.
for epoch in range(3):
print('Start of epoch %d' % (epoch,))
# Iterate over the batches of the dataset.
for step, (x_batch_train, y_batch_train) in enumerate(train_dataset):
with tf.GradientTape() as tape:
logits = model(x_batch_train)
loss_value = loss_fn(y_batch_train, logits)
grads = tape.gradient(loss_value, model.trainable_variables)
optimizer.apply_gradients(zip(grads, model.trainable_variables))
# Update training metric.
train_acc_metric(y_batch_train, logits)
# Log every 200 batches.
if step % 200 == 0:
print('Training loss (for one batch) at step %s: %s' % (step, float(loss_value)))
print('Seen so far: %s samples' % ((step + 1) * 64))
# Display metrics at the end of each epoch.
train_acc = train_acc_metric.result()
print('Training acc over epoch: %s' % (float(train_acc),))
# Reset training metrics at the end of each epoch
train_acc_metric.reset_states()
# Run a validation loop at the end of each epoch.
for x_batch_val, y_batch_val in val_dataset:
val_logits = model(x_batch_val)
# Update val metrics
val_acc_metric(y_batch_val, val_logits)
val_acc = val_acc_metric.result()
val_acc_metric.reset_states()
print('Validation acc: %s' % (float(val_acc),))
## 添加自己構(gòu)造的loss, 每次只能看到最新一次訓練增加的loss
class ActivityRegularizationLayer(layers.Layer):
def call(self, inputs):
self.add_loss(1e-2 * tf.reduce_sum(inputs))
return inputs
inputs = keras.Input(shape=(784,), name='digits')
x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
# Insert activity regularization as a layer
x = ActivityRegularizationLayer()(x)
x = layers.Dense(64, activation='relu', name='dense_2')(x)
outputs = layers.Dense(10, activation='softmax', name='predictions')(x)
model = keras.Model(inputs=inputs, outputs=outputs)
logits = model(x_train[:64])
print(model.losses)
logits = model(x_train[:64])
logits = model(x_train[64: 128])
logits = model(x_train[128: 192])
print(model.losses)
# 將loss添加進求導中
optimizer = keras.optimizers.SGD(learning_rate=1e-3)
for epoch in range(3):
print('Start of epoch %d' % (epoch,))
for step, (x_batch_train, y_batch_train) in enumerate(train_dataset):
with tf.GradientTape() as tape:
logits = model(x_batch_train)
loss_value = loss_fn(y_batch_train, logits)
# Add extra losses created during this forward pass:
loss_value += sum(model.losses)
grads = tape.gradient(loss_value, model.trainable_variables)
optimizer.apply_gradients(zip(grads, model.trainable_variables))
# Log every 200 batches.
if step % 200 == 0:
print('Training loss (for one batch) at step %s: %s' % (step, float(loss_value)))
print('Seen so far: %s samples' % ((step + 1) * 64))
到此這篇關(guān)于TensorFlow2.0使用keras訓練模型的實現(xiàn)的文章就介紹到這了,更多相關(guān)TensorFlow2.0 keras訓練模型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- 入門tensorflow教程之TensorBoard可視化模型訓練
- TensorFlow2.X使用圖片制作簡單的數(shù)據(jù)集訓練模型
- 如何將tensorflow訓練好的模型移植到Android (MNIST手寫數(shù)字識別)
- 一小時學會TensorFlow2之大幅提高模型準確率