建立预测模型:Python中的逻辑回归
打造准确预测模型:Python中的逻辑回归
当您开始学习机器学习时,逻辑回归是您将添加到工具箱中的第一个算法之一。它是一种简单而强大的算法,常用于二分类任务。
考虑一个包含0和1两个类别的二分类问题。逻辑回归将一个逻辑或S形函数拟合到输入数据,并预测查询数据点属于类别1的概率。有趣的,不是吗?
在本教程中,我们将从头开始学习逻辑回归,内容包括:
- 逻辑(或S形)函数
- 如何从线性回归转化为逻辑回归
- 逻辑回归的工作原理
最后,我们将构建一个简单的逻辑回归模型,用于对电离层的雷达回波进行分类。
逻辑函数
在我们深入了解逻辑回归之前,让我们回顾一下逻辑函数的工作原理。逻辑(或S形)函数可表示为:
绘制逻辑函数时,如下所示:
根据绘图结果,我们可以看到:
- 当x = 0时,σ(x)的值为0.5。
- 当x趋近于+∞时,σ(x)趋近于1。
- 当x趋近于-∞时,σ(x)趋近于0。
因此,对于所有实数输入,逻辑函数将它们压缩到取值范围为[0, 1]的区间内。
从线性回归到逻辑回归
让我们首先讨论为什么不能对二分类问题使用线性回归。
在二分类问题中,输出是一个分类标签(0或1)。因为线性回归预测的是连续值输出,可能小于0或大于1,这在目标问题上是没有意义的。
此外,在输出标签属于两个类别之一时,直线可能不是最佳拟合。
那么我们如何从线性回归转化为逻辑回归呢?在线性回归中,预测输出由以下式子给出:

其中β是系数,X_i是预测变量(或特征)。
不失一般性,让我们假设X_0 = 1:

因此,我们可以得到一个更简洁的表达式:
在逻辑回归中,我们需要预测的概率p_i在[0,1]区间内。我们知道,逻辑函数将输入“压缩”以使其取值范围在[0,1]区间内。
因此,将这个表达式代入逻辑函数,我们得到了预测概率:
逻辑回归的内部工作原理
那么我们如何找到最适用于给定数据集的逻辑曲线?为了回答这个问题,让我们了解最大似然估计。
最大似然估计(MLE)用于通过最大化似然函数估计逻辑回归模型的参数。让我们详细介绍逻辑回归中MLE的过程以及如何使用梯度下降优化来构建成本函数。
拆解最大似然估计
如前所述,我们将二元结果发生的概率建模为一个或多个预测变量(或特征)的函数:
这里,β是模型参数或系数。X_1, X_2,…, X_n是预测变量。
MLE旨在找到最大化观察数据的似然性的β值。似然函数被表示为L(β),表示在逻辑回归模型下观察到给定预测值的给定结果的概率。
构建对数似然函数
为了简化优化过程,通常使用对数似然函数,因为它将概率乘积转化为对数概率之和。
逻辑回归的对数似然函数由以下公式给出:
成本函数与梯度下降
现在我们知道了对数似然的本质,让我们继续构建逻辑回归的成本函数,以及通过梯度下降寻找最佳模型参数。
逻辑回归的成本函数
为了优化逻辑回归模型,我们需要最大化对数似然度。因此我们可以使用负的对数似然度作为成本函数,在训练过程中进行最小化。负对数似然度,通常称为逻辑损失,定义如下:
学习算法的目标是找到最小化该成本函数的β值。梯度下降是一种常用的优化算法,用于寻找该成本函数的最小值。
逻辑回归中的梯度下降
梯度下降 是一种迭代优化算法,通过沿着成本函数相对于β的梯度的相反方向更新模型参数β。逻辑回归使用梯度下降的步骤t+1的更新规则如下:
这里α是学习率。
可以使用链式法则计算偏导数。梯度下降迭代地更新参数,直到收敛,找到最大化观察数据似然性的β的最优值。
使用Scikit-Learn在Python中进行逻辑回归
现在您已经了解逻辑回归的工作原理,让我们使用Scikit-Learn库构建一个预测模型。
我们将使用UCI机器学习仓库的ionosphere数据集进行本教程。该数据集包含34个数值特征。输出是二进制的,为“good”或“bad”(用“g”或“b”表示)。输出标签“good”指的是在电离层中检测到一些结构的雷达返回。
步骤1 – 加载数据集
首先,下载数据集并将其读入到pandas dataframe中:
import pandas as pd
import urllib
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/ionosphere/ionosphere.data"
data = urllib.request.urlopen(url)
df = pd.read_csv(data, header=None)
步骤2 – 探索数据集
让我们来看一下数据框的前几行:
# 显示DataFrame的前几行
df.head()
df.head()的截断输出
让我们获取关于数据集的一些信息:非空值的数量和每列的数据类型:
# 获取关于数据集的信息
print(df.info())
df.info()的截断输出
因为我们的特征都是数值型的,我们还可以使用数据帧的describe()方法获取一些描述性统计信息:
# 获取数据集的描述性统计信息
print(df.describe())
df.describe()的截断输出
目前,列名为0至34,包括标签。因为数据集没有为列提供描述性名称,它只将它们称为attribute_1到attribute_34。如果你愿意,你可以像下面的示例一样重新命名数据框的列名:
column_names = ["attribute_1", "attribute_2", "attribute_3", "attribute_4", "attribute_5",
"attribute_6", "attribute_7", "attribute_8", "attribute_9", "attribute_10",
"attribute_11", "attribute_12", "attribute_13", "attribute_14", "attribute_15",
"attribute_16", "attribute_17", "attribute_18", "attribute_19", "attribute_20",
"attribute_21", "attribute_22", "attribute_23", "attribute_24", "attribute_25",
"attribute_26", "attribute_27", "attribute_28", "attribute_29", "attribute_30",
"attribute_31", "attribute_32", "attribute_33", "attribute_34", "class_label"]
df.columns = column_names
注意:这一步是可选的。如果你愿意,可以继续使用默认的列名。
# 显示DataFrame的前几行
df.head()
df.head()的截断输出(重新命名列名后)
步骤3 – 重命名类别标签并可视化类别分布
因为输出的类别标签是’g’和’b’,我们需要将其分别映射到1和0,可以使用map()或replace()来完成:
# 将类别标签从'g'和'b'转换为1和0
df["class_label"] = df["class_label"].replace({'g': 1, 'b': 0})
我们还可以可视化类别标签的分布:
import matplotlib.pyplot as plt# 计算每个类别中的数据点数量class_counts = df['class_label'].value_counts()# 创建柱状图可视化类别分布plt.bar(class_counts.index, class_counts.values)plt.xlabel('类别标签')plt.ylabel('数量')plt.xticks(class_counts.index)plt.title('类别分布')plt.show()
类别标签的分布
我们可以看到分布存在一定的不平衡,类别1的记录数量多于类别0的记录。在构建逻辑回归模型时,我们将处理这种类别不平衡。
步骤5 – 数据集预处理
让我们像这样收集特征和输出标签:
X = df.drop('class_label', axis=1) # 输入特征y = df['class_label'] # 目标变量
将数据集拆分为训练集和测试集后,我们需要对数据集进行预处理。
当存在多个数值特征时,每个特征可能处于不同的尺度上,所以我们需要对数值特征进行预处理。常见的方法是将它们转换为具有零均值和单位方差的分布。
来自scikit-learn的preprocessing模块的StandardScaler可以帮助我们实现这一目标。
from sklearn.preprocessing import StandardScalerfrom sklearn.model_selection import train_test_split# 将数据集拆分为训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 获取数值特征的索引列表numerical_feature_indices = list(range(34)) # 假设数值特征在列0到33之间# 初始化StandardScalerscaler = StandardScaler()# 对训练集中的数值特征进行标准化X_train.iloc[:, numerical_feature_indices] = scaler.fit_transform(X_train.iloc[:, numerical_feature_indices])# 使用训练集上训练的scaler对测试集中的数值特征进行标准化X_test.iloc[:, numerical_feature_indices] = scaler.transform(X_test.iloc[:, numerical_feature_indices])
步骤6 – 构建逻辑回归模型
现在我们可以创建一个逻辑回归分类器。 逻辑回归类(LogisticRegression)是scikit-learn的linear_model模块的一部分。
请注意,我们已将class_weight参数设置为’balanced’。这将帮助我们考虑类别不平衡。通过为每个类别分配权重,与类别中的记录数量成反比。
在实例化类之后,我们可以将模型拟合到训练数据集中:
from sklearn.linear_model import LogisticRegressionmodel = LogisticRegression(class_weight='balanced')model.fit(X_train, y_train)
步骤7 – 评估逻辑回归模型
您可以调用predict()方法获取模型的预测结果。
除了准确率分数外,我们还可以得到包含精确度、召回率和F1值等指标的分类报告。
from sklearn.metrics import accuracy_score, classification_reporty_pred = model.predict(X_test)accuracy = accuracy_score(y_test, y_pred)print(f"准确率: {accuracy:.2f}")classification_rep = classification_report(y_test, y_pred)print("分类报告:\n", classification_rep)
恭喜,您已经编写了第一个逻辑回归模型!
结论
在本教程中,我们详细了解了逻辑回归:从理论和数学到编写逻辑回归分类器的过程。
作为下一步,尝试为您选择的合适的数据集构建逻辑回归模型。
数据集来源
Ionosphere数据集使用知识共享署名4.0国际许可 (CC BY 4.0) 进行许可:
Sigillito,V., Wing,S., Hutton,L., and Baker,K.. (1989). Ionosphere. UCI机器学习仓库. https://doi.org/10.24432/C5W01B.
[Bala Priya C](https://twitter.com/balawc27) 是一名来自印度的开发者和技术作家。她喜欢在数学、编程、数据科学和内容创作的交叉领域工作。她感兴趣和擅长的领域包括DevOps、数据科学和自然语言处理。她喜欢阅读、写作、编程和咖啡!目前,她正在通过撰写教程、指南、观点文章等来学习和与开发者社区分享自己的知识。




