通过前两章的学习,我们目前拥有的是经过清洗后的泰坦尼克号的数据集,那么我们这次的目的就是,完成泰坦尼克号存活预测这个任务。
载入我们提供清洗之后的数据(clear_data.csv),大家也将原始数据载入(train.csv),说说他们有什么不同
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from IPython.display import Image
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
data = pd.read_csv('clear_data.csv')
data
?
?不同在于:清洗之后的数据更简洁,而且数据的形式已经被转化为了计算机可以处理的形式。
模型搭建
- 处理完前面的数据我们就得到建模数据,下一步是选择合适模型
- 在进行模型选择之前我们需要先知道数据集最终是进行监督学习还是无监督学习
- 模型的选择一方面是通过我们的任务来决定的。
- 除了根据我们任务来选择模型外,还可以根据数据样本量以及特征的稀疏性来决定
- 刚开始我们总是先尝试使用一个基本的模型来作为其baseline,进而再训练其他模型做对比,最终选择泛化能力或性能比较好的模型
这里采用的是sklearn库?
# sklearn模型算法选择路径图
Image('sklearn.png')
?【思考】数据集哪些差异会导致模型在拟合数据是发生变化?
1、样本的数量 2、是否是分类问题 3、是否有已标记的数据 4、如果是分类问题,类别数目是否已知 5、是否是数量预测问题 6、数据是否只有少量的重要特征 7、是否要做结构分析
任务一:切割训练集和测试集
这里使用留出法划分数据集
- 将数据集分为自变量和因变量
- 按比例切割训练集和测试集(一般测试集的比例有30%、25%、20%、15%和10%)
- 使用分层抽样
- 设置随机种子以便结果能复现
思考
- 划分数据集的方法有哪些?
- 为什么使用分层抽样,这样的好处有什么?
?
#写入代码
from sklearn.model_selection import train_test_split
# 一般先取出X和y后再切割,有些情况会使用到未切割的
X=data
y=train['Survived']
# 对数据集进行切割
X_train,X_test,y_train,y_test=train_test_split(X,y,stratify=y,random_state=0)#stratify=y表示对y进行分层
# 查看数据形状
X_train.shape,X_test.shape
?
【思考】?
数据之间差别特别大的时候就不可以进行随机选取,否则会导致数据的预测存在重大误差
?
?
任务二:模型创建
- 创建基于线性模型的分类模型(逻辑回归)
- 创建基于树的分类模型(决策树、随机森林)
- 分别使用这些模型进行训练,分别的到训练集和测试集的得分
- 查看模型的参数,并更改参数值,观察模型变化
?模型一:逻辑回归
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
# 默认参数逻辑回归模型
lr=LogisticRegression()
lr.fit(X_train,y_train)
# 查看训练集和测试集score值
print("Testing set score: {:.2f}".format(lr.score(X_train, y_train)))
print("testing set score:{:.2f}".format(lr.score(X_test,y_test)))
?
# 调整参数后的逻辑回归模型
#C:float 默认:1.0 正则化强度, 与支持向量机一样,较小的值指定更强的正则化。
lr2=LogisticRegression(C=100)
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)))
?
?模型二:随机森林 随机森林本质上是许多以不同方式过拟合的决策树的集合,我们可以对这些互不相同的树的结果取平均值来降低过拟合,这样既能减少过拟合又能保持树的预测能力。 构造随机森林的步骤:
①确定用于构造的树的个数
②对数据进行自助采样
③基于新数据集构造决策树 n_estimators是构造的决策树的数量,n_estimators越大越好,但占用的内存与训练和预测的时间也会相应增长,且边际效益是递减的,所以要在可承受的内存/时间内选取尽可能大的n_estimators。而在sklearn中,n_estimators默认为10。 选取的特征子集中特征的个数通过max_features参数来控制,max_features越小,随机森林中的树就越不相同,但过小(取1时)会导致在划分时无法选择对哪个特征进行测试。 ?
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)
rfc2.fit(X_train, y_train)
# 查看训练集和测试集score值
print("Training set score: {:.2f}".format(rfc2.score(X_train, y_train)))
print("Testing set score: {:.2f}".format(rfc2.score(X_test, y_test)))
?
【思考】
- 为什么线性模型可以进行分类任务,背后是怎么的数学关系
- 对于多分类问题,线性模型是怎么进行分类的
线性回归是可以用来做分类任务的,只需要对结果设置一个阈值就可以进行分类。 对于多分类的问题,可以利用逻辑回归训练多个分类器,把其中一个当做一类,其他的作为一类
任务三:输出模型预测结果
?
pred=lr.predict(X_train)
pred[:10]
pred_proba=lr.predict_proba(X_train)
pred_proba[:10]
?
?思考:预测标签的概率对我们有什么帮助
可以让我们知道分类前的预测情况,并借此可以根据我们的需要改变分类的阈值
模型搭建和评估-评估
模型评估
- 模型评估是为了知道模型的泛化能力。
- 交叉验证(cross-validation)是一种评估泛化性能的统计学方法,它比单次划分训练集和测试集的方法更加稳定、全面。
- 在交叉验证中,数据被多次划分,并且需要训练多个模型。
- 最常用的交叉验证是 k 折交叉验证(k-fold cross-validation),其中 k 是由用户指定的数字,通常取 5 或 10。
- 准确率(precision)度量的是被预测为正例的样本中有多少是真正的正例
- 召回率(recall)度量的是正类样本中有多少被预测为正类
- f-分数是准确率与召回率的调和平均
任务一:交叉验证
- 用10折交叉验证来评估之前的逻辑回归模型
- 计算交叉验证精度的平均值
Image('Snipaste_2020-01-05_16-37-56.png') from sklearn.model_selection import cross_val_score
lr = LogisticRegression(C=100)
scores=cross_val_score(lr,X_train,y_train,cv=10)
scores
print("Average cross-validation score: {:.2f}".format(scores.mean())) ? ? ? 思考 - k折越多的情况下会带来什么样的影响?
数据有限,单一的把数据都用来做训练模型,容易导致过拟合。(反过来,如果数据足够多,完全可以不使用交叉验证。)较小的k值会导致可用于建模的数据量太小,所以小数据集的交叉验证结果需要格外注意,建议选择较大的k值.但较大的k值也意味着将耗用更多的内存和时间,所以原则上我们经常选择k值为10?
任务二:混淆矩阵
- 计算二分类问题的混淆矩阵
- 计算精确率、召回率以及f-分数
【思考】什么是二分类问题的混淆矩阵,理解这个概念,知道它主要是运算到什么任务中的?
混淆矩阵就是将预测的情况和实际情况结合在一起,总共有四种情况,分别为预测真-实际真,预测真-实际假,预测假-实际真,预测假-实际假,混淆矩阵经常用于评价模型预测结果的精确度。?
Image('Snipaste_2020-01-05_16-38-26.png')
?
?
#提示:准确率 (Accuracy),精确度(Precision),Recall,f-分数计算方法
Image('Snipaste_2020-01-05_16-39-27.png')
?
?
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
print(classification_report(y_train, pred))
?
?
?思考:
要确保你设置的混淆矩阵具有现实意义。?
任务三:ROC曲线
?思考:什么是OCR曲线,OCR曲线的存在是为了解决什么问题?
ROC的全名叫做Receiver Operating Characteristic,中文名字叫“受试者工作特征曲线”,其主要分析工具是一个画在二维平面上的曲线——ROC 曲线。 平面的横坐标是false positive rate(FPR),纵坐标是true positive rate(TPR)。对某个分类器而言,我们可以根据其在测试样本上的表现得到一个TPR和FPR点对。这样,此分类器就可以映射成ROC平面上的一个点。顾名思义,AUC的值就是处于ROC 曲线下方的那部分面积的大小。通常,AUC的值介于0.5到1.0之间,较大的AUC代表了较好的性能。AUC(Area Under roc Curve)是一种用来度量分类模型好坏的一个标准。
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)
?
思考
?对于多分类问题,ROC曲线的获取主要有两种方法:? 假设测试样本个数为m,类别个数为n。在训练完成后,计算出每个测试样本的在各类别下的概率或置信度,得到一个[m, n]形状的矩阵P,每一行表示一个测试样本在各类别下概率值(按类别标签排序)。相应地,将每个测试样本的标签转换为类似二进制的形式,每个位置用来标记是否属于对应的类别(也按标签排序,这样才和前面对应),由此也可以获得一个[m, n]的标签矩阵L。? ①方法一:每种类别下,都可以得到m个测试样本为该类别的概率(矩阵P中的列)。所以,根据概率矩阵P和标签矩阵L中对应的每一列,可以计算出各个阈值下的假正例率(FPR)和真正例率(TPR),从而绘制出一条ROC曲线。这样总共可以绘制出n条ROC曲线。最后对n条ROC曲线取平均,即可得到最终的ROC曲线。? ②方法二:? 首先,对于一个测试样本:1)标签只由0和1组成,1的位置表明了它的类别(可对应二分类问题中的‘’正’’),0就表示其他类别(‘’负‘’);2)要是分类器对该测试样本分类正确,则该样本标签中1对应的位置在概率矩阵P中的值是大于0对应的位置的概率值的。基于这两点,将标签矩阵L和概率矩阵P分别按行展开,转置后形成两列,这就得到了一个二分类的结果。所以,此方法经过计算后可以直接得到最终的ROC曲线。?
【思考】你能从这条OCR曲线的到什么信息?这些信息可以做什么?
roc曲线下方的面积明显大于0.5,我们可以得知该模型的分类结果很好。?
|