网上服装商城网站建设方案策划书seo快排公司哪家好
前言
有时候,我们需要往模型里面添加一些自定义的loss。
这些自定义的loss主要分为两大类:
- loss是基于样本的正确标签 yrealy_{real}yreal 和预测的logit ypredy_{pred}ypred 计算得到。这种loss主要集中在对分类损失的改进上,例如Focal Loss等。
- loss需要模型的中间层信息参与运算。这种loss常见的就是对权重的正则化项,高级一点还有对抗机器学习里面的FGSM的对抗学习正则化项。
其中,第一类loss可以通过自定义loss函数,或者loss类,然后在模型compile的时候指定损失就可以了。
第二类loss则不能通过模型compile()函数来指定,而需要调用add_loss()
函数来指定。
第一类loss必须能够通过yrealy_{real}yreal 和 ypredy_{pred}ypred,以及某些额外的超参数 得到计算得到。
这种函数的输入是两个参数yrealy_{real}yreal 和 ypredy_{pred}ypred, 输出是一个tensor,tensor的必须得是对每个样本都输出一个值。
定义好之后,在model的compile里面指定就是了。
例如:
alpha1=0.2
alpha2=0.5
def custom_loss_function(y_true, y_pred):squared_difference = tf.square(y_true - y_pred)##如果计算过程需要用上超参数,则先在全局作用域定义超参数,然后在函数里面直接使用这些超参数。return tf.reduce_mean(squared_difference, axis=-1)model.compile(optimizer='adam', loss=custom_loss_function)
再比如 Focal Loss的定义:
其中γ\gammaγ 是一个超参数,用于调和loss,我们可以在实现的时候把它定义为一个全局的参数,然后再函数里面使用它就可以了。
第二类loss则是需要神经网络本身参与计算,例如L2正则化啥的。
这类loss的定义,一般是在网络搭建的后面,因为这些loss的计算能够方便的访问到中间层的输出或权重。
这种loss没有像第一类loss一样有输入输出的约定,loss一般就是用某个函数封装的任意计算图。
定义好loss之后,把调用模型的add_loss
函数把这部分计算图加到模型即可。
compile里面指定的loss和add_loss指定的loss的关系:
在keras的model.compile函数源码中可以看到如下的代码:
with K.name_scope('loss'):for i in range(len(self.outputs)):if i in skip_target_indices:continuey_true = self.targets[i]y_pred = self.outputs[i]weighted_loss = weighted_losses[i]sample_weight = sample_weights[i]mask = masks[i]loss_weight = loss_weights_list[i]with K.name_scope(self.output_names[i] + '_loss'):output_loss = weighted_loss(y_true, y_pred,sample_weight, mask)if len(self.outputs) > 1:self.metrics_tensors.append(output_loss)self.metrics_names.append(self.output_names[i] + '_loss')if total_loss is None:total_loss = loss_weight * output_losselse:total_loss += loss_weight * output_lossif total_loss is None:if not self.losses:raise ValueError('The model cannot be compiled ''because it has no loss to optimize.')else:total_loss = 0.# Add regularization penalties# and other layer-specific losses.for loss_tensor in self.losses:total_loss += loss_tensor
前面是计算compile里面指定的loss,然后再把self.losses
里面损失加起来。
而self.losses
就是模型(包括它使用到所有层)通过add_loss
函数添加的损失。