动手学数据分析(5)模型建立与评估

前面几个task分别学习了数据的加载,观察,探索性数据分析,数据清洗,特征值观察,数据的重构可视化等…今天就可以进入到数据建模部分的学习。
task5的任务分成了两个部分
数据建模

  • 了解数据建模
  • 使用sklearn完成分类模型的构建

模型评估

  • 了解模型评估
  • 使用sklearn完成模型评估

数据建模

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

任务大致可以分为三大类

任务对应算法
无监督学习k均值聚类、主成分分析、关联规则、社会网络分析
监督学习回归分析、k最近邻、支持向量机、决策树、随机森林、神经网络
强化学习多臂老虎机

什么是无监督学习?

  • 任务目标:指出数据中隐藏的模式。
    之所以称为无监督学习,是因为我们并不知道要找的模式是什么,而是要依靠算法从数据集中发现模式。
    什么是监督学习?
  • 任务目标:使用数据中的模式做预测
    他们的预测都基于已有的模式

什么是强化学习?

  • 任务目标:使用数据中的模式做预测,并根据越来越多的反馈结果不断改进。
    无监督学习和监督学习模型在部署之后便无法更改,不同于此,强化学习模型自身可以通过反馈结果不断改进。

本次建模使用的是sklearn,他是机器学习中一个很常用的库。

下面给出一个sklearn模型算法选择的路径图

# sklearn模型算法选择路径图
Image('sklearn.png')

在这里插入图片描述
通过这个图我们能够更清晰的知道我们进行数据分析时具体需要建一个什么样的模型。

建模的流程:

  1. 切割数据集
    在开始建模之前,还需要把数据集拆分为两个部分:训练集和测试集。在普通机器学习项目中至少需要包括这两个数据集,一个用于训练机器,确定模型。另一个用于测试模型的准确性。不仅如此还需要一个验证集,以在最终测试之前增加验证环节

【思考】划分数据集的方法有哪些?
对于数据集的划分有三种方法:留出法,交叉验证法和自助法

from sklearn.model_selection import train_test_split
# 一般先取出X和y后再切割,有些情况会使用到未切割的,这时候X和y就可以用,x是清洗好的数据,y是我们要预测的存活数据'Survived'
X = data
y = train['Survived']
# 对数据集进行切割
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=0)
# 查看数据形状
X_train.shape, X_test.shape

sklearn中的train_test_split函数,是机器学习中拆分数据集的常用工具。

参数作用
stratify依据标签y,按原数据y中各类比例,分配给train和test,使得train和test中各类数据的比例与原数据集一样
random_state用于数据集拆分过程的随机化设定。如果指定了一个整数,那么这个数叫做随机化种子,每次设定固定的种子能够保证得到同样的训练集和测试集,否则进行随机分割
train_data所要划分的样本特征集
train_target所要划分的样本结果
test_size样本占比,可以为浮点、整数或None,默认为None,若为浮点时,表示测试集占总样本的百分比,若为整数时,表示测试样本样本数,若为None时,test size自动设置成0.25
train_size可以为浮点、整数或None,默认为None,若为浮点时,表示训练集占总样本的百分比,若为整数时,表示训练样本的样本数,若为None时,train_size自动被设置成0.75

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

在数据集本身已经是随机处理之后的,或者说数据集非常大,内部已经足够随机,此时不需要进行随机选取。或者数据集是时序类型的,需要按照时间顺序来排列。

  1. 建立模型
    创建基于线性模型的分类模型
    最常见的两种线性分类算法是Logistic回归(logistic regression)和线性支持向量机(linear support vector machine,线性SVM)

给出一段示例代码:

from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC

X,y=mglearn.datasets.make_forge()

fig,axes=plt.subplots(1,2,figsize=(10,3))

for model,ax in zip([LinearSVC(),LogisticRegression()],axes):
    clf=model.fit(X,y)
    mglearn.plots.plot_2d_separator(clf,X,fill=False,eps=0.5,ax=ax,alpha=.7)
    
    mglearn.discrete_scatter(X[:,0],X[:,1],y,ax=ax)
    ax.set_title("{}".format(clf.__class__.__name__))
    ax.set_xlabel("Feature 0")
    ax.set_ylabel("Feature 1")
axes[0].legend()

打印测试集和训练集的分数

print("Training set score: {:.2f}".format(lr.score(X_train, y_train)))
print("Testing set score: {:.2f}".format(lr.score(X_test, y_test)))

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

from sklearn.model_selection import train_test_split  #从sklearn中导入适当的评估器类,选择模型类
Xtrain,Xtest,Ytrain,Ytest =train_test_split(wine.data,wine.target,test_size=0.3)  #实例化
clf=DecisionTreeClassifier(random_state=0)
rfc=RandomForestClassifier(random_state=0)
clf=clf.fit(Xtrain,Ytrain)    #调用模型的fit方法对数据进行拟合
rfc=rfc.fit(Xtrain,Ytrain)
score_c=clf.score(Xtest,Ytest)   #评估模型
score_r=rfc.score(Xtest,Ytest)
print("Single Tree:{}".format(score_c)
      ,"Random Forest:{}".format(score_r))

决策树分类模型极易过拟合,随机森林的基本思路就是把很多棵决策树的结果集成起来,避免过拟合,同时提高准确率。其中每一棵树都是在原始数据集当中抽取不同子集进行训练,这样做虽然单独的一棵决策树它的预测偏差可能会有小幅度增加,但是进行综合平均之后,模型性能会大大地提升。

参数作用
max_features默认为auto。“auto”/“sqrt”(总特征个数开平方取整),“log2”(总特征个数取对数取整)这个参数在决策树中也有其默认为None,即有多少特征用多少特征。
n_estimators决策树个数,默认100。
bootstrap每次构建树是否采用有放回样本的方式抽取数据集,默认为True。
oob_score是否使用袋外数据来评估模型,默认为False。
boostrap和 oob_score这两个参数一般要配合使用。如果boostrap是False,那么每次训练时都用整个数据集训练,如果boostrap是True,那么就会产生袋外数据。
max_samples构建每棵树需要抽取的最大样本数据量,默认为None
n_jobs:设定fit和predict阶段并列执行的CPU核数,如果设置为-1表示并行执行的任务数等于计算机核数。默认为None,即采用单核计算。
verbose控制构建数过程的冗长度,默认为0。
warm_start当设置为True,重新使用之前的结构去拟合样例并且加入更多的估计器(estimators,在这里就是随机树)到组合器中。默认为 False

关于调参:总结一下在sklearn中调参的思路:

① 基于泛化误差与模型复杂度的关系来进行调参;

② 根据对模型的影响程度,由大到小对参数排序,并确定哪些参数会使模型复杂度减小,哪些会增大;

③ 依次选择合适的参数,通过绘制学习曲线或网格搜索的方法调参,直到找到最大准确得分。

【思考】为什么线性模型可以进行分类任务,背后是怎么的数学关系?

逻辑回归主要用于分类,与我熟悉的线性回归模型相比,两个都是线性模型,线性回归是普通线性模型,逻辑回归是广义线性模型表达形式上,逻辑回归是线性回归套上了一个Sigmoid函数。线性回归假设响应变量服从正态分布,逻辑回归假设响应变量服从伯努利分布。同时,线性回归是根据最小二乘法求解模模型自变量的系数,而逻辑回归是根据似然函数。

【思考】对于多分类问题,线性模型是怎么进行分类的?

对于多分类而言,将多个二分类的逻辑回归组合,即可实现多分类

  1. 输出模预测结果
    一般监督模型在sklearn里面有个predict能输出预测标签,predict_proba则可以输出标签概率
# 预测标签
pred = lr.predict(X_train)
 # 此时我们可以看到0和1的数组
pred[:10]
 # 预测标签概率
pred_proba = lr.predict_proba(X_train)
 pred_proba[:10]

模型评估

建好模型之后必须对他进行评估。我们经常经常会使用一些评价指标来比较模型的预测准确度。对于如何定义和惩罚不同类型的预测误差,不同的评价指标各不相同。
最常用的几种评价指标:
分类指标:
接受者操作特征曲线下面积通常简称为曲线下面积,这个指标允许我们在最大化正例率和最小化假正率之间做权衡。

  • 正利率:被模型正确预测为正类别的样本所占的比例。
    正利率=正例数/(正例数+假负例数)

  • 假正利率:被模型错误预测为正类别的样本所占的比例。
    假正利率=假正例数/(假正例数+负例数)

这种权衡可以通过接受者操作特征曲线(ROC)曲线可视化。
最佳预测模型所对应的曲线下面积最大,因此可以借助其ROC曲线可以选择。

对于多分类问题如何绘制ROC曲线

from sklearn.metrics import roc_curve
#ROC曲线在sklearn中的模块为sklearn.metrics
fpr, tpr, thresholds = roc_curve(y_test, lr.decision_function(X_test))
plt.plot(fpr, tpr, label="ROC Curve")
plt.xlabel("FPR")
plt.ylabel("TPR (recall)")
# 找到最接近于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)

交叉验证

Image('Snipaste_2020-01-05_16-37-56.png')

交叉验证在sklearn中的模块为sklearn.model_selection

from sklearn.model_selection import cross_val_score

k折交叉验证分数

lr = LogisticRegression(C=100)
scores = cross_val_score(lr, X_train, y_train, cv=10)

平均交叉验证分数

print("Average cross-validation score: {:.2f}".format(scores.mean()))

混淆矩阵
在这里插入图片描述
在这里插入图片描述

from sklearn.metrics import confusion_matrix
# 训练模型
lr = LogisticRegression(C=100)
lr.fit(X_train, y_train)
pred = lr.predict(X_train)
# 混淆矩阵
confusion_matrix(y_train, pred)
from sklearn.metrics import classification_report
# 精确率、召回率以及f1-score
print(classification_report(y_train, pred))

总结

  • 一般情况下,都会用:K折交叉验证来分离数据集。
  • 数据量比较大,或者算法效率较低的情况下会考虑:分离训练数据集和评估数据
  • 平衡评估算法,模型训练的速度以及数据集的大小:弃一交叉验证和重复随机评估、训练集分离

最后再总结一下sklearn建模的流程:
数据获取——>数据预处理——>模型训练——>模型评估——>模型优化——>模型持久化

热门文章

暂无图片
编程学习 ·

那些年让我们目瞪口呆的bug

程序员一生与bug奋战,可谓是杀敌无数,见怪不怪了!在某知识社交平台中,一个“有哪些让程序员目瞪口呆的bug”的话题引来了6700多万的阅读,可见程序员们对一个话题的敏感度有多高。 1、麻省理工“只能发500英里的邮件” …
暂无图片
编程学习 ·

redis的下载与安装

下载redis wget http://download.redis.io/releases/redis-5.0.0.tar.gz解压redis tar -zxvf redis-5.0.0.tar.gz编译 make安装 make install快链方便进入redis ln -s redis-5.0.0 redis
暂无图片
编程学习 ·

《大话数据结构》第三章学习笔记--线性表(一)

线性表的定义 线性表:零个或多个数据元素的有限序列。 线性表元素的个数n定义为线性表的长度。n为0时,为空表。 在比较复杂的线性表中,一个数据元素可以由若干个数据项组成。 线性表的存储结构 顺序存储结构 可以用C语言中的一维数组来…
暂无图片
编程学习 ·

对象的扩展

文章目录对象的扩展属性的简洁表示法属性名表达式方法的name属性属性的可枚举性和遍历可枚举性属性的遍历super关键字对象的扩展运算符解构赋值扩展运算符AggregateError错误对象对象的扩展 属性的简洁表示法 const foo bar; const baz {foo}; baz // {foo: "bar"…
暂无图片
编程学习 ·

让程序员最头疼的5种编程语言

世界上的编程语言,按照其应用领域,可以粗略地分成三类。 有的语言是多面手,在很多不同的领域都能派上用场。大家学过的编程语言很多都属于这一类,比如说 C,Java, Python。 有的语言专注于某一特定的领域&…
暂无图片
编程学习 ·

写论文注意事项

参考链接 给研究生修改了一篇论文后,该985博导几近崩溃…… 重点分析 摘要与结论几乎重合 这一条是我见过研究生论文中最常出现的事情,很多情况下,他们论文中摘要部分与结论部分重复率超过70%。对于摘要而言,首先要用一小句话引…
暂无图片
编程学习 ·

安卓 串口开发

上图: 上码: 在APP grable添加 // 串口 需要配合在项目build.gradle中的repositories添加 maven {url "https://jitpack.io" }implementation com.github.licheedev.Android-SerialPort-API:serialport:1.0.1implementation com.jakewhart…
暂无图片
编程学习 ·

2021-2027年中国铪市场调研与发展趋势分析报告

2021-2027年中国铪市场调研与发展趋势分析报告 本报告研究中国市场铪的生产、消费及进出口情况,重点关注在中国市场扮演重要角色的全球及本土铪生产商,呈现这些厂商在中国市场的铪销量、收入、价格、毛利率、市场份额等关键指标。此外,针对…
暂无图片
编程学习 ·

Aggressive cows题目翻译

描述&#xff1a; Farmer John has built a new long barn, with N (2 < N < 100,000) stalls.&#xff08;John农民已经新建了一个长畜棚带有N&#xff08;2<N<100000&#xff09;个牛棚&#xff09; The stalls are located along a straight line at positions…
暂无图片
编程学习 ·

剖析组建PMO的6个大坑︱PMO深度实践

随着事业环境因素的不断纷繁演进&#xff0c;项目时代正在悄悄来临。设立项目经理转岗、要求PMP等项目管理证书已是基操&#xff0c;越来越多的组织开始组建PMO团队&#xff0c;大有曾经公司纷纷建造中台的气质&#xff08;当然两者的本质并不相同&#xff0c;只是说明这个趋势…
暂无图片
编程学习 ·

Flowable入门系列文章118 - 进程实例 07

1、获取流程实例的变量 GET运行时/进程实例/ {processInstanceId} /变量/ {变量名} 表1.获取流程实例的变量 - URL参数 参数需要值描述processInstanceId是串将流程实例的id添加到变量中。变量名是串要获取的变量的名称。 表2.获取流程实例的变量 - 响应代码 响应码描述200指…
暂无图片
编程学习 ·

微信每天自动给女[男]朋友发早安和土味情话

微信通知&#xff0c;每天给女朋友发早安、情话、诗句、天气信息等~ 前言 之前逛GitHub的时候发现了一个自动签到的小工具&#xff0c;b站、掘金等都可以&#xff0c;我看了下源码发现也是很简洁&#xff0c;也尝试用了一下&#xff0c;配置也都很简单&#xff0c;主要是他有一…
暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法&#xff0c;在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较&#xff0c;从而确定目标数是在中间数的左边还是右边&#xff0c;将查…
暂无图片
编程学习 ·

项目经理,你有什么优势吗?

大侠被一个问题问住了&#xff1a;你和别人比&#xff0c;你的优势是什么呢? 大侠听到这个问题后&#xff0c;脱口而出道&#xff1a;“项目管理能力和经验啊。” 听者抬头看了一下大侠&#xff0c;显然听者对大侠的这个回答不是很满意&#xff0c;但也没有继续追问。 大侠回家…
暂无图片
编程学习 ·

nginx的负载均衡和故障转移

#注&#xff1a;proxy_temp_path和proxy_cache_path指定的路径必须在同一分区 proxy_temp_path /data0/proxy_temp_dir; #设置Web缓存区名称为cache_one&#xff0c;内存缓存空间大小为200MB&#xff0c;1天没有被访问的内容自动清除&#xff0c;硬盘缓存空间大小为30GB。 pro…
暂无图片
编程学习 ·

业务逻辑漏洞

身份认证安全 绕过身份认证的几种方法 暴力破解 测试方法∶在没有验证码限制或者一次验证码可以多次使用的地方&#xff0c;可以分为以下几种情况︰ (1)爆破用户名。当输入的用户名不存在时&#xff0c;会显示请输入正确用户名&#xff0c;或者用户名不存在 (2)已知用户名。…