交叉熵损失函数(Cross-Entropy Loss)

06-02 566阅读

原理

交叉熵损失函数是深度学习中分类问题常用的损失函数,特别适用于多分类问题。它通过度量预测分布与真实分布之间的差异,来衡量模型输出的准确性。

交叉熵的数学公式

交叉熵的定义如下:

C r o s s E n t r o y L o s s = − ∑ i = 1 N y i ⋅ l o g ( y ^ i ) \begin{equation} CrossEntroyLoss = -\sum_{i=1}^{N}y_i \cdot log(\hat{y}_i) \end{equation} CrossEntroyLoss=−i=1∑N​yi​⋅log(y^​i​)​​

  • N N N:类别数
  • y i y_i yi​:真实的标签(用 one-hot 编码表示,只有目标类别对应的位置为 1,其他位置为 0)。
  • y ^ i \hat{y}_i y^​i​​:模型的预测概率,即 softmax 的输出值。

    对于单个样本:

    L o s s = − l o g ( y ^ c ) \begin{equation} Loss = -log(\hat{y}_c) \end{equation} Loss=−log(y^​c​)​​

    其中 c c c是真实类别的索引。

    解释:

    • 如果模型的预测概率 y ^ c \hat{y}_c y^​c​越接近1,则 − l o g ( y ^ c ) -log(\hat{y}_c) −log(y^​c​)越小,损失越大。
    • 如果 y ^ c \hat{y}_c y^​c​越接近0,则 − l o g ( y ^ c ) -log(\hat{y}_c) −log(y^​c​)​越大,损失越大。
      交叉熵损失和softmax函数的关系
      • 模型通常输出logits(未归一化的分数),例如 [ z 1 , z 2 , ⋯   , z N ] [z_1,z_2,\cdots,z_N] [z1​,z2​,⋯,zN​]。

      • softmax函数将logits转化为概率分布:

        y ^ i = z z i ∑ j = 1 N e z j \begin{equation} \hat{y}_i = \dfrac{z^{z_i}}{\sum_{j=1}^N e^{z_j}} \end{equation} y^​i​=∑j=1N​ezj​zzi​​​​

      • 交叉熵损失结合 softmax,用来计算预测分布与真实分布之间的差异。

        在 PyTorch 的 CrossEntropyLoss 中,softmax 和交叉熵是结合在一起实现的,因此你不需要手动调用 softmax。

        特性

        应用场景:

        • 多分类任务,例如图像分类、文本分类等。
        • 真实标签通常以整数形式存储(如 0, 1, 2)。

          数值稳定性:

          • 由于 softmax 和交叉熵结合在一起,可以避免单独计算 softmax 导致的数值不稳定问题。

            Pytorch中的实现

            构造函数

            PyTorch 提供了 torch.nn.CrossEntropyLoss:

            torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduction='mean')
            

            参数说明:

            • weight:用于对不同类别赋予不同的权重。
            • ignore_index:指定忽略某些类别的损失(通常用于处理 padding)。
            • reduction:决定损失的输出形式:
              • 'mean'(默认):返回损失的均值。
              • 'sum':返回损失的总和。
              • 'none':返回每个样本的损失值。
                使用示例

                1、单样本交叉熵损失

                import torch
                import torch.nn as nn
                # 模型的输出 logits 和真实标签
                logits = torch.tensor([[2.0, 1.0, 0.1]])  # 未经过 softmax 的输出
                labels = torch.tensor([0])               # 真实标签(类别索引)
                # 定义交叉熵损失函数
                criterion = nn.CrossEntropyLoss()
                # 计算损失
                loss = criterion(logits, labels)
                print("CrossEntropyLoss:", loss.item())
                

                解释:

                • logits 是未归一化的分数。
                • labels 是类别索引(如类别 0)。
                • 内部会先对 logits 应用 softmax,再计算交叉熵损失。

                  计算细节:

                  a)、给定的数据

                  • logits: [ 2.0 1.0 0.1 ] \begin{bmatrix} 2.0 & 1.0 & 0.1 \end{bmatrix} [2.0​1.0​0.1​]
                    • 这是模型输出的未归一化分数(logits)。
                    • labels: [ 0 ] \begin{bmatrix} 0 \end{bmatrix} [0​]
                      • 真实标签,表示类别索引(0 表示第一类)。

                        b)、CrossEntropyLoss 的计算公式,交叉熵损失公式如下:

                        L o s s = − 1 N ∑ i = 1 N l o g ( e x p ( l o g i t y i ) ∑ j e x p ( l o g i t j ) ) \begin{equation} Loss = -\dfrac{1}{N} \sum_{i=1}^{N} log \left( \dfrac{exp(logit_{y_i})}{\sum_j exp(logit_j)} \right) \end{equation} Loss=−N1​i=1∑N​log(∑j​exp(logitj​)exp(logityi​​)​)​​

                        其中:

                        • N N N: 样本数量(在这里为 1)。
                        • l o g i t j logit_j logitj​: 第 j j j类的 logit 值。
                        • y i y_i yi​: 样本 i i i​ 的真实类别索引。

                          c)、具体的步骤

                          step 1:softmax计算概率分布

                          softmax函数将logits转换为概率分布:

                          s o f t m a x ( z i ) = e x p ( z i ) ∑ j e x p ( z j ) \begin{equation} softmax(z_i) = \dfrac{exp(z_i)}{\sum_j exp(z_j)} \end{equation} softmax(zi​)=∑j​exp(zj​)exp(zi​)​​​

                          对于logits: [ 2.0 1.0 0.1 ] \begin{bmatrix} 2.0 & 1.0 & 0.1 \end{bmatrix} [2.0​1.0​0.1​],计算如下:

                          • 计算每个元素的指数:

                            e x p ( 2.0 ) = e 2 ≈ 7.389 , e x p ( 1.0 ) = e 1 ≈ 2.718 , e x p ( 0.1 ) = e 0.1 ≈ 1.105 \begin{equation} exp(2.0)=e^2 \approx 7.389, \quad exp(1.0)=e^1 \approx 2.718, \quad exp(0.1)=e^{0.1} \approx 1.105 \end{equation} exp(2.0)=e2≈7.389,exp(1.0)=e1≈2.718,exp(0.1)=e0.1≈1.105​​

                            • 求和:

                              s u m = 7.389 + 2.718 + 1.105 ≈ 11.212 \begin{equation} sum = 7.389 + 2.718 + 1.105 \approx 11.212 \end{equation} sum=7.389+2.718+1.105≈11.212​​

                              • 计算每个类别的概率:

                                s o f t m a x ( 2.0 ) = 7.389 11.212 ≈ 0.659 , s o f t m a x ( 1.0 ) = 2.718 11.212 ≈ 0.242 , s o f t m a x ( 0.1 ) = 1.105 11.212 ≈ 0.099 \begin{equation} softmax(2.0)=\dfrac{7.389}{11.212} \approx 0.659,\quad softmax(1.0)=\dfrac{2.718}{11.212} \approx 0.242,\quad softmax(0.1)=\dfrac{1.105}{11.212} \approx 0.099 \end{equation} softmax(2.0)=11.2127.389​≈0.659,softmax(1.0)=11.2122.718​≈0.242,softmax(0.1)=11.2121.105​≈0.099​​

                                概率分布为:

                                [ 0.659 0.242 0.099 ] \begin{bmatrix} 0.659 & 0.242 & 0.099 \end{bmatrix} [0.659​0.242​0.099​]

                                step 2:取真实标签对应的概率

                                真实标签 y = 0 y=0 y=0,对应的概率为第一个类别的softmax输出:

                                P ( y = 0 ) = 0.659 \begin{equation} P(y=0)=0.659 \end{equation} P(y=0)=0.659​​

                                step 3:计算交叉熵损失

                                根据交叉熵公式,损失为:

                                L o s s = − l o g ( P ( y = 0 ) ) = − l o g ( 0.659 ) \begin{equation} Loss = -log(P(y=0)) = -log(0.659) \end{equation} Loss=−log(P(y=0))=−log(0.659)​​

                                计算对数值:

                                l o g ( 0.659 ) ≈ − 0.416 \begin{equation} log(0.659) \approx -0.416 \end{equation} log(0.659)≈−0.416​​

                                因此,损失为:

                                L o s s = 0.416 \begin{equation} Loss = 0.416 \end{equation} Loss=0.416​​

                                2、多样本交叉熵损失

                                logits = torch.tensor(
                                        [[1.5, 0.3, 2.1], [2.0, 1.0, 0.1], [0.1, 2.2, 1.0]]
                                    )  # Batch size = 3
                                labels = torch.tensor([2, 0, 1])  # Batch size = 3
                                # 定义交叉熵损失函数
                                criterion = nn.CrossEntropyLoss()
                                # 计算损失
                                loss = criterion(logits, labels)
                                print("CrossEntropyLoss:", loss.item())
                                

                                a)、给定的数据

                                logits(未归一化的分数):

                                l o g i t s = [ 1.5 0.3 2.1 2.0 1.0 0.1 0.1 2.2 1.0 ] logits = \begin{bmatrix} 1.5 & 0.3 & 2.1 \\ 2.0 & 1.0 & 0.1 \\ 0.1 & 2.2 & 1.0 \end{bmatrix} logits= ​1.52.00.1​0.31.02.2​2.10.11.0​ ​

                                labels(真实标签的索引):

                                l a b e l s = [ 2 0 1 ] labels = \begin{bmatrix} 2 & 0 & 1 \end{bmatrix} labels=[2​0​1​]

                                • 第一行对应的类别2
                                • 第二行对应的类别0
                                • 第三行对应的类别1

                                  b)、交叉熵损失函数

                                  L o s s = − 1 N ∑ i = 1 N l o g ( e x p ( l o g i t i , y i ) ∑ j e x p ( l o g i t i , j ) ) \begin{equation} Loss = -\dfrac{1}{N} \sum_{i=1}^{N} log \left( \dfrac{exp(logit_{i,y_i})}{\sum_j exp(logit_{i,j})} \right) \end{equation} Loss=−N1​i=1∑N​log(∑j​exp(logiti,j​)exp(logiti,yi​​)​)​​

                                  其中:

                                  • N = 3 N=3 N=3: 是批量大小。
                                  • l o g i t i , j logit_{i,j} logiti,j​: 是样本 i i i对类别 j j j的预测分数。
                                  • y i y_i yi​: 样本 i i i​​ 的真实类别索引。

                                    c)、逐行计算softmax概率和交叉熵损失

                                    step 1:第一行 l o g i t s = [ 1.5 0.3 2.1 ] logits = \begin{bmatrix} 1.5 & 0.3 & 2.1 \end{bmatrix} logits=[1.5​0.3​2.1​]​,真实标签 = 2

                                    • 计算softmax:

                                      • 计算每个分数的指数值:

                                        e x p ( 1.5 ) ≈ 4.481 , e x p ( 0.3 ) ≈ 1.350 , e x p ( 2.1 ) ≈ 8.165 \begin{equation} exp(1.5) \approx 4.481, \quad exp(0.3) \approx 1.350, \quad exp(2.1) \approx 8.165 \end{equation} exp(1.5)≈4.481,exp(0.3)≈1.350,exp(2.1)≈8.165​​

                                        • 求和

                                          s u m = 4.481 + 1.350 + 8.165 ≈ 13.996 \begin{equation} sum = 4.481 + 1.350 + 8.165 \approx 13.996 \end{equation} sum=4.481+1.350+8.165≈13.996​​

                                          • 计算每个类别的概率

                                            P ( 0 ) = 4.481 13.996 ≈ 0.32 , P ( 1 ) = 1.350 13.996 ≈ 0.096 , P ( 2 ) = 8.165 13.996 ≈ 0.583 \begin{equation} P(0) = \dfrac{4.481}{13.996} \approx 0.32,\quad P(1) = \dfrac{1.350}{13.996} \approx 0.096,\quad P(2) = \dfrac{8.165}{13.996} \approx 0.583 \end{equation} P(0)=13.9964.481​≈0.32,P(1)=13.9961.350​≈0.096,P(2)=13.9968.165​≈0.583​​

                                          • 取真实类别2的概率:

                                            P ( y = 2 ) = 0.583 \begin{equation} P(y=2) = 0.583 \end{equation} P(y=2)=0.583​​

                                            • 计算损失:

                                              L o s s 1 = − l o g ( 0.583 ) ≈ 0.540 \begin{equation} Loss_1 = -log(0.583) \approx 0.540 \end{equation} Loss1​=−log(0.583)≈0.540​​

                                              step 2:第二行 l o g i t s = [ 2.0 1.0 0.1 ] logits = \begin{bmatrix} 2.0 & 1.0 & 0.1 \end{bmatrix} logits=[2.0​1.0​0.1​]​,真实标签 = 0

                                              • 计算softmax:

                                                • 计算每个分数的指数值:

                                                  e x p ( 2.0 ) ≈ 7.389 , e x p ( 1.0 ) ≈ 2.718 , e x p ( 0.1 ) ≈ 1.105 \begin{equation} exp(2.0) \approx 7.389, \quad exp(1.0) \approx 2.718, \quad exp(0.1) \approx 1.105 \end{equation} exp(2.0)≈7.389,exp(1.0)≈2.718,exp(0.1)≈1.105​​

                                                  • 求和

                                                    s u m = 7.389 + 2.718 + 1.105 ≈ 11.212 \begin{equation} sum = 7.389 + 2.718 + 1.105 \approx 11.212 \end{equation} sum=7.389+2.718+1.105≈11.212​​

                                                    • 计算每个类别的概率

                                                      P ( 0 ) = 7.389 11.212 ≈ 0.659 , P ( 1 ) = 2.718 11.212 ≈ 0.242 , P ( 2 ) = 1.105 11.212 ≈ 0.099 \begin{equation} P(0) = \dfrac{7.389}{11.212} \approx 0.659,\quad P(1) = \dfrac{2.718}{11.212} \approx 0.242,\quad P(2) = \dfrac{1.105}{11.212} \approx 0.099 \end{equation} P(0)=11.2127.389​≈0.659,P(1)=11.2122.718​≈0.242,P(2)=11.2121.105​≈0.099​​

                                                    • 取真实类别0的概率:

                                                      P ( y = 0 ) = 0.659 \begin{equation} P(y=0) = 0.659 \end{equation} P(y=0)=0.659​​

                                                      • 计算损失:

                                                        L o s s 2 = − l o g ( 0.659 ) ≈ 0.417 \begin{equation} Loss_2 = -log(0.659) \approx 0.417 \end{equation} Loss2​=−log(0.659)≈0.417​​

                                                        step 3:第二行 l o g i t s = [ 0.1 2.2 1.0 ] logits = \begin{bmatrix} 0.1 & 2.2 & 1.0 \end{bmatrix} logits=[0.1​2.2​1.0​]​,真实标签 = 1

                                                        • 计算softmax:

                                                          • 计算每个分数的指数值:

                                                            e x p ( 0.1 ) ≈ 1.105 , e x p ( 2.2 ) ≈ 9.025 , e x p ( 1.0 ) ≈ 2.718 \begin{equation} exp(0.1) \approx 1.105, \quad exp(2.2) \approx 9.025, \quad exp(1.0) \approx 2.718 \end{equation} exp(0.1)≈1.105,exp(2.2)≈9.025,exp(1.0)≈2.718​​

                                                            • 求和

                                                              s u m = 1.105 + 9.025 + 2.718 ≈ 12.848 \begin{equation} sum = 1.105 + 9.025 + 2.718 \approx 12.848 \end{equation} sum=1.105+9.025+2.718≈12.848​​

                                                              • 计算每个类别的概率

                                                                P ( 0 ) = 1.105 12.848 ≈ 0.086 , P ( 1 ) = 9.025 12.848 ≈ 0.703 , P ( 2 ) = 2.718 12.848 ≈ 0.211 \begin{equation} P(0) = \dfrac{1.105}{12.848} \approx 0.086,\quad P(1) = \dfrac{9.025}{12.848} \approx 0.703,\quad P(2) = \dfrac{2.718}{12.848} \approx 0.211 \end{equation} P(0)=12.8481.105​≈0.086,P(1)=12.8489.025​≈0.703,P(2)=12.8482.718​≈0.211​​

                                                              • 取真实类别1的概率:

                                                                P ( y = 1 ) = 0.703 \begin{equation} P(y=1) = 0.703 \end{equation} P(y=1)=0.703​​

                                                                • 计算损失:

                                                                  L o s s 3 = − l o g ( 0.703 ) ≈ 0.353 \begin{equation} Loss_3 = -log(0.703) \approx 0.353 \end{equation} Loss3​=−log(0.703)≈0.353​​

                                                                  d)、批量损失

                                                                  将每个样本的损失平均:

                                                                  L o s s = L o s s 1 + L o s s 2 + L o s s 3 3 = 0.540 + 0.417 + 0.353 3 ≈ 0.437 \begin{equation} Loss = \dfrac{Loss_1 + Loss_2 + Loss_3}{3} = \dfrac{0.540 + 0.417 + 0.353}{3} \approx 0.437 \end{equation} Loss=3Loss1​+Loss2​+Loss3​​=30.540+0.417+0.353​≈0.437​​

                                                                  3、带权重的交叉熵

                                                                  在某些情况下,类别分布不平衡,可以为不同类别设置权重:

                                                                  weights = torch.tensor([1.0, 2.0, 3.0])  # 类别权重
                                                                  criterion = nn.CrossEntropyLoss(weight=weights)
                                                                  loss = criterion(logits, labels)
                                                                  print("Weighted CrossEntropyLoss:", loss.item())
                                                                  

                                                                  4、示例:在神经网络中的应用

                                                                  import torch
                                                                  import torch.nn as nn
                                                                  import torch.optim as optim
                                                                  # 定义一个简单的神经网络
                                                                  class SimpleNet(nn.Module):
                                                                      def __init__(self):
                                                                          super(SimpleNet, self).__init__()
                                                                          self.fc = nn.Linear(4, 3)  # 输入 4 维特征,输出 3 类
                                                                      def forward(self, x):
                                                                          return self.fc(x)
                                                                  # 模型、损失函数和优化器
                                                                  model = SimpleNet()
                                                                  criterion = nn.CrossEntropyLoss()
                                                                  optimizer = optim.Adam(model.parameters(), lr=0.01)
                                                                  # 输入数据和标签
                                                                  inputs = torch.tensor([[0.5, 1.2, -1.3, 0.8], [0.3, -0.7, 1.0, 1.5]])  # Batch size = 2
                                                                  labels = torch.tensor([0, 2])  # 两个样本对应的真实类别
                                                                  # 前向传播
                                                                  outputs = model(inputs)
                                                                  # 计算损失
                                                                  loss = criterion(outputs, labels)
                                                                  print("Loss:", loss.item())
                                                                  # 反向传播和优化
                                                                  loss.backward()
                                                                  optimizer.step()
                                                                  

                                                                  5、总结

                                                                  • 交叉熵损失函数用于度量预测分布与真实分布之间的差异,是分类问题中的核心工具。

                                                                  • 在 PyTorch 中,torch.nn.CrossEntropyLoss 结合了 softmax 和交叉熵计算,使用简单且高效。

                                                                  • 可以通过参数调整(如权重)来适应不平衡数据集。

                                                                    整合的代码

                                                                    import torch
                                                                    import torch.nn as nn
                                                                    import torch.optim as optim
                                                                    def single_instance_CrossEntropyLoss():
                                                                        # 模型的输出 logits 和真实标签
                                                                        logits = torch.tensor([[2.0, 1.0, 0.1]])  # 未经过 softmax 的输出
                                                                        labels = torch.tensor([0])  # 真实标签(类别索引)
                                                                        # 定义交叉熵损失函数
                                                                        criterion = nn.CrossEntropyLoss()
                                                                        # 计算损失
                                                                        loss = criterion(logits, labels)
                                                                        print("CrossEntropyLoss:", loss.item())
                                                                    def multi_instance_CrossEntropyLoss():
                                                                        logits = torch.tensor(
                                                                            [[1.5, 0.3, 2.1], [2.0, 1.0, 0.1], [0.1, 2.2, 1.0]]
                                                                        )  # Batch size = 3
                                                                        labels = torch.tensor([2, 0, 1])  # Batch size = 3
                                                                        # 定义交叉熵损失函数
                                                                        criterion = nn.CrossEntropyLoss()
                                                                        # 计算损失
                                                                        loss = criterion(logits, labels)
                                                                        print("CrossEntropyLoss:", loss.item())
                                                                    # 定义一个简单的神经网络
                                                                    class SimpleNet(nn.Module):
                                                                        def __init__(self):
                                                                            super(SimpleNet, self).__init__()
                                                                            self.fc = nn.Linear(4, 3)  # 输入 4 维特征,输出 3 类
                                                                        def forward(self, x):
                                                                            return self.fc(x)
                                                                    def apply_deepLearning_CrossEntropyLoss():
                                                                        # 模型、损失函数和优化器
                                                                        model = SimpleNet()
                                                                        criterion = nn.CrossEntropyLoss()
                                                                        optimizer = optim.Adam(model.parameters(), lr=0.01)
                                                                        # 输入数据和标签
                                                                        inputs = torch.tensor(
                                                                            [[0.5, 1.2, -1.3, 0.8], [0.3, -0.7, 1.0, 1.5]]
                                                                        )  # Batch size = 2
                                                                        labels = torch.tensor([0, 2])  # 两个样本对应的真实类别
                                                                        # 前向传播
                                                                        outputs = model(inputs)
                                                                        # 计算损失
                                                                        loss = criterion(outputs, labels)
                                                                        print("Loss:", loss.item())
                                                                        # 反向传播和优化
                                                                        loss.backward()
                                                                        optimizer.step()
                                                                    if __name__ == "__main__":
                                                                        print("*" * 30)
                                                                        single_instance_CrossEntropyLoss()
                                                                        multi_instance_CrossEntropyLoss()
                                                                        apply_deepLearning_CrossEntropyLoss()
                                                                    
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码