逻辑回归
在本节课中,我们将使用逻辑回归来完成分类任务。
什么是逻辑回归?
逻辑回归(Logistic Regression)是一种用于机器学习分类任务的算法,用于根据某些自变量预测样本属于某一类别的概率。简而言之,逻辑回归模型会计算输入特征的加权和(通常包含一个偏置项),然后对结果应用逻辑函数(即Sigmoid函数)。
逻辑回归的输出值始终在 (0, 1) 区间内,因此非常适合二分类任务。输出越接近1,表示当前样本被划分为类别1(正类)的概率越高;反之,越接近0,则越可能属于类别0(负类)。
如上公式所示, 是我们需要学习或优化的参数, 是输入数据。当输出值接近 1 时,表示该样本更可能是正样本(y=1);若输出接近 0,则更可能是负样本(y=0)。
为了优化模型,我们需要定义一个损失函数(也称代价函数或目标函数)。在逻辑回归中,我们使用对数似然损失函数(log-likelihood loss):
其中, 表示训练样本的数量, 是第 个样本的真实标签, 是模型对该样本的预测概率。当某个样本的真实标签为 1 时,公式中的第二项为0,此时我们希望第一项越大越好;反之,若真实标签为 0,则希望第二项越大越好。最终将所有样本的损失求和取平均,并加上负号。我们的目标是最小化 : 越小,说明模型在数据集上的拟合效果越好。
由于无法通过解析方法直接求解最优 ,我们必须借助优化算法,例如梯度下降法。由于 是一个凸函数,因此梯度下降法能够保证找到全局最小值。
下面我们开始编写代码。
在乳腺癌数据集上建模
我们先跳过数据加载与划分部分,完整代码将在后文展示。
首先需要创建模型。在 sklearn 中,LogisticRegression 类位于 linear_model 模块下。我们需要先创建一个 LogisticRegression 对象。可以看到,我们传入了参数 solver="liblinear",该参数用于控制所使用的优化算法。对于小型数据集,liblinear 是首选求解器。还有许多其他可调参数,详细列表可参考官方API文档,本节仅关注如何使用。
LogisticRegression 提供多个可调节的超参数,例如 penalty、tol 和 C 等,这些不是本节重点,后续课程会进一步介绍。训练模型也非常简单,只需调用 fit 方法即可:
1from sklearn.linear_model import LogisticRegression 2 3lr = LogisticRegression(solver="liblinear") 4# train_x 和 train_y 分别是训练数据和标签 5lr.fit(train_x, train_y)
模型训练完成后,接下来评估其性能。在分类任务中,有许多可用的评估指标,如 AUC、精确率(precision)、召回率(recall)、F1-score 等,它们都被广泛使用。本节不会详细介绍所有指标,相关内容将在专门的“评估指标”课程中讲解。
以下是完整的代码示例,你可以动手尝试运行:
1import sklearn.datasets as datasets 2from sklearn.linear_model import LogisticRegression 3from sklearn.model_selection import train_test_split 4import sklearn.metrics as metrics 5import matplotlib.pyplot as plt 6import numpy as np 7 8cancer = datasets.load_breast_cancer() 9print("The data shape of breast cancer is {}".format(cancer.data.shape)) 10print("There are {} classes in this dataset".format(cancer.target_names.size)) 11 12train_x, test_x, train_y, test_y = train_test_split(cancer.data, 13 cancer.target, 14 test_size=0.2, 15 random_state=42) 16 17print("The first five samples {}".format(train_x[:5])) 18print("The first five targets {}".format(train_y[:5])) 19 20lr = LogisticRegression(solver="liblinear") 21lr.fit(train_x, train_y) 22 23pred_y = lr.predict(test_x) 24print("The first five prediction {}".format(pred_y[:5])) 25print("The real first five labels {}".format(test_y[:5])) 26 27cr = metrics.classification_report(test_y, pred_y) 28print(cr)
- 第8行调用
load_breast_cancer加载乳腺癌数据集,并在第12行将其划分为训练集和测试集。 - 第20行创建了一个
逻辑回归模型,示例中设置了参数solver="liblinear"。 - 第27行调用了
classification_report函数,第28行输出的结果将显示模型性能的详细报告。
曲线下面积(AUC)
AUC(Area Under the Curve)是分类任务中非常有用且常用的评估指标。在讨论AUC之前,我们需要理解ROC曲线:它是通过在不同阈值下绘制真阳性率(TPR)与假阳性率(FPR)的关系得到的。简而言之,AUC就是ROC曲线下的面积。若想深入了解AUC或ROC,可查阅相关资料。
在scikit-learn中,若要从测试集计算AUC指标,需执行以下步骤:
- 获取所有测试样本的预测概率得分;
- 计算一系列FPR和TPR;
- 计算曲线下面积。
请看以下代码。AUC值为 0.997,表明模型性能非常优秀。
1# lr 是前面构建的逻辑回归模型 2pred_score = lr.predict_proba(test_x) 3# pos_label 指定哪个整数值代表正类标签 4fpr, tpr, thresholds = metrics.roc_curve(test_y, pred_score[:,1], pos_label=1) 5auc = metrics.auc(fpr, tpr)
在生成的数据集上建模并绘制决策边界
我们再来看另一个例子。与前一个示例不同的是,本例将绘制决策边界,直观展示正样本、负样本以及分类边界。
决策边界(或决策面)是一个超平面,它将整个特征空间划分为两个区域,每个区域对应一个类别。
首先,我们使用 make_classification 生成一个包含两类标签的数据集。接着创建 LogisticRegression 模型并进行训练:
1import sklearn.datasets as datasets 2from sklearn.linear_model import LogisticRegression 3 4X,y = datasets.make_classification(n_features=2, 5 n_redundant=0, n_informative=1,n_clusters_per_class=1) 6lr2 = LogisticRegression(solver="liblinear") 7lr2.fit(X, y)
训练完成后,我们将测试数据点与决策边界一同绘制成图。图中数据点以两种颜色表示两个类别,中间的直线即为决策边界。结果显示分类效果良好,除少数异常点外,其余样本均被正确分开。
1import sklearn.datasets as datasets 2from sklearn.linear_model import LogisticRegression 3from sklearn.model_selection import train_test_split 4import sklearn.metrics as metrics 5import matplotlib.pyplot as plt 6import numpy as np 7 8X, y = datasets.make_classification(n_features=2, 9 n_redundant=0, 10 n_informative=1, 11 n_clusters_per_class=1) 12lr2 = LogisticRegression(solver="liblinear") 13lr2.fit(X, y) 14 15fig, axe = plt.subplots(dpi=800) 16axe.scatter(X[:, 0], X[:, 1], c=y, marker='o') 17line_bias = lr2.intercept_ 18line_w = lr2.coef_.T 19points_x = np.linspace(-2, 2, 100) 20points_y = [(line_w[0] * x + line_bias) / (-1 * line_w[1]) for x in points_x] 21axe.plot(points_x, points_y) 22fig.savefig("output/img.png", dpi = 300) 23plt.close(fig)
- 第8行通过调用
make_classification生成一个人工数据集,该数据集有两个特征和两个类别。由于本例不关注评估指标,无需划分训练集和测试集。 - 第12行创建
逻辑回归模型,并设置参数solver="liblinear"。 - 第15至21行使用 Matplotlib 绘制数据点并画出决策边界。在此例中,决策边界是一条直线,用于分隔两类数据点。
建议你动手运行上面的代码,以获得更丰富的交互式体验。