Keras API参考:损失
损失函数的目的是计算模型在训练期间应寻求最小化的量。
可用损失
请注意,所有损失都可以通过类句柄和函数句柄获得。类句柄使您能够将配置参数传递给构造函数(例如loss_fn = CategoricalCrossentropy(from_logits=True)),当以独立方式使用时,它们默认执行缩减(请参见下面的详细信息)。
概率损失
- BinaryCrossentropy class
- CategoricalCrossentropy class
- SparseCategoricalCrossentropy class
- Poisson class
- binary_crossentropy function
- categorical_crossentropy function
- sparse_categorical_crossentropy function
- poisson function
- KLDivergence class
- kl_divergence function
回归损失
- MeanSquaredError class
- MeanAbsoluteError class
- MeanAbsolutePercentageError class
- MeanSquaredLogarithmicError class
- CosineSimilarity class
- mean_squared_error function
- mean_absolute_error function
- mean_absolute_percentage_error function
- mean_squared_logarithmic_error function
- cosine_similarity function
- Huber class
- huber function
- LogCosh class
- log_cosh function
用于“maximum-margin”分类的铰链损失
- Hinge class
- SquaredHinge class
- CategoricalHinge class
- hinge function
- squared_hinge function
- categorical_hinge function
将损失与compile()&fit()一起使用
损失函数是编译Keras模型所需的两个参数之一:
from tensorflow import keras from tensorflow.keras import layers model = keras.Sequential() model.add(layers.Dense(64, kernel_initializer='uniform', input_shape=(10,))) model.add(layers.Activation('softmax')) loss_fn = keras.losses.SparseCategoricalCrossentropy() model.compile(loss=loss_fn, optimizer='adam')
所有内置的损失函数也可以通过它们的字符串标识符传递:
# pass optimizer by name: default parameters will be used model.compile(loss='sparse_categorical_crossenropy', optimizer='adam')
损失函数通常通过实例化损失类(例如keras.losses.SparseCategoricalCrossenropy)创建。所有损耗也作为功能句柄(例如keras.losses.sparse_categorical_crossentropy).)提供。
使用类可以在实例化时传递配置参数,例如:
loss_fn = keras.losses.SparseCategoricalCrossentropy(from_logits=True)
单独使用损失
损失是使用参数loss_fn loss_fn(y_true, y_pred, sample_weight=None)
调用的可调用对象:
- y_true:基本真实值,形状
(batch_size, d0, ... dN)
。对于稀疏损失函数,例如稀疏分类交叉点,形状应该是(batch_size, d0, ... dN-1)
。 - y_pred:形状的预测值
(batch_size, d0, .. dN)
。 - sample_weight:可选的sample_weight用作每个样本损失的减去加权系数。如果提供标量,则损失只按给定值缩放。如果
sample_weight
是大小为[BATCH_SIZE]的张量,则批次的每个样本的总损失将由sample_weight
矢量中的相应元素重新缩放。如果sample_weight
的形状为(batch_size, d0, ... dN-1)
(或者可以广播到该形状),则y_pred
的每个损耗元素通过相应的sample_weight的值进行缩放。(注dN-1
:所有损失函数减少1维,通常axis=-1。)。
默认情况下,损失函数为每个输入样本返回一个标量损失值,例如:
>>> tf.keras.losses.mean_squared_error(tf.ones((2, 2,)), tf.zeros((2, 2))) <tf.Tensor: shape=(2,), dtype=float32, numpy=array([1., 1.], dtype=float32)>
但是,损失类实例有一个缩减构造函数参数,默认为“sum_over_batch_size”(即平均值)。允许值为“sum_over_batch_size”、“sum”和“none”:
- “sum_over_batch_size”表示损失实例将返回批次中每个样本损失的平均值。
- “sum”表示损失实例将返回批次中每个样本损失的总和。
- “none”表示损失实例将返回每个样本损失的完整数组。
>>> loss_fn = tf.keras.losses.MeanSquaredError(reduction='sum_over_batch_size') >>> loss_fn(tf.ones((2, 2,)), tf.zeros((2, 2))) <tf.Tensor: shape=(), dtype=float32, numpy=1.0>
>>> loss_fn = tf.keras.losses.MeanSquaredError(reduction='sum') >>> loss_fn(tf.ones((2, 2,)), tf.zeros((2, 2))) <tf.Tensor: shape=(), dtype=float32, numpy=2.0>
>>> loss_fn = tf.keras.losses.MeanSquaredError(reduction='none') >>> loss_fn(tf.ones((2, 2,)), tf.zeros((2, 2))) <tf.Tensor: shape=(2,), dtype=float32, numpy=array([1., 1.], dtype=float32)>
请注意,这是tf.keras.losses.means_squared_error
等损失函数与tf.keras.losses.MeanSquaredError
等默认损失类实例之间的重要区别:函数版本不执行缩减,但默认情况下类实例执行缩减。
>>> loss_fn = tf.keras.losses.mean_squared_error >>> loss_fn(tf.ones((2, 2,)), tf.zeros((2, 2))) <tf.Tensor: shape=(2,), dtype=float32, numpy=array([1., 1.], dtype=float32)>
>>> loss_fn = tf.keras.losses.MeanSquaredError() >>> loss_fn(tf.ones((2, 2,)), tf.zeros((2, 2))) <tf.Tensor: shape=(), dtype=float32, numpy=1.0>
使用fit()
时,这种差异是无关紧要的,因为减少是由框架处理的。
下面介绍如何将损失类实例用作简单培训循环的一部分:
loss_fn = tf.keras.losses.CategoricalCrossentropy(from_logits=True) optimizer = tf.keras.optimizers.Adam() # Iterate over the batches of a dataset. for x, y in dataset: with tf.GradientTape() as tape: logits = model(x) # Compute the loss value for this batch. loss_value = loss_fn(y, logits) # Update the weights of the model to minimize the loss value. gradients = tape.gradient(loss_value, model.trainable_weights) optimizer.apply_gradients(zip(gradients, model.trainable_weights))
创建自定义损失
任何带有签名loss_fn(y_true, y_pred)返回损失数组(输入批中的一个样本)的可调用函数都可以作为损失传递给compile()。请注意,对于任何此类损失,都会自动支持样本加权。
下面是一个简单的示例:
def my_loss_fn(y_true, y_pred): squared_difference = tf.square(y_true - y_pred) return tf.reduce_mean(squared_difference, axis=-1) # Note the `axis=-1` model.compile(optimizer='adam', loss=my_loss_fn)
add_loses()接口
应用于模型输出的损失函数并不是造成损失的唯一途径。
编写自定义层或子类模型的调用方法时,可能需要计算要在训练期间最小化的标量(例如,正则化损失)。您可以使用Add_Loss()层方法来跟踪此类损失条款。
以下是基于输入的L2范数添加稀疏正则化损失的层的示例:
from tensorflow.keras.layers import Layer class MyActivityRegularizer(Layer): """Layer that creates an activity sparsity regularization loss.""" def __init__(self, rate=1e-2): super(MyActivityRegularizer, self).__init__() self.rate = rate def call(self, inputs): # We use `add_loss` to create a regularization loss # that depends on the inputs. self.add_loss(self.rate * tf.reduce_sum(tf.square(inputs))) return inputs
通过add_loss
添加的损失值可以在任何层或模型的.losses list
属性中检索(它们是从每个底层递归检索的):
from tensorflow.keras import layers class SparseMLP(Layer): """Stack of Linear layers with a sparsity regularization loss.""" def __init__(self, output_dim): super(SparseMLP, self).__init__() self.dense_1 = layers.Dense(32, activation=tf.nn.relu) self.regularization = MyActivityRegularizer(1e-2) self.dense_2 = layers.Dense(output_dim) def call(self, inputs): x = self.dense_1(inputs) x = self.regularization(x) return self.dense_2(x) mlp = SparseMLP(1) y = mlp(tf.ones((10, 10))) print(mlp.losses) # List containing one float32 scalar
这些损失在每次向前传递开始时由顶层清除–它们不会累积。因此,layer.losses
始终只包含最后一次向前传递过程中产生的损失。在编写训练循环时,您通常会在计算梯度之前对这些损失进行求和。
# Losses correspond to the *last* forward pass. mlp = SparseMLP(1) mlp(tf.ones((10, 10))) assert len(mlp.losses) == 1 mlp(tf.ones((10, 10))) assert len(mlp.losses) == 1 # No accumulation.
使用model.fit()时,会自动处理此类损失条件。
在编写自定义培训循环时,您应该手动从model.loses检索这些术语,如下所示:
loss_fn = tf.keras.losses.CategoricalCrossentropy(from_logits=True) optimizer = tf.keras.optimizers.Adam() # Iterate over the batches of a dataset. for x, y in dataset: with tf.GradientTape() as tape: # Forward pass. logits = model(x) # Loss value for this batch. loss_value = loss_fn(y, logits) # Add extra loss terms to the loss value. loss_value += sum(model.losses) # Update the weights of the model to minimize the loss value. gradients = tape.gradient(loss_value, model.trainable_weights) optimizer.apply_gradients(zip(gradients, model.trainable_weights))
有关更多详细信息,请参阅add_loses()文档。