基于正则化逻辑回归的分类

作者:Eric · 发表于 2023年6月7日 · 更新于 2024年1月24日


文章目录

引言

逻辑回归长期以来一直是对分类结果进行建模的流行工具,广泛应用于流行病学、金融和计量经济学等领域。

在今天的博客中,我们将探讨逻辑回归的基础知识。我们将使用真实世界的调查数据应用,并提供逐步指南,帮助您使用 GAUSS 机器学习库实现自己的正则化逻辑回归模型,包括:

  1. 数据准备
  2. 模型拟合
  3. 分类预测
  4. 评估预测结果和模型拟合

什么是逻辑回归?

逻辑回归是一种统计方法,可用于基于观测到的特征或变量来预测事件发生的概率。然后可以根据概率阈值使用预测概率对数据进行分类。

例如,如果我们要对"TRUE"和"FALSE"结果进行建模,可以预测所有预测概率为 0.5 及以上的结果为"TRUE"。

从数学上讲,逻辑回归将结果的概率建模为自变量的逻辑函数:

$$ Pr(Y = 1 | X) = p(X) = \frac{e^{B_0 + B_1X}}{1 + e^{B_0 + B_1X}} $$

对数几率表示形式有时更常见,因为它对自变量是线性的:

$$ \log \bigg( \frac{p(X)}{1 + p(X)} \bigg) = B_0 + B_1X $$

关于此模型需要注意以下几点:

  • 逻辑回归模型始终产生介于 0 和 1 之间的预测值。
  • 逻辑回归模型中系数的大小不能像经典线性模型那样直接解释。
  • 逻辑回归模型中系数的符号可以按预期解释。例如,如果 $X_1$ 的系数为负,可以得出结论:增加 $X_1$ 会降低 $p(X)$。

带正则化的逻辑回归

逻辑回归的一个潜在缺陷是其容易过拟合,特别是在高维特征集的情况下。使用 L1 和/或 L2 惩罚参数的正则化有助于防止过拟合并改进预测。

L1与L2正则化比较

L1与L2正则化比较
$L1$ 惩罚(Lasso)$L2$ 惩罚(Ridge)
惩罚项$\lambda \sum_{j=1}^p |\beta_j|$$\lambda \sum_{j=1}^p \beta_j^2$
对异常值稳健
收缩系数
可选择特征
对相关特征敏感
有助于防止过拟合
有助于处理多重共线性
需要超参数选择(λ)

我们之前的博客 《使用机器学习回归模型预测产出缺口》 对 L1 和 L2 正则化进行了更详细的介绍。

使用调查数据预测客户满意度

今天我们将使用 航空公司乘客满意度数据来演示带正则化的逻辑回归。我们的任务是利用以下信息预测乘客满意度:

变量描述
id受访者标识号
Gender(性别)性别标识:女性或男性
Customer Type(客户类型)忠诚或不忠诚客户
Age(年龄)客户年龄(岁)
Type of travel(旅行类型)个人或商务旅行
Class(座位等级)经济舱或商务舱座位
Flight Distance(飞行距离)飞行距离(英里)
Wifi service(WiFi服务)客户评分(0-5 分制)
Schedule convenient(时间便捷性)客户评分(0-5 分制)
Ease of Online booking(在线预订便利性)客户评分(0-5 分制)
Gate location(登机口位置)客户评分(0-5 分制)
Food and drink(餐饮)客户评分(0-5 分制)
Seat comfort(座椅舒适度)客户评分(0-5 分制)
Online boarding(在线登机)客户评分(0-5 分制)
Inflight entertainment(机上娱乐)客户评分(0-5 分制)
On-board service(机上服务)客户评分(0-5 分制)
Leg room service(腿部空间)客户评分(0-5 分制)
Baggage handling(行李处理)客户评分(0-5 分制)
Checkin service(值机服务)客户评分(0-5 分制)
Inflight service(飞行服务)客户评分(0-5 分制)
Cleanliness(清洁度)客户评分(0-5 分制)
Departure Delay in minutes(出发延误分钟数)出发延误分钟数
Arrival Delay in minutes(到达延误分钟数)到达延误分钟数
satisfaction(满意度)整体航空公司满意度。可能回答包括"满意"或"中立或不满意"

分析的第一步是使用 loadd 加载数据:

new;
library gml;
rndseed 8906876;

/*
** Load datafile
*/
// Set path and filename
load_path = "data/";
fname = "airline_satisfaction.gdat";

// Load data
airline_data = loadd(load_path $+ fname);

// Split data
y = airline_data[., "satisfaction"];
X = delcols(airline_data, "satisfaction"$|"id");

数据探索

在开始建模之前,我们先做一些初步的数据探索。首先检查调查数据常见问题。

我们将检查:

  • 使用 isunique 检查重复观测值。
  • 使用 dstatmt 检查缺失值

首先检查重复项,以便在查看汇总统计之前删除任何重复项:

// Check for duplicates
isunique(airline_data);

isunique 过程返回 1(数据唯一)或 0(存在重复)。

1.00000000

结果显示数据中没有重复项。

接下来检查缺失值:

/*
** Check for data cleaning issues
*/
// Summary statistics
call dstatmt(airline_data);

这会打印所有变量的汇总统计信息

Variable                       Mean     Std Dev      Variance     Minimum     Maximum     Valid Missing
-------------------------------------------------------------------------------------------------------

Gender                        -----       -----         -----      Female        Male    103904    0
Customer Type                 -----       -----         -----  Loyal Cust  disloyal C    103904    0
Age                           39.38       15.11         228.5           7          85    103904    0
Type of Travel                -----       -----         -----  Business t  Personal T    103904    0
Class                         -----       -----         -----    Business    Eco Plus    103904    0
Flight Distance                2108        1266     1.603e+06           0        3801    103904    0
Wifi service                  -----       -----         -----           0           5    103904    0
Schedule convenient           -----       -----         -----           0           5    103904    0
Ease of Online booking        -----       -----         -----           0           5    103904    0
Gate location                 -----       -----         -----           0           5    103904    0
Food and drink                -----       -----         -----           0           5    103904    0
Online boarding               -----       -----         -----           0           5    103904    0
Seat comfort                  -----       -----         -----           0           5    103904    0
Inflight entertainment        -----       -----         -----           0           5    103904    0
Onboard service               -----       -----         -----           0           5    103904    0
Leg room service              -----       -----         -----           0           5    103904    0
Baggage handling              -----       -----         -----           1           5    103904    0
Checkin service               -----       -----         -----           0           5    103904    0
Inflight service              -----       -----         -----           0           5    103904    0
Cleanliness                   -----       -----         -----           0           5    103904    0
Departure Delay in Minutes    14.82       38.23          1462           0        1592    103904    0
Arrival Delay in Minutes      15.25       38.81          1506           0        1584    103904    0
satisfaction                  -----       -----         -----  neutral or   satisfied    103904    0

汇总统计信息给了我们一些有用的见解:

  • 数据集中没有缺失值。
  • 数值变量的汇总统计没有显示明显的异常值。
  • 所有分类调查数据的评分范围从 0 到 5,但 Baggage handling(行李处理) 除外,其范围从 1 到 5。所有分类变量需要在建模之前转换为虚拟变量。

从汇总统计中还可以观察到,许多变量名称过长。长变量名可能:难以记住、容易输错、打印结果时被截断(更不用说输入起来很烦人了!)。

让我们使用 dfname 简化变量名:

/*
** Update variable names
*/
// Create string array of short names
string short_names = {"Loyalty", "Reason", "Distance", "Wifi", 
                      "Schedule", "Booking", "Gate", "Boarding", 
                      "Entertainment", "Leg room", "Baggage", "Checkin", 
                      "Departure Delay", "Arrival Delay" };

// Create string array of original names to change                      
string original_names = { "Customer Type", "Type of Travel", "Flight Distance", "Wifi service",
                          "Schedule convenient", "Ease of Online booking", "Gate location", "Online boarding",
                          "Inflight entertainment", "Leg room service", "Baggage handling", "Checkin service",
                          "Departure Delay in Minutes", "Arrival Delay in Minutes" };

// Change names
airline_data = dfname(airline_data, short_names, original_names);

数据可视化

数据可视化是了解目标变量与特征之间关系的好方法。让我们探索客户和航班特征与报告的满意度之间的关系。特别地,我们将关注满意度与以下因素的关系:

  • 年龄
  • 性别
  • 飞行距离
  • 座位等级
  • 客户类型

准备绘图数据

今天我们将使用柱状图来探索数据中的关系。我们将数据分为子组,并检查这些子组报告的满意度。

对于分类变量,我们有天然定义的子组。但对于连续变量 Age(年龄)Distance(距离),我们首先需要基于这些变量的范围生成分箱。

首先将 Age 变量分箱。为此我们将使用 reclassifycutsreclassify 过程:

/*
** Create bins for age
*/
// Set age categories cut points
// Class 0: 20 and Under
// Class 1: 21 - 30
// Class 2: 31 - 40
// Class 3: 41 - 50
// Class 4: 51 - 60
// Class 5: 61 - 70
// Class 6: Over 70
cut_pts = { 20, 30, 40, 50, 60, 70 };

// Create numeric classes
age_new = reclassifycuts(airline_data[., "Age"], cut_pts);

// Generate labels to recode to
to = "20 and Under"$|
       "21-30"$|
       "31-40"$|
       "41-50"$|
       "51-60"$|
       "61-70"$|
       "Over 70";

// Recode to categorical variable
age_cat = reclassify(age_new, unique(age_new), to);

// Convert to dataframe
age_cat = asDF(age_cat, "Age Group");

可以使用 frequency 过程快速查看此分类变量的频数:

// Check frequency of age groups
frequency(age_cat, "Age Group");
       Label      Count   Total %    Cum. %
20 and Under      11333     10.91     10.91
       21-30      21424     20.62     31.53
       31-40      21203     20.41     51.93
       41-50      23199     22.33     74.26
       51-60      18769     18.06     92.32
       61-70       7220     6.949     99.27
     Over 70        756    0.7276       100
       Total     103904       100

现在对 Distance(距离) 进行同样的操作:

/*
** Create bins for flight distance
*/       
// Set distance categories cut points
cut_pts = { 1000, 1500, 2000, 2500, 3000, 3500 };

// Create numeric classes
distance_new = reclassifycuts(airline_data[., "Distance"], cut_pts);

// Generate labels to recode to
to = "1000 and Under"$|
       "1001-1500"$|
       "1501-2000"$|
       "2001-2500"$|
       "2501-3000"$|
       "3000-3500"$|
       "Over 3500";

// Recode to categorical variable
distance_cat = reclassify(distance_new, unique(distance_new), to);

// Convert to dataframe
distance_cat = asDF(distance_cat, "Flight Range");

// Check frequencies
frequency(distance_cat, "Flight Range");
         Label      Count   Total %    Cum. %
1000 and Under      28017     26.96     26.96
     1001-1500      10976     10.56     37.53
     1501-2000       9331      8.98     46.51
     2001-2500       7834      7.54     54.05
     2501-3000       8053      7.75      61.8
     3000-3500      24815     23.88     85.68
     Over 3500      14878     14.32       100
         Total     103904       100

年龄

不同年龄组的满意度分布

从上图可以看出,20 岁及以下和 60 岁以上的乘客比其他年龄组更不容易满意。

性别

不同性别的满意度分布

图表显示性别对报告的满意度影响很小。

飞行距离

不同飞行距离的满意度分布

飞行距离图显示,3000 英里及以上和 1000 英里及以下的航程满意度略低。

座位等级

不同座位等级的满意度分布

商务舱乘客与其他乘客的满意度存在明显差异。商务舱客户的满意率远高于经济舱或优选经济舱客户。

客户类型

不同客户类型的满意度分布

最后,忠诚乘客比不忠诚乘客更经常感到满意。

特征工程

与调查数据常见的情况一样,我们的许多变量都是分类变量。我们需要在建模之前将它们表示为虚拟变量。我们将使用 oneHot 过程来实现。由于 oneHot 只接受单个变量,我们需要循环遍历所有分类变量。

首先创建所有分类变量的列表:

/*
** Create dummy variables
*/
// Get all variable names
col_names = getColNames(X);

// Get types of all variables
col_types = getColTypes(X);

// Select names of variables that are categorical
cat_names = selif(col_names, col_types .== "category");

// Loop through categorical variables to create dummy variables
dummy_vars = {};
for i(1, rows(cat_names), 1); 
    dummy_vars = dummy_vars~oneHot(X[., cat_names[i]]);
endfor;

// Delete original categorical variables and replace with dummy variables
X = delcols(x, cat_names)~dummy_vars;

模型评估

使用 classificationMetrics 过程报告多个分类指标。这些指标提供了模型在不同目标上表现如何的信息。

模型比较指标

模型比较指标
指标描述
准确率(Accuracy)整体模型准确率。等于正确预测数除以总预测数。
精确率(Precision)模型正确识别类别结果的能力。等于真正例数除以假正例数加真正例数。
召回率(Recall)模型正确预测所有类别结果的能力。等于真正例数除以假负例数加真正例数。
F1 分数精确率和召回率的调和平均,提供模型性能更平衡的视角。分数为 1 表示完美的精确率和召回率。

在拟合和测试模型时,我们将牢记这些指标。

逻辑回归模型拟合

现在我们准备开始拟合模型。首先准备数据:

使用 trainTestSplit 创建训练和测试数据集。

// Split data into 70% training and 30% test set
{ y_train, y_test, X_train, X_test } = trainTestSplit(y, X, 0.7);

使用 rescale 缩放数据。

/*
** Data rescaling
*/
// Number of variables to rescale
numeric_vars = 4;

// Rescale training data
{ X_train[.,1:numeric_vars], x_mu, x_sd } = rescale(X_train[.,1:numeric_vars], "standardize");

// Rescale test data using same scaling factors as x_train
X_test[.,1:numeric_vars] = rescale(X_test[.,1:numeric_vars], x_mu, x_sd);

随机森林模型不同,逻辑回归模型对变量尺度的大差异很敏感。如上所示,我们从训练集计算均值和标准差,并使用这些参数来缩放测试集。这一点很重要。

测试集的目的是估计模型在未见数据上的表现。在训练/测试划分之前使用整个数据集的均值和标准差,会导致测试集信息"泄漏"到模型中。信息泄漏超出了本文的范围,但一般来说,测试集应被视为在模型拟合完成之后才可用的信息。

案例一:无正则化的逻辑回归

作为基准案例,我们将考虑不带任何正则化的逻辑回归模型。我们将使用所有默认设置,因此唯一的输入是因变量和自变量数据。

使用训练数据:

/*************************************
** Base case model
** No regularization
*************************************/

/*
** Training
*/
// Declare 'lr_mdl' to be 
// an 'logisticRegModel' structure
// to hold the trained model
struct logisticRegModel lr_mdl;

// Train the logistic regression classifier
lr_mdl = logisticRegFit(y_train, X_train);

// Check training set performance
y_hat_train = lmPredict(lr_mdl, X_train);

// Model evaluations
print "Training Metrics";
call classificationMetrics(y_train, y_hat_train);

classificationMetrics 过程打印评估表:

No regularization
Training Metrics
==============================================================
                                        Classification metrics
==============================================================
                  Class   Precision  Recall  F1-score  Support

neutral or dissatisfied        0.93    0.92      0.93    41102
              satisfied        0.90    0.91      0.90    31631

              Macro avg        0.91    0.92      0.91    72733
           Weighted avg        0.92    0.92      0.92    72733

               Accuracy                          0.92    72733
/*
** Testing
*/
// Make predictions on the test set, from our trained model
y_hat_test = lmPredict(lr_mdl, X_test);

/*
** Model evaluation
*/
print "Testing Metrics";
call classificationMetrics(y_test, y_hat_test);

这段代码打印以下结果:

Testing Metrics
==============================================================
                                        Classification metrics
==============================================================
                  Class   Precision  Recall  F1-score  Support

neutral or dissatisfied        0.93    0.92      0.92    17777
              satisfied        0.90    0.91      0.90    13394

              Macro avg        0.91    0.91      0.91    31171
           Weighted avg        0.91    0.91      0.91    31171

               Accuracy                          0.91    31171

比较训练数据和测试数据的表现,有几点值得注意:

  • 首先,训练集和测试集的准确率差异很小,训练准确率为 0.92,测试准确率为 0.91。
  • 我们的模型在测试集和训练集上提供了相同的平均 F1 分数,这提供了平衡的性能度量。

这为什么重要?这种比较很好地表明我们没有过拟合训练集。由于正则化的主要目的是解决模型过度拟合训练数据的问题,我们并没有太多理由使用它。但为了演示目的,我们将展示如何实现 L2 正则化。

案例二:带 L2 正则化的逻辑回归

要使用 logisticRegFit 实现正则化,我们将使用一个 logisticRegControl 结构。

/*************************************
** L2 Regularization
*************************************/

/*
** Training
*/
// Declare 'lrc' to be a logisticRegControl
// structure and fill with default settings 
struct logisticRegControl lrc;
lrc = logisticRegControlCreate();

// Set L2 regularization parameter
lrc.l2 = 0.05;

// Declare 'lr_mdl' to be 
// a 'logisticRegModel' structure
// to hold the trained model
struct logisticRegModel lr_mdl;

// Train the logistic regression classifier
lr_mdl = logisticRegFit(y_train, X_train, lrc);

/*
** Testing
*/
// Make predictions on the test set
y_hat_l2 = lmPredict(lr_mdl, X_test);

/*
** Model evaluation
*/
call classificationMetrics(y_test, y_hat_l2);

分类指标打印如下:

L2 regularization
==============================================================
                                        Classification metrics
==============================================================
                  Class   Precision  Recall  F1-score  Support

neutral or dissatisfied        0.89    0.93      0.91    17777
              satisfied        0.90    0.84      0.87    13394

              Macro avg        0.90    0.89      0.89    31171
           Weighted avg        0.89    0.89      0.89    31171

               Accuracy                          0.89    31171

注意,使用 L2 惩罚后,模型性能相比基准案例有所下降,准确率(0.89)和平均 F1 分数(0.89)均降低。这并不意外,因为我们之前并未发现模型存在过拟合的证据。

结论

在今天的博客中,我们探讨了逻辑回归和正则化。通过使用真实世界的航空公司乘客满意度数据应用,我们:

  1. 执行了初步数据准备和设置。
  2. 训练了带正则化和不带正则化的逻辑回归模型。
  3. 进行了分类预测。
  4. 解释了分类指标。

延伸阅读

  1. 使用机器学习技术预测经济衰退
  2. 主成分分析在金融中的应用
  3. 使用机器学习回归模型预测产出缺口
  4. 机器学习超参数调优基础
  5. 理解交叉验证
  6. 使用真实世界数据进行机器学习

 

 


 

在线留言

尊敬的客户朋友,如您有任何意见建议,请通过下表反馈给我们,我们会尽快与您联系。

 

 

 

 

联系我们

 

微信公众号

咨询微信

企业店铺

400-621-1085

(节假日期间办公室座机如无人接听,请选择其他联系方式,感谢理解!祝您节日快乐!)

 

联系我们 快速链接 相关产品 上海卡贝信息技术有限公司

©2026  上海卡贝信息技术有限公司

产品中心

下载中心

站点地图

隐私政策

 

销售QQ咨询

产品QQ咨询

淘宝店铺

 

综述

GAUSS产品

应用程序

第三方应用程序

最新更新:26版

相关文档

下载试用

购买咨询

 

SAS

GraphPad Prism

LISREL

SmartPLS

Stata

HLM

IRTPRO

TreeAge

Design-Expert

IBM SPSS Statistics

EViews

RATS

SigmaPlot

EndNote

Citavi

LINGO

@RISK

BayesiaLab

Hugin

E-Prime

XLfit