二分类问题的交叉熵

  在二分类问题中,损失函数(loss function)为交叉熵(cross entropy)损失函数。对于样本点(x,y)来说,y是真实的标签,在二分类问题中,其取值只可能为集合{0, 1}. 我们假设某个样本点的真实标签为yt, 该样本点取yt=1的概率为yp, 则该样本点的损失函数为

\[-log(yt|yp)=-(ytlog(yp)+(1-yt)log(1-yp))
\]

对于整个模型而言,其损失函数就是所有样本点的损失函数的平均值。注意到,对于该损失函数,其值应该为非负值,因为yp的取值在(0,1)之间。

自己实现的方法有问题?

  在Python的sklearn模块中,实现二分类问题的交叉熵损失函数为log_loss()。我们尝试着运行官网中给出的例子,同时,用自己的方法实现该损失函数,其Python代码如下:

from sklearn.metrics import log_loss
from math import log # 自然对数为底 # 二分类的交叉熵损失函数
# 利用sklearn模块的计算结果
y_true = [0, 0, 1, 1]
y_pred = [[.9, .1], [.8, .2], [.3, .7], [.01, .99]]
sk_log_loss = log_loss(y_true, y_pred)
print('Loss by sklearn: %s.'%sk_log_loss) # 利用公式计算得到的结果
Loss = 0
for label, prob in zip(y_true, y_pred):
Loss -= (label*log(prob[0])+(1-label)*log(prob[1])) Loss = Loss/len(y_true)
print('Loss by equation: %s.'% Loss)

在y_pred中,每个样本点都对应一组概率,如果我们把第一个概率作为样本分类为0的概率,第二个概率作为样本分类为1的概率,我们就会得到以下的输出结果:

Loss by sklearn: 0.1738073366910675.
Loss by equation: 2.430291498935543.

我们惊讶的发现,两种方法得到的损失函数值竟然是不一样的。可是,貌似我们的计算公式也没有出问题啊,这到底是怎么回事呢?

  这时候,我们最好的办法是借助源代码的帮助,看看源代码是怎么实现的,与我们的计算方法有什么不一样。

研究sklearn中的log_loss()源代码

  sklearn模块中的log_loss()函数的源代码地址为:https://github.com/scikit-learn/scikit-learn/blob/ed5e127b/sklearn/metrics/classification.py#L1576 。

  在具体分析源代码之前,我们应该注意以下几点(这也是从源代码中发现的):

  • 损失函数中的对数以自然常数e为底;
  • 预测概率的值有可能会出现0或1的情形,这在公式中是无意义的。因此,该代码使用了numpy中的clip()函数,将预测概率控制在[eps, 1-eps]范围内,其中eps为一个很小的数,避免了上述问题的出现。

  在log_loss()函数中,参数为:y_true, y_pred, eps, normalize, sample_weight,labels,为了分析问题的方便,我们只考虑该函数在所有默认参数取默认值时的情形。y_true为样本的真实标签,y_pred为预测概率。

  对于样本的真实标签y_true, 源代码中的处理代码为:

    lb = LabelBinarizer()

    if labels is not None:
lb.fit(labels)
else:
lb.fit(y_true) transformed_labels = lb.transform(y_true) if transformed_labels.shape[1] == 1:
transformed_labels = np.append(1 - transformed_labels,
transformed_labels, axis=1)

也就说,当我们的y_true为一维的时候,处理后的标签应当为二维的,比如说,我们输入的y_true为[0,0,1,1],那么处理后的标签应当为:

[[1 0]
[1 0]
[0 1]
[0 1]]

  对于预测概率,源代码中的处理过程为

	# Clipping
y_pred = np.clip(y_pred, eps, 1 - eps) # If y_pred is of single dimension, assume y_true to be binary
# and then check.
if y_pred.ndim == 1:
y_pred = y_pred[:, np.newaxis]
if y_pred.shape[1] == 1:
y_pred = np.append(1 - y_pred, y_pred, axis=1)

也就说,当我们的y_true为一维的时候,处理后的标签应当为二维的,这跟处理样本的真实标签y_true是一样的。处理完y_true和y_pred后,之后就按照损失函数的公式得到计算值。

自己实现二分类问题的交叉熵计算

  在我们分析完log_loss的源代码后,我们就能自己用公式来实现这个函数了,其Python代码如下:

from sklearn.metrics import log_loss
from math import log # 自然对数为底 # 二分类的交叉熵损失函数的计算 # y_true为一维,y_pred为二维
# 用sklearn的log_loss函数计算损失函数
y_true = [0,0,1,1]
y_pred = [[0.1,0.9], [0.2,0.8], [0.3,0.7], [0.01, 0.99]]
sk_log_loss = log_loss(y_true,y_pred)
print('Loss by sklearn: %s.'%sk_log_loss) # 用公式自己实现损失函数的计算
Loss = 0
for label, prob in zip(y_true, y_pred):
Loss -= ((1-label)*log(prob[0])+label*log(prob[1])) Loss = Loss/len(y_true)
print('Loss by equation: %s.'% Loss) # y_true为一维,y_pred为二维
# 用sklearn的log_loss函数计算损失函数
y_true = [0,0,1,1]
y_pred = [0.1, 0.2, 0.3, 0.01]
sk_log_loss = log_loss(y_true,y_pred)
print('Loss by sklearn: %s.'%sk_log_loss) # 用公式自己实现损失函数的计算
Loss = 0
for label, prob in zip(y_true, y_pred):
Loss -= ((1-label)*log(1-prob)+label*log(prob)) Loss = Loss/len(y_true)
print('Loss by equation: %s.'% Loss)

运行该函数,输出的结果为:

Loss by sklearn: 1.0696870713050948.
Loss by equation: 1.0696870713050948.
Loss by sklearn: 1.5344117643215158.
Loss by equation: 1.5344117643215158.

  这样我们就用公式能自己实现二分类问题的交叉熵计算了,计算结果与sklearn的log_loss()函数一致。

感悟

  有空就得读读程序的源代码,不仅有助于我们解决问题,还能给我们很多启示,比如log_loss()函数中的np.clip()函数的应用,能很好地避免出现预测概率为0或1的情形。

  log_loss()函数的实现虽然简单,但阅读源代码的乐趣是无穷的。以后也会继续更新,希望大家多多关注。

注意:本人现已开通两个微信公众号: 因为Python(微信号为:python_math)以及轻松学会Python爬虫(微信号为:easy_web_scrape), 欢迎大家关注哦~~

Sklearn中二分类问题的交叉熵计算的更多相关文章

  1. 机器学习之路:tensorflow 深度学习中 分类问题的损失函数 交叉熵

    经典的损失函数----交叉熵 1 交叉熵: 分类问题中使用比较广泛的一种损失函数, 它刻画两个概率分布之间的距离 给定两个概率分布p和q, 交叉熵为: H(p, q) = -∑ p(x) log q( ...

  2. 关于交叉熵(cross entropy),你了解哪些

    二分~多分~Softmax~理预 一.简介 在二分类问题中,你可以根据神经网络节点的输出,通过一个激活函数如Sigmoid,将其转换为属于某一类的概率,为了给出具体的分类结果,你可以取0.5作为阈值, ...

  3. 理解交叉熵(cross_entropy)作为损失函数在神经网络中的作用

    交叉熵的作用 通过神经网络解决多分类问题时,最常用的一种方式就是在最后一层设置n个输出节点,无论在浅层神经网络还是在CNN中都是如此,比如,在AlexNet中最后的输出层有1000个节点: 而即便是R ...

  4. 交叉熵的数学原理及应用——pytorch中的CrossEntropyLoss()函数

    分类问题中,交叉熵函数是比较常用也是比较基础的损失函数,原来就是了解,但一直搞不懂他是怎么来的?为什么交叉熵能够表征真实样本标签和预测概率之间的差值?趁着这次学习把这些概念系统学习了一下. 首先说起交 ...

  5. 【转载】深度学习中softmax交叉熵损失函数的理解

    深度学习中softmax交叉熵损失函数的理解 2018-08-11 23:49:43 lilong117194 阅读数 5198更多 分类专栏: Deep learning   版权声明:本文为博主原 ...

  6. 交叉熵理解:softmax_cross_entropy,binary_cross_entropy,sigmoid_cross_entropy简介

    cross entropy 交叉熵的概念网上一大堆了,具体问度娘,这里主要介绍深度学习中,使用交叉熵作为类别分类. 1.二元交叉熵 binary_cross_entropy 我们通常见的交叉熵是二元交 ...

  7. 『TensorFlow』分类问题与两种交叉熵

    关于categorical cross entropy 和 binary cross entropy的比较,差异一般体现在不同的分类(二分类.多分类等)任务目标,可以参考文章keras中两种交叉熵损失 ...

  8. 深度学习原理与框架-Tensorflow卷积神经网络-卷积神经网络mnist分类 1.tf.nn.conv2d(卷积操作) 2.tf.nn.max_pool(最大池化操作) 3.tf.nn.dropout(执行dropout操作) 4.tf.nn.softmax_cross_entropy_with_logits(交叉熵损失) 5.tf.truncated_normal(两个标准差内的正态分布)

    1. tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME')  # 对数据进行卷积操作 参数说明:x表示输入数据,w表示卷积核, stride ...

  9. 转:Lucene之计算相似度模型VSM(Vector Space Model) : tf-idf与交叉熵关系,cos余弦相似度

    原文:http://blog.csdn.net/zhangbinfly/article/details/7734118 最近想学习下Lucene ,以前运行的Demo就感觉很神奇,什么原理呢,尤其是查 ...

随机推荐

  1. android踩坑日记1

    Android四大组件-活动.服务.广播.碎片 情况一 应用场景:定时从服务器获取数据,然后活动或者碎片中根据最新获得的数据,更新UI. 思考: 首先定时,想到定时器,推荐使用系统自带的AlertMa ...

  2. FPGA学习之旅

    从大学就开始使用stm32,工作之后,仍然没有摆脱,从f1系列,到f4系列,然后又到L1系列,尽管可以满足工作需要,但还是希望可以摆脱束缚,尝试学习FPGA,希望能够遇到一个好机遇.

  3. Python之旅Day5 列表生成式 生成器 迭代器 装饰器

    装饰器 器即函数,装饰即修饰,意指为其他函数添加新功能 装饰器定义:本质就是函数,功能是为其他函数添加新功能 装饰器涉及的知识点= 高阶函数+函数嵌套+闭包 在遵循下面两个原则的前提下为被装饰者新功能 ...

  4. 移动APP外挂攻防实战

    前言 近日,某某龙在2018年的一次会议上发表了一个演讲,4000多人聚集在现场玩“跳一跳”游戏.随着他们指尖的翻飞跳跃,大屏幕上的现场排名也在不断刷新……而在全场的惊叹声中,最高分出现了,967分! ...

  5. asp.net中的Filter类型其实是被当作单例的

    Filter对请求进行过滤.例如,在进行身份验证的基础上增加一些权限判断,对于身份验证通过的用户,检测其是否有开通UserSpace,如果没有则在Response中说明.示例代码如下: public ...

  6. centos7安装git踩坑记

    之前自己是按照Git 服务器搭建这篇博客来安装git服务器的,一步步顺序下来,但git clone的时候,每次都要求输入密码.说好的SSH免密登录呢.前后搞了一天多才搞定,现在记录下踩过的坑. 坑1: ...

  7. 了解iOS消息推送一文就够:史上最全iOS Push技术详解

    本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表. 1.引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ.微信等IM界面处于前台时,聊天消息和指 ...

  8. ubuntu18.04安装redis

    首先更新源 sudo apt-get update 安装命令: sudo  apt-get install redis-server 查看tcp 连接 netstat -ap | grep  6379 ...

  9. Java核心技术卷一基础知识-第12章-泛型程序设计-读书笔记

    第12章 泛型程序设计 本章内容: * 为什么要使用泛型程序设计 * 定义简单泛型类 * 泛型方法 * 类型变量的限定 * 泛型代码和虚拟机 * 约束与局限性 * 泛型类型的继承规则 * 通配符类型 ...

  10. .net core 发布linux报错“The configured user limit (128) on the number of inotify instances has been reached”

    https://stackoverflow.com/questions/45875981/error-while-reading-json-file-in-dotnet-core-the-config ...