赞
踩
逻辑回归是机器学习中非常重要的一种统计方法,广泛用于分类问题。尽管名为“回归”,逻辑回归实际上是用来做二分类的工具,例如判断邮件是否为垃圾邮件,或者一个患者是否有某种疾病。逻辑回归的优点在于它的输出可以被解释为概率,这为决策提供了便利,而且它相对简单,易于实现,是初学者入门机器学习的良好起点。
本文将全面解析逻辑回归模型,包括它的结构、学习目标、优化算法,以及如何使用 Python 进行实现。读者将从基本的数学原理了解到如何在实际数据集上应用逻辑回归,最终能够自己动手编写代码,建立并优化逻辑回归模型。文章的结构清晰,旨在帮助刚接触人工智能的大学新生,理解并掌握逻辑回归的核心概念和应用。
模型定义
逻辑回归(Logistic Regression,简称 LR)是一种广义线性模型(GLM),通常用于分类问题。与传统的线性回归模型(预测连续值输出)不同,逻辑回归预测的是一个概率值,表示为介于 0 和 1 之间的数。这使得它非常适合于二分类问题,比如预测一个电子邮件是不是垃圾邮件。
模型功能
逻辑回归通过输入特征的加权和,使用 sigmoid 函数将任意实数映射到 (0, 1) 区间,输出一个概率值。Sigmoid 函数的 S 形曲线确保了输出值在 0 到 1 之间,这个值表示样本属于正类(通常编码为 1)的概率。
决策边界
逻辑回归模型的决策边界是功能的关键,这是一个用来决定样本分类的边界。在逻辑回归中,这个边界是线性的,意味着它可以用一条直线(或者在多维空间中是一个超平面)来表示。当逻辑回归模型的输出(概率)等于 0.5 时,对应的输入特征组合就位于这条决策边界上。
逻辑回归的数学基础非常重要,理解它有助于深入掌握模型的工作原理。模型本质上是一个概率估计,通过最大似然估计(MLE)来优化参数。公式表达为:
其中 ( p ) 是给定输入特征 ( x ) 下样本属于正类的概率,( w ) 表示模型参数。
逻辑回归的目标是调整 ( w ) 的值,使得模型的预测尽可能接近实际的标签。
预测和实际的对比
在使用逻辑回归进行分类时,核心目标是确保模型的预测概率尽可能接近实际的标签。例如,如果一个样本的实际标签是 1(正类),逻辑回归模型预测这个样本属于正类的概率应该接近 1。相反,如果样本的标签是 0(负类),则模型的预测概率应接近 0。这种方式帮助我们评价和优化模型的性能,确保模型能够正确区分不同类别的样本。
最大似然估计(MLE)是一种在统计模型中估计参数的方法,它寻找能够使观测到的数据出现概率最大的参数值。在逻辑回归中,MLE尝试找到一组参数,使得给定参数下,观测到的样本标签的概率最大化。这通常通过优化一个称为似然函数的表达式来实现,该函数是对所有数据点的预测概率的乘积。
交叉熵损失函数解释
交叉熵损失函数是评估逻辑回归模型性能的一个关键工具。它衡量的是模型预测的概率分布与实际标签的概率分布之间的差异。公式可以表示为:
其中 ( y ) 是实际标签,( p ) 是预测为正类的概率。这个损失函数的值越小,表示模型的预测结果与实际情况越接近。
一般来说,交叉熵损失函数的值越小,模型的分类准确度越高。通过训练过程中损失函数的下降趋势,我们可以观察到模型性能的改善。实际操作中,可以通过绘制训练周期与损失值的图表来直观展示这一过程,帮助理解模型优化的效果。
算法原理
梯度下降法是一种用于优化逻辑回归模型参数的流行算法,其核心思想是利用函数的梯度(或斜率)来确定参数更新的方向。梯度指示了函数增长最快的方向,因此在优化过程中,我们沿着梯度的相反方向(下降最快的方向)调整参数,以寻找函数的最小值。
梯度下降可以通过一个简单的比喻来理解:想象你在山上,需要找到下山的最快路径。在任何位置,你都可以查看周围最陡峭的下坡路,然后朝那个方向迈出一步。梯度下降法就是这样在参数空间中寻找损失函数最小值的方法。
算法步骤
梯度下降的每一步都需要计算损失函数关于每个参数的梯度
其中:
是损失函数 ( J ) 关于参数 (θ) 的梯度
更新的步骤重复进行,直到满足停止条件,例如梯度的大小小于某个阈值,或达到预定的迭代次数。
在实际操作中,选择合适的学习率是非常关键的,因为太小的学习率会导致收敛过慢,而太大的学习率则可能导致跳过最小值点,使得算法无法正确收敛。
数据集简介
我们将使用乳腺癌分类数据集(Breast Cancer Wisconsin Diagnostic Dataset)进行逻辑回归的实践。这个数据集包含了乳腺癌肿瘤的各种医学特征,每个样本被标记为恶性或良性,非常适合用来练习二分类问题。选择此数据集的原因是因为它的特征明确、数据质量高,且问题设置符合逻辑回归处理的典型场景。
数据预处理
数据预处理是机器学习中至关重要的一步,它直接影响模型的性能。对乳腺癌数据集的预处理包括:
核心函数解释
在Python中实现逻辑回归,我们需要定义几个核心函数:
sigmoid
:该函数计算sigmoid激活,用于将线性回归输出转换为概率。
- def sigmoid(z):
- return 1 / (1 + np.exp(-z))
- # initialize_with_zeros:初始化模型参数。
- def initialize_with_zeros(dim):
- w = np.zeros((dim, 1))
- b = 0
- return w, b
- # propagate:计算损失函数和梯度,用于后续的梯度下降步骤。
- def propagate(w, b, X, Y):
- m = X.shape[1]
- A = sigmoid(np.dot(w.T, X) + b)
- cost = (-1 / m) * np.sum(Y * np.log(A) + (1 - Y) * np.log(1 - A))
- dw = (1 / m) * np.dot(X, (A - Y).T)
- db = (1 / m) * np.sum(A - Y)
- return dw, db, cost
- # 准确率计算
- def accuracy(Y_true, Y_pred):
- return np.mean(Y_true == Y_pred)
完整代码
- import numpy as np
- import pandas as pd
- from sklearn.model_selection import train_test_split
- from sklearn.preprocessing import StandardScaler
- from sklearn.metrics import confusion_matrix, accuracy_score
-
- # 定义sigmoid函数
- def sigmoid(z):
- return 1 / (1 + np.exp(-z))
-
- # 初始化参数
- def initialize_with_zeros(dim):
- w = np.zeros((dim, 1))
- b = 0
- return w, b
-
- # 前向和后向传播
- def propagate(w, b, X, Y):
- m = X.shape[1]
- A = sigmoid(np.dot(w.T, X) + b)
- cost = (-1 / m) * np.sum(Y * np.log(A) + (1 - Y) * np.log(1 - A))
- dw = (1 / m) * np.dot(X, (A - Y).T)
- db = (1 / m) * np.sum(A - Y)
- return dw, db, cost
-
- # 优化函数
- def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost=False):
- costs = []
- for i in range(num_iterations):
- dw, db, cost = propagate(w, b, X, Y)
- w = w - learning_rate * dw
- b = b - learning_rate * db
- if i % 100 == 0:
- costs.append(cost)
- if print_cost:
- print("Cost after iteration %i: %f" % (i, cost))
- return w, b, costs
-
- # 预测函数
- def predict(w, b, X):
- m = X.shape[1]
- Y_prediction = np.zeros((1, m))
- w = w.reshape(X.shape[0], 1)
- A = sigmoid(np.dot(w.T, X) + b)
- for i in range(A.shape[1]):
- Y_prediction[0, i] = 1 if A[0, i] > 0.5 else 0
- return Y_prediction
-
- # 主函数
- def model(X_train, Y_train, X_test, Y_test, num_iterations=2000, learning_rate=0.5, print_cost=False):
- w, b = initialize_with_zeros(X_train.shape[0])
- w, b, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)
- Y_prediction_test = predict(w, b, X_test)
- Y_prediction_train = predict(w, b, X_train)
-
-
- # 计算准确率
- train_accuracy = 100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100
- test_accuracy = 100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100
-
- print("train accuracy: {} %".format(train_accuracy))
- print("test accuracy: {} %".format(test_accuracy))
-
- d = {"costs": costs,
- "Y_prediction_test": Y_prediction_test,
- "Y_prediction_train": Y_prediction_train,
- "train_accuracy": train_accuracy,
- "test_accuracy": test_accuracy,
- "w": w,
- "b": b,
- "learning_rate": learning_rate,
- "num_iterations": num_iterations}
- return d
- import numpy as np
- import numpy as np
- from sklearn import datasets
- from sklearn.model_selection import train_test_split
- from sklearn.preprocessing import StandardScaler
-
- # 加载数据
- data = datasets.load_breast_cancer()
- X, y = data.data, data.target
-
- # 分割数据为训练集和测试集
- X_train, X_test, Y_train, Y_test = train_test_split(X, y, test_size=0.2, random_state=42)
-
- # 特征标准化
- scaler = StandardScaler()
- X_train = scaler.fit_transform(X_train)
- X_test = scaler.transform(X_test)
-
- # 将标签数据格式化为正确的形状
- Y_train = Y_train.reshape((Y_train.shape[0], 1)).T
- Y_test = Y_test.reshape((Y_test.shape[0], 1)).T
-
- # 调用模型函数
- results = model(X_train.T, Y_train, X_test.T, Y_test, num_iterations=2000, learning_rate=0.005, print_cost=True)
-
- # 打印准确率
- print("Training accuracy: {:.2f}%".format(results['train_accuracy']))
- print("Test accuracy: {:.2f}%".format(results['test_accuracy']))
这段代码演示了如何加载乳腺癌数据集,对其进行预处理,并用逻辑回归模型进行训练和测试。确保在运行这些代码之前已经定义了 model()
函数及其相关的辅助函数,如 sigmoid()
、initialize_with_zeros()
、propagate()
和 optimize()
。
运行输出
逻辑回归是一项可用于预测二分类结果(binary outcome)的统计技术,广泛应用于金融、医学、犯罪学和其他社会科学中。逻辑回归使用简单且非常有效,你可以在许多机器学习、应用统计的书中的前几章中找到个关于逻辑回归的介绍。逻辑回归在许多统计课程中都会用到。
我们不难找到使用R语言的高质量的逻辑回归实例,如UCLA的教程R Data Analysis Examples: Logit Regression就是一个很好的资源。Python是机器学习领域最流行的语言之一,并且已有许多Python的资源涵盖了支持向量积和文本分类等话题,但少有关于逻辑回归的资料。
示例代码中使用了一些算法包,请确保在运行这些代码前,你的电脑已经安装了如下包:
可参考 Windows安装Python机器学习包 或 Ubuntu/CentOS安装Python机器学习包 来搭建所需要的环境。
在此使用与Logit Regression in R相同的数据集来研究Python中的逻辑回归,目的是要辨别不同的因素对研究生录取的影响。
数据集中的前三列可作为预测变量(predictor variables):
gpa
gre
分数rank
表示本科生母校的声望第四列admit
则是二分类目标变量(binary target variable),它表明考生最终是否被录用。
使用 pandas.read_csv
加载数据,这样我们就有了可用于探索数据的DataFrame
。
language-python
注意到有一列属性名为rank
,但因为rank
也是pandas dataframe中一个方法的名字,因此需要将该列重命名为"prestige".
现在我们就将需要的数据正确载入到Python中了,现在来看下数据。我们可以使用pandas
的函数describe
来给出数据的摘要--describe
与R语言中的summay
类似。这里也有一个用于计算标准差的函数std
,但在describe
中已包括了计算标准差。
我特别喜欢pandas
的pivot_table/crosstab
聚合功能。crosstab
可方便的实现多维频率表(frequency tables)(有点像R语言中的table
)。你可以用它来查看不同数据所占的比例。
language-python
运行代码后,绘制的柱状统计图如下所示:
虚拟变量,也叫哑变量,可用来表示分类变量、非数量因素可能产生的影响。在计量经济学模型,需要经常考虑属性因素的影响。例如,职业、文化程度、季节等属性因素往往很难直接度量它们的大小。只能给出它们的“Yes—D=1”或”No—D=0”,或者它们的程度或等级。为了反映属性因素和提高模型的精度,必须将属性因素“量化”。通过构造0-1型的人工变量来量化属性因素。
pandas
提供了一系列分类变量的控制。我们可以用get_dummies
来将"prestige"一列虚拟化。
get_dummies
为每个指定的列创建了新的带二分类预测变量的DataFrame,在本例中,prestige
有四个级别:1,2,3以及4(1代表最有声望),prestige
作为分类变量更加合适。当调用get_dummies
时,会产生四列的dataframe,每一列表示四个级别中的一个。
language-python
这样,数据原本的prestige
属性就被prestige_x
代替了,例如原本的数值为2,则prestige_2
为1,prestige_1
、prestige_3
、prestige_4
都为0。
将新的虚拟变量加入到了原始的数据集中后,就不再需要原来的prestige
列了。在此要强调一点,生成m个虚拟变量后,只要引入m-1个虚拟变量到数据集中,未引入的一个是作为基准对比的。
最后,还需加上常数intercept,statemodels
实现的逻辑回归需要显式指定。
实际上完成逻辑回归是相当简单的,首先指定要预测变量的列,接着指定模型用于做预测的列,剩下的就由算法包去完成了。
本例中要预测的是admin
列,使用到gre
、gpa
和虚拟变量prestige_2
、prestige_3
、prestige_4
。prestige_1
作为基准,所以排除掉,以防止多元共线性(multicollinearity)和引入分类变量的所有虚拟变量值所导致的陷阱(dummy variable trap)。
language-python
在这里是使用了statesmodels
的Logit函数,更多的模型细节可以查阅statesmodels
的文档
(本小节是博主补充的)通过上述步骤,我们就得到了训练后的模型。基于这个模型,我们就可以用来预测数据,代码如下:
language-python
在这里,我是简单的将原始数据再作为待预测的数据进行检验。通过上述步骤得到的是一个概率值,而不是一个直接的二分类结果(被录取/不被录取)。通常,我们可以设定一个阈值,若 predict 大于该阈值,则认为是被录取了,反之,则表示不被录取。
在上面的例子中,假定预测概率大于 0.5 则表示预测被录取,一共预测有 49 个被录取,其中有 30 个预测命中,精确度为 61.22%。
statesmodels
提供了结果的摘要,如果你使用过R语言,你会发现结果的输出与之相似。
language-python
language-python
你可以看到模型的系数,系数拟合的效果,以及总的拟合质量,以及一些统计度量。[待补充: 模型结果主要参数的含义]
当然你也可以只观察结果的某部分,如置信区间(confidence interval)可以看出模型系数的健壮性。
language-python
在这个例子中,我们可以肯定被录取的可能性与应试者毕业学校的声望存在着逆相关的关系。
换句话说,高排名学校(prestige_1==True)的湘鄂生呗录取的概率比低排名学校(prestige_4==True)要高。
odds ratio: OR值,是相对危险度,又称比值比、优势比。
使用每个变量系数的指数来生成odds ratio,可知变量每单位的增加、减少对录取几率的影响。例如,如果学校的声望为2,则我们可以期待被录取的几率减少大概50%。UCLA上有一个对odds ratio更为深入的解释: 在逻辑回归中如何解释odds ratios?。
language-python
我们也可以使用置信区间来计算系数的影响,来更好地估计一个变量影响录取率的不确定性。
language-python
为了评估我们分类器的效果,我们将使用每个输入值的逻辑组合(logical combination)来重新创建数据集,如此可以得知在不同的变量下预测录取可能性的增加、减少。首先我们使用名为 cartesian
的辅助函数来生成组合值(来源于: 如何使用numpy构建两个数组的组合)
我们使用 np.linspace
创建 "gre" 和 "gpa" 值的一个范围,即从指定的最大、最小值来创建一个线性间隔的值的范围。在本例子中,取已知的最大、最小值。
language-python
现在我们已生成了预测结果,接着通过画图来呈现结果。我编写了一个名为 isolate_and_plot
的辅助函数,可以比较给定的变量与不同的声望等级、组合的平均可能性。为了分离声望和其他变量,我使用了 pivot_table
来简单地聚合数据。
language-python
结果图显示了 gre, gpa 和 prestige 如何影响录取。可以看出,随着 gre 和 gpa 的增加,录取可能性如何逐渐增加,并且,不同的学校声望对录取可能性的增加程度相差很大。
逻辑回归是用于分类的优秀算法,尽管有一些更加性感的,或是黑盒分类器算法,如SVM和随机森林(RandomForest)在一些情况下性能更好,但深入了解你正在使用的模型是很有价值的。很多时候你可以使用随机森林来筛选模型的特征,并基于筛选出的最佳的特征,使用逻辑回归来重建模型。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。