网站设置快捷方式,网站建设业务员的话术,云朵课堂网站开发怎么收费,杭州建设网站平台的哪些企业比较好目录
第一章 - 数据科学家如何战胜困难第二章 - 数据科学框架第三章 - 步骤1#xff1a;定义问题和步骤2#xff1a;收集数据第四章 - 步骤3#xff1a;准备数据第五章 - 数据清洗的4个C#xff1a;纠正、补全、创建和转换第六章 - 步骤4#xff1a;使用统计学进行探索性…目录
第一章 - 数据科学家如何战胜困难第二章 - 数据科学框架第三章 - 步骤1定义问题和步骤2收集数据第四章 - 步骤3准备数据第五章 - 数据清洗的4个C纠正、补全、创建和转换第六章 - 步骤4使用统计学进行探索性分析第七章 - 步骤5建立模型第八章 - 评估模型性能第九章 - 使用超参数调整模型第十章 - 使用特征选择调整模型第十一章 - 步骤6验证和实施第十二章 - 结论和步骤7优化和战略 数据科学家如何战胜机遇
这是一个经典问题预测二元事件的结果。通俗地说这意味着它要么发生了要么没有发生。例如你赢了或者没有赢你通过了考试或者没有通过考试你被接受或者没有被接受你懂的。一个常见的商业应用是流失或客户保留。另一个流行的用例是医疗保健的死亡率或生存分析。二元事件创造了一个有趣的动态因为我们知道统计上一个随机猜测应该达到50%的准确率而不需要创建一个算法或编写一行代码。然而就像自动纠正拼写技术一样有时我们人类可以太聪明了实际上表现不如硬币翻转。在这个内核中我使用Kaggle的入门竞赛泰坦尼克号从灾难中学习机器学习向读者介绍如何使用数据科学框架来战胜机遇。
当技术太聪明而超出我们的控制时会发生什么 一个数据科学框架
定义问题 如果数据科学、大数据、机器学习、预测分析、商业智能或其他流行词是解决方案那么问题是什么俗话说不要把马车放在马前面。问题在需求之前需求在解决方案之前解决方案在设计之前设计在技术之前。我们经常在确定要解决的实际问题之前就急于采用新的闪亮技术、工具或算法。收集数据 约翰·奈斯比特在他1984年的书《大趋势》中写道我们“淹没在数据中却渴望知识。”所以很有可能数据集已经存在于某个地方以某种格式存在。它可以是外部的或内部的结构化的或非结构化的静态的或流式的客观的或主观的等等。俗话说你不必重新发明轮子你只需要知道在哪里找到它。在下一步中我们将关注如何将“脏数据”转化为“干净数据”。准备数据以供使用 这一步通常被称为数据整理是将“野生”数据转化为“可管理”数据的必要过程。数据整理包括为存储和处理实施数据架构制定数据治理标准以确保质量和控制进行数据提取即ETL和网络抓取以及进行数据清洗以识别异常、缺失或异常值数据点。进行探索性分析 任何与数据打过交道的人都知道垃圾进垃圾出GIGO。因此部署描述性和图形统计来寻找数据集中的潜在问题、模式、分类、相关性和比较非常重要。此外数据分类即定性与定量对于理解和选择正确的假设检验或数据模型也很重要。建模数据 像描述性和推断统计一样数据建模可以总结数据或预测未来结果。您的数据集和预期结果将确定可用的算法。重要的是要记住算法只是工具而不是魔术棒或灵丹妙药。您仍然必须是了解如何选择正确工具的技术专家。一个类比是让某人递给你一个十字螺丝刀然后他们递给你一个平头螺丝刀或者更糟糕的是一个锤子。最好的情况下这显示出完全不理解。最坏的情况下这将使项目无法完成。在数据建模中也是如此。错误的模型最多会导致性能不佳最坏的情况下会得出错误的结论作为可操作的情报。验证和实施数据模型 在基于数据子集训练模型之后是时候测试模型了。这有助于确保您没有过度拟合模型或者使其对所选子集过于特定以至于不能准确地适应同一数据集的另一个子集。在这一步中我们确定我们的模型是否过度拟合、泛化或拟合不足我们的数据集。优化和制定策略 这是“仿生人”步骤您可以通过迭代整个过程来使其变得更好、更强大、更快。作为数据科学家您的策略应该是外包开发运营和应用程序管道以便有更多时间专注于建议和设计。一旦您能够打包您的想法这就成为您的“货币兑换”比率。 第一步定义问题
对于这个项目问题陈述已经给出我们需要开发一个算法来预测泰坦尼克号上乘客的生存结果。
…
项目概述 泰坦尼克号的沉没是历史上最臭名昭著的船难之一。1912年4月15日在她的首航中泰坦尼克号与冰山相撞后沉没导致2224名乘客和船员中的1502人死亡。这场轰动的悲剧震惊了国际社会并促使出台更好的船舶安全规定。
造成如此多人员伤亡的原因之一是乘客和船员的救生艇不够。尽管在沉船中幸存涉及一定的运气成分但某些人群比其他人更有可能幸存比如妇女、儿童和上层阶级。
在这个挑战中我们要求您完成对可能幸存的人群的分析。具体而言我们要求您应用机器学习的工具来预测哪些乘客在这场悲剧中幸存下来。
实践技能
二元分类Python和R基础知识
第二步收集数据
数据集也已经以测试和训练数据的形式给出可以在Kaggle的泰坦尼克号来自灾难的机器学习上找到。 步骤3准备数据以供使用
由于步骤2已经为我们提供了黄金般的服务所以步骤3也是如此。因此数据整理中的常规流程如数据架构、治理和提取都不在范围内。因此只有数据清理在范围内。
3.1 导入库
以下代码是用Python 3.x编写的。库提供了预先编写的功能以执行必要的任务。这个想法是为什么要写十行代码当你可以写一行呢。
# 加载所需的包
import sys # 访问系统参数的包
print(Python版本{}. format(sys.version))import pandas as pd # 数据处理和分析的包类似于R的数据框架和SQL的功能
print(pandas版本{}. format(pd.__version__))import matplotlib # 科学和出版可视化的包
print(matplotlib版本{}. format(matplotlib.__version__))import numpy as np # 科学计算的基础包
print(NumPy版本{}. format(np.__version__))import scipy as sp # 科学计算和高级数学的包
print(SciPy版本{}. format(sp.__version__)) import IPython
from IPython import display # 在Jupyter notebook中漂亮地打印数据框
print(IPython版本{}. format(IPython.__version__)) import sklearn # 机器学习算法的集合
print(scikit-learn版本{}. format(sklearn.__version__))# 其他库
import random
import time# 忽略警告
import warnings
warnings.filterwarnings(ignore)
print(-*25)# 输入数据文件在../input/目录中可用。
# 例如运行以下代码点击运行或按ShiftEnter将列出输入目录中的文件from subprocess import check_output
print(check_output([ls, ../input]).decode(utf8))# 将任何结果写入当前目录作为输出。Python version: 3.6.3 |Anaconda custom (64-bit)| (default, Nov 20 2017, 20:41:42)
[GCC 7.2.0]
pandas version: 0.20.3
matplotlib version: 2.1.1
NumPy version: 1.13.0
SciPy version: 1.0.0
IPython version: 5.3.0
scikit-learn version: 0.19.1
-------------------------
gender_submission.csv
test.csv
train.csv3.11 加载数据建模库
我们将使用流行的scikit-learn库来开发我们的机器学习算法。在sklearn中算法被称为估计器并在它们自己的类中实现。为了进行数据可视化我们将使用matplotlib和seaborn库。以下是常见的加载类。
# 导入所需的库和模块# 导入常用的模型算法
from sklearn import svm, tree, linear_model, neighbors, naive_bayes, ensemble, discriminant_analysis, gaussian_process
from xgboost import XGBClassifier# 导入常用的模型辅助工具
from sklearn.preprocessing import OneHotEncoder, LabelEncoder
from sklearn import feature_selection
from sklearn import model_selection
from sklearn import metrics# 导入可视化相关的库和模块
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.pylab as pylab
import seaborn as sns
from pandas.tools.plotting import scatter_matrix# 配置可视化默认设置
# %matplotlib inline 表示在Jupyter Notebook中显示图形
%matplotlib inline
mpl.style.use(ggplot) # 设置图形样式为ggplot风格
sns.set_style(white) # 设置seaborn图形样式为白色背景
pylab.rcParams[figure.figsize] 12, 8 # 设置图形大小为12x83.2 相识和问候数据
这是相识和问候的步骤。首先通过名字来了解你的数据并对其进行一些了解。它是什么样子的数据类型和值它是如何运作的自变量/特征变量它的目标是什么因变量/目标变量。可以把它看作是第一次约会在你跳进并开始在卧室里戳它之前。
在开始这一步之前我们首先导入我们的数据。接下来我们使用info()和sample()函数以获取变量数据类型即定性 vs 定量的快速和粗略的概述。点击这里查看源数据字典。
Survived变量是我们的结果或因变量。它是一个二元名义数据类型1表示幸存0表示未幸存。所有其他变量都是潜在的预测变量或自变量。需要注意的是更多的预测变量并不意味着更好的模型而是选择正确的变量。PassengerID和Ticket变量被认为是随机唯一标识符对结果变量没有影响。因此它们将被排除在分析之外。Pclass变量是一个有序数据类型表示船票等级是社会经济地位SES的代理变量1表示上层阶级2表示中层阶级3表示下层阶级。Name变量是一个名义数据类型。可以在特征工程中使用它来从称号中推导出性别从姓氏中推导出家庭大小从像医生或硕士这样的称号中推导出SES。由于这些变量已经存在我们将利用它来看看像硕士这样的称号是否有所不同。Sex和Embarked变量是名义数据类型。它们将被转换为虚拟变量进行数学计算。Age和Fare变量是连续定量数据类型。SibSp表示同行的兄弟姐妹/配偶的数量Parch表示同行的父母/子女的数量。两者都是离散定量数据类型。这可以用于特征工程创建一个家庭大小和独自一人的变量。Cabin变量是一个名义数据类型可以在特征工程中用于近似确定事故发生时船上的位置和甲板层次的SES。然而由于存在许多空值它并没有增加价值因此被排除在分析之外。
# 导入数据
data_raw pd.read_csv(../input/train.csv) # 从文件中导入数据# 导入验证数据
data_val pd.read_csv(../input/test.csv) # 从文件中导入验证数据# 创建数据副本
data1 data_raw.copy(deepTrue) # 使用深拷贝创建数据副本# 将数据副本放入数据清洗器中
data_cleaner [data1, data_val] # 将数据副本放入数据清洗器列表中# 预览数据
print(data_raw.info()) # 打印数据的基本信息
data_raw.sample(10) # 随机抽样并打印10条数据样本class pandas.core.frame.DataFrame
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId 891 non-null int64
Survived 891 non-null int64
Pclass 891 non-null int64
Name 891 non-null object
Sex 891 non-null object
Age 714 non-null float64
SibSp 891 non-null int64
Parch 891 non-null int64
Ticket 891 non-null object
Fare 891 non-null float64
Cabin 204 non-null object
Embarked 889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6 KB
NonePassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked85585613Aks, Mrs. Sam (Leah Rosen)female18.0013920919.3500NaNS70170211Silverthorne, Mr. Spencer Victormale35.000PC 1747526.2875E24S18018103Sage, Miss. Constance GladysfemaleNaN82CA. 234369.5500NaNS40941003Lefebre, Miss. IdafemaleNaN31413325.4667NaNS77677703Tobin, Mr. RogermaleNaN003831217.7500F38Q40440503Oreskovic, Miss. Marijafemale20.0003150968.6625NaNS495003Arnold-Franchi, Mrs. Josef (Josefine Franchi)female18.01034923717.8000NaNS83683703Pasic, Mr. Jakobmale21.0003150978.6625NaNS61962002Gavey, Mr. Lawrencemale26.0003102810.5000NaNS89089103Dooley, Mr. Patrickmale32.0003703767.7500NaNQ 3.21 数据清洗的四个C修正、补全、创建和转换
在这个阶段我们将通过以下四个步骤来清洗我们的数据1修正异常值和离群值2补全缺失信息3创建新的特征进行分析4将字段转换为正确的格式进行计算和展示。
修正 在审查数据时我们发现没有异常或不可接受的数据输入。此外我们发现年龄和票价可能存在离群值。然而由于它们是合理的值我们将在完成探索性分析后决定是否应该包含或排除在数据集中。值得注意的是如果它们是不合理的值例如年龄为800而不是80那么现在修正可能是一个安全的决定。然而当我们修改数据的原始值时我们需要谨慎因为这可能需要创建一个准确的模型。补全 年龄、船舱和登船港口字段中存在空值或缺失数据。缺失值可能是不好的因为一些算法不知道如何处理空值会导致失败。而其他算法如决策树可以处理空值。因此在开始建模之前修复这些问题非常重要因为我们将比较和对比几个模型。有两种常见的方法要么删除记录要么使用合理的输入填充缺失值。不推荐删除记录尤其是大比例的记录除非它真正代表了一个不完整的记录。相反最好是填充缺失值。对于定性数据基本的方法是使用众数进行填充。对于定量数据基本的方法是使用均值、中位数或均值随机标准差进行填充。中级方法是根据特定的标准使用基本方法比如按照等级或登船港口按票价和SES的平均年龄。还有更复杂的方法但在部署之前应该与基准模型进行比较以确定复杂性是否真正增加了价值。对于这个数据集年龄将使用中位数进行填充船舱属性将被删除登船港口将使用众数进行填充。后续的模型迭代可能会修改这个决策以确定是否提高了模型的准确性。创建 特征工程是指我们利用现有特征创建新特征以确定它们是否提供了预测结果的新信号。对于这个数据集我们将创建一个标题特征以确定它是否在生存中起到了作用。转换 最后但同样重要的是我们将处理格式。没有日期或货币格式只有数据类型格式。我们的分类数据被导入为对象这使得进行数学计算变得困难。对于这个数据集我们将把对象数据类型转换为分类虚拟变量。
# 打印训练数据中含有空值的列
print(Train columns with null values:\n, data1.isnull().sum())# 打印分隔线
print(-*10)# 打印测试/验证数据中含有空值的列
print(Test/Validation columns with null values:\n, data_val.isnull().sum())# 打印分隔线
print(-*10)# 对原始数据进行描述性统计包括所有列的统计信息
data_raw.describe(includeall)Train columns with null values:PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
----------
Test/Validation columns with null values:PassengerId 0
Pclass 0
Name 0
Sex 0
Age 86
SibSp 0
Parch 0
Ticket 0
Fare 1
Cabin 327
Embarked 0
dtype: int64
----------PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedcount891.000000891.000000891.000000891891714.000000891.000000891.000000891891.000000204889uniqueNaNNaNNaN8912NaNNaNNaN681NaN1473topNaNNaNNaNLindahl, Miss. Agda Thorilda ViktoriamaleNaNNaNNaN1601NaNC23 C25 C27SfreqNaNNaNNaN1577NaNNaNNaN7NaN4644mean446.0000000.3838382.308642NaNNaN29.6991180.5230080.381594NaN32.204208NaNNaNstd257.3538420.4865920.836071NaNNaN14.5264971.1027430.806057NaN49.693429NaNNaNmin1.0000000.0000001.000000NaNNaN0.4200000.0000000.000000NaN0.000000NaNNaN25%223.5000000.0000002.000000NaNNaN20.1250000.0000000.000000NaN7.910400NaNNaN50%446.0000000.0000003.000000NaNNaN28.0000000.0000000.000000NaN14.454200NaNNaN75%668.5000001.0000003.000000NaNNaN38.0000001.0000000.000000NaN31.000000NaNNaNmax891.0000001.0000003.000000NaNNaN80.0000008.0000006.000000NaN512.329200NaNNaN
3.22 清洗数据
现在我们知道要清洗什么了让我们执行我们的代码。
开发者文档
pandas.DataFramepandas.DataFrame.infopandas.DataFrame.describe索引和选择数据pandas.isnullpandas.DataFrame.sumpandas.DataFrame.modepandas.DataFrame.copypandas.DataFrame.fillnapandas.DataFrame.droppandas.Series.value_countspandas.DataFrame.loc
###COMPLETING: complete or delete missing values in train and test/validation dataset
# 对训练集和测试/验证集中的缺失值进行填充或删除for dataset in data_cleaner: # 使用中位数填充缺失的年龄值dataset[Age].fillna(dataset[Age].median(), inplace True)# 使用众数填充缺失的登船港口值dataset[Embarked].fillna(dataset[Embarked].mode()[0], inplace True)# 使用中位数填充缺失的票价值dataset[Fare].fillna(dataset[Fare].median(), inplace True)# 在训练集中删除客舱、乘客ID和票号这些特征/列
drop_column [PassengerId,Cabin, Ticket]
data1.drop(drop_column, axis1, inplace True)# 打印训练集中的缺失值总数
print(data1.isnull().sum())
print(-*10)# 打印测试/验证集中的缺失值总数
print(data_val.isnull().sum())Survived 0
Pclass 0
Name 0
Sex 0
Age 0
SibSp 0
Parch 0
Fare 0
Embarked 0
dtype: int64
----------
PassengerId 0
Pclass 0
Name 0
Sex 0
Age 0
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 327
Embarked 0
dtype: int64###创建为训练集和测试/验证集进行特征工程
for dataset in data_cleaner: #离散变量dataset[FamilySize] dataset [SibSp] dataset[Parch] 1 #计算家庭成员数量dataset[IsAlone] 1 #初始化为独自一人是dataset[IsAlone].loc[dataset[FamilySize] 1] 0 #如果家庭成员数量大于1则更新为不是独自一人否#快速而简单的代码从姓名中分离出称号http://www.pythonforbeginners.com/dictionary/python-splitdataset[Title] dataset[Name].str.split(, , expandTrue)[1].str.split(., expandTrue)[0] #从姓名中提取称号#连续变量分箱qcut与cut的区别https://stackoverflow.com/questions/30211923/what-is-the-difference-between-pandas-qcut-and-pandas-cut#使用qcut对票价进行分箱https://pandas.pydata.org/pandas-docs/stable/generated/pandas.qcut.htmldataset[FareBin] pd.qcut(dataset[Fare], 4) #对票价进行分箱#使用cut对年龄进行分箱https://pandas.pydata.org/pandas-docs/stable/generated/pandas.cut.htmldataset[AgeBin] pd.cut(dataset[Age].astype(int), 5) #对年龄进行分箱#清理罕见的称号
#print(data1[Title].value_counts())
stat_min 10 #虽然小是任意的但我们将使用统计学中常见的最小值http://nicholasjjackson.com/2012/03/08/sample-size-is-10-a-magic-number/
title_names (data1[Title].value_counts() stat_min) #这将创建一个以称号为索引的真假序列#apply和lambda函数是一种快速而简单的代码可以用较少的行数找到并替换https://community.modeanalytics.com/python/tutorial/pandas-groupby-and-python-lambda-functions/
data1[Title] data1[Title].apply(lambda x: Misc if title_names.loc[x] True else x) #如果称号在title_names中为True则替换为Misc
print(data1[Title].value_counts())
print(-*10)#再次预览数据
data1.info()
data_val.info()
data1.sample(10)Mr 517
Miss 182
Mrs 125
Master 40
Misc 27
Name: Title, dtype: int64
----------
class pandas.core.frame.DataFrame
RangeIndex: 891 entries, 0 to 890
Data columns (total 14 columns):
Survived 891 non-null int64
Pclass 891 non-null int64
Name 891 non-null object
Sex 891 non-null object
Age 891 non-null float64
SibSp 891 non-null int64
Parch 891 non-null int64
Fare 891 non-null float64
Embarked 891 non-null object
FamilySize 891 non-null int64
IsAlone 891 non-null int64
Title 891 non-null object
FareBin 891 non-null category
AgeBin 891 non-null category
dtypes: category(2), float64(2), int64(6), object(4)
memory usage: 85.5 KB
class pandas.core.frame.DataFrame
RangeIndex: 418 entries, 0 to 417
Data columns (total 16 columns):
PassengerId 418 non-null int64
Pclass 418 non-null int64
Name 418 non-null object
Sex 418 non-null object
Age 418 non-null float64
SibSp 418 non-null int64
Parch 418 non-null int64
Ticket 418 non-null object
Fare 418 non-null float64
Cabin 91 non-null object
Embarked 418 non-null object
FamilySize 418 non-null int64
IsAlone 418 non-null int64
Title 418 non-null object
FareBin 418 non-null category
AgeBin 418 non-null category
dtypes: category(2), float64(2), int64(6), object(6)
memory usage: 46.8 KBSurvivedPclassNameSexAgeSibSpParchFareEmbarkedFamilySizeIsAloneTitleFareBinAgeBin65112Doling, Miss. Elsiefemale18.00123.0000S20Miss(14.454, 31.0](16.0, 32.0]56103Sivic, Mr. Huseinmale40.0007.8958S11Mr(-0.001, 7.91](32.0, 48.0]73711Lesurer, Mr. Gustave Jmale35.000512.3292C11Mr(31.0, 512.329](32.0, 48.0]36813Jermyn, Miss. Anniefemale28.0007.7500Q11Miss(-0.001, 7.91](16.0, 32.0]83703Sirota, Mr. Mauricemale28.0008.0500S11Mr(7.91, 14.454](16.0, 32.0]29911Baxter, Mrs. James (Helene DeLaudeniere Chaput)female50.001247.5208C20Mrs(31.0, 512.329](48.0, 64.0]27301Natsch, Mr. Charles Hmale37.00129.7000C20Mr(14.454, 31.0](32.0, 48.0]11702Turpin, Mr. William John Robertmale29.01021.0000S20Mr(14.454, 31.0](16.0, 32.0]81003Alexander, Mr. Williammale26.0007.8875S11Mr(-0.001, 7.91](16.0, 32.0]23402Leyson, Mr. Robert William Normanmale24.00010.5000S11Mr(7.91, 14.454](16.0, 32.0]
3.23 转换格式
我们将把分类数据转换为虚拟变量以进行数学分析。有多种编码分类变量的方法我们将使用sklearn和pandas函数。
在这一步中我们还将为数据建模定义我们的x自变量/特征/解释变量/预测变量等和y因变量/目标变量/结果变量等变量。
开发者文档
分类编码Sklearn LabelEncoderSklearn OneHotEncoderPandas Categorical dtypepandas.get_dummies
#CONVERT: 使用Label Encoder将对象转换为类别用于训练集和测试/验证集的数据#对分类数据进行编码
label LabelEncoder()
for dataset in data_cleaner: dataset[Sex_Code] label.fit_transform(dataset[Sex]) #将Sex列中的性别数据转换为数字编码dataset[Embarked_Code] label.fit_transform(dataset[Embarked]) #将Embarked列中的登船港口数据转换为数字编码dataset[Title_Code] label.fit_transform(dataset[Title]) #将Title列中的称号数据转换为数字编码dataset[AgeBin_Code] label.fit_transform(dataset[AgeBin]) #将AgeBin列中的年龄段数据转换为数字编码dataset[FareBin_Code] label.fit_transform(dataset[FareBin]) #将FareBin列中的票价段数据转换为数字编码#define y变量即目标/结果
Target [Survived]#define x变量即原始特征用于特征选择
data1_x [Sex,Pclass, Embarked, Title,SibSp, Parch, Age, Fare, FamilySize, IsAlone] #用于图表的漂亮名称/值
data1_x_calc [Sex_Code,Pclass, Embarked_Code, Title_Code,SibSp, Parch, Age, Fare] #用于算法计算的编码
data1_xy Target data1_x
print(Original X Y: , data1_xy, \n)#define x变量即带有分箱特征的原始特征以删除连续变量
data1_x_bin [Sex_Code,Pclass, Embarked_Code, Title_Code, FamilySize, AgeBin_Code, FareBin_Code]
data1_xy_bin Target data1_x_bin
print(Bin X Y: , data1_xy_bin, \n)#define x和y变量即原始虚拟特征
data1_dummy pd.get_dummies(data1[data1_x]) #对data1中的data1_x进行独热编码
data1_x_dummy data1_dummy.columns.tolist() #获取独热编码后的列名列表
data1_xy_dummy Target data1_x_dummy
print(Dummy X Y: , data1_xy_dummy, \n)data1_dummy.head() #显示独热编码后的数据的前几行Original X Y: [Survived, Sex, Pclass, Embarked, Title, SibSp, Parch, Age, Fare, FamilySize, IsAlone] Bin X Y: [Survived, Sex_Code, Pclass, Embarked_Code, Title_Code, FamilySize, AgeBin_Code, FareBin_Code] Dummy X Y: [Survived, Pclass, SibSp, Parch, Age, Fare, FamilySize, IsAlone, Sex_female, Sex_male, Embarked_C, Embarked_Q, Embarked_S, Title_Master, Title_Misc, Title_Miss, Title_Mr, Title_Mrs] PclassSibSpParchAgeFareFamilySizeIsAloneSex_femaleSex_maleEmbarked_CEmbarked_QEmbarked_STitle_MasterTitle_MiscTitle_MissTitle_MrTitle_Mrs031022.07.2500200100100010111038.071.2833201010000001230026.07.9250111000100100311035.053.1000201000100001430035.08.0500110100100010
3.24 Da-Double Check 清洁数据
既然我们已经清洁了我们的数据让我们进行一次折扣的双重检查
# 打印训练数据中含有空值的列
print(Train columns with null values: \n, data1.isnull().sum())# 打印分隔线
print(-*10)# 打印训练数据的信息
print (data1.info())# 打印分隔线
print(-*10)# 打印测试/验证数据中含有空值的列
print(Test/Validation columns with null values: \n, data_val.isnull().sum())# 打印分隔线
print(-*10)# 打印测试/验证数据的信息
print (data_val.info())# 打印分隔线
print(-*10)# 打印数据的统计描述信息包括所有列
data_raw.describe(include all)Train columns with null values: Survived 0
Pclass 0
Name 0
Sex 0
Age 0
SibSp 0
Parch 0
Fare 0
Embarked 0
FamilySize 0
IsAlone 0
Title 0
FareBin 0
AgeBin 0
Sex_Code 0
Embarked_Code 0
Title_Code 0
AgeBin_Code 0
FareBin_Code 0
dtype: int64
----------
class pandas.core.frame.DataFrame
RangeIndex: 891 entries, 0 to 890
Data columns (total 19 columns):
Survived 891 non-null int64
Pclass 891 non-null int64
Name 891 non-null object
Sex 891 non-null object
Age 891 non-null float64
SibSp 891 non-null int64
Parch 891 non-null int64
Fare 891 non-null float64
Embarked 891 non-null object
FamilySize 891 non-null int64
IsAlone 891 non-null int64
Title 891 non-null object
FareBin 891 non-null category
AgeBin 891 non-null category
Sex_Code 891 non-null int64
Embarked_Code 891 non-null int64
Title_Code 891 non-null int64
AgeBin_Code 891 non-null int64
FareBin_Code 891 non-null int64
dtypes: category(2), float64(2), int64(11), object(4)
memory usage: 120.3 KB
None
----------
Test/Validation columns with null values: PassengerId 0
Pclass 0
Name 0
Sex 0
Age 0
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 327
Embarked 0
FamilySize 0
IsAlone 0
Title 0
FareBin 0
AgeBin 0
Sex_Code 0
Embarked_Code 0
Title_Code 0
AgeBin_Code 0
FareBin_Code 0
dtype: int64
----------
class pandas.core.frame.DataFrame
RangeIndex: 418 entries, 0 to 417
Data columns (total 21 columns):
PassengerId 418 non-null int64
Pclass 418 non-null int64
Name 418 non-null object
Sex 418 non-null object
Age 418 non-null float64
SibSp 418 non-null int64
Parch 418 non-null int64
Ticket 418 non-null object
Fare 418 non-null float64
Cabin 91 non-null object
Embarked 418 non-null object
FamilySize 418 non-null int64
IsAlone 418 non-null int64
Title 418 non-null object
FareBin 418 non-null category
AgeBin 418 non-null category
Sex_Code 418 non-null int64
Embarked_Code 418 non-null int64
Title_Code 418 non-null int64
AgeBin_Code 418 non-null int64
FareBin_Code 418 non-null int64
dtypes: category(2), float64(2), int64(11), object(6)
memory usage: 63.1 KB
None
----------PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedcount891.000000891.000000891.000000891891714.000000891.000000891.000000891891.000000204889uniqueNaNNaNNaN8912NaNNaNNaN681NaN1473topNaNNaNNaNLindahl, Miss. Agda Thorilda ViktoriamaleNaNNaNNaN1601NaNC23 C25 C27SfreqNaNNaNNaN1577NaNNaNNaN7NaN4644mean446.0000000.3838382.308642NaNNaN29.6991180.5230080.381594NaN32.204208NaNNaNstd257.3538420.4865920.836071NaNNaN14.5264971.1027430.806057NaN49.693429NaNNaNmin1.0000000.0000001.000000NaNNaN0.4200000.0000000.000000NaN0.000000NaNNaN25%223.5000000.0000002.000000NaNNaN20.1250000.0000000.000000NaN7.910400NaNNaN50%446.0000000.0000003.000000NaNNaN28.0000000.0000000.000000NaN14.454200NaNNaN75%668.5000001.0000003.000000NaNNaN38.0000001.0000000.000000NaN31.000000NaNNaNmax891.0000001.0000003.000000NaNNaN80.0000008.0000006.000000NaN512.329200NaNNaN
3.25 分割训练和测试数据
如前所述提供的测试文件实际上是竞赛提交的验证数据。因此我们将使用sklearn函数将训练数据分为两个数据集75/25的比例。这很重要这样我们就不会过度拟合我们的模型。也就是说算法对于给定的子集非常特定不能准确地推广到同一数据集的另一个子集。重要的是我们的算法没有看到我们将用于测试的子集这样它就不会通过记忆答案来“作弊”。我们将使用sklearn的 train_test_split函数。在后面的章节中我们还将使用sklearn的交叉验证函数将我们的数据集分为训练和测试集以进行数据建模比较。
# 导入模块
# model_selection是一个模块用于拆分训练集和测试集
# train_test_split是model_selection模块中的一个函数用于拆分数据集
# data1是一个数据集包含特征和目标变量
# data1_x_calc是data1中的特征变量
# Target是data1中的目标变量# 使用train_test_split函数将data1中的特征变量data1_x_calc和目标变量Target拆分为训练集和测试集
# random_state参数用于控制随机数生成器的种子保证每次拆分的结果一致
# 拆分后的训练集特征变量赋值给train1_x测试集特征变量赋值给test1_x
# 拆分后的训练集目标变量赋值给train1_y测试集目标变量赋值给test1_y
train1_x, test1_x, train1_y, test1_y model_selection.train_test_split(data1[data1_x_calc], data1[Target], random_state0)# 使用train_test_split函数将data1中的特征变量data1_x_bin和目标变量Target拆分为训练集和测试集
# random_state参数用于控制随机数生成器的种子保证每次拆分的结果一致
# 拆分后的训练集特征变量赋值给train1_x_bin测试集特征变量赋值给test1_x_bin
# 拆分后的训练集目标变量赋值给train1_y_bin测试集目标变量赋值给test1_y_bin
train1_x_bin, test1_x_bin, train1_y_bin, test1_y_bin model_selection.train_test_split(data1[data1_x_bin], data1[Target], random_state0)# 使用train_test_split函数将data1_dummy中的特征变量data1_x_dummy和目标变量Target拆分为训练集和测试集
# random_state参数用于控制随机数生成器的种子保证每次拆分的结果一致
# 拆分后的训练集特征变量赋值给train1_x_dummy测试集特征变量赋值给test1_x_dummy
# 拆分后的训练集目标变量赋值给train1_y_dummy测试集目标变量赋值给test1_y_dummy
train1_x_dummy, test1_x_dummy, train1_y_dummy, test1_y_dummy model_selection.train_test_split(data1_dummy[data1_x_dummy], data1[Target], random_state0)# 打印data1的形状即数据集的行数和列数
print(Data1 Shape: {}.format(data1.shape))# 打印train1_x的形状即训练集特征变量的行数和列数
print(Train1 Shape: {}.format(train1_x.shape))# 打印test1_x的形状即测试集特征变量的行数和列数
print(Test1 Shape: {}.format(test1_x.shape))# 打印train1_x_bin的前几行数据
train1_x_bin.head()Data1 Shape: (891, 19)
Train1 Shape: (668, 8)
Test1 Shape: (223, 8)Sex_CodePclassEmbarked_CodeTitle_CodeFamilySizeAgeBin_CodeFareBin_Code1051323110680322711253132321232013231107060224121 第四步使用统计方法进行探索性分析
现在我们的数据已经清洗完毕我们将使用描述性和图形统计方法来描述和总结我们的变量。在这个阶段您将发现自己正在对特征进行分类并确定它们与目标变量以及彼此之间的相关性。
# 离散变量与生存率的相关性# 使用groupby函数进行分组类似于透视表操作
for x in data1_x:# 如果变量的数据类型不是float64if data1[x].dtype ! float64 :# 打印输出相关性信息print(Survival Correlation by:, x)# 使用groupby函数按照变量x进行分组并计算生存率的平均值print(data1[[x, Target[0]]].groupby(x, as_indexFalse).mean())# 打印分隔线print(-*10, \n)# 使用crosstab函数进行交叉表操作
# 交叉表用于统计两个或多个变量之间的频数分布关系
print(pd.crosstab(data1[Title],data1[Target[0]]))Survival Correlation by: SexSex Survived
0 female 0.742038
1 male 0.188908
---------- Survival Correlation by: PclassPclass Survived
0 1 0.629630
1 2 0.472826
2 3 0.242363
---------- Survival Correlation by: EmbarkedEmbarked Survived
0 C 0.553571
1 Q 0.389610
2 S 0.339009
---------- Survival Correlation by: TitleTitle Survived
0 Master 0.575000
1 Misc 0.444444
2 Miss 0.697802
3 Mr 0.156673
4 Mrs 0.792000
---------- Survival Correlation by: SibSpSibSp Survived
0 0 0.345395
1 1 0.535885
2 2 0.464286
3 3 0.250000
4 4 0.166667
5 5 0.000000
6 8 0.000000
---------- Survival Correlation by: ParchParch Survived
0 0 0.343658
1 1 0.550847
2 2 0.500000
3 3 0.600000
4 4 0.000000
5 5 0.200000
6 6 0.000000
---------- Survival Correlation by: FamilySizeFamilySize Survived
0 1 0.303538
1 2 0.552795
2 3 0.578431
3 4 0.724138
4 5 0.200000
5 6 0.136364
6 7 0.333333
7 8 0.000000
8 11 0.000000
---------- Survival Correlation by: IsAloneIsAlone Survived
0 0 0.505650
1 1 0.303538
---------- Survived 0 1
Title
Master 17 23
Misc 15 12
Miss 55 127
Mr 436 81
Mrs 26 99# 导入matplotlib.pyplot库用于绘制图形
import matplotlib.pyplot as plt# 设置图形的大小为16x12
plt.figure(figsize[16,12])# 在第一个子图中绘制箱线图
plt.subplot(231)
plt.boxplot(xdata1[Fare], showmeans True, meanline True)
plt.title(Fare Boxplot) # 设置子图标题
plt.ylabel(Fare ($)) # 设置y轴标签# 在第二个子图中绘制箱线图
plt.subplot(232)
plt.boxplot(data1[Age], showmeans True, meanline True)
plt.title(Age Boxplot)
plt.ylabel(Age (Years))# 在第三个子图中绘制箱线图
plt.subplot(233)
plt.boxplot(data1[FamilySize], showmeans True, meanline True)
plt.title(Family Size Boxplot)
plt.ylabel(Family Size (#))# 在第四个子图中绘制直方图
plt.subplot(234)
plt.hist(x [data1[data1[Survived]1][Fare], data1[data1[Survived]0][Fare]], stackedTrue, color [g,r],label [Survived,Dead])
plt.title(Fare Histogram by Survival)
plt.xlabel(Fare ($))
plt.ylabel(# of Passengers)
plt.legend()# 在第五个子图中绘制直方图
plt.subplot(235)
plt.hist(x [data1[data1[Survived]1][Age], data1[data1[Survived]0][Age]], stackedTrue, color [g,r],label [Survived,Dead])
plt.title(Age Histogram by Survival)
plt.xlabel(Age (Years))
plt.ylabel(# of Passengers)
plt.legend()# 在第六个子图中绘制直方图
plt.subplot(236)
plt.hist(x [data1[data1[Survived]1][FamilySize], data1[data1[Survived]0][FamilySize]], stackedTrue, color [g,r],label [Survived,Dead])
plt.title(Family Size Histogram by Survival)
plt.xlabel(Family Size (#))
plt.ylabel(# of Passengers)
plt.legend()matplotlib.legend.Legend at 0x7f57f3087860# 使用seaborn图形进行多变量比较https://seaborn.pydata.org/api.html# 创建一个2行3列的图形大小为16x12
fig, saxis plt.subplots(2, 3,figsize(16,12))# 绘制柱状图横轴为Embarked纵轴为Survived数据来源为data1绘制在saxis[0,0]位置
sns.barplot(x Embarked, y Survived, datadata1, ax saxis[0,0])# 绘制柱状图横轴为Pclass纵轴为Survived指定顺序为[1,2,3]数据来源为data1绘制在saxis[0,1]位置
sns.barplot(x Pclass, y Survived, order[1,2,3], datadata1, ax saxis[0,1])# 绘制柱状图横轴为IsAlone纵轴为Survived指定顺序为[1,0]数据来源为data1绘制在saxis[0,2]位置
sns.barplot(x IsAlone, y Survived, order[1,0], datadata1, ax saxis[0,2])# 绘制点图横轴为FareBin纵轴为Survived数据来源为data1绘制在saxis[1,0]位置
sns.pointplot(x FareBin, y Survived, datadata1, ax saxis[1,0])# 绘制点图横轴为AgeBin纵轴为Survived数据来源为data1绘制在saxis[1,1]位置
sns.pointplot(x AgeBin, y Survived, datadata1, ax saxis[1,1])# 绘制点图横轴为FamilySize纵轴为Survived数据来源为data1绘制在saxis[1,2]位置
sns.pointplot(x FamilySize, y Survived, datadata1, ax saxis[1,2])matplotlib.axes._subplots.AxesSubplot at 0x7f57f2f11080# 导入必要的库
import matplotlib.pyplot as plt
import seaborn as sns# 创建一个包含3个子图的图表大小为14x12
fig, (axis1, axis2, axis3) plt.subplots(1, 3, figsize(14, 12))# 在第一个子图上绘制箱线图比较Pclass船舱等级和Fare票价与Survived是否生存之间的关系
sns.boxplot(xPclass, yFare, hueSurvived, datadata1, axaxis1)
axis1.set_title(Pclass vs Fare Survival Comparison) # 设置第一个子图的标题# 在第二个子图上绘制小提琴图比较Pclass船舱等级和Age年龄与Survived是否生存之间的关系
sns.violinplot(xPclass, yAge, hueSurvived, datadata1, splitTrue, axaxis2)
axis2.set_title(Pclass vs Age Survival Comparison) # 设置第二个子图的标题# 在第三个子图上绘制箱线图比较Pclass船舱等级和FamilySize家庭大小与Survived是否生存之间的关系
sns.boxplot(xPclass, yFamilySize, hueSurvived, datadata1, axaxis3)
axis3.set_title(Pclass vs Family Size Survival Comparison) # 设置第三个子图的标题Text(0.5,1,Pclass vs Family Size Survival Comparison)# 导入必要的库
import seaborn as sns
import matplotlib.pyplot as plt# 创建一个包含3个子图的图形大小为14x12
fig, qaxis plt.subplots(1, 3, figsize(14, 12))# 在第一个子图上绘制柱状图比较性别和登船港口对生存率的影响
sns.barplot(xSex, ySurvived, hueEmbarked, datadata1, axqaxis[0])
qaxis[0].set_title(Sex vs Embarked Survival Comparison)# 在第二个子图上绘制柱状图比较性别和客舱等级对生存率的影响
sns.barplot(xSex, ySurvived, huePclass, datadata1, axqaxis[1])
qaxis[1].set_title(Sex vs Pclass Survival Comparison)# 在第三个子图上绘制柱状图比较性别和是否独自一人对生存率的影响
sns.barplot(xSex, ySurvived, hueIsAlone, datadata1, axqaxis[2])
qaxis[2].set_title(Sex vs IsAlone Survival Comparison)Text(0.5,1,Sex vs IsAlone Survival Comparison)# 导入必要的库已经在代码之外完成了这里不需要再次导入# 创建一个1行2列的子图大小为14x12
fig, (maxis1, maxis2) plt.subplots(1, 2,figsize(14,12))# 绘制一个点图比较家庭大小与性别、生存率的关系
sns.pointplot(xFamilySize, ySurvived, hueSex, datadata1,palette{male: blue, female: pink}, # 设置男性为蓝色女性为粉色markers[*, o], linestyles[-, --], ax maxis1) # 设置标记和线型将图绘制在第一个子图上# 绘制一个点图比较船舱等级与性别、生存率的关系
sns.pointplot(xPclass, ySurvived, hueSex, datadata1,palette{male: blue, female: pink}, # 设置男性为蓝色女性为粉色markers[*, o], linestyles[-, --], ax maxis2) # 设置标记和线型将图绘制在第二个子图上matplotlib.axes._subplots.AxesSubplot at 0x7f57f2df7978# 导入 seaborn 库
import seaborn as sns# 创建一个 FacetGrid 对象用于绘制多个子图
# data1 是数据集col Embarked 表示按照 Embarked 列进行分组
e sns.FacetGrid(data1, colEmbarked)# 在每个子图中绘制一个 pointplot表示不同 Pclass、Sex 对应的 Survived 的均值
# Pclass 表示 x 轴Survived 表示 y 轴Sex 表示 hue颜色ci95.0 表示置信区间为 95%
# palette deep 表示使用深色调色板
e.map(sns.pointplot, Pclass, Survived, Sex, ci95.0, palettedeep)# 添加图例
e.add_legend()seaborn.axisgrid.FacetGrid at 0x7f57f660f2b0# 导入必要的库
import seaborn as sns# 创建一个FacetGrid对象用于绘制图表
# data1是数据集hue参数指定按照Survived列的值进行分类
# aspect参数指定图表的宽高比
a sns.FacetGrid(data1, hueSurvived, aspect4)# 使用kdeplot函数绘制核密度估计图并设置阴影效果
# Age参数指定绘制的数据列为Age
a.map(sns.kdeplot, Age, shadeTrue)# 设置x轴的范围为0到数据集中Age列的最大值
a.set(xlim(0, data1[Age].max()))# 添加图例
a.add_legend()seaborn.axisgrid.FacetGrid at 0x7f57f254b048# 导入必要的库
import seaborn as sns
import matplotlib.pyplot as plt# 创建一个FacetGrid对象用于绘制多个子图
# data1是数据集row参数指定按照Sex列进行分组col参数指定按照Pclass列进行分组hue参数指定按照Survived列进行着色
h sns.FacetGrid(data1, rowSex, colPclass, hueSurvived)# 在每个子图上绘制直方图x轴为Age列alpha参数指定透明度为0.75
h.map(plt.hist, Age, alpha0.75)# 添加图例
h.add_legend()seaborn.axisgrid.FacetGrid at 0x7f57f246bdd8# 导入必要的库
import seaborn as sns# 绘制数据集的配对图
# data1为数据集
# hue参数指定了根据Survived列的值对数据进行着色
# palette参数指定了使用deep调色板进行着色
# size参数指定了图的大小为1.2
# diag_kind参数指定了对角线上的图形类型为kde即核密度估计图
# diag_kws参数指定了对角线上的图形的阴影为True
# plot_kws参数指定了散点图的大小为10
pp sns.pairplot(data1, hueSurvived, palettedeep, size1.2, diag_kindkde, diag_kwsdict(shadeTrue), plot_kwsdict(s10))# 设置x轴标签为空即不显示x轴标签
pp.set(xticklabels[])seaborn.axisgrid.PairGrid at 0x7f57f22bd2b0# 导入必要的库
import matplotlib.pyplot as plt
import seaborn as sns# 定义一个函数用于绘制数据集的相关性热力图
def correlation_heatmap(df):# 创建一个图形和一个子图_ , ax plt.subplots(figsize (14, 12))# 设置调色板用于表示相关性的颜色colormap sns.diverging_palette(220, 10, as_cmap True)# 绘制热力图_ sns.heatmap(df.corr(), # 计算数据集的相关系数矩阵cmap colormap, # 使用调色板设置颜色squareTrue, # 设置热力图为正方形cbar_kws{shrink:.9 }, # 设置颜色条的大小axax, # 指定子图annotTrue, # 在热力图上显示数值linewidths0.1, # 设置热力图中每个单元格的边框宽度vmax1.0, # 设置颜色条的最大值linecolorwhite, # 设置热力图中每个单元格的边框颜色annot_kws{fontsize:12 } # 设置热力图上数值的字体大小)# 设置图标题plt.title(Pearson Correlation of Features, y1.05, size15)# 调用函数绘制数据集data1的相关性热力图
correlation_heatmap(data1)第五步建模数据
数据科学是数学如统计学、线性代数等、计算机科学如编程语言、计算机系统等和商业管理如沟通、专业知识等之间的多学科领域。大多数数据科学家来自这三个领域之一所以他们倾向于偏向于这个学科。然而数据科学就像一个三条腿的凳子没有一条腿比其他腿更重要。因此这一步需要数学方面的高级知识。但是不用担心我们只需要一个高层次的概述我们将在本文档中介绍。此外由于计算机科学的帮助很多繁重的工作已经为您完成。因此曾经需要数学或统计学研究生学位的问题现在只需要几行代码就可以解决。最后我们需要一些商业头脑来思考问题。毕竟就像训练一只导盲犬一样它是从我们这里学习而不是相反。
机器学习ML顾名思义是教机器如何思考而不是告诉它们该如何思考。虽然这个主题和大数据已经存在了几十年但由于进入门槛降低它比以往任何时候都更受欢迎无论是对企业还是专业人士来说。这既是好事也是坏事。好处是这些算法现在可以被更多的人使用可以解决现实世界中更多的问题。坏处是进入门槛降低意味着更多的人不会了解他们正在使用的工具并可能得出错误的结论。这就是为什么我专注于教给你们的不仅仅是要做什么还要告诉你们为什么要这样做。之前我用一个类比来解释就像让别人递给你一个十字螺丝刀他们递给你一个平头螺丝刀或者更糟糕的是一个锤子。最好的情况下这显示了完全的无知。最坏的情况下这使得完成项目变得不可能甚至更糟糕的是实施了错误的可行性情报。所以现在我已经强调了我的观点我将告诉你们该怎么做最重要的是为什么要这样做。
首先你必须明白机器学习的目的是解决人类的问题。机器学习可以分为监督学习、无监督学习和强化学习。监督学习是通过向模型呈现包含正确答案的训练数据集来训练模型。无监督学习是通过使用不包含正确答案的训练数据集来训练模型。而强化学习是前两者的混合模型不会立即得到正确答案而是在一系列事件之后得到正确答案以加强学习。我们正在进行监督机器学习因为我们通过呈现一组特征及其相应的目标来训练我们的算法。然后我们希望向它呈现同一数据集的一个新的子集并在预测准确性方面获得类似的结果。
有许多机器学习算法但它们可以分为四类分类、回归、聚类或降维具体取决于目标变量和数据建模目标。我们将把聚类和降维留到另一天重点关注分类和回归。我们可以概括地说连续目标变量需要回归算法而离散目标变量需要分类算法。值得一提的是逻辑回归虽然在名称中有回归但实际上是一种分类算法。由于我们的问题是预测乘客是否生存这是一个离散目标变量。我们将使用sklearn库中的分类算法开始我们的分析。我们将使用交叉验证和评分指标在后面的部分中讨论来排名和比较我们算法的性能。
机器学习选择
Sklearn估计器概述Sklearn估计器详细信息选择估计器思维导图选择估计器备忘单
现在我们确定了我们的解决方案是一个监督学习分类算法。我们可以缩小选择范围。
机器学习分类算法
集成方法广义线性模型GLM朴素贝叶斯最近邻算法支持向量机SVM决策树判别分析
数据科学101如何选择机器学习算法MLA
**重要提示**当涉及数据建模时初学者常问的问题是“什么是最好的机器学习算法”对此初学者必须了解机器学习的无免费午餐定理NFLT。简而言之NFLT表明没有一个超级算法在所有情况下、对于所有数据集都表现最佳。因此最好的方法是尝试多个MLA对它们进行调整并比较它们在特定情况下的表现。尽管如此已经进行了一些对算法的比较研究比如Caruana Niculescu-Mizil 2006的MLA比较Ogutu et al. 2011的基因组选择研究Fernandez-Delgado et al. 2014的17个家族的179个分类器比较Thoma 2016 sklearn比较还有一种观点认为“更多的数据胜过更好的算法”(https://www.kdnuggets.com/2015/06/machine-learning-more-data-better-algorithms.html)。
那么对于所有这些信息初学者应该从哪里开始呢我建议从树、装袋、随机森林和提升开始。它们基本上是决策树的不同实现方式决策树是最容易学习和理解的概念。与像SVC这样的算法相比它们也更容易调整下一节将讨论这一点。下面我将概述如何运行和比较几个MLA但本文档的其余部分将重点介绍通过决策树及其衍生算法学习数据建模。
# 机器学习算法MLA选择和初始化# 导入所需的库
# 这里没有给出import语句需要根据实际情况导入所需的库# 定义MLA列表包含各种机器学习算法
MLA [# 集成方法ensemble.AdaBoostClassifier(), # AdaBoost分类器ensemble.BaggingClassifier(), # Bagging分类器ensemble.ExtraTreesClassifier(), # ExtraTrees分类器ensemble.GradientBoostingClassifier(), # GradientBoosting分类器ensemble.RandomForestClassifier(), # RandomForest分类器# 高斯过程gaussian_process.GaussianProcessClassifier(), # 高斯过程分类器# 广义线性模型linear_model.LogisticRegressionCV(), # 带交叉验证的逻辑回归分类器linear_model.PassiveAggressiveClassifier(), # PassiveAggressive分类器linear_model.RidgeClassifierCV(), # 带交叉验证的岭回归分类器linear_model.SGDClassifier(), # 随机梯度下降分类器linear_model.Perceptron(), # 感知机分类器# 朴素贝叶斯naive_bayes.BernoulliNB(), # 伯努利朴素贝叶斯分类器naive_bayes.GaussianNB(), # 高斯朴素贝叶斯分类器# 最近邻neighbors.KNeighborsClassifier(), # K最近邻分类器# 支持向量机svm.SVC(probabilityTrue), # 支持向量机分类器svm.NuSVC(probabilityTrue), # Nu支持向量机分类器svm.LinearSVC(), # 线性支持向量机分类器# 决策树tree.DecisionTreeClassifier(), # 决策树分类器tree.ExtraTreeClassifier(), # ExtraTree分类器# 判别分析discriminant_analysis.LinearDiscriminantAnalysis(), # 线性判别分析分类器discriminant_analysis.QuadraticDiscriminantAnalysis(), # 二次判别分析分类器# xgboostXGBClassifier() # XGBoost分类器]# 使用ShuffleSplit类进行交叉验证划分数据集
cv_split model_selection.ShuffleSplit(n_splits10, test_size.3, train_size.6, random_state0) # 将数据集划分为10份训练集占60%测试集占30%# 创建用于比较MLA指标的表格
MLA_columns [MLA Name, MLA Parameters, MLA Train Accuracy Mean, MLA Test Accuracy Mean, MLA Test Accuracy 3*STD, MLA Time]
MLA_compare pd.DataFrame(columnsMLA_columns)# 创建用于比较MLA预测结果的表格
MLA_predict data1[Target]# 遍历MLA列表计算并保存性能指标到表格中
row_index 0
for alg in MLA:# 获取算法名称和参数MLA_name alg.__class__.__name__MLA_compare.loc[row_index, MLA Name] MLA_nameMLA_compare.loc[row_index, MLA Parameters] str(alg.get_params())# 使用交叉验证评估模型性能cv_results model_selection.cross_validate(alg, data1[data1_x_bin], data1[Target], cvcv_split)MLA_compare.loc[row_index, MLA Time] cv_results[fit_time].mean() # 计算平均训练时间MLA_compare.loc[row_index, MLA Train Accuracy Mean] cv_results[train_score].mean() # 计算平均训练准确率MLA_compare.loc[row_index, MLA Test Accuracy Mean] cv_results[test_score].mean() # 计算平均测试准确率MLA_compare.loc[row_index, MLA Test Accuracy 3*STD] cv_results[test_score].std() * 3 # 计算测试准确率的3倍标准差用于评估模型的稳定性# 保存MLA预测结果alg.fit(data1[data1_x_bin], data1[Target])MLA_predict[MLA_name] alg.predict(data1[data1_x_bin])row_index 1# 打印并按测试准确率排序表格
MLA_compare.sort_values(by[MLA Test Accuracy Mean], ascendingFalse, inplaceTrue)
MLA_compareMLA NameMLA ParametersMLA Train Accuracy MeanMLA Test Accuracy MeanMLA Test Accuracy 3*STDMLA Time21XGBClassifier{base_score: 0.5, booster: gbtree, cols...0.8563670.8294780.05275460.03380624RandomForestClassifier{bootstrap: True, class_weight: None, cri...0.8923220.8264930.06795250.014775514SVC{C: 1.0, cache_size: 200, class_weight: ...0.8372660.8261190.04538760.04451073GradientBoostingClassifier{criterion: friedman_mse, init: None, l...0.8666670.8227610.04987310.071586415NuSVC{cache_size: 200, class_weight: None, coe...0.8357680.8227610.04936810.05247072ExtraTreesClassifier{bootstrap: False, class_weight: None, cr...0.8951310.8212690.06908630.014425717DecisionTreeClassifier{class_weight: None, criterion: gini, m...0.8951310.819030.05757040.001897241BaggingClassifier{base_estimator: None, bootstrap: True, b...0.8904490.8138060.06140410.015724513KNeighborsClassifier{algorithm: auto, leaf_size: 30, metric...0.8503750.8138060.06908630.0023379818ExtraTreeClassifier{class_weight: None, criterion: gini, m...0.8951310.8126870.06348110.001606970AdaBoostClassifier{algorithm: SAMME.R, base_estimator: Non...0.8204120.811940.04986060.0729315GaussianProcessClassifier{copy_X_train: True, kernel: None, max_it...0.8717230.8104480.04925370.35027320QuadraticDiscriminantAnalysis{priors: None, reg_param: 0.0, store_cova...0.8215360.807090.08103890.01765778RidgeClassifierCV{alphas: (0.1, 1.0, 10.0), class_weight: N...0.7966290.794030.03603020.010547219LinearDiscriminantAnalysis{n_components: None, priors: None, shrink...0.7968160.794030.03603020.0055038716LinearSVC{C: 1.0, class_weight: None, dual: True,...0.797940.7936570.04006460.02746186LogisticRegressionCV{Cs: 10, class_weight: None, cv: None, ...0.7970040.7906720.06535820.12913412GaussianNB{priors: None}0.7947570.7813430.08745680.0018361311BernoulliNB{alpha: 1.0, binarize: 0.0, class_prior:...0.7857680.7753730.05703470.002002697PassiveAggressiveClassifier{C: 1.0, average: False, class_weight: N...0.7344570.7305970.1488260.0023890710Perceptron{alpha: 0.0001, class_weight: None, eta0...0.7400750.7287310.1622210.001856839SGDClassifier{alpha: 0.0001, average: False, class_wei...0.7370790.7261190.173720.00182471
# 导入seaborn和matplotlib.pyplot模块# 使用seaborn的barplot函数绘制条形图
# x轴为MLA Test Accuracy Meany轴为MLA Name数据为MLA_compare颜色为m
sns.barplot(xMLA Test Accuracy Mean, yMLA Name, dataMLA_compare, colorm)# 使用pyplot的title函数设置图表标题
plt.title(Machine Learning Algorithm Accuracy Score \n)# 使用pyplot的xlabel函数设置x轴标签
plt.xlabel(Accuracy Score (%))# 使用pyplot的ylabel函数设置y轴标签
plt.ylabel(Algorithm)Text(0,0.5,Algorithm)5.1 评估模型性能
让我们回顾一下通过一些基本的数据清洗、分析和机器学习算法MLA我们能够以约82%的准确率预测乘客的生存情况。对于几行代码来说这已经不错了。但是我们总是会问的问题是我们能做得更好更重要的是能否获得我们投入时间的回报ROI例如如果我们只能将准确率提高1/10个百分点是否值得投入3个月的开发时间如果你从事研究工作也许答案是肯定的但如果你主要从事商业工作答案通常是否定的。所以在改进模型时要记住这一点。
数据科学101确定基准准确率
在决定如何改进我们的模型之前让我们确定一下我们的模型是否值得保留。为了做到这一点我们必须回到数据科学101的基础知识。我们知道这是一个二元问题因为只有两种可能的结果乘客幸存或死亡。所以把它看作是一个硬币翻转问题。如果你有一枚公平的硬币你猜测正面或反面那么你有50%的几率猜对。所以让我们将50%作为最差的模型性能因为低于这个水平那么当我可以通过抛硬币来预测时我为什么还需要你呢
好吧所以在没有关于数据集的任何信息的情况下我们总是可以通过二元问题得到50%的准确率。但是我们有关于数据集的信息所以我们应该能做得更好。我们知道1502/2224或67.5%的人死亡。因此如果我们只是预测最常见的情况即100%的人死亡那么我们将有67.5%的准确率。所以让我们将68%作为差模型性能的标准因为低于这个水平那么当我可以通过预测最常见的情况来预测时我为什么还需要你呢
数据科学101如何创建自己的模型
我们的准确率在提高但我们能做得更好吗我们的数据中有任何信号吗为了说明这一点我们将构建自己的决策树模型因为它是最容易理解和需要简单的加法和乘法计算的模型。在创建决策树时您希望提出问题将您的目标响应分割成生存/1和死亡/0的同质子组。这既是科学的一部分也是艺术的一部分所以让我们玩一下21个问题的游戏以展示它是如何工作的。如果你想自己跟着做下载训练数据集并导入Excel。在行中创建一个透视表列中是生存情况值是计数和行计数的百分比行中是下面描述的特征。
记住游戏的目标是使用决策树模型创建子组将生存/1放入一个桶中将死亡/0放入另一个桶中。我们的经验法则是多数人的规则。也就是说如果多数人或50%以上幸存那么我们子组中的每个人都幸存/1但如果幸存的人少于50%那么我们子组中的每个人都死亡/0。此外如果子组少于10个和/或我们的模型准确率达到平稳或下降我们将停止。明白了吗我们开始吧
问题1你在泰坦尼克号上吗 如果是那么大多数人62%死亡。请注意我们的样本生存率与我们的总体生存率不同尽管如此如果我们假设每个人都死亡我们的样本准确率为62%。
问题2你是男性还是女性 男性大多数人81%死亡。女性大多数人74%幸存。给我们的准确率为79%。
问题3A沿着女性分支计数314你是1、2还是3等舱 1等舱大多数人97%幸存2等舱大多数人92%幸存。由于死亡子组少于10个我们将停止沿着这个分支继续下去。3等舱幸存和死亡的比例是50-50。没有新的信息可以改善我们的模型。
问题4A沿着女性3等舱分支计数144你是从C、Q还是S登船的 我们获得了一些信息。C和Q大多数人仍然幸存所以没有变化。此外死亡子组少于10个所以我们将停止。S大多数人63%死亡。所以我们将女性、3等舱、从S登船的人从假设他们幸存改为假设他们死亡。我们的模型准确率提高到81%。
问题5A沿着女性3等舱从S登船的分支计数88 到目前为止看起来我们做出了正确的决策。再增加一层似乎并没有获得更多的信息。这个子组中有55人死亡33人幸存由于大多数人死亡我们需要找到一个信号来识别这33人或者找到一个子组将他们从死亡改为幸存以提高我们的模型准确率。我们可以尝试一下我们的特征。我发现的一个是票价0-8大多数人幸存。这是一个样本量很小的样本11-9但在统计学中经常使用。我们稍微提高了准确率但没有足够的提高使我们超过82%。所以我们就到这里吧。
问题3B沿着男性分支计数577 回到问题2我们知道大多数男性死亡。所以我们正在寻找一个能够识别大多数幸存的子组的特征。令人惊讶的是舱位或者登船地并不像对女性那样重要但是头衔是重要的并且使我们的准确率达到了82%。尝试其他特征没有一个能将我们的准确率推到82%以上。所以我们暂时停在这里。
你做到了在非常少的信息的情况下我们达到了82%的准确率。在最差、差、好、更好和最好的尺度上我们将82%设置为好因为它是一个简单的模型给我们带来了不错的结果。但问题仍然存在我们能比我们手工制作的模型做得更好吗
在我们继续之前让我们编写上面所写的代码。请注意这是一个由“手工”创建的手动过程。你不必这样做但在开始使用MLA之前了解它是很重要的。把MLA想象成一台TI-89计算器在微积分考试中使用它非常强大可以帮助你完成很多繁重的工作。但是如果你在考试中不知道你在做什么即使是TI-89也无法帮助你通过。所以明智地学习下一节的内容。
参考资料交叉验证和决策树教程
#IMPORTANT: 这是一个手工制作的模型仅用于学习目的。
#然而你也可以创建自己的预测模型而不需要使用复杂的算法 :)#硬币翻转模型使用随机数生成器生成1/幸存 0/死亡的预测结果#遍历DataFrame的行返回(index, Series)对https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.iterrows.html
for index, row in data1.iterrows(): #随机数生成器https://docs.python.org/2/library/random.htmlif random.random() .5: # 随机生成一个0.0到1.0之间的浮点数 data1.set_value(index, Random_Predict, 1) #预测为幸存/1else: data1.set_value(index, Random_Predict, 0) #预测为死亡/0#计算随机猜测幸存的准确率。使用快捷方式 1 正确猜测0 错误猜测
#该列的平均值将等于准确率
data1[Random_Score] 0 #假设预测错误
data1.loc[(data1[Survived] data1[Random_Predict]), Random_Score] 1 #对于正确的预测将其设置为1
print(Coin Flip Model Accuracy: {:.2f}%.format(data1[Random_Score].mean()*100))#我们也可以使用scikit的accuracy_score函数来节省几行代码
#http://scikit-learn.org/stable/modules/generated/sklearn.metrics.accuracy_score.html#sklearn.metrics.accuracy_score
print(Coin Flip Model Accuracy w/SciKit: {:.2f}%.format(metrics.accuracy_score(data1[Survived], data1[Random_Predict])*100))Coin Flip Model Accuracy: 47.81%
Coin Flip Model Accuracy w/SciKit: 47.81%# 通过性别、舱位等因素对数据进行分组并计算存活率
pivot_female data1[data1.Sexfemale].groupby([Sex,Pclass, Embarked,FareBin])[Survived].mean()
print(Survival Decision Tree w/Female Node: \n,pivot_female)# 通过性别、头衔等因素对数据进行分组并计算存活率
pivot_male data1[data1.Sexmale].groupby([Sex,Title])[Survived].mean()
print(\n\nSurvival Decision Tree w/Male Node: \n,pivot_male)Survival Decision Tree w/Female Node: Sex Pclass Embarked FareBin
female 1 C (14.454, 31.0] 0.666667(31.0, 512.329] 1.000000Q (31.0, 512.329] 1.000000S (14.454, 31.0] 1.000000(31.0, 512.329] 0.9555562 C (7.91, 14.454] 1.000000(14.454, 31.0] 1.000000(31.0, 512.329] 1.000000Q (7.91, 14.454] 1.000000S (7.91, 14.454] 0.875000(14.454, 31.0] 0.916667(31.0, 512.329] 1.0000003 C (-0.001, 7.91] 1.000000(7.91, 14.454] 0.428571(14.454, 31.0] 0.666667Q (-0.001, 7.91] 0.750000(7.91, 14.454] 0.500000(14.454, 31.0] 0.714286S (-0.001, 7.91] 0.533333(7.91, 14.454] 0.448276(14.454, 31.0] 0.357143(31.0, 512.329] 0.125000
Name: Survived, dtype: float64Survival Decision Tree w/Male Node: Sex Title
male Master 0.575000Misc 0.250000Mr 0.156673
Name: Survived, dtype: float64#handmade data model using brain power (and Microsoft Excel Pivot Tables for quick calculations)
#手工制作的数据模型使用大脑计算以及Microsoft Excel数据透视表进行快速计算def mytree(df):#初始化表格以存储预测结果Model pd.DataFrame(data {Predict:[]})male_title [Master] #幸存的称号for index, row in df.iterrows():#问题1你是否在泰坦尼克号上大多数人都死了Model.loc[index, Predict] 0#问题2你是女性吗大多数女性幸存if (df.loc[index, Sex] female):Model.loc[index, Predict] 1#问题3A 女性 - 班级和问题4 登船地点提供最少的信息#问题5B 女性 - 票价范围将女性节点决策树中小于0.5的值设为0if ((df.loc[index, Sex] female) (df.loc[index, Pclass] 3) (df.loc[index, Embarked] S) (df.loc[index, Fare] 8)):Model.loc[index, Predict] 0#问题3B 男性称号将大于0.5的值设为1表示大多数幸存if ((df.loc[index, Sex] male) (df.loc[index, Title] in male_title)):Model.loc[index, Predict] 1return Model#对数据进行建模
Tree_Predict mytree(data1)
print(Decision Tree Model Accuracy/Precision Score: {:.2f}%\n.format(metrics.accuracy_score(data1[Survived], Tree_Predict)*100))#使用http://scikit-learn.org/stable/modules/generated/sklearn.metrics.classification_report.html#sklearn.metrics.classification_report生成准确率摘要报告
#其中召回率得分真正例/真正例假反例1为最佳http://scikit-learn.org/stable/modules/generated/sklearn.metrics.recall_score.html#sklearn.metrics.recall_score
#F1得分精确率和召回率的加权平均值1为最佳http://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html#sklearn.metrics.f1_score
print(metrics.classification_report(data1[Survived], Tree_Predict))Decision Tree Model Accuracy/Precision Score: 82.04%precision recall f1-score support0 0.82 0.91 0.86 5491 0.82 0.68 0.75 342avg / total 0.82 0.82 0.82 891# 绘制混淆矩阵的函数import itertoolsdef plot_confusion_matrix(cm, classes, normalizeFalse, titleConfusion matrix, cmapplt.cm.Blues):这个函数打印并绘制混淆矩阵。可以通过设置normalizeTrue来进行归一化。if normalize:# 如果需要归一化则将混淆矩阵的每个元素除以该行的总和以得到归一化的混淆矩阵cm cm.astype(float) / cm.sum(axis1)[:, np.newaxis]print(Normalized confusion matrix)else:print(Confusion matrix, without normalization)# 打印混淆矩阵print(cm)# 绘制混淆矩阵图像plt.imshow(cm, interpolationnearest, cmapcmap)plt.title(title)plt.colorbar()tick_marks np.arange(len(classes))plt.xticks(tick_marks, classes, rotation45)plt.yticks(tick_marks, classes)fmt .2f if normalize else dthresh cm.max() / 2.# 在每个混淆矩阵元素的中心位置添加文本显示该元素的值for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):plt.text(j, i, format(cm[i, j], fmt),horizontalalignmentcenter,colorwhite if cm[i, j] thresh else black)plt.tight_layout()plt.ylabel(True label)plt.xlabel(Predicted label)# 计算混淆矩阵
cnf_matrix metrics.confusion_matrix(data1[Survived], Tree_Predict)
np.set_printoptions(precision2)class_names [Dead, Survived]
# 绘制未归一化的混淆矩阵图像
plt.figure()
plot_confusion_matrix(cnf_matrix, classesclass_names,titleConfusion matrix, without normalization)# 绘制归一化的混淆矩阵图像
plt.figure()
plot_confusion_matrix(cnf_matrix, classesclass_names, normalizeTrue, titleNormalized confusion matrix)Confusion matrix, without normalization
[[497 52][108 234]]
Normalized confusion matrix
[[ 0.91 0.09][ 0.32 0.68]]5.11 使用交叉验证CV评估模型性能
在第5.0步骤中我们使用了sklearn cross_validate函数来训练、测试和评估我们的模型性能。
记住我们需要使用不同的子集来构建模型的训练数据和评估模型的测试数据。否则我们的模型将会过拟合。这意味着它在已经见过的数据上的“预测”非常好但在未见过的数据上的预测非常糟糕这根本就不是预测。这就像在学校测验中作弊得到满分但当你参加考试时你会失败因为你从未真正学到任何东西。机器学习也是如此。
CV基本上是一个快捷方式可以多次拆分和评分我们的模型这样我们就可以了解它在未见数据上的表现如何。这在Kaggle竞赛或任何一种一致性很重要且应避免出现意外的情况下非常有帮助。
除了CV之外我们还使用了一个定制的sklearn train test splitter以在测试评分中引入一些随机性。下面是默认CV拆分的图片。 5.12 使用超参数调整模型
当我们使用sklearn决策树分类器时我们接受了所有函数的默认值。这给了我们机会看看不同的超参数设置如何改变模型的准确性。(点击这里了解更多关于参数和超参数的信息。)
然而为了调整模型我们需要真正理解它。这就是为什么我在前面的部分花时间向你展示预测如何工作的原因。现在让我们更多地了解一下我们的决策树算法。
来源sklearn 决策树的一些优点包括 简单易懂易于解释。可以将树可视化。需要很少的数据准备。其他技术通常需要数据归一化需要创建虚拟变量和删除空值。但请注意该模块不支持缺失值。使用树进行预测的成本即预测数据与用于训练树的数据点数量的对数成正比。能够处理数值和分类数据。其他技术通常专门用于分析只有一种类型变量的数据集。有关更多信息请参阅算法。能够处理多输出问题。使用白盒模型。如果在模型中观察到某种情况那么对于该条件的解释很容易通过布尔逻辑来解释。相比之下在黑盒模型例如人工神经网络中结果可能更难解释。可以使用统计测试验证模型。这使得可以考虑模型的可靠性。即使其假设与生成数据的真实模型略有违背也能表现良好。 决策树的缺点包括 决策树学习器可能创建过于复杂的树无法很好地推广数据。这被称为过拟合。为了避免这个问题需要使用修剪目前不支持设置叶节点所需的最小样本数或设置树的最大深度等机制。决策树可能不稳定因为数据的微小变化可能导致生成完全不同的树。通过在集成中使用决策树可以缓解这个问题。学习最优决策树的问题在多个方面上被认为是NP完全的甚至对于简单的概念也是如此。因此实际的决策树学习算法基于启发式算法如贪婪算法在每个节点上做出局部最优决策。这样的算法不能保证返回全局最优决策树。通过在集成学习器中训练多个树可以缓解这个问题其中特征和样本是随机抽样并替换的。有些概念很难学习因为决策树不容易表达它们例如XOR、奇偶校验或多路复用器问题。如果某些类别占主导地位决策树学习器会创建有偏差的树。因此建议在拟合决策树之前平衡数据集。
下面是可用的超参数和定义 class sklearn.tree.DecisionTreeClassifier(criterion’gini’, splitter’best’, max_depthNone, min_samples_split2, min_samples_leaf1, min_weight_fraction_leaf0.0, max_featuresNone, random_stateNone, max_leaf_nodesNone, min_impurity_decrease0.0, min_impurity_splitNone, class_weightNone, presortFalse) 我们将使用ParameterGrid、GridSearchCV和自定义的sklearn评分来调整我们的模型点击这里了解更多关于ROC_AUC得分的信息。然后我们将使用graphviz可视化我们的树。点击这里了解更多关于ROC_AUC得分的信息。
# 导入需要的库
from sklearn import tree
from sklearn import model_selection# 创建决策树分类器对象
dtree tree.DecisionTreeClassifier(random_state 0)# 使用交叉验证评估基础模型
base_results model_selection.cross_validate(dtree, data1[data1_x_bin], data1[Target], cv cv_split)# 使用训练数据拟合决策树模型
dtree.fit(data1[data1_x_bin], data1[Target])# 输出决策树模型的参数
print(BEFORE DT Parameters: , dtree.get_params())# 输出基础模型的训练得分和测试得分
print(BEFORE DT Training w/bin score mean: {:.2f}. format(base_results[train_score].mean()*100))
print(BEFORE DT Test w/bin score mean: {:.2f}. format(base_results[test_score].mean()*100))
print(BEFORE DT Test w/bin score 3*std: /- {:.2f}. format(base_results[test_score].std()*100*3))
#print(BEFORE DT Test w/bin set score min: {:.2f}. format(base_results[test_score].min()*100))
print(-*10)# 设置超参数的取值范围
param_grid {criterion: [gini, entropy], # 评估标准两种计算信息增益的公式gini和entropy默认为gini#splitter: [best, random], # 分割策略两种策略best和random默认为bestmax_depth: [2,4,6,8,10,None], # 决策树的最大深度默认为None#min_samples_split: [2,5,10,.03,.05], # 最小分割样本数占总样本数的比例默认为2#min_samples_leaf: [1,5,10,.03,.05], # 最小叶子节点样本数占总样本数的比例默认为1#max_features: [None, auto], # 在进行分割时考虑的最大特征数默认为None或全部特征random_state: [0] # 随机数种子用于控制随机数生成器}# 使用网格搜索选择最佳模型
tune_model model_selection.GridSearchCV(tree.DecisionTreeClassifier(), param_gridparam_grid, scoring roc_auc, cv cv_split)
tune_model.fit(data1[data1_x_bin], data1[Target])# 输出最佳模型的参数
print(AFTER DT Parameters: , tune_model.best_params_)# 输出最佳模型的训练得分和测试得分
print(AFTER DT Training w/bin score mean: {:.2f}. format(tune_model.cv_results_[mean_train_score][tune_model.best_index_]*100))
print(AFTER DT Test w/bin score mean: {:.2f}. format(tune_model.cv_results_[mean_test_score][tune_model.best_index_]*100))
print(AFTER DT Test w/bin score 3*std: /- {:.2f}. format(tune_model.cv_results_[std_test_score][tune_model.best_index_]*100*3))
print(-*10)# 使用最佳模型进行交叉验证
#tune_results model_selection.cross_validate(tune_model, data1[data1_x_bin], data1[Target], cv cv_split)# 输出最佳模型的参数和训练得分、测试得分
#print(AFTER DT Parameters: , tune_model.best_params_)
#print(AFTER DT Training w/bin set score mean: {:.2f}. format(tune_results[train_score].mean()*100))
#print(AFTER DT Test w/bin set score mean: {:.2f}. format(tune_results[test_score].mean()*100))
#print(AFTER DT Test w/bin set score min: {:.2f}. format(tune_results[test_score].min()*100))
#print(-*10)BEFORE DT Parameters: {class_weight: None, criterion: gini, max_depth: None, max_features: None, max_leaf_nodes: None, min_impurity_decrease: 0.0, min_impurity_split: None, min_samples_leaf: 1, min_samples_split: 2, min_weight_fraction_leaf: 0.0, presort: False, random_state: 0, splitter: best}
BEFORE DT Training w/bin score mean: 89.51
BEFORE DT Test w/bin score mean: 82.09
BEFORE DT Test w/bin score 3*std: /- 5.57
----------
AFTER DT Parameters: {criterion: gini, max_depth: 4, random_state: 0}
AFTER DT Training w/bin score mean: 89.35
AFTER DT Test w/bin score mean: 87.40
AFTER DT Test w/bin score 3*std: /- 5.00
----------5.13 使用特征选择调整模型
正如之前所述更多的预测变量并不意味着模型更好而是选择正确的预测变量才能得到更好的模型。因此在数据建模中另一步是进行特征选择。Sklearn提供了几种选择我们将使用递归特征消除RFE与交叉验证CV。
#base model
#输出数据集data1[data1_x_bin]的形状和列名
print(BEFORE DT RFE Training Shape Old: , data1[data1_x_bin].shape)
print(BEFORE DT RFE Training Columns Old: , data1[data1_x_bin].columns.values)#输出基础模型的训练得分和测试得分的平均值和标准差
print(BEFORE DT RFE Training w/bin score mean: {:.2f}. format(base_results[train_score].mean()*100))
print(BEFORE DT RFE Test w/bin score mean: {:.2f}. format(base_results[test_score].mean()*100))
print(BEFORE DT RFE Test w/bin score 3*std: /- {:.2f}. format(base_results[test_score].std()*100*3))
print(-*10)#feature selection
#使用RFECV进行特征选择
dtree_rfe feature_selection.RFECV(dtree, step 1, scoring accuracy, cv cv_split)
dtree_rfe.fit(data1[data1_x_bin], data1[Target])#将x和y转换为减少的特征并拟合新模型
#另一种方法可以使用管道来减少拟合和转换步骤http://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html
X_rfe data1[data1_x_bin].columns.values[dtree_rfe.get_support()]
rfe_results model_selection.cross_validate(dtree, data1[X_rfe], data1[Target], cv cv_split)#print(dtree_rfe.grid_scores_)
#输出数据集data1[X_rfe]的形状和列名
print(AFTER DT RFE Training Shape New: , data1[X_rfe].shape)
print(AFTER DT RFE Training Columns New: , X_rfe)#输出特征选择后的模型的训练得分和测试得分的平均值和标准差
print(AFTER DT RFE Training w/bin score mean: {:.2f}. format(rfe_results[train_score].mean()*100))
print(AFTER DT RFE Test w/bin score mean: {:.2f}. format(rfe_results[test_score].mean()*100))
print(AFTER DT RFE Test w/bin score 3*std: /- {:.2f}. format(rfe_results[test_score].std()*100*3))
print(-*10)#tune rfe model
#使用GridSearchCV对特征选择后的模型进行调参
rfe_tune_model model_selection.GridSearchCV(tree.DecisionTreeClassifier(), param_gridparam_grid, scoring roc_auc, cv cv_split)
rfe_tune_model.fit(data1[X_rfe], data1[Target])#print(rfe_tune_model.cv_results_.keys())
#print(rfe_tune_model.cv_results_[params])
#输出调参后的模型的最佳参数
print(AFTER DT RFE Tuned Parameters: , rfe_tune_model.best_params_)
#print(rfe_tune_model.cv_results_[mean_train_score])
#输出调参后的模型的训练得分和测试得分的平均值和标准差
print(AFTER DT RFE Tuned Training w/bin score mean: {:.2f}. format(rfe_tune_model.cv_results_[mean_train_score][tune_model.best_index_]*100))
#print(rfe_tune_model.cv_results_[mean_test_score])
print(AFTER DT RFE Tuned Test w/bin score mean: {:.2f}. format(rfe_tune_model.cv_results_[mean_test_score][tune_model.best_index_]*100))
print(AFTER DT RFE Tuned Test w/bin score 3*std: /- {:.2f}. format(rfe_tune_model.cv_results_[std_test_score][tune_model.best_index_]*100*3))
print(-*10)BEFORE DT RFE Training Shape Old: (891, 7)
BEFORE DT RFE Training Columns Old: [Sex_Code Pclass Embarked_Code Title_Code FamilySizeAgeBin_Code FareBin_Code]
BEFORE DT RFE Training w/bin score mean: 89.51
BEFORE DT RFE Test w/bin score mean: 82.09
BEFORE DT RFE Test w/bin score 3*std: /- 5.57
----------
AFTER DT RFE Training Shape New: (891, 6)
AFTER DT RFE Training Columns New: [Sex_Code Pclass Title_Code FamilySize AgeBin_Code FareBin_Code]
AFTER DT RFE Training w/bin score mean: 88.16
AFTER DT RFE Test w/bin score mean: 83.06
AFTER DT RFE Test w/bin score 3*std: /- 6.22
----------
AFTER DT RFE Tuned Parameters: {criterion: gini, max_depth: 4, random_state: 0}
AFTER DT RFE Tuned Training w/bin score mean: 89.39
AFTER DT RFE Tuned Test w/bin score mean: 87.34
AFTER DT RFE Tuned Test w/bin score 3*std: /- 6.21
----------# 导入graphviz库
import graphviz # 使用tree.export_graphviz函数生成决策树的MLA版本的图形化表示
# 参数dtree为决策树模型
# 参数out_file为输出文件默认为None表示不输出到文件而是返回生成的图形化表示的字符串
# 参数feature_names为特征的名称列表用于标识决策树中的特征
# 参数class_names为类别的名称列表用于标识决策树中的类别
# 参数filled为布尔值表示是否给决策树的节点填充颜色默认为False
# 参数rounded为布尔值表示是否给决策树的节点绘制圆角矩形默认为False
dot_data tree.export_graphviz(dtree, out_fileNone, feature_names data1_x_bin, class_names True,filled True, rounded True)# 使用graphviz库的Source函数将生成的图形化表示字符串转换为图形对象
graph graphviz.Source(dot_data) # 输出图形对象
graph任务请翻译以下markdown为中文请保留markdown的格式并输出翻译结果。 语料:
Step 6: Validate and Implement
The next step is to prepare for submission using the validation data.
翻译结果
第六步验证和实施
下一步是使用验证数据准备提交。
# 对比算法的预测结果其中1表示完全相似0表示完全相反
# 在这些预测结果中有一些1但也有足够多的蓝色和浅红色可以通过将它们结合起来创建一个“超级算法”
# 使用correlation_heatmap函数绘制相关性热力图传入MLA_predict作为参数# 导入所需的库和模块# 导入ensemble模块中的VotingClassifier类用于实现投票分类器
from sklearn import ensemble
# 导入gaussian_process模块中的GaussianProcessClassifier类用于实现高斯过程分类器
from sklearn import gaussian_process
# 导入linear_model模块中的LogisticRegressionCV类用于实现逻辑回归分类器
from sklearn import linear_model
# 导入naive_bayes模块中的BernoulliNB和GaussianNB类用于实现朴素贝叶斯分类器
from sklearn import naive_bayes
# 导入neighbors模块中的KNeighborsClassifier类用于实现K近邻分类器
from sklearn import neighbors
# 导入svm模块中的SVC类用于实现支持向量机分类器
from sklearn import svm
# 导入xgboost模块中的XGBClassifier类用于实现XGBoost分类器
from xgboost import XGBClassifier# 定义投票分类器的模型列表
vote_est [# 集成方法(ada, ensemble.AdaBoostClassifier()), # AdaBoost分类器(bc, ensemble.BaggingClassifier()), # Bagging分类器(etc,ensemble.ExtraTreesClassifier()), # ExtraTrees分类器(gbc, ensemble.GradientBoostingClassifier()), # GradientBoosting分类器(rfc, ensemble.RandomForestClassifier()), # RandomForest分类器# 高斯过程分类器(gpc, gaussian_process.GaussianProcessClassifier()),# 逻辑回归分类器(lr, linear_model.LogisticRegressionCV()),# 朴素贝叶斯分类器(bnb, naive_bayes.BernoulliNB()), # 伯努利朴素贝叶斯分类器(gnb, naive_bayes.GaussianNB()), # 高斯朴素贝叶斯分类器# K近邻分类器(knn, neighbors.KNeighborsClassifier()),# 支持向量机分类器(svc, svm.SVC(probabilityTrue)),# XGBoost分类器(xgb, XGBClassifier())
]# 创建硬投票分类器
vote_hard ensemble.VotingClassifier(estimatorsvote_est, votinghard)
# 使用交叉验证对硬投票分类器进行评估
vote_hard_cv model_selection.cross_validate(vote_hard, data1[data1_x_bin], data1[Target], cvcv_split)
# 使用训练数据对硬投票分类器进行训练
vote_hard.fit(data1[data1_x_bin], data1[Target])# 输出硬投票分类器的训练得分均值
print(Hard Voting Training w/bin score mean: {:.2f}.format(vote_hard_cv[train_score].mean() * 100))
# 输出硬投票分类器的测试得分均值
print(Hard Voting Test w/bin score mean: {:.2f}.format(vote_hard_cv[test_score].mean() * 100))
# 输出硬投票分类器的测试得分3倍标准差
print(Hard Voting Test w/bin score 3*std: /- {:.2f}.format(vote_hard_cv[test_score].std() * 100 * 3))
print(- * 10)# 创建软投票分类器
vote_soft ensemble.VotingClassifier(estimatorsvote_est, votingsoft)
# 使用交叉验证对软投票分类器进行评估
vote_soft_cv model_selection.cross_validate(vote_soft, data1[data1_x_bin], data1[Target], cvcv_split)
# 使用训练数据对软投票分类器进行训练
vote_soft.fit(data1[data1_x_bin], data1[Target])# 输出软投票分类器的训练得分均值
print(Soft Voting Training w/bin score mean: {:.2f}.format(vote_soft_cv[train_score].mean() * 100))
# 输出软投票分类器的测试得分均值
print(Soft Voting Test w/bin score mean: {:.2f}.format(vote_soft_cv[test_score].mean() * 100))
# 输出软投票分类器的测试得分3倍标准差
print(Soft Voting Test w/bin score 3*std: /- {:.2f}.format(vote_soft_cv[test_score].std() * 100 * 3))
print(- * 10)Hard Voting Training w/bin score mean: 86.59
Hard Voting Test w/bin score mean: 82.39
Hard Voting Test w/bin score 3*std: /- 4.95
----------
Soft Voting Training w/bin score mean: 87.15
Soft Voting Test w/bin score mean: 82.35
Soft Voting Test w/bin score 3*std: /- 4.85
----------#IMPORTANT: THIS SECTION IS UNDER CONSTRUCTION!!!! 12.24.17
#UPDATE: This section was scrapped for the next section; as its more computational friendly.#WARNING: Running is very computational intensive and time expensive
#code is written for experimental/developmental purposes and not production ready#tune each estimator before creating a super model
#http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html
grid_n_estimator [50,100,300] # 定义n_estimators的取值范围
grid_ratio [.1,.25,.5,.75,1.0] # 定义learning_rate和max_samples的取值范围
grid_learn [.01,.03,.05,.1,.25] # 定义learning_rate的取值范围
grid_max_depth [2,4,6,None] # 定义max_depth的取值范围
grid_min_samples [5,10,.03,.05,.10] # 定义min_samples_split和min_samples_leaf的取值范围
grid_criterion [gini, entropy] # 定义criterion的取值范围
grid_bool [True, False] # 定义bool类型的取值范围
grid_seed [0] # 定义random_state的取值范围vote_param [{
# #http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.AdaBoostClassifier.htmlada__n_estimators: grid_n_estimator, # AdaBoostClassifier的n_estimators参数取值范围ada__learning_rate: grid_ratio, # AdaBoostClassifier的learning_rate参数取值范围ada__algorithm: [SAMME, SAMME.R], # AdaBoostClassifier的algorithm参数取值范围ada__random_state: grid_seed, # AdaBoostClassifier的random_state参数取值范围#http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.BaggingClassifier.html#sklearn.ensemble.BaggingClassifierbc__n_estimators: grid_n_estimator, # BaggingClassifier的n_estimators参数取值范围bc__max_samples: grid_ratio, # BaggingClassifier的max_samples参数取值范围bc__oob_score: grid_bool, # BaggingClassifier的oob_score参数取值范围bc__random_state: grid_seed, # BaggingClassifier的random_state参数取值范围#http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.ExtraTreesClassifier.html#sklearn.ensemble.ExtraTreesClassifieretc__n_estimators: grid_n_estimator, # ExtraTreesClassifier的n_estimators参数取值范围etc__criterion: grid_criterion, # ExtraTreesClassifier的criterion参数取值范围etc__max_depth: grid_max_depth, # ExtraTreesClassifier的max_depth参数取值范围etc__random_state: grid_seed, # ExtraTreesClassifier的random_state参数取值范围#http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingClassifier.html#sklearn.ensemble.GradientBoostingClassifiergbc__loss: [deviance, exponential], # GradientBoostingClassifier的loss参数取值范围gbc__learning_rate: grid_ratio, # GradientBoostingClassifier的learning_rate参数取值范围gbc__n_estimators: grid_n_estimator, # GradientBoostingClassifier的n_estimators参数取值范围gbc__criterion: [friedman_mse, mse, mae], # GradientBoostingClassifier的criterion参数取值范围gbc__max_depth: grid_max_depth, # GradientBoostingClassifier的max_depth参数取值范围gbc__min_samples_split: grid_min_samples, # GradientBoostingClassifier的min_samples_split参数取值范围gbc__min_samples_leaf: grid_min_samples, # GradientBoostingClassifier的min_samples_leaf参数取值范围 gbc__random_state: grid_seed, # GradientBoostingClassifier的random_state参数取值范围#http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html#sklearn.ensemble.RandomForestClassifierrfc__n_estimators: grid_n_estimator, # RandomForestClassifier的n_estimators参数取值范围rfc__criterion: grid_criterion, # RandomForestClassifier的criterion参数取值范围rfc__max_depth: grid_max_depth, # RandomForestClassifier的max_depth参数取值范围rfc__min_samples_split: grid_min_samples, # RandomForestClassifier的min_samples_split参数取值范围rfc__min_samples_leaf: grid_min_samples, # RandomForestClassifier的min_samples_leaf参数取值范围 rfc__bootstrap: grid_bool, # RandomForestClassifier的bootstrap参数取值范围rfc__oob_score: grid_bool, # RandomForestClassifier的oob_score参数取值范围rfc__random_state: grid_seed, # RandomForestClassifier的random_state参数取值范围#http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegressionCV.html#sklearn.linear_model.LogisticRegressionCVlr__fit_intercept: grid_bool, # LogisticRegressionCV的fit_intercept参数取值范围lr__penalty: [l1,l2], # LogisticRegressionCV的penalty参数取值范围lr__solver: [newton-cg, lbfgs, liblinear, sag, saga], # LogisticRegressionCV的solver参数取值范围lr__random_state: grid_seed, # LogisticRegressionCV的random_state参数取值范围#http://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.BernoulliNB.html#sklearn.naive_bayes.BernoulliNBbnb__alpha: grid_ratio, # BernoulliNB的alpha参数取值范围bnb__prior: grid_bool, # BernoulliNB的prior参数取值范围bnb__random_state: grid_seed, # BernoulliNB的random_state参数取值范围#http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html#sklearn.neighbors.KNeighborsClassifierknn__n_neighbors: [1,2,3,4,5,6,7], # KNeighborsClassifier的n_neighbors参数取值范围knn__weights: [uniform, distance], # KNeighborsClassifier的weights参数取值范围knn__algorithm: [auto, ball_tree, kd_tree, brute], # KNeighborsClassifier的algorithm参数取值范围knn__random_state: grid_seed, # KNeighborsClassifier的random_state参数取值范围#http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html#sklearn.svm.SVC#http://blog.hackerearth.com/simple-tutorial-svm-parameter-tuning-python-rsvc__kernel: [linear, poly, rbf, sigmoid], # SVC的kernel参数取值范围svc__C: grid_max_depth, # SVC的C参数取值范围svc__gamma: grid_ratio, # SVC的gamma参数取值范围svc__decision_function_shape: [ovo, ovr], # SVC的decision_function_shape参数取值范围svc__probability: [True], # SVC的probability参数取值范围svc__random_state: grid_seed, # SVC的random_state参数取值范围#http://xgboost.readthedocs.io/en/latest/parameter.htmlxgb__learning_rate: grid_ratio, # XGBClassifier的learning_rate参数取值范围xgb__max_depth: [2,4,6,8,10], # XGBClassifier的max_depth参数取值范围xgb__tree_method: [exact, approx, hist], # XGBClassifier的tree_method参数取值范围xgb__objective: [reg:linear, reg:logistic, binary:logistic], # XGBClassifier的objective参数取值范围xgb__seed: grid_seed # XGBClassifier的seed参数取值范围 }]#Soft Vote with tuned models
#grid_soft model_selection.GridSearchCV(estimator vote_soft, param_grid vote_param, cv 2, scoring roc_auc)
#grid_soft.fit(data1[data1_x_bin], data1[Target])#print(grid_soft.cv_results_.keys())
#print(grid_soft.cv_results_[params])
#print(Soft Vote Tuned Parameters: , grid_soft.best_params_)
#print(grid_soft.cv_results_[mean_train_score])
#print(Soft Vote Tuned Training w/bin set score mean: {:.2f}. format(grid_soft.cv_results_[mean_train_score][tune_model.best_index_]*100))
#print(grid_soft.cv_results_[mean_test_score])
#print(Soft Vote Tuned Test w/bin set score mean: {:.2f}. format(grid_soft.cv_results_[mean_test_score][tune_model.best_index_]*100))
#print(Soft Vote Tuned Test w/bin score 3*std: /- {:.2f}. format(grid_soft.cv_results_[std_test_score][tune_model.best_index_]*100*3))
#print(-*10)#credit: https://rasbt.github.io/mlxtend/user_guide/classifier/EnsembleVoteClassifier/
#cv_keys (mean_test_score, std_test_score, params)
#for r, _ in enumerate(grid_soft.cv_results_[mean_test_score]):
# print(%0.3f /- %0.2f %r
# % (grid_soft.cv_results_[cv_keys[0]][r],
# grid_soft.cv_results_[cv_keys[1]][r] / 2.0,
# grid_soft.cv_results_[cv_keys[2]][r]))#print(-*10)#WARNING: Running is very computational intensive and time expensive.
#Code is written for experimental/developmental purposes and not production ready!#定义一些超参数的取值范围
grid_n_estimator [10, 50, 100, 300] #AdaBoostClassifier和BaggingClassifier的n_estimators参数的取值范围
grid_ratio [.1, .25, .5, .75, 1.0] #BaggingClassifier的max_samples参数的取值范围和SVC的gamma参数的取值范围
grid_learn [.01, .03, .05, .1, .25] #AdaBoostClassifier和GradientBoostingClassifier的learning_rate参数的取值范围
grid_max_depth [2, 4, 6, 8, 10, None] #ExtraTreesClassifier和GradientBoostingClassifier的max_depth参数的取值范围
grid_min_samples [5, 10, .03, .05, .10] #暂时没有使用到
grid_criterion [gini, entropy] #ExtraTreesClassifier和RandomForestClassifier的criterion参数的取值范围
grid_bool [True, False] #LogisticRegressionCV的fit_intercept参数的取值范围
grid_seed [0] #随机种子#定义一些模型的参数组合
grid_param [[{#AdaBoostClassifier - http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.AdaBoostClassifier.htmln_estimators: grid_n_estimator, #default50learning_rate: grid_learn, #default1#algorithm: [SAMME, SAMME.R], #default’SAMME.Rrandom_state: grid_seed}],[{#BaggingClassifier - http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.BaggingClassifier.html#sklearn.ensemble.BaggingClassifiern_estimators: grid_n_estimator, #default10max_samples: grid_ratio, #default1.0random_state: grid_seed}],[{#ExtraTreesClassifier - http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.ExtraTreesClassifier.html#sklearn.ensemble.ExtraTreesClassifiern_estimators: grid_n_estimator, #default10criterion: grid_criterion, #default”gini”max_depth: grid_max_depth, #defaultNonerandom_state: grid_seed}],[{#GradientBoostingClassifier - http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingClassifier.html#sklearn.ensemble.GradientBoostingClassifier#loss: [deviance, exponential], #default’deviance’learning_rate: [.05], #default0.1 -- 12/31/17 set to reduce runtime -- The best parameter for GradientBoostingClassifier is {learning_rate: 0.05, max_depth: 2, n_estimators: 300, random_state: 0} with a runtime of 264.45 seconds.n_estimators: [300], #default100 -- 12/31/17 set to reduce runtime -- The best parameter for GradientBoostingClassifier is {learning_rate: 0.05, max_depth: 2, n_estimators: 300, random_state: 0} with a runtime of 264.45 seconds.#criterion: [friedman_mse, mse, mae], #default”friedman_mse”max_depth: grid_max_depth, #default3 random_state: grid_seed}],[{#RandomForestClassifier - http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html#sklearn.ensemble.RandomForestClassifiern_estimators: grid_n_estimator, #default10criterion: grid_criterion, #default”gini”max_depth: grid_max_depth, #defaultNoneoob_score: [True], #defaultFalse -- 12/31/17 set to reduce runtime -- The best parameter for RandomForestClassifier is {criterion: entropy, max_depth: 6, n_estimators: 100, oob_score: True, random_state: 0} with a runtime of 146.35 seconds.random_state: grid_seed}],[{ #GaussianProcessClassifiermax_iter_predict: grid_n_estimator, #default: 100random_state: grid_seed}],[{#LogisticRegressionCV - http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegressionCV.html#sklearn.linear_model.LogisticRegressionCVfit_intercept: grid_bool, #default: True#penalty: [l1,l2],solver: [newton-cg, lbfgs, liblinear, sag, saga], #default: lbfgsrandom_state: grid_seed}],[{#BernoulliNB - http://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.BernoulliNB.html#sklearn.naive_bayes.BernoulliNBalpha: grid_ratio, #default: 1.0}],#GaussianNB - [{}],[{#KNeighborsClassifier - http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html#sklearn.neighbors.KNeighborsClassifiern_neighbors: [1,2,3,4,5,6,7], #default: 5weights: [uniform, distance], #default ‘uniform’algorithm: [auto, ball_tree, kd_tree, brute]}],[{#SVC - http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html#sklearn.svm.SVC#http://blog.hackerearth.com/simple-tutorial-svm-parameter-tuning-python-r#kernel: [linear, poly, rbf, sigmoid],C: [1,2,3,4,5], #default1.0gamma: grid_ratio, #edfault: autodecision_function_shape: [ovo, ovr], #default:ovrprobability: [True],random_state: grid_seed}],[{#XGBClassifier - http://xgboost.readthedocs.io/en/latest/parameter.htmllearning_rate: grid_learn, #default: .3max_depth: [1,2,4,6,8,10], #default 2n_estimators: grid_n_estimator, seed: grid_seed }] ]start_total time.perf_counter() #记录总的运行时间
for clf, param in zip (vote_est, grid_param): #对于每个模型和其对应的参数组合进行遍历start time.perf_counter() best_search model_selection.GridSearchCV(estimator clf[1], param_grid param, cv cv_split, scoring roc_auc) #使用GridSearchCV进行参数搜索best_search.fit(data1[data1_x_bin], data1[Target]) #在训练集上进行参数搜索run time.perf_counter() - start #记录每个模型的运行时间best_param best_search.best_params_ #获取最佳参数print(The best parameter for {} is {} with a runtime of {:.2f} seconds..format(clf[1].__class__.__name__, best_param, run))clf[1].set_params(**best_param) #将最佳参数设置给模型run_total time.perf_counter() - start_total #记录总的运行时间
print(Total optimization time was {:.2f} minutes..format(run_total/60))print(-*10)The best parameter for AdaBoostClassifier is {learning_rate: 0.1, n_estimators: 300, random_state: 0} with a runtime of 37.28 seconds.
The best parameter for BaggingClassifier is {max_samples: 0.25, n_estimators: 300, random_state: 0} with a runtime of 33.04 seconds.
The best parameter for ExtraTreesClassifier is {criterion: entropy, max_depth: 6, n_estimators: 100, random_state: 0} with a runtime of 68.93 seconds.
The best parameter for GradientBoostingClassifier is {learning_rate: 0.05, max_depth: 2, n_estimators: 300, random_state: 0} with a runtime of 38.77 seconds.
The best parameter for RandomForestClassifier is {criterion: entropy, max_depth: 6, n_estimators: 100, oob_score: True, random_state: 0} with a runtime of 84.14 seconds.
The best parameter for GaussianProcessClassifier is {max_iter_predict: 10, random_state: 0} with a runtime of 6.19 seconds.
The best parameter for LogisticRegressionCV is {fit_intercept: True, random_state: 0, solver: liblinear} with a runtime of 9.40 seconds.
The best parameter for BernoulliNB is {alpha: 0.1} with a runtime of 0.24 seconds.
The best parameter for GaussianNB is {} with a runtime of 0.05 seconds.
The best parameter for KNeighborsClassifier is {algorithm: brute, n_neighbors: 7, weights: uniform} with a runtime of 5.56 seconds.
The best parameter for SVC is {C: 2, decision_function_shape: ovo, gamma: 0.1, probability: True, random_state: 0} with a runtime of 30.49 seconds.
The best parameter for XGBClassifier is {learning_rate: 0.01, max_depth: 4, n_estimators: 300, seed: 0} with a runtime of 43.57 seconds.
Total optimization time was 5.96 minutes.
----------# 导入所需的库# 创建一个Hard Voting分类器使用之前定义的vote_est模型列表voting方式为hard
grid_hard ensemble.VotingClassifier(estimators vote_est , voting hard)# 使用交叉验证对Hard Voting分类器进行评估使用data1[data1_x_bin]作为特征数据data1[Target]作为目标数据cv参数为cv_split
grid_hard_cv model_selection.cross_validate(grid_hard, data1[data1_x_bin], data1[Target], cv cv_split)# 使用data1[data1_x_bin]和data1[Target]对Hard Voting分类器进行训练
grid_hard.fit(data1[data1_x_bin], data1[Target])# 打印Hard Voting分类器在训练集上的平均得分
print(Hard Voting w/Tuned Hyperparameters Training w/bin score mean: {:.2f}. format(grid_hard_cv[train_score].mean()*100)) # 打印Hard Voting分类器在测试集上的平均得分
print(Hard Voting w/Tuned Hyperparameters Test w/bin score mean: {:.2f}. format(grid_hard_cv[test_score].mean()*100))# 打印Hard Voting分类器在测试集上的得分的3倍标准差
print(Hard Voting w/Tuned Hyperparameters Test w/bin score 3*std: /- {:.2f}. format(grid_hard_cv[test_score].std()*100*3))
print(-*10)# 创建一个Soft Voting分类器使用之前定义的vote_est模型列表voting方式为soft
grid_soft ensemble.VotingClassifier(estimators vote_est , voting soft)# 使用交叉验证对Soft Voting分类器进行评估使用data1[data1_x_bin]作为特征数据data1[Target]作为目标数据cv参数为cv_split
grid_soft_cv model_selection.cross_validate(grid_soft, data1[data1_x_bin], data1[Target], cv cv_split)# 使用data1[data1_x_bin]和data1[Target]对Soft Voting分类器进行训练
grid_soft.fit(data1[data1_x_bin], data1[Target])# 打印Soft Voting分类器在训练集上的平均得分
print(Soft Voting w/Tuned Hyperparameters Training w/bin score mean: {:.2f}. format(grid_soft_cv[train_score].mean()*100)) # 打印Soft Voting分类器在测试集上的平均得分
print(Soft Voting w/Tuned Hyperparameters Test w/bin score mean: {:.2f}. format(grid_soft_cv[test_score].mean()*100))# 打印Soft Voting分类器在测试集上的得分的3倍标准差
print(Soft Voting w/Tuned Hyperparameters Test w/bin score 3*std: /- {:.2f}. format(grid_soft_cv[test_score].std()*100*3))
print(-*10)# 输出各个分类器的最佳参数和运行时间
# AdaBoostClassifier的最佳参数是{learning_rate: 0.1, n_estimators: 300, random_state: 0}运行时间为33.39秒
# BaggingClassifier的最佳参数是{max_samples: 0.25, n_estimators: 300, random_state: 0}运行时间为30.28秒
# ExtraTreesClassifier的最佳参数是{criterion: entropy, max_depth: 6, n_estimators: 100, random_state: 0}运行时间为64.76秒
# GradientBoostingClassifier的最佳参数是{learning_rate: 0.05, max_depth: 2, n_estimators: 300, random_state: 0}运行时间为34.35秒
# RandomForestClassifier的最佳参数是{criterion: entropy, max_depth: 6, n_estimators: 100, oob_score: True, random_state: 0}运行时间为76.32秒
# GaussianProcessClassifier的最佳参数是{max_iter_predict: 10, random_state: 0}运行时间为6.01秒
# LogisticRegressionCV的最佳参数是{fit_intercept: True, random_state: 0, solver: liblinear}运行时间为8.04秒
# BernoulliNB的最佳参数是{alpha: 0.1}运行时间为0.19秒
# GaussianNB的最佳参数是{}运行时间为0.04秒
# KNeighborsClassifier的最佳参数是{algorithm: brute, n_neighbors: 7, weights: uniform}运行时间为4.84秒
# SVC的最佳参数是{C: 2, decision_function_shape: ovo, gamma: 0.1, probability: True, random_state: 0}运行时间为29.39秒
# XGBClassifier的最佳参数是{learning_rate: 0.01, max_depth: 4, n_estimators: 300, seed: 0}运行时间为46.23秒
# 总优化时间为5.56分钟。Hard Voting w/Tuned Hyperparameters Training w/bin score mean: 85.22
Hard Voting w/Tuned Hyperparameters Test w/bin score mean: 82.31
Hard Voting w/Tuned Hyperparameters Test w/bin score 3*std: /- 5.26
----------
Soft Voting w/Tuned Hyperparameters Training w/bin score mean: 84.76
Soft Voting w/Tuned Hyperparameters Test w/bin score mean: 82.28
Soft Voting w/Tuned Hyperparameters Test w/bin score 3*std: /- 5.42
----------# 准备数据进行建模# 打印数据信息
print(data_val.info())
print(-*10)# 手工决策树 - 提交得分 0.77990
# 将Survived列设置为mytree函数的返回值并转换为整数类型
data_val[Survived] mytree(data_val).astype(int)# 决策树建模 - 使用完整数据集进行建模提交得分默认0.76555调整后0.77990
# 使用决策树分类器进行建模
# submit_dt tree.DecisionTreeClassifier()
# submit_dt model_selection.GridSearchCV(tree.DecisionTreeClassifier(), param_gridparam_grid, scoringroc_auc, cvcv_split)
# submit_dt.fit(data1[data1_x_bin], data1[Target])
# print(Best Parameters: , submit_dt.best_params_) # 最佳参数: {criterion: gini, max_depth: 4, random_state: 0}
# 将Survived列设置为submit_dt.predict函数的返回值
# data_val[Survived] submit_dt.predict(data_val[data1_x_bin])# Bagging建模 - 使用完整数据集进行建模提交得分默认0.75119调整后0.77990
# 使用Bagging分类器进行建模
# submit_bc ensemble.BaggingClassifier()
# submit_bc model_selection.GridSearchCV(ensemble.BaggingClassifier(), param_grid{n_estimators:grid_n_estimator, max_samples: grid_ratio, oob_score: grid_bool, random_state: grid_seed}, scoringroc_auc, cvcv_split)
# submit_bc.fit(data1[data1_x_bin], data1[Target])
# print(Best Parameters: , submit_bc.best_params_) # 最佳参数: {max_samples: 0.25, n_estimators: 500, oob_score: True, random_state: 0}
# 将Survived列设置为submit_bc.predict函数的返回值
# data_val[Survived] submit_bc.predict(data_val[data1_x_bin])# Extra Tree建模 - 使用完整数据集进行建模提交得分默认0.76555调整后0.77990
# 使用Extra Trees分类器进行建模
# submit_etc ensemble.ExtraTreesClassifier()
# submit_etc model_selection.GridSearchCV(ensemble.ExtraTreesClassifier(), param_grid{n_estimators: grid_n_estimator, criterion: grid_criterion, max_depth: grid_max_depth, random_state: grid_seed}, scoringroc_auc, cvcv_split)
# submit_etc.fit(data1[data1_x_bin], data1[Target])
# print(Best Parameters: , submit_etc.best_params_) # 最佳参数: {criterion: entropy, max_depth: 6, n_estimators: 100, random_state: 0}
# 将Survived列设置为submit_etc.predict函数的返回值
# data_val[Survived] submit_etc.predict(data_val[data1_x_bin])# Random Forest建模 - 使用完整数据集进行建模提交得分默认0.71291调整后0.73205
# 使用Random Forest分类器进行建模
# submit_rfc ensemble.RandomForestClassifier()
# submit_rfc model_selection.GridSearchCV(ensemble.RandomForestClassifier(), param_grid{n_estimators: grid_n_estimator, criterion: grid_criterion, max_depth: grid_max_depth, random_state: grid_seed}, scoringroc_auc, cvcv_split)
# submit_rfc.fit(data1[data1_x_bin], data1[Target])
# print(Best Parameters: , submit_rfc.best_params_) # 最佳参数: {criterion: entropy, max_depth: 6, n_estimators: 100, random_state: 0}
# 将Survived列设置为submit_rfc.predict函数的返回值
# data_val[Survived] submit_rfc.predict(data_val[data1_x_bin])# Ada Boosting建模 - 使用完整数据集进行建模提交得分默认0.74162调整后0.75119
# 使用Ada Boosting分类器进行建模
# submit_abc ensemble.AdaBoostClassifier()
# submit_abc model_selection.GridSearchCV(ensemble.AdaBoostClassifier(), param_grid{n_estimators: grid_n_estimator, learning_rate: grid_ratio, algorithm: [SAMME, SAMME.R], random_state: grid_seed}, scoringroc_auc, cvcv_split)
# submit_abc.fit(data1[data1_x_bin], data1[Target])
# print(Best Parameters: , submit_abc.best_params_) # 最佳参数: {algorithm: SAMME.R, learning_rate: 0.1, n_estimators: 300, random_state: 0}
# 将Survived列设置为submit_abc.predict函数的返回值
# data_val[Survived] submit_abc.predict(data_val[data1_x_bin])# Gradient Boosting建模 - 使用完整数据集进行建模提交得分默认0.75119调整后0.77033
# 使用Gradient Boosting分类器进行建模
# submit_gbc ensemble.GradientBoostingClassifier()
# submit_gbc model_selection.GridSearchCV(ensemble.GradientBoostingClassifier(), param_grid{learning_rate: grid_ratio, n_estimators: grid_n_estimator, max_depth: grid_max_depth, random_state:grid_seed}, scoringroc_auc, cvcv_split)
# submit_gbc.fit(data1[data1_x_bin], data1[Target])
# print(Best Parameters: , submit_gbc.best_params_) # 最佳参数: {learning_rate: 0.25, max_depth: 2, n_estimators: 50, random_state: 0}
# 将Survived列设置为submit_gbc.predict函数的返回值
# data_val[Survived] submit_gbc.predict(data_val[data1_x_bin])# Extreme Boosting建模 - 使用完整数据集进行建模提交得分默认0.73684调整后0.77990
# 使用Extreme Boosting分类器进行建模
# submit_xgb XGBClassifier()
# submit_xgb model_selection.GridSearchCV(XGBClassifier(), param_grid{learning_rate: grid_learn, max_depth: [0,2,4,6,8,10], n_estimators: grid_n_estimator, seed: grid_seed}, scoringroc_auc, cvcv_split)
# submit_xgb.fit(data1[data1_x_bin], data1[Target])
# print(Best Parameters: , submit_xgb.best_params_) # 最佳参数: {learning_rate: 0.01, max_depth: 4, n_estimators: 300, seed: 0}
# 将Survived列设置为submit_xgb.predict函数的返回值
# data_val[Survived] submit_xgb.predict(data_val[data1_x_bin])# Hard Voting分类器 - 使用完整数据集进行建模提交得分默认0.75598调整后0.77990
# 将Survived列设置为grid_hard.predict函数的返回值
data_val[Survived] grid_hard.predict(data_val[data1_x_bin])# Soft Voting分类器 - 使用完整数据集进行建模提交得分默认0.73684调整后0.74162
# 将Survived列设置为vote_soft.predict函数的返回值
# data_val[Survived] vote_soft.predict(data_val[data1_x_bin])
# data_val[Survived] grid_soft.predict(data_val[data1_x_bin])# 提交文件
submit data_val[[PassengerId,Survived]]
submit.to_csv(../working/submit.csv, indexFalse)# 打印验证数据分布
print(Validation Data Distribution: \n, data_val[Survived].value_counts(normalizeTrue))
# 随机抽取10个样本
submit.sample(10)class pandas.core.frame.DataFrame
RangeIndex: 418 entries, 0 to 417
Data columns (total 21 columns):
PassengerId 418 non-null int64
Pclass 418 non-null int64
Name 418 non-null object
Sex 418 non-null object
Age 418 non-null float64
SibSp 418 non-null int64
Parch 418 non-null int64
Ticket 418 non-null object
Fare 418 non-null float64
Cabin 91 non-null object
Embarked 418 non-null object
FamilySize 418 non-null int64
IsAlone 418 non-null int64
Title 418 non-null object
FareBin 418 non-null category
AgeBin 418 non-null category
Sex_Code 418 non-null int64
Embarked_Code 418 non-null int64
Title_Code 418 non-null int64
AgeBin_Code 418 non-null int64
FareBin_Code 418 non-null int64
dtypes: category(2), float64(2), int64(11), object(6)
memory usage: 63.1 KB
None
----------
Validation Data Distribution: 0 0.633971
1 0.366029
Name: Survived, dtype: float64PassengerIdSurvived113100516996117096211911083037612681379291469381236112802941186036612580 第七步优化和策略
结论
数据科学框架的第一次迭代似乎收敛于0.77990的提交准确率。使用相同的数据集和不同的决策树实现adaboost、随机森林、梯度提升、xgboost等进行调优都无法超过0.77990的提交准确率。有趣的是在这个数据集中简单的决策树算法具有最佳的默认提交分数并且通过调优实现了相同的最佳准确率。
虽然在单个数据集上测试少数算法无法得出一般性结论但对于提到的数据集有几点观察结果
训练数据集与测试/验证数据集和总体人口的分布不同。这导致交叉验证CV准确率和Kaggle提交准确率之间存在较大差距。在相同的数据集下基于决策树的算法在适当的调优后似乎收敛于相同的准确率。尽管经过调优没有机器学习算法能够超过自制算法。作者认为对于小数据集来说人工算法是要超越的标杆。
基于这些观察结果对于第二次迭代我将花更多时间在预处理和特征工程上以更好地对齐CV分数和Kaggle分数并提高整体准确率。