(一)逻辑回归算法的概念和核心思想
(1.1)逻辑回归算法概念
- 逻辑回归是一种用于解决分类问题的统计学习方法,尽管名称中带有“回归”,但其本质是分类模型,它通过构建特征与类别之间的概率映射关系,实现对样本所属类别的预测,适用于线性可分的二分类问题
(1.2)逻辑回归算法核心思想
- 核心思想是通过sigmoid函数将线性回归的输出映射到概率空间(0到1之间),从而判断样本属于某个类别的可能性
(二)逻辑回归算法流程
逻辑回归本质是二分类概率建模,通过以下步骤实现:
- 线性组合:将输入特征加权求和 → 得到「对数几率」
- Sigmoid变换:将对数几率映射到 [0,1] 区间 → 输出正类概率
- 损失函数:定义预测误差 → 采用交叉熵损失
- 参数优化:用梯度下降法最小化损失 → 更新权重和偏置
- 预测决策:根据概率阈值划分类别
(2.1) 数据准备与预处理
目标:将原始数据转化为适合模型输入的格式
核心目的:让所有特征在模型中具有同等重要性,提升算法性能和稳定性
- 特征工程:
- 数值型特征:标准化/归一化(如Z-score)→ 消除量纲差异
- 类别型特征:独热编码(One-Hot Encoding)→ 转换为数值向量
- 数据分割:
- 训练集(Training Set)
- 测试集(Test Set)
- 验证集(Validation Set)
示例数据格式:
(2.2)模型构建:线性组合 → 对数几率
目标:建立特征与类别间的线性关系
公式:
(2.3)Sigmoid 变换 → 概率输出
目标:将任意实数压缩到 [0,1] 区间
公式:
函数性质:
概率解释:
(2.4)损失函数:交叉熵损失
目标:衡量预测概率与真实标签的差异
公式:
关键性质:
真实标签 y=1 → 预测概率越接近1 → 损失越小
真实标签 y=0 → 预测概率越接近0 → 损失越小
(2.5) 参数优化:梯度下降法
目标:找到使损失最小的参数
公式:
损失曲面 → 寻找最低点
梯度下降 → 沿着最陡下降方向更新参数
学习率 → 控制每次更新的步长
(2.6)预测与决策
步骤:
预测概率 → 阈值比较 → 类别输出
↓ ↓
≥0.5 <0.5
↓ ↓
正类 负类
(三)具体案例
(3.1)案例内容
(3.2)任务目标:
利用人工智能模型逻辑回归算法, 实现寝室的分配,将相同类型的分配在同一个寝室,爱学习的在一起,一般般在一起,爱玩在一起
历史数据:从大三、大四的学长得到历史数据,通过调查问卷来调查学生的特征,由负责的辅导员来决定学生的结果
学生玩游戏的时间、看书的时间、旅游的路程
逻辑回归算法实现模型LogisticRegression(C=0.01)
新的数据(大一的学生,提前预判学生是1、2、3)
(3.3)代码实现:
# ========== 1. 数据读取模块 ==========
import numpy as np
data = np.loadtxt('datingTestSet2(2).txt') # 从文本文件一次性读入二维数组:行=样本,列=特征+标签
# ========== 2. 特征/标签分离模块 ==========
X = data[:, :-1] # 特征矩阵:取所有行、除最后一列外的全部列
y = data[:, -1] # 标签向量:取所有行的最后一列(类别:1,2,3...)
# ========== 3. 训练-测试集划分模块 ==========
from sklearn.model_selection import train_test_split
x_train_w, x_test_w, y_train_w, y_test_w = train_test_split(
X, y, # 待划分的特征与标签
test_size=0.3, # 30% 做测试集,70% 做训练集
random_state=1000) # 随机种子固定,保证每次运行结果一致
# ========== 4. 模型构建与训练模块 ==========
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression(C=0.01) # 建立逻辑回归模型(C 越小正则越强)
lr.fit(x_train_w, y_train_w) # 用训练集拟合模型参数
# ========== 5. 预测与评估模块 ==========
test_predicted = lr.predict(x_test_w) # 对测试集样本进行类别预测
result = lr.score(x_test_w, y_test_w) # 计算并返回测试集整体准确率
(3.4)代码详细解析:
(3.4.1)数据读取模块
data = np.loadtxt('datingTestSet2(2).txt') # 行=样本,列=特征+标签
作用:将文本文件中的数据加载为NumPy二维数组
- 数据已清洗且无缺失值,每行是一个样本,最后一列为类别标签
- 数据结构示例如下:
[特征1, 特征2, ..., 特征N, 标签] [x₁₁, x₁₂, ..., x₁ₙ, y₁] ← 第1个样本 [x₂₁, x₂₂, ..., x₂ₙ, y₂] ← 第2个样本 ...
(3.4.2)特征/标签分离模块
X = data[:, :-1] # 所有行、除最后一列外的所有列 → 特征矩阵
y = data[:, -1] # 所有行的最后一列 → 标签向量
作用:将原始数据拆分为特征矩阵 X 和标签向量 y
- X 的形状为 [n_samples, n_features],每一行是一个样本的特征向量
- y 的形状为 [n_samples],存储每个样本的真实类别标签(如1, 2, 3...)
[n_samples, n_features] 是一种常见的数据形状表示法,用于描述二维数组(如 NumPy 数组或 Pandas DataFrame)的结构
n_samples: 样本数量(Number of samples)
- 表示数据集中独立观测值的数量(即多少条数据记录)
- 对应维度:数组的第一个维度(行数)
- 示例:如果有 100 个客户的购买记录,则 n_samples = 100
n_features: 特征数量(Number of features)
- 表示每个样本的属性个数(即每条记录包含多少种测量指标)
- 对应维度:数组的第二个维度(列数)
- 示例:若每个客户记录了年龄、收入、消费金额共 3 个属性,则 n_features = 3
(3.4.3) 训练-测试集划分模块
x_train_w, x_test_w, y_train_w, y_test_w = train_test_split(
X, y, test_size=0.3, random_state=1000)
作用:将数据集划分为训练集(70%)和测试集(30%)
- test_size=0.3:30%的数据用于测试,70%用于训练
- random_state=1000:固定随机种子,确保每次划分结果一致(可复现性)
(3.4.4) 模型构建与训练模块
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression(C=0.01) # 建立逻辑回归模型
lr.fit(x_train_w, y_train_w) # 用训练集拟合模型参数
作用:初始化逻辑回归模型并基于训练数据拟合参数。
模型定义:
- LogisticRegression 是Scikit-Learn封装的逻辑回归类,底层通过最小化交叉熵损失函数 + L2正则项来优化参数
- C=0.01:正则化强度(L2惩罚系数),C越小,正则化越强,模型越倾向于欠拟合(适用于高噪声数据)
- 公式:损失函数 = 交叉熵损失 + α||β||²,其中α=1/C
参数优化:
- 默认使用坐标下降法(Coordinate Descent)求解带L2正则化的逻辑回归问题
- 优化目标:找到最优权重向量 β,使得预测概率与真实标签的交叉熵损失最小
(3.4.5)预测与评估模块
test_predicted = lr.predict(x_test_w) # 对测试集样本进行类别预测
result = lr.score(x_test_w, y_test_w) # 计算测试集准确率
作用:对测试集进行预测并计算模型性能
关键步骤:
- 对每个测试样本 x,计算线性组合 z = βᵀx,并通过Sigmoid函数转换为概率 p(y=1|x)
- 根据阈值(默认0.5)将概率映射为类别标签(≥0.5 → 正类,否则负类)
- 多分类场景下,选择概率最大的类别作为预测结果
(3.5)运行结果:
(3.6)datingTestSet2(2).txt文件:
(四)具体案例
利用信用卡交易数据,训练一个逻辑回归模型来检测欺诈交易(二分类问题:正常 vs 欺诈)
(4.1)代码示例:
# ========== 1. 数据读取模块 ==========
import pandas as pd
data = pd.read_csv(r"./creditcard.csv") # 读取信用卡交易数据
print(data.head()) # 查看前 5 行,快速了解数据格式
# ========== 2. 数据预处理模块 ==========
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler() # 创建 Z-score 标准化器
data['Amount'] = scaler.fit_transform(data[['Amount']]) # 把 Amount 列标准化为均值 0、方差 1
data = data.drop(['Time'], axis=1) # 删除 Time 列(与欺诈检测关系不大)
# ========== 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 = pd.value_counts(data['Class']) # 统计正负样本数量
print(labels_count) # 输出类别分布(0: 正常,1: 欺诈)
plt.title("正负例样本数")
plt.xlabel("类别")
plt.ylabel("频数")
labels_count.plot(kind='bar') # 画柱状图
plt.show() # 直观查看样本极度不平衡
# ========== 4. 特征/标签分离模块 ==========
X_whole = data.drop('Class', axis=1) # 去掉标签列,剩余所有列作为特征
y_whole = data.Class # 单独取出标签列(0 或 1)
# ========== 5. 训练-测试集划分模块 ==========
from sklearn.model_selection import train_test_split
x_train_w, x_test_w, y_train_w, y_test_w = train_test_split(
X_whole, y_whole,
test_size=0.3, # 30% 做测试集
random_state=1000) # 固定随机种子,结果可复现
# ========== 6. 模型构建与训练模块 ==========
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression(C=0.01) # 建立逻辑回归模型(C 越小正则越强)
lr.fit(x_train_w, y_train_w) # 用训练集拟合参数
# ========== 7. 预测与评估模块 ==========
test_predicted = lr.predict(x_test_w) # 对测试集进行类别预测
result = lr.score(x_test_w, y_test_w) # 计算整体准确率
from sklearn import metrics
print(metrics.classification_report(y_test_w, test_predicted))
# 打印精确率、召回率、F1-score 等详细指标,衡量模型在正负样本上的表现
(4.2)creditcard.csv文件展示:
(4.3)运行结果:
(五)备注
(5.1)消除量纲差异
- 量纲指数据的物理单位或取值范围(如“米”“千克”“元”)
- 消除量纲差异是通过数学变换使不同特征的数值范围趋于一致,避免因量纲不同导致某些特征主导模型训练
- 核心目的:让所有特征在模型中具有同等重要性,提升算法性能和稳定性
场景1:未消除量纲的后果
假设我们有一个二分类问题,包含两个特征:
- 年龄(范围:20~60岁)
- 收入(范围:3000~10000元)
数据示例:
问题:
- 收入的数值(3000~10000)远大于年龄(20~60),模型会认为收入的重要性远高于年龄。
- 即使年龄对分类有帮助,也可能被收入掩盖
场景2:消除量纲的方法
常用方法有两种:
- 标准化(Z-score):将特征转换为均值为0、标准差为1的分布
公式:x' = (x - μ) / σ
- 归一化(Min-Max缩放):将特征压缩到[0,1]区间
公式:x' = (x - min) / (max - min)
以标准化为例处理上述数据:
- 年龄:均值 μ=35,标准差 σ≈15 → 标准化后范围约 [-1, 1.33]
- 收入:均值 μ=6500,标准差 σ≈2500 → 标准化后范围约 [-1.4, 1.2]
处理后的数据:
效果:
• 年龄和收入的数值范围均接近 [-1.5, 1.5],两者对模型的影响均衡
• 模型能同时学习到年龄和收入的特征,而非仅依赖收入