机器学习中的 7 大损失函数实战总结(附Python演练)
介绍
想象一下-你已经在给定的数据集上训练了机器学习模型,并准备好将它交付给客户。但是,你如何确定该模型能够提供最佳结果?是否有指标或技术可以帮助你快速评估数据集上的模型?
当然是有的,简而言之,机器学习中损失函数可以解决以上问题。
损失函数是我们喜欢使用的机器学习算法的核心。但大多数初学者和爱好者不清楚如何以及在何处使用它们。
它们并不难理解,反而可以增强你对机器学习算法的理解。那么,什么是损失函数,你如何理解它们的意义?
在本文中,我将讨论机器学习中使用的7种常见损失函数,并解释每种函数的使用方法。
目录
什么是损失函数?
回归损失函数
平方误差损失
绝对误差损失
Huber损失
二分类损失函数
二分类交叉熵
Hinge损失
多分类损失函数
多分类交叉熵损失
KL散度(Kullback Leibler Divergence Loss)
什么是损失函数?
假设你在山顶,需要下山。你如何决定走哪个方向?
我要做的事情如下:
环顾四周,看看所有可能的路径
拒绝那些上升的路径。这是因为这些路径实际上会消耗更多的体力并使下山任务变得更加艰难
最后,走我认为的坡度最大的路径
关于我判断我的决策是否好坏的直觉,这正是损失函数能够提供的功能。
损失函数将决策映射到其相关成本
决定走上坡的路径将耗费我们的体力和时间。决定走下坡的路径将使我们受益。因此,下坡的成本是更小的。
在有监督的机器学习算法中,我们希望在学习过程中最小化每个训练样例的误差。这是使用梯度下降等一些优化策略完成的。而这个误差来自损失函数。
损失函数(Loss Function)和成本函数(Cost Function)之间有什么区别?
在此强调这一点,尽管成本函数和损失函数是同义词并且可以互换使用,但它们是不同的。
损失函数用于单个训练样本。它有时也称为误差函数(error function)。另一方面,成本函数是整个训练数据集的平均损失(average function)。优化策略旨在最小化成本函数。
回归损失函数
此时你必须非常熟悉线性回归。它涉及对因变量Y和几个独立变量Xi之间的线性关系进行建模。因此,我们在空间中对这些数据拟合出一条直线或者超平面。
Y = a0 + a1 * X1 + a2 * X2 + ....+ an * Xn
我们将使用给定的数据点来找到系数a0,a1,…,an。
我们将使用著名的波士顿住房数据集^1来理解这个概念。为了简单起见,我们将只使用一个特征-每个住宅的平均房间数(Average number of rooms per dwelling)(X)来预测因变量-1000美元价位的房屋的中位数价值(Median Value)(Y)
我们将使用梯度下降(Gradient Descent)作为优化策略来查找回归线。我不会详细介绍Gradient Descent的细节,但这里提醒一下权重更新规则:
这里,θj是要更新的权重,α是学习率,J是成本函数。成本函数由θ参数化。我们的目标是找到产生最小总成本的θ值。
我已经为下面的每个损失函数定义了我们将遵循的步骤:
写出预测函数f(X)的表达式,并确定我们需要找到的参数
确定每个训练样本计算得到的损失
找到成本函数(所有样本的平均损失)的表达式
找到与每个未知参数相关的成本函数的梯度
确定学习率并在固定次数中进行迭代执行权重更新规则
1.平方误差损失
每个训练样本的平方误差损失(也称为L2 Loss)是实际值和预测值之差的平方:
相应的成本函数是这些平方误差的平均值(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次得到下图:
让我们再谈谈MSE损失函数,它是一个二次函数(形式为ax^2+bx+c),并且值大于等于0。二次函数的图形如下图所示:
二次函数仅具有全局最小值。由于没有局部最小值,所以我们永远不会陷入它。因此,可以保证梯度下降将收敛到全局最小值(如果它完全收敛)。
MSE损失函数通过平方误差来惩罚模型犯的大错误。把一个比较大的数平方会使它变得更大。但有一点需要注意,这个属性使MSE成本函数对异常值的健壮性降低。因此,如果我们的数据容易出现许多的异常值,则不应使用这个它。
2.绝对误差损失
每个训练样本的绝对误差是预测值和实际值之间的距离,与符号无关。绝对误差也称为L1 Loss:
正如我之前提到的,成本是这些绝对误差的平均值(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次后,我们得到以下图:
3.Huber损失
Huber损失结合了MSE和MAE的最佳特性。对于较小的误差,它是二次的,否则是线性的(对于其梯度也是如此)。Huber损失需要确定δ参数:
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次权重更新迭代得到下图:
Huber损失对于异常值比MSE更强。它用于稳健回归(robust regression),M估计法(M-estimator)和可加模型(additive model)。Huber损失的变体也可以用于分类。
二分类损失函数
意义如其名。二分类是指将物品分配到两个类中的一个。该分类基于应用于输入特征向量的规则。二分类的例子例如,根据邮件的主题将电子邮件分类为垃圾邮件或非垃圾邮件。
我将在乳腺癌数据集^2上说明这些二分类损失函数。平均半径,面积,周长等特征将肿瘤分类为"恶性(Malignant)"或"良性(Benign)"。为简化起见,我们将仅使用两个输入特征(X_1和X_2),即"最差区域(worst area)"和"平均对称性(mean symmetry)"用于分类。Y是二值的,为0(恶性)或1(良性)。
这是我们数据的散点图:
cancer
1.二元交叉熵损失
让我们从理解术语"熵"开始。通常,我们使用熵来表示无序或不确定性。测量具有概率分布p(X)的随机变量X:
负号用于使最后的结果为正数。
概率分布的熵值越大,表明分布的不确定性越大。同样,一个较小的值代表一个更确定的分布。
这使得二元交叉熵适合作为损失函数(你希望最小化其值)。我们对输出概率p的分类模型使用二元交叉熵损失。
元素属于第1类(或正类)的概率=p
元素属于第0类(或负类)的概率=1-p
然后,输出标签y(可以取值0和1)的交叉熵损失和和预测概率p定义为:
这也称为Log-Loss(对数损失)。为了计算概率p,我们可以使用sigmoid函数。这里,z是我们输入功能的函数:
sigmoid函数的范围是[0,1],这使得它适合于计算概率。
推荐你引用以下代码时先尝试自己计算出梯度
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次迭代得到下图:
2.Hinge损失
Hinge损失主要用于带有类标签-1和1的支持向量机(SVM)。因此,请确保将数据集中"恶性"类的标签从0更改为-1。
Hinge损失不仅会惩罚错误的预测,还会惩罚不自信的正确预测。
数据对(x,y)的Hinge损失如图:
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次迭代的更新函数之后,得到下图:
Hinge损失简化了SVM的数学运算,同时最大化了损失(与对数损失(Log-Loss)相比)。当我们想要做实时决策而不是高度关注准确性时,就可以使用它。
多分类损失函数
电子邮件不仅被归类为垃圾邮件或垃圾邮件(这不再是90年代了!)。它们分为各种其他类别-工作,家庭,社交,促销等。
我们将使用Iris数据集^3来理解剩余的两个损失函数。我们将使用2个特征X1萼片长度(Sepal length)和特征X2花瓣宽度(Petal width)来预测鸢尾花的类别(Y) -Setosa,Versicolor或Virginica
我们的任务是使用神经网络模型和Keras内置的Adam优化器来实现分类器。这是因为随着参数数量的增加,数学以及代码将变得难以理解。
这是我们数据的散点图:
1.多分类交叉熵损失
多分类交叉熵损失是二元交叉熵损失的推广。输入向量Xi和相应的one-hot编码目标向量Yi的损失是:
我们使用softmax函数来找到概率pij:
"Softmax层是接在神经网络的输出层前。Softmax层必须与输出层具有相同数量的节点。"Google Developer's Blog
最后,我们的输出是具有给定输入的最大概率的类别。
我们使用一个输入层和一个输出层建立一个模型,并用不同的学习速度编译它。在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轮训练后成本和准确度的图如下:
2. KL散度
KL散度概率分布与另一个概率分布区别的度量。KL散度为零表示分布相同。
请注意,发散函数不对称。即:
这就是为什么KL散度不能用作距离度量的原因。
我将描述使用KL散度作为损失函数而不进行数学计算的基本方法。在给定一些近似分布Q的情况下,我们希望近似关于输入特征的目标变量的真实概率分布P. 由于KL散度不对称,我们可以通过两种方式实现:
第一种方法用于监督学习,第二种方法用于强化学习。KL散度在功能上类似于多分类交叉熵,KL散度也可以称为P相对于Q的相对熵:
我们在compile()函数中指定'kullback_leibler_divergence'作为损失函数,就像我们之前在处理多分类交叉熵损失时所做的那样。
# 导入包
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轮训练后成本和准确度的图如下:
与多分类分类相比,KL散度更常用于逼近复杂函数。我们在使用变分自动编码器(VAE)等深度生成模型时经常使用KL散度。
欢迎关注磐创博客资源汇总站:
http://docs.panchuang.net/
欢迎关注PyTorch官方中文教程站:
http://pytorch.panchuang.net/
机器学习中的 7 大损失函数实战总结(附Python演练)的更多相关文章
- 机器学习经典分类算法 —— k-近邻算法(附python实现代码及数据集)
目录 工作原理 python实现 算法实战 约会对象好感度预测 故事背景 准备数据:从文本文件中解析数据 分析数据:使用Matplotlib创建散点图 准备数据:归一化数值 测试算法:作为完整程序验证 ...
- 机器学习经典分类算法 —— k-均值算法(附python实现代码及数据集)
目录 工作原理 python实现 算法实战 对mnist数据集进行聚类 小结 附录 工作原理 聚类是一种无监督的学习,它将相似的对象归到同一个簇中.类似于全自动分类(自动的意思是连类别都是自动构建的) ...
- 机器学习中的损失函数 (着重比较:hinge loss vs softmax loss)
https://blog.csdn.net/u010976453/article/details/78488279 1. 损失函数 损失函数(Loss function)是用来估量你模型的预测值 f( ...
- 机器学习中的算法-决策树模型组合之随机森林与GBDT
机器学习中的算法(1)-决策树模型组合之随机森林与GBDT 版权声明: 本文由LeftNotEasy发布于http://leftnoteasy.cnblogs.com, 本文可以被全部的转载或者部分使 ...
- 机器学习中的数学(1)-回归(regression)、梯度下降(gradient descent)
版权声明: 本文由LeftNotEasy所有,发布于http://leftnoteasy.cnblogs.com.如果转载,请注明出处,在未经作者同意下将本文用于商业用途,将追究其法律责任. 前言: ...
- 顶尖大数据挖掘实战平台(TipDM-H8)产品白皮书
顶尖大数据挖掘实战平台 (TipDM-H8) 产 品 说 明 书 广州泰迪智能科技有限公司 版权所有 地址: 广州市经济技术开发区科学城232号 网址: http: ...
- 机器学习中的K-means算法的python实现
<机器学习实战>kMeans算法(K均值聚类算法) 机器学习中有两类的大问题,一个是分类,一个是聚类.分类是根据一些给定的已知类别标号的样本,训练某种学习机器,使它能够对未知类别的样本进行 ...
- 机器学习中模型泛化能力和过拟合现象(overfitting)的矛盾、以及其主要缓解方法正则化技术原理初探
1. 偏差与方差 - 机器学习算法泛化性能分析 在一个项目中,我们通过设计和训练得到了一个model,该model的泛化可能很好,也可能不尽如人意,其背后的决定因素是什么呢?或者说我们可以从哪些方面去 ...
- 机器学习中Batch Size、Iteration和Epoch的概念
Batch Size:批尺寸.机器学习中参数更新的方法有三种: (1)Batch Gradient Descent,批梯度下降,遍历全部数据集计算一次损失函数,进行一次参数更新,这样得到的方向能够更加 ...
随机推荐
- 使用Vagrant部署虚拟分布式开发和测试环境
同步更新到笔者个人博客,可以访问我的博客查看原文:https://www.rockysky.tech 创建自动化配置开发环境 最近由于最近研究和学习的关系,需要经常配置和搭建多个虚拟机组成的分布式系统 ...
- 操作系统-IO管理和磁盘调度
I/O设备 IO设备的类型 分为三类:人机交互类外部设备:打印机.显示器.鼠标.键盘等等.这类设备数据交换速度相对较慢,通常是以字节为单位进行数据交换的 存储设备:用于存储程序和数据的设备,如磁盘.磁 ...
- 一起了解 .Net Foundation 项目 No.13
.Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. MVVM Light To ...
- beego的安装以及bee的安装和使用
beego的安装以及bee的安装和使用 一.beego的安装 1.beego是什么 beego 是一个快速开发 Go 应用的 HTTP 框架,他可以用来快速开发 API.Web 及后端服务等各种应用, ...
- PHP时区转换(默认中国时区<Asia/Shanghai>转意大利时区<Europe/Rome>)
<?php function changeTimeZone($date_time, $format = 'Y-m-d H:i:s', $to = 'Europe/Rome', $from = ' ...
- springboot 解决实体类值为null或者数组为空,不返回前台
一个注解解决问题 @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonInclude(JsonInclude.Include.NON_NULL)
- 【前端性能优化】高性能JavaScript整理总结
高性能JavaScript整理总结 关于前端性能优化:首先想到的是雅虎军规34条然后最近看了<高性能JavaScript>大概的把书中提到大部分知识梳理了下并加上部分个人理解这本书有参考雅 ...
- 基础JavaScript练习(三)总结
任务目的 实践JavaScript数组.字符串相关操作 任务描述 基于任务四进行升级 将新元素输入框从input改为textarea 允许一次批量输入多个内容,格式可以为数字.中文.英文等,可以通过用 ...
- mongoose-面向对象操作mongodb的Nodejs框架
介绍 无论是mysql还是mongodb,传统的与数据库交互的方式都是按照他们提供的API来写代码.它们提供的API往往不是很容易理解,而且难以记忆,如果传错了参数,写错一个符号都要查文档. ORM( ...
- 跟我猜Spring-boot:依赖注入
依赖注入 引&目标 本篇是<跟我猜Spring-Boot>系列的第二篇(Oh,我竟然已经写了10篇了,真不容易). 在上一篇中,我们实现了Bean的创建,但是仅仅是创建而已,并没有 ...