逻辑回归(logistic regression)通常用于分类问题,它已经很大程度上被分类(classification)这个概念代替了,至于我们怎么理解逻辑回归中的 regression,我们对照线性回归(linear regression)来看一下。
Regression v.s. classification
Logistic 函数
对于一个线性回归问题来说,我们用非常简单的线性回归模型 来求解,它的输出是连续的,正因为连续,所以我们称它为一个 regression 问题。那怎样把它转化为一个分类问题呢?我们前面已经阐述过了,用到 sigmoid 函数(),它又叫做 logistic 函数。通过 logistic 函数,模型就变成了 ,我们将输出缩小到 的范围内,输出接近 0,结果则为 0,输出接近 1,结果则为 1。
目标
在线性回归问题中,我们希望得到的预测值 接近真实值 ,最好是两者相等。所以我们优化的过程是减小两者的差距,这个差距用一些范数来表示,比如 。
而在分类问题中,我们希望准确率(accuracy)更高,也就是说总样本数量一定,预测对的数量越多越好。但我们不能直接对 accuracy 进行优化,而是对比预测结果的概率分布与真实结果的概率分布进行优化。
那为什么不能直接对 accuracy 进行优化呢?
**
拿一个二分类问题来说,总样本数为 N,预测对的数量为 n,按照我们的定义,。假定目前的状态为总样本有 5 个,预测对的有 3 个,即目前的准确率为 0.6,若剩下两个没预测对的目前输出分别为 和 ,预测结果为 和,真实结果分别对应 和,我们来看一下。
要想优化 accuracy,则需要让预测对的数量变多,对于后一个没预测对的样本来说,要想预测结果变为, 则至少要变为 ,但参数值在 0.1 变成 0.5 的过程中,accuracy 始终不变,为 0.6,所以说在这个过程中,accuracy 对该参数的偏导长时间为 0。
对于前一个没预测对的样本来说,要想预测结果变为,只需让 中第二个参数的值大于第三个参数的值即可,可以变成 ,这样的话第二个参数的值从 0.49999 变为 0.50001 增加了 0.00002,预测对的数量 +1,准确值就变成了 0.8,我们粗略计算一下 accuracy 对第二个参数的偏导 ,这样算起来,第二个参数的梯度就很大,实际上,accuracy 的变化是瞬间完成的,也就是说在这一瞬间,accuracy 对所有参数是不可导的。
怎样优化
对于上述的二分类问题,我们使用的输出格式是概率分布,这是在多分类问题中常用的格式。当然,对于二分类问题,我们也可以使用范围为 的标量的格式表示输出 ,输出 接近 0,结果 则为 0,输出 接近 1,结果 则为 1。对于这种标量的格式,我们优化的目标则是使得结果 更接近目标值 ,而不是输出 更接近目标值 。这里我们仍然用到 函数,这样做,二分类就是一个回归问题,理所当然,它被叫做 logistic regression。
但如果我们用多分类的视角,它就应该被叫做 classification 了。因为这样的话,模型的输出 和 目标值 都是概率分布格式,即 ,,概率分布意味着非此即彼,并不连续。我们优化的目标相应的变成了使得概率分布 更接近概率分布 ,即 。而 中的每一个 都是一个范围为 的标量,而且 。
那么现在问题就来了,我们怎样限制所有 的和为 1,又怎样优化使得 ?我们在导数与梯度部分挖过两个坑,一个是交叉熵损失函数(Cross Entropy),一个是 softmax 激活函数,它们在这里正派上用场。
Classification 问题优化
交叉熵损失函数通常伴随着 softmax 函数同时出现,所以我们先解释什么是 softmax 函数。
Softmax 函数
首先,softmax 函数可以使 中的每一个 都压缩在 的范围内,而且所有 的和为 1。我们将进入 softmax 函数之前的加权求和值用 表示,softmax 函数长下面这个样子:
为什么不直接用 呢,这样也可以将 压缩在 范围内,并且所有 的和也为 1?因为 softmax 有一个优势,它可以将较大的 放得更大,较小的 压缩在一个小范围内,拉开大小数值差距。举个例子,假设我们现在有一个三分类问题,某一层加权求和后,,经过 softmax 函数,,,,。 与 的差距相比 和 拉大了,这样可以鼓励某个类别的特征与其他类别的特征相互分离。
求一下 softmax 对 a 的导数,令 ,那么 。要注意的是,对于 n 分类问题, 有 n 个, 也有 n 个,那么 对 的偏导数 就有 个。其中分两种情况, 和 。
当 :
当 :
综上,
或
交叉熵函数
理解了 softmax 激活函数,我们来看一下交叉熵损失函数。我们都知道,熵(entropy)是表示系统混乱程度的一个参量,信息中的熵叫做信息熵。要理解信息熵,我们需要先达成一个共识,系统的熵越大,随机性越大,概率分布越均匀。例 的熵大于 。那么我们引出信息熵的公式:
为了验证上面的共识,我们将 和 代入公式,计算,,验证概率分布越均匀,熵越大。
什么是交叉熵呢?交叉熵刻画的是两个概率分布之间的距离,或者说是概率分布 来表达概率分布 的困难程度。在神经网络中, 代表正确答案,也就是目标值 的概率分布, 代表的是预测值,输出值 的概率分布,下面是它的公式:
交叉熵越小,两个概率分布越相近。为了说明这一点,我们把 拆开:
这样, 就被拆分成了 加上 ,后者是相对熵(Relative Entropy),又被叫做 KL 散度(KL Divergence),用 表示。它是两个概率分布差异的非对称性度量,非对称的意思是 不一定等于 。我们大概可以用两个函数重叠的面积来理解一下 KL 散度。
右边图中的函数比左边图中函数重叠的面积大,我们理解为右边图中两个函数的匹配程度更高, 越小,当两个函数完全匹配时, 等于 0。那么,对于 classification 问题来说,目标值 的概率分布 永远是 分布,也就是:
将 代入 可以求得 等于 0,也就是说,对于 classification 问题来说,,,即此时, 只跟 与 的匹配程度有关。所以,KL 越小,交叉熵越小,概率分布越相近。
Pytorch 实现 soft 与 交叉熵
from torch.nn import functional as F
import torch
x = torch.randn(1, 784)
w = torch.randn(10, 784)
a = x@w.t()
# 在 pytorch 中,cross_entropy 函数已经将 softmax 封装了,
# 我们调用 cross_entropy 函数只需传入 a,也就是 xw + b 就可
loss = F.cross_entropy(a, torch.tensor([1]))
print(loss) # tensor(77.1725)
# 如果我们自己实现,首先调用 softmax 函数将 a 转为概率分布 o,
# 然后计算 log(o),我们文中使用的 log_2(o),都可,不影响
# 调用 nll_loss 函数,模拟 PQ 点乘
o = F.softmax(a, dim=1)
p = torch.log(o)
loss = F.nll_loss(p, torch.tensor([1]))
print(loss) # tensor(77.1725)