[TensorFlow] 交叉熵损失函数,加权交叉熵损失函数
写在前面
在文章[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=N1i∑Li=−N1i∑C=1∑MyiclogPic
代码:
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] 交叉熵损失函数,加权交叉熵损失函数相关推荐
- 【TensorFlow】TensorFlow从浅入深系列之六 -- 教你深入理解经典损失函数(交叉熵、均方误差)
本文是<TensorFlow从浅入深>系列之第6篇 TensorFlow从浅入深系列之一 -- 教你如何设置学习率(指数衰减法) TensorFlow从浅入深系列之二 -- 教你通过思维导 ...
- 【TensorFlow系列二】经典损失函数(交叉熵、均方差)
↑ 点击上方[计算机视觉联盟]关注我们 1.交叉熵 交叉熵是分类问题中使用比较广的一种损失函数,刻画了两个概率分布之间的距离. 给定两个概率分布p和q,通过q来表示p的交叉熵为: 交叉熵刻画的是两个概 ...
- 【数据挖掘】神经网络 后向传播算法( 向后传播误差 | 输出层误差公式 | 隐藏层误差公式 | 单元连接权值更新公式 | 单元偏置更新公式 | 反向传播 | 损失函数 | 误差平方和 | 交叉熵 )
文章目录 I . 向后传播误差 简介 II . 输出层误差计算公式 III . 隐藏层层误差计算公式 IV . 使用误差更新 连接权值 V . 使用误差更新 单元偏置 VI . 反向传播 过程 VII ...
- 损失函数、python实现均方误差、交叉熵误差函数、mini-batch的损失函数
损失函数 what is 损失函数 均方误差 交叉熵误差 计算mini-batch学习的损失函数 why 损失函数 what is 损失函数 神经网络学习目标是找到各层合适的权重参数w和偏置b,使得最 ...
- 机器学习中的损失函数(交叉熵损失、Hinge loss)
损失函数 文章目录 损失函数 1 交叉熵损失 1.1 从最大似然估计到交叉熵损失 概率论中的MLE 机器学习中的MLE 交叉熵损失 1.2 多分类的交叉熵损失函数 1.3 比较 2. Hinge lo ...
- Pytorch深度学习笔记(02)--损失函数、交叉熵、过拟合与欠拟合
目录 一.损失函数 二.交叉熵损失函数详解 1.交叉熵 2.信息量 3.信息熵 4.相对熵(KL散度) 5.交叉熵 6.交叉熵在单分类问题中的应用 7.总结: 三.过拟合和欠拟合通俗解释 1.过拟合 ...
- 常用损失函数:交叉熵损失
目录 什么是损失函数 均方误差与交叉熵 为什么要使用交叉熵 交叉熵与KL散度之间的关系 参考文献 什么是损失函数 对于损失函数网上已经有充分的解释:"机器学习中所有的算法都需要最大化或最小化 ...
- 交叉熵损失函数python_交叉熵损失函数nn.CrossEntropyLoss()
nn.CrossEntropyLoss() 1.引言 在使用pytorch深度学习框架做多分类时,计算损失函数通常会使用交叉熵损失函数nn.CrossEntropyLoss() 2. 信息量和熵 信息 ...
- 损失函数(交叉熵误差)
损失函数 神经网络以某个指标为线索寻找最优权重参数.神经网络的学习中所用的指标称为损失函数 (loss function).这个损失函数可以使用任意函数,但一般用均方误差和交叉熵误差等. 交叉熵误差 ...
最新文章
- python操作sqlserver如何判断删除的数据不存在_Python MongoDB 插入数据时已存在则不执行,不存在则插入的解决方法...
- python dlib学习(一):人脸检测
- Dmoz介绍及怎么提交?
- ai边缘平滑_华为P40的多帧曝光AI智能处理,逆光也能无法阻挡你的美
- winform程序最大化时,页面显示不全的问题
- vue中关于flv.js的心得操作
- C++课程设计详解-12306的模拟实现
- JNI----Native本地方法接口
- python导入自己写的模块_Python:包、模块和导入
- listview复用机制研究
- 来尝个鲜,Python3.8几大新功能体验,冲鸭!
- python整数缓存机制
- APP抓包教程 windows + mimtproxy +夜神模拟器 + XposedInstaller + JustTrustMe
- 抽象类(abstract)
- 创建本地版PACS系统
- 使用语义分割架构的文档扫描仪 DeepLabV3
- Vue —— mockjs 模拟数据、轮播图插件 Swiper
- 吃透JAVA的Stream流操作,多年实践总结
- eChats折线图更新数据不自然,要闪一下,动态数据解决
- 关于SpringCloud,Spring容器重复初始化的问题
热门文章
- 十年 Java API 版权案终落地、Log4j 漏洞蛰伏八年后席卷全球,2021 年开源圈大事件盘点
- 基于深度模型的Out of Distribution(OOD)检测相关方法介绍
- VMware Workstation——虚拟机启动Ubuntu系统时报错:“另一个程序已锁定文件的一部分,进程无法访问”解决办法
- 常见15个C语言的标准库
- [转帖]pfSense软路由系统的使用
- Hiding in Plain Sight: A Longitudinal Study of Combosquatting Abuse
- 安卓开发入门教程-UI控件_EditText
- Python——使用ipython
- Swagger2简介
- 20 个好用的 Go 语言微服务开发框架