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中操作字典之setdefault()方法的使用
May 21 Python
Python中摘要算法MD5,SHA1简介及应用实例代码
Jan 09 Python
Python实现图片尺寸缩放脚本
Mar 10 Python
python3中获取文件当前绝对路径的两种方法
Apr 26 Python
python实现爬取图书封面
Jul 05 Python
详解将Pandas中的DataFrame类型转换成Numpy中array类型的三种方法
Jul 06 Python
python通过TimedRotatingFileHandler按时间切割日志
Jul 17 Python
python numpy之np.random的随机数函数使用介绍
Oct 06 Python
python、Matlab求定积分的实现
Nov 20 Python
Pytorch释放显存占用方式
Jan 13 Python
基于python实现计算两组数据P值
Jul 10 Python
Python中的With语句的使用及原理
Jul 29 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
php Calender(日历)代码分享
2014/01/03 PHP
php设计模式之命令模式使用示例
2014/03/02 PHP
windows7下安装php的php-ssh2扩展教程
2014/07/04 PHP
php验证码实现代码(3种)
2015/09/07 PHP
非阻塞动态加载javascript广告实现代码
2010/11/17 Javascript
JS弹出对话框返回值代码(asp.net后台)
2010/12/28 Javascript
浅析JavaScript中的delete运算符
2013/11/30 Javascript
JS验证邮箱格式是否正确的代码
2013/12/05 Javascript
一个js过滤空格的小函数
2014/10/10 Javascript
js操作滚动条事件实例
2015/01/29 Javascript
JavaScript测试工具之Karma-Jasmine的安装和使用详解
2015/12/03 Javascript
微信小程序  audio音频播放详解及实例
2016/11/02 Javascript
实例解析jQuery工具函数
2016/12/01 Javascript
详解vuelidate 对于vueJs2.0的验证解决方案
2017/03/09 Javascript
常用的js方法合集
2017/03/10 Javascript
AngularJS中$http使用的简单介绍
2017/03/17 Javascript
jQuery插件FusionCharts绘制2D柱状图和折线图的组合图效果示例【附demo源码】
2017/04/10 jQuery
webpack打包单页面如何引用的js
2017/06/07 Javascript
简单实现jQuery弹窗效果
2017/10/30 jQuery
vue 组件 全局注册和局部注册的实现
2018/02/28 Javascript
JS原型与继承操作示例
2019/05/09 Javascript
vue实现PC端录音功能的实例代码
2019/06/05 Javascript
Node.js中出现未捕获异常的处理方法
2020/06/29 Javascript
python cookielib 登录人人网的实现代码
2012/12/19 Python
python程序封装为win32服务的方法
2021/03/07 Python
详解python中index()、find()方法
2019/08/29 Python
python编写俄罗斯方块
2020/03/13 Python
Python itertools.product方法代码实例
2020/03/27 Python
python读取excel进行遍历/xlrd模块操作
2020/07/12 Python
化石印度尼西亚在线商店:Fossil Indonesia
2019/03/11 全球购物
安全生产管理合理化建议书
2014/03/12 职场文书
2014年工商所工作总结
2014/12/09 职场文书
焦裕禄观后感
2015/06/03 职场文书
2015年暑假生活总结
2015/07/13 职场文书
初中语文教师研修日志
2015/11/13 职场文书
党员干部学习三严三实心得体会
2016/01/05 职场文书