前言
在TensorFlow中提供了挺多损失函数的,这里主要测试一下均方差与交叉熵相关的几个函数的计算流程。主要是测试来自于tf.nn
与tf.losses
的mean_square_error
、sigmoid_cross_entry
、softmax_cross_entry
、sparse_softmax_cross_entry
国际惯例,参考博客:
预备
单热度编码one-hot
先复习一下one_hot
编码,就是将真实标签转换为01标签,需要注意的是tf的one_hot
编码中标签0代表的是1,0,0...
而非0,0,0...
labels_n=np.array([0,1,2])
labels_oh=tf.one_hot(labels_n,depth=3)
with tf.Session() as sess:
print(sess.run(labels_oh))
'''
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
'''
softmax
通常将最后的输出规整到和为1的形式:
softmax = tf.exp(logits) / tf.reduce_sum(tf.exp(logits), axis)
设输出为,则
sigmoid
激活函数:
交叉熵
多标签分类(每个样本可能属于多个标签),最后一层使用sigmoid
激活:
单标签分类(每个样本只可能属于一个标签),最后一层使用softmax
激活:
准备测试
进入测试之前,需要先引入相关的包
import numpy as np
import tensorflow as tf
交叉熵相关函数的测试,使用的变量是
labels=np.array([[1,0,0],[0,1,0],[0,0,1]],dtype='float32')
preds=np.array([[5,6,3],[7,5,1],[1,2,8]],dtype='float32')
均方差损失-MSE
原理
对应项相减的平方和的均值,通常用来做回归,计算预测值与真实值的误差
代码测试
定义相关变量:
ori_labels=np.array([[1,2,3]],dtype='float32')
pred_labels=np.array([[5,3,3]],dtype='float32')
调用原本函数测试:
mse_op=tf.losses.mean_squared_error(labels=ori_labels,predictions=pred_labels)
with tf.Session() as sess:
print(sess.run(mse_op))
'''
5.6666665
'''
手动实现过程:
with tf.Session() as sess:
print(sess.run(tf.reduce_mean(tf.square(ori_labels-pred_labels))))
'''
5.6666665
'''
总结
原理就是求原标签与预测标签的平方和损失的均值。
sigmoid_cross_entry
原理
使用sigmoid
激活的交叉熵,毫无疑问,玩得多标签分类,流程是:
- 将输出用
sigmoid
激活 - 使用多标签分类的交叉熵计算损失
代码测试
使用tf.losses
中的交叉熵损失
tf_sce=tf.losses.sigmoid_cross_entropy(labels,preds)
with tf.Session() as sess:
print(sess.run(tf_sce))
#2.3132434
使用tf.nn
中的交叉熵损失:
tf_sce1=tf.nn.sigmoid_cross_entropy_with_logits(labels=labels,logits=preds)
with tf.Session() as sess:
print(sess.run(tf_sce1))
'''
[[6.7153485e-03 6.0024757e+00 3.0485873e+00]
[7.0009112e+00 6.7153485e-03 1.3132617e+00]
[1.3132617e+00 2.1269281e+00 3.3540637e-04]]
'''
使用流程实现:
#先计算sigmoid,再计算交叉熵
preds_sigmoid=tf.sigmoid(preds)
ce=-labels*tf.log(preds_sigmoid)-(1-labels)*(tf.log(1-preds_sigmoid))
# ce= - tf.reduce_sum(labels*tf.log(preds_sigmoid),-1)
with tf.Session() as sess:
print(sess.run(ce))
print(sess.run(tf.reduce_mean(ce)))
'''
[[6.7153242e-03 6.0024934e+00 3.0485876e+00]
[7.0009704e+00 6.7153242e-03 1.3132617e+00]
[1.3132617e+00 2.1269276e+00 3.3539196e-04]]
2.3132522
'''
总结
-
多标签分类,输入是原始和预测标签的编码
-
tf.losses
中的计算结果是tf.nn
中计算结果的均值
softmax_cross_entry
原理
使用softmax
激活,显然就是单标签分类的情况,流程是:
- 将输出用
softmax
激活 - 计算单标签分类的交叉熵损失
代码测试
使用tf.losses
中的函数:
tf_sce=tf.losses.softmax_cross_entropy(labels,preds)
with tf.Session() as sess:
print(sess.run(tf_sce))
#1.160502
使用tf.nn
中的函数:
tf_sce1=tf.nn.softmax_cross_entropy_with_logits(labels=labels,logits=preds)
with tf.Session() as sess:
print(sess.run(tf_sce1))
#[1.3490121 2.129109 0.00338493]
使用流程计算:
#先计算softmax,再计算交叉熵
preds_sigmoid=tf.nn.softmax(preds)
ce= - tf.reduce_sum(labels*tf.log(preds_sigmoid),-1)
# ce=-labels*tf.log(preds_sigmoid)-(1-labels)*(tf.log(1-preds_sigmoid))
with tf.Session() as sess:
print(sess.run(ce))
print(sess.run(tf.reduce_mean(ce)))
'''
[1.3490121 2.129109 0.00338495]
1.1605021
'''
总结
- 用於单标签分类,输入是真实和预测标签的单热度编码
tf.losses
中的计算结果是tf.nn
中计算结果的均值
sparse_softmax_cross_entry
原理
还是看到softmax
,依旧是单标签分类,但是多了个sparse
,代表输入标签可以是非单热度标签,流程:
- 将原标签转为单热度编码
- 将输出用
softmax
激活 - 计算单标签分类的交叉熵
代码测试
假设原始标签的非单热度编码是:
labels_n=np.array([0,1,2])
利用tf.losses
中的损失函数:
tf_scen=tf.losses.sparse_softmax_cross_entropy(labels=labels_n,logits=preds)
with tf.Session() as sess:
print(sess.run(tf_sce))
#1.160502
利用tf.nn
中的损失函数:
tf_sce1=tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels_n,logits=preds)
with tf.Session() as sess:
print(sess.run(tf_sce1))
print(sess.run(tf.reduce_mean(tf_sce1)))
'''
[1.3490121 2.129109 0.00338493]
1.160502
'''
利用流程实现:
labels_onehot=tf.one_hot(labels_n,depth=3)
preds_sigmoid=tf.nn.softmax(preds)
ce= - tf.reduce_sum(labels_onehot*tf.log(preds_sigmoid),-1)
# ce=-labels*tf.log(preds_sigmoid)-(1-labels)*(tf.log(1-preds_sigmoid))
with tf.Session() as sess:
print(sess.run(labels_onehot))
print(sess.run(ce))
print(sess.run(tf.reduce_mean(ce)))
'''
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
[1.3490121 2.129109 0.00338495]
1.1605021
'''
总结
- 有
sparse
代表原始标签不用转成单热度编码 - 适用於单标签分类
tf.losses
是tf.nn
中函数的均值
总结
本文主要对比了:
tf.nn
、tf.losses
中同一类损失函数的使用方法与区别- 分析计算流程,并实现验证
- 了解
TensorFlow
中回归、单标签分类、多标签分类的损失函数的选择
博客代码:
链接:https://pan.baidu.com/s/1b40rNxjdOIIE2g7_Afctiw
提取码:0sb0