一 softmax
计算loss时,预测值要与真实值分布在相同的数据区间内,例如真实值在[0,1]区间内,那么网络的预测值也要在相同的区间(0,1)内;这样在计算loss是才会有较好的效果。
在做二分类时,可在网络的输出层使用激活函数sigmoid(),将输出压缩在(0,1)区间,
softmax可看做是对sigmoid的扩展,是用于多分类的激活函数,softmax就是将网络的输出转化成对应类别的概率值;
二 cross_entropy
交叉熵是统计学中两个数据分布差异的一直度量;
其中p(x)是labels,q(x)是logits
三 tensorflow中计算cross_entropy的方式
(1)自己使用公式计算
soft_max = tf.nn.softmax(logits)
cross_entropy = -tf.reduce_sum(labels*tf.log(soft_max),1)
loss = tf.reduce_mean(cross_entropy)
上面,cross_entropy是一个shape是[batch_size]的tensor,而loss是shape是1的数值,需要使用tf.reduce_sum()或者tf.reduce_mean()计算当前batch_size的总交叉熵loss,或者平均交叉熵loss;
或者不指定tf.reduce_sum()的axis,直接求当前batch的交叉熵总和作为loss
soft_max = tf.nn.softmax(logits)
loss = -tf.reduce_sum(labels*tf.log(soft_max))
- tips:tf.reduce_sum()默认是计算输入tensor的总和,指定axis时,会按照指定的轴进行求和;
(2)Softmax交叉熵,label使用one_hot编码
使用tf.nn.softmax_cross_entropy_with_logits(logits,onehot_labels,name=None)
适用于每个类别独立并且相互排斥,也就是每张图片自能属于一种类别
输入:logits和labels必须具有相同的shape,和dtype。labels必须是one-hot编码形式。
输出:shape=[batch_size]的交叉熵cross_entropy
此函数会做两件事:
- 对网络输出使用softmax,转化成总和为1,对应于各个类别的概率值
- 使用交叉熵公式计算cross_entropy,此时cross_entropy是shape=[batch_size],可以认为是batch中每个图片的交叉熵的值;
同时要注意与tf.losses.softmax_cross_entropy(logits,onehot_labels)的区别, tf.losses.softmax_cross_entropy()返回的是平均交叉熵的值,相当于在tf.nn.softmax_cross_entropy_with_logits()后加上tf.reduce_mean()对交叉熵求平均,
此函数会做三件事:
- 对网络输出使用softmax,转化成总和为1,对应于各个类别的概率值
- 使用交叉熵公式计算cross_entropy,此时cross_entropy是shape=[batch_size],可以认为是batch中每个图片的交叉熵的值;
- 使用tf.reduce_mean(cross_entropy)计算平均交叉熵
(3)Softmax交叉熵,labels不使用one_hot编码
使用tf.nn.sparse_softmax_cross_entropy_with_logits(logits,labels,name=None)
适用于每个类别独立并且相互排斥
输入:logits[batch_size,num_classes],label是从0开始代表类别的整形数组,必须是非one-hot编码
输入:shape=[batch_size]的交叉熵cross_entropy
tf.losses.sparse_softmax_cross_entropy()也是相当于在tf.nn.sparse_softmax_cross_entropy_with_logits后加上tf.reduce_mean对列表求均值;
(4)sigmoid交叉熵,激活函数使用sigmoid
使用tf.nn.sigmoid_cross_entropy_with_logits(logits,labels,name=None)
适用于每个类别相互独立,并且不相互排斥,也就是说每个图片可以属于多个类别;
输入:logits,labels 必须具有相同的shape和type
输出:shape=[batch_size,num_classes]当前batch中网络输出节点每个节点的cross_entropy
用sigmoid做分类原本只能用于二分类,例如,网络输出节点1个,使用sigmoid函数将网络输出压缩至(0,1)范围内,用0和1代表两个类别;
将sigmoid扩展至多分类,例如假设num_classes=10,对一张图片中包含的数字(0~9)做分类(一张图片可能包含多种数字),标签label可能是(1,0,1,1,0,0,1,0,1,0)(图片包含0,2,3,6,8,数字),那么将网络的输出节点设置为10,对于每个节点使用都sigmoid激活函数来做二分类,判断是/不是当前类别;如第一个输出节点判别是否包含数字1,第二个判别是否包含数字2......
loss使用交叉熵cross_entropy=-labels(tf.log(sigmoid(logits)))-(1-labels(tf.log(1-sigmoid(logits))))
或者使用tf.nn.sigmoid_cross_entropy_with_logits(logits,labels,name=None)
loss = tf.reduce_mean(cross_entropy)
或者使用tf.losses.sigmoid_cross_entropy()直接求平均交叉熵loss。
- tips:softmax激活函数会使用所用的输出节点一起来计算属于每个类别的概率,而sigmoid激活函数只针对当前节点,返回包含当前节点类别的概率,
此函数会做两件事:
- 对网络输出使用sigmoid,
- 使用交叉熵公式计算cross_entropy