百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

深度学习中的损失函数(deepfm损失函数)

toyiye 2024-07-05 01:41 25 浏览 0 评论

前言

你可以用神经网络来完成各种各样的任务,比如对数据进行分类,把动物图片分成猫和狗,或者做回归任务,预测每个月的收入等等。不同的任务有不同的输出,也需要用不同类型的损失函数来评估。

损失函数的选择会影响算法的性能。如果你能正确地设置损失函数,你的模型就能按照你的期望运行。

幸运的是,我们可以根据机器学习任务的特点来选择合适的损失函数。

本文将介绍深度学习中常用的损失函数,以及如何构建自定义损失函数。读完本文,你应该能够为你的项目挑选合适的损失函数。

什么是损失函数?

在我们介绍损失函数的具体内容之前,让我们回顾一下损失函数的概念。

损失函数是用来衡量预测输出和给定的目标值之间的差距。损失函数告诉我们算法模型离达到预期结果还差多少。“损失”一词意味着模型因为没有产生预期结果而要承担的代价。

例如,一个损失函数(我们用J表示)可以接受以下两个参数:

预测输出(y_pred) 目标值(y)


神经网络损失函数的图示


这个函数会通过比较模型的预测输出和期望输出来评估模型的性能。如果y_pred和y之间的差距很大,那么损失值就会很高。

如果差距很小或者值几乎相等,那么损失值就会很低。因此,你需要使用一个能够在模型训练时根据数据集的情况给予适当惩罚的损失函数。

损失函数会根据算法要解决的问题的性质而有所不同。因此为了解决不同类别的问题,应选择不同类别的损失函数。

损失函数的分类

损失函数大致可以广义地分为 3 种类型:分类损失 回归损失 排名损失

当模型预测连续值(如人的年龄)时,将使用回归损失函数。 当模型预测离散值(例如电子邮件是否为垃圾邮件)时,将使用分类损失函数。 当模型预测输入之间的相对距离时,将使用排名损失函数,例如根据产品在电子商务搜索页面上的相关性对产品进行排名。

现在我们将探讨 PyTorch 中不同类型的损失函数,进行可视化展示以理解,并且给出使用方法:

分类损失(待完成)

回归损失

平均绝对误差损失 MAE Loss/L1 Loss(Mean Absolute Error Loss/L1 Loss)

平均绝对误差是目标变量和预测变量之间的绝对误差的平均值,它反映了预测的准确性,而不考虑误差的正负。平均绝对误差的取值范围是从 0 到无穷大,越接近 0 表示预测越准确。

从零实现并可视化平均绝对误差损失

import matplotlib.pyplot as plt
import numpy as np

# 定义平均绝对误差损失函数
def mae_loss(y_true, y_pred):
  return np.mean(abs(y_true - y_pred))

# 定义真值
y_true = 0

# 定义预测值的取值区间与频率
x = np.linspace(-10000, 10000, 100)

# 计算对每个预测值的均方误差损失值
y = [mae_loss(y_true, x[i]) for i in range(len(x))]
#列表推导是从另一个可迭代对象(如列表、元组、范围等)创建列表的简洁方法。列表推导的一般语法为:
#[expression for item in iterable if condition]
#这将通过将表达式应用于满足条件的可迭代对象中的每个项目来创建新列表。该条件是可选的,可以省略。

#等价于:
# for i in range(len(x)):
#   y.append(mae_loss(y_true, x[i]))
#.append 加元素到列表末尾


# 绘制损失函数
plt.plot(x, y)
plt.xlabel("Predictions")
plt.ylabel("MAE Loss")
plt.title("MAE Loss vs Predictions")
plt.show()


平均绝对误差损失(Y轴)与预测值(X轴)的关系图


均方误差损失 MSE Loss(Mean Squared Error Loss)

均方误差 (MSE) 是最常用的回归损失函数。MSE 是目标变量和预测值之间的平方距离之和。

L_{MSE} = \frac{1}{n} \sum_{i=1}^n (y_i - \hat{y}_i)^2

其中 $n$ 是样本数量,$y_i$ 是第 $i$ 个样本的真实值,$\hat{y}_i$ 是第 $i$ 个样本的预测值。

另一种可能的写法是:

L_{MSE} = \frac{1}{n} \| y - \hat{y} \|^2

其中 $y$$\hat{y}$ 是真实值和预测值的向量,$\| \cdot \|$ 表示欧几里得范数。

从零实现并可视化均方误差损失

import matplotlib.pyplot as plt
import numpy as np

# Define the MSE loss function
def mse_loss(y_true, y_pred):
  return np.mean((y_true - y_pred) ** 2)

# Define the true value
y_true = 0

# Define the range of predictions
x = np.linspace(-10000, 10000, 100)

# Compute the MSE loss for each prediction using a list comprehension
y = [mse_loss(y_true, x[i]) for i in range(len(x))]
#列表推导是从另一个可迭代对象(如列表、元组、范围等)创建列表的简洁方法。列表推导的一般语法为:
#[expression for item in iterable if condition]
#这将通过将表达式应用于满足条件的可迭代对象中的每个项目来创建新列表。该条件是可选的,可以省略。

#等价于:
# for i in range(len(x)):
#   y.append(mse_loss(y_true, x[i]))
#.append 加元素到列表末尾


# Plot the loss function
plt.plot(x, y)
plt.xlabel("Predictions")
plt.ylabel("MSE Loss")
plt.title("MSE Loss vs Predictions")
plt.show()

均方误差损失(Y轴)与预测值(X轴)的关系图


均方根误差 RMSE()

RMSE 是均方根误差的英文缩写,它是一种衡量预测值和真实值之间差异的指标。RMSE 是均方误差(MSE)的平方根,MSE 是预测值和真实值之差的平方的平均值。RMSE 越小,说明预测值和真实值越接近,模型的拟合效果越好。均方根误差是与平均绝对误差处于相同的尺度,这方便了我们后续对平均绝对误差与均方误差的比较。

RMSE 的计算公式如下:

RMSE = \sqrt{\frac{1}{n} \sum_{i=1}^n (y_i - \hat{y}_i)^2}

其中 $n$ 是样本数量,$y_i$ 是第 $i$ 个样本的真实值,$\hat{y}_i$ 是第 $i$ 个样本的预测值。

另一种写法是:

RMSE = \sqrt{\frac{1}{n} \| y - \hat{y} \|^2}

其中 $y$$\hat{y}$ 是真实值和预测值的向量,$\| \cdot \|$ 表示欧几里得范数。

从零实现并可视化均方根误差损失函数

import matplotlib.pyplot as plt
import numpy as np
import math

# Define the MAE loss function
def RMSE_loss(y_true, y_pred):
  return math.sqrt(np.mean((y_true - y_pred)**2))

# Define the true value
y_true = 0

# Define the range of predictions
x = np.linspace(-10000, 10000, 100)

# Compute the RMSE loss for each prediction using a list comprehension
y = [RMSE_loss(y_true, x[i]) for i in range(len(x))]
#列表推导是从另一个可迭代对象(如列表、元组、范围等)创建列表的简洁方法。列表推导的一般语法为:
#[expression for item in iterable if condition]
#这将通过将表达式应用于满足条件的可迭代对象中的每个项目来创建新列表。该条件是可选的,可以省略。

#等价于:
# for i in range(len(x)):
#   y.append(mae_loss(y_true, x[i]))
#.append 加元素到列表末尾


# Plot the loss function
plt.plot(x, y)
plt.xlabel("Predictions")
plt.ylabel("RMSE Loss")
plt.title("RMSE Loss vs Predictions")
plt.show()

均方根误差损失函数(Y轴)与预测值(X轴)的关系图


对平均绝对误差损失函数,与均方误差损失函数的分析

简而言之,使用使用平方误差更容易求解,但使用绝对误差对异常值更可靠。但是为什么?

在训练机器学习模型时,我们的目标都是找到最小化损失函数的点。当然,当预测完全等于真实值时,这两个函数都达到最小值。

我们来比较一下两种情况下的 MAE 和 RMSE(它是 MSE 开平方,使它和 MAE 在同一量级)的数值。在第一种情况下,预测值和真实值很接近,误差的方差很小。在第二种情况下,有一个异常的观测值,误差很大。

左: 错误彼此接近 右: 与其他错误相比,一个错误相差甚远


我们从中观察到什么,它如何帮助我们选择使用哪个损失函数?

MSE 是对误差(y — y_predicted = e)的平方,所以如果 e > 1,误差(e)就会放大很多。如果我们的数据里有一个离群值,那么 e 就会很大,e2 就会更大。这样一来,用 MSE 作为损失函数的模型就会比用 MAE 作为损失函数的模型更倾向于拟合离群值。在上面的第二种情况中,用 RMSE 作为损失函数的模型会为了减小一个离群值的影响而牺牲其他正常的样本,这会降低它的整体性能。

如果训练数据被离群值污染了(也就是说,在训练环境中我们错误地收到了一些不切实际的极大或极小的值,而在测试环境中没有),那么 MAE 损失就很有用。

直观地说,我们可以这样理解:如果我们要用一个预测值来拟合所有试图最小化 MSE 的观测值,那么这个预测值应该是所有目标值的均值。但是,如果我们要最小化 MAE,那么这个预测值应该是所有观测值的中位数。我们知道中位数对离群值的抗干扰能力比均值强,所以 MAE 对离群值的抗干扰能力也比 MSE 强。

使用 MAE 损失(特别是对于神经网络)有一个很大的问题,就是它的梯度始终是一样的,这意味着即使损失值很小,梯度也很大。这对学习不利。为了解决这个问题,我们可以使用动态学习率,当我们接近最优解时,动态学习率会变小。在这种情况下,MSE 就表现得很好,即使用固定的学习率也能收敛。对于较大的损失值,MSE 损失的梯度较高,当损失接近 0 时变小,使得在训练结束时更加精确(见下图)。


选择使用哪个损失函数

应结合具体问题的实践,选择合适的损失函数。

如果离群值对实际问题很重要,需要检出,那么应该用 MSE 作为损失函数。反之,如果我们认为离群值只是数据损坏的表现,那么应该用 MAE 作为损失函数。

L1 vs. L2 Loss function – Rishabh Shukla (rishy.github.io),这篇文章对使用 L1 损失和 L2 损失的回归模型在有无离群值的情况下的性能进行了比较。文中,L1 损失和 L2 损失就是 MAE 和 MSE 的别名。

L1 损失对离群值更鲁棒,但它的导数不连续,所以求解效率低。L2 损失对离群值很敏感,但它有更稳定和封闭的解(通过令导数为 0 得到)。

两者的问题:在某些实际应用场景下,这两种损失函数都不能给出理想的预测。

比如说,如果我们的数据中 90% 的观测值的真实目标值是 150,剩下 10% 的目标值在 0-30 之间。那么,用 MAE 作为损失函数的模型可能会把所有观测值都预测为 150,忽略了 10% 的离群情况,因为它会试图接近中位数。同样的情况下,用 MSE 的模型会给出很多在 0 到 30 范围内的预测,因为它会偏向于离群值。在很多实际应用场景中,这两种结果都不是我们想要的。

那么这种情况怎么办呢?一个简单的办法是对目标变量进行转换。另一个办法是尝试不同的损失函数。这就引出了我们的第三种损失函数:平滑平均绝对误差

平滑平均绝对误差(Huber Loss)

平滑平均绝对误差损失函数比平方误差损失函数更不受离群值的影响。它在 0 点也是可导的。它基本上是绝对误差,但当误差很小的时候,它就变成了平方误差。误差多小才算很小,取决于一个可以调节的超参数 δ(delta)。当 δ 接近 0 时,Huber 损失和 MSE 很像,当 δ 很大时,Huber 损失和 MAE 很像。

import matplotlib.pyplot as plt
import numpy as np
import math
#import torch
# Define the smooth_MAE loss function

def smooth_mae_loss(y_true, y_pred, delta=1.0):
    diff = np.abs(y_true - y_pred)
    mask = diff < delta
    return np.where(mask, diff - 0.5 * delta, 0.5 * diff ** 2 / delta)

# Define the true value
y_true = 0

# Define the range of predictions
x = np.linspace(-10, 10, 100)

# Define the list of delta values
deltas = [0.1, 1, 10]

# Define the list of colors or linestyles for plotting
colors = ["r", "g", "b"]
linestyles = ["-", "--", "-."]

# Plot the loss function for each delta value
plt.figure()
for i in range(len(deltas)):
    # Compute the smooth_MAE loss for each prediction using a list comprehension
    y = [smooth_mae_loss(y_true, x[j], delta=deltas[i]) for j in range(len(x))]
    # Plot the loss function with the corresponding color and linestyle
    plt.plot(x, y, color=colors[i], linestyle=linestyles[i], label=f"delta={deltas[i]}")
plt.xlabel("Predictions")
plt.ylabel("Smooth MAE Loss")
plt.title("Smooth MAE Loss vs Predictions")
plt.legend()
plt.show()

Y:平滑平均绝对误差,X:预测值


δ 的选择很重要,因为它决定了我们把哪些误差看作是离群值。误差大于 δ 的时候,用 L1 损失来最小化(对大的离群值不敏感),误差小于 delta 的时候,用 L2 损失来最小化(对小的误差更精确)。

为什么要使用平滑平均绝对误差损失函数? 使用 MAE 训练神经网络有一个很大的问题,就是它的梯度一直很大,这可能导致在用梯度下降法训练结束时错过最优解。对于 MSE,当损失接近最优解时,梯度变小,使得训练更加精确。

在这种情况下,平滑平均绝对误差损失函数就很有用,因为它在最优解附近变平滑,从而减小梯度。而且它比 MSE 更能抵抗离群值的干扰。所以,它结合了 MSE 和 MAE 的优点。不过,平滑平均绝对误差损失函数的问题是我们可能需要调整超参数 delta,这是一个反复试验的过程。

对数损失函数 Log-cosh Loss

对数损失函数是预测值和真实值之间差异的双曲余弦的对数的平均值,它比 L2 更平滑。它的公式如下:

L(y, \hat{y}) = \sum_{i=1}^n \log(\cosh(y_i - \hat{y}_i))

其中,$y$是真实值,$\hat{y}$是预测值,$n$是样本数量。

Log-cosh loss的含义是:

  • 当预测值和真实值之间的差异很小(接近0)时,log-cosh loss近似于平方损失(MSE),即$\log(\cosh(x)) \approx \frac{x^2}{2}$。这时,log-cosh loss对小误差有较大的惩罚,可以提高模型的精度。
  • 当预测值和真实值之间的差异很大(远离0)时,log-cosh loss近似于绝对损失(MAE),即$\log(\cosh(x)) \approx |x| - \log(2)$。这时,log-cosh loss对大误差有较小的惩罚,可以提高模型的鲁棒性。

因此,log-cosh loss可以看作是平方损失和绝对损失的折中,既能保证模型的精度,又能抵抗异常值的影响。

绘制对数损失函数的图形

import matplotlib.pyplot as plt
import numpy as np
import math

# Define the MAE loss function
def log_cosh_loss(y_true, y_pred):
  return np.log(np.cosh(y_true-y_pred))

# Define the true value
y_true = 0

# Define the range of predictions
x = np.linspace(-10, 10, 100)

# Compute the RMSE loss for each prediction using a list comprehension
y = [log_cosh_loss(y_true, x[i]) for i in range(len(x))]


# Plot the loss function
plt.plot(x, y)
plt.xlabel("Predictions")
plt.ylabel("RMSE Loss")
plt.title("RMSE Loss vs Predictions")
plt.show()

log-cosh主要像均方误差一样工作,但不会被偶尔出现的非常大的误差所影响。它具有 Huber 损失的所有优点,而且和 Huber 损失不同的是,它在任何地方都可以求二阶导数。log(cosh(x))(x ** 2) / 2xabs(x) - log(2)x

为什么我们需要二阶导数?许多像 XGBoost 这样的 ML 模型实现都使用牛顿法来寻找最优解,这就需要用到二阶导数(Hessian)。对于像 XGBoost 这样的 ML 框架来说,能求二阶导数的函数更有利。

XgBoost中使用的目标函数。注意对一阶和二阶导数的依赖性


分位数损失 Quantile Loss (未完成)

分位数损失是一种用于解决回归问题的损失函数,它是预测值和真实值之间差异的绝对值乘以一个分位数权重的平均值。它的公式如下:

分位数损失的含义是:

  • 当预测值和真实值之间的差异为正(即预测值大于真实值)时,分位数损失函数乘以一个正的权重$\tau$,这个权重表示了对高估的惩罚程度。当$\tau$接近1时,高估的惩罚很大;当$\tau$接近0时,高估的惩罚很小。
  • 当预测值和真实值之间的差异为负(即预测值小于真实值)时,分位数损失函数乘以一个负的权重$\tau - 1$,这个权重表示了对低估的惩罚程度。当$\tau$接近1时,低估的惩罚很小;当$\tau$接近0时,低估的惩罚很大。

因此,分位数损失可以看作是一种灵活的损失函数,它可以根据不同的分位数参数来调整对高估和低估的偏好3。

在深度学习中,分位数损失有一些应用,例如:

  • 可以用于变分自编码器(VAE)中,来提高输出质量和不确定性量化。
  • 可以用于二分类问题中,来估计条件分位数和置信区间。
  • 可以用于时间序列预测中,来提高模型的鲁棒性和稳定性。

排名损失

相关推荐

「2022 年」崔庆才 Python3 爬虫教程 - 代理的使用方法

前面我们介绍了多种请求库,如urllib、requests、Selenium、Playwright等用法,但是没有统一梳理代理的设置方法,本节我们来针对这些库来梳理下代理的设置方法。1.准备工作...

Python 3 基础教程 - 函数(python基础函数大全)

函数是一组有组织的、可重用的代码,用于执行单个相关操作。函数为应用程序提供更好的模块化和高度的代码重用。Python提供了许多内置函数,如print()等。也可以创建自己的函数。这些函数称为用户...

Python3.7.4图文安装教程(python3.7详细安装教程)

Python更新的很快,一转眼Python2已经过时了,本文为大家详细说明Python最新版本3.7.4的安装过程,跟着步骤一步一步操作,轻松搞定安装。没有软件可以关注我头条私信我1、下载好后是一个压...

非程序员的其他从业者,三天可入门Python编程,附教程与相应工具

这是一种应用十分广泛的编程语言Python,它打破了只有程序员才能编程的“戒律”,尤其是近年来国家予以Python编程的支持,让这门语言几乎应用到各种工作中。那么对于并不是职业程序员的人,该如何才能快...

008 - 匿名函数lambda-python3-cookbook中文教程

有名函数通过def来定义有一个有名字的函数。defmyfun():return1,2,3...

花了3万多买的python教程全套,现在分享给大家(python全栈)

花了3万多买的Python教程全套,现在分享给大家(Python全栈)文末惊喜记得看完哦。...

花来3万多买的python教程全套,现在分享给大家(python全栈)

花了3万多买的Python教程全套,现在分享给大家(Python全栈)文末惊喜记得看完哦。...

Python3最新版安装教程(Windows)(python3.7.0安装教程win10)

接下来给大家讲解一下python最新安装包的安装教程。·首先大家可以去这里搜索一下我的笔记,大概讲了一下,然后找到它的官网,下载的是windows,可以看一下最新的版本。·选择64位,点击下载就即可了...

笨办法学python3》再笨的人都能学会python,附PDF,拿走不谢

《笨办法学python3》这本书的最终目标是让你起步python编程,虽然说是用“笨办法”学习写程序,但是其实并不是这样的。所谓的“笨办法”就是指这本书的教学方式,也就是“指令式”的教学,在这个过程中...

python3 (1)(python312)

Python3Introduction:LearnthebasicsofPython3programming,withitskeyfeatures,andprovideyo...

Python3 教程-- 3、解释器(python3菜鸟教程官网)

Python3解释器Python解释器Linux/Unix的系统上,Python解释器通常被安装在/usr/local/bin/python3.4这样的有效路径(目录)里。我们可以将路径/us...

《笨办法学python3》再笨的人都能学会python,附PDF,拿走不谢

《笨办法学python3》这本书的最终目标是让你起步python编程,虽然说是用“笨办法”学习写程序,但是其实并不是这样的。所谓的“笨办法”就是指这本书的教学方式,也就是“指令式”的教学,在这个过程中...

入门经典!《Python 3程序开发指南》python学习教程赠送!

《Python3程序开发指南》(????)??嗨!你们的小可爱又来辣,小编自学python时用到的视频学习教程分享给大家~都是非常系统性、非常详细的教程哦,希望能帮助到你!转发文章+私信小编“资料”...

Python3.7最新安装教程,一看就会

一、博主自言随着人工智能的快速发展,python语言越来越受大家的欢迎,博主前段时间先自学了一次,这次再次巩固,顺便分享给大家我遇到的坑。帮助大家学习的时候少走弯路。希望会对大家有所帮助,欢迎留言...

# Python 3 # Python 3 教程(#python3.10教程)

Python3教程Python的3.0版本,常被称为Python3000,或简称Py3k。相对于Python的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python3....

取消回复欢迎 发表评论:

请填写验证码