学习日记 7.28
在机器学习的学习之路上,线性回归和逻辑回归是两块重要的基石。今天我们将通过两个实战案例,从理论到代码,全面掌握这两种算法的应用:
案例一:多元线性回归—— 根据体重和年龄预测血压收缩压;案例二:逻辑回归—— 信用卡欺诈交易检测(Kaggle 经典数据集)。
一、多元线性回归
1.1 什么是多元线性回归?
简单线性回归使用一个自变量来预测因变量,而多元线性回归则使用两个或以上的自变量。其数学表达式为:
y = β₀ + β₁x₁ + β₂x₂ + ... + βₙxₙ + ε其中:
y是目标变量(因变量),x₁, x₂, ..., xₙ是特征(自变量),β₀是截距,β₁, β₂, ..., βₙ是回归系数,ε是误差项。
1.2 实战:血压预测
数据集
我们使用的数据集包含三个字段:体重、年龄、血压收缩,共 14 条记录。
| 体重(kg) | 年龄(岁) | 血压收缩(mmHg) |
|---|---|---|
| 76.0 | 50 | 120 |
| 91.5 | 20 | 141 |
| 85.5 | 20 | 124 |
| 82.5 | 30 | 126 |
| 79.0 | 30 | 117 |
| ... | ... | ... |
完整代码
import pandas as pd from sklearn.linear_model import LinearRegression 1. 读取数据 data = pd.read_csv("多元线性回归.csv", encoding="gbk", engine="python") 2. 查看相关性 —— 了解各特征与目标变量之间的关系 corr = data[["体重", "年龄", "血压收缩"]].corr() print("====== 相关性矩阵 ======") print(corr) 3. 创建模型 lr_model = LinearRegression() 4. 准备特征和目标变量 x = data[['体重', '年龄']] # 特征矩阵 y = data['血压收缩'] # 目标变量 5. 训练模型 lr_model.fit(x, y) 6. 模型评估 —— R² 分数 score = lr_model.score(x, y) print(f"\n模型 R² 分数: {score}") 7. 查看模型参数 print(f"\n回归系数: {lr_model.coef_}") print(f"截距: {lr_model.intercept_:.2f}")运行结果
====== 相关性矩阵 ====== 体重 年龄 血压收缩 体重 1.000000 -0.700283 0.906402 年龄 -0.700283 1.000000 -0.382773 血压收缩 0.906402 -0.382773 1.000000 模型 R² 分数: 0.9461441227520285结果深度解读
1. 相关性矩阵分析
体重 年龄 血压收缩 体重 1.000000 -0.700283 0.906402 年龄 -0.700283 1.000000 -0.382773 血压收缩 0.906402 -0.382773 1.000000从相关性矩阵中可以得出以下结论:
| 关系 | 相关系数 | 解读 |
|---|---|---|
| 体重 ↔ 血压收缩 | 0.906 | 强正相关—— 体重越大,收缩压越高。这是影响血压的最主要因素 |
| 年龄 ↔ 血压收缩 | -0.383 | 弱负相关—— 在这组数据中,年龄与血压呈现轻微负相关 |
| 体重 ↔ 年龄 | -0.700 | 中等负相关—— 数据中体重和年龄存在一定的负相关关系 |
关键发现:体重的相关系数高达 0.906,说明体重是影响收缩压的核心因素。而年龄在本数据集中与收缩压呈弱负相关(-0.383),这可能与样本特性有关。
2. R² 分数分析
模型 R² 分数为0.9461,这意味着:
模型能够解释94.61%的血压收缩压变化。拟合效果非常好,说明体重和年龄这两个特征对血压有很强的解释力。不过需要注意:这里 R² 是在训练集上计算的,没有做训练集/测试集划分(14 条数据太少)。在实际项目中,应该划分数据集并用测试集来评估,避免过拟合。
二、逻辑回归 —— 信用卡欺诈检测
2.1 什么是逻辑回归?
尽管名字里有"回归",但逻辑回归是一种分类算法。它通过 Sigmoid 函数将线性回归的输出映射到 [0, 1] 区间,从而得到属于某个类别的概率:
P(y=1|x) = 1 / (1 + e^-(β₀ + β₁x₁ + ... + βₙxₙ))对于二分类问题,通常设定阈值为 0.5:
概率 ≥ 0.5 → 正类(1,欺诈交易);概率 < 0.5 → 负类(0,正常交易)。
2.2 数据集介绍
本案例使用的是Kaggle 信用卡欺诈检测数据集,包含约 28.5 万条交易记录。
| 字段 | 说明 |
|---|---|
| Time | 交易时间(秒) |
| V1 ~ V28 | PCA 降维后的特征(脱敏处理) |
| Amount | 交易金额 |
| Class | 标签:0 = 正常交易,1 = 欺诈交易 |
2.3 完整代码详解
Step 1:读取数据并查看基本信息
import pandas as pd data = pd.read_csv(r"./creditcard.csv") print(data.head())输出结果(前 5 行):
Time V1 V2 V3 V4 V5 ... V27 V28 Amount Class 0 0.0 -1.359807 -0.072781 2.536347 1.378155 -0.338321 ... 0.133558 -0.021053 149.62 0 1 0.0 1.191857 0.266151 0.166480 0.448154 0.060018 ... -0.008983 0.014724 2.69 0 2 1.0 -1.358354 -1.340163 1.773209 0.379780 -0.503198 ... -0.055353 -0.059752 378.66 0 3 1.0 -0.966272 -0.185226 1.792993 -0.863291 -0.010309 ... 0.062723 0.061458 123.50 0 4 2.0 -1.158233 0.877737 1.548718 0.403034 -0.407193 ... 0.219422 0.215153 69.99 0 [5 rows x 31 columns]数据共有 31 列,包含 28 个 PCA 特征(V1~V28)、Time、Amount 和 Class 标签。可以看到 Amount 列的数值(149.62, 2.69, 378.66...)差异很大,后面需要进行标准化处理。
Step 2:数据预处理 —— Z-score 标准化
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() data['Amount'] = scaler.fit_transform(data[['Amount']]) data = data.drop(['Time'], axis=1)为什么要对 Amount 做标准化?
Amount列的数值范围(0 ~ 25691)远大于 V1~V28(经过 PCA 后基本在 [-5, 5] 范围内)。如果不进行标准化,模型会错误地认为 Amount 比其他特征重要得多,从而影响模型效果。
Z-score 标准化公式:
zᵢⱼ = (xᵢⱼ - x̄ᵢ) / sᵢx̄ᵢ:该特征的均值(数学期望);sᵢ:该特征的标准差;标准化后数据均值为 0,标准差为 1。
这里我们把Time列删除了 —— 交易发生的绝对时间与欺诈行为之间通常没有直接的线性关系,保留它反而可能引入噪声。
Step 3:数据可视化 —— 查看正负样本分布
import matplotlib.pyplot as plt from pylab import mpl 解决中文显示问题 mpl.rcParams['font.sans-serif'] = ['Microsoft YaHei'] mpl.rcParams['axes.unicode_minus'] = False 统计类别数量并绘图 labels_count = data['Class'].value_counts() print(labels_count) plt.title("正负样本分布") plt.xlabel("类别") plt.ylabel("频数") labels_count.plot(kind='bar') plt.show()输出结果:
Class 0 284315 1 492 Name: count, dtype: int64这个结果非常震撼:
| 类别 | 数量 | 占比 |
|---|---|---|
| 正常交易(0) | 284,315 | 99.83% |
| 欺诈交易(1) | 492 | 0.17% |
关键发现:正常交易和欺诈交易的比例约为578:1!这意味着每 579 笔交易中才可能出现 1 笔欺诈交易 —— 这是一个极度不平衡的数据集。
Step 4:划分训练集和测试集
from sklearn.model_selection import train_test_split X_model = data.drop(['Class'], axis=1) # 特征矩阵(29列) y_model = data.Class # 标签列 X_train_w, X_test_w, y_train_w, y_test_w = train_test_split( X_model, y_model, test_size=0.3, # 30% 作为测试集 random_state=1000 # 随机种子,保证结果可复现 )train_test_split 参数说明:
| 参数 | 含义 |
|---|---|
test_size=0.3 | 30% 的数据划分为测试集,70% 为训练集 |
random_state=1000 | 固定随机种子,确保每次运行得到相同的划分结果 |
Step 5:训练逻辑回归模型
from sklearn.linear_model import LogisticRegression C 是正则化强度的倒数:C 越小,正则化越强,模型越简单 lr = LogisticRegression(C=0.01) lr.fit(X_train_w, y_train_w)关于参数 C 的深入理解:
C是正则化强度的倒数。C = 0.01:正则化非常强 → 防止模型过拟合。逻辑回归默认使用L2 正则化(岭回归)。这里选较小的 C 值,是因为数据极度不平衡,需要用强正则化来约束模型。
Step 6:模型评估
test_predicted = lr.predict(X_test_w) # 对测试集进行预测 result = lr.score(X_test_w, y_test_w) # 计算准确率 print(f"模型准确率: {result}")输出结果:
模型准确率: 0.9990168884519505运行结果深度解读
准确率高达99.90%,这看起来非常优秀!但这里有一个重要陷阱:
准确率 = 99.90% 并不意味着模型真的很好!
还记得我们之前统计的类别分布吗?欺诈交易只占 0.17%。如果我们写一个"傻瓜模型"——把所有交易都预测为正常交易:
# 傻瓜策略:全部预测为 0 dummy_accuracy = (y_test_w == 0).sum() / len(y_test_w) print(f"全部预测为正常的准确率: {dummy_accuracy}") # 输出约: 0.9983 (99.83%)这个"什么都不做"的策略也能达到99.83%的准确率!所以:
核心结论:在不平衡数据集中,准确率(Accuracy)不是一个可靠的评估指标。我们需要关注的是:
精确率(Precision):被预测为欺诈的交易中,有多少是真正的欺诈?召回率(Recall):真正的欺诈交易中,有多少被模型检测出来了?F1 分数:精确率和召回率的调和平均。AUC-ROC:模型区分正负样本的能力。
三、线性回归 vs 逻辑回归:对比总结
| 对比维度 | 线性回归 | 逻辑回归 |
|---|---|---|
| 任务类型 | 回归(预测连续值) | 分类(预测离散类别) |
| 输出范围 | (-∞, +∞) | [0, 1](概率值) |
| 损失函数 | 均方误差(MSE) | 交叉熵损失(Log Loss) |
| 激活函数 | 无(线性输出) | Sigmoid 函数 |
| 评估指标 | R², MAE, MSE, RMSE | 精确率、召回率、F1、AUC-ROC |
| 典型应用 | 房价预测、气温预测 | 垃圾邮件检测、欺诈检测、疾病诊断 |
四、实战经验总结
4.1 两个案例的对比启示
| 维度 | 案例一(线性回归) | 案例二(逻辑回归) |
|---|---|---|
| 数据量 | 14 条(小样本) | 28.5 万条(大数据) |
| 特征数 | 2 个 | 29 个 |
| 核心挑战 | 样本太少,容易过拟合 | 样本极度不平衡 |
| R²/准确率 | 0.9461(优秀) | 0.9990(看似优秀,实则存疑) |
| 可信度 | 需更多数据验证 | 不能只看准确率 |
4.2 关键
R² = 0.9461 说明什么?体重和年龄共同解释了 94.61% 的血压变异。但 14 条数据太少,模型可能过拟合,需要更多样本验证。准确率 = 99.90% 说明什么?单独看:模型表现极好。结合类别分布看:几乎所有样本都是负类,"全部预测为 0"也有 99.83%。真相:模型的提升仅为 0.07%,这点提升来自正确识别了极少数的欺诈交易。数据预处理的重要性:Amount 标准化消除量纲差异,避免大数值特征主导模型;Time 删除去除与目标变量无关的特征,减少噪声;相关性分析中体重与血压的相关性(0.906)远超年龄(-0.383)。
五、进阶建议
针对信用卡欺诈检测案例,可以从以下方向继续优化:
处理样本不平衡:设置class_weight='balanced'让模型自动按类别频率调整权重;或用 SMOTE 过采样(random_state=42固定随机种子,保证结果可复现)。
更全面的模型评估:不平衡数据中准确率不可靠,应关注精确率、召回率、F1 和 AUC,用classification_report和roc_auc_score全面评估。
