本记录为本人参加datawhale数据分析(泰坦尼克号任务项目)学习笔记,不足之处多多指教。
经过前面的两章的知识点的学习,我可以对数数据的本身进行处理,比如数据本身的增删查补,还可以做必要的清洗工作。那么下面我们就要开始使用我们前面处理好的数据了。这一章我们要做的就是使用数据,我们做数据分析的目的也就是,运用我们的数据以及结合我的业务来得到某些我们需要知道的结果。那么分析的第一步就是建模,搭建一个预测模型或者其他模型;我们从这个模型的到结果之后,我们要分析我的模型是不是足够的可靠,那我就需要评估这个模型。
导入相关库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from IPython.display import Image
这些库作用:
1、pandas是一个强大的分析结构化数据的工具集;它的使用基础是Numpy(提供高性能的矩阵运算);用于数据挖掘和数据分析,同时也提供数据清洗功能
2、 NumPy是Python中科学计算的基础包,是pandas使用基础
3、matplotib 是可视化库
4、 seaborn是基于Matplotlib的Python数据可视化库。它提供了一个高级界面,用于绘制引人入胜且内容丰富的统计图形
%matplotlib inline #内置可视化显示出来不需要在show
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
plt.rcParams['figure.figsize'] = (10, 6) # 设置输出图片大小
shape包含在numpy库,是矩阵(ndarray)的属性,可以获取矩阵的形状(例如二维数组的行列),获取的结果是一个元组
train = pd.read_csv('train.csv')
train.shape
#读取清洗过的数据集
data = pd.read_csv('clear_data.csv')
data.shape
模型搭建
- 处理完前面的数据我们就得到建模数据,下一步是选择合适模型
- 在进行模型选择之前我们需要先知道数据集最终是进行监督学习还是无监督学习
- 模型的选择一方面是通过我们的任务来决定的。
- 除了根据我们任务来选择模型外,还可以根据数据样本量以及特征的稀疏性来决定
- 刚开始我们总是先尝试使用一个基本的模型来作为其baseline,进而再训练其他模型做对比,最终选择泛化能力或性能比较好的模型
这里建模,并不是从零开始,自己一个人完成完成所有代码的编译。我们这里使用一个机器学习最常用的一个库(sklearn)来完成我们的模型的搭建。
划分数据集的方法有哪些?
常用三种:留出法 (hold-out) 交叉验证法(k fold cross validation) 自助法(bootstrapping)
1.留出法: 直接将数据集划分为两个互斥的集合, 分别作为训练集和测试集, 其中训练集一般是2/3 ~ 4/5
该方法两个注意点:
训练集和测试集的划分要尽可能的保持数据分布一致性,如分层采样(stratified sampling)
单次使用留出法的评估结果往往不够稳定和可靠,因此使用留出法时一般要采用若干次随机划分、重复进行试验评估取其平均值作为留出法的评估结果。缺点:若训练集包含了绝大多数的样本, 那么训练出的model更加接近于整个数据集训练出的结果, 但是测试集的数量少了,评估结果就不一定准确了。若测试集的数量较多的话,那么训练集与整个数据集差别较大,训练出的模型与整个数据集训练出的结果相差也较大,从而降低了评估结果的保真性(fidelity)。
2.交叉验证法(cross validation):将数据集划D分为k个大小相似的互斥子集, 每个子集尽量保证数据分布的一致性(用分层采样);每次用k-1个子集的并集作为训练集, 余下的那一个作为测试集,从而进行k次训练和测试,最终返回的是k个测试结果的均值。由于数据集存在多种划分方式, 为减小由于划分方式的不同而引入的差别,k着交叉验证通常要随机使用不同的划分方式重复p次, 最终的评估结果是p次k折交叉验证结果的均值。(常见的有10次10折交叉验证)
3.留一法(Leave-One-Out简称LOO)(cross validation 特例):假设数据集D包含m个样本,令k=m,显然留一发不再受随机样本划分方式的影响,因为留一法的训练数据集只比D少一个样本,训练出的模型与用D训练出的模型很相似,且评估结果也是测试了数据集D中所有的样本取得平均值,因此留一法的评估结果往往比较准确。但是留一法也有一个很大的缺陷就是计算量太大了, 若D有一百万个样本那么就需要训练一百万个模型。
4.自助法(bootstrapping): 给定包含m个样本的数据集D,我们对他进行采样产生D’:具体过程是:随机取一个样本放入D’中, 再将该样本放回到D中,使得该样本可以在下次采样时仍然可以被采到, 这个过程重复m次就得到了包含m个数据集的D’。
显然原始数据集D和D’并不完全一样,某样本被始终采不到的概率为(1-1/m)^m, 取其极限为0.368,即通过自助法原始数据集约有0.368左右的数据没有出现在D’中, 因此可以用D’作为训练集, D-D’作为测试集,这样的测试结果称为“包外估计”(out of bag estimate)
应用:自助法能从初始数据中产生多个不同的数据集,在数据集较小、难以划分训练集和测试集情况下很有用,对集成学习也有很大的好处,但也存在一定的问题,自助法改变了初始数据的分布,会引入估计偏差,一般在数据量足够的情况下交叉验证与留一法更加常用。
-
为什么使用分层抽样,这样的好处有什么?
先将总体的单位按某种特征分为若干次级总体(层),然后再从每一层内进行单纯随机抽样,组成一个样本。分层可以提高总体指标估计值的精确度,它可以将一个内部变异很大的总体分成一些内部变异较小的层(次总体)。每一层内个体变异越小越好,层间变异则越大越好。分层抽样比单纯随机抽样所得到的结果准确性更高,组织管理更方便,而且它能保证总体中每一层都有个体被抽到。这样除了能估计总体的参数值,还可以分别估计各个层内的情况,因此分层抽样技术常被采用。 -
切割数据集是为了后续能评估模型泛化能力
-
sklearn中切割数据集的方法为
train_test_split
-
查看函数文档可以在jupyter notebook里面使用
train_test_split?
后回车即可看到
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:可以为浮点、整数或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 = 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
- 什么情况下切割数据集的时候不用进行随机选取
在数据集本身已经是随机处理之后的,或者说数据集非常大,内部已经足够随机了
模型创建
- 创建基于线性模型的分类模型(逻辑回归)
- 创建基于树的分类模型(决策树、随机森林)
- 分别使用这些模型进行训练,分别的到训练集和测试集的得分
- 查看模型的参数,并更改参数值,观察模型变化
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
# 默认参数逻辑回归模型
lr = LogisticRegression()
lr.fit(X_train, y_train)
# 查看训练集和测试集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)))
# 调整参数后的逻辑回归模型
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)))
# 默认参数的随机森林分类模型
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)
print("Training set score: {:.2f}".format(rfc2.score(X_train, y_train)))
print("Testing set score: {:.2f}".format(rfc2.score(X_test, y_test)))
【思考】
- 为什么线性模型可以进行分类任务,背后是怎么的数学关系
基于线性回归的结果,进行离散化得到有限个分类结果
- 对于多分类问题,线性模型是怎么进行分类的
基于线性回归的结果,进行离散化得到有限个分类结果
输出模型预测结果
- 输出模型预测分类标签
- 输出不同分类标签的预测概率
- 一般监督模型在sklearn里面有个
predict
能输出预测标签,predict_proba
则可以输出标签概率
# 预测标签
pred = lr.predict(X_train)
# 此时我们可以看到0和1的数组
pred[:10]
# 预测标签概率
pred_proba = lr.predict_proba(X_train)
pred_proba[:10]
- 预测标签的概率对我们有什么帮助
能知道模型的准确性
模型搭建和评估-评估
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from IPython.display import Image
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
# 一般先取出X和y后再切割,有些情况会使用到未切割的,这时候X和y就可以用,x是清洗好的数据,y是我们要预测的存活数据'Survived'
data = pd.read_csv('clear_data.csv')
train = pd.read_csv('train.csv')
X = data
y = train['Survived']
# 对数据集进行切割
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=0)
# 默认参数逻辑回归模型
lr = LogisticRegression()
lr.fit(X_train, y_train)
模型评估
- 模型评估是为了知道模型的泛化能力。
- 交叉验证(cross-validation)是一种评估泛化性能的统计学方法,它比单次划分训练集和测试集的方法更加稳定、全面。
- 在交叉验证中,数据被多次划分,并且需要训练多个模型。
- 最常用的交叉验证是 k 折交叉验证(k-fold cross-validation),其中 k 是由用户指定的数字,通常取 5 或 10。
- 准确率(precision)度量的是被预测为正例的样本中有多少是真正的正例
- 召回率(recall)度量的是正类样本中有多少被预测为正类
- f-分数是准确率与召回率的调和平均
交叉验证
- 用10折交叉验证来评估之前的逻辑回归模型
- 计算交叉验证精度的平均值
- 交叉验证在sklearn中的模块为
sklearn.model_selection
from sklearn.model_selection import cross_val_score
lr = LogisticRegression(C=100)
scores = cross_val_score(lr, X_train, y_train, cv=10)
# k折交叉验证分数
scores
# 平均交叉验证分数
print("Average cross-validation score: {:.2f}".format(scores.mean()))
- k折越多的情况下会带来什么样的影响?
K折越多,单次训练验证时,用作训练集的数据就会越多,而用作验证集的数据越少。这样平均的结果会更加可靠,但是所耗费的总时间也会增多。
混淆矩阵
混淆矩阵(confusion matrix)衡量的是一个分类器分类的准确程度。
真阳性(True Positive,TP):样本的真实类别是正例,并且模型预测的结果也是正例
真阴性(True Negative,TN):样本的真实类别是负例,并且模型将其预测成为负例
假阳性(False Positive,FP):样本的真实类别是负例,但是模型将其预测成为正例
假阴性(False Negative,FN):样本的真实类别是正例,但是模型将其预测成为负例
主要运用
1)用于观察模型在各个类别上的表现,可以计算模型对应各个类别的准确率,召回率;
2)通过混淆矩阵可以观察到类别直接哪些不容易区分,比如A类别中有多少被分到了B类别,这样可以有针对性的设计特征等,使得类别更有区分性;
简单来说就是看看有多少错判的.
- 混淆矩阵的方法在sklearn中的
sklearn.metrics
模块 - 混淆矩阵需要输入真实标签和预测标签
- 精确率、召回率以及f-分数可使用
classification_report
模块
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))
ROC曲线
ROC的全名叫做Receiver Operating Characteristic,中文名字叫“受试者工作特征曲线”,其主要分析工具是一个画在二维平面上的曲线——ROC 曲线。平面的横坐标是false positive rate(FPR),纵坐标是true positive rate(TPR)。对某个分类器而言,我们可以根据其在测试样本上的表现得到一个TPR和FPR点对。
作用:
①很容易地查出任意界限值时的对疾病的识别能力。
②选择最佳的诊断界限值。
③用于两种或两种以上不同诊断试验对疾病识别能力的比较。
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)