第三章 模型搭建和评估–建模
经过前面的两章的知识点的学习,我可以对数数据的本身进行处理,比如数据本身的增删查补,还可以做必要的清洗工作。那么下面我们就要开始使用我们前面处理好的数据了。这一章我们要做的就是使用数据,我们做数据分析的目的也就是,运用我们的数据以及结合我的业务来得到某些我们需要知道的结果。那么分析的第一步就是建模,搭建一个预测模型或者其他模型;我们从这个模型的到结果之后,我们要分析我的模型是不是足够的可靠,那我就需要评估这个模型。
我们拥有的泰坦尼克号的数据集,那么我们这次的目的就是,完成泰坦尼克号存活预测这个任务。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from IPython.display import Image
%matplotlib inline
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('train.csv')
data.head()
#写入代码
# 清洗数据
df=pd.read_csv('clear_data.csv')
df.head()
#写入代码
df.shape
# (891, 11)
模型搭建
- 处理完前面的数据我们就得到建模数据,下一步是选择合适模型
- 在进行模型选择之前我们需要先知道数据集最终是进行监督学习还是无监督学习
- 模型的选择一方面是通过我们的任务来决定的。
- 除了根据我们任务来选择模型外,还可以根据数据样本量以及特征的稀疏性来决定
- 刚开始我们总是先尝试使用一个基本的模型来作为其baseline,进而再训练其他模型做对比,最终选择泛化能力或性能比较好的模型
这里我的建模,并不是从零开始,自己一个人完成完成所有代码的编译。我们这里使用一个机器学习最常用的一个库(sklearn)来完成我们的模型的搭建。
下面给出sklearn的算法选择路径,供大家参考
sklearn模型算法选择路径图
【思考】 数据集哪些差异会导致模型在拟合数据是发生变化
思考回答
- 样本数量
- 是否是分类问题
- 数据是否有标记
- 数据特征维度
任务一:切割训练集和测试集
这里使用留出法划分数据集
- 将数据集分为自变量和因变量
- 按比例切割训练集和测试集(一般测试集的比例有30%、25%、20%、15%和10%)
- 使用分层抽样
- 设置随机种子以便结果能复现
划分数据集的方法有哪些?
留出法(Hold-out)、交叉验证法(Cross validation)、自助法(Bootstrapping)
对于数据量充足的时候,通常采用 留出法 或者 k折交叉验证法 来进行训练/测试集的划分;
对于数据集小且难以有效划分训练/测试集时使用 自助法;
对于数据集小且可有效划分的时候最好使用 留一法 来进行划分
为什么使用分层抽样,这样的好处有什么?
(A)当一个总体其内部分层明显时,分层抽样能够克服简单随机抽样的缺点。由于它是按群体的特征分布从不同层获得尽可能均衡的样本数,使样本与总体更相似。
(B)分层抽样可以提高样本推断总体的精确度。
(C)便于了解某些特定类别和对不同属性的群体进行分析比较。
(D)使大规模抽样变得较为容易,便于调查过程的行政管理。
提示1
- 切割数据集是为了后续能评估模型泛化能力
- sklearn中切割数据集的方法为
train_test_split
- 查看函数文档可以在jupyter notebook里面使用
train_test_split?
后回车即可看到 - 分层和随机种子在参数里寻找
要从clear_data.csv和train.csv中提取train_test_split()所需的参数
在机器学习中,我们通常将原始数据按照比例分割为“测试集”和“训练集”,从 sklearn.model_selection 中调用train_test_split 函数
简单用法如下:
X_train,X_test, y_train, y_test =sklearn.model_selection.train_test_split(train_data,train_target,test_size=0.4, random_state=0,stratify=y_train)
-
train_data:所要划分的样本特征集
-
train_target:所要划分的样本结果
-
test_size:样本占比,如果是整数的话就是样本的数量
-
random_state:是随机数的种子。随机数种子:其实就是该组随机数的编号,在需要重复试验的时候,保证得到一组一样的随机数。比如你每次都填1,其他参数一样的情况下你得到的随机数组是一样的。但填0或不填,每次都会不一样。
-
stratify是为了保持split前类的分布。比如有100个数据,80个属于A类,20个属于B类。如果train_test_split(… test_size=0.25, stratify = y_all), 那么split之后数据如下:
- training: 75个数据,其中60个属于A类,15个属于B类。
- testing: 25个数据,其中20个属于A类,5个属于B类。
用了stratify参数,training集和testing集的类的比例是 A:B= 4:1,等同于split前的比例(80:20)。通常在这种类分布不平衡的情况下会用到stratify。
将stratify=X就是按照X中的比例分配
将stratify=y就是按照y中的比例分配
整体总结起来各个参数的设置及其类型如下:
主要参数说明:
*arrays:可以是列表、numpy数组、scipy稀疏矩阵或pandas的数据框
test_size:可以为浮点、整数或None,默认为None
①若为浮点时,表示测试集占总样本的百分比
②若为整数时,表示测试样本样本数
③若为None时,test size自动设置成0.25
train_size:可以为浮点、整数或None,默认为None
①若为浮点时,表示训练集占总样本的百分比
②若为整数时,表示训练样本的样本数
③若为None时,train_size自动被设置成0.75
random_state:可以为整数、RandomState实例或None,默认为None
①若为None时,每次生成的数据都是随机,可能不一样
②若为整数时,每次生成的数据都相同
stratify:可以为类似数组或None
①若为None时,划分出来的测试集或训练集中,其类标签的比例也是随机的
②若不为None时,划分出来的测试集或训练集中,其类标签的比例同输入的数组中类标签的比例相同,可以用于处理不均衡的数据集
#写入代码
from sklearn.model_selection import train_test_split
#写入代码
# 一般先取出X和y后再切割,有些情况会使用到未切割的,这时候X和y就可以用,x是清洗好的数据,y是我们要预测的存活数据'Survived'
x=df
y=data['Survived']
#写入代码
x_train,x_test,y_train,y_test=train_test_split(x,y,stratify=y,test_size=0.3,random_state=0)
#写入代码
x_train.shape,x_test.shape
# x_train=891*0.7
# x_test=891*0.3
【思考】
什么情况下切割数据集的时候不用进行随机选取
思考回答
在数据集本身已经是随机处理之后的,或者说数据集非常大,内部已经足够随机了
任务二:模型创建
- 创建基于线性模型的分类模型(逻辑回归)
- 创建基于树的分类模型(决策树、随机森林)
- 分别使用这些模型进行训练,分别的到训练集和测试集的得分
- 查看模型的参数,并更改参数值,观察模型变化
提示2
- 逻辑回归不是回归模型而是分类模型,不要与
LinearRegression
混淆 - 随机森林其实是决策树集成为了降低决策树过拟合的情况
- 线性模型所在的模块为
sklearn.linear_model
- 树模型所在的模块为
sklearn.ensemble
#写入代码
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
#写入代码
# 默认参数逻辑回归模型
lr = LogisticRegression()
lr.fit(x_train, y_train)
#写入代码
# 查看训练集和测试集score值 作用:返回该次预测的系数R2 最好是1
print("Training set score: {:.2f}".format(lr.score(x_train, y_train)))
print("Testing set score: {:.2f}".format(lr.score(x_test, y_test)))
#写入代码
# 调整参数后的逻辑回归模型
# 参数参考:https://blog.csdn.net/jark_/article/details/78342644
lr2 = LogisticRegression(C=100) # C是正则化系数λ的倒数,float类型,默认为1.0。必须是正浮点型数。像SVM一样,越小的数值表示越强的正则化。
lr2.fit(x_train, y_train)
print("Training set score: {:.2f}".format(lr2.score(x_train, y_train)))
print("Testing set score: {:.2f}".format(lr2.score(x_test, y_test)))
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ni6btWcx-1629888381126)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b46f34c721c049b08e331e1f96c36c09~tplv-k3u1fbpfcp-watermark.image)]
# 默认参数的随机森林分类模型
rfc = RandomForestClassifier()
rfc.fit(x_train, y_train)
print("Training set score: {:.2f}".format(rfc.score(x_train, y_train)))
print("Testing set score: {:.2f}".format(rfc.score(x_test, y_test)))
# 调整参数后的随机森林分类模型
rfc2 = RandomForestClassifier(n_estimators=100, max_depth=5)
# n_estimators : integer, optional (default=10) 整数,可选择(默认值为10)。森林里(决策)树的数目。
# max_depth : integer or None, optional (default=None) 整数或者无值,可选的(默认为None)(决策)树的最大深度。如果值为None,那么会扩展节点,直到所有的叶子是纯净的,或者直到所有叶子包含少于min_sample_split的样本。
rfc2.fit(x_train, y_train)
print("Training set score: {:.2f}".format(rfc2.score(x_train, y_train)))
print("Testing set score: {:.2f}".format(rfc2.score(x_test, y_test)))
任务三:输出模型预测结果
- 输出模型预测分类标签
- 输出不同分类标签的预测概率
提示3
- 一般监督模型在sklearn里面有个
predict
能输出预测标签,predict_proba
则可以输出标签概率
#写入代码
pre=lr.predict(x_train)
#写入代码
pre[:10]
#写入代码
pre_proda=lr.predict_proba(x_train)
#写入代码
pre_proda[:10]
【思考】 预测标签的概率对我们有什么帮助
预测标签的概率能够让我们判断该标签的可信度,越接近1的话可信度越高