文章目录
4.4.1 逻辑回归的应用场景
- 广告点击率
- 是否为垃圾邮件
- 是否患病
- 金融诈骗
- 虚假账号
看到上面的例子,我们可以发现其中的特点,那就是都属于两个类别之间的判断。逻辑回归就是解决二分类问题的利器
4.4.2 逻辑回归的原理
1. 输入
逻辑回归的输入 就是 线性回归的输出
2. 激活函数
- sigmoid函数
- 分析
o 回归的结果输入到sigmoid函数当中
o 输出结果:[0, 1]区间中的一个概率值,默认为0.5为阈值
逻辑回归最终的分类是通过属于某个类别的概率值来判断是否属于某个类别,并且这个类别默认标记为1(正例),另外的一个类别会标记为0(反例)(方便损失计算)
输出结果解释(重要):假设有两个类别A,B,并且假设我们的概率值为属于A(1)这个类别的概率值。现在有一个样本的输入到逻辑回归输出结果0.6,那么这个概率值超过0.5,意味着我们训练或者预测的结果就是A(1)类别。那么反之,如果得出结果为0.3那么,训练或者预测结果就为B(0)类别。所以接下来我们回忆之前的线性回归预测结果我们用均方误差衡量,那如果对于逻辑回归,我们预测的结果不对该怎么去衡量这个损失呢?我们来看这样一张图
那么如何去衡量逻辑回归的预测结果与真实结果的差异呢?
3. 损失以及优化
3.1 损失
逻辑回归的损失,称之为对数似然损失,公式如下:
- 分开类别:
怎么理解单个的式子呢?这个要根据log的函数图像来理解
当y=1时
当真实值接近1,损失函数接近于0。
当y=0时
当真实值接近0,损失函数接近于0。 - 综合完整损失函数
看到这个式子,其实跟我们讲的信息熵类似。
我们已经知道,log( P), P值越大,结果越小(负的),所以我们可以对着这个损失的式子去分析
3.2 优化
同样使用梯度下降优化算法,去减少损失函数的值。这样去更新逻辑回归前面对应算法的权重参数,提升原本属于1类别的概率,降低原本是0类别的概率。
4.4.3 逻辑回归API
sklearn.linear_model.LogisticRegression(solver='liblinear', penalty=‘l2’, C = 1.0)
- solver:优化求解方式(默认开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数)
o sag:根据数据集自动选择,随机平均梯度下降 - penalty:正则化的种类
- C:正则化力度
默认将类别数量少的当做正例
LogisticRegression方法相当于 SGDClassifir(loss=“log”, penalty=" "),SGDClassifier实现了一个普通的随机梯度下降学习,也支持平均随机梯度下降法(ASGD),可以通过设置average=True。而使用LogisticRegression(实现了SAG)
4.4.4 案例:癌症分类预测-良/恶性乳腺癌肿瘤预测
- 数据介绍
原始数据的下载地址 - 数据描述
(1)699条样本,共11列数据,第一列用语检索的id,后9列分别是与肿瘤
相关的医学特征,最后一列表示肿瘤类型的数值。
(2)包含16个缺失值,用”?”标出。
1. 分析
- 获取数据
读取的时候加上names - 数据处理
缺失值处理 - 数据集划分
- 特征工程
标准化处理 - 逻辑回归预估器
- 模型评估
2. 代码
import pandas as pd
import numpy as np
# 1.获取数据
column_name = ['Sample code number', 'Clump Thickness', 'Uniformity of Cell Size', 'Uniformity of Cell Shape', 'Marginal Adhesion', 'Single Epithelial Cell Size', 'Bare Nuclei', 'Bland Chromatin', 'Normal Nucleoli', 'Mitoses', 'Class']
data = pd.read_csv("breast-cancer-wisconsin.data",names=column_name)
data
# 输出1
# 2.缺失值处理
# 2.1 替换 -> np.nan
data = data.replace(to_replace="?",value=np.nan)
# 2.2 删除缺失样本
data.dropna(inplace=True)
data.isnull().any()
# 说明不存在缺失
# 输出2
# 3.划分数据集
from sklearn.model_selection import train_test_split
data
# 输出3
# 筛选特征值和目标值(索引)
x = data.iloc[:,1:-1]
y = data["Class"]
x
# 输出4
y
# 输出5
x_train,x_test,y_train,y_test = train_test_split(x,y)
x_train
# 输出6
# 4.特征工程--标准化
from sklearn.preprocessing import StandardScaler
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
x_train
# 输出7
# 5.预估器流程
from sklearn.linear_model import LogisticRegression
estimator = LogisticRegression()
estimator.fit(x_train,y_train)
# 逻辑回归模型参数:回归系数和偏置
estimator.coef_
# 输出8
estimator.intercept_
# 输出9
# 6.模型评估
y_predict = estimator.predict(x_test)
print("y_predict:\n",y_predict)
print("直接对比真实值和预测值:\n",y_test == y_predict)
score = estimator.score(x_test,y_test)
print("准确率为:\n",score)
#输出10
3. 输出
- 输出1
- 输出2
Sample code number False
Clump Thickness False
Uniformity of Cell Size False
Uniformity of Cell Shape False
Marginal Adhesion False
Single Epithelial Cell Size False
Bare Nuclei False
Bland Chromatin False
Normal Nucleoli False
Mitoses False
Class False
dtype: bool
- 输出3
- 输出4
- 输出5
0 2
1 2
2 2
3 2
4 2
..
694 2
695 2
696 4
697 4
698 4
Name: Class, Length: 683, dtype: int64
- 输出6
- 输出7
array([[ 1.9038863 , 0.24264639, 0.54261942, ..., 0.2024589 ,
-0.6277008 , -0.34710902],
[ 1.55968087, 2.16380544, 2.16730447, ..., -0.2072603 ,
0.03154599, -0.34710902],
[ 0.52706457, -0.71793313, -0.75712862, ..., -1.02669869,
-0.6277008 , -0.34710902],
...,
[ 1.9038863 , 2.16380544, 2.16730447, ..., 1.84133569,
-0.6277008 , 1.85375558],
[ 0.18285914, -0.71793313, -0.75712862, ..., -0.61697949,
-0.6277008 , -0.34710902],
[ 1.55968087, 0.56283957, 1.51743045, ..., -0.61697949,
-0.6277008 , 1.85375558]])
- 输出8
array([[1.08933605, 0.17079909, 0.95268012, 0.92101552, 0.45043016,
1.30437445, 1.14416143, 0.18697209, 0.61917046]])
- 输出9
array([-1.01021108])
- 输出10
y_predict:
[2 2 2 2 2 4 2 2 2 2 2 4 4 4 2 2 2 2 4 4 2 2 2 2 2 4 2 2 2 2 2 2 2 4 2 4 2
2 2 2 4 2 4 2 2 4 4 2 4 2 4 4 2 4 4 2 4 2 4 4 4 4 2 2 4 2 4 2 2 2 2 2 2 2
2 2 4 2 2 2 4 2 2 4 2 4 2 4 2 2 2 2 2 2 4 2 2 2 2 2 4 4 4 2 4 4 2 2 2 2 2
2 4 2 2 4 4 4 4 4 2 2 2 2 2 2 2 2 2 2 4 2 2 2 2 2 2 4 2 2 2 4 2 4 4 4 4 2
2 2 4 2 2 2 2 2 2 2 4 4 2 2 2 2 4 2 4 2 2 4 2]
直接对比真实值和预测值:
127 True
420 True
616 True
409 True
88 True
...
603 True
624 True
513 True
20 True
256 True
Name: Class, Length: 171, dtype: bool
准确率为:
0.9649122807017544
4.4.5 分类的评估方法
1. 精确率与召回率
1.1 混淆矩阵
在分类任务下,预测结果(Predicted Condition)与正确标记(True Condition)之间存在四种不同的组合,构成混淆矩阵(适用于多分类)
TP = True Possitive
FN = False Negative
FP = False Possitive
TN = True Negative
1.2 精确率(Precision)与召回率(Recall)
恶性 — 正例
- 精确率(Precision):预测结果为正例样本中真实为正例的比例
TP/(TP+FP)
- 召回率(Recall):真实为正例的样本中预测结果为正例的比例(查的全,对正样本的区分能力)
TP/(TP+FN) 真的患癌症,且能够被检查出来的概率
- 还有其他的评估标准,F1-score,反映了模型的稳健型
1.3 分类评估报告API
sklearn.metrics.classification_report(y_true, y_pred, labels=[], target_names=None )
- y_true:真实目标值
- y_pred:估计器预测目标值
- labels:指定类别对应的数字
- target_names:目标类别名称
- return:每个类别精确率与召回率
我们用上一节癌症模型的评估
from sklearn.metrics import classification_report
report = classification_report(y_test,y_predict,labels=[2,4],target_names=["良性","恶性"])
print(report)
输出:
precision recall f1-score support
良性 0.97 0.98 0.97 114
恶性 0.96 0.93 0.95 57
accuracy 0.96 171
macro avg 0.96 0.96 0.96 171
weighted avg 0.96 0.96 0.96 171
我们主要关注的是恶性的recall值,为0.93。
也就是说,如果有100个癌症患者,只有93个人被诊断出癌症,还有7个人未被检查出癌症,
假设这样一个情况(样本不均衡),如果99个样本癌症,1个样本非癌症,不管怎样我全都预测正例(默认癌症为正例) ----不负责任的模型,但是他的指标都很高,如下
准确率 = 99/100=99%
召回率 = 99/99 =100%
精确率 = 99/100 = 99%
F1-score = 2 x 0.99 x 1/(0.99+1)= 99.497%
问题:如何衡量样本不均衡下的评估?
2. ROC曲线与AUC指标
2.1 TPR与FPR
- TPR = TP / (TP + FN) — 召回率
所有真实类别为1的样本中,预测类别为1的比例 - FPR = FP / (FP + FN)
所有真实类别为0的样本中,预测类别为1的比例
2.2 ROC曲线
ROC曲线的横轴就是FPRate,纵轴就是TPRate,当二者相等时,表示的意义则是:对于不论真实类别是1还是0的样本,分类器预测为1的概率是相等的,此时AUC为0.5
蓝色曲线表示ROC曲线
蓝色区域与x轴、y轴围成的面积是AUC指标
2.3 AUC指标
- AUC的概率意义是随机取一对正负样本,正样本得分大于负样本的概率
- AUC的最小值为0.5,最大值为1,取值越高越好
- AUC=1,完美分类器,采用这个预测模型时,不管设定什么阈值都能得出完美预测。绝大多数预测的场合,不存在完美分类器。
- 0.5<AUC<1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值。
最终AUC的范围在[0.5, 1]之间,并且越接近1越好
2.4 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:每个样本预测的概率值,可以是正类的估计概率、置信值或者分类器方法的返回值
# 将y_test 转换成 0 1
y_true = np.where(y_test>3,1,0)
y_true
from sklearn.metrics import roc_auc_score
roc_auc_score(y_true,y_predict)
输出:
array([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0,
0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0,
0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0,
1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0])
0.956140350877193
还是刚刚的例子:
假设这样一个情况(样本不均衡),如果99个样本癌症,1个样本非癌症,不管怎样我全都预测正例(默认癌症为正例) ----不负责任的模型,但是他的指标都很高,如下
准确率 = 99/100=99%
召回率 = 99/99 =100%
精确率 = 99/100 = 99%
F1-score = 2 x 0.99 x 1/(0.99+1)= 99.497%
TPR= 100 %
FPR = 1/1 =100%
AUC =0.5 —> 模型不好
2.5 总结
- AUC只能用来评价二分类
- AUC非常适合评价样本不平衡中的分类器性能