keras中的loss、optimizer、metrics用法

作者:wyf 时间:2022-06-15 15:53:07 

用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

标签:keras,loss,optimizer,metrics
0
投稿

猜你喜欢

  • MIME Type 引出的两难困境

    2011-06-14 09:45:41
  • 在python的类中动态添加属性与生成对象

    2021-04-27 00:26:59
  • go日志库logrus的安装及快速使用

    2024-04-26 17:31:40
  • Python查找第n个子串的技巧分享

    2023-02-20 22:02:55
  • python爬虫用mongodb的理由

    2023-09-27 23:06:40
  • python的pytest框架之命令行参数详解(下)

    2021-04-19 17:23:48
  • go学习笔记读取consul配置文件详解

    2024-05-09 10:08:14
  • Golang HTTP服务超时控制实现原理分析

    2024-05-08 10:52:16
  • pytorch 更改预训练模型网络结构的方法

    2022-04-02 04:41:19
  • Yahoo!网站性能最佳体验的34条黄金守则——JavaScript和CSS

    2008-05-29 13:34:00
  • Python pip安装模块提示错误解决方案

    2022-03-07 02:26:27
  • 网站中视觉元素的设计

    2008-04-27 20:47:00
  • QCon大会散记

    2010-05-03 14:19:00
  • SQL 查询性能优化 解决书签查找

    2024-01-28 08:33:53
  • SQL Server的基本功能性语句介绍

    2024-01-19 20:33:02
  • 在IPython中执行Python程序文件的示例

    2023-02-20 09:06:14
  • 详解pytest分布式执行插件 pytest-xdist 的高级用法

    2022-11-04 21:41:51
  • 详解Python中常用的激活函数(Sigmoid、Tanh、ReLU等)

    2022-03-25 22:45:51
  • python使用opencv在Windows下调用摄像头实现解析

    2021-01-08 04:13:01
  • 解决Python字典查找报Keyerror的问题

    2021-05-07 00:53:55
  • asp之家 网络编程 m.aspxhome.com