模型搭建和评估

  • 建模
    • 导入各种库及可视化设置
    • 模型的选择路径
    • 模型搭建
      • 任务一:切割训练集和测试集
      • 任务二:模型创建
        • 创建基于线性模型的分类模型(逻辑回归)
        • 创建基于树的分类模型(决策树、随机森林)
      • 任务三:输出模型预测结果
    • 模型评估
      • 模型评估的方法
        • K折交叉验证
        • 混淆矩阵极其衍生指标
          • 实例
        • ROC曲线

经过前面的两章的知识点的学习,可以对数据的本身进行处理,比如数据本身的增删查补,还可以做必要的清洗工作。那么下面我们就要开始使用我们前面处理好的数据了。这一章我们要做的就是使用数据,我们做数据分析的目的也就是,运用我们的数据以及结合我的业务来得到某些我们需要知道的结果。那么分析的第一步就是建模,搭建一个预测模型或者其他模型;我们从这个模型的到结果之后,我们要分析我的模型是不是足够的可靠,那我就需要评估这个模型。

建模

  1. 处理完前面的数据我们就得到建模数据,下一步是选择合适模型
  2. 在进行模型选择之前我们需要先知道数据集最终是进行监督学习还是无监督学习
  3. 除了根据我们任务来选择模型外,还可以根据数据样本量以及特征的稀疏性来决定
  4. 刚开始我们总是先尝试使用一个基本的模型来作为其baseline,进而再训练其他模型做对比,最终选择泛化能力或性能比较好的模型

导入各种库及可视化设置

import pandas as pd#用于数据处理的库,围绕DataFrame数据类型为核心开展
import numpy as np#科学计算的基础包,快速高效的多维数组对象ndarray,用于对数组执行元素及计算或直接对数组执行数学运算,线性代数运算、傅里叶变换、随机数生成、集成c、c++等代码到python
import matplotlib.pyplot as plt#数据可视化库
import seaborn as sns#基于matplotlib的数据可视化库
from IPython.display import Image#基于Matplotlib库的数据可视化库
%matplotlib inline#%matplotlib inline 可以在Ipython编译器里直接使用,功能是可以内嵌绘图,并且可以省略掉plt.show()这一步。
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
plt.rcParams['figure.figsize'] = (10, 6)  # 设置输出图片大小

载入我们提供清洗之后的数据(clear_data.csv),大家也将原始数据载入(train.csv),说说他们有什么不同?

data=pd.read_csv("clear_data.csv")
train=pd.read_csv("train.csv")
  • 从列名上看,清洗过的数据删除了Name、Ticket、Cabin等与建模无关的列数据
  • 将Sex列和Embarked列进行独热编码
  • 对原数据中的空缺值进行了填充
  • 处理后的数据仅有int和flaot两种数据类型

模型的选择路径

  • 处理完前面的数据我们就得到建模数据,下一步是选择合适模型
  • 在进行模型选择之前我们需要先知道数据集最终是进行监督学习还是无监督学习
  • 模型的选择一方面是通过我们的任务来决定的。
  • 除了根据我们任务来选择模型外,还可以根据数据样本量以及特征的稀疏性来决定
  • 刚开始我们总是先尝试使用一个基本的模型来作为其baseline,进而再训练其他模型做对比,最终选择泛化能力或性能比较好的模型
    下面给出sklearn的算法选择路径,供大家参考

模型搭建

【思考】数据集哪些差异会导致模型在拟合数据时发生变化

  • 训练集、测试集的样本划分是否均衡,是否存在某类样本集中在某个数据集上的情况
  • 数据是否具有代表性
  • 数据之间是否存在联系,比如时间上的先后顺序
  • 机器学习的一个重要假设是数据独立同分布
  • 数据量是否足够

任务一:切割训练集和测试集

这里使用留出法划分数据集

  1. 将数据集分为自变量和因变量
  2. 按比例切割训练集和测试集(一般测试集的比例有30%、25%、20%、15%和10%)
  3. 使用分层抽样
  4. 设置随机种子以便结果能复现

问题:

  1. 为什么要划分数据集

    • 用于检验模型的拟合程度、泛化能力及稳定性
    • 一般而言,训练集表现好但测试集表现不好的模型存在过拟合风险,训练集的效果明显差于测试集则模型有欠拟合风险
    • 过拟合:模型学习的过于细致
    • 欠拟合:模型学习的过于粗糙
  2. 划分数据集的方法有哪些?
    • 留出法

      • “留出法”直接将数据集D划分为两个互斥的集合,一个为训练集S,一个为测试集T,即D=S∪T,S∩T=∅.在S上进行模型学习,然后用T来评估其测试误差,作为对泛化误差的估计。
      • 单次使用留出法得到的估计结果往往不够稳定可靠,在使用留出法时,一般要采用若干次随机划分、重复进行模型评估后取平均值作为留出法的评估结果。
      • 数据量为10000左右。如果只是划成训练集和测试集则为:70%验证集,30%测试集。如果划成训练集、验证集和测试集则为:60%训练集,20%验证集,20%测试集。
      • 数据量为百万级别。 验证集和测试集占数据总量的比例会趋向变得更小。比如有1000000条数据,只需各拿出10000条作为验证集和测试集。
    • 交叉验证法
      • 首先将数据分成两部分,左边训练集,右边测试集,训练集用于建立模型,在建模过程中不能加入任何与测试集有关的信息,否则相当于泄题。
      • 再将训练集切分成多份,假设分为了10份,在验证某一次结果是,需要把整个过程分成10步,第一步用前九份作训练集,最后一份做验证集,得到一个结果,以此类推,每一次都用另外一份作为验证集,其他作为训练集。经过10步以后,训练集的每一份都作了一次验证集,得到10个结果。
      • 对最终的10个结果进行平均。
      • “交叉验证法”先将数据集D划分为k个大小相同的互斥子集,即D=D1∪D2∪⋯∪Dk,Di∩Dj=∅(i≠j).其中每个子集Di都应尽量保持数据分布的一致性,即从D中通过分层采样得到。
      • 然后,每次都用其中的k−1个子集的并集作为训练集,余下一个作为测试集,这样就可以得到k组训练集/测试集,从而可以进行k次模型的学习,并把这k个测试结果的均值作为评估结果,通常我们把交叉验证法称为“k折交叉验证”。
      • 优点:从有限的数据中尽可能挖掘多的信息,从各种角度去学习我们现有的有限的数据,避免出现局部的极值。在这个过程中无论是训练样本还是测试样本都得到了尽可能多的学习。
        ​ - 缺点:当数据集比较大时,训练模型的开销较大。
    • 自助法
      • 每次随机从初始数据集 D 中选择一个样本拷贝到结果数据集 D′ 中,重复操作 m 次 ,就得到了含有 m 个样本的数据集 D′ (注意:D 中有部分样本会在 D′ 中多次出现)。将 D′ 作为训练集,D∖D′ 作为验证集(测试集)。样本在 m 次采样中始终不被采集到的概率是(1−1m)m(1-\cfrac{1}{m})^m(1−m1​)m,取极限为:lim⁡m⟶∞(1−1m)m=1e≈0.368\mathop{\lim}\limits_{m\longrightarrow\infty}(1-\cfrac{1}{m})^m=\cfrac{1}{e}\approx0.368m⟶∞lim​(1−m1​)m=e1​≈0.368,通过自助采样,初始数据集中约有36.8%的样本未出现在采样集 D′ 中。
      • 优点:自助法在数据集较小、难以有效划分训练集和测试集时很有用。此外,自助法能从初始数据集中产生多个不同的训练集,这对集成学习等方法有很大的好处。
      • 缺点:自助法产生的数据集改变了初始数据集的分布,这会引入估计偏差。因此在初始数据量足够时,留出法和交叉验证法更加常用一些。
  3. 为什么使用分层抽样,这样的好处有什么?
    • 可以保证抽样后各数据集的样本比例相同,从而避免因样本分布差异而导致的偏差。
    • 使用分层抽样后,如果模型在不同数据集上效果差异大,我们可以更有把把握是因为拟合问题,而非数据问题。
from sklearn.model_selection import train_test_split
#使用sklearn.model_selection中的train_test_split进行分层抽样
#通过stratify参数指定分层对应的变量,如果不指定stratify参数则为普通的随机抽样
train_test_split?#查看函数参数,截取在下
'''
* arrays:具有相同长度/形状的可索引序列[0]允许的输入是列表,numpy数组,scipy-sparse矩阵或pandas dataframes。
test_size:float,int或None,可选(默认=None)如果为float,则应介于0.0到1.0之间并代表比例包含在测试拆分中的数据集的数量。如果为int,则表示测试样品的绝对数量。如果为None,则将值设置为训练集补集的大小。如果``train_size``也为None,它将设置为0.25。
train_size:浮点数,整数或无,(默认=无)如果为float,则应介于0.0和1.0之间,并表示数据集要包含在火车分割中的比例。如果int,表示火车样本的绝对数量。如果没有,该值将自动设置为测试大小的补码。
random_state:int,RandomState实例或无,可选(默认值:无)如果为int,则random_state是随机数生成器使用的种子;否则为false。如果是RandomState实例,则random_state是随机数生成器;如果为None,则随机数生成器是使用的RandomState实例通过`np.random`。
shuffle:布尔值,可选(默认= True)拆分前是否对数据进行混洗。如果shuffle = False然后分层必须为“无”。
分层:类数组或无(默认=无)如果不是None,则以分层方式拆分数据,使用类标签。'''
X = data#DataFrame
y = train['Survived']#Series
#对数据集按照y进行分层抽样,随机种子为0,为保证每次运行结果一样
#返回结果中X_train、X_test为DataFrame类型,y_train、 y_test为Series类型
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=0)

什么情况下切割数据集的时候不用进行随机选取?

任务二:模型创建

创建基于线性模型的分类模型(逻辑回归)

lr = LogisticRegression()#会出现警告lbfgs 无法收敛,要求增加迭代次数
lr.fit(X_train, y_train)
#调整迭代次数重新创建模型,警告消除
lr = LogisticRegression(max_iter=1000)
lr.fit(X_train, y_train)
'''
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,intercept_scaling=1, l1_ratio=None, max_iter=1000,multi_class='auto', n_jobs=None, penalty='l2',random_state=None, solver='lbfgs', tol=0.0001, verbose=0,warm_start=False)
'''
# 查看训练集和测试集score值
print("Training set score: {:.2f}".format(lr.score(X_train, y_train)))
print("Testing set score: {:.2f}".format(lr.score(X_test, y_test)))
#Training set score: 0.81
#Testing set score: 0.78
# 调整参数后的逻辑回归模型
lr2 = LogisticRegression(C=100,max_iter=1000)
lr2.fit(X_train, y_train)
'''
LogisticRegression(C=100, class_weight=None, dual=False, fit_intercept=True,intercept_scaling=1, l1_ratio=None, max_iter=1000,multi_class='auto', n_jobs=None, penalty='l2',random_state=None, solver='lbfgs', tol=0.0001, verbose=0,warm_start=False)
'''
print("Training set score: {:.2f}".format(lr2.score(X_train, y_train)))
print("Testing set score: {:.2f}".format(lr2.score(X_test, y_test)))
#Training set score: 0.80
#Testing set score: 0.78

创建基于树的分类模型(决策树、随机森林)

# 默认参数的随机森林分类模型
rfc = RandomForestClassifier()
rfc.fit(X_train, y_train)
'''
RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,criterion='gini', max_depth=None, max_features='auto',max_leaf_nodes=None, max_samples=None,min_impurity_decrease=0.0, min_impurity_split=None,min_samples_leaf=1, min_samples_split=2,min_weight_fraction_leaf=0.0, n_estimators=100,n_jobs=None, oob_score=False, random_state=None,verbose=0, warm_start=False)
'''
print("Training set score: {:.2f}".format(rfc.score(X_train, y_train)))
print("Testing set score: {:.2f}".format(rfc.score(X_test, y_test)))
#Training set score: 1.00
#Testing set score: 0.83
# 调整参数后的随机森林分类模型
rfc2 = RandomForestClassifier(n_estimators=100, max_depth=5)
rfc2.fit(X_train, y_train)
'''
RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,criterion='gini', max_depth=5, max_features='auto',max_leaf_nodes=None, max_samples=None,min_impurity_decrease=0.0, min_impurity_split=None,min_samples_leaf=1, min_samples_split=2,min_weight_fraction_leaf=0.0, n_estimators=100,n_jobs=None, oob_score=False, random_state=None,verbose=0, warm_start=False)
'''
print("Training set score: {:.2f}".format(rfc2.score(X_train, y_train)))
print("Testing set score: {:.2f}".format(rfc2.score(X_test, y_test)))
#Training set score: 0.87
#Testing set score: 0.81

为什么线性模型可以进行分类任务,背后是怎么的数学关系?
基于逻辑回归的分类预测模型
对于多分类问题,线性模型是怎么进行分类的?

任务三:输出模型预测结果

#输出逻辑回归的预测结果
pred = lr.predict(X_train)
pred
'''
array([0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1,1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0,1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1,0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0,0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0,1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1,0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0,0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1,0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1,1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1,0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1,0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1,0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1,1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0,0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0,1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1,1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0,0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0,0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0,0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0,1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0,0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0,1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1,0, 0, 0, 0, 0, 0, 0, 0], dtype=int64)
'''
#输出随机森林的预测结果
rfc2.predict(X_train)
'''
array([0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1,1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1,0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0,1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0,0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1,0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1,1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0,1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1,0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0,0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0,1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0,1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0,1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0,1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0], dtype=int64)
'''
#逻辑回归与随机森林预测相同率
sum(rfc2.predict(X_train)==pred)/len(rfc2.predict(X_train)==pred)
#0.9026946107784432
#逻辑回归预测概率,第一列为预测为0的概率
pred_proba = lr.predict_proba(X_train)
pred_proba
'''
array([[0.5983501 , 0.4016499 ],[0.12785797, 0.87214203],[0.46238894, 0.53761106],...,[0.93827246, 0.06172754],[0.93993416, 0.06006584],[0.8815433 , 0.1184567 ]])
'''
#随机森林预测概率,,第一列为预测为0的概率
rfc.predict_proba(X_train)
array([[0.78, 0.22],[0.01, 0.99],[0.98, 0.02],...,[0.82, 0.18],[0.91, 0.09],[0.95, 0.05]])

预测标签的概率对我们有什么帮助?

  • 可用来调整正负案例切分点
  • 对于某些应用场景,如违约预测,输出的概率可以作为客户是好是坏的概率。

模型评估

模型评估的方法

K折交叉验证

交叉验证再前面部分已经有过介绍,现在具体来实现:

#导入交叉验证模块
from sklearn.model_selection import cross_val_score
'''
cross_val_score(estimator,X,y=None,groups=None,scoring=None,cv=None,n_jobs=None,verbose=0,fit_params=None,pre_dispatch='2*n_jobs',error_score=nan,
)
Docstring:
通过交叉验证评估分数在用户指南<cross_validation>中内容。参量
----------
estimator:实现“ fit”的估计器对象用于拟合数据的对象。
X:类似数组要拟合的数据。可以是例如列表或数组。
y:类似数组,可选,默认:无在以下情况下要尝试预测的目标变量监督学习。
groups:类数组,形状为(n_samples,),可选将数据集拆分为时使用的样本的标签分组训练/测试集。仅与“ Group”:term:`cv`结合使用实例(例如GroupKFold类)。
scoring:字符串,可调用或无,可选,默认:无字符串(请参阅模型评估文档)或带签名的计分员可调用对象/函数``scorer(estimator,X,y)``应该只返回一个值。类似于:cross_validate但只允许使用一个指标。如果为None,则使用估算器的默认计分器(如果有)。cv:int,交叉验证生成器或可迭代的,可选的确定交叉验证拆分策略。简历的可能输入是:-无,要使用默认的5倍交叉验证,-整数,用于指定“(分层)KFold”中的折叠次数,-:CV splitter`,-可迭代的屈服(训练,测试)拆分为索引数组。对于整数/无输入,如果估计量是分类器,而y是二进制或多类,都使用StraifiedKFold。在所有在其他情况下,使用KFold类。有关各种信息,请参考:用户指南<cross_validation>。可以在此处使用的交叉验证策略。..版本已更改:: 0.22如果无从3倍更改为5倍,则为cv默认值。n_jobs:int或None,可选(默认=无)用于进行计算的CPU数量。除非在:obj:`joblib.parallel_backend`上下文中,否则“ None``表示1。-1表示使用所有处理器。请参阅术语表<n_jobs>更多细节。verbose:整数,可选详细程度。fit_params:dict,可选传递给估算器的fit方法的参数。pre_dispatch:int或字符串,可选控制并行期间调度的作业数执行。减少此数字可能有助于避免调度更多作业时内存消耗激增比CPU可以处理的多该参数可以是:-无,在这种情况下,所有作业都将立即执行创建并产生。将此用于轻便和快速运行的作业,以避免因按需而造成的延迟产生工作-一个整数,给出确切的总职位数产生-字符串,根据n_jobs给出表达式,如“ 2 * n_jobs”error_score:“提高”或数字如果估算器拟合出现错误,则分配给分数的值。如果设置为“ raise”,则会引发错误。如果给出数值,则引发FitFailedWarning。这个参数不会影响改装步骤,因为它总是会引发错误。return
-------
scores:浮点数组,形状=(len(list(cv)),)每次交叉验证的估算器得分数组。
'''
#对逻辑回归进行交叉验证
scores = cross_val_score(lr, X_train, y_train, cv=10)
#array([0.8358209 , 0.7761194 , 0.82089552, 0.80597015, 0.85074627,
#       0.86567164, 0.73134328, 0.86567164, 0.75757576, 0.71212121])
print("Average cross-validation score: {:.2f}".format(scores.mean()))
#Average cross-validation score: 0.80
#随机森林进行交叉验证
scores1 = cross_val_score(rfc2, X_train, y_train, cv=10)
#array([0.85074627, 0.80597015, 0.85074627, 0.7761194 , 0.82089552,
#       0.8358209 , 0.76119403, 0.80597015, 0.74242424, 0.75757576])
print("Average cross-validation score1: {:.2f}".format(scores1.mean()))
#Average cross-validation score1: 0.80

混淆矩阵极其衍生指标

在分类任务中,模型的预测结果可以分为四类:

  • 真正类:True Positive,TP ,正类预测为正类
  • 假负类:False Negative ,FN,正类预测为负类
  • 假正类:False Positive,FP,负类预测为正类
  • 真负类:True Negative,TN,负类预测为负类

上述四类预测结果可以组成如下混淆矩阵:

混淆矩阵 样本正类Positive 样本负类Negative
预测正类True TP FP
预测负类False FN TN

由以上四个指标可以衍生出准确率、召回率、精确度,其中:
准确率(Accuracy),表示分类问题中,正确预测的占总体的百分比:
Accuracy=TP+TNTP+FP+FN+TNAccuracy=\cfrac{TP+TN}{TP+FP+FN+TN}Accuracy=TP+FP+FN+TNTP+TN​
召回率(Recall),表示正例中有多少能正确预测,也叫查全率:
Recall=TPTP+FNRecall=\cfrac{TP}{TP+FN}Recall=TP+FNTP​
精确度(Precision),表示预测为正例中实际是正例的比例:
Precision=TPTP+FPPrecision=\cfrac{TP}{TP+FP}Precision=TP+FPTP​
值得注意的是召回率(Recall)和精确度(Precision)是一对矛盾的度量,通常精确率高时召回率低,召回率高时精确率低。
还可定义P-R曲线:
在上一部分内容中,分类算法预测的结果如下:

其中第一列为预测为0的概率,第二列为预测为1的概率,我们可以选择其中一列,假如选择第一列,对预测结果进行降序排序,以当前概率阈值,大于该阈值的样本预测为正例(正例标签为0),逐个计算当前召回率和精确率。再以召回率横坐标精确率纵坐标,绘制各点连接成线。

P-R曲线可以直观的显示分类模型在总体样本上的精确率召回率,也可以对比多个分类模型的型内,从上图可以看出A模型优于B、C模型。图中的平衡点是精确率=召回率时各自的取值平衡点离原点越远越好

import  matplotlib.pyplot as plt
res1=pd.DataFrame(pred_proba[:,1],y_train)
res1.reset_index(inplace=True)
res1.columns=['y','y_prob']
res1.sort_values(by='y_prob',ascending=False,inplace=True)
def P_R(data):'''data中需要有y列和y_prob列'''def pred_value(data,yuzhi):data['y_pred'+str(yuzhi)]=data['y_prob'].map(lambda x: 1 if x>=yuzhi else 0)for i in data.y_prob:pred_value(data,i)def precision(y_true,y_pred):true_positive=sum(y and y_p for y,y_p in zip(y_true,y_pred))predicted_positive=sum(y_pred)return true_positive/predicted_positivedef recall(y_true,y_pred):true_positive=sum(y and y_p for y,y_p in zip(y_true,y_pred))real_positive=sum(y_true)return true_positive/real_positiveP=[]R=[]for i in data.columns[2:]:p=precision(data['y'],data[i])P.append(p)r=recall(data['y'],data[i])R.append(r)plt.plot(R,P,'b')plt.plot([0,1],[0,1],'k--')plt.xlabel("Recall Rate")plt.ylabel("Precision Rate")plt.title("P-R Curve")plt.show()
P_R(res1)

逻辑回归的P-R曲线如下:

res2=pd.DataFrame(rfc2.predict_proba(X_train)[:,1],y_train)
res2.reset_index(inplace=True)
res2.columns=['y','y_prob']
res2.sort_values(by='y_prob',ascending=False,inplace=True)
P_R(res2)

随机森林P_R曲线如下:

从上述两图可以看出随机森林模型效果优于逻辑回归模型效果。
第二种方法

#逻辑回归
from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds = precision_recall_curve(y_train, lr.predict_proba(X_train)[:,1])
def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):plt.plot(thresholds, precisions[: -1], "b--", label="Precision")plt.plot(thresholds, recalls[:-1], "g-", label = "Recall")plt.xlabel("Threshold")plt.legend(loc = "upper left")plt.ylim([0,1])plot_precision_recall_vs_threshold(precisions, recalls, thresholds)
plt.show()


可以看出在划分阈值为0.5左右时逻辑回归模型取得最优效果,此时精确率和召回率约为0.72

#随机森林
from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds = precision_recall_curve(y_train, rfc2.predict_proba(X_train)[:,1])
def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):plt.plot(thresholds, precisions[: -1], "b--", label="Precision")plt.plot(thresholds, recalls[:-1], "g-", label = "Recall")plt.xlabel("Threshold")plt.legend(loc = "upper left")plt.ylim([0,1])plot_precision_recall_vs_threshold(precisions, recalls, thresholds)
plt.show()


可以看出在划分阈值为0.4左右时随机森林模型取得最优效果,此时精确率和召回率约为0.8.

另外一种方法是比较平衡点,就是上图中红色虚线与蓝色实线交叉点,此时精确率等于召回率
有如下定义:
2F1=1P+1RF1=2TP2TP+FP+FN\cfrac{2}{F_1}=\cfrac{1}{P}+\cfrac{1}{R} \\ F_1=\cfrac{2TP}{2TP+FP+FN}F1​2​=P1​+R1​F1​=2TP+FP+FN2TP​

实例

逻辑回归混淆矩阵

from sklearn.metrics import confusion_matrix
'''
confusion_matrix(y_true,y_pred,labels=None,sample_weight=None,normalize=None,
)
参数
----------
y_true:形状类似数组的形状(n_samples,)基本事实(正确)目标值。y_pred:形状类似数组的形状(n_samples,)分类器返回的估计目标。labels:形状类似数组(n_classes),默认=无索引矩阵的标签列表。 这可以用来重新排序或选择标签的子集。如果给出``无'',则至少出现一次的那些y_true或y_pred中的字母按排序顺序使用。sample_weight:形状类似数组的形状(n_samples,),默认=无样品重量。normalize:{'true','pred','all'},默认=无在真实(行),预测(列)上标准化混淆矩阵条件或全部人口。 如果为None,则混淆矩阵将为标准化。return
-------
C:形状的ndarray(n_classes,n_classes)混淆矩阵。'''
confusion_matrix(y_train, lr.predict(X_train))
#array([[354,  58],
#       [ 72, 184]], dtype=int64)
import seaborn as sns
plt.figure(figsize=(8,6))
sns.heatmap(confusion_matrix(y_train, lr.predict(X_train)),annot=True,cmap='Blues')
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()


随机森林混淆矩阵

import seaborn as sns
plt.figure(figsize=(8,6))
sns.heatmap(confusion_matrix(y_train, rfc.predict(X_train)),annot=True,cmap='Blues')
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()

from sklearn.metrics import classification_report
#逻辑回归精确率、召回率、f1
print(classification_report(y_train, pred))
'''precision    recall  f1-score   support0       0.83      0.86      0.84       4121       0.76      0.72      0.74       256accuracy                           0.81       668macro avg       0.80      0.79      0.79       668
weighted avg       0.80      0.81      0.80       668
'''
#随机森林精确率、召回率、f1
print(classification_report(y_train, rfc2.predict(X_train)))
'''precision    recall  f1-score   support0       0.85      0.95      0.90       4121       0.90      0.74      0.81       256accuracy                           0.87       668macro avg       0.87      0.84      0.85       668
weighted avg       0.87      0.87      0.86       668
'''

ROC曲线

ROC曲线的横坐标是假正例率(FPR),纵坐标是真正例率(TPR),其中,TPR=TPTP+FN=正类的召回率FPR=FPTN+FP=1−负类召回率TPR=\cfrac{TP}{TP+FN}=正类的召回率 \\ FPR=\cfrac{FP}{TN+FP}=1-负类召回率TPR=TP+FNTP​=正类的召回率FPR=TN+FPFP​=1−负类召回率实践中可从sklearn.metrics调用roc_curve函数

#导入ROC曲线数据计算函数和AUC计算函数
from sklearn.metrics import roc_curve,roc_auc_score
#逻辑回归
fpr, tpr, thresholds = roc_curve(y_test, lr.decision_function(X_test))
auc=roc_auc_score(y_test, lr.decision_function(X_test))
plt.plot(fpr, tpr, label="ROC Curve")
plt.plot([0,1],[0,1],'k--')
plt.xlabel("FPR")
plt.ylabel("TPR (recall)")
plt.title("ROC Curve The AUC ={}".format(round(auc,2)))
# 找到最接近于0的阈值
close_zero = np.argmin(np.abs(thresholds))
plt.plot(fpr[close_zero], tpr[close_zero], 'o', markersize=10, label="threshold zero", fillstyle="none", c='k', mew=2)
plt.legend(loc=4)

#导入ROC曲线数据计算函数和AUC计算函数
from sklearn.metrics import roc_curve,roc_auc_score
#随机森林
#随机森林中没有decision_function函数直接用predict_proba替代,但thresholds无效
fpr, tpr, thresholds = roc_curve(y_test, rfc2.predict_proba(X_test)[:,1])
auc=roc_auc_score(y_test, rfc2.predict_proba(X_test)[:,1])
plt.plot(fpr, tpr, label="ROC Curve")
plt.plot([0,1],[0,1],'k--')
plt.xlabel("FPR")
plt.ylabel("TPR (recall)")
plt.title("ROC Curve The AUC ={}".format(round(auc,2)))
# 找到最接近于0的阈值
close_zero = np.argmin(np.abs(thresholds))
plt.plot(fpr[close_zero], tpr[close_zero], 'o', markersize=10, label="threshold zero", fillstyle="none", c='k', mew=2)
plt.legend(loc=4)

Datawhale数据分析课程第三章建模与评估相关推荐

  1. Datawhale数据分析课程第二章

    Datawhale数据分析课程第二章 准备工作 数据清洗及特征处理 相关定义 缺失值观察与处理 任务一:缺失值观察 (1) 请查看每个特征缺失值个数 (2) 请查看Age, Cabin, Embark ...

  2. 《Spark快速大数据分析》—— 第三章 RDD编程

    本文转自博客园xingoo的博客,原文链接:<Spark快速大数据分析>-- 第三章 RDD编程,如需转载请自行联系原博主.

  3. javascript进阶课程--第三章--匿名函数和闭包

    javascript进阶课程--第三章--匿名函数和闭包 一.总结 二.学习要点 掌握匿名函数和闭包的应用 三.匿名函数和闭包 匿名函数 没有函数名字的函数 单独的匿名函数是无法运行和调用的 可以把匿 ...

  4. Mysql系列课程--第三章 建表 插数据

    数据库模型图 /班级表/ CREATE TABLE `class` (`c_no` int(11) NOT NULL AUTO_INCREMENT,`c_name` varchar(45) NOT N ...

  5. 计算机第三章ppt课件ppt,计算机操作系统(大学课程)第三章幻灯片课件.ppt

    计算机操作系统(大学课程)第三章幻灯片课件.ppt 2.成组调度 应用程序A 应用程序B Cpu1 线程1 线程1 Cpu2 线程2 空闲 Cpu3 线程3 空闲 Cpu4 线程4 空闲 时间 1/2 ...

  6. Datawhale 202210 Excel | 第三章 快捷键操作示例 Excel快捷键列表

    Excel快捷键及快捷操作示例 1. 快捷键操作示例 1.1 自动插入求和公式 1.2 自动进行列差异比对 1.3 自动填充 需要提取客户的手机号 身份证号码中提取出生日期 2. 快捷键列表 常用 文 ...

  7. 百度Apollo智能驾驶进阶课程——第三章 百度Apollo定位技术

    无人车车辆定位技术入门与应用 1. 技术入门 1.1 什么是无人车自定位技术 1.2 为什么无人车需要一个精准的定位系统 1.3 定位技术的分类 2. 基础知识 2.1 三维几何变换 2.1.1 坐标 ...

  8. 3/14课程 第三章 结构化的项目前期和面向对象的项目前期实例

    ---恢复内容开始--- 3.1项目前期的主要工作 现状分析(硬件分析 软件分析) 需求收集 粗略设计(体系结构设计 硬件网络设计 应用系统设计 安全设计 配套设计) 可行性分析(经济可行性分析 技术 ...

  9. matlab 常用m文件,MATLAB基础课程 第三章 M文件知识(4)

    上堂课讲了if语句, 本堂课讲什么呢? 开始讲开关结构了. 注意事项!!! 与其他的程序设计语言(比如C语言)的switch-case语句不同的是,在MATLAB语言中,当其中一个case语句后的条件 ...

最新文章

  1. java date truncate_在Java中将dateTime转换为dd / mm / yy格式的日期
  2. CodeForces - 1220E Tourism(边双缩点+树形dp)
  3. 底部检测的do...while循环
  4. arp欺骗的软件有哪些_局域网内如何防止ARP欺骗
  5. ceph对象存储ceph-deploy部署记录
  6. 085 对象的绑定方法
  7. Mongodb 学习
  8. webservice的wsdl文件怎么生成
  9. python OJ 绝对值最大
  10. 中国区边界shp文件以及STRM 90m DEM分享(百度云免费下载链接)
  11. 银河麒麟Kylin_s10_sp3安装Oracle11g(FS)(官方补丁认证)(亲测有效)
  12. FreeRTOS原理剖析:空闲任务分析
  13. jn5168烧写方法
  14. #110-【我也不知道这是什么鬼算法】Ska Piggy Banks
  15. jzoj3094. Hash函数
  16. 牛客编程巅峰赛S1第3场 - 黄金钻石 A.简单题 B.dfs C.并查集
  17. RNN-循环神经网络-吴恩达读书笔记
  18. JavaEE12_EL和JSTL
  19. canvas制作在线画板
  20. 使用命令行下载VS2022离线安装文件

热门文章

  1. linux php扩展编译安装,Linux下单独编译安装PHP扩展包
  2. 【已解决】VS2019下载超慢的问题
  3. 中科软测试面试题2019_2019无锡中科软软件开发面试
  4. csdn ubb 炮炮兵表情自定义插件
  5. 北京验车地点与验车流程
  6. 码教授告诉你为什么你的#ppt做的就是没有吸引力#(转自码教授微博)
  7. Leetcode 1346:检查整数及其两倍数是否存在(超详细的解法!!!)
  8. python爬取京东机票,监控机票,机票价格分析
  9. php网上花店开题报告,《网上花店设计开题报告.doc
  10. HPH学习——使用PhpStorm自定义配置Apace 和PHP 环境