|
基于正则化逻辑回归的分类作者:Eric · 发表于 2023年6月7日 · 更新于 2024年1月24日 文章目录引言逻辑回归长期以来一直是对分类结果进行建模的流行工具,广泛应用于流行病学、金融和计量经济学等领域。 在今天的博客中,我们将探讨逻辑回归的基础知识。我们将使用真实世界的调查数据应用,并提供逐步指南,帮助您使用 GAUSS 机器学习库实现自己的正则化逻辑回归模型,包括:
什么是逻辑回归?逻辑回归是一种统计方法,可用于基于观测到的特征或变量来预测事件发生的概率。然后可以根据概率阈值使用预测概率对数据进行分类。 例如,如果我们要对"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 $$ 关于此模型需要注意以下几点:
带正则化的逻辑回归逻辑回归的一个潜在缺陷是其容易过拟合,特别是在高维特征集的情况下。使用 L1 和/或 L2 惩罚参数的正则化有助于防止过拟合并改进预测。 L1与L2正则化比较
我们之前的博客 《使用机器学习回归模型预测产出缺口》 对 L1 和 L2 正则化进行了更详细的介绍。 使用调查数据预测客户满意度今天我们将使用 航空公司乘客满意度数据来演示带正则化的逻辑回归。我们的任务是利用以下信息预测乘客满意度:
分析的第一步是使用 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"); 数据探索在开始建模之前,我们先做一些初步的数据探索。首先检查调查数据常见问题。 我们将检查:
首先检查重复项,以便在查看汇总统计之前删除任何重复项: // Check for duplicates isunique(airline_data);
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 汇总统计信息给了我们一些有用的见解:
从汇总统计中还可以观察到,许多变量名称过长。长变量名可能:难以记住、容易输错、打印结果时被截断(更不用说输入起来很烦人了!)。 让我们使用 /*
** 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);
数据可视化数据可视化是了解目标变量与特征之间关系的好方法。让我们探索客户和航班特征与报告的满意度之间的关系。特别地,我们将关注满意度与以下因素的关系:
准备绘图数据今天我们将使用柱状图来探索数据中的关系。我们将数据分为子组,并检查这些子组报告的满意度。 对于分类变量,我们有天然定义的子组。但对于连续变量 首先将 /*
** 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");
可以使用 // 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
现在对 /*
** 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 英里及以下的航程满意度略低。 座位等级商务舱乘客与其他乘客的满意度存在明显差异。商务舱客户的满意率远高于经济舱或优选经济舱客户。 客户类型最后,忠诚乘客比不忠诚乘客更经常感到满意。 特征工程与调查数据常见的情况一样,我们的许多变量都是分类变量。我们需要在建模之前将它们表示为虚拟变量。我们将使用 首先创建所有分类变量的列表: /*
** 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;
模型评估使用 模型比较指标
在拟合和测试模型时,我们将牢记这些指标。 逻辑回归模型拟合现在我们准备开始拟合模型。首先准备数据: 使用 // Split data into 70% training and 30% test set
{ y_train, y_test, X_train, X_test } = trainTestSplit(y, X, 0.7);
使用 /*
** 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);
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
比较训练数据和测试数据的表现,有几点值得注意:
这为什么重要?这种比较很好地表明我们没有过拟合训练集。由于正则化的主要目的是解决模型过度拟合训练数据的问题,我们并没有太多理由使用它。但为了演示目的,我们将展示如何实现 L2 正则化。 案例二:带 L2 正则化的逻辑回归要使用 /************************************* ** 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)均降低。这并不意外,因为我们之前并未发现模型存在过拟合的证据。 结论在今天的博客中,我们探讨了逻辑回归和正则化。通过使用真实世界的航空公司乘客满意度数据应用,我们:
延伸阅读
在线留言尊敬的客户朋友,如您有任何意见建议,请通过下表反馈给我们,我们会尽快与您联系。
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||