TensorFlow2.0教程2:使用keras訓練模型


  最近對tensorflow十分感興趣,所以想做一個系列來詳細講解tensorflow來。

  本教程主要由tensorflow2.0官方教程的個人學習復現筆記整理而來,並借鑒了一些keras構造神經網絡的方法,中文講解,方便喜歡閱讀中文教程的朋友,tensorflow官方教程:https://www.tensorflow.org

  1.一般的模型構造、訓練、測試流程

  # 模型構造

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

  # 載入數據

  (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類, 並重寫一下函數

  _init_(self),初始化。

  update_state(self,y_true,y_pred,sample_weight = None),它使用目標y_true和模型預測y_pred來更新狀態變量。

  result(self),它使用狀態變量來計算最終結果。

  reset_states(self),重新初始化度量的狀態。

  # 這是一個簡單的示例,顯示如何實現CatgoricalTruePositives指標,該指標計算正確分類為屬於給定類的樣本數量

  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)

  # 以定義網絡層的方式添加網絡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)

  # 也可以以定義網絡層的方式添加要統計的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上面加

  # 也可以以定義網絡層的方式添加要統計的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傳入測試數據,還可以使用validation_split划分驗證數據

  ps:validation_split只能在用numpy數據訓練的情況下使用

  model.fit(x_train, y_train, batch_size=32, epochs=1, validation_split=0.2)

  3.使用tf.data構造數據

  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.樣本權重和類權重

  “樣本權重”數組是一個數字數組,用於指定批處理中每個樣本在計算總損失時應具有多少權重。 它通常用於不平衡的分類問題(這個想法是為了給予很少見的類更多的權重)。 當使用的權重是1和0時,該數組可以用作損失函數的掩碼(完全丟棄某些樣本對總損失的貢獻)。

  “類權重”dict是同一概念的更具體的實例:它將類索引映射到應該用於屬於該類的樣本的樣本權重。 例如,如果類“0”比數據中的類“1”少兩倍,則可以使用class_weight = {0:1.,1:0.5}。

  # 增加第5類的權重

  import numpy as np

  # 樣本權重

  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)

  # 類權重

  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數據

  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的權重

  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.使用回調

  Keras中的回調是在訓練期間(在epoch開始時,batch結束時,epoch結束時等)在不同點調用的對象,可用於實現以下行為:

  在培訓期間的不同時間點進行驗證(超出內置的每個時期驗證)

  定期檢查模型或超過某個精度閾值

  在訓練似乎平穩時改變模型的學習率

  在訓練似乎平穩時對頂層進行微調

  在培訓結束或超出某個性能閾值時發送電子郵件或即時消息通知等等。

  可使用的內置回調有

  ModelCheckpoint:定期保存模型。

  EarlyStopping:當訓練不再改進驗證指標時停止培訓。

  TensorBoard:定期編寫可在TensorBoard中顯示的模型日志(更多細節見“可視化”)。

  CSVLogger:將丟失和指標數據流式傳輸到CSV文件。

  等等無錫人流醫院哪家好 http://www.wxbhnkyy120.com/

  6.1回調使用

  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模型回調

  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)

  # 動態調整學習率

  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創建自己的回調方法

  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.自己構造訓練和驗證循環

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

  # 自己構造循環

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

  ## 添加自己構造的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))


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM