keras中的loss、optimizer、metrics

用keras搭好模型架构之后的下一步,就是执行编译操作。在编译时,经常需要指定三个参数

  • loss
  • optimizer
  • metrics

这三个参数有两类选择:

  • 使用字符串
  • 使用标识符,如keras.losses,keras.optimizers,metrics包下面的函数

例如:

sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy',
              optimizer=sgd,
              metrics=['accuracy'])

因为有时可以使用字符串,有时可以使用标识符,令人很想知道背后是如何操作的。下面分别针对optimizer,loss,metrics三种对象的获取进行研究。

optimizer

一个模型只能有一个optimizer,在执行编译的时候只能指定一个optimizer。
在keras.optimizers.py中,有一个get函数,用于根据用户传进来的optimizer参数获取优化器的实例:

def get(identifier):
    # 如果后端是tensorflow并且使用的是tensorflow自带的优化器实例,可以直接使用tensorflow原生的优化器
    if K.backend() == 'tensorflow':
        # Wrap TF optimizer instances
        if isinstance(identifier, tf.train.Optimizer):
            return TFOptimizer(identifier)
    # 如果以json串的形式定义optimizer并进行参数配置
    if isinstance(identifier, dict):
        return deserialize(identifier)
    elif isinstance(identifier, six.string_types):
        # 如果以字符串形式指定optimizer,那么使用优化器的默认配置参数
        config = {'class_name': str(identifier), 'config': {}}
        return deserialize(config)
    if isinstance(identifier, Optimizer):
        # 如果使用keras封装的Optimizer的实例
        return identifier
    else:
        raise ValueError('Could not interpret optimizer identifier: ' +
                         str(identifier))

其中,deserilize(config)函数的作用就是把optimizer反序列化制造一个实例。

loss

keras.losses函数也有一个get(identifier)方法。其中需要注意以下一点:

如果identifier是可调用的一个函数名,也就是一个自定义的损失函数,这个损失函数返回值是一个张量。这样就轻而易举的实现了自定义损失函数。除了使用str和dict类型的identifier,我们也可以直接使用keras.losses包下面的损失函数。

def get(identifier):
    if identifier is None:
        return None
    if isinstance(identifier, six.string_types):
        identifier = str(identifier)
        return deserialize(identifier)
    if isinstance(identifier, dict):
        return deserialize(identifier)
    elif callable(identifier):
        return identifier
    else:
        raise ValueError('Could not interpret '
                         'loss function identifier:', identifier)

metrics

在model.compile()函数中,optimizer和loss都是单数形式,只有metrics是复数形式。因为一个模型只能指明一个optimizer和loss,却可以指明多个metrics。metrics也是三者中处理逻辑最为复杂的一个。

在keras最核心的地方keras.engine.train.py中有如下处理metrics的函数。这个函数其实就做了两件事:

  • 根据输入的metric找到具体的metric对应的函数
  • 计算metric张量

在寻找metric对应函数时,有两种步骤:

  • 使用字符串形式指明准确率和交叉熵
  • 使用keras.metrics.py中的函数
def handle_metrics(metrics, weights=None):
    metric_name_prefix = 'weighted_' if weights is not None else ''

    for metric in metrics:
        # 如果metrics是最常见的那种:accuracy,交叉熵
        if metric in ('accuracy', 'acc', 'crossentropy', 'ce'):
            # custom handling of accuracy/crossentropy
            # (because of class mode duality)
            output_shape = K.int_shape(self.outputs[i])
            # 如果输出维度是1或者损失函数是二分类损失函数,那么说明是个二分类问题,应该使用二分类的accuracy和二分类的的交叉熵
            if (output_shape[-1] == 1 or
                self.loss_functions[i] == losses.binary_crossentropy):
                # case: binary accuracy/crossentropy
                if metric in ('accuracy', 'acc'):
                    metric_fn = metrics_module.binary_accuracy
                elif metric in ('crossentropy', 'ce'):
                    metric_fn = metrics_module.binary_crossentropy
            # 如果损失函数是sparse_categorical_crossentropy,那么目标y_input就不是one-hot的,所以就需要使用sparse的多类准去率和sparse的多类交叉熵
            elif self.loss_functions[i] == losses.sparse_categorical_crossentropy:
                # case: categorical accuracy/crossentropy
                # with sparse targets
                if metric in ('accuracy', 'acc'):
                    metric_fn = metrics_module.sparse_categorical_accuracy
                elif metric in ('crossentropy', 'ce'):
                    metric_fn = metrics_module.sparse_categorical_crossentropy
            else:
                # case: categorical accuracy/crossentropy
                if metric in ('accuracy', 'acc'):
                    metric_fn = metrics_module.categorical_accuracy
                elif metric in ('crossentropy', 'ce'):
                    metric_fn = metrics_module.categorical_crossentropy
            if metric in ('accuracy', 'acc'):
                    suffix = 'acc'
            elif metric in ('crossentropy', 'ce'):
                    suffix = 'ce'
            weighted_metric_fn = weighted_masked_objective(metric_fn)
            metric_name = metric_name_prefix + suffix
        else:
            # 如果输入的metric不是字符串,那么就调用metrics模块获取
            metric_fn = metrics_module.get(metric)
            weighted_metric_fn = weighted_masked_objective(metric_fn)
            # Get metric name as string
            if hasattr(metric_fn, 'name'):
                metric_name = metric_fn.name
            else:
                metric_name = metric_fn.__name__
            metric_name = metric_name_prefix + metric_name

        with K.name_scope(metric_name):
            metric_result = weighted_metric_fn(y_true, y_pred,
                                                weights=weights,
                                                mask=masks[i])

        # Append to self.metrics_names, self.metric_tensors,
        # self.stateful_metric_names
        if len(self.output_names) > 1:
            metric_name = self.output_names[i] + '_' + metric_name
        # Dedupe name
        j = 1
        base_metric_name = metric_name
        while metric_name in self.metrics_names:
            metric_name = base_metric_name + '_' + str(j)
            j += 1
        self.metrics_names.append(metric_name)
        self.metrics_tensors.append(metric_result)

        # Keep track of state updates created by
        # stateful metrics (i.e. metrics layers).
        if isinstance(metric_fn, Layer) and metric_fn.stateful:
            self.stateful_metric_names.append(metric_name)
            self.stateful_metric_functions.append(metric_fn)
            self.metrics_updates += metric_fn.updates

无论怎么使用metric,最终都会变成metrics包下面的函数。当使用字符串形式指明accuracy和crossentropy时,keras会非常智能地确定应该使用metrics包下面的哪个函数。因为metrics包下的那些metric函数有不同的使用场景,例如:

  • 有的处理的是one-hot形式的y_input(数据的类别),有的处理的是非one-hot形式的y_input
  • 有的处理的是二分类问题的metric,有的处理的是多分类问题的metric

当使用字符串“accuracy”和“crossentropy”指明metric时,keras会根据损失函数、输出层的shape来确定具体应该使用哪个metric函数。在任何情况下,直接使用metrics下面的函数名是总不会出错的。

keras.metrics.py文件中也有一个get(identifier)函数用于获取metric函数。

def get(identifier):
    if isinstance(identifier, dict):
        config = {'class_name': str(identifier), 'config': {}}
        return deserialize(config)
    elif isinstance(identifier, six.string_types):
        return deserialize(str(identifier))
    elif callable(identifier):
        return identifier
    else:
        raise ValueError('Could not interpret '
                         'metric function identifier:', identifier)

如果identifier是字符串或者字典,那么会根据identifier反序列化出一个metric函数。
如果identifier本身就是一个函数名,那么就直接返回这个函数名。这种方式就为自定义metric提供了巨大便利。

keras中的设计哲学堪称完美。

原文地址:https://www.cnblogs.com/weiyinfu/p/9783776.html

时间: 2025-01-18 00:41:10

keras中的loss、optimizer、metrics的相关文章

keras model.compile(loss='目标函数 ', optimizer='adam', metrics=['accuracy'])

目录 目标函数 1.mean_squared_error 2. mean_absolute_error 3.mean_absolute_percentage_error 4. mean_squared_logarithmic_error 5.squared_hinge 6.hinge 7.binary_crossentropy 8.categorical_crossentropy 参考: 目标函数 目标函数,或称损失函数,是网络中的性能函数,也是编译一个模型必须的两个参数之一.由于损失函数种类众

【tf.keras】tf.keras使用tensorflow中定义的optimizer

我的 tensorflow+keras 版本: print(tf.VERSION) # '1.10.0' print(tf.keras.__version__) # '2.1.6-tf' tf.keras 没有实现 AdamW,即 Adam with Weight decay.论文<DECOUPLED WEIGHT DECAY REGULARIZATION>提出,在使用 Adam 时,weight decay 不等于 L2 regularization.具体可以参见 当前训练神经网络最快的方式

keras中保存自定义层和loss

在keras中保存模型有几种方式: (1):使用callbacks,可以保存训练中任意的模型,或选择最好的模型 logdir = './callbacks' if not os.path.exists(logdir): os.mkdir(logdir) output_model_file = os.path.join(logdir, "xxxx.h5") callbacks = [ tf.keras.callbacks.ModelCheckpoint(output_model_file

keras中的mask操作

使用背景 最常见的一种情况, 在NLP问题的句子补全方法中, 按照一定的长度, 对句子进行填补和截取操作. 一般使用keras.preprocessing.sequence包中的pad_sequences方法, 在句子前面或者后面补0. 但是这些零是我们不需要的, 只是为了组成可以计算的结构才填补的. 因此计算过程中, 我们希望用mask的思想, 在计算中, 屏蔽这些填补0值得作用. keras中提供了mask相关的操作方法. 原理 在keras中, Tensor在各层之间传递, Layer对象

第20章 keras中“开箱即用”CNNs

第20章 keras中"开箱即用"CNNs 到目前为止,我们学习了如何从头开始训练CNNs.这些CNNs大多数工作在浅层(以及较小数据集上),以至于它们可以很容易的在CPU上训练,而不需要在更贵的GPU上,这使得我们能够掌握神经网络和深度学习的基础. 但是由于我们只在浅层网络上工作,我们无法利用深度学习带给我们的全分类能力.幸运的是,keras库预置了5种在ImageNet数据集上预训练的CNNs: l  VGG16 l  VGG19 l  ResNet50 l  Inception

keras中使用预训练模型进行图片分类

keras中含有多个网络的预训练模型,可以很方便的拿来进行使用. 安装及使用主要参考官方教程:https://keras.io/zh/applications/   https://keras-cn.readthedocs.io/en/latest/other/application/ 官网上给出了使用 ResNet50 进行 ImageNet 分类的样例 from keras.applications.resnet50 import ResNet50 from keras.preprocess

keras中的shape/input_shape

在keras中,数据是以张量的形式表示的,张量的形状称之为shape,表示从最外层向量逐步到达最底层向量的降维解包过程.“维”的也叫“阶”,形状指的是维度数和每维的大小.比如,一个一阶的张量[1,2,3]的shape是(3,); 一个二阶的张量[[1,2,3],[4,5,6]]的shape是(2,3);一个三阶的张量[[[1],[2],[3]],[[4],[5],[6]]]的shape是(2,3,1) input_shape就是指输入张量的shape.例如,input_dim=784,dim是指

浅谈人脸识别中的loss 损失函数

浅谈人脸识别中的loss 损失函数 2019-04-17 17:57:33 liguiyuan112 阅读数 641更多 分类专栏: AI 人脸识别 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u012505617/article/details/89355690 在人脸识别中,算法的提高主要体现在损失函数的设计上,损失函数会对整个网络的优化有着导向性的作用.我们看到许多常用的损失函数

如何在python 深度学习Keras中计算神经网络集成模型

神经网络的训练过程是一个挑战性的优化过程,通常无法收敛. 这可能意味着训练结束时的模型可能不是稳定的或表现最佳的权重集,无法用作最终模型. 解决此问题的一种方法是使用在训练运行结束时看到的多个模型的权重平均值. 平均模型权重 学习深度神经网络模型的权重需要解决高维非凸优化问题. 解决此优化问题的一个挑战是,有许多“ 好的 ”解决方案,学习算法可能会反弹而无法稳定. 解决此问题的一种方法是在训练过程即将结束时合并所收集的权重.通常,这可以称为时间平均,并称为Polyak平均或Polyak-Rupp