引入

二分类问题如:邮件是否为垃圾邮件,交易是否为诈骗,肿瘤是良性还是恶性

通过“回归”进行“分类”的主要思想:根据现有数据,对分类边界线建立回归公式,以此进行分类。

不同于线性回归模型(对应于 连续值 continuous),我们预测出的值是一个离散值(discreate):y^{0,1}\hat{y} \in \{0, 1\}(负类还是正类)。

  • 单位阶跃函数(unit-step function),能够接受所有输入,通过线性回归模型产生预测值zz (实数),根据zz 的范围转换为对应的 0 或 1 值。但问题显然:函数不连续,而且需要事先假设数据分布(如z<0z < 0,预测为 0等)

    感知机(Perception),是二分类的线性模型,输入为实例的特征向量,输出为实例的类别(取 +1-1

  • 对数几率回归(Logistic Regression),属于Sigmoid函数。它不是仅预测出“类别”,而是能够得到近似概率预测(概率估计),将实数映射到[0,1][0, 1] 区间。此外,它是任意阶可导的凸函数,在数学上能够使用最优化算法。

    σ(z)=11+ez\sigma(z) = \frac{1}{1 + e^{-z}}

模型

z=ωTx+bz = \mathbf{\omega}^T\mathbf{x}+b。假定

y=σ(z)=σ(ωTx+b)=11+eωTx+by = \sigma(z) = \sigma(\mathbf{\omega}^T\mathbf{x}+b) = \frac{1}{1 + e^{-\mathbf{\omega}^T\mathbf{x}+b}}

我们视样本x\mathbf{x} 作为正类的可能性,即P(y=1)P(y = 1),显然(1y)(1 - y) 为反例的可能性,即P(y=0)P(y=0)

该模型因而满足广义线性模型y=g1(ωTx+b)y = g^{-1}(\mathbf{\omega}^T\mathbf{x}+b)

训练方法

假设某一样本ii,预测值为y^\hat{y},而yy 是真实标签。

如果使用平方误差,由于是非凸函数,难以收敛

我们可通过极大似然法来估计w\mathbf{w}bb

已知样本点xx ,而模型参数θ\theta 未知,即似然函数(likelihood function)。它描述了对于不同的θ\theta ,出现 样本点xx 的概率是多少。

要使得观察样本出现的概率最大(拟合的分布更加趋近于观察样本的分布),显然要使似然函数最大化。更多关于极大似然法的理解:参见该篇文章

对数几率回归模型最大化“对数似然”——即令每个样本属于其真实标记的概率越大越好,对应地,最大化似然相当于最小化损失:

l(i)=( y(i)lny^(i)+(1y(i))ln(1y^(i)) )l^{(i)}=-(\ y^{(i)}\ln{\hat{y}^{(i)}} + (1 - y^{(i)})\ln{(1 - \hat{y}^{(i)})}\ )

交叉熵损失函数 相较于 均方损失函数 的优势:可参见这篇文章

对于mm个样本:(x(1),y(1)),(x(2),y(2)),...,(x(m),y(m))(x^{(1)},y^{(1)}),(x^{(2)},y^{(2)}),...,(x^{(m)},y^{(m)}),得到 BCE Loss(二分类用的交叉熵损失函数)

L(w,b)=1mi=1m( y(i)lny^(i)+(1y(i))ln(1y^(i)) )L(\mathbf{w}, b)=-\frac{1}{m}\sum_{i=1}^{m}{ (\ y^{(i)}\ln{\hat{y}^{(i)}} + (1 - y^{(i)})\ln{(1 - \hat{y}^{(i)})} \ ) }

接着,使用批量随机梯度下降法,即能得到效果不错的参数wb\mathbf{w}、b

分类模型的评估指标

混淆矩阵(Confusion Matrix)

Ground Truth \ PredictionPositive(e.g. sick)Negative
PositiveTrue Positive (TP)False Negative (FN)
NegativeFalse Positive (FP)True Negative (TN)
  • 准确率:

    Accuracy=正确分类数所有数据=TP+TNTP+TN+FN+TN=TPall detectionsAccuracy = \frac{正确分类数}{所有数据} = \frac{TP+TN}{TP+TN+FN+TN} = \frac{TP}{\text{all detections}}

  • 查准率:

    Precision=TP预测生病数=TPTP+FP=TPall ground truthsPrecision = \frac{TP}{预测生病数} = \frac{TP}{TP+FP} = \frac{TP}{\text{all ground truths}}

    可理解为:预测为生病的数据中,有多少是真正生病的

  • 查全率、召回率、敏感性(sensitity,TPR):

    Recall=TP真实生病数=TPTP+FNRecall = \frac{TP}{真实生病数} = \frac{TP}{TP+FN}

    可理解为:真正生病的数据中,有多少是被预测出来的

  • F1 - score:

    F1score=21Precision+1Recall=2×Precision×RecallPrecision+RecallF1 - score = \frac{2}{\frac{1}{Precision} + \frac{1}{Recall}} = \frac{2 \times Precision \times Recall}{Precision + Recall}

    F1-score 是PrecisionPrecisionRecallRecall的调和平均数,可以如下理解:

对于多分类混淆矩阵而言,其混淆矩阵如下:

举例来说:

Ground Truth \ PredictionCatDogPig
Cat1523
Dog6120
Pig0422

Accuracy=15+12+2215+2+3+6+12+0+0+4+22Accuracy = \frac{15 + 12 + 22}{15 + 2 + 3 + 6 + 12 + 0 + 0 + 4 + 22}

对于 Cat:

Precision=1515+6+0    Recall=1515+2+3Precision = \frac{15}{15 + 6 + 0}\ \ \ \ Recall = \frac{15}{15 + 2 + 3}

对于 Dog:

Precsion=122+12+4   Recall=126+12+0Precsion = \frac{12}{2 + 12 + 4}\ \ \ Recall = \frac{12}{6 + 12 + 0}

围绕「查全」及「查准」找到对应分母即可

ROC 曲线

ROC(Receiver Operating Characteristic,受试者工作特性曲线),基于某一分类器下所有可能的阈值所构建的,其中:

  • x 轴——召回率(signal efficiency):TPR (recall)=TPTP+FNTPR\ (recall) = \frac{TP}{TP + FN}

  • y 轴——虚报率(background efficiency):FPR=FPFP+TNFPR = \frac{FP}{FP + TN}

  • AUCAUC:ROC 曲线下方与坐标轴所围成的面积(0.5AUC1)(0.5 \le AUC \le 1)

    显然,AUCAUC 越高,分类器的分类性能越好

完美的分类器随机猜测

适用场景

不均衡样本正样本极少(e.g. 垃圾邮件检测、信用卡欺诈)负样本极少
对数损失不敏感,故不适用不敏感,故不适用
F1-Score✅✅✅(更加有效)不适用
ROC - AUC

基于PyTorch框架的实现(自定义块版本)

假定训练一个分类器,根据学习时长(Hours),来分类出是否考试通过(Pass)

准备数据集

1
2
3
import torch
x_data = torch.Tensor([[1.0],[2.0],[3.0]])
y_data = torch.Tensor([[0], [0], [1]])

定义模型

1
2
3
4
5
6
7
8
9
10
class LogisticRegressionModel(torch.nn.Module):
def __init__(self): # 构造方法与线性回归基本一致
super(LogisticRegressionModel, self).__init__()
self.linear = torch.nn.Linear(1, 1)

def forward(self, x): # 前馈
y_pred = torch.sigmoid(self.linear(x)) # 不是调用.linear()
return y_pred

model = LogisticRegressionModel()

定义损失函数及优化器

1
2
criterion = torch.nn.BCELoss(reduction='sum')# 使用交叉熵(cross-entropy)
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01)

训练

此处仅使用了基本的梯度下降法

1
2
3
4
5
6
7
# 代码几乎没有变化
for epoch in range(1000):
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
optimizer.zero_grad()
loss.backward()
optimizer.step()

绘制图像

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 200) # 返回200个等间距的点
x_t = torch.Tensor(x).view((200, 1))
y_t = model(x_t)
y = y_t.data.numpy()
plt.plot(x, y)
plt.plot([0, 10], [0.5, 0.5], c = 'r') # 画出y=0.5直线
plt.xlabel('Hours')
plt.ylabel('Probability of Pass')
plt.grid()
plt.show()