文章目录
逻辑回归
逻辑回归简介
逻辑回归是解决二分类问题的利器
在这里插入图片描述
逻辑回归的数学基础
- 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曲线的优劣可以通过曲线下的面积(AUC)来衡量,AUC越大表示分类器性能越好。
- 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()
- 运行结果