逻辑回归LR与广义线性模型GLM

逻辑回归(Logistic Regression, LR)和广义线性模型(Generalized Linear Model, GLM)是统计建模和机器学习中的重要工具。它们常用于分类问题和回归分析。以下是关于逻辑回归和广义线性模型开发实践的一些专业知识:

1. 广义线性模型(GLM)概述

广义线性模型是一个扩展的线性回归模型,它允许响应变量(因变量)具有不同的分布族,而不仅仅是正态分布。GLM包括三个主要组成部分:

逻辑回归是一种用于解决二分类问题的对数线性模型。它的核心思想是将逻辑函数(sigmoid函数)应用于线性回归的预测值,从而将原始的实数输出转换为概率形式。这样,我们就可以通过设定一个阈值来将概率转换为最终的分类结果。

在实践中,逻辑回归具有简单、高效和易于解释等优点。然而,它也有一些局限性,例如对异常值的敏感性以及在多分类问题中的表现不佳。

  • 线性预测器:表示为 η=Xβ\eta = X\betaη=Xβ,其中 XXX 是输入特征矩阵,β\betaβ 是回归系数。
  • 链接函数:将线性预测器 η\etaη 映射到响应变量的均值。例如,逻辑回归使用逻辑函数作为链接函数。
  • 分布族:响应变量的概率分布,如二项分布(逻辑回归)、泊松分布(泊松回归)、正态分布(线性回归)等。

2. 逻辑回归(LR)

逻辑回归是广义线性模型的一个特例,主要用于二分类问题。它的核心思想是通过逻辑函数将线性预测器的输出映射到一个介于0和1之间的概率值。

逻辑回归模型的主要组成部分:
  • 线性预测器:η=Xβ\eta = X\betaη=Xβ
  • 逻辑链接函数:p=11+e−(Xβ)p = \frac{1}{1 + e^{-(X\beta)}}p=1+e−(Xβ)1​,其中 ppp 是事件发生的概率。
  • 损失函数:逻辑回归使用的是交叉熵损失函数,也称为对数损失(log-loss)。
逻辑回归模型的开发实践:
  1. 数据预处理

    • 特征标准化:标准化特征有助于加快收敛速度,特别是在梯度下降算法中。
    • 处理不平衡数据:对于类别不平衡的数据,可以使用过采样、欠采样或生成对抗样本等方法进行处理。
  2. 模型拟合

    • 选择优化算法:逻辑回归可以使用梯度下降法、拟牛顿法(如BFGS)或其他优化算法进行拟合。
    • 正则化:使用L1(Lasso)或L2(Ridge)正则化来防止过拟合。
  3. 模型评估

    • 评估指标:常用指标包括准确率、精确率、召回率、F1分数、ROC曲线和AUC值。
    • 交叉验证:使用k折交叉验证评估模型的稳定性和泛化能力。
  4. 超参数调优

    • 选择正则化参数:通过交叉验证选择最佳的正则化参数。

除了逻辑回归,GLM还包括其他回归模型,如:

  • 泊松回归:用于计数数据,响应变量服从泊松分布。适用于事件发生的次数建模。

    • 链接函数:对数链接函数,即 log⁡(λ)=Xβ\log(\lambda) = X\betalog(λ)=Xβ,其中 λ\lambdaλ 是事件的发生率。
  • 负二项回归:用于过度离散的计数数据,响应变量服从负二项分布。

  • Gamma回归:用于正值连续响应变量,适合处理响应变量为非负连续数据。

  1. 选择合适的分布和链接函数

    • 根据响应变量的类型选择合适的分布族和链接函数。
  2. 数据预处理

    • 处理缺失值:根据情况选择插补或删除缺失值。
    • 特征选择:选择对响应变量有显著影响的特征。
  3. 模型拟合与评估

    • 使用最大似然估计(MLE)进行参数估计。
    • 对于泊松回归和Gamma回归,可以使用伪R²、AIC(赤池信息准则)和BIC(贝叶斯信息准则)等指标评估模型的拟合优度。
  4. 诊断与调整

    • 诊断残差:检查残差的分布,识别模型假设是否合理。
    • 模型调整:根据诊断结果进行模型调整,如变换响应变量或选择不同的链接函数。
  • 多重共线性:在特征间存在高度相关性时,可能导致回归系数不稳定。可以通过主成分分析(PCA)或其他降维技术来缓解。
  • 异常值:对模型有较大影响的异常值需要特别处理,如使用鲁棒回归方法。
  • 数据不平衡:逻辑回归和其他GLM在处理数据不平衡问题时可能表现不佳,考虑使用加权损失函数或其他处理技术。

适用问题类型:逻辑回归适用于二分类问题;而GLM可以应用于多分类、有序分类和回归问题。
模型假设:逻辑回归假设因变量服从二项分布;而GLM的假设更为灵活,可以根据具体问题选择不同的分布形式。

IRLS 优势
收敛速度:IRLS通常在少数几次迭代后就能快速收敛,特别适用于样本量较大时。它在许多实际问题中表现出良好的收敛性。

简单易行:IRLS的实现相对简单,基于最小二乘法的迭代加权更新,易于理解和实现。

鲁棒性:IRLS在处理某些类型的响应变量(如二项分布、泊松分布等)时表现良好,特别适用于这些分布的特定性质。

广泛适用性:IRLS不仅适用于广义线性回归模型,也可以用于其他一些需要迭代加权的统计模型。

隐语的GLM是基于秘密共享mpc协议实现的,计算的算子基本都可以化简为加法和乘法,因此列举了这两类算子的秘密贡献计算逻辑,加法比较容易理解,乘法需要借助beaver三元组辅助实现。

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
 
from functools import partial
from sklearn.datasets import fetch_openml
from sklearn.metrics import (
    mean_absolute_error,
    mean_squared_error,
    mean_tweedie_deviance,
)
 
 
def load_mtpl2(n_samples=None):
    """获取法国机动车第三方责任保险索赔数据集。
    参数
    ----------
    n_samples: int, 默认值=None
      要选择的样本数量(为了更快的运行时间)。完整数据集有 678013 个样本。
    """
    # 从 https://www.openml.org/d/41214 获取 freMTPL2freq 数据集
    df_freq = fetch_openml(data_id=41214, as_frame=True).data
    df_freq["IDpol"] = df_freq["IDpol"].astype(int)
    df_freq.set_index("IDpol", inplace=True)
 
    # 从 https://www.openml.org/d/41215 获取 freMTPL2sev 数据集
    df_sev = fetch_openml(data_id=41215, as_frame=True).data
 
    # 按照相同的 ID 累计索赔金额
    df_sev = df_sev.groupby("IDpol").sum()
 
    df = df_freq.join(df_sev, how="left")
    df["ClaimAmount"].fillna(0, inplace=True)
 
    # 去掉字符串字段的引号
    for column_name in df.columns[df.dtypes.values == object]:
        df[column_name] = df[column_name].str.strip("'")
    return df.iloc[:n_samples]
 
 
def plot_obs_pred(
    df,
    feature,
    weight,
    observed,
    predicted,
    y_label=None,
    title=None,
    ax=None,
    fill_legend=False,
):
    """绘制观察值和预测值 - 按特征级别聚合。
    参数
    ----------
    df : DataFrame
        输入数据
    feature: str
        要绘制的特征列名
    weight : str
        df 中权重或曝光量的列名
    observed : str
        df 中观察目标的列名
    predicted : DataFrame
        具有与 df 相同索引的预测目标数据框
    fill_legend : bool, 默认值=False
        是否显示填充区域的图例
    """
    # 按特征级别聚合观察变量和预测变量
    df_ = df.loc[:, [feature, weight]].copy()
    df_["observed"] = df[observed] * df[weight]
    df_["predicted"] = predicted * df[weight]
    df_ = (
        df_.groupby([feature])[[weight, "observed", "predicted"]]
        .sum()
        .assign(observed=lambda x: x["observed"] / x[weight])
        .assign(predicted=lambda x: x["predicted"] / x[weight])
    )
 
    ax = df_.loc[:, ["observed", "predicted"]].plot(style=".", ax=ax)
    y_max = df_.loc[:, ["observed", "predicted"]].values.max() * 0.8
    p2 = ax.fill_between(
        df_.index,
        0,
        y_max * df_[weight] / df_[weight].values.max(),
        color="g",
        alpha=0.1,
    )
    if fill_legend:
        ax.legend([p2], ["{} distribution".format(feature)])
    ax.set(
        ylabel=y_label if y_label is not None else None,
        title=title if title is not None else "Train: Observed vs Predicted",
    )
 
 
def score_estimator(
    estimator,
    X_train,
    X_test,
    df_train,
    df_test,
    target,
    weights,
    tweedie_powers=None,
):
    """使用不同的指标评估估计器在训练集和测试集上的表现"""
 
    metrics = [
        ("D² explained", None),  # 如果存在,使用默认评分器
        ("mean abs. error", mean_absolute_error),
        ("mean squared error", mean_squared_error),
    ]
    if tweedie_powers:
        metrics += [
            (
                "mean Tweedie dev p={:.4f}".format(power),
                partial(mean_tweedie_deviance, power=power),
            )
            for power in tweedie_powers
        ]
 
    res = []
    for subset_label, X, df in [
        ("train", X_train, df_train),
        ("test", X_test, df_test),
    ]:
        y, _weights = df[target], df[weights]
        for score_label, metric in metrics:
            if isinstance(estimator, tuple) and len(estimator) == 2:
                # 对由频率模型和严重性模型乘积组成的模型进行评分
                est_freq, est_sev = estimator
                y_pred = est_freq.predict(X) * est_sev.predict(X)
            else:
                y_pred = estimator.predict(X)
 
            if metric is None:
                if not hasattr(estimator, "score"):
                    continue
                score = estimator.score(X, y, sample_weight=_weights)
            else:
                score = metric(y, y_pred, sample_weight=_weights)
 
            res.append({"subset": subset_label, "metric": score_label, "score": score})
 
    res = (
        pd.DataFrame(res)
        .set_index(["metric", "subset"])
        .score.unstack(-1)
        .round(4)
        .loc[:, ["train", "test"]]
    )
    return res

除了IRLS,拟牛顿法(Quasi-Newton Methods)也是经常被使用的二阶优化器。L-BFGS(Limited-memory BFGS):适用于大规模问题的BFGS变种,利用有限内存近似海森矩阵

计算效率:对于大规模数据集,逻辑回归通常更快,因为它的计算过程相对简单;而GLM可能需要更多的计算资源和时间来拟合模型。
解释性:逻辑回归的输出可以直接解释为概率,因此更容易解释;而GLM的输出解释可能需要更多的专业知识或统计技巧。
综上所述,逻辑回归和广义线性模型都是强大的对数线性模型工具。在选择使用哪一个时,我们需要考虑问题的类型、数据的特性以及计算资源的限制等因素。在实践中,我们可以根据具体的需求和限制来选择最合适的模型。例如,对于二分类问题,如果数据的分布符合二项分布的假设并且计算资源有限,逻辑回归可能是一个更好的选择。而对于多分类或有序分类问题,或者当因变量的分布不符合任何预先设定的形式时,广义线性模型可能更加合适。

此外,对于需要同时处理分类和回归问题的情况,我们可以考虑使用一种称为“广义线性混合模型”的方法。这种方法结合了GLM的灵活性和混合模型的强大功能,允许我们在同一框架内处理各种类型的数据和问题。这将是我们在未来深入研究的一个重要方向。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值