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中的文件操作
Aug 28 Python
python模拟登录并且保持cookie的方法详解
Apr 04 Python
python实现单向链表详解
Feb 08 Python
python 获取当天每个准点时间戳的实例
May 22 Python
Python机器学习库scikit-learn安装与基本使用教程
Jun 25 Python
Python输出\u编码将其转换成中文的实例
Dec 15 Python
解决python3 HTMLTestRunner测试报告中文乱码的问题
Dec 17 Python
Python3获取拉勾网招聘信息的方法实例
Apr 03 Python
把JSON数据格式转换为Python的类对象方法详解(两种方法)
Jun 04 Python
在Django中自定义filter并在template中的使用详解
May 19 Python
windows10在visual studio2019下配置使用openCV4.3.0
Jul 14 Python
Pyqt5将多个类组合在一个界面显示的完整示例
Sep 04 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实现网页端验证码功能
2017/07/11 PHP
基于PHP实现生成随机水印图片
2020/12/09 PHP
Ajax::prototype 源码解读
2007/01/22 Javascript
DOM相关内容速查手册
2007/02/07 Javascript
ExtJS 2.0 GridPanel基本表格简明教程
2010/05/25 Javascript
原生js实现查找/添加/删除/指定元素的class
2013/04/12 Javascript
javascript:json数据的页面绑定示例代码
2014/01/26 Javascript
jQuery简单tab切换效果实现方法
2015/04/08 Javascript
jQuery实现标题有打字效果的焦点图代码
2015/11/16 Javascript
基于JavaScript实现图片点击弹出窗口而不是保存
2016/02/06 Javascript
深入理解javascript中concat方法
2016/12/12 Javascript
js仿京东轮播效果 选项卡套选项卡使用
2017/01/12 Javascript
js实现5秒倒计时重新发送短信功能
2017/02/05 Javascript
zTree节点文字过多的处理方法
2017/11/24 Javascript
vue 实现通过手机发送短信验证码注册功能
2018/04/19 Javascript
webpack4 处理SCSS的方法示例
2018/09/03 Javascript
JS中使用new Option()实现时间联动效果
2018/12/10 Javascript
layer父页获取弹出层输入框里面的值方法
2019/09/02 Javascript
[02:36]DOTA2混沌骑士 英雄基础教程
2013/11/26 DOTA
[44:15]DOTA2上海特级锦标赛主赛事日 - 5 败者组决赛Liquid VS EG第二局
2016/03/06 DOTA
Python中的Numeric包和Numarray包使用教程
2015/04/13 Python
Python将DataFrame的某一列作为index的方法
2018/04/08 Python
用TensorFlow实现多类支持向量机的示例代码
2018/04/28 Python
Python学习笔记之变量、自定义函数用法示例
2019/05/28 Python
python中hasattr()、getattr()、setattr()函数的使用
2019/08/16 Python
python3.x 生成3维随机数组实例
2019/11/28 Python
Python While循环语句实例演示及原理解析
2020/01/03 Python
pytorch 彩色图像转灰度图像实例
2020/01/13 Python
Python嵌入C/C++进行开发详解
2020/06/09 Python
Java Unsafe类实现原理及测试代码
2020/09/15 Python
美国中小型企业领先的办公家具供应商:Office Designs
2016/11/26 全球购物
建筑个人求职信范文
2014/01/25 职场文书
煤矿安全承诺书
2014/05/22 职场文书
外出学习心得体会范文
2016/01/18 职场文书
html5实现点击弹出图片功能
2021/07/16 HTML / CSS
Python爬虫 简单介绍一下Xpath及使用
2022/04/26 Python