51

机器学习中的 7 大损失函数实战总结(附Python演练)

 4 years ago
source link: https://www.tuicool.com/articles/ZVFJjee
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

uQBvuum.jpg!web

译者 | VK

源 | Analytics Vidhya

【磐创 AI 导读】 本文 为大家介绍了 Python机器学习算法的7个损失函数的详细指南 ,希望对大家有所帮助。 想要获取更多的机器学习、深度学习资源,欢迎大家点击上方蓝字关注我们的公众号: 磐创AI。

概述

  • 学习什么是损失函数以及它们如何在机器学习算法中工作

  • 损失函数实际上是我们经常使用的技术的核心

  • 本文介绍了多种损失函数与它们的工作原理以及如何使用Python对它们进行编程

介绍

想象一下-你已经在给定的数据集上训练了机器学习模型,并准备好将它交付给客户。但是,你如何确定该模型能够提供最佳结果?是否有指标或技术可以帮助你快速评估数据集上的模型?

当然是有的,简而言之,机器学习中损失函数可以解决以上问题。

损失函数是我们喜欢使用的机器学习算法的核心。但大多数初学者和爱好者不清楚如何以及在何处使用它们。

IfyURvu.jpg!web

它们并不难理解,反而可以增强你对机器学习算法的理解。那么,什么是损失函数,你如何理解它们的意义?

在本文中,我将讨论机器学习中使用的7种常见损失函数,并解释每种函数的使用方法。

目录

  • 什么是损失函数?

  • 回归损失函数

  • 平方误差损失

  • 绝对误差损失

  • Huber损失

  • 二分类损失函数

  • 二分类交叉熵

  • Hinge损失

  • 多分类损失函数

  • 多分类交叉熵损失

  • KL散度(Kullback Leibler Divergence Loss)

什么是损失函数?

假设你在山顶,需要下山。你如何决定走哪个方向?

faE363m.jpg!web

我要做的事情如下:

  • 环顾四周,看看所有可能的路径

  • 拒绝那些上升的路径。这是因为这些路径实际上会消耗更多的体力并使下山任务变得更加艰难

  • 最后,走 我认为的 坡度最大的路径

关于我判断我的决策是否好坏的直觉,这正是损失函数能够提供的功能。

损失函数将决策映射到其相关成本

决定走上坡的路径将耗费我们的体力和时间。决定走下坡的路径将使我们受益。因此,下坡的成本是更小的。

在有监督的机器学习算法中,我们希望在学习过程中最小化每个训练样例的误差。这是使用梯度下降等一些优化策略完成的。而这个误差来自损失函数。

损失函数(Loss Function)和成本函数(Cost Function)之间有什么区别?

在此强调这一点,尽管 成本函数损失函数 是同义词并且可以互换使用,但它们是不同的。

损失函数用于单个训练样本。它有时也称为 误差函数 ( error function )。另一方面,成本函数是整个训练数据集的 平均损失 ( average function )。优化策略旨在最小化成本函数。

回归损失函数

此时你必须非常熟悉线性回归。它涉及对因变量Y和几个独立变量 X i 之间的线性关系进行建模。因此,我们在空间中对这些数据拟合出一条直线或者超平面。

Y = a0 + a1 * X1 + a2 * X2 + ....+ an * Xn

我们将使用给定的数据点来找到系数a0,a1,…,an。

3Uv6Vjm.png!web

我们将使用著名的波士顿住房数据集^1来理解这个概念。为了简单起见,我们将只使用一个特征-每个住宅的平均房间数( Average number of rooms per dwelling )(X)来预测因变量-1000美元价位的房屋的中位数价值( Median Value )(Y)

rEFZ7rr.png!web

我们将使用 梯度下降 ( Gradient Descent )作为优化策略来查找回归线。我不会详细介绍Gradient Descent的细节,但这里提醒一下权重更新规则:

RNRJJjj.jpg!web

这里, θ j 是要更新的权重, α 是学习率, J 是成本函数。成本函数由 θ 参数化。我们的目标是找到产生最小总成本的θ值。

我已经为下面的每个损失函数定义了我们将遵循的步骤:

  1. 写出预测函数f(X)的表达式,并确定我们需要找到的参数

  2. 确定每个训练样本计算得到的损失

  3. 找到成本函数(所有样本的平均损失)的表达式

  4. 找到与每个未知参数相关的成本函数的梯度

  5. 确定学习率并在固定次数中进行迭代执行权重更新规则

1.平方误差损失

每个训练样本的平方误差损失(也称为 L2 Loss )是实际值和预测值之差的平方:

FnMFBrE.jpg!web

相应的成本函数是这些 平方误差的平均值 (MSE)。

推荐你引用以下代码时先尝试自己计算出梯度

def update_weights_MSE(m, b, X, Y, learning_rate):
    m_deriv = 0
    b_deriv = 0
    N = len(X)
    for i in range(N):
        # 计算偏导数为
        # -2x(y - (mx + b))
        m_deriv += -2*X[i] * (Y[i] - (m*X[i] + b))
        # -2(y - (mx + b))
        b_deriv += -2*(Y[i] - (m*X[i] + b))
    # 我们减去它,因为导数指向最陡的上升方向
    m -= (m_deriv / float(N)) * learning_rate
    b -= (b_deriv / float(N)) * learning_rate

    return m, b

在波士顿住房数据上,在不同的学习率中分别迭代了500次得到下图:

6vuIfiU.png!web

让我们再谈谈MSE损失函数,它是一个二次函数(形式为ax^2+bx+c),并且值大于等于0。二次函数的图形如下图所示:

uAFB3e6.png!web

二次函数仅具有全局最小值。由于没有局部最小值,所以我们永远不会陷入它。因此,可以保证梯度下降将收敛到全局最小值(如果它完全收敛)。

MSE损失函数通过平方误差来惩罚模型犯的大错误。把一个比较大的数平方会使它变得更大。但有一点需要注意,这个属性使MSE成本函数对异常值的健壮性降低。 因此,如果我们的数据容易出现许多的异常值,则不应使用这个它。

2.绝对误差损失

每个训练样本的绝对误差是预测值和实际值之间的距离,与符号无关。绝对误差也称为 L1 Loss

EZZjya6.jpg!web

正如我之前提到的,成本是这些绝对误差的平均值(MAE)。

与MSE相比,MAE成本对异常值更加健壮。但是,在数学方程中处理绝对或模数运算符并不容易。我们可以认为这是MAE的缺点。

以下是MAE成本更新权重的代码

def update_weights_MAE(m, b, X, Y, learning_rate):
    m_deriv = 0
    b_deriv = 0
    N = len(X)
    for i in range(N):
        #计算偏导数
        # -x(y - (mx + b)) / |mx + b|
        m_deriv += - X[i] * (Y[i] - (m*X[i] + b)) / abs(Y[i] - (m*X[i] + b))
        # -(y - (mx + b)) / |mx + b|
        b_deriv += -(Y[i] - (m*X[i] + b)) / abs(Y[i] - (m*X[i] + b))
    #我们减去它,因为导数指向最陡的上升方向
    m -= (m_deriv / float(N)) * learning_rate
    b -= (b_deriv / float(N)) * learning_rate
    return m, b

在不同学习速率中分别迭代500次后,我们得到以下图:

BZJR7zz.png!web

3.Huber损失

Huber损失结合了MSE和MAE的最佳特性。对于较小的误差,它是二次的,否则是线性的(对于其梯度也是如此)。Huber损失需要确定 δ 参数:

6F3U3qF.jpg!web
def update_weights_Huber(m, b, X, Y, delta, learning_rate):
    m_deriv = 0
    b_deriv = 0
    N = len(X)
    for i in range(N):
        # 小值的二次导数,大值的线性导数
        if abs(Y[i] - m*X[i] - b) <= delta:
            m_deriv += -X[i] * (Y[i] - (m*X[i] + b))
            b_deriv += - (Y[i] - (m*X[i] + b))
        else:
            m_deriv += delta * X[i] * ((m*X[i] + b) - Y[i]) / abs((m*X[i] + b) - Y[i])
            b_deriv += delta * ((m*X[i] + b) - Y[i]) / abs((m*X[i] + b) - Y[i])
    #我们减去它,因为导数指向最陡的上升方向
    m -= (m_deriv / float(N)) * learning_rate
    b -= (b_deriv / float(N)) * learning_rate
    return m, b

我们以0.0001的学习速率分别对 δ 参数的不同值进行500次权重更新迭代得到下图:

IzUFraI.png!web

Huber损失对于异常值比MSE更强。 它用于稳健回归(robust regression),M估计法(M-estimator)和可加模型(additive model)。Huber损失的变体也可以用于分类。

二分类损失函数

意义如其名。二分类是指将物品分配到两个类中的一个。该分类基于应用于输入特征向量的规则。二分类的例子例如,根据邮件的主题将电子邮件分类为垃圾邮件或非垃圾邮件。

我将在乳腺癌数据集^2上说明这些二分类损失函数。

我们希望根据 平均半径面积周长 等特征将肿瘤分类为" 恶性(Malignant) "或" 良性(Benign) "。为简化起见,我们将仅使用两个输入特征(X_1和X_2),即" 最差区域(worst area) "和" 平均对称性(mean symmetry) "用于分类。Y是二值的,为0(恶性)或1(良性)。

这是我们数据的散点图:

qQ32eef.png!web cancer

1.二元交叉熵损失

让我们从理解术语"熵"开始。通常,我们使用熵来表示无序或不确定性。测量具有概率分布p(X)的随机变量X:

ji2uYjY.jpg!web

负号用于使最后的结果为正数。

概率分布的熵值越大,表明分布的不确定性越大。同样,一个较小的值代表一个更确定的分布。

这使得二元交叉熵适合作为损失函数( 你希望最小化其值 )。我们对输出概率p的分类模型使用 二元交叉熵损失

元素属于第1类(或正类)的概率=p
元素属于第0类(或负类)的概率=1-p

然后,输出标签y(可以取值0和1)的交叉熵损失和和预测概率p定义为:

3iuUzeI.jpg!web

这也称为Log-Loss(对数损失)。为了计算概率p,我们可以使用sigmoid函数。这里,z是我们输入功能的函数:

VNZ3Mny.jpg!web

sigmoid函数的范围是[0,1],这使得它适合于计算概率。

BZvUrmR.png!web

推荐你引用以下代码时先尝试自己计算出梯度

def update_weights_BCE(m1, m2, b, X1, X2, Y, learning_rate):
    m1_deriv = 0
    m2_deriv = 0
    b_deriv = 0
    N = len(X1)
    for i in range(N):
        s = 1 / (1 / (1 + math.exp(-m1*X1[i] - m2*X2[i] - b)))
        # 计算偏导数
        m1_deriv += -X1[i] * (s - Y[i])
        m2_deriv += -X2[i] * (s - Y[i])
        b_deriv += -(s - Y[i])
    # 我们减去它,因为导数指向最陡的上升方向
    m1 -= (m1_deriv / float(N)) * learning_rate
    m2 -= (m2_deriv / float(N)) * learning_rate
    b -= (b_deriv / float(N)) * learning_rate
    return m1, m2, b

在不同alpha值里使用权重更新规则进行1000次迭代得到下图:

MzmEVj6.png!web

2.Hinge损失

Hinge损失主要用于带有类标签-1和1的支持向量机(SVM)。因此,请确保将数据集中"恶性"类的标签从0更改为-1。

Hinge损失不仅会惩罚错误的预测,还会惩罚不自信的正确预测。

数据对(x,y)的Hinge损失如图:

7FN3yiZ.jpg!web hinge.jpg
def update_weights_Hinge(m1, m2, b, X1, X2, Y, learning_rate):

    m1_deriv = 0
    m2_deriv = 0
    b_deriv = 0
    N = len(X1)
    for i in range(N):
        # 计算偏导数
        if Y[i]*(m1*X1[i] + m2*X2[i] + b) <= 1:
            m1_deriv += -X1[i] * Y[i]
            m2_deriv += -X2[i] * Y[i]
            b_deriv += -Y[i]
        # 否则偏导数为0
    # 我们减去它,因为导数指向最陡的上升方向
    m1 -= (m1_deriv / float(N)) * learning_rate
    m2 -= (m2_deriv / float(N)) * learning_rate
    b -= (b_deriv / float(N)) * learning_rate
return m1, m2, b

在使用三个不同的alpha值运行2000次迭代的更新函数之后,得到下图:

3QzIJ3a.png!web

Hinge损失简化了SVM的数学运算,同时最大化了损失(与对数损失(Log-Loss)相比)。当我们想要做实时决策而不是高度关注准确性时,就可以使用它。

多分类损失函数

电子邮件不仅被归类为垃圾邮件或垃圾邮件(这不再是90年代了!)。它们分为各种其他类别-工作,家庭,社交,促销等。

我们将使用Iris数据集^3来理解剩余的两个损失函数。我们将使用2个特征 X 1 萼片长度(Sepal length) 和特征 X 2 花瓣宽度(Petal width) 来预测鸢尾花的类别(Y) - Setosa,Versicolor或Virginica

我们的任务是使用神经网络模型和Keras内置的Adam优化器来实现分类器。这是因为随着参数数量的增加,数学以及代码将变得难以理解。

这是我们数据的散点图:

N7nmiab.png!web

1.多分类交叉熵损失

多分类交叉熵损失是二元交叉熵损失的推广。输入向量 X i 和相应的one-hot编码目标向量 Y i 的损失是:

FfYRzef.jpg!web

我们使用softmax函数来找到概率 p i j

veuEfyu.jpg!web

"Softmax层是接在神经网络的输出层前。Softmax层必须与输出层具有相同数量的节点。"Google Developer's Blog

uiEfqaf.jpg!web

最后,我们的输出是具有给定输入的最大概率的类别。

我们使用一个输入层和一个输出层建立一个模型,并用不同的学习速度编译它。在model.compile()语句中将损失函数指定为' categorical_crossentropy ':

# 导入包
from keras.layers import Dense
from keras.models import Sequential
from keras.optimizers import adam
#alpha设置为0.001,如adam优化器中的lr参数所示
# 创建模型
model_alpha1 = Sequential()
model_alpha1.add(Dense(50, input_dim=2, activation='relu'))
model_alpha1.add(Dense(3, activation='softmax'))
# 编译模型
opt_alpha1 = adam(lr=0.001)
model_alpha1.compile(loss='categorical_crossentropy', optimizer=opt_alpha1, metrics=['accuracy'])
# 拟合模型
# dummy_Y是one-hot形式编码的
# history_alpha1用于为绘图的验证和准确性评分
history_alpha1 = model_alpha1.fit(dataX, dummy_Y, validation_data=(dataX, dummy_Y), epochs=200, verbose=0)

在不同的学习率经过200轮训练后成本和准确度的图如下:

JjuMjmR.png!webNNZF3aB.png!web

2. KL散度

KL散度概率分布与另一个概率分布区别的度量。KL散度为零表示分布相同。

63aeYfQ.jpg!web

请注意,发散函数不对称。即:

raIRBbr.jpg!web

这就是为什么KL散度不能用作距离度量的原因。

我将描述使用KL散度作为损失函数而不进行数学计算的基本方法。在给定一些近似分布Q的情况下,我们希望近似关于输入特征的目标变量的真实概率分布P. 由于KL散度不对称,我们可以通过两种方式实现:

myMBfmV.jpg!web

第一种方法用于监督学习,第二种方法用于强化学习。KL散度在功能上类似于多分类交叉熵,KL散度也可以称为P相对于Q的相对熵:

我们在compile()函数中指定'kullback_leibler_divergence'作为损失函数,就像我们之前在处理多分类交叉熵损失时所做的那样。

JFNnyy7.jpg!web
# 导入包
from keras.layers import Dense
from keras.models import Sequential
from keras.optimizers import adam
# alpha设置为0.001,如adam优化器中的lr参数所示
#  创建模型
model_alpha1 = Sequential()
model_alpha1.add(Dense(50, input_dim=2, activation='relu'))
model_alpha1.add(Dense(3, activation='softmax'))
# 编译模型
opt_alpha1 = adam(lr=0.001)
model_alpha1.compile(loss='kullback_leibler_divergence', optimizer=opt_alpha1, metrics=['accuracy'])
# 拟合模型
# dummy_Y是one-hot形式编码的
# history_alpha1用于为绘图的验证和准确性评分
history_alpha1 = model_alpha1.fit(dataX, dummy_Y, validation_data=(dataX, dummy_Y), epochs=200, verbose=0)

在不同的学习率经过200轮训练后成本和准确度的图如下:

jUby6vj.png!webiqmYja2.png!web

与多分类分类相比,KL散度更常用于逼近复杂函数。我们在使用变分自动编码器(VAE)等深度生成模型时经常使用KL散度。

你也许还想

●  使用SlimYOLOv3框架实现实时目标检测

●  日常福利|市面上第一个专门介绍AutoML的书籍纸质版+电子版免费送!!

●  深度强化学习(DRL)专栏开篇

欢迎扫码关注:

J3aYnyj.jpg!web

 点击下方  |   |  了解更多


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK