交叉熵损失函数和softmax笔记

交叉熵损失函数和softmax笔记,第1张

交叉损失函数和softmax笔记

文章目录
  • 1. 交叉熵定义
  • 2.交叉熵损失思考
  • 3.交叉熵损失代码
  • 4. softmax 回归的简洁实现
    • 4.1 代码
    • 4.2 结果

注:本文代码参考李沐书籍,这里只做代码解析。

1. 交叉熵定义

交叉熵是信息论中的一个重要概念,主要用于度量两个概率分布间的差异性,要理解交叉熵,需要先了解下面几个概念

  • 信息量
    香农大佬说过"信息是用来消除随机不确定的东西",就是用信息量来表示一个事件从不确定到确定这种状态的量度单位。信息量的大小和信息发生的概率成反比。假设某一事件发生的概率为P(X),我们将信息量I(X)定义如下
    I ( X ) = − log ⁡ ( P ( X ) ) (1) I(X)=-log(P(X))tag1 I(X)=−log(P(X))(1)
  • 信息熵 H(X)
    信息熵表示的信息量的期望的和,我们知道,期望就是概率乘以值;那么可以得到。
    H ( X ) = − ∑ i = 1 n P ( x i ) log ⁡ P ( x i ) (2) H(X)=-sum_{i=1}^{n}P(x_i)log P(x_i)tag2 H(X)=−i=1∑n​P(xi​)logP(xi​)(2)
    注:当我们求得的结果为两种情况,即二项式分布时候, n =2 时。那么
    H ( X ) = − [ P ( x i ) log ⁡ P ( x i ) + ( 1 − P ( x i ) ) log ⁡ ( 1 − P ( x i ) ) ] (3) H(X)=-[P(x_i)log P(x_i)+(1-P(x_i))log(1-P(x_i))]tag3 H(X)=−[P(xi​)logP(xi​)+(1−P(xi​))log(1−P(xi​))](3)
  • 相对熵(KL 散度)
    如果对于同一个随机变量X有两个单独概率分布,P(X) 和 Q(X),我们通过 KL散度来描述两个概率分布之间的差异。那为什么要这样做呢?因为我们已经有了概率分布 P(X)的具体参数,我们希望对于未知的概率分布 Q(X) 的进行分析,最好是有一个参数 KL 散度 来描述这两个概率分布的差异,当 KL散度很小时,那么我们就可以说明这两个分布相似。
    D K L ( p ∣ ∣ q ) = ∑ i = 1 n p ( x i ) log ⁡ ( p ( x i ) q ( x i ) ) (4) D_{KL}(p||q)=sum_{i=1}^np(x_i)log{(frac{p(x_i)}{q(x_i)})}tag 4 DKL​(p∣∣q)=i=1∑n​p(xi​)log(q(xi​)p(xi​)​)(4)
    D K L ( p ∣ ∣ q ) = ∑ i = 1 n p ( x i ) log ⁡ ( p ( x i ) ) ⏟ p ( x i ) 的 信 息 熵 + − ∑ i = 1 n p ( x i ) log ⁡ ( q ( x i ) ) ⏟ p ( x i ) 和 q ( x i ) 的 交 叉 熵 (5) D_{KL}(p||q)=underbrace{sum_{i=1}^np(x_i)log{(p(x_i))}}_{p(x_i)的信息熵}+underbrace{-sum_{i=1}^np(x_i)log{(q(x_i))}}_{p(x_i)和q(x_i)的交叉熵}tag {5} DKL​(p∣∣q)=p(xi​)的信息熵 i=1∑n​p(xi​)log(p(xi​))​​+p(xi​)和q(xi​)的交叉熵 −i=1∑n​p(xi​)log(q(xi​))​​(5)
    注:这里我们就出现了交叉熵了:
  • 交叉熵:
    − ∑ i = 1 n p ( x i ) log ⁡ ( q ( x i ) ) (6) -sum_{i=1}^np(x_i)log{(q(x_i))}tag{6} −i=1∑n​p(xi​)log(q(xi​))(6)
2.交叉熵损失思考

那为什么交叉熵能够表示两个概率之间的差异呢?为什么它就很方便的表达了。这里我们假设这里的 p ( x i ) p(x_i) p(xi​)为模型中实际的概率标签 y i y_i yi​, q ( x i ) q(x_i) q(xi​)为模型预测的 y i ^ hat{y_i} yi​^​,假设 类别数n = q代入上式可得:
l ( y i , y i ^ ) = − ∑ j = 1 q y i log ⁡ y i ^ (7) l(y_i,hat{y_i})=-sum_{j=1}^q y_ilog{hat{y_i}}tag{7} l(yi​,yi​^​)=−j=1∑q​yi​logyi​^​(7)
假设模型预测的 y i ^ hat{y_i} yi​^​是通过 softmax运算得到的,满足如下:
y j ^ = s o f t m a x ( o j ) = e x p ( o j ) ∑ k e x p ( o k ) (8) hat{y_j}=softmax(o_j)=frac{exp(o_j)}{sum_kexp(o_k)}tag{8} yj​^​=softmax(oj​)=∑k​exp(ok​)exp(oj​)​(8)
将 (8) 带入到 (7) 可得:
l ( y i , y i ^ ) = − ∑ j = 1 q y j log ⁡ e x p ( o j ) ∑ k e x p ( o k ) (9) l(y_i,hat{y_i})=-sum_{j=1}^q y_jlog{frac{exp(o_j)}{sum_kexp(o_k)}}tag{9} l(yi​,yi​^​)=−j=1∑q​yj​log∑k​exp(ok​)exp(oj​)​(9)
l ( y i , y i ^ ) = ∑ j = 1 q y j log ⁡ ∑ k e x p ( o k ) − ∑ j = 1 q y j o j (10) l(y_i,hat{y_i})=sum_{j=1}^q y_jlogsum_kexp(o_k)-sum_{j=1}^qy_jo_jtag{10} l(yi​,yi​^​)=j=1∑q​yj​logk∑​exp(ok​)−j=1∑q​yj​oj​(10)
注:当我们用 one-hot 独热编码表示 y i y_i yi​时,那么除了第 j 项为1,其他均为 0 ,则:
l ( y i , y i ^ ) = log ⁡ ∑ k = 1 q e x p ( o k ) − ∑ j = 1 q y j o j (11) l(y_i,hat{y_i})=logsum_{k=1}^qexp(o_k)-sum_{j=1}^qy_jo_jtag{11} l(yi​,yi​^​)=logk=1∑q​exp(ok​)−j=1∑q​yj​oj​(11)
对上式求导可得:
∂ l ( y i , y i ^ ) ∂ o j = e x p ( o j ) ∑ k = 1 q e x p ( o k ) − y j (12) frac{partial l(y_i,hat{y_i})}{partial o_j}=frac{exp(o_j)}{sum_{k=1}^qexp(o_k)}-y_jtag{12} ∂oj​∂l(yi​,yi​^​)​=∑k=1q​exp(ok​)exp(oj​)​−yj​(12)
注意:此时我们发现 y j ^ = s o f t m a x ( o j ) = e x p ( o j ) ∑ k e x p ( o k ) hat{y_j}=softmax(o_j)=frac{exp(o_j)}{sum_kexp(o_k)} yj​^​=softmax(oj​)=∑k​exp(ok​)exp(oj​)​
∂ l ( y i , y i ^ ) ∂ o j = y j ^ − y j (13) frac{partial l(y_i,hat{y_i})}{partial o_j}=hat{y_j}-y_jtag{13} ∂oj​∂l(yi​,yi​^​)​=yj​^​−yj​(13)
重点:上式说明了,当我们用交叉熵表示损失函数的时候,我们模型中预测用到 softmax 时候,交叉熵的导数即为预测标签 y i ^ hat{y_i} yi​^​与真实标签 y i y_i yi​的差。这样就非常方便了,我们只需要用交叉熵为损失函数就可以了。
我们可以类比最小二乘法的损失函数 :
l ( y i , y i ^ ) = 1 2 ( y j ^ − y j ) 2 (14) l(y_i,hat{y_i})=frac{1}{2}(hat{y_j}-y_j)^2tag{14} l(yi​,yi​^​)=21​(yj​^​−yj​)2(14)
∂ l ( y i , y i ^ ) ∂ o j = y j ^ − y j (15) frac{partial l(y_i,hat{y_i})}{partial o_j}=hat{y_j}-y_jtag{15} ∂oj​∂l(yi​,yi​^​)​=yj​^​−yj​(15)
这样类比后,我们发现,用交叉熵做损失函数也能跟用最小二乘法表示一样实现。

3.交叉熵损失代码
  • 代码核心思想:交叉熵采用真实标签的预测概率的负对数似然
    举例1 :
    假设我们有真实标签 y i y_i yi​,用它来表示样本中真实样本的位置
y = torch.tensor([0,2]) # 0,2 表示样本中真实正确标签的位置

我们用 y i ^ hat{y_i} yi​^​来表示样本中各个类别的概率分布,并用 y 来告诉程序哪个概率是正确的。

y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])

结合起来如下:

y_hat[[0, 1], y] # 等价于 y_hat[[0, 1], [0,2]]
# 就是 0 对应于0; 1 对应于 2
# 第 0 个 [0.1, 0.3, 0.6] 中选择 第 0 个 ,即 0.1
# 第 1 个 [0.3, 0.2, 0.5] 中选择 第 2 个 ,即 0.5
# 所以以上代码输出结果为:tensor([0.1000, 0.5000])

那么我们就可以将上述得到的值求负对数似然即可

  • 交叉熵代码
def cross_entropy(y_hat, y):
	return -torch.log(y_hat[range(len(y_hat)), y])
4. softmax 回归的简洁实现

我们这里应用pytorch 框架的相关函数来搭建 softmax 回归,在搭建过程中十分的方便。

4.1 代码
# -*- coding: utf-8 -*-
# @Project: zc
# @Author: zc
# @File name: softmax的简洁实现
# @Create time: 2021/11/22 18:09

# 1.导入相关库
import torch
from torch import nn
from d2l import torch as d2l
import matplotlib.pyplot as plt

# 2.将数据导入并生成train_iter训练集,test_iter 测试集
batch_size = 256  # 设置批量大小
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)  # 将数据加载到迭代器中

# 3. 定义模型
# PyTorch不会隐式地调整输⼊的形状。因此,
# 我们在线性层前定义了展平层(flatten),来调整⽹络输⼊的形状
net = nn.Sequential(
	nn.Flatten(), nn.Linear(784, 10)
)


# 4.初始化模型值
def init_weights(m):
	if type(m) == nn.Linear:
		nn.init.normal_(m.weight, std=0.01)


net.apply(init_weights)

# 5. 定义损失函数

loss = nn.CrossEntropyLoss()

# 6. 定义优化器

trainer = torch.optim.SGD(net.parameters(), lr=0.1)

# 7.开始训练模型
num_epochs = 10  # 训练次数为 10

# 8.开始训练
d2l.train_ch3(net=net, train_iter=train_iter, test_iter=test_iter, loss=loss, num_epochs=num_epochs, updater=trainer)
# 9.预测
d2l.predict_ch3(net,test_iter) 
plt.show() # 显示结果
4.2 结果
  • 训练
  • 预测

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5580875.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-14
下一篇 2022-12-14

发表评论

登录后才能评论

评论列表(0条)

保存