KLDivLoss
作用:
用于连续分布的距离度量;并且对离散采用的连续输出空间分布进行回归通常很有用;用label_smoothing就采用这个;
公式:




公式理解:
p(x)是真实分布,q(x)是拟合分布;实际计算时;通常p(x)作为target,只是概率分布;而xn则是把输出做了LogSoftmax计算;即把概率分布映射到log空间;所以
K-L散度值实际是看log(p(x))-log(q(x))的差值,差值越小,说明拟合越相近。
pytorch使用:

当前版本torch(1.3.1)要想获得真正的KL散度;设置:
reduce=False;size_average=False
(reduce默认也是True,返回所有元素loss的和;size_average=默认是True,是对batch中每个元素进行求平均,当为False时,返回各样本各维度的loss之和;
因为reduce为False会忽略size_average参数,所以其实只需要把reduce=False即可)
代码验证:
import torch
import torch.nn as nn
import numpy as np
# ----------------------------------- KLDiv loss
loss_f = nn.KLDivLoss(size_average=False, reduce=False)
loss_f_mean = nn.KLDivLoss(size_average=True, reduce=True)
# 生成网络输出 以及 目标输出
output = torch.from_numpy(np.array([[0.1132, 0.5477, 0.3390]])).float()
output.requires_grad = True
target = torch.from_numpy(np.array([[0.8541, 0.0511, 0.0947]])).float()
loss_1 = loss_f(output, target)
loss_mean = loss_f_mean(output, target)
print('\nloss: ', loss_1)
print('\nloss_mean: ', loss_mean)
# 熟悉计算公式,手动计算样本的第一个元素的loss,注意这里只有一个样本,是 element-wise计算的
output = output[0].detach().numpy()
output_1 = output[0] # 第一个样本的第一个元素
target_1 = target[0][0].numpy()
loss_1 = target_1 * (np.log(target_1) - output_1)
print('\n第一个样本第一个元素的loss:', loss_1

链接:https://github.com/TingsongYu/PyTorch_Tutorial/blob/master/Code/3_optimizer/3_1_lossFunction/6_KLDivLoss.py
Note:
D(p||q) ≠ D(q||p) ,不具有对称性所以不能称之为K-L距离 |