我刚开始学习Tensorflow和Keras,我想知道是否有另一种更手动的选项来训练模型,而不使用fit方法。
我想手动进行优化过程:我想使用我自己的损失函数来更新参数,并使用我计算出的损失来更新这些参数。
有没有办法做到这一点,还是我在瞎担心?
我问这个问题是因为我想更深入地了解Keras模型的工作原理,以及是否有任何方法可以在不使用fit方法的情况下训练网络,这看起来像是做了很多事情。
回答:
可以查看这个教程:Tensorflow – 自定义训练。教程中解释了如何创建你自己的损失函数,自定义优化器,以及如何定义训练循环。你可以完全控制训练过程。
我在这里复制了教程中可能最吸引你的代码:
# 自定义损失函数def loss(target_y, predicted_y): return tf.reduce_mean(tf.square(target_y - predicted_y))# 定义训练循环def train(model, inputs, outputs, learning_rate): with tf.GradientTape() as t: current_loss = loss(outputs, model(inputs)) dW, db = t.gradient(current_loss, [model.W, model.b]) model.W.assign_sub(learning_rate * dW) model.b.assign_sub(learning_rate * db)model = Model()Ws, bs = [], []epochs = range(10)for epoch in epochs: Ws.append(model.W.numpy()) bs.append(model.b.numpy()) current_loss = loss(outputs, model(inputs)) train(model, inputs, outputs, learning_rate=0.1) print('Epoch %2d: W=%1.2f b=%1.2f, loss=%2.5f' % (epoch, Ws[-1], bs[-1], current_loss))
该教程使用了一个非常简单的线性模型,但它非常有用,可以帮助你理解概念。然而,如果你对更复杂的内容感兴趣,可以查看这个教程:Tensorflow – 自定义训练:逐步指南
# 创建模型 model = tf.keras.Sequential([ tf.keras.layers.Dense(10, activation=tf.nn.relu, input_shape=(4,)), # 需要输入形状 tf.keras.layers.Dense(10, activation=tf.nn.relu), tf.keras.layers.Dense(3)])# 你可以在这里定义自己的损失函数loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)def loss(model, x, y, training): # training=training仅在有在训练和推理时行为不同的层时需要(例如Dropout)。 y_ = model(x, training=training) return loss_object(y_true=y, y_pred=y_)# 在这里创建你的梯度和优化器def grad(model, inputs, targets): with tf.GradientTape() as tape: loss_value = loss(model, inputs, targets, training=True) return loss_value, tape.gradient(loss_value, model.trainable_variables)optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)# 训练循环 train_loss_results = []train_accuracy_results = []num_epochs = 201for epoch in range(num_epochs): epoch_loss_avg = tf.keras.metrics.Mean() epoch_accuracy = tf.keras.metrics.SparseCategoricalAccuracy() # 训练循环 - 使用32的批次 for x, y in train_dataset: # 优化模型 loss_value, grads = grad(model, x, y) optimizer.apply_gradients(zip(grads, model.trainable_variables)) # 跟踪进度 epoch_loss_avg.update_state(loss_value) # 添加当前批次的损失 # 比较预测标签与实际标签 # training=True仅在有在训练和推理时行为不同的层时需要(例如Dropout)。 epoch_accuracy.update_state(y, model(x, training=True)) # 结束epoch train_loss_results.append(epoch_loss_avg.result()) train_accuracy_results.append(epoch_accuracy.result()) if epoch % 50 == 0: print("Epoch {:03d}: Loss: {:.3f}, Accuracy: {:.3%}".format(epoch, epoch_loss_avg.result(), epoch_accuracy.result()))