文章目录
- 一、逻辑回归:从线性回归到二分类的跨越
- 1.1 逻辑回归简介
- 1.2 Sigmoid函数:概率映射的数学本质
- 1.3 参数 w w w 和 b b b 对Sigmoid的调控
- 1.4 从线性回归到分类
- 1.5 决策边界:从概率到类别(结合图3、图4)
- 二、似然函数与交叉熵损失:从概率建模到参数优化的数学桥梁
- 2.1 似然函数:基于伯努利分布的联合概率建模
- 2.2 对数似然:从连乘到连加的数学变换
- 2.3 交叉熵损失:从最大化到最小化的目标转换
- 2.4 等价性证明:最大化似然 ≡ 最小化交叉熵
- 三、sklearn 实现逻辑回归:从 API 到实战应用
- 3.1 sklearn逻辑回归API详解
- 3.2 模型训练与预测流程
- 3.3程序代码
一、逻辑回归:从线性回归到二分类的跨越
1.1 逻辑回归简介
逻辑回归(Logistic Regression)是机器学习中解决二分类问题的经典算法,尽管名称中包含"回归",但它本质上是一种分类方法。其核心思想是通过将线性回归的输出映射到(0,1)概率区间,从而实现分类预测。具体来说:
- 利用线性模型 f ( x ) = w T x + b f(x) = w^T x + b f(x)=wTx+b 计算特征的线性组合
- 通过Sigmoid函数将线性输出转换为概率值 P ( y = 1 ∣ x ) P(y=1|x) P(y=1∣x)
- 设置概率阈值(如0.5)将概率转换为类别标签
逻辑回归广泛应用于医学诊断、金融风控、广告点击率预估等场景,其优势在于模型简单、可解释性强,且在小规模数据上表现优异。
-
f ( x ) = w T x + b f(x) = w^T x + b f(x)=wTx+b 的数学推导
线性模型 f ( x ) = w T x + b f(x) = w^T x + b f(x)=wTx+b 的推导源于概率论中的伯努利分布和对数几率变换:
-
什么是伯努利分布?
伯努利分布是描述二元随机变量(只有两种可能结果)的最基本概率分布。在二分类问题中,样本标签 y ∈ { 0 , 1 } y \in \{0,1\} y∈{0,1} 正好满足:- 结果互斥:每个样本只能属于一个类别
- 概率完备: P ( y = 1 ) + P ( y = 0 ) = 1 P(y=1) + P(y=0) = 1 P(y=1)+P(y=0)=1
- 形式简洁:单参数 p p p 完全定义整个分布
与经典概率分布(如正态分布)相比,伯努利分布:
- 直接建模离散的二分类结果
- 完美匹配分类问题的概率特性
- 数学形式简单且可解释性强
- 伯努利分布 vs 经典概率求法
-
经典概率求法(频率学派)
在传统概率计算中,我们通过统计事件发生的频率来估计概率:
p = 正类样本数 总样本数 p = \frac{\text{正类样本数}}{\text{总样本数}} p=总样本数正类样本数示例:
抛硬币10次,出现正面7次,则正面概率:
p = 7 10 = 0.7 p = \frac{7}{10} = 0.7 p=107=0.7 -
伯努利分布的本质
伯努利分布 P ( y ) = p y ( 1 − p ) 1 − y P(y) = p^y(1-p)^{1-y} P(y)=py(1−p)1−y 是经典概率的数学抽象:
- 当 y = 1 y=1 y=1 (正类): P ( 1 ) = p 1 ( 1 − p ) 0 = p P(1) = p^1(1-p)^0 = p P(1)=p1(1−p)0=p
- 当 y = 0 y=0 y=0 (负类): P ( 0 ) = p 0 ( 1 − p ) 1 = 1 − p P(0) = p^0(1-p)^1 = 1-p P(0)=p0(1−p)1=1−p
-
关键联系:
经典概率 k n \frac{k}{n} nk 正是伯努利分布在 n n n 次独立试验中正类出现次数 k k k 的期望值:
E [ y ] = p = k n E[y] = p = \frac{k}{n} E[y]=p=nk -
对比分析
特性 | 经典概率求法 | 伯努利分布 |
---|---|---|
表达形式 | 统计比值 k n \frac{k}{n} nk | 参数化概率模型 p y ( 1 − p ) 1 − y p^y(1-p)^{1-y} py(1−p)1−y |
计算基础 | 依赖具体观测数据 | 基于概率参数 p p p |
预测能力 | 只能描述已观测数据 | 可预测未知样本概率 |
数学处理 | 难以建立特征-概率的映射 | 可连接特征与概率(如 p = σ ( w T x + b ) p=\sigma(w^Tx+b) p=σ(wTx+b)) |
- 实际应用示例
假设医学检测:
- 100人中20人阳性 → 经典概率: p = 20 / 100 = 0.2 p=20/100=0.2 p=20/100=0.2
- 伯努利分布建模:
- P ( y = 1 ) = 0.2 P(y=1)=0.2 P(y=1)=0.2
- P ( y = 0 ) = 0.8 P(y=0)=0.8 P(y=0)=0.8
- 对新患者 x x x,可通过 p = σ ( w T x + b ) p=\sigma(w^Tx+b) p=σ(wTx+b) 预测患病概率
核心优势:伯努利分布将离散的频率统计转化为连续的概率模型,为建立特征与概率的数学关系奠定了基础,这是经典概率比无法实现的。
-
继续 f ( x ) = w T x + b f(x) = w^T x + b f(x)=wTx+b 的数学推导
对于二分类问题, y y y 服从伯努利分布:
P ( y ∣ x ) = p y ( 1 − p ) 1 − y P(y|x) = p^y(1-p)^{1-y} P(y∣x)=py(1−p)1−y
其中 p = P ( y = 1 ∣ x ) p = P(y=1|x) p=P(y=1∣x) 是样本属于正类的概率。 -
对数几率变换
为建立 p p p 与特征 x x x 的关系,定义对数几率:
logit ( p ) = ln ( p 1 − p ) \text{logit}(p) = \ln \left( \frac{p}{1-p} \right) logit(p)=ln(1−pp)- 该变换将概率 p ∈ [ 0 , 1 ] p \in [0,1] p∈[0,1] 映射到实数域 ( − ∞ , + ∞ ) (-\infty, +\infty) (−∞,+∞)
-
关键假设
逻辑回归的核心假设是:对数几率与特征呈线性关系
ln ( p 1 − p ) = w T x + b \ln \left( \frac{p}{1-p} \right) = w^T x + b ln(1−pp)=wTx+b -
代数求解
通过代数变换求解 p p p:
p 1 − p = e w T x + b p = ( 1 − p ) e w T x + b p ( 1 + e w T x + b ) = e w T x + b p = e w T x + b 1 + e w T x + b = 1 1 + e − ( w T x + b ) \begin{align*} \frac{p}{1-p} &= e^{w^T x + b} \\ p &= (1-p)e^{w^T x + b} \\ p(1 + e^{w^T x + b}) &= e^{w^T x + b} \\ p &= \frac{e^{w^T x + b}}{1 + e^{w^T x + b}} \\ &= \frac{1}{1 + e^{-(w^T x + b)}} \end{align*} 1−pppp(1+ewTx+b)p=ewTx+b=(1−p)ewTx+b=ewTx+b=1+ewTx+bewTx+b=1+e−(wTx+b)1 -
最终形式
得到线性模型与Sigmoid函数的组合:
P ( y = 1 ∣ x ) = σ ( w T x + b ) = 1 1 + e − ( w T x + b ) P(y=1|x) = \sigma(w^T x + b) = \frac{1}{1 + e^{-(w^T x + b)}} P(y=1∣x)=σ(wTx+b)=1+e−(wTx+b)1
其中:- w w w:权重向量,表示各特征的重要性
- b b b:偏置项,表示决策边界的偏移
- w T x = ∑ i = 1 n w i x i w^T x = \sum_{i=1}^n w_i x_i wTx=∑i=1nwixi:特征线性组合
-
关键数学关系
概念 | 数学表达式 | 取值范围 | 解释 |
---|---|---|---|
原始概率 | $p = P(y=1 | x)$ | [ 0 , 1 ] [0, 1] [0,1] |
几率 | p 1 − p \frac{p}{1-p} 1−pp | [ 0 , + ∞ ) [0, +\infty) [0,+∞) | 正负类概率比 |
对数几率 | ln ( p 1 − p ) \ln\left(\frac{p}{1-p}\right) ln(1−pp) | ( − ∞ , + ∞ ) (-\infty, +\infty) (−∞,+∞) | 几率的自然对数 |
线性模型 | w T x + b w^T x + b wTx+b | ( − ∞ , + ∞ ) (-\infty, +\infty) (−∞,+∞) | 特征线性组合 |
1.2 Sigmoid函数:概率映射的数学本质
-
函数定义与几何意义
Sigmoid函数是逻辑回归的核心,其数学表达式为:
σ ( z ) = 1 1 + e − z \sigma(z) = \frac{1}{1 + e^{-z}} σ(z)=1+e−z1- 符号解析:
- z z z:线性组合结果(为 z = w T x + b z = w^T x + b z=wTx+b);
- e e e:自然对数底数(≈2.71828),负责将线性输出映射到指数空间。
图 1 图1 图1
从 Sigmoid函数曲线(图1) 可见:
- 当 z → + ∞ z \to +\infty z→+∞ 时, e − z → 0 e^{-z} \to 0 e−z→0, σ ( z ) → 1 \sigma(z) \to 1 σ(z)→1(正类概率趋近1);
- 当 z → − ∞ z \to -\infty z→−∞ 时, e − z → + ∞ e^{-z} \to +\infty e−z→+∞, σ ( z ) → 0 \sigma(z) \to 0 σ(z)→0(正类概率趋近0);
- 当 z = 0 z=0 z=0 时, σ ( z ) = 0.5 \sigma(z)=0.5 σ(z)=0.5,是二分类的天然决策阈值( σ ( z ) ≥ 0.5 \sigma(z) \geq 0.5 σ(z)≥0.5 预测为正类,反之为负类)。
- 符号解析:
1.3 参数 w w w 和 b b b 对Sigmoid的调控
图 2 图2 图2
-
权重 w w w 的影响
w w w 控制Sigmoid曲线的陡峭程度(对 z z z 变化的敏感程度):
- ∣ w ∣ |w| ∣w∣ 越大,曲线越陡峭(如 w = 5 w=5 w=5 时, z z z 微小变化即可让 σ ( z ) \sigma(z) σ(z) 从0跃升至1);
- ∣ w ∣ |w| ∣w∣ 越小,曲线越平缓(如 w = 0.5 w=0.5 w=0.5 时, z z z 需大幅变化才会改变 σ ( z ) \sigma(z) σ(z))。
-
偏置 b b b 的影响
b b b 控制Sigmoid曲线的左右平移(决策阈值的位置):
- b > 0 b>0 b>0 时,曲线左移(更小的 z z z 就能让 σ ( z ) = 0.5 \sigma(z)=0.5 σ(z)=0.5);
- b < 0 b<0 b<0 时,曲线右移(更大的 z z z 才能让 σ ( z ) = 0.5 \sigma(z)=0.5 σ(z)=0.5)。
-
权重符号的影响
w w w 的正负决定Sigmoid曲线的倾斜方向:
- w > 0 w>0 w>0 时, σ ( z ) \sigma(z) σ(z) 随 z z z 增大而递增(正相关);
- w < 0 w<0 w<0 时, σ ( z ) \sigma(z) σ(z) 随 z z z 增大而递减(负相关),需通过 b b b 调整决策逻辑。
1.4 从线性回归到分类
-
线性组合: z = w T x + b z = w^T x + b z=wTx+b
逻辑回归首先计算 线性组合 z z z,继承线性回归的形式:
z = w 1 x 1 + w 2 x 2 + ⋯ + w n x n + b z = w_1 x_1 + w_2 x_2 + \dots + w_n x_n + b z=w1x1+w2x2+⋯+wnxn+b- 符号解析:
- w = [ w 1 , w 2 , … , w n ] T w = [w_1, w_2, \dots, w_n]^T w=[w1,w2,…,wn]T:权重向量,每个 w i w_i wi 表示特征 x i x_i xi 的“重要性”;
- x = [ x 1 , x 2 , … , x n ] T x = [x_1, x_2, \dots, x_n]^T x=[x1,x2,…,xn]T:样本的特征向量( n n n 为特征维度);
- b b b:偏置项,代表“基准概率”(所有 x i = 0 x_i=0 xi=0 时的 z z z 值)。
- 符号解析:
图 3 图3 图3
-
概率映射: P ( y = 1 ∣ x ) = σ ( z ) P(y=1|x) = \sigma(z) P(y=1∣x)=σ(z)(结合图3)
通过Sigmoid函数,线性组合 z z z 被映射为 正类概率:
P ( y = 1 ∣ x ; w , b ) = σ ( w T x + b ) P(y=1|x; w, b) = \sigma(w^T x + b) P(y=1∣x;w,b)=σ(wTx+b)
负类概率为:
P ( y = 0 ∣ x ; w , b ) = 1 − σ ( w T x + b ) P(y=0|x; w, b) = 1 - \sigma(w^T x + b) P(y=0∣x;w,b)=1−σ(wTx+b)合并表达式(全概率公式):
P ( y ∣ x ; w , b ) = [ σ ( w T x + b ) ] y ⋅ [ 1 − σ ( w T x + b ) ] 1 − y P(y|x; w, b) = \left[\sigma(w^T x + b)\right]^y \cdot \left[1 - \sigma(w^T x + b)\right]^{1-y} P(y∣x;w,b)=[σ(wTx+b)]y⋅[1−σ(wTx+b)]1−y- 当 y = 1 y=1 y=1 时,公式退化为 σ ( w T x + b ) \sigma(w^T x + b) σ(wTx+b)(仅保留正类概率);
- 当 y = 0 y=0 y=0 时,公式退化为 1 − σ ( w T x + b ) 1 - \sigma(w^T x + b) 1−σ(wTx+b)(仅保留负类概率)。
图 3 图3 图3
图 4 图4 图4
1.5 决策边界:从概率到类别(结合图3、图4)
当 σ ( z ) ≥ 0.5 \sigma(z) \geq 0.5 σ(z)≥0.5 时,预测 y = 1 y=1 y=1;否则预测 y = 0 y=0 y=0。此时决策边界满足:
w T x + b = 0 w^T x + b = 0 wTx+b=0
- 一维特征(图3):决策边界是 x x x 的具体值(如 x = 0.67 x=0.67 x=0.67);
- 二维特征(图4):决策边界是直线(如 w 1 x 1 + w 2 x 2 + b = 0 w_1 x_1 + w_2 x_2 + b = 0 w1x1+w2x2+b=0);
- 高维特征:决策边界扩展为超平面,分割特征空间为两个区域。
绘图代码:
import numpy as np # 导入NumPy库,用于数值计算
import matplotlib.pyplot as plt # 导入Matplotlib绘图库
from matplotlib.colors import ListedColormap # 导入颜色映射工具
from mpl_toolkits.mplot3d import Axes3D # 导入3D绘图工具# 设置中文字体,确保图表能正确显示中文
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False # 定义Sigmoid函数,数学公式为σ(z) = 1/(1+e^(-z))
def sigmoid(z):return 1 / (1 + np.exp(-z))# 1. 绘制Sigmoid函数的基本曲线
def plot_sigmoid():z = np.linspace(-10, 10, 1000) # 生成-10到10之间的1000个等距点作为输入sigma_z = sigmoid(z) # 计算Sigmoid函数值plt.figure(figsize=(10, 6)) # 创建10x6英寸的画布plt.plot(z, sigma_z, linewidth=2.5) # 绘制Sigmoid曲线,线宽2.5plt.axhline(y=0.5, color='r', linestyle='--', alpha=0.5) # 添加y=0.5的红色虚线plt.axvline(x=0, color='gray', linestyle='--', alpha=0.5) # 添加x=0的灰色虚线plt.title('Sigmoid函数曲线', fontsize=15) # 设置标题plt.xlabel('z 值 (线性组合结果)', fontsize=12) # 设置x轴标签plt.ylabel('σ(z) 值 (概率值)', fontsize=12) # 设置y轴标签plt.grid(True, alpha=0.3) # 添加网格线,透明度0.3# 填充z≥0区域(蓝色)和z<0区域(红色),突出概率大于/小于0.5的部分plt.fill_between(z, sigma_z, 0.5, where=(z >= 0), color='lightblue', alpha=0.3)plt.fill_between(z, sigma_z, 0.5, where=(z < 0), color='lightcoral', alpha=0.3)# 添加文本注释,说明概率大于/小于0.5的区域plt.text(3, 0.85, 'σ(z) > 0.5', fontsize=12)plt.text(-3, 0.15, 'σ(z) < 0.5', fontsize=12)plt.tight_layout() # 自动调整布局plt.savefig('sigmoid_function.png', dpi=300) # 保存图片plt.show() # 显示图表# 2. 绘制不同参数对Sigmoid函数的影响对比
def plot_sigmoid_with_different_params():z = np.linspace(-10, 10, 1000) # 生成输入数据plt.figure(figsize=(12, 8)) # 创建12x8英寸的画布# 第一个子图:不同权重w对Sigmoid的影响plt.subplot(2, 2, 1)for w in [0.5, 1, 2, 5]: # 遍历不同的权重值plt.plot(z, sigmoid(w * z), label=f'w={w}') # 绘制不同w的曲线plt.title('不同权重 w 的影响', fontsize=13) # 设置标题plt.xlabel('z', fontsize=10) # 设置坐标轴标签plt.ylabel('σ(z)', fontsize=10)plt.legend() # 显示图例plt.grid(True, alpha=0.3) # 添加网格# 第二个子图:不同偏置b对Sigmoid的影响plt.subplot(2, 2, 2)for b in [-2, -1, 0, 1, 2]: # 遍历不同的偏置值plt.plot(z, sigmoid(z + b), label=f'b={b}') # 绘制不同b的曲线plt.title('不同偏置 b 的影响', fontsize=13)plt.xlabel('z', fontsize=10)plt.ylabel('σ(z)', fontsize=10)plt.legend()plt.grid(True, alpha=0.3)# 第三个子图:不同参数组合(w,b)的影响plt.subplot(2, 2, 3)params = [(1, 0), (2, 0), (1, -2), (2, 2)] # 参数组合列表for w, b in params: # 遍历参数组合plt.plot(z, sigmoid(w * z + b), label=f'w={w}, b={b}') # 绘制曲线plt.title('不同参数组合的影响', fontsize=13)plt.xlabel('z', fontsize=10)plt.ylabel('σ(z)', fontsize=10)plt.legend()plt.grid(True, alpha=0.3)# 第四个子图:权重符号对Sigmoid的影响plt.subplot(2, 2, 4)for w in [1, -1, 2, -2]: # 遍历正负权重plt.plot(z, sigmoid(w * z), label=f'w={w}') # 绘制曲线plt.title('权重符号的影响', fontsize=13)plt.xlabel('z', fontsize=10)plt.ylabel('σ(z)', fontsize=10)plt.legend()plt.grid(True, alpha=0.3)plt.tight_layout() # 调整布局plt.savefig('sigmoid_params_comparison.png', dpi=300) # 保存图片plt.show() # 显示图表# 3. 绘制逻辑回归从线性组合到概率映射的完整过程
def plot_logistic_probability_mapping():np.random.seed(42) # 设置随机种子,确保结果可复现x = np.linspace(-5, 5, 100) # 生成输入特征xw = 1.5 # 权重b = -1 # 偏置z = w * x + b # 线性组合z = wx + bprob = sigmoid(z) # 计算属于正类的概率# 根据概率生成分类标签(概率>0.5为正类1,否则为负类0)y = (prob > 0.5).astype(int)# 添加噪声模拟真实数据noise = np.random.normal(0, 0.2, 100) # 生成均值0、标准差0.2的噪声x_noise = x + noise # 带噪声的特征prob_noise = sigmoid(w * x_noise + b) # 带噪声的概率y_noise = (prob_noise > 0.5).astype(int) # 带噪声的标签plt.figure(figsize=(12, 10)) # 创建画布# 第一子图:线性回归结果z = wx + bplt.subplot(2, 2, 1)# 绘制带噪声的数据点,颜色根据标签区分plt.scatter(x_noise, z, c=y_noise, cmap=ListedColormap(['#FF9999', '#99CCFF']),edgecolors='k', alpha=0.7)plt.plot(x, z, 'r-', linewidth=2) # 绘制线性回归直线plt.axhline(y=0, color='gray', linestyle='--', alpha=0.5) # 添加y=0的虚线plt.title('线性回归结果 (z = wx + b)', fontsize=13)plt.xlabel('输入特征 x', fontsize=10)plt.ylabel('线性组合结果 z', fontsize=10)plt.grid(True, alpha=0.3)# 第二子图:Sigmoid函数映射过程plt.subplot(2, 2, 2)# 绘制z到概率的映射关系,点颜色根据标签区分plt.scatter(z, prob_noise, c=y_noise, cmap=ListedColormap(['#FF9999', '#99CCFF']),edgecolors='k', alpha=0.7)plt.plot(z, prob, 'g-', linewidth=2) # 绘制Sigmoid曲线plt.axhline(y=0.5, color='r', linestyle='--', alpha=0.5) # 添加y=0.5虚线plt.axvline(x=0, color='gray', linestyle='--', alpha=0.5) # 添加x=0虚线plt.title('Sigmoid函数映射', fontsize=13)plt.xlabel('线性组合结果 z', fontsize=10)plt.ylabel('概率值 P(y=1|x)', fontsize=10)plt.grid(True, alpha=0.3)# 第三子图:逻辑回归的最终分类结果plt.subplot(2, 2, 3)# 绘制特征x与预测概率的关系,点颜色根据标签区分plt.scatter(x_noise, y_noise, c=y_noise, cmap=ListedColormap(['#FF9999', '#99CCFF']),edgecolors='k', alpha=0.7, s=50)plt.plot(x, prob, 'g-', linewidth=2) # 绘制概率曲线plt.axhline(y=0.5, color='r', linestyle='--', alpha=0.5) # 添加决策阈值线plt.title('逻辑回归分类结果', fontsize=13)plt.xlabel('输入特征 x', fontsize=10)plt.ylabel('预测概率 P(y=1|x)', fontsize=10)plt.grid(True, alpha=0.3)# 第四子图:逻辑回归的决策边界plt.subplot(2, 2, 4)# 绘制特征x与标签y的关系,点颜色根据标签区分plt.scatter(x_noise, y_noise, c=y_noise, cmap=ListedColormap(['#FF9999', '#99CCFF']),edgecolors='k', alpha=0.7, s=50)plt.axhline(y=0.5, color='r', linestyle='--', alpha=0.5) # 添加概率阈值线decision_boundary = -b / w # 计算决策边界x值plt.axvline(x=decision_boundary, color='blue', linestyle='-', alpha=0.7) # 绘制决策边界# 填充决策边界两侧的区域,区分分类结果plt.fill_between(x, 0, 1, where=(x > decision_boundary), color='#99CCFF', alpha=0.2)plt.fill_between(x, 0, 1, where=(x <= decision_boundary), color='#FF9999', alpha=0.2)plt.title(f'决策边界 (x = {decision_boundary:.2f})', fontsize=13)plt.xlabel('输入特征 x', fontsize=10)plt.ylabel('类别标签 y', fontsize=10)plt.grid(True, alpha=0.3)plt.tight_layout() # 调整布局plt.savefig('logistic_regression_mapping.png', dpi=300) # 保存图片plt.show() # 显示图表# 4. 绘制二维特征空间中的逻辑回归决策面
def plot_3d_decision_boundary():np.random.seed(42) # 设置随机种子x1 = np.linspace(-5, 5, 50) # 生成特征x1x2 = np.linspace(-5, 5, 50) # 生成特征x2x1, x2 = np.meshgrid(x1, x2) # 生成二维网格点w1, w2, b = 1, 2, -3 # 设置权重和偏置# 计算线性组合z = w1x1 + w2x2 + b和对应的概率z = w1 * x1 + w2 * x2 + bprob = sigmoid(z)fig = plt.figure(figsize=(12, 10)) # 创建画布# 第一子图:3D决策面ax1 = fig.add_subplot(221, projection='3d') # 创建3D子图# 绘制3D曲面,颜色映射为viridis,透明度0.8surf = ax1.plot_surface(x1, x2, prob, cmap='viridis', alpha=0.8)# 在3D曲面上绘制z=0.5的等高线(决策边界)ax1.contour(x1, x2, prob, levels=[0.5], colors='r', linestyles='dashed', linewidths=2)ax1.set_title('逻辑回归决策面', fontsize=13) # 设置标题ax1.set_xlabel('特征 x1', fontsize=10) # 设置坐标轴标签ax1.set_ylabel('特征 x2', fontsize=10)ax1.set_zlabel('P(y=1|x1,x2)', fontsize=10)ax1.view_init(elev=30, azim=45) # 设置3D视图角度fig.colorbar(surf, ax=ax1, shrink=0.5, aspect=5) # 添加颜色条# 第二子图:决策边界等高线图ax2 = fig.add_subplot(222) # 创建子图# 绘制概率的填充等高线图,20个层级,颜色映射viridiscontour = ax2.contourf(x1, x2, prob, levels=20, cmap='viridis', alpha=0.8)# 绘制概率=0.5的等高线(决策边界)ax2.contour(x1, x2, prob, levels=[0.5], colors='r', linestyles='dashed', linewidths=2)ax2.set_title('决策边界等高线图', fontsize=13)ax2.set_xlabel('特征 x1', fontsize=10)ax2.set_ylabel('特征 x2', fontsize=10)fig.colorbar(contour, ax=ax2, shrink=0.5, aspect=5) # 添加颜色条# 生成随机样本点n_samples = 100 # 样本数量x1_samples = np.random.uniform(-5, 5, n_samples) # 随机生成x1x2_samples = np.random.uniform(-5, 5, n_samples) # 随机生成x2z_samples = w1 * x1_samples + w2 * x2_samples + b # 计算线性组合prob_samples = sigmoid(z_samples) # 计算概率y_samples = (prob_samples > 0.5).astype(int) # 生成标签# 第三子图:带样本点的决策边界ax3 = fig.add_subplot(223) # 创建子图# 绘制概率的填充等高线图contour = ax3.contourf(x1, x2, prob, levels=20, cmap='viridis', alpha=0.6)# 绘制决策边界ax3.contour(x1, x2, prob, levels=[0.5], colors='r', linestyles='dashed', linewidths=2)# 绘制样本点,颜色根据标签区分scatter = ax3.scatter(x1_samples, x2_samples, c=y_samples,cmap=ListedColormap(['#FF9999', '#99CCFF']),edgecolors='k', alpha=0.8, s=50)ax3.set_title('带样本点的决策边界', fontsize=13)ax3.set_xlabel('特征 x1', fontsize=10)ax3.set_ylabel('特征 x2', fontsize=10)# 添加类别图例legend1 = ax3.legend(*scatter.legend_elements(), title="类别")ax3.add_artist(legend1)fig.colorbar(contour, ax=ax3, shrink=0.5, aspect=5) # 添加颜色条# 第四子图:概率分布热图ax4 = fig.add_subplot(224) # 创建子图# 绘制概率热图,设置范围和颜色映射im = ax4.imshow(prob, extent=[-5, 5, -5, 5], origin='lower',cmap='viridis', aspect='auto')# 绘制决策边界ax4.contour(x1, x2, prob, levels=[0.5], colors='r', linestyles='dashed', linewidths=2)ax4.set_title('概率分布热图', fontsize=13)ax4.set_xlabel('特征 x1', fontsize=10)ax4.set_ylabel('特征 x2', fontsize=10)fig.colorbar(im, ax=ax4, shrink=0.5, aspect=5) # 添加颜色条plt.tight_layout() # 调整布局plt.savefig('3d_decision_boundary.png', dpi=300) # 保存图片plt.show() # 显示图表# 5. 绘制逻辑回归的对数损失函数
def plot_logistic_loss():# 定义对数损失函数def log_loss(y_true, y_pred):epsilon = 1e-15 # 防止对数计算中出现0或1,导致数值溢出y_pred = np.clip(y_pred, epsilon, 1 - epsilon) # 限制预测概率范围# 对数损失公式:- [y_true*log(y_pred) + (1-y_true)*log(1-y_pred)]return -(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))y_pred = np.linspace(0.01, 0.99, 100) # 生成0.01到0.99的100个预测概率值plt.figure(figsize=(10, 6)) # 创建画布# 绘制真实标签为1时的损失曲线plt.plot(y_pred, log_loss(1, y_pred), label='y=1 (正类)')# 绘制真实标签为0时的损失曲线plt.plot(y_pred, log_loss(0, y_pred), label='y=0 (负类)')plt.title('逻辑回归的对数损失函数', fontsize=15) # 设置标题plt.xlabel('预测概率 P(y=1|x)', fontsize=12) # 设置坐标轴标签plt.ylabel('损失值', fontsize=12)plt.grid(True, alpha=0.3) # 添加网格plt.legend(fontsize=12) # 显示图例# 添加注释,说明预测正确和错误时的损失情况plt.annotate('预测正确时损失小', xy=(0.95, log_loss(1, 0.95)), xytext=(0.7, 0.5),arrowprops=dict(facecolor='black', shrink=0.05, width=1.5, headwidth=8))plt.annotate('预测错误时损失大', xy=(0.05, log_loss(1, 0.05)), xytext=(0.3, 3),arrowprops=dict(facecolor='black', shrink=0.05, width=1.5, headwidth=8))plt.tight_layout() # 调整布局plt.savefig('logistic_loss_function.png', dpi=300) # 保存图片plt.show() # 显示图表# 主程序:依次调用所有绘图函数
if __name__ == "__main__":plot_sigmoid() # 绘制Sigmoid函数基本曲线plot_sigmoid_with_different_params() # 绘制不同参数的Sigmoid对比plot_logistic_probability_mapping() # 绘制逻辑回归概率映射plot_3d_decision_boundary() # 绘制二维特征的决策面plot_logistic_loss() # 绘制对数损失函数
二、似然函数与交叉熵损失:从概率建模到参数优化的数学桥梁
2.1 似然函数:基于伯努利分布的联合概率建模
过渡衔接:在通过伯努利分布与对数几率变换建立特征-概率映射后,如何求解最优参数 ( w , b ) (w, b) (w,b)?这需要从样本的联合概率分布出发,构建优化目标函数。
在逻辑回归中,样本标签 y i y_i yi 服从伯努利分布,单个样本的概率为:
P ( y i ∣ x i ; w , b ) = [ σ ( w T x i + b ) ] y i [ 1 − σ ( w T x i + b ) ] 1 − y i P(y_i|x_i; w, b) = \left[\sigma(w^T x_i + b)\right]^{y_i} \left[1 - \sigma(w^T x_i + b)\right]^{1-y_i} P(yi∣xi;w,b)=[σ(wTxi+b)]yi[1−σ(wTxi+b)]1−yi
若 m m m 个样本独立同分布,则联合似然函数为所有样本概率的乘积:
L ( w , b ) = ∏ i = 1 m P ( y i ∣ x i ; w , b ) = ∏ i = 1 m [ σ ( z i ) ] y i [ 1 − σ ( z i ) ] 1 − y i L(w, b) = \prod_{i=1}^{m} P(y_i|x_i; w, b) = \prod_{i=1}^{m} \left[\sigma(z_i)\right]^{y_i} \left[1 - \sigma(z_i)\right]^{1-y_i} L(w,b)=i=1∏mP(yi∣xi;w,b)=i=1∏m[σ(zi)]yi[1−σ(zi)]1−yi
- 符号说明:
- z i = w T x i + b z_i = w^T x_i + b zi=wTxi+b;
- y i ∈ { 0 , 1 } y_i \in \{0, 1\} yi∈{0,1} 为第 i i i 个样本的真实标签;
- ∏ \prod ∏ 为连乘符号,体现独立事件联合概率的计算逻辑。
核心目标:寻找参数 ( w , b ) (w, b) (w,b) 使得 L ( w , b ) L(w, b) L(w,b) 最大,即让观测数据出现的概率最大化(与1.4节伯努利分布的概率建模逻辑连贯)。
2.2 对数似然:从连乘到连加的数学变换
直接优化连乘式计算复杂,利用对数函数性质 ln ( ∏ f i ) = ∑ ln ( f i ) \ln(\prod f_i) = \sum \ln(f_i) ln(∏fi)=∑ln(fi) 转换为对数似然函数:
ln L ( w , b ) = ∑ i = 1 m [ y i ln σ ( z i ) + ( 1 − y i ) ln ( 1 − σ ( z i ) ) ] \ln L(w, b) = \sum_{i=1}^{m} \left[ y_i \ln \sigma(z_i) + (1-y_i) \ln (1 - \sigma(z_i)) \right] lnL(w,b)=i=1∑m[yilnσ(zi)+(1−yi)ln(1−σ(zi))]
- 详细推导步骤:
- 对似然函数取自然对数: ln L ( w , b ) = ln ( ∏ i = 1 m P ( y i ∣ x i ) ) \ln L(w, b) = \ln \left( \prod_{i=1}^{m} P(y_i|x_i) \right) lnL(w,b)=ln(∏i=1mP(yi∣xi)),其中 P ( y i ∣ x i ) P(y_i|x_i) P(yi∣xi) 为单个样本概率;
- 利用对数乘法性质展开: ln L ( w , b ) = ∑ i = 1 m ln P ( y i ∣ x i ) \ln L(w, b) = \sum_{i=1}^{m} \ln P(y_i|x_i) lnL(w,b)=∑i=1mlnP(yi∣xi);
- 代入伯努利分布概率表达式:
ln P ( y i ∣ x i ) = ln { [ σ ( z i ) ] y i [ 1 − σ ( z i ) ] 1 − y i } = y i ln σ ( z i ) + ( 1 − y i ) ln ( 1 − σ ( z i ) ) \ln P(y_i|x_i) = \ln \left\{ \left[\sigma(z_i)\right]^{y_i} \left[1 - \sigma(z_i)\right]^{1-y_i} \right\} = y_i \ln \sigma(z_i) + (1-y_i) \ln (1 - \sigma(z_i)) lnP(yi∣xi)=ln{[σ(zi)]yi[1−σ(zi)]1−yi}=yilnσ(zi)+(1−yi)ln(1−σ(zi))。
2.3 交叉熵损失:从最大化到最小化的目标转换
为将“最大化对数似然”转化为机器学习中常见的损失函数最小化问题,定义:
L o s s ( w , b ) = − ln L ( w , b ) = − ∑ i = 1 m [ y i ln σ ( z i ) + ( 1 − y i ) ln ( 1 − σ ( z i ) ) ] Loss(w, b) = -\ln L(w, b) = -\sum_{i=1}^{m} \left[ y_i \ln \sigma(z_i) + (1-y_i) \ln (1 - \sigma(z_i)) \right] Loss(w,b)=−lnL(w,b)=−i=1∑m[yilnσ(zi)+(1−yi)ln(1−σ(zi))]
-
信息论视角:
交叉熵 H ( y , y ^ ) = − ∑ i = 1 m [ y i ln y ^ i + ( 1 − y i ) ln ( 1 − y ^ i ) ] H(y, \hat{y}) = -\sum_{i=1}^{m} \left[ y_i \ln \hat{y}_i + (1-y_i) \ln (1 - \hat{y}_i) \right] H(y,y^)=−∑i=1m[yilny^i+(1−yi)ln(1−y^i)] 衡量真实分布 y y y 与预测分布 y ^ \hat{y} y^ 的差异,当 y ^ i = σ ( z i ) \hat{y}_i = \sigma(z_i) y^i=σ(zi) 时, L o s s Loss Loss 即为交叉熵,直接量化1.4节中“概率映射准确性”的损失。
- 几何意义:
- 当预测概率 σ ( z i ) \sigma(z_i) σ(zi) 与真实标签 y i y_i yi 一致时(如 y i = 1 y_i=1 yi=1 且 σ ( z i ) → 1 \sigma(z_i)\to1 σ(zi)→1), L o s s → 0 Loss \to 0 Loss→0;
- 当预测相反时(如 y i = 1 y_i=1 yi=1 且 σ ( z i ) → 0 \sigma(z_i)\to0 σ(zi)→0)。
2.4 等价性证明:最大化似然 ≡ 最小化交叉熵
从数学变换看:
arg max w , b L ( w , b ) ⇔ arg max w , b ln L ( w , b ) ⇔ arg min w , b L o s s ( w , b ) \arg\max_{w,b} L(w,b) \quad \Leftrightarrow \quad \arg\max_{w,b} \ln L(w,b) \quad \Leftrightarrow \quad \arg\min_{w,b} Loss(w,b) argw,bmaxL(w,b)⇔argw,bmaxlnL(w,b)⇔argw,bminLoss(w,b)
三者本质是同一优化问题的不同表达,核心是 对数函数的单调性 和 极值方向的反转(取负号)。
三、sklearn 实现逻辑回归:从 API 到实战应用
- sklearn的介绍和安装:网页链接
3.1 sklearn逻辑回归API详解
核心类与参数说明
from sklearn.linear_model import LogisticRegression
-
主要参数:
-
solver:优化算法选择
liblinear
:适用于小数据集,支持L1/L2正则化sag/saga
:适用于大数据集,支持增量学习lbfgs
:拟牛顿法,收敛速度快,默认选项
-
penalty:正则化类型
l1
:L1正则化(Lasso),可产生稀疏解l2
:L2正则化(Ridge),默认选项,防止过拟合
-
C:正则化强度的倒数,值越小惩罚越严厉,默认值为1.0
-
class_weight:类别不平衡处理
balanced
:自动调整权重,适用于正负样本比例悬殊场景- 字典形式:如
{0:1, 1:10}
表示正类权重为负类的10倍
-
3.2 模型训练与预测流程
数据集:电信客户流失数据集
官方数据集下载地址:下载链接
百度网盘下载地址:下载链接 提取码: pujh
将数据集导入项目根目录即可
-
工具准备:导入核心库
pandas
处理表格数据(读文件、列操作),numpy 支持数值计算;
matplotlib+seaborn
画图表(看数据分布、模型结果);
sklearn
模块分工:train_test_split
分训练 / 测试集,MinMaxScaler
归一化特征,LogisticRegression
建模型,classification_report/roc_auc_score
评估效果。
中文字体设置:解决图表中文乱码、负号异常问题,让结果更直观。 -
数据加载与初检
pd.read_csv('churn.csv')
读数据,info()
看 列名、数据类型、缺失值(本案例无缺失,简化处理)。 -
数据预处理:让模型 “读懂” 数据
独热编码(get_dummies
):把 “性别”“合同类型” 等字符串转成 0/1 数值(模型只能处理数值),drop_first=True
避免 多重共线性(如 “性别” 只留 “男” 列,女则为 0)。
列重命名:把编码后的机器名(如gender_Male
)改成中文(如 性别),方便分析。
拆分特征与目标:data_x
存客户属性 / 服务 / 费用(特征),data_y 存 “是否流失”(目标)。 -
可视化:发现数据规律
用sns.countplot
画 流失分布,发现 未流失客户远多于流失客户(数据不平衡)→ 后续评估需重点看 流失类的召回率(别漏判流失客户)。 -
数据分割:训练 vs 测试
train_test_split
按 8:2 拆分,random_state=44
固定随机种子(结果可复现)。 -
特征工程:归一化
MinMaxScaler
把特征缩到 [0,1] 范围(如 “月费” 10→100、“总费用” 100→1000,缩放后统一尺度)。
训练集fit_transform
(先学规则再转换),测试集transform
(复用规则,避免 “作弊”)→ 逻辑回归对特征尺度敏感,归一化加速模型收敛。 -
模型训练:逻辑回归
LogisticRegression(max_iter=1000)
:设最大迭代次数 1000(避免默认次数不足导致不收敛),用训练集 fit 学规律(特征→流失的关系)。
归一化的介绍:网页链接 -
运行效果
精确率:0.8020
AUC得分:0.8331
分类报告:precision recall f1-score supportFalse 0.84 0.91 0.87 1027 True 0.68 0.52 0.59 382 accuracy 0.80 1409 macro avg 0.76 0.71 0.73 1409 weighted avg 0.79 0.80 0.79 1409
3.3程序代码
分类任务的评估方法和根据评估指标进行优化:网页链接
import pandas as pd # 导入Pandas库用于数据处理
import numpy as np # 导入NumPy库用于数值计算
import matplotlib.pyplot as plt # 导入Matplotlib用于数据可视化
import seaborn as sns # 导入Seaborn用于高级数据可视化
from sklearn.preprocessing import MinMaxScaler # 导入特征缩放工具
from sklearn.linear_model import LogisticRegression # 导入逻辑回归模型
from sklearn.metrics import classification_report, roc_auc_score # 导入评估指标
from sklearn.model_selection import train_test_split # 导入数据分割工具# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体,确保中文能正常显示
plt.rcParams['axes.unicode_minus'] = False # 确保负号能正常显示# 1.加载数据
base_data = pd.read_csv('churn.csv') # 从CSV文件读取数据
print("数据基本信息:")
base_data.info() # 查看数据的基本信息,包括列名、数据类型和缺失值情况# 2.数据预处理
# 2.1 将字符串转变成数值(独热编码),并重命名列
data = pd.get_dummies(base_data, drop_first=True) # 将分类特征转换为数值特征,使用drop_first避免多重共线性
data.rename(columns={'gender_Male': '性别', 'Partner_att': '配偶状态', 'Dependents_att': '受抚养人状态','landline': '固定电话','internet_att': '互联网服务', 'internet_other': '其他互联网服务', 'StreamingTV': '电视流媒体服务','StreamingMovies': '电影流媒体服务','Contract_Month': '月付合同', 'Contract_1YR': '一年期合同', 'PaymentBank': '银行支付','PaymentCreditcard': '信用卡支付','PaymentElectronic': '电子支付', 'MonthlyCharges': '月费', 'TotalCharges': '总费用'},inplace=True # 原地修改列名
)# 2.2 数据分割(特征集和目标集)
data['客户流失'] = data['Churn_Yes'] # 创建目标变量列
data.drop(['Churn_Yes'], axis=1, inplace=True) # 删除原始目标变量列
data_x = data.iloc[:, :-1] # 提取特征集(所有列除了最后一列)
data_y = data.iloc[:, -1] # 提取目标集(最后一列)# 2.3 数据展示 - 添加可视化:客户流失分布情况
plt.figure(figsize=(10, 6)) # 设置图表大小
sns.countplot(x='客户流失', data=data) # 绘制客户流失分布柱状图
plt.title('客户流失分布情况') # 设置图表标题
plt.savefig('churn_distribution.png') # 保存图表为图片
plt.show() # 显示图表# 3.数据分割:将数据分为训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(data_x, data_y, test_size=0.2, random_state=44 # 测试集占比20%,设置随机种子确保结果可复现
)# 4.特征工程:使用Min-Max缩放对特征进行归一化
ss = MinMaxScaler() # 初始化MinMaxScaler
nx_train = ss.fit_transform(x_train) # 对训练集进行缩放并学习缩放参数
nx_test = ss.transform(x_test) # 使用训练集学习的参数对测试集进行缩放# 5.模型创建与训练
lr = LogisticRegression(max_iter=1000) # 初始化逻辑回归模型,设置最大迭代次数为1000
lr.fit(nx_train, y_train) # 使用训练数据训练模型# 6.模型预测
pred_y = lr.predict(nx_test) # 预测测试集的分类标签
pred_proba = lr.predict_proba(nx_test)[:, 1] # 获取测试集样本属于正类的概率# 7.模型评估
print(f"\n精确率:{lr.score(nx_test, y_test):.4f}") # 计算并打印模型准确率
print(f"AUC得分:{roc_auc_score(y_test, pred_proba):.4f}") # 计算并打印AUC值
print("\n分类报告:")
print(classification_report(y_test, pred_y)) # 打印分类报告,包含精确率、召回率、F1分数等指标# 8.特征重要性分析
plt.figure(figsize=(12, 8)) # 设置图表大小
# 创建特征重要性DataFrame,使用系数的绝对值作为重要性指标
importance = pd.DataFrame({'特征': data_x.columns,'重要性': np.abs(lr.coef_[0]) # 获取逻辑回归模型的系数绝对值
}).sort_values('重要性', ascending=False) # 按重要性降序排序# 只展示前10个重要特征
sns.barplot(x='重要性', y='特征', data=importance.head(10)) # 绘制特征重要性条形图
plt.title('Top 10特征重要性') # 设置图表标题
plt.tight_layout() # 自动调整布局
plt.savefig('feature_importance.png') # 保存图表
plt.show() # 显示图表