基本损失函数
损失函数作用
- 计算出实际输出和目标之间的差距
- 为我们更新输出提供依据(反向传播)
o u t p u t : 10 , 10 , 20 t a r g e t : 30 , 20 , 50 l o s s = ∣ ( 30 − 10 ) ∣ + ∣ ( 20 − 10 ) ∣ + ∣ ( 50 − 10 ) ∣ = 70 L 1 l o s s = 70 / 3 = 23.33 output: 10,10,20 \\ target : 30,20,50 \\ loss=|(30-10)|+|(20-10)|+\mid ( 50-10) \mid=70\\ L1loss=70 / 3=23.33 output:10,10,20target:30,20,50loss=∣(30−10)∣+∣(20−10)∣+∣(50−10)∣=70L1loss=70/3=23.33
交叉熵
两个不同的模型比较,需要熵作为中介。比如,黄金和白银比较价值,需要把他们都换算为美元,才能对比
1.信息量
-
不同的信息,含有不同的信息量,假设下列对阵表中阿根廷的夺冠概率是1/8,A同学告诉我阿根廷夺冠了,那么这个信息量就很大了(因为它包括了阿根廷进了四强,决赛);B同学告诉我阿根廷进决赛了,那么这个信息量就较小。
-
假设f(x):= 信息量(:=是定义符),x是信息
- f ( 阿 根 廷 夺 冠 ) = f ( 阿 根 廷 进 决 赛 ) + f ( 阿 根 廷 赢 了 决 赛 ) f(阿根廷夺冠)= f(阿根廷进决赛)+ f(阿根廷赢了决赛) f(阿根廷夺冠)=f(阿根廷进决赛)+f(阿根廷赢了决赛)
因为事件越不确定,则其包含的信息量就越多,所以
自变量又可以变为事件的概率
则有:
f ( 1 / 8 ) = f ( 1 / 4 ) + f ( 1 / 2 ) f(1/8)= f(1/4)+ f(1/2) f(1/8)=f(1/4)+f(1/2)
同时,也必须满足
- P ( 阿 根 廷 夺 冠 ) = P ( 阿 根 廷 进 决 赛 ) ∗ P ( 阿 根 廷 赢 得 了 决 赛 ) P(阿根廷夺冠)= P(阿根廷进决赛)*P(阿根廷赢得了决赛) P(阿根廷夺冠)=P(阿根廷进决赛)∗P(阿根廷赢得了决赛)
所以
🚀 f ( P ( 阿 根 廷 夺 冠 ) ∗ P ( 阿 根 廷 赢 得 了 决 赛 ) ) = f ( P ( 阿 根 廷 进 决 赛 ) ) + f ( P ( 阿 根 廷 赢 得 了 决 赛 ) ) f(P(阿根廷夺冠)*P(阿根廷赢得了决赛))=f(P(阿根廷进决赛))+ f(P(阿根廷赢得了决赛)) f(P(阿根廷夺冠)∗P(阿根廷赢得了决赛))=f(P(阿根廷进决赛))+f(P(阿根廷赢得了决赛))
所以,用表达式中肯定有🌻log
又因为事件发生概率和信息量成反比,所以有 -log
2.熵
🔥熵:一个事件,从原来的不确定到完全确定,有多大的难度
。而信息量的期望,就是熵H§
🌈 P f P_f Pf是总信息量, f ( p i ) f(p_i) f(pi)是该事件的信息量, p i p_i pi是该事件发生的概率
交叉熵越小,两个模型就越接近
3.相对熵(KL散度)
f Q ( q i ) f_Q(q_i) fQ(qi)表示Q系统的信息量; f P ( p i ) f_P(p_i) fP(pi)是P系统的信息量
D K L ( P ∣ ∣ Q ) D_KL(P||Q) DKL(P∣∣Q)表示两个系统的相对熵,或者说KL散度
D K L ( P ∣ ∣ Q ) D_KL(P||Q) DKL(P∣∣Q)以P为基准,去考虑P、Q相差多少
D K L ( Q ∣ ∣ P ) D_KL(Q||P) DKL(Q∣∣P)表示以Q为基准
- $\sum_{i=1}^{m} p_{i} \cdot\left(f_{Q}\left(q_{i}\right)-f_{P}\left(p_{i}\right)\right) \$
f Q ( q i ) − f P ( p i ) f_{Q}\left(q_{i}\right)-f_{P}\left(p_{i}\right) fQ(qi)−fP(pi)表示某一事件,在Q系统的信息量,减去P系统的信息量
D K L ( P ∥ Q ) : = ∑ i = 1 m p i ⋅ ( f Q ( q i ) − f P ( p i ) ) = ∑ i = 1 m p i ⋅ ( ( − log 2 q i ) − ( − log 2 p i ) ) = ∑ i = 1 m p i ⋅ ( − log 2 q i ) − ∑ m i = 1 m p i ⋅ ( − log 2 p i ) \begin{array}{l} \boldsymbol{D}_{\boldsymbol{K} \boldsymbol{L}}(\boldsymbol{P} \| \boldsymbol{Q}) \\ :=\sum_{i=1}^{m} p_{i} \cdot\left(f_{Q}\left(q_{i}\right)-f_{P}\left(p_{i}\right)\right) \\ =\sum_{i=1}^{m} p_{i} \cdot\left(\left(-\log _{2} q_{i}\right)-\left(-\log _{2} p_{i}\right)\right) \\ =\sum_{i=1}^{m} p_{i} \cdot\left(-\log _{2} q_{i}\right)-\sum_{m i=1}^{m} p_{i} \cdot\left(-\log _{2} p_{i}\right) \end{array} DKL(P∥Q):=∑i=1mpi⋅(fQ(qi)−fP(pi))=∑i=1mpi⋅((−log2qi)−(−log2pi))=∑i=1mpi⋅(−log2qi)−∑mi=1mpi⋅(−log2pi)
∑
m
i
=
1
m
p
i
⋅
(
−
log
2
p
i
)
\sum_{m i=1}^{m} p_{i} \cdot(-\log _{2} p_{i})
∑mi=1mpi⋅(−log2pi):P的熵,因为我们把P定做基准了,所以看散度时,只需要考虑
∑
i
=
1
m
p
i
⋅
(
−
log
2
q
i
)
\sum_{i=1}^{m} p_{i} \cdot\left(-\log _{2} q_{i}\right)
∑i=1mpi⋅(−log2qi),这一部分,就是交叉熵
了
-
二分类问题
交叉熵要包含所有可能的结果,而二分类的结果为:是/否,所以要有 ( 1 − x i ) ⋅ log 2 ( 1 − y i ) (1-x_{i}) \cdot \log _{2}\left(1-y_{i}\right) (1−xi)⋅log2(1−yi)
H ( P , Q ) = − ∑ i = 1 n ( x i ⋅ log 2 y i + ( 1 − x i ) ⋅ log 2 ( 1 − y i ) ) \begin{array}{ll} \boldsymbol{H}(\boldsymbol{P}, \boldsymbol{Q}) & =-\sum_{i=1}^{n}\left(x_{i} \cdot \log _{2} y_{i}+\left(1-x_{i}\right) \cdot \log _{2}\left(1-y_{i}\right)\right) \end{array} H(P,Q)=−∑i=1n(xi⋅log2yi+(1−xi)⋅log2(1−yi)) -
多分类问题
KaTeX parse error: Expected 'EOF', got '&' at position 49: …boldsymbol{Q}) &̲ =\sum_{i=1}^{m…
4.交叉熵
pytorch中的交叉熵有点不太一样,它是以softmax
函数作为事件的概率
w c w_c wc是权重
理论很难,使用起来确很简单,就一句代码的事~😎
loss_fn = nn.CrossEntropyLoss() # 交叉熵损失
数学计算
loss ( x , class ) = − log ( exp ( x [ class ] ) ∑ j exp ( x [ j ] ) ) = − x [ class ] + log ( ∑ j exp ( x [ j ] ) ) \mathbf{\mathbb{} } \operatorname{loss}(x, \text { class })=-\log \left(\frac{\exp (x[\text { class }])}{\sum_{j} \exp (x[j])}\right)=-{\color{Purple} } x[\text { class }]+\log \left(\sum_{j} \exp (x[j])\right) loss(x, class )=−log(∑jexp(x[j])exp(x[ class ]))=−x[ class ]+log(j∑exp(x[j]))
程序
import torch
import torch.nn as nn
import math
criterion = nn.CrossEntropyLoss()
output = torch.randn(1, 5, requires_grad=True)
label = torch.empty(1, dtype=torch.long).random_(5)
loss = criterion(output, label)
print("网络输出为5类:")
print(output)
print("要计算label的类别:")
print(label)
print("计算loss的结果:")
print(loss)
first = 0
for i in range(1):
first = -output[i][label[i]]
print("output:{}".format(output[i]))
print("label:{}".format(label[i]))
print("first:{}".format(first))
second = 0
for i in range(1):
for j in range(5):
second += math.exp(output[i][j])
print("second:{}".format(second))
res = 0
res = (first + math.log(second))
print("自己的计算结果:")
print(res)
手动计算
注意:python中log的底是e,即ln