【机器学习】逻辑回归|分类问题评估|混淆矩阵|ROC曲线|AUC指标 介绍及案例代码实现

发布于:2024-10-13 ⋅ 阅读:(43) ⋅ 点赞:(0)

逻辑回归

逻辑回归简介

​ 逻辑回归是解决二分类问题的利器
在这里插入图片描述

逻辑回归的数学基础

  • sigmoid函数:

在这里插入图片描述

  • 概率 - 事件发生的可能性

    联合概率和条件概率是概率论中的基本概念,它们用于描述随机变量之间的关系,如:北京早上堵车的可能性 P_A = 0.7

    中午堵车的可能性 P_B = 0.3

    晚上堵车的可能性 P_C = 0.4

  • 联合概率 – 指两个或多个随机变量同时发生的概率

    P_A = 0.7 周1早上 周2早上同时堵车的概率P_A P_B = 0.7*0.7 = 0.49

  • 条件概率 –表示事件A在另外一个事件B已经发生条件下的发生概率,P(a|b)

    P_A = 0.7 周1早上 堵车的情况下,中午再堵车的概率 P_B|A = 0.7 * 0.3 = 0.21

  • 极大似然估计

    核心思想:根据观测到的结果来估计模型算法中的未知参数

在这里插入图片描述

​ 例如:

​ 假设有一枚不均匀的硬币,出现正面的概率和反面的概率是不同的。假定出现正面的概率为𝜃,
抛了6次得到如下现象 D = {正面,反面,反面,正面,正面,正面}。每次投掷事件都是相互独立的。
则根据产生的现象D,来估计参数𝜃是多少?

在这里插入图片描述

逻辑回归原理

概念

  • 逻辑回归概念 Logistic Regression
    • 一种分类模型,把线性回归的输出作为逻辑回归的输入
    • 输出是(0,1)之间的值
  • 基本思想
    • 利用线性模型 f(x) = w^T + b 根据特征的重要性计算出的一个值
    • 在使用sigmoid函数 将f(x)的输出映射为概率值
      • 设置阈值(eg:0.5) 输出概率值大于0.5归类为1类 否则归类为0类
  • 逻辑回归的假设函数
    • h(w) = sigmoid(w^T + b)
    • 线性回归的输出作为逻辑回归的输入
  • 举例

在这里插入图片描述

损失函数

  • 公式
    在这里插入图片描述

  • 损失函数的设计思想: 预测值为A B 两个类别 真实类别所在的位置 概率值越大越好

逻辑回归API函数和案例

sklearn.linear_model.LogisticRegression(solver='liblinear', penalty=‘l2’, C = 1.0)
  • solver 损失函数优化方法:
    • iblinear 对小数据集场景训练速度更快,sag 和 saga 对大数据集更快一些。
    • 2 正则化:
      • 1 sag、saga 支持 L2 正则化或者没有正则化
      • 2 liblinear 和 saga 支持 L1 正则化
  • penalty:正则化的种类,l1 或者 l2
  • C:正则化力度
  • 默认将类别数量少的当做正例

案例癌症分类预测

  • 数据描述

(1)699条样本,共11列数据,第一列用语检索的id,后9列分别是与肿瘤相关的医学特征,
​ 最后一列表示肿瘤类型的数值。
(2)包含16个缺失值,用”?”标出。
(3)2表示良性,4表示恶性

在这里插入图片描述

  • 代码实现
"""
案例:
    逻辑回归模型 预测癌症信息
逻辑回归:
    属于回归任务的一种 主要用于二分法
    原理:
        1.把线性回归的值 传入 Sigmoid 函数 计算概率
        2.手动蛇者阈值(eg:0.6) 然后查看上述的概率是否达到我们设定的阈值 及逆行分类
    损失函数:
        先基于 极大似然函数计算 然后转换成对数似然函数 当做损失函数 结合梯度下降计算最小值

"""

import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.metrics import mean_squared_error, accuracy_score  # 计算均方误差
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge, Lasso
from sklearn.preprocessing import StandardScaler


def demo01():
    data = pd.read_csv(r"D:\hm\homework\pywork\workProject\ML_Project\data\breast-cancer-wisconsin.csv")
    # 数据预处理 用 np.NaN 替换? 缺失值
    data = data.replace('?', np.NaN)
    # 删除缺失值 按行删除
    data.dropna(axis=0, inplace=True)  # axis = 0 按行删除
    # 手动提取数据 即 特征和标签
    print(data.head())
    x = data.iloc[:, 1:10]
    y = data.iloc[:, 10]
    # 划分训练集和测试集
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2)
    # 特征工程
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.transform(x_test)
    # 模型训练
    estimator = LogisticRegression()
    estimator.fit(x_train, y_train)
    # 模型预测
    y_predict = estimator.predict(x_test)

    # 模型评估
    print('准确率:', estimator.score(x_test, y_test))  # 预测前 评估
    print('准确率:', accuracy_score(y_test, y_predict)) # 预测后 评估

    # 混淆矩阵 精准率 召回率 F1值(F1-score) AUC值(Area under Curve), ROC 曲线



if __name__ == '__main__':
    demo01()

分类问题评估

混淆矩阵

在这里插入图片描述

  • 混淆矩阵的四个指标

    • 真实值是 正例 的样本中,被分类为 正例 的样本数量有多少,叫做真正例(TP,True Positive)
    • 真实值是 正例 的样本中,被分类为 假例 的样本数量有多少,叫做伪反例(FN,False Negative)
    • 真实值是 假例 的样本中,被分类为 正例 的样本数量有多少,叫做伪正例(FP,False Positive)
    • 真实值是 假例 的样本中,被分类为 假例 的样本数量有多少,叫做真反例(TN,True Negative)
  • 例子

    已知:样本集10样本,有 6 个恶性肿瘤样本,4 个良性肿瘤样本,我们假设恶性肿瘤为正例

模型A:预测对了 3 个恶性肿瘤样本,4 个良性肿瘤样本
请计算:TP、FN、FP、TN

真正例 TP 为:3
伪反例 FN 为:3
伪正例 FP 为:0
真反例 TN:4

模型B:预测对了 6 个恶性肿瘤样本,1个良性肿瘤样本
请计算:TP、FN、FP、TN

真正例 TP 为:6
伪反例 FN 为:0
伪正例 FP 为:3
真反例 TN:1

注意:TP+FN+FP+TN = 总样本数量

分类评估方法 - 精确率 召回率 F1

  • 精确率

    • 查准率,对正例样本的预测准确率。比如:把恶性肿瘤当做正例样本,想知道模型对恶性肿瘤的预测准确率。
    • 计算方法:P = TP/TP+ FP
    • 例子
      在这里插入图片描述
  • 召回率

    • 也叫查全率,指的是预测为真正例样本占所有真实正例样本的比重例如:恶性肿瘤当做正例样本,则我们想知道模型是否能把所有的恶性肿瘤患者都预测出来。

    • 计算方法:P = TP/TP+ FN

    • 在这里插入图片描述

    • 例子

在这里插入图片描述

  • F1 - score
    • 若对模型的精度、召回率都有要求,希望知道模型在这两个评估方向的综合预测能力?
    • 计算方法:P == 2 ∗Precision ∗Recall/Precision+Recall

在这里插入图片描述

  • 代码实现
"""
演示 逻辑回归模型 的评估方式 即: 精确率 召回率 F1值

混淆矩阵解释:
    概述:
        用来描述 真实值(样本值)中 正例,反例 和 预测值的 正例,反例 之间的关系的
    名词解释:
        真正例(TP True Positive) : 样本值 = 正例 预测值 = 正例
        伪正例(FP False Positive) : 样本值 = 假例 预测值 = 正例
        真反例(TN True Negative) : 样本值 = 假例 预测值 = 假例
        伪反例(FN False Negative) : 样本值 = 正例 预测值 = 假例

逻辑回归模型评估
    方式1: 正确率(准确率)   预测的真实结果/样本总数
    方式2: 精确率(Precision) tp/ tp + fp  (精度)
    方式3: 召回率(Recall) tp/tp + fn     (查全率)
    方式3: 召回率(Recall) tp/tp + fn     (查全率)
    方式4 F1-score 2*Precision*Recall / Precision + Recall
"""

import pandas as pd
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score

# 1.准备样本集 6个恶行肿瘤 4 个 良性肿瘤   即: 训练集的标签
y_train = ['恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '良性', '良性', '良性', '良性']
# 2. 准备标签
labels = ['恶性', '良性']

# 3. 准备预测值 即 模型a 预测对 3个恶性 4个良性
y_pred_a = ['恶性', '恶性', '恶性', '良性', '良性', '良性', '良性', '良性', '良性', '良性']

# 4.准备预测值 即 模型b 预测对了 6个恶性 1个良性
y_pred_b = ['恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '良性']

# 5. 基于模型 a 构建混淆矩阵 (confusion_matrix)
cm_a = confusion_matrix(y_train, y_pred_a, labels=labels)
print(cm_a)

# 6. 把上述的混淆矩阵 转成 DataFrame
cm_a_df = pd.DataFrame(cm_a, index=labels, columns=labels)
print(cm_a_df)
print('------------------------------------------------------------------------------------------')
# 7. 基于模型 b 构建混淆矩阵 (confusion_matrix)
cm_b = confusion_matrix(y_train, y_pred_b, labels=labels)
print(cm_b)

# 8. 把上述的混淆矩阵 转成 DataFrame
cm_b_df = pd.DataFrame(cm_b, index=labels, columns=labels)
print(cm_b_df)

# 9.计算a b 的精确率
precision_a = cm_a[0][0] / (cm_a[0][0] + cm_a[1][0])
precision_b = cm_b[0][0] / (cm_b[0][0] + cm_b[1][0])

precision_a1 = precision_score(y_train, y_pred_a,pos_label='恶性')
precision_b1 = precision_score(y_train, y_pred_b,pos_label='恶性')
print('精确率 a:{}, b:{}'.format(precision_a, precision_b))
print('精确率 a1:{}, b1:{}'.format(precision_a1, precision_b1))

# 10.计算a b 的召回率
recall_a = cm_a[0][0] / (cm_a[0][0] + cm_a[0][1])
recall_b = cm_b[0][0] / (cm_b[0][0] + cm_b[0][1])
print('召回率 a:{}, b:{}'.format(recall_a, recall_b))
recall_a1 = recall_score(y_train, y_pred_a,pos_label='恶性')
recall_b1 = recall_score(y_train, y_pred_b,pos_label='恶性')
print('召回率 a1:{}, b1:{}'.format(recall_a1, recall_b1))

# 11.计算a b 的F1值
f1_a = 2 * precision_a * recall_a / (precision_a + recall_a)
f1_b = 2 * precision_b * recall_b / (precision_b + recall_b)
print('F1值 a:{}, b:{}'.format(f1_a, f1_b))
f1_a1 = f1_score(y_train, y_pred_a,pos_label='恶性')
f1_b1 = f1_score(y_train, y_pred_b,pos_label='恶性')
print('F1值 a1:{}, b1:{}'.format(f1_a1, f1_b1))

ROC曲线 AUC指标

  • 真正率TPR与假正率FPR
    • 1 正样本中被预测为正样本的概率TPR (True Positive Rate)
    • 2 负样本中被预测为正样本的概率FPR (False Positive Rate)
    • 通过这两个指标可以描述模型对正/负样本的分辨能力
  • ROC曲线(Receiver Operating Characteristic curve)
    • 是一种常用于评估分类模型性能的可视化工具。ROC曲线以模型的真正率TPR为纵轴,假正率FPR为横轴,它将模型在不同阈值下的表现以曲线的形式展现出来。
  • AUC (Area Under the ROC Curve)曲线下面积
    • ROC曲线的优劣可以通过曲线下的面积(AUC)来衡量,AUC越大表示分类器性能越好。
      当AUC=0.5时,表示分类器的性能等同于随机猜测
      当AUC=1时,表示分类器的性能完美,能够完全正确地将正负例分类。****

在这里插入图片描述

  • ROC 曲线图像中,4 个特殊点的含义

点坐标说明:图像x轴FPR/y轴TPR, 任意一点坐标A(FPR值, TPR值)
点(0, 0) :所有的负样本都预测正确,所有的正样本都预测为错误 。相当于点的(FPR值0, TPR值0)
点(1, 0) :所有的负样本都预测错误,所有的正样本都预测错误。相当于点的(FPR值1, TPR值0)

最不好的效果 :点(1, 1):所有的负样本都预测错误,表示所有的正样本都预测正确。相当于点的(FPR值1,TPR值1)
最好的效果: 点(0, 1):所有的负样本都预测正确,表示所有的正样本都预测正确 。相当于点的(FPR值0,TPR值1)

  • 从图像上来看
    • 曲线越靠近 (0,1) 点则模型对正负样本的辨别能力就越强
    • AUC 是 ROC 曲线下面的面积,该值越大,则模型的辨别能力就越强,AUC 范围在 [0, 1] 之间
      当 AUC= 1 时,该模型被认为是完美的分类器,但是几乎不存在完美分类器
      当 AUC <= 0.5 时,模型区分正负样本的就会变得模棱两可,近似于随机猜测
案例

在这里插入图片描述

思路分析:根据不同的阈值,求出TPR、FPR,得出点坐标画ROC图

在这里插入图片描述

AUC 计算的API
from sklearn.metrics import roc_auc_score
sklearn.metrics.roc_auc_score(y_true, y_score)

计算ROC曲线面积,即AUC值
y_true:每个样本的真实类别,必须为0(反例),1(正例)标记
y_score:预测得分,可以是正例的估计概率、置信值或者分类器方法的返回值

分类评估报告api
sklearn.metrics.classification_report(y_true, y_pred, labels=[], target_names=None )

y_true:真实目标值
y_pred:估计器预测目标值
labels:指定类别对应的数字
target_names:目标类别名称
return:每个类别精确率与召回率

电信客户流失预测案例

  • 案例需求:
    • 已知:用户个人,通话,上网等信息数据
    • 需求:通过分析特征属性确定用户流失的原因,以及哪些因素可能导致用户流失。建立预测模型来判断用户是否流失,并提出用户流失预警策略。
  • 数据集介绍

在这里插入图片描述
在这里插入图片描述

  • 案例步骤分析

    1、数据基本处理
    主要是查看数据行/列数量
    对类别数据数据进行one-hot处理
    查看标签分布情况
    2、特征筛选
    分析哪些特征对标签值影响大
    对标签进行分组统计,对比0/1标签分组后的均值等
    初步筛选出对标签影响比较大的特征,形成x、y
    3、模型训练
    样本均衡情况下模型训练
    样本不平衡情况下模型训练
    交叉验证网格搜素等方式模型训练
    4、模型评估
    精确率
    Roc_AUC指标计算

  • 代码实现

"""
案例
    电信用户流失预测
"""
# 定义函数 表示数据预处理
# 定义函数 表示 数据查看 绘图
# 定义函数 表示 模型训练 评估 预测

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt


# 定义函数 数据预处理
def demo01():
    churn_df = pd.read_csv(r'D:\hm\homework\pywork\workProject\ML_Project\data\churn.csv')
    churn_df.info()

    # 数据预处理 把 字符串列 转成 数字列 采用 one-hot  热编码
    churn_df = pd.get_dummies(churn_df)
    churn_df.info()
    churn_df.head()

    churn_df.drop(['Churn_No', 'gender_Male'], axis=1, inplace=True)

    # 修改列名
    churn_df.rename(columns={'Churn_Yes': 'flag'}, inplace=True)
    churn_df.info()
    churn_df.head()


# 特征筛选
def demo02():
    churn_df = pd.read_csv(r'D:\hm\homework\pywork\workProject\ML_Project\data\churn.csv')
    churn_df = pd.get_dummies(churn_df)
    churn_df.drop(['Churn_No', 'gender_Male'], axis=1, inplace=True)
    churn_df.rename(columns={'Churn_Yes': 'flag'}, inplace=True)
    print(churn_df.head())
    print(churn_df.flag.value_counts())
    print(churn_df.columns)
    sns.countplot(data=churn_df, x='Contract_Month', hue='flag')
    plt.show()


if __name__ == '__main__':
    demo02()
  • 运行结果
    在这里插入图片描述

在这里插入图片描述