1. 逻辑回归算法概述
逻辑回归(Logistic Regression)是机器学习领域最基础且实用的分类算法之一。虽然名称中带有"回归"二字,但它实际上是一种用于解决二分类问题的线性模型。我第一次接触这个算法是在2013年处理信用卡欺诈检测项目时,当时就被它简洁的数学形式和出色的解释性所吸引。
与线性回归直接预测数值不同,逻辑回归通过sigmoid函数将线性组合的结果映射到(0,1)区间,可以理解为事件发生的概率。比如在医疗诊断中,我们可以用逻辑回归预测患者患某种疾病的概率;在金融风控中,可以预测贷款违约的可能性。这种概率输出的特性使得逻辑回归成为许多业务场景的首选算法。
注意:虽然逻辑回归常用于二分类,但通过One-vs-Rest或Softmax扩展也可以处理多分类问题。不过本文主要聚焦其最典型的二分类应用。
2. 算法原理深度解析
2.1 核心数学原理
逻辑回归的核心在于sigmoid函数(也称为logistic函数):
σ(z) = 1 / (1 + e^(-z))
其中z = w^T x + b,即特征的线性组合。这个函数的精妙之处在于它将任意实数映射到(0,1)区间,完美契合概率的定义。我经常用"压扁弹簧"的比喻向新手解释——无论输入值多大或多小,输出都会被"压"在0到1之间。
在实际项目中,参数估计通常采用极大似然估计法。我们构建似然函数:
L(w,b) = ∏ [σ(z)]^y [1-σ(z)]^(1-y)
然后通过梯度下降等优化算法找到使似然函数最大化的参数w和b。这里有个经验之谈:当特征量纲差异大时,建议先进行标准化处理,否则梯度下降可能收敛缓慢。
2.2 损失函数的选择
逻辑回归最常用的损失函数是交叉熵损失(Cross-Entropy Loss),其数学表达式为:
J(w,b) = -[y log(σ(z)) + (1-y)log(1-σ(z))]
与均方误差损失相比,交叉熵在分类问题中有两个显著优势:
- 当预测值与真实值差距较大时,梯度也较大,有利于快速收敛
- 避免了sigmoid函数与平方损失组合导致的梯度消失问题
在TensorFlow中实现时,可以注意到它已经内置了将sigmoid和交叉熵联合计算的优化版本tf.nn.sigmoid_cross_entropy_with_logits,这比分开计算更数值稳定。
3. 工程实现关键细节
3.1 特征工程实践
逻辑回归对特征工程的质量非常敏感。根据我的项目经验,以下几个处理步骤往往能显著提升模型效果:
- 缺失值处理:对于数值特征,我通常用中位数填充;对于类别特征,则单独作为一个类别处理。在Python中可以用SimpleImputer实现:
python复制from sklearn.impute import SimpleImputer
num_imputer = SimpleImputer(strategy='median')
cat_imputer = SimpleImputer(strategy='constant', fill_value='missing')
-
类别特征编码:避免直接使用LabelEncoder,它会引入虚假的大小关系。推荐使用OneHotEncoder或更节省空间的TargetEncoding。当类别数量很多时,可以考虑哈希技巧。
-
特征交叉:手动构造特征交互项有时能带来意外惊喜。比如在广告点击率预测中,"用户年龄段"与"广告类别"的组合特征往往比单独特征更有区分度。
3.2 正则化策略
逻辑回归容易过拟合,特别是在特征维度高而样本量少的情况下。常用的正则化方法有:
- L1正则(LASSO):产生稀疏解,适用于特征选择
- L2正则(Ridge):使参数平滑衰减
- ElasticNet:结合L1和L2的优点
在scikit-learn中的实现示例:
python复制from sklearn.linear_model import LogisticRegression
# L1正则
model_l1 = LogisticRegression(penalty='l1', solver='liblinear', C=0.1)
# L2正则
model_l2 = LogisticRegression(penalty='l2', C=0.1)
参数C是正则化强度的倒数,通常需要通过交叉验证来确定最佳值。我的经验是从0.001到100的对数空间中进行网格搜索。
4. 模型评估与优化
4.1 评估指标选择
准确率(Accuracy)是最直观的指标,但在类别不平衡时可能产生误导。比如在欺诈检测中,即使模型总是预测"非欺诈",准确率也可能高达99.9%。这种情况下应该关注:
- 精确率(Precision):预测为正的样本中实际为正的比例
- 召回率(Recall):实际为正的样本中被正确预测的比例
- F1分数:精确率和召回率的调和平均
- ROC-AUC:综合考量模型在不同阈值下的表现
在sklearn中计算这些指标非常方便:
python复制from sklearn.metrics import classification_report
print(classification_report(y_true, y_pred))
4.2 阈值调整技巧
逻辑回归默认使用0.5作为分类阈值,但这不一定是最优选择。通过调整阈值可以在精确率和召回率之间取得平衡。我常用的方法是:
- 计算测试集上每个样本的预测概率
- 绘制精确率-召回率曲线
- 根据业务需求选择合适阈值
例如,在癌症筛查中我们可能更关注召回率(尽量不漏诊),而在垃圾邮件过滤中则更看重精确率(避免误判正常邮件)。
5. 实战案例:信用卡欺诈检测
5.1 数据准备与探索
我们使用Kaggle上的信用卡欺诈数据集,这是一个典型的类别不平衡数据集(欺诈交易仅占0.17%)。首先进行探索性分析:
python复制import pandas as pd
df = pd.read_csv('creditcard.csv')
print(df['Class'].value_counts(normalize=True))
由于隐私保护,原始特征已经过PCA处理,我们保留Time和Amount两个原始特征。Amount特征的值范围很大,需要进行对数变换:
python复制import numpy as np
df['LogAmount'] = np.log1p(df['Amount'])
5.2 模型训练与评估
考虑到类别极度不平衡,我们采取以下策略:
- 使用分层抽样确保训练集和测试集分布一致
- 在损失函数中引入类别权重
- 使用SMOTE算法进行过采样
实现代码:
python复制from sklearn.model_selection import train_test_split
from imblearn.over_sampling import SMOTE
X_train, X_test, y_train, y_test = train_test_split(
X, y, stratify=y, test_size=0.3)
smote = SMOTE(random_state=42)
X_res, y_res = smote.fit_resample(X_train, y_train)
model = LogisticRegression(class_weight='balanced', max_iter=1000)
model.fit(X_res, y_res)
最终我们获得了0.98的AUC分数,召回率达到0.85,这在欺诈检测中已经是相当不错的表现。
6. 常见问题与解决方案
6.1 收敛问题
问题现象:模型无法收敛,或者损失函数震荡严重。
可能原因及解决方案:
- 学习率过大 → 减小学习率或使用自适应学习率算法(如Adam)
- 特征尺度差异大 → 进行标准化处理
- 正则化强度不合适 → 调整C参数
- 数据存在异常值 → 进行RobustScaler处理
6.2 预测概率校准
有时逻辑回归输出的概率不够准确(比如预测为0.9的事件实际只发生了70%)。这时可以使用Platt Scaling或Isotonic Regression进行概率校准:
python复制from sklearn.calibration import CalibratedClassifierCV
calibrated = CalibratedClassifierCV(model, method='isotonic', cv=5)
calibrated.fit(X_train, y_train)
6.3 多分类扩展
虽然逻辑回归本质是二分类器,但可以通过以下方式扩展到多分类:
- One-vs-Rest:训练K个二分类器(K为类别数)
- Multinomial Logistic Regression:使用softmax函数直接建模多类概率分布
在sklearn中只需设置multi_class参数:
python复制model = LogisticRegression(multi_class='multinomial', solver='lbfgs')
7. 与其他算法的对比
7.1 与线性回归的对比
虽然都带有"回归"二字,但两者有本质区别:
- 线性回归:输出连续值,最小化平方误差
- 逻辑回归:输出概率,最大化似然函数
一个常见的误区是试图用线性回归解决分类问题,这会导致预测值超出[0,1]范围且对异常值敏感。
7.2 与决策树的对比
决策树可以自动处理非线性关系,但容易过拟合;逻辑回归需要手动构造非线性特征,但模型更简单、解释性更强。在实践中,我经常将两者结合使用:
- 先用决策树进行特征选择
- 提取决策路径作为新特征
- 再用逻辑回归建模
这种方法在不少Kaggle比赛中被证明有效。
7.3 与神经网络的对比
对于简单的线性可分问题,逻辑回归通常就足够好,而且训练更快、更易解释。但随着数据复杂度增加,特别是存在高阶交互时,神经网络的优势会显现出来。我的经验法则是:先从逻辑回归开始,只有当其表现明显不足时才考虑更复杂的模型。
逻辑回归模型训练完成后,可以通过检查系数来分析每个特征的影响方向和大小。例如在金融风控模型中,我们可能会发现"最近30天逾期次数"这个特征的系数显著为正,说明它与违约风险正相关。这种解释性在需要模型透明度的领域(如金融、医疗)尤为重要。