tensorflow计算交叉熵损失函数(cross_entropy)的方法总结

交叉熵损失函数是用来度量两个概率分布间的差异性,有关交叉熵损失函数的原理在这篇博客中讲解得很好。而本文主要对以下几种tensorflow中常用的交叉熵损失函数进行比较和总结:

  • tf.losses.sigmoid_cross_entropy
  • tf.nn.sigmoid_cross_entropy_with_logits
  • tf.losses.softmax_cross_entropy
  • tf.nn.softmax_cross_entropy_with_logits_v2
  • tf.losses.sparse_softmax_cross_entropy

1. tf.losses.sigmoid_cross_entropy

import tensorflow as tf

batch_size = 4
num_classes = 2
'''
tf.losses.sigmoid_cross_entropy适用于二分类问题,是对logits先进行sigmoid再求交叉熵
args:
    logits:不经过sigmoid处理的神经网络输出,是分类器对每个类别打的分数,shape:[batch_size, num_classes]
    labels:真实标签值,shape:[batch_size, num_classes]
'''
logits = tf.constant([[9., 2.],
                      [1, 7.],
                      [5., 4.],
                      [2., 8.]])
labels = tf.constant([0, 1, 0, 1])
one_hot_labels = tf.one_hot(labels, depth=num_classes, dtype=tf.int32)
loss = tf.losses.sigmoid_cross_entropy(multi_class_labels=one_hot_labels, logits=logits)

sess = tf.InteractiveSession()
print(loss.eval())

打印的结果为:loss:1.1991692

2. tf.nn.sigmoid_cross_entropy_with_logits

import tensorflow as tf

batch_size = 4
num_classes = 2
'''
tf.nn.sigmoid_cross_entropy_with_logits与tf.losses.sigmoid_cross_entropy的功能类似,主要差别如下:
    1. 前者要求logits和labels不仅要有相同的shape,还要有相同的type
    2. 前者的输出为一个list,后者的输出为一个具体的数值
args:
    logits:不经过sigmoid处理的神经网络输出,是分类器对每个类别打的分数,shape:[batch_size, num_classes]
    labels:真实标签值,shape:[batch_size,num_classes]
'''
logits = tf.constant([[9., 2.],
                      [1., 7.],
                      [5., 4.],
                      [2., 8.]])
# logits = tf.cast(logits, tf.float32)
labels = tf.constant([0, 1, 0, 1], dtype=tf.int32)
labels = tf.one_hot(labels, depth=num_classes, dtype=tf.float32)
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=labels, logits=logits))

sess = tf.InteractiveSession()
print(loss.eval())

打印的结果为:loss:1.1991692,与方法1的结果相同

3.tf.losses.softmax_cross_entropy

import tensorflow as tf

batch_size = 4
num_classes = 3
'''
tf.losses.softmax_cross_entropy适用于多分类问题,是对logits先进行softmax再求交叉熵
args:
    logits:不经过softmax处理的神经网络输出,是分类器对每个类别打的分数,shape:[batch_size, num_classes]
    labels:真实标签值,shape:[batch_size, num_classes]
'''
logits = tf.constant([[9., 2., 4.],
                      [1., 7., 3.],
                      [5., 4., 8.],
                      [2., 8., 9.]])
labels = tf.constant([1, 0, 2, 1])
one_hot_labels = tf.one_hot(labels, depth=num_classes, dtype=tf.int32)
loss = tf.losses.softmax_cross_entropy(onehot_labels=one_hot_labels, logits=logits)

sess = tf.InteractiveSession()
print(loss.eval())

打印结果为:loss:3.6020036

4.tf.nn.softmax_cross_entropy_with_logits_v2

import tensorflow as tf

batch_size = 4
num_classes = 3
'''
tf.nn.softmax_cross_entropy_with_logits_v2的功能与tf.losses.softmax_cross_entropy类似,两者的差别如下:
    1. 前者的输出为一个list,后者的输出为一个具体的值
args:
    logits:不经过softmax处理的神经网络输出,是分类器对每个类别打的分数,shape:[batch_size, num_classes]
    labels:真实标签值,shape:[batch_size, num_classes]
'''
logits = tf.constant([[9., 2., 4.],
                      [1., 7., 3.],
                      [5., 4., 8.],
                      [2., 8., 9.]])
labels = tf.constant([1, 0, 2, 1])
one_hot_labels = tf.one_hot(labels, depth=num_classes, dtype=tf.int32)
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=one_hot_labels, logits=logits))

sess = tf.InteractiveSession()
print(loss.eval())

打印的结果为:loss:3.6020036,与方法3的结果相同

5.tf.losses.sparse_softmax_cross_entropy

import tensorflow as tf

batch_size = 4
num_classes = 3
'''
tf.losses.sparse_softmax_cross_entropy的功能与tf.losses.softmax_cross_entropy类似,两者的差别如下:
    1. 前者的参数labels不需要ont_hot编码
args:
    logits:不经过softmax处理的神经网络输出,是分类器对每个类别打的分数,shape:[batch_size, num_classes]
    labels:真实标签值,shape:[batch_size,]
'''
logits = tf.constant([[9., 2., 4.],
                      [1., 7., 3.],
                      [5., 4., 8.],
                      [2., 8., 9.]])
labels = tf.constant([1, 0, 2, 1])
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)

sess = tf.InteractiveSession()
print(loss.eval())

打印的结果为:loss:3.6020036,与方法3和方法4的结果相同

总结:

  1. sigmoid交叉熵损失函数适用于二分类问题,softmax交叉熵损失函数适用于多分类问题。
  2. tf.nn模块中的损失函数输出为一个list,可用tf.reduce_mean()函数求均值作为最终损失;tf.losses模块中的损失函数输出为一个值。
  3. sparse_softmax_cross_entropy与softmax_cross_entropy的区别是前者的labels参数不需要one_hot编码,可以减少一些内存占用。
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以将这部分代码转化为PyTorch,转化后的代码如下: import torch import torch.nn as nn import torch.nn.functional as F def cross_entropy_loss(y_true, y_pred): # 计算交叉损失 cross_entropy = nn.CrossEntropyLoss()(y_pred, y_true) return cross_entropy def boundary_loss(y_true, y_pred): # 计算边界损失 boundary_filter = torch.tensor([[0, 1, 0], [1, -4, 1], [0, 1, 0]], dtype=torch.float32) boundary_filter = boundary_filter.view(1, 1, 3, 3) y_true_boundary = F.conv2d(y_true, boundary_filter, padding=1) y_pred_boundary = F.conv2d(y_pred, boundary_filter, padding=1) boundary_loss = F.mse_loss(y_true_boundary, y_pred_boundary) return boundary_loss def total_loss(y_true, y_pred): # 总损失函数 = 交叉损失 + 边界损失 return cross_entropy_loss(y_true, y_pred) + 0.5 * boundary_loss(y_true, y_pred) # 构建模型 class Model(nn.Module): def __init__(self): super(Model, self).__init__() self.conv1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, stride=1, padding=1) self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, stride=1, padding=1) self.pool = nn.MaxPool2d(kernel_size=2, stride=2) self.fc1 = nn.Linear(32*8*8, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = F.relu(self.conv1(x)) x = self.pool(F.relu(self.conv2(x))) x = x.view(-1, 32*8*8) x = F.relu(self.fc1(x)) x = self.fc2(x) return x model = Model() # 编译模型 optimizer = torch.optim.Adam(model.parameters(), lr=0.001) loss_fn = total_loss metrics = ['accuracy']
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值