逻辑回归(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)