TensorFlow损失函数专题详解


Posted in Python onApril 26, 2018

一、分类问题损失函数——交叉熵(crossentropy)

交叉熵刻画了两个概率分布之间的距离,是分类问题中使用广泛的损失函数。给定两个概率分布p和q,交叉熵刻画的是两个概率分布之间的距离:

TensorFlow损失函数专题详解

我们可以通过Softmax回归将神经网络前向传播得到的结果变成交叉熵要求的概率分布得分。在TensorFlow中,Softmax回归的参数被去掉了,只是一个额外的处理层,将神经网络的输出变成一个概率分布。

代码实现:

import tensorflow as tf 
 
y_ = tf.constant([[1.0, 0, 0]]) # 正确标签 
y1 = tf.constant([[0.9, 0.06, 0.04]]) # 预测结果1 
y2 = tf.constant([[0.5, 0.3, 0.2]]) # 预测结果2 
# 以下为未经过Softmax处理的类别得分 
y3 = tf.constant([[10.0, 3.0, 2.0]]) 
y4 = tf.constant([[5.0, 3.0, 1.0]]) 
 
# 自定义交叉熵 
cross_entropy1 = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y1, 1e-10, 1.0))) 
cross_entropy2 = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y2, 1e-10, 1.0))) 
# TensorFlow提供的集成交叉熵 
# 注:该操作应该施加在未经过Softmax处理的logits上,否则会产生错误结果 
# labels为期望输出,且必须采用labels=y_, logits=y的形式将参数传入 
cross_entropy_v2_1 = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y3) 
cross_entropy_v2_2 = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y4) 
 
sess = tf.InteractiveSession() 
print('[[0.9, 0.06, 0.04]]:', cross_entropy1.eval()) 
print('[[0.5, 0.3, 0.2]]:', cross_entropy2.eval()) 
print('v2_1', cross_entropy_v2_1.eval()) 
print('v2_2',cross_entropy_v2_2.eval()) 
sess.close() 
 
''''' 
[[0.9, 0.06, 0.04]]: 0.0351202 
[[0.5, 0.3, 0.2]]: 0.231049 
v2_1 [ 0.00124651] 
v2_2 [ 0.1429317] 
'''

tf.clip_by_value()函数可将一个tensor的元素数值限制在指定范围内,这样可防止一些错误运算,起到数值检查作用。

* 乘法操作符是元素之间直接相乘,tensor中是每个元素对应相乘,要去别去tf.matmul()函数的矩阵相乘。

tf.nn.softmax_cross_entropy_with_logits(labels=y_,logits=y)是TensorFlow提供的集成交叉熵函数。该操作应该施加在未经过Softmax处理的logits上,否则会产生错误结果;labels为期望输出,且必须采用labels=y_, logits=y3的形式将参数传入。

二、回归问题损失函数——均方误差(MSE,mean squared error)

均方误差亦可用于分类问题的损失函数,其定义为:

TensorFlow损失函数专题详解

三、自定义损失函数

对于理想的分类问题和回归问题,可采用交叉熵或者MSE损失函数,但是对于一些实际的问题,理想的损失函数可能在表达上不能完全表达损失情况,以至于影响对结果的优化。例如:对于产品销量预测问题,表面上是一个回归问题,可使用MSE损失函数。可实际情况下,当预测值大于实际值时,损失值应是正比于商品成本的函数;当预测值小于实际值,损失值是正比于商品利润的函数,多数情况下商品成本和利润是不对等的。自定义损失函数如下:

TensorFlow损失函数专题详解

TensorFlow中,通过以下代码实现loss= tf.reduce_sum(tf.where(tf.greater(y, y_), (y-y_)*loss_more,(y_-y)*loss_less))。

tf.greater(x,y),返回x>y的判断结果的bool型tensor,当tensor x, y的维度不一致时,采取广播(broadcasting)机制。

tf.where(condition,x=None, y=None, name=None),根据condition选择x (if true) or y (if false)。

代码实现:

import tensorflow as tf 
from numpy.random import RandomState 
 
batch_size = 8 
x = tf.placeholder(tf.float32, shape=(None, 2), name='x-input') 
y_ = tf.placeholder(tf.float32, shape=(None, 1), name='y-input') 
 
w1 = tf.Variable(tf.random_normal([2,1], stddev=1, seed=1)) 
y = tf.matmul(x, w1) 
 
# 根据实际情况自定义损失函数 
loss_less = 10 
loss_more = 1 
# tf.select()在1.0以后版本中已删除,tf.where()替代 
loss = tf.reduce_sum(tf.where(tf.greater(y, y_), 
        (y-y_)*loss_more, (y_-y)*loss_less)) 
train_step = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss) 
 
rdm = RandomState(seed=1) # 定义一个随机数生成器并设定随机种子 
dataset_size = 128 
X = rdm.rand(dataset_size, 2) 
Y = [[x1 + x2 +rdm.rand()/10.0 - 0.05] for (x1, x2) in X] # 增加一个-0.05~0.05的噪声 
 
sess = tf.InteractiveSession() 
tf.global_variables_initializer().run() 
for i in range(5000): 
 start = (i * batch_size) % dataset_size 
 end = min(start+batch_size, dataset_size) 
 train_step.run({x: X[start: end], y_: Y[start: end]}) 
 if i % 500 == 0: 
  print('step%d:\n' % i, w1.eval()) 
print('final w1:\n', w1.eval()) 
sess.close() 
 
''''' 
loss_less = 10 
loss_more = 1 
final w1: 
 [[ 1.01934695] 
 [ 1.04280889]] 
 
loss_less = 1 
loss_more = 10 
final w1: 
 [[ 0.95525807] 
 [ 0.9813394 ]] 
 
loss_less = 1 
loss_more = 1 
final w1: 
 [[ 0.9846065 ] 
 [ 1.01486754]] 
'''

根据程序输出可见,当我们将loss_less=10时,表明我们对预测值过小表征的损失值更大,优化得到的参数均略大于1;当loss_more=10时,表明我们对预测值过大表征的损失值更大,优化得到的参数均略小于1;当两者均设为1时,得到的参数约等于1。

四、TensorFlow的Cross_Entropy实现

1. tf.nn.softmax_cross_entropy_with_logits(_sentinel=None,labels=None, logits=None, dim=-1, name=None)

该函数的功能是自动计算logits(未经过Softmax)与labels之间的cross_entropy交叉熵。

该操作应该施加在未经过Softmax处理的logits上,否则会产生错误结果;labels为期望输出,且必须采用labels=y_,logits=y3的形式将参数传入。

第一个参数logits:就是神经网络最后一层的输出,如果有batch的话,它的大小就是[batchsize,num_classes],单样本的话,大小就是num_classes

第二个参数labels:实际的标签,大小同上。

注意:如果labels的每一行是one-hot表示,也就是只有一个地方为1,其他地方为0,可以使用tf.sparse_softmax_cross_entropy_with_logits()

警告: (1)这个操作的输入logits是未经缩放的,该操作内部会对logits使用softmax操作;(2)参数labels,logits必须有相同的形状 [batch_size, num_classes] 和相同的类型(float16, float32,float64)中的一种。

该函数具体的执行过程分两步:首先对logits做一个Softmax,

TensorFlow损失函数专题详解

第二步就是将第一步的输出与样本的实际标签labels做一个交叉熵。

TensorFlow损失函数专题详解

注意!!!这个函数的返回值并不是一个数,而是一个向量,如果要求交叉熵,我们要再做一步tf.reduce_sum操作,就是对向量里面所有元素求和,最后才得到交叉熵,如果求loss,则要做一步tf.reduce_mean操作,对向量求均值!

2. tf.nn.sparse_softmax_cross_entropy_with_logits(_sentinel=None,labels=None, logits=None, name=None)

该函数与tf.nn.softmax_cross_entropy_with_logits(_sentinel=None,labels=None, logits=None, dim=-1, name=None)十分相似,唯一的区别在于labels,该函数的标签labels要求是排他性的即只有一个正确类别,labels的形状要求是[batch_size] 而值必须是从0开始编码的int32或int64,而且值范围是[0, num_class),对比于tf.nn.softmax_cross_entropy_with_logits的[batchsize,num_classes]格式的得分编码。

其他使用注意事项参见tf.nn.softmax_cross_entropy_with_logits的说明。

3. tf.nn.sigmoid_cross_entropy_with_logits(_sentinel=None,labels=None, logits=None, name=None)

sigmoid_cross_entropy_with_logits是TensorFlow最早实现的交叉熵算法。这个函数的输入是logits和labels,logits就是神经网络模型中的 W * X矩阵,注意不需要经过sigmoid,而labels的shape和logits相同,就是正确的标签值,例如这个模型一次要判断100张图是否包含10种动物,这两个输入的shape都是[100, 10]。注释中还提到这10个分类之间是独立的、不要求是互斥,这种问题我们称为多目标(多标签)分类,例如判断图片中是否包含10种动物中的一种或几种,标签值可以包含多个1或0个1。

4. tf.nn.weighted_cross_entropy_with_logits(targets, logits, pos_weight, name=None)

weighted_sigmoid_cross_entropy_with_logits是sigmoid_cross_entropy_with_logits的拓展版,多支持一个pos_weight参数,在传统基于sigmoid的交叉熵算法上,正样本算出的值乘以某个系数。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python迭代器与生成器详解
Mar 10 Python
SVM基本概念及Python实现代码
Dec 27 Python
TensorFlow实现Softmax回归模型
Mar 09 Python
详解【python】str与json类型转换
Apr 29 Python
基于python的Paxos算法实现
Jul 03 Python
django的auth认证,authenticate和装饰器功能详解
Jul 25 Python
python日志模块logbook使用方法
Sep 19 Python
python导入不同目录下的自定义模块过程解析
Nov 18 Python
解决Python使用列表副本的问题
Dec 19 Python
Python 实现向word(docx)中输出
Feb 13 Python
浅析Python 抽象工厂模式的优缺点
Jul 13 Python
python区块链实现简版工作量证明
May 25 Python
浅谈Tensorflow模型的保存与恢复加载
Apr 26 #Python
Python实现爬取百度贴吧帖子所有楼层图片的爬虫示例
Apr 26 #Python
Python实现的计算器功能示例
Apr 26 #Python
python email smtplib模块发送邮件代码实例
Apr 26 #Python
Python利用正则表达式实现计算器算法思路解析
Apr 25 #Python
Python实现随机生成手机号及正则验证手机号的方法
Apr 25 #Python
Python实现按中文排序的方法示例
Apr 25 #Python
You might like
一个简洁的多级别论坛
2006/10/09 PHP
PHP新手NOTICE错误常见解决方法
2011/12/07 PHP
php获取随机数组列表的方法
2014/11/13 PHP
PDO预处理语句PDOStatement对象使用总结
2014/11/20 PHP
微信公众平台开发实现2048游戏的方法
2015/04/15 PHP
php+flash+jQuery多图片上传源码分享
2020/07/27 PHP
yii2实现Ueditor百度编辑器的示例代码
2018/11/02 PHP
DHTML 中的绝对定位
2006/11/26 Javascript
jquery 模拟类搜索框自动完成搜索提示功能(改进)
2010/05/24 Javascript
Javascript 浮点运算的问题分析与解决方法
2013/08/27 Javascript
js截取字符串的两种方法及区别详解
2013/11/05 Javascript
localResizeIMG先压缩后使用ajax无刷新上传(移动端)
2015/08/11 Javascript
第二次聊一聊JS require.js模块化工具的基础知识
2016/04/17 Javascript
利用Javascript仿Excel的数据透视分析功能
2016/09/07 Javascript
jquery实现拖动效果(代码分享)
2017/01/25 Javascript
Vuex之理解Store的用法
2017/04/19 Javascript
浅谈angular4 ng-content 中隐藏的内容
2017/08/18 Javascript
vue实现分页组件
2020/06/16 Javascript
ES6 class的应用实例分析
2019/06/27 Javascript
微信小程序实现页面浮动导航
2020/01/08 Javascript
package.json各个属性说明详解
2020/03/11 Javascript
Vue toFixed保留两位小数的3种方式
2020/10/23 Javascript
Python基础篇之初识Python必看攻略
2016/06/23 Python
Python3自动签到 定时任务 判断节假日的实例
2018/11/13 Python
python远程连接MySQL数据库
2019/04/19 Python
安装完Python包然后找不到模块的解决步骤
2020/02/13 Python
使用tensorflow实现VGG网络,训练mnist数据集方式
2020/05/26 Python
详解Python遍历列表时删除元素的正确做法
2021/01/07 Python
美国生日蛋糕店:Bake Me A Wish!
2017/02/08 全球购物
尤为Wconcept中国官网:韩国设计师品牌服饰
2019/01/10 全球购物
一些网络技术方面的面试题
2014/05/01 面试题
建筑工程毕业生自我鉴定
2014/01/14 职场文书
房屋出租协议书
2014/04/10 职场文书
春季防火方案
2014/05/10 职场文书
大学生个人总结范文
2015/02/15 职场文书
详解ZABBIX监控ESXI主机的问题
2022/06/21 Servers