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 django使用haystack:全文检索的框架(实例讲解)
Sep 27 Python
python正则实现计算器功能
Dec 14 Python
Python企业编码生成系统之系统主要函数设计详解
Jul 26 Python
Python线上环境使用日志的及配置文件
Jul 28 Python
Python 如何提高元组的可读性
Aug 26 Python
python 字典访问的三种方法小结
Dec 05 Python
django-xadmin根据当前登录用户动态设置表单字段默认值方式
Mar 13 Python
PyQt5 控件字体样式等设置的实现
May 13 Python
python绘制分布折线图的示例
Sep 24 Python
Python 微信公众号文章爬取的示例代码
Nov 30 Python
pandas 操作 Excel操作总结
Mar 31 Python
Python pyecharts绘制条形图详解
Apr 02 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原理之Session Gc的一个小概率Notice
2011/04/12 PHP
JS的replace方法介绍
2012/10/20 Javascript
Node.js开发指南中的简单实例(mysql版)
2013/09/17 Javascript
jquery给图片添加鼠标经过时的边框效果
2013/11/12 Javascript
jQuery 获取兄弟元素的几种不错方法
2014/05/23 Javascript
同一个网页中实现多个JavaScript特效的方法
2015/02/02 Javascript
JS日期加减,日期运算代码
2015/11/05 Javascript
Angularjs结合Bootstrap制作的一个TODO List
2016/08/18 Javascript
javascript数字验证的实例代码(推荐)
2016/08/20 Javascript
jQuery基于ajax操作json数据简单示例
2017/01/05 Javascript
基于node.js依赖express解析post请求四种数据格式
2017/02/13 Javascript
jQuery插件echarts实现的多柱子柱状图效果示例【附demo源码下载】
2017/03/04 Javascript
详解微信小程序设置底部导航栏目方法
2017/06/29 Javascript
使用MUI框架模拟手机端的下拉刷新和上拉加载功能
2017/09/04 Javascript
JavaScript多态与封装实例分析
2018/07/27 Javascript
vue添加class样式实例讲解
2019/02/12 Javascript
微信小程序如何获取群聊的openGid以及名称详解
2019/07/17 Javascript
IntelliJ IDEA编辑器配置vue高亮显示
2019/09/26 Javascript
Vue仿百度搜索功能
2020/12/28 Vue.js
python中的break、continue、exit()、pass全面解析
2017/08/05 Python
Python实现基本数据结构中栈的操作示例
2017/12/04 Python
Python pygorithm模块用法示例【常见算法测试】
2018/08/16 Python
Python基于WordCloud制作词云图
2019/11/29 Python
python的sys.path模块路径添加方式
2020/03/09 Python
python实现最短路径的实例方法
2020/07/19 Python
python开发一个解析protobuf文件的简单编译器
2020/11/17 Python
Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?用contains来区分是否有重复的对象。还是都不用
2013/07/30 面试题
关于Assembly命名空间的三个面试题
2015/07/23 面试题
雪山饭庄的创业计划书范文
2014/01/18 职场文书
8和9的加减法教学反思
2014/05/01 职场文书
工地安全标语
2014/06/07 职场文书
会计系毕业求职信
2014/08/07 职场文书
初中同学会致辞
2015/08/01 职场文书
护理专业毕业自我鉴定
2019/08/12 职场文书
PHP中->和=>的意思
2021/03/31 PHP
python基础之类方法和静态方法
2021/10/24 Python