- 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∑nP(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∑np(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∑np(xi)log(p(xi))+p(xi)和q(xi)的交叉熵 −i=1∑np(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∑np(xi)log(q(xi))(6)
那为什么交叉熵能够表示两个概率之间的差异呢?为什么它就很方便的表达了。这里我们假设这里的
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∑qyilogyi^(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)=∑kexp(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∑qyjlog∑kexp(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∑qyjlogk∑exp(ok)−j=1∑qyjoj(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∑qexp(ok)−j=1∑qyjoj(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=1qexp(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)=∑kexp(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)
这样类比后,我们发现,用交叉熵做损失函数也能跟用最小二乘法表示一样实现。
- 代码核心思想:交叉熵采用真实标签的预测概率的负对数似然
举例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 结果
- 训练
- 预测
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)