news 2026/9/24 17:08:32

30天吃掉TensorFlow2:损失函数losses完全指南——从内置损失函数到自定义Focal Loss

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
30天吃掉TensorFlow2:损失函数losses完全指南——从内置损失函数到自定义Focal Loss
  • 教程
  • 深度学习
  • 机器学习

【免费下载链接】eat_tensorflow2_in_30_days

Tensorflow2.0 🍎🍊 is delicious, just eat it! 😋😋

项目地址:https://gitcode.com/gh_mirrors/ea/eat_tensorflow2_in_30_days
点击查看免费下载

eat_tensorflow2_in_30_days项目第五章(中阶 API)中,5-5,损失函数losses.md 系统讲解了深度学习目标函数的构成、Keras 内置损失函数的选择原则,以及两种自定义损失函数的实现范式。本文以该文档为骨架,结合仓库中 1-1,结构化数据建模流程范例.md、1-3,文本数据建模流程范例.md、1-4,时间序列数据建模流程范例.md、6-2,训练模型的3种方法.md 等章节中的真实调用代码,深入讲解回归、二分类、多分类场景下的损失函数选型,并给出可直接复制运行的 Focal Loss 自定义实现。读完本文,你将掌握:如何在model.compile与自定义训练循环中正确指定损失函数、如何理解正则化项与约束项在目标函数中的作用,以及如何用函数式和类式两种写法实现自己的损失函数。

一、目标函数的构成:损失函数 + 正则化项

监督学习的目标函数一般由损失函数(Loss)和正则化项(Regularization)两部分组成:

Objective = Loss + Regularization

其中损失函数衡量模型预测与真实标签之间的差距,是梯度下降优化的直接对象;而正则化项则是对模型复杂度施加的惩罚,用于抑制过拟合。两者共同决定了模型参数的最优方向。

1.1 正则化项在层中指定

对于 Keras 模型,目标函数中的正则化项一般在各层内部指定,而不是在编译阶段传入。以layers.Dense为例,常用的正则化相关参数有:

  • kernel_regularizer:对权重矩阵 W 施加正则化,如regularizers.l1(0.01)regularizers.l2(0.01)regularizers.l1_l2(l1, l2)
  • bias_regularizer:对偏置向量 b 施加正则化;
  • activity_regularizer:对层输出(激活后的值)施加正则化;
  • kernel_constraint/bias_constraint:约束权重或偏置的取值范围,例如constraints.MaxNorm(max_value=2, axis=0)将每个权向量的范数限制在 2 以内。这同样是一种正则化手段,通过在优化迭代中把参数投影回约束域来实现。

以下是原文档给出的完整示例,构造了一个带多种正则化与约束的两层网络,并以binary_crossentropy作为损失函数、AUC作为评估指标完成编译:

import numpy as np import pandas as pd import tensorflow as tf from tensorflow.keras import layers, models, losses, regularizers, constraints tf.keras.backend.clear_session() model = models.Sequential() model.add(layers.Dense(64, input_dim=64, kernel_regularizer=regularizers.l2(0.01), activity_regularizer=regularizers.l1(0.01), kernel_constraint=constraints.MaxNorm(max_value=2, axis=0))) model.add(layers.Dense(10, kernel_regularizer=regularizers.l1_l2(0.01, 0.01), activation="sigmoid")) model.compile(optimizer="rmsprop", loss="binary_crossentropy", metrics=["AUC"]) model.summary()

输出(模型结构示意,两个全连接层合计 4810 个可训练参数):

Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense (Dense) (None, 64) 4160 _________________________________________________________________ dense_1 (Dense) (None, 10) 650 ================================================================= Total params: 4,810 Trainable params: 4,810 Non-trainable params: 0 _________________________________________________________________

要点:正则化项绑定在层上、随层一起序列化保存;而损失函数则在model.compile(loss=...)时统一指定。二者职责分离,这是 Keras 目标函数设计的基本约定。

1.2 损失函数在编译时指定

损失函数在模型编译(compile)时指定,针对不同任务有明确的选择惯例:

任务类型推荐损失函数说明
回归mean_squared_error(mse)均方误差,衡量预测值与真实值平方差的均值
二分类binary_crossentropy二元交叉熵
多分类(label 为 one-hot 编码)categorical_crossentropy类别交叉熵
多分类(label 为类别序号编码)sparse_categorical_crossentropy稀疏类别交叉熵

多分类任务中,标签编码方式直接决定损失函数的选择:one-hot 编码(如[0,1,0,0])配categorical_crossentropy整数序号编码(如2)配sparse_categorical_crossentropy,两者计算等价,只是输入形式不同。

二、内置损失函数:类的实现与函数的实现

Keras 内置损失函数一般有类实现函数实现两种形式。例如CategoricalCrossentropycategorical_crossentropy都是类别交叉熵,前者是类(tf.keras.losses.CategoricalCrossentropy),后者是函数(tf.keras.losses.categorical_crossentropy)。类实现可以携带状态与配置、支持序列化,通常在自定义训练循环中作为对象调用;函数实现更轻量,适合直接传入compile或低阶 API。

原文档列出的常用内置损失函数整理如下:

损失函数用途简写类实现 / 函数实现
mean_squared_error回归,均方误差mse/MSEMeanSquaredError
mean_absolute_error回归,平均绝对误差mae/MAEMeanAbsoluteError
mean_absolute_percentage_error回归,平均百分比误差mape/MAPEMeanAbsolutePercentageError
Huber回归,介于 mse 与 mae 之间,对异常值鲁棒仅类实现Huber
binary_crossentropy二分类,二元交叉熵BinaryCrossentropy
categorical_crossentropy多分类(label one-hot)CategoricalCrossentropy
sparse_categorical_crossentropy多分类(label 序号编码)SparseCategoricalCrossentropy
hinge二分类,SVM 经典损失(合页损失)Hinge
kld相对熵(KL 散度),度量两个概率分布差异,常用于 EM 类算法KLDivergence/KLD
cosine_similarity余弦相似度,可用于多分类CosineSimilarity

2.1 仓库中的实际用法印证

这些内置损失在项目各实战章节中均有直接调用,可相互印证:

  • 回归:3-3,高阶API示范.md 中model.compile(optimizer="adam", loss="mse", metrics=["mae"])以字符串形式传入 mse;6-6,使用tensorflow-serving部署模型.md 中线性回归模型同样使用loss="mse"
  • 二分类:1-1,结构化数据建模流程范例.md 中泰坦尼克生存预测使用loss='binary_crossentropy', metrics=['AUC'],与本文示例配置一致。
  • 多分类:6-4,使用多GPU训练模型.md 与 6-5,使用TPU训练模型.md 中均使用类实现losses.SparseCategoricalCrossentropy(from_logits=True),并显式声明from_logits=True——当网络最后一层是线性输出(未经过 softmax)时,必须开启该参数,让交叉熵在内部完成 softmax 计算,数值上更稳定。

2.2 在自定义训练循环中使用类实现

内置损失函数的类实现可以直接作为对象在tf.GradientTape中调用。1-3,文本数据建模流程范例.md 展示了 IMDb 文本分类中losses.BinaryCrossentropy()的完整用法:

optimizer = optimizers.Nadam() loss_func = losses.BinaryCrossentropy() train_loss = metrics.Mean(name='train_loss') train_metric = metrics.BinaryAccuracy(name='train_accuracy') @tf.function def train_step(model, features, labels): with tf.GradientTape() as tape: predictions = model(features, training=True) loss = loss_func(labels, predictions) gradients = tape.gradient(loss, model.trainable_variables) optimizer.apply_gradients(zip(gradients, model.trainable_variables)) train_loss.update_state(loss) train_metric.update_state(labels, predictions)

这里loss_func作为可调用对象接收(labels, predictions)返回标量损失,与metrics.Mean配合在批次间累加平均,构成一个完整的中阶 API 自定义训练循环。

三、自定义损失函数:函数式与类式两种范式

当内置损失无法满足需求时,Keras 支持两种自定义方式,二者的共同接口约定是:接收两个张量y_truey_pred作为输入,输出一个标量作为损失值

3.1 函数式定义

直接编写一个接收(y_true, y_pred)、返回标量的函数即可,函数闭包可以捕获超参数:

def focal_loss(gamma=2., alpha=0.75): def focal_loss_fixed(y_true, y_pred): bce = tf.losses.binary_crossentropy(y_true, y_pred) p_t = (y_true * y_pred) + ((1 - y_true) * (1 - y_pred)) alpha_factor = y_true * alpha + (1 - y_true) * (1 - alpha) modulating_factor = tf.pow(1.0 - p_t, gamma) loss = tf.reduce_sum(alpha_factor * modulating_factor * bce, axis=-1) return loss return focal_loss_fixed

3.2 类式定义:继承tf.keras.losses.Loss

tf.keras.losses.Loss进行子类化,重写call方法实现损失计算逻辑,即可得到带配置能力的类实现:

class FocalLoss(tf.keras.losses.Loss): def __init__(self, gamma=2.0, alpha=0.75, name="focal_loss"): self.gamma = gamma self.alpha = alpha def call(self, y_true, y_pred): bce = tf.losses.binary_crossentropy(y_true, y_pred) p_t = (y_true * y_pred) + ((1 - y_true) * (1 - y_pred)) alpha_factor = y_true * self.alpha + (1 - y_true) * (1 - self.alpha) modulating_factor = tf.pow(1.0 - p_t, self.gamma) loss = tf.reduce_sum(alpha_factor * modulating_factor * bce, axis=-1) return loss

两种写法计算逻辑完全一致;类式实现额外具备name标识,便于在compile、TensorBoard 与模型保存中区分。

3.3 Focal Loss 的原理与参数含义

Focal Loss 是对binary_crossentropy的一种改进,在样本不均衡且存在大量易分类样本的场景下,相比普通二元交叉熵具有明显优势。它引入两个可调参数:

  • alpha:主要用于衰减负样本的权重(默认0.75,偏向正样本);
  • gamma:主要用于衰减容易训练样本的权重(默认2.0)。

通过二者配合,模型将注意力聚焦在正样本困难样本上——这正是 "Focal"(聚焦)名称的由来。其数学定义如下:

$$ focal_loss(y,p) = \begin{cases} -\alpha (1-p)^{\gamma}\log(p) & \text{if y = 1}\ -(1-\alpha) p^{\gamma}\log(1-p) & \text{if y = 0} \end{cases} $$

对照代码理解:p_t表示样本被正确分类的概率(y=1时取py=0时取1-p);modulating_factor = (1-p_t)^gamma是调制因子,样本越易分类(p_t越接近 1)其惩罚越小,从而压低易样本的贡献;alpha_factor则按标签类别加权,实现正负样本的平衡。

3.4 仓库中的自定义损失实例:MSPE

自定义损失在仓库中有多处真实应用。1-4,时间序列数据建模流程范例.md 为新冠新增病例预测定义了 MSPE(平均平方百分比误差),并实现了get_config以保证可序列化:

# 自定义损失函数,考虑平方差和预测目标的比值 class MSPE(losses.Loss): def call(self, y_true, y_pred): err_percent = (y_true - y_pred)**2 / (tf.maximum(y_true**2, 1e-7)) mean_err_percent = tf.reduce_mean(err_percent) return mean_err_percent def get_config(self): config = super(MSPE, self).get_config() return config

随后以model.compile(optimizer=optimizer, loss=MSPE(name="MSPE"))的方式传入编译(1-4,时间序列数据建模流程范例.md),并在模型加载后(第570行)复用同一损失完成评估。注意其中tf.maximum(y_true**2, 1e-7)的写法是为了防止除零,这是自定义损失函数中常见的数值稳定性处理技巧,与 Focal Loss 中的实现细节异曲同工。

四、损失函数在三种训练范式中的接入方式

结合 6-2,训练模型的3种方法.md 的划分,损失函数在 Keras 的三种训练范式中接入位置不同,本质却一致:

  1. 内置训练(model.fit:损失在compile阶段传入,字符串、函数、类实例三者皆可,如 5-4,模型层layers.md 的model.compile(optimizer="sgd", loss="mse", metrics=["mae"])
  2. 自定义训练循环(tf.GradientTape:损失作为对象在每一步前向传播中手动计算,如 1-3,文本数据建模流程范例.md 所示;
  3. 中阶 API 方式(model.loss_func属性):3-2,中阶API示范.md 将losses.mean_squared_errorlosses.binary_crossentropy赋值给模型的loss_func属性,在自定义的train_step中调用(第112行、第294行),实现"半内置半自定义"的训练流程。

五、小结与延伸阅读

本仓库的 eat_tf2_ebook.md 收录了全部章节的合订内容(其中 MSPE、SparseCategoricalCrossentropy(from_logits=True)loss="mse"等用法均与各章节一一对应),english/Chapter5-5.md 提供了本章的英文版本,适合对照阅读。

核心结论回顾

  1. 目标函数 = 损失函数 + 正则化项;正则化(*_regularizer*_constraint)在层中声明,损失函数在compile时指定;
  2. 选型口诀:回归用mse,二分类用binary_crossentropy,多分类依据标签编码选择categorical_crossentropy(one-hot)或sparse_categorical_crossentropy(序号);
  3. 内置损失有类/函数双实现,类实现支持状态、配置与序列化,适合自定义训练循环;
  4. 自定义损失只需实现(y_true, y_pred) -> scalar,函数式适合快速原型,继承tf.keras.losses.Loss重写call(可选实现get_config)适合正式项目;Focal Loss 通过alpha平衡正负样本、gamma聚焦困难样本,是样本不均衡场景下的首选改造方向。
  • 教程
  • 深度学习
  • 机器学习

【免费下载链接】eat_tensorflow2_in_30_days

Tensorflow2.0 🍎🍊 is delicious, just eat it! 😋😋

项目地址:https://gitcode.com/gh_mirrors/ea/eat_tensorflow2_in_30_days
点击查看免费下载

相关推荐

上一篇:如何快速上手Factorie:构建概率模型的完整指南
下一篇:终极指南:如何生成专业的LZ4测试报告并集成JUnit与CI

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 17:02:52

大麦自动抢票指南:Python Selenium + Appium 双端抢票脚本完整教程

大麦自动抢票指南:Python Selenium Appium 双端抢票脚本完整教程 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase ticket-purchase 是一…

作者头像 李华
网站建设 2026/9/24 17:01:00

高速传输灵活交付 金士顿移动存储赋能项目全周期数据流转迁移

乙方项目归档交付应包含完整项目的原始素材、源文件、多版迭代稿件、最终成片与交付文档等等。而实际上,很多行业往往需要混合办公、跨地协作,依托网盘存储看似便利实际暗藏隐患,不仅容易出现版本错乱、链接过期、文件压缩损坏、画质音质失真…

作者头像 李华