datawhale数据分析5——数据可视化数据建模及模型评估

Task05:数据建模及模型评估

声明:本文主要参考DataWhale开源学习——动手学数据分析,GitHub地址:https://github.com/datawhalechina/hands-on-data-analysis

#第一步依旧是准备工作导入库,数据
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
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)  # 设置输出图片大小
train = pd.read_csv('train.csv')
train.shape
(891, 12)

【思考】这些库的作用是什么呢?你需要查一查

【思考题回答】numpy,matplotlib,pandas是数据分析的三大基本库。

       seaborn是在Matplotlib的基础上进行了更高级的API封装,因此可以进行更复杂的图形设计和输出的库。

       %matplotlib inline:将matplotlib的图表直接嵌入到Notebook中。

一.特征工程

特征工程是整个机器学习中非常重要的一部分,如何对数据进行特征提取对最终结果的影响非常大。在建模过程中,一般会优先考虑算法和参数,但是数据特征才决定了整体结果的上限,而算法和参数只决定了如何逼近这个上限。特征工程其实就是要从原始数据中找到最有价值的信息,并转换成计算机所能读懂的形式。

1.1 任务一:缺失值填充

缺失值填充方法:

  • 对分类变量缺失值:填充某个缺失值字符(NA)、用最多类别的进行填充
  • 对连续变量缺失值:填充均值、中位数、众数
# 对分类变量进行填充
train['Cabin'] = train['Cabin'].fillna('NA')
train['Embarked'] = train['Embarked'].fillna('S')
# 对连续变量进行填充
train['Age'] = train['Age'].fillna(round(train['Age'].mean())) #年龄一般为整数,故加个四舍五入函数
# 检查缺失值比例
train.isnull().sum().sort_values(ascending=False)
Embarked       0
Cabin          0
Fare           0
Ticket         0
Parch          0
SibSp          0
Age            0
Sex            0
Name           0
Pclass         0
Survived       0
PassengerId    0
dtype: int64

1.2 任务二:编码分类变量

这里采用pd.get_dummies()函数进行虚拟变量转换,get_dummies是利用pandas实现one hot encode的方式。

  • 官方文档:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.get_dummies.html
#train.head()
# 取出所有的输入特征
data = train[['Pclass','Sex','Age','SibSp','Parch','Fare', 'Embarked']]
# 进行虚拟变量转换
data = pd.get_dummies(data)
data.head()
PclassAgeSibSpParchFareSex_femaleSex_maleEmbarked_CEmbarked_QEmbarked_S
0322.0107.250001001
1138.01071.283310100
2326.0007.925010001
3135.01053.100010001
4335.0008.050001001

二.模型搭建

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

我们这里使用一个机器学习最常用的一个库(sklearn)来完成我们的模型的搭建

官网:https://scikit-learn.org/stable/

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

在这里插入图片描述

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

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

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

【思考】

  • 划分数据集的方法有哪些?
  • 为什么使用分层抽样,这样的好处有什么?

【思考回答】

  • 划分数据集的方法:留出法,交叉验证法,自助法。参考:https://blog.csdn.net/weixin_38753213/article/details/112690712
  • 分层采用好处:1.当一个总体内部分层明显时,分层抽样能够提高样本的代表性;2.分层抽样特别适用于既要对总体参数进行推断,也要对各子总体的参数进行推断的情形;3.分层抽样实施起来灵活方便,而且便于组织。

任务提示1

  • 切割数据集是为了后续能评估模型泛化能力
  • sklearn中切割数据集的方法为train_test_split
  • 查看函数文档可以在jupyter notebook里面使用train_test_split?后回车即可看到
  • 分层和随机种子在参数里寻找
from sklearn.model_selection import train_test_split
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
((668, 10), (223, 10))

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

【思考回答】数据在进行切割前已经进行过切割处理的或数据集本身非常大的情况。

2.2 任务二:模型创建

  • 创建基于线性模型的分类模型(逻辑回归)
  • 创建基于树的分类模型(决策树、随机森林)
  • 分别使用这些模型进行训练,分别的到训练集和测试集的得分
  • 查看模型的参数,并更改参数值,观察模型变化
提示2
  • 逻辑回归不是回归模型而是分类模型,不要与LinearRegression混淆
  • 随机森林其实是决策树集成为了降低决策树过拟合的情况
  • 线性模型所在的模块为sklearn.linear_model
  • 树模型所在的模块为sklearn.ensemble
2.2.1 逻辑回归

逻辑回归不是回归模型而是分类模型,在sklearn.linear_model中,需要调节参数C(正则化系数)

  • 正则化是机器学习中的概念,具体可参考西瓜书或其它机器学习相关资料,举个例子简单来说,如果训练集有n个样本,那么一定可以通过一个n-1阶函数完美拟合这些点,使得样本在训练集中的准确率是100%,但是这个模型的泛化能力很差,在测试集上效果就不好了。正则化惩罚就是通过惩罚高阶项解决过拟合问题从而提高模型的泛化能力。
from sklearn.linear_model import LogisticRegression
#采用默认参数
lr = LogisticRegression()
lr.fit(X_train,y_train)
print('训练集得分:{:.2f}'.format(lr.score(X_train,y_train)))
print('测试集得分:{:.2f}'.format(lr.score(X_test,y_test)))
训练集得分:0.80
测试集得分:0.78
# 调整参数后的逻辑回归模型
lr2 = LogisticRegression(C=100)
lr2.fit(X_train, y_train)
print('训练集得分:{:.2f}'.format(lr2.score(X_train,y_train)))
print('测试集得分:{:.2f}'.format(lr2.score(X_test,y_test)))
训练集得分:0.80
测试集得分:0.79
2.2.2 随机森林

随机森林是集成学习中的一种算法,通过并行训练一堆决策树来各自独立地学习和作出预测。这些预测最后结合成单预测,因此优于任何一个单分类的做出预测。

可参考:https://blog.csdn.net/yangyin007/article/details/82385967

这里采用sklearn.emsemble模块,主要调节n_estimateorsmax_depth

  • n_estimateors:决策树的个数,数量太少欠拟合,数量太多过拟合
  • max_depth:决策树的最大深度,同样深度太浅欠拟合,深度太深过拟合
from sklearn.ensemble import RandomForestClassifier
#采用默认参数
rfc = RandomForestClassifier()
rfc.fit(X_train,y_train)
print('训练集得分:{:.2f}'.format(rfc.score(X_train,y_train)))
print('测试集得分:{:.2f}'.format(rfc.score(X_test,y_test)))
训练集得分:0.97
测试集得分:0.82
#调整参数
rfc2 = RandomForestClassifier(n_estimators=80, max_depth=5)
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)))
Training set score: 0.86
Testing set score: 0.83

【思考】

  • 为什么线性模型可以进行分类任务,背后是怎么的数学关系
  • 对于多分类问题,线性模型是怎么进行分类的

【思考回答】

  • 通过一个线性平面将数据进行分隔,分为平面以上和平面以下数据,实现二分类
  • 两个想法:1.通过点距离平面的远近进行分类;2.转化为多个二分类问题求解。

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

  • 输出模型预测分类标签
  • 输出不同分类标签的预测概率
提示3
  • 一般监督模型在sklearn里面有个predict能输出预测标签,predict_proba则可以输出标签概率
#预测标签
lr_predict = lr.predict(X_train)
lr_predict[:10]
array([0, 1, 1, 1, 0, 0, 1, 0, 1, 1], dtype=int64)
#预测概率
lr_pre = lr.predict_proba(X_train)
lr_pre[:10]
array([[0.62834351, 0.37165649],
       [0.14872739, 0.85127261],
       [0.47129261, 0.52870739],
       [0.20331331, 0.79668669],
       [0.86395534, 0.13604466],
       [0.90416819, 0.09583181],
       [0.13796589, 0.86203411],
       [0.89506733, 0.10493267],
       [0.05712809, 0.94287191],
       [0.13565136, 0.86434864]])

【思考】

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

【思考回答】

  • 我们可以根据自己的需求,调节阈值从而得到我们想要的分类结果。

三.模型评估

  • 模型评估是为了知道模型的泛化能力。
  • 交叉验证(cross-validation)是一种评估泛化性能的统计学方法,它比单次划分训练集和测试集的方法更加稳定、全面。
  • 在交叉验证中,数据被多次划分,并且需要训练多个模型。
  • 最常用的交叉验证是 k 折交叉验证(k-fold cross-validation),其中 k 是由用户指定的数字,通常取 5 或 10。
  • 准确率(precision)度量的是被预测为正例的样本中有多少是真正的正例
  • 召回率(recall)度量的是正类样本中有多少被预测为正类
  • f-分数是准确率与召回率的调和平均

3.1 任务一:交叉验证

  • 用10折交叉验证来评估之前的逻辑回归模型
  • 计算交叉验证精度的平均值

可参考:https://blog.csdn.net/tianguiyuyu/article/details/80697223

在这里插入图片描述

提示4
  • 交叉验证在sklearn中的模块为sklearn.model_selection
from sklearn.model_selection import cross_val_score
lr = LogisticRegression()
score = cross_val_score(lr,X_train,y_train,cv=10)
score.mean()
0.7977425705696117
  • 【思考】k折越多的情况下会带来什么样的影响?
  • 【思考回答】会导致测试集的样本减少,最终score的方差会加大

3.2 任务二:混淆矩阵

  • 计算二分类问题的混淆矩阵

  • 计算精确率、召回率以及f-分数

  • 【思考】什么是二分类问题的混淆矩阵,理解这个概念,知道它主要是运算到什么任务中的

  • 【思考回答】混淆矩阵是一个二维方阵,包含四个情况:
    真实值是positive,模型认为是positive的数量(True Positive=TP)
    真实值是positive,模型认为是negative的数量(False Negative=FN):这就是统计学上的第二类错误
    真实值是negative,模型认为是positive的数量(False Positive=FP):这就是统计学上的第一类错误
    真实值是negative,模型认为是negative的数量(True Negative=TN)

在这里插入图片描述

在这里插入图片描述

提示5
  • 混淆矩阵的方法在sklearn中的sklearn.metrics模块
  • 混淆矩阵需要输入真实标签和预测标签
  • 精确率、召回率以及f-分数可使用classification_report模块
from sklearn.metrics import confusion_matrix
# 训练模型
lr = LogisticRegression()
lr.fit(X_train, y_train)
pred = lr.predict(X_train)
#计算混淆矩阵
cnf_matrix = confusion_matrix(y_train,pred)
def plot_confusion_matrix(cm, classes,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    """
    This function prints and plots the confusion matrix.
    """
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=0)
    plt.yticks(tick_marks, classes)

    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, cm[i, j],
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
# 画混淆矩阵
import itertools
class_names = [0,1]
plt.figure()
plot_confusion_matrix(cnf_matrix
                      , classes=class_names
                      , title='Confusion matrix')
plt.show()

在这里插入图片描述

from sklearn.metrics import classification_report
# 精确率、召回率以及f1-score
print(classification_report(y_train, pred))
             precision    recall  f1-score   support

          0       0.83      0.86      0.84       412
          1       0.76      0.71      0.74       256

avg / total       0.80      0.80      0.80       668

3.3 任务三:ROC曲线

  • 绘制ROC曲线
  • 【思考】什么是ROC曲线,OCR曲线的存在是为了解决什么问题?
  • 【思考回答】https://blog.csdn.net/zhaomengszu/article/details/72471474
提示6
  • ROC曲线在sklearn中的模块为sklearn.metrics
  • ROC曲线下面所包围的面积越大越好
from sklearn.metrics import roc_curve
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)
<matplotlib.legend.Legend at 0x1bb2a9b4b00>

在这里插入图片描述

  • 【问题】对于多分类问题如何绘制ROC曲线
  • 【问题回答】https://blog.csdn.net/xyz1584172808/article/details/81839230
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值