Logistic Regression in Python – From Zero to Hero
作者:禅与计算机程序设计艺术
1.简介
Logistic Regression (LR) 是一种常用的分类模型,用于预测某个事件的发生或不发生,属于线性模型。它可以用来解决二分类问题,即预测一个样本是正面类别还是负面类别的问题。但是LR也可扩展到多分类问题、回归问题等其它类型的问题上。
LR模型的核心在于计算每个样本的“概率”值,也就是它属于正面类别的概率或者属于负面的概率。那么如何根据LR模型的结果做出预测呢?LR模型的预测方法有两种:
-
最大后验估计(MAP)法:这种方法认为每次试验的结果都遵循一个概率分布,比如贝叶斯定理,假设第i次试验的结果服从正态分布,那么第i个样本的“似然函数”的形式就是y_i=b_0+βx_i,其中b_0表示正例的截距项,β表示参数,x_i表示输入特征向量。通过对各个样本求“似然函数”的均值,就可以得到这组数据的“期望输出”,再用贝叶斯公式求出这个“期望输出”的概率分布。最后选取使得“期望输出”最高的那个作为最终的分类结果。
-
频率派法:这种方法认为在每一个可能的分类上都会有一个确定的概率,也就是说,“硬币正反面出现的次数比例”或“某种疾病的患病率”。因此,首先要计算出每个样本对应的所有可能的类别(假设有k个可能的类别),然后再分别统计这些样本在每个类别上的“响应变量”(比如正面或负面)的个数。利用这些统计数据,就可以计算出各个类的“先验概率”,或者说各个类的“极大似然估计”。然后,将每个样本的“输入特征”代入“条件概率”公式,计算出该样本属于各个类别的“似然概率”。最后,根据这些似然概率乘上相应的“先验概率”值,就得到了每一个样本的“后验概率”。最后,选择具有最大“后验概率”值的类别作为最终的分类结果。
在实际应用中,通常会用MLlib库中的LogisticRegression()函数实现LR分类器。它的主要参数如下:
- featuresCol: 指定用于训练模型的数据集的特征列名。
- labelCol: 指定用于训练模型的数据集的标签列名。
- predictionCol: 指定模型的预测输出列名。
- maxIter: 设置迭代次数,一般设置10至50次就能获得比较好的效果。
- regParam: L2正则化参数,默认设置为0。如果设置为0,则没有L2正则化。如果设置为非零值,则会添加L2正则化。
- elasticNetParam: L1/L2正则化参数,默认设置为0,即只有L2正则化。如果设置为1,则同时添加L1和L2正则化。
- family: 设置拟合模型的分布族,目前支持三种分布族:
- "gaussian":适用于连续变量的线性回归。
- "binomial":适用于二元分类问题。
- "multinomial":适用于多元分类问题。
本文基于Spark MLlib进行LR模型的实现。
2.相关概念及术语说明
2.1 朴素贝叶斯概率模型
朴素贝叶斯概率模型(Naive Bayes probability model)是由周志华教授提出的关于信息检索的统计学习方法。该模型基于贝叶斯定理,假设所有特征之间相互独立,并根据特征出现的先验概率和每个特征给定的值,计算出每个类别(观察者)出现的概率。该模型假设特征之间相互独立,因此朴素贝叶斯模型也可以被称为“简单模型”。该模型还能够处理缺失数据,只需要将缺失数据视为可能值。
2.2 概率密度函数(Probability Density Function,PDF)
在数学上,概率密度函数(英语:probability density function;缩写作 PDF)是一个描述一个随机变量 X 的分布的函数。在概率论和统计学中,概率密度函数提供了一种非标准的表示方式,用直观的方式来显示随机变量的概率分布。概率密度函数是一个定义域为自然数的连续函数,其值可以被认为是 X 在某个点 x 下的分度(希腊字母 pai 为 “probability” 的首字母)。概率密度函数的积分表示了分布的总体概率。
当概率密度函数存在时,随机变量的概率分布可以写成概率质量函数(Probability Mass Function,PMF)。具体来说,对于离散型随机变量,如果 x 是变量的一个可能值,则 PMF 表示为 P(X = x),等于概率密度函数值在点 x 处的积分。对于连续型随机变量,PMF 可以定义为概率密度函数在自变量取任意值时的面积。
2.3 对数似然函数(Log-likelihood function)
在机器学习和优化里,对数似然函数(英语:log-likelihood function 或 log likelihood)是衡量模型参数的指标之一,是决定模型是否正确的参数。在模型已知的情况下,最大化对数似然函数等价于最小化负对数似然函数,负对数似然函数又被称为边缘似然函数(marginal likelihood)。
假设模型的目标是对观测到的数据 y 进行分类,并且模型的参数为 θ ,且假设 X 和 Y 具有联合概率分布 P(X,Y;θ)。对数似然函数 L(θ) 是模型参数 θ 使得观测到的观测数据 y 拥有概率最大的对数概率,也就是说,对于给定的样本 x∈D,模型预测出的 y=f(x;θ) 应该有较大的概率。即:
L(θ)=∑_{i=1}^N[y_ilogp(x_i|y=c;θ)+(1−y_ilog(1−p(x_i|y=c;θ)))]
其中 N 是数据集的大小, c ∈ {1,2,...,K} 是分类的类别, log 是以 e 为底的自然对数。
为了使得模型能够更好地拟合数据,就需要找到使得似然函数(或似然密度函数)最大的模型参数。由于 θ 的数量远远多于 N,所以无法直接对所有的 θ 取值进行搜索。通常采用梯度下降法(gradient descent algorithm)、拟牛顿法(Newton method)或共轭梯度法(conjugate gradient method)等方法来确定参数的值。
3.核心算法原理和具体操作步骤以及数学公式讲解
3.1 模型构建
(1)准备数据集
构建LR模型的数据集需要包括以下三个元素:输入特征、输出标签和样本权重。其中,输入特征是指用于预测的属性值,输出标签是目标变量,如是否违规,是否恶意等;权重是样本的重要程度,可以通过抽样方法赋予不同样本不同的权重。此外,LR模型还需要知道类别的数量,决定模型的复杂程度。
(2)特征工程
对输入特征进行预处理的方法很多,包括数据清洗、数据变换、特征选择等。数据清洗主要是删除异常值、缺失值和冗余数据;数据变换包括特征缩放、归一化和特征交叉等;特征选择方法包括方差选择、卡方检验、递归特征消除等。在实际应用中,特征工程是数据预处理的一环,对性能影响很大。
(3)模型评估方法
模型评估的方法主要有十几种,包括准确率(accuracy)、精确率(precision)、召回率(recall)、ROC曲线、AUC等。准确率代表的是分类正确的样本占全部样本的百分比,精确率代表的是检出的样本中真实样本的比例,召回率代表的是正确检出的样本比例。其他方法还有平均损失(mean loss)、宏查全率(macro averaged recall)、微查全率(micro averaged recall)、F1分数等。
(4)超参数调整
超参数是指对模型进行训练过程中的参数,如学习速率、迭代次数、正则化系数、正则化类型等。超参数的选择对模型的训练有着至关重要的作用,通常通过网格搜索或随机搜索的方法来寻找最优值。
3.2 算法原理
LR模型通过分析样本中的输入特征之间的关系来建立对输入特征的模型。LR模型假设每个特征在样本间服从高斯分布,并假设样本数据服从伯努利分布。
(1)高斯分布
高斯分布(Gaussian distribution)是一种连续型概率分布,它是数学上两个变量的线性组合的概率分布,满足钟形曲线的分布图。高斯分布由两个参数,均值 μ 和 标准差 σ^2 来确定,μ 是分布的中心,σ^2 是分布的尺度。高斯分布的概率密度函数可以表示为:
P(x)=exp(-1/2(x-μ)^T _σ-1_(x-μ))/sqrt(2π*σ2)
μ 和 σ^2 是高斯分布的自然参数,用来描述分布的位置和尺度。
(2)伯努利分布
伯努利分布(Bernoulli distribution)又称两点分布,是离散型概率分布,只有两种可能的取值:成功或失败,常用来描述单个事件的成功概率。伯努利分布的概率质量函数可以表示为:
P(x)=px(1-p){1-x}
p 是单次试验成功的概率。
(3)似然函数与似然估计
对于给定的训练数据集,似然函数(likelihood function)用来表示模型对训练数据集中样本的信心程度。如果模型参数 θ 导致训练样本出现的概率非常小,那么似然函数就会趋近于零;如果模型参数 θ 导致训练样本出现的概率非常大,那么似然函数就会趋近于无穷大。似然函数的表达式如下:
L(θ)=∏_n{p(x^{(n)};θ)}
p(x^{(n)};θ) 是模型对第 n 个样本的似然估计, θ 是模型的参数。
计算似然函数的目的就是为了求解模型参数 θ 使得似然函数取得最大值。然而,直接求解似然函数的最大值并不是一个好方案。因为直接计算似然函数的最大值存在一些困难,原因如下:
- 参数空间的复杂度过高:对于高维模型,模型的参数数量指数增长,参数空间的复杂度也随之指数增长,因此,计算模型参数的概率分布变得越来越困难。
- 数据集的规模太小:当样本数量 n 小于参数的数量 k 时,模型参数 θ 的确切值往往不好估计,因此,直接求解似然函数的最大值可能会产生偏差。
为了避免以上两个问题,引入了参数估计的方法。
(4)极大似然估计
极大似然估计(maximum likelihood estimation,MLE)是一种参数估计的方法,其基本思想是在已知模型的情况下,估计模型参数使得观测到的数据出现的概率最大。它通过极大化似然函数的方法来寻找使似然函数取得最大值的模型参数。极大似然估计可以被看作是从参数空间中找到使观测数据的分布最一致的模型参数。极大似icheatsettlestimation 的表达式如下:
θ=argmax_{\theta}{L(\theta)}=\underset{\theta}{argmin}-\frac{1}{n}\sum_{i=1}{n}[y_ilogp(x{(i)};\theta)+(1−y_ilog(1−p(x^{(i)};\theta)))]
θ 是模型的参数,n 是数据集的大小,y_i 是第 i 个样本的输出值,x^{(i)} 是第 i 个样本的输入特征。MLE 方法的目标就是找到使得似然函数取得最大值的 θ。
MLE 方法有如下特点:
- 当样本数量 n 大于参数的数量 k 时,极大似然估计是最有效的方法。
- 通过极大化似然函数,MLE 可求得准确的模型参数,而且不需要对模型进行过度假设,因此,MLE 容易实现。
- MLE 方法在高维空间中仍然有效。
(5)负对数似然函数与最大熵模型
对于给定的训练数据集,负对数似然函数(negative log-likelihood function,NLL)表示模型对训练数据集中样本的不确定程度。如果模型参数 θ 导致训练样本出现的概率非常小,那么负对数似然函数就会趋近于正无穷大;如果模型参数 θ 导致训练样本出现的概率非常大,那么负对数似然函数就会趋近于负无穷大。NLL 与似然函数的关系如下:
NLL=-log(L(θ))=-∑_{i=1}^N[y_ilogp(x_i|y=c;θ)+(1−y_ilog(1−p(x_i|y=c;θ)))],
η 是常数项,在这里忽略掉。
最大熵模型(Maximum Entropy Model,ME)是一种基于信息理论的模型,它由多个高斯分布构成,并且要求每个高斯分布的均值和方差固定,但不对其参数进行限制。最大熵模型可以在各种数据集上表现良好,是一种强大的监督学习方法。ME 模型的基本思路是希望模型对训练数据集中的每个样本给出高置信度的预测,因此,ME 模型往往用于分类问题中。
ME 模型的表达式如下:
ln(p(x|y))=-\frac{(1/2)(√((2\pi)d||Ω||)T)y(1/2)(z(x)-μ)||Ω(1/2)T-(1/2)||Ω{-1}μ-z(x)||2}{\lambda}+\frac{1}{2}(∂mu_cTz(x)+λ∇mu_c^Ts(x))+c_0-\frac{1}{2}ln|\Omega|-d/2\pi
其中,z(x) 是输入 x 的隐含变量,∞ 为无穷大,Ω 是表示模型方差的对角矩阵。λ 是正则化参数,它控制了模型的复杂度。
由于 ME 模型没有显式的参数,因此只能依靠负对数似然函数来进行参数估计。因此,对于 MLE 方法,NLL 与似然函数的转换关系如下:
NLL=-log(L(θ))=-∑_{i=1}^N[y_ilogp(x_i|y=c;θ)+(1−y_ilog(1−p(x_i|y=c;θ)))].
ME 模型的似然函数可以表示为:
ln(p(x|y,\Lambda))=\int q(z(x)|y,\Lambda)ln(\frac{p(x,z(x);y,\Lambda)}{q(z(x)|y,\Lambda)})dz(x),
其中,q(z(x)|y,\Lambda) 是用于表示模型输出的分布,当用极大似然估计进行参数估计时,需要在似然函数中加入正则化项来惩罚模型的参数过度依赖训练数据。λ 越小,惩罚越厉害,模型的复杂度越低;λ 越大,惩罚越弱,模型的复杂度越高。
(6)损失函数与优化算法
损失函数(loss function)是评价模型在训练过程中质量的指标。在模型训练过程中,如果损失函数的值不断减少,说明模型正在逐渐学会对训练数据集的表现越来越准确,否则的话,模型可能遇到了参数过拟合、欠拟合等问题。
损失函数常用的有平方误差损失函数、绝对值误差损失函数、对数似然损失函数等。对于不同类型的模型,损失函数的选择往往不同。损失函数的计算公式如下:
L=(y_pred-y)^2+(1-y_pred)*log(1-y_pred)
y_pred 是模型对训练样本的预测值,y 是真实值。
优化算法(optimization algorithm)是指模型训练过程中用来更新模型参数的算法。如随机梯度下降法(stochastic gradient descent)、改进的随机梯度下降法(improved stochastic gradient descent)、拟牛顿法(Newton's method)、共轭梯度法(conjugate gradient method)等。在模型训练过程中,优化算法应该不断更新模型参数,使得损失函数值最小,从而使模型更加精确地拟合训练数据。
3.3 代码实现
from pyspark.ml.classification import LogisticRegression
from pyspark.sql.functions import col, lit
import pandas as pd
# 创建 SparkSession
spark = SparkSession \
.builder \
.appName("Logistic Regression") \
.config("spark.some.config.option", "some-value") \
.getOrCreate()
# 加载训练数据
train_data = spark.read.csv("file:///path/to/training_dataset.csv", header=True)
train_data.cache().count() # 查看数据集大小
# 将标签转换为向量
label_assembler = VectorAssembler(inputCols=["label"], outputCol="labelVec")
labeled_data = label_assembler.transform(train_data).select('features', 'labelVec')
# 设置 LR 模型参数
lr = LogisticRegression(maxIter=10, regParam=0.3, elasticNetParam=0.8, family='multinomial')
# 拆分数据集
splits = labeled_data.randomSplit([0.7, 0.3])
train = splits[0]
test = splits[1]
print("Training Dataset Count: " + str(train.count()))
print("Test Dataset Count: " + str(test.count()))
# 训练模型
model = lr.fit(train)
# 使用模型对测试数据集进行预测
predictions = model.transform(test)
predictions.show()
# 查看模型评估指标
evaluator = BinaryClassificationEvaluator(rawPredictionCol="prediction")
accuracy = evaluator.evaluate(predictions)
print("Model Accuracy: " + str(accuracy))
# 模型保存与加载
model.write().overwrite().save("/path/to/model")
sameModel = LogisticRegressionModel.load("/path/to/model")
代码解读
