写在前面

在文章[TensorFlow] argmax, softmax_cross_entropy_with_logits, sparse_softmax_cross_entropy_with_logits函数详解中,提到了交叉熵损失函数的计算方式以及tensorflow中的输入和输出等。本篇文章会更细地讲一下tensorflow中交叉熵损失函数的应用,以及在优化过程中可能用到加权交叉熵损失函数的使用方式。

一、基础计算

当存在多个类别时,通常使用交叉熵损失函数来衡量模型的效果,也是对模型调参的重要依据,交叉熵损失函数的公式为:
L=1N∑iLi=−1N∑i∑C=1MyiclogPic\begin{aligned} L = \frac{1}{N}\sum_{i}L_i = -\frac{1}{N} \sum_{i} \sum_{C=1}^My_{ic}logP_{ic} \end{aligned} L=N1​i∑​Li​=−N1​i∑​C=1∑M​yic​logPic​​
代码:

import tensorflow as tf
import numpy as npsess=tf.Session()
#logits代表wx+b的输出,注意:logits没有进行softmax
logits = np.array([[1, 2, 3],[4, 5, 6],[7, 10, 3],[8, 2, 0],[9, 6, 3]], dtype=np.float32)
#labels是[2,2,1,0,1]的ont-hot编码形式
labels = np.array([[0, 0, 1],[0, 0, 1],[0, 1, 0],[1, 0, 0],[0, 1, 0]], dtype=np.float32)softmax_out=tf.nn.softmax(logits)
print("softmax_out is::")
print(sess.run(softmax_out))print("labels * tf.log(softmax_out) is::")
print(sess.run(labels * tf.log(softmax_out)))   # label和softmax_out取log后相乘print("cross_entropy1 is::")
cross_entropy1 = -tf.reduce_sum(labels * tf.log(softmax_out), axis=1)  # 每个样本的不同label,求损失和
print(sess.run(cross_entropy1))

结果:

softmax_out is::
[[9.0030573e-02 2.4472848e-01 6.6524094e-01][9.0030573e-02 2.4472848e-01 6.6524094e-01][4.7384717e-02 9.5174748e-01 8.6788135e-04][9.9719369e-01 2.4717962e-03 3.3452120e-04][9.5033026e-01 4.7314156e-02 2.3556333e-03]]
labels * tf.log(softmax_out) is::
[[-0.0000000e+00 -0.0000000e+00 -4.0760601e-01][-0.0000000e+00 -0.0000000e+00 -4.0760601e-01][-0.0000000e+00 -4.9455535e-02 -0.0000000e+00][-2.8102510e-03 -0.0000000e+00 -0.0000000e+00][-0.0000000e+00 -3.0509458e+00 -0.0000000e+00]]
cross_entropy1 is::
[4.0760601e-01 4.0760601e-01 4.9455535e-02 2.8102510e-03 3.0509458e+00]

二、tf.nn.softmax_cross_entropy_with_logits和tf.nn.sparse_softmax_cross_entropy_with_logits

1.两个函数的输出结果相同,区别在于输入的labels不同。
2.对于sparse_softmax_cross_entropy_with_logits, labels的size是[batch_size],每个label的取值范围是[0, num_classes-1],即每个样本的label就是0、1、2.
3.对于softmax_cross_entropy_with_logits, labels的size是[batch_size, num_classes],即sparse_softmax_cross_entropy_with_logits中labels的one-hot值。

代码:

import tensorflow as tf
import numpy as npsess = tf.Session()
# logits代表wx+b的输出,注意:logits没有进行softmax
logits = np.array([[1, 2, 3],[4, 5, 6],[7, 10, 3],[8, 2, 0],[9, 6, 3]], dtype=np.float32)print("cross_entropy2 is::")
cross_entropy2 = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=labels)
print(sess.run(cross_entropy2))# labels是[2,2,1,0,1]的ont-hot编码形式
labels = np.array([[0, 0, 1],[0, 0, 1],[0, 1, 0],[1, 0, 0],[0, 1, 0]], dtype=np.float32)print("cross_entropy3 is::")
classes = tf.argmax(labels, axis=1)  # array([2,2,1,0,1])
cross_entropy3 = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=classes)
print(sess.run(cross_entropy3))

结果:

cross_entropy2 is::
[4.0760595e-01 4.0760595e-01 4.9455538e-02 2.8102214e-03 3.0509458e+00]
cross_entropy3 is::
[4.0760595e-01 4.0760595e-01 4.9455538e-02 2.8102214e-03 3.0509458e+00]

三、tf.losses.softmax_cross_entropy 和 tf.losses.sparse_softmax_cross_entropy

1.主要用于进行不同样本的loss计算,但可通过权重来控制loss损失值
2.默认weights=1,等价于tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits)
3.weights为标量w时,等价于w*tf.reduce_mean(tf.nn.softmax_corss…)
4.weights为向量时,算出的每个loss需要乘以对应样本权重,再求均值
5.tf.losses.sparse_softmax_cross_entropy 同理等等价于tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits),只不过输入labels是非one-hot编码格式

代码:

import tensorflow as tf
import numpy as np
sess = tf.Session()
#logits代表wx+b的输出,注意:logits没有进行softmax
logits = np.array([[1, 2, 3],[4, 5, 6],[7, 10, 3],[8, 2, 0],[9, 6, 3]], dtype=np.float32)
#labels是[2,2,1,0,1]的ont-hot编码形式
labels = np.array([[0, 0, 1],[0, 0, 1],[0, 1, 0],[1, 0, 0],[0, 1, 0]], dtype=np.float32)cross1 = tf.nn.softmax_cross_entropy_with_logits(labels=labels,logits=logits)
cross2 = tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=logits)
cross3 = tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=logits, weights=0.3)print("cross1 is::")
print (sess.run(cross1))
print("cross2 is::")
print (sess.run(cross2))
print("tf.reduce_mean(cross1) is::")
print (sess.run(tf.reduce_mean(cross1)))    print("cross3 is::")
print (sess.run(cross3))
print("0.3*tf.reduce_mean(cross1) is::")
print (sess.run(0.3*tf.reduce_mean(cross1)))

结果:

cross1 is::
[4.0760595e-01 4.0760595e-01 4.9455538e-02 2.8102214e-03 3.0509458e+00]
cross2 is::
0.7836847
tf.reduce_mean(cross1) is::
0.7836847

四、加权交叉熵损失 – 样本加权

tf.losses.softmax_cross_entropy可以对损失进行加权,当每个样本的权重不同时,可以按照样本的权重加权。

import tensorflow as tf
import numpy as np
sess = tf.Session()
#logits代表wx+b的输出,注意:logits没有进行softmax
logits = np.array([[1, 2, 3],[4, 5, 6],[7, 10, 3],[8, 2, 0],[9, 6, 3]], dtype=np.float32)
#labels是[2,2,1,0,1]的ont-hot编码形式
labels = np.array([[0, 0, 1],[0, 0, 1],[0, 1, 0],[1, 0, 0],[0, 1, 0]], dtype=np.float32)cross2 = tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=logits)
cross3 = tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=logits, weights=0.3)    # 每个样本都权重0.3print("cross2 is::")
print (sess.run(cross2))
print("cross3 is::")
print (sess.run(cross3))
print("0.3*tf.reduce_mean(cross1) is::")
print (sess.run(0.3*tf.reduce_mean(cross1)))  cross4 = tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=logits,weights=[1, 2, 3, 4, 5])  # 用于控制每个样本的权重
print("cross4 is::", cross4)
print (sess.run(cross4))
print("sum", 4.0760595e-01 * 1 + 4.0760595e-01 * 2 + 4.9455538e-02 * 3 + 2.8102214e-03 * 4 + 3.0509458e+00 * 5)
print("average", (4.0760595e-01 * 1 + 4.0760595e-01 * 2 + 4.9455538e-02 * 3 + 2.8102214e-03 * 4 + 3.0509458e+00 * 5)/5.)

结果:

cross2 is::
0.7836847
cross3 is::
0.23510543
0.3*tf.reduce_mean(cross1) is::
0.23510541
cross4 is::
3.3274307
sum 16.6371543496
average 3.3274308699199997

五、加权交叉熵损失 – 类别加权

实际可能会遇到这样的情况,对于每个样本是没有权重的,但是针对不同的类别,有相应的权重,比如,类别3更不希望错误,所以类别3的损失权重可能会设置的比其他大。

对于我们需要重视的类别,可以给其较高的权重,(权重越高,损失越大,模型越会学好这个类别),如:
某个类别较少,则可以给出较高的权重,使其训练的更好
某个类别不允许错误,则需要尽量训练好这个数据,可以将其权重调高

#logits代表wx+b的输出,注意:logits没有进行softmax
logits = np.array([[1, 2, 3],[4, 5, 6],[7, 10, 3],[8, 2, 0],[9, 6, 3]], dtype=np.float32)
#labels是[2,2,1,0,1]的ont-hot编码形式
labels = np.array([[0, 0, 1],[0, 0, 1],[0, 1, 0],[1, 0, 0],[0, 1, 0]], dtype=np.float32)class_weights = tf.constant([[1.0, 1.5, 4.0]])  # 3个类别的权重,用于控制每个类别的权重
weights = tf.reduce_sum(class_weights * labels, axis=1)  # 向量化的权重
print("weights is::", sess.run(weights))cross1 = tf.nn.softmax_cross_entropy_with_logits(labels=labels,logits=logits)
print("cross1 is::")
print(sess.run(cross1))
weighted_losses = cross1 * weights
print("weighted_losses is::")
print(sess.run(weighted_losses))
print("tf.reduce_mean(weighted_losses) is::")
print(sess.run(tf.reduce_mean(weighted_losses)))softmax_out=tf.nn.softmax(logits)
print("softmax_out is::")
print(sess.run(softmax_out))
print("labels * tf.log(softmax_out) is::")
print(sess.run(labels * tf.log(softmax_out)))   # label和softmax_out取log后相乘sum = 4.0760601e-01 * 4 + 4.0760601e-01 * 4 + 4.9455535e-02 * 1.5 + 2.8102510e-03 * 1 + 3.0509458e+00 * 1.5   # 通过普通的计算方法看下是否与结果一致
print("sum/5 is::", sum/5)

结果:

weights is:: [4.  4.  1.5 1.  1.5]
cross1 is::
[4.0760595e-01 4.0760595e-01 4.9455538e-02 2.8102214e-03 3.0509458e+00]
weighted_losses is::
[1.6304238e+00 1.6304238e+00 7.4183308e-02 2.8102214e-03 4.5764189e+00]
tf.reduce_mean(weighted_losses) is::
1.582852
softmax_out is::
[[9.0030573e-02 2.4472848e-01 6.6524094e-01][9.0030573e-02 2.4472848e-01 6.6524094e-01][4.7384717e-02 9.5174748e-01 8.6788135e-04][9.9719369e-01 2.4717962e-03 3.3452120e-04][9.5033026e-01 4.7314156e-02 2.3556333e-03]]
labels * tf.log(softmax_out) is::
[[-0.0000000e+00 -0.0000000e+00 -4.0760601e-01][-0.0000000e+00 -0.0000000e+00 -4.0760601e-01][-0.0000000e+00 -4.9455535e-02 -0.0000000e+00][-2.8102510e-03 -0.0000000e+00 -0.0000000e+00][-0.0000000e+00 -3.0509458e+00 -0.0000000e+00]]
sum/5 is:: 1.5828520667

六、加权交叉熵损失 – 类别转移矩阵加权

上面是针对不同的类别,权重不同,但是若不是针对固定的类别有权重,而是比如:将类别1预测为类别2,这种错误代价较高,反而将类别1预测为类别3代价较低,这种方式怎么来进行损失加权呢?如预测值和真实值预测权重矩阵为:

真实类别1 真实类别2 真实类别3
预测类别1 1 4 2
预测类别2 5 1 1
预测类别3 4 3 1

其中w01=4w_{01}=4w01​=4表示预测类别为1实际类别为2的权重,w02=2w_{02}=2w02​=2表示预测类别为1实际类别为3的权重。

代码:

#logits代表wx+b的输出,注意:logits没有进行softmax
logits = np.array([[1, 2, 3],[4, 5, 6],[7, 10, 3],[2, 8, 0],[9, 6, 3]], dtype=np.float32)
#labels是[2,2,1,0,1]的ont-hot编码形式
labels = np.array([[0, 1, 0],[0, 0, 1],[0, 1, 0],[1, 0, 0],[0, 1, 0]], dtype=np.float32)
transfer_weights = tf.constant([[1.0, 4.0, 2.0],[5.0, 1.0, 1.0],[4.0, 3.0, 1.0]])weighted_logits = tf.matmul(logits, transfer_weights)
print("weighted_logits is::")
print(sess.run(weighted_logits))  # 得到预测值为logits情况下,实际label=1、label=2、label=3下的加权logitssoftmax_out=tf.nn.softmax(weighted_logits)
print("softmax_out is::")
print(sess.run(softmax_out))
print("labels * tf.log(softmax_out) is::")
print(sess.run(labels * tf.log(softmax_out)))   # label和softmax_out取log后相乘cross1 = tf.nn.softmax_cross_entropy_with_logits(labels=labels,logits=weighted_logits)
cross2 = tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=weighted_logits)
print ("cross1 is::", sess.run(cross1))
print ("cross2 is::", sess.run(cross2))sum = 8.000336 + 34. + 22. + 0. + 0.6931472  # 常规算法,与参数结果比较是否一致
print("average is::", sum/5.)

结果:

weighted_logits is::
[[23. 15.  7.][53. 39. 19.][69. 47. 27.][42. 16. 12.][51. 51. 27.]]
softmax_out is::
[[9.99664545e-01 3.35350080e-04 1.12497425e-07][9.99999166e-01 8.31528041e-07 1.71390690e-15][1.00000000e+00 2.78946810e-10 5.74952202e-19][1.00000000e+00 5.10908893e-12 9.35762291e-14][5.00000000e-01 5.00000000e-01 1.88756719e-11]]
labels * tf.log(softmax_out) is::
[[ -0.         -8.000336   -0.       ][ -0.         -0.        -34.       ][  0.        -22.         -0.       ][  0.         -0.         -0.       ][ -0.         -0.6931472  -0.       ]]
cross1 is:: [ 8.000336  34.        22.         0.         0.6931472]
cross2 is:: 12.938696
average is:: 12.93869664

参考文章:
Tensorflow交叉熵的代码实现

[TensorFlow] 交叉熵损失函数,加权交叉熵损失函数相关推荐

  1. 【TensorFlow】TensorFlow从浅入深系列之六 -- 教你深入理解经典损失函数(交叉熵、均方误差)

    本文是<TensorFlow从浅入深>系列之第6篇 TensorFlow从浅入深系列之一 -- 教你如何设置学习率(指数衰减法) TensorFlow从浅入深系列之二 -- 教你通过思维导 ...

  2. 【TensorFlow系列二】经典损失函数(交叉熵、均方差)

    ↑ 点击上方[计算机视觉联盟]关注我们 1.交叉熵 交叉熵是分类问题中使用比较广的一种损失函数,刻画了两个概率分布之间的距离. 给定两个概率分布p和q,通过q来表示p的交叉熵为: 交叉熵刻画的是两个概 ...

  3. 【数据挖掘】神经网络 后向传播算法( 向后传播误差 | 输出层误差公式 | 隐藏层误差公式 | 单元连接权值更新公式 | 单元偏置更新公式 | 反向传播 | 损失函数 | 误差平方和 | 交叉熵 )

    文章目录 I . 向后传播误差 简介 II . 输出层误差计算公式 III . 隐藏层层误差计算公式 IV . 使用误差更新 连接权值 V . 使用误差更新 单元偏置 VI . 反向传播 过程 VII ...

  4. 损失函数、python实现均方误差、交叉熵误差函数、mini-batch的损失函数

    损失函数 what is 损失函数 均方误差 交叉熵误差 计算mini-batch学习的损失函数 why 损失函数 what is 损失函数 神经网络学习目标是找到各层合适的权重参数w和偏置b,使得最 ...

  5. 机器学习中的损失函数(交叉熵损失、Hinge loss)

    损失函数 文章目录 损失函数 1 交叉熵损失 1.1 从最大似然估计到交叉熵损失 概率论中的MLE 机器学习中的MLE 交叉熵损失 1.2 多分类的交叉熵损失函数 1.3 比较 2. Hinge lo ...

  6. Pytorch深度学习笔记(02)--损失函数、交叉熵、过拟合与欠拟合

    目录 一.损失函数 二.交叉熵损失函数详解 1.交叉熵 2.信息量 3.信息熵 4.相对熵(KL散度) 5.交叉熵 6.交叉熵在单分类问题中的应用 7.总结: 三.过拟合和欠拟合通俗解释 1.过拟合 ...

  7. 常用损失函数:交叉熵损失

    目录 什么是损失函数 均方误差与交叉熵 为什么要使用交叉熵 交叉熵与KL散度之间的关系 参考文献 什么是损失函数 对于损失函数网上已经有充分的解释:"机器学习中所有的算法都需要最大化或最小化 ...

  8. 交叉熵损失函数python_交叉熵损失函数nn.CrossEntropyLoss()

    nn.CrossEntropyLoss() 1.引言 在使用pytorch深度学习框架做多分类时,计算损失函数通常会使用交叉熵损失函数nn.CrossEntropyLoss() 2. 信息量和熵 信息 ...

  9. 损失函数(交叉熵误差)

    损失函数 神经网络以某个指标为线索寻找最优权重参数.神经网络的学习中所用的指标称为损失函数 (loss function).这个损失函数可以使用任意函数,但一般用均方误差和交叉熵误差等. 交叉熵误差 ...

最新文章

  1. python操作sqlserver如何判断删除的数据不存在_Python MongoDB 插入数据时已存在则不执行,不存在则插入的解决方法...
  2. python dlib学习(一):人脸检测
  3. Dmoz介绍及怎么提交?
  4. ai边缘平滑_华为P40的多帧曝光AI智能处理,逆光也能无法阻挡你的美
  5. winform程序最大化时,页面显示不全的问题
  6. vue中关于flv.js的心得操作
  7. C++课程设计详解-12306的模拟实现
  8. JNI----Native本地方法接口
  9. python导入自己写的模块_Python:包、模块和导入
  10. listview复用机制研究
  11. 来尝个鲜,Python3.8几大新功能体验,冲鸭!
  12. python整数缓存机制
  13. APP抓包教程 windows + mimtproxy +夜神模拟器 + XposedInstaller + JustTrustMe
  14. 抽象类(abstract)
  15. 创建本地版PACS系统
  16. 使用语义分割架构的文档扫描仪 DeepLabV3
  17. Vue —— mockjs 模拟数据、轮播图插件 Swiper
  18. 吃透JAVA的Stream流操作,多年实践总结
  19. eChats折线图更新数据不自然,要闪一下,动态数据解决
  20. 关于SpringCloud,Spring容器重复初始化的问题

热门文章

  1. 十年 Java API 版权案终落地、Log4j 漏洞蛰伏八年后席卷全球,2021 年开源圈大事件盘点
  2. 基于深度模型的Out of Distribution(OOD)检测相关方法介绍
  3. VMware Workstation——虚拟机启动Ubuntu系统时报错:“另一个程序已锁定文件的一部分,进程无法访问”解决办法
  4. 常见15个C语言的标准库
  5. [转帖]pfSense软路由系统的使用
  6. Hiding in Plain Sight: A Longitudinal Study of Combosquatting Abuse
  7. 安卓开发入门教程-UI控件_EditText
  8. Python——使用ipython
  9. Swagger2简介
  10. 20 个好用的 Go 语言微服务开发框架