以 Titanic 为例,如下是数据挖掘 workflow 总结。html
明确任务目标:预测泰坦尼克号的乘客是否生还。它是个二分类任务,生还为1,不然为0。正则表达式
# data analysis and wrangling import pandas as pd import numpy as np import random as rnd
# visualization import seaborn as sns import matplotlib.pyplot as plt # machine learning from sklearn.linear_model import LogisticRegression from sklearn.svm import SVC,LinearSVC from sklearn.ensemble import RandomForestClassifierfrom sklearn.tree import DecisionTreeClassifier ......
使用Pandas DataFrame读取数据。
# 使用Pandas DataFrame读取数据 train_df = pd.read_csv('./xxx/train.csv') test_df = pd.read_csv('./xxx/test.csv') combine = [train_df, test_df]
# column 列名 index 行名 查看总共有哪些特征
print(train_df.columns.values)
# preview the data
train_df.head() train_df.tail()
# 查看数据类型和缺失值
train_df.info() print('_'*40) test_df.info()
# 查看数据离散分布状况
train_df.describe()
# 只输出离散型变量的分布状况
train_df.describe(include=['O'])
下图介绍了不一样的数据类型。数据能够按 Nominal(名义)、Ordinal(顺序)、Interval(区间) 以及 Ratio(比率) 分;也能够按 Discrete (离散)、Continuous (连续)分;还能按照 Int (整数)、Float (浮点数)或者 String (字符串)、Object (对象)区分。算法
Correlatingapp
咱们想知道哪些特征与 Survival 相关。dom
Completing机器学习
Correcting学习
Creating测试
Classifingui
特征,即变量。在建模以前,咱们要寻找与预测结果显著相关的特征【特征选择】,判断哪些特征与预测结果具有显著相关性(正相关或者负相关)。spa
为了证明咱们的假设,咱们能够经过旋转特征来分析特征的相关性。在这一阶段,咱们只能分析不存在缺失值的特征。好比 categorical(Sex)、ordinal(Pclass)以及discrete(SibSp,Parch)类型的特征。
# 分别计算一等座、二等座、三等座的存活率,并按存活率从高到低进行排序 train_df[['Pclass', 'Survived']].groupby(['Pclass'],as_index=False).mean().sort_values(by='Survived', ascending=False) # 得出结果 存活率:一等座>二等座>三等座 # 分别计算男性和女性的存活率,并按存活率从高到低排序 train_df[['Sex','Survived']].groupby(['Sex'],as_index=False).mean().sort_values(by='Survived',ascending=False) # 得出结论 存活率:女性>男性 # 分别计算不一样的配偶和兄弟姐妹数量的存活率,并按存活率从高到低排序 train_df[['SibSp','Survived']].groupby(['SibSp'],as_index=False).mean().sort_values(by='Survived',ascending=False) # 分别计算不一样的父母和子女数量的存活率,并按存活率从高到低排序 train_df[['Parch','Survived']].groupby(['Parch'],as_index=False).mean().sort_values(by='Survived',ascending=False) # 没有规律可循,后面建立新特征查看
直方图对于分析连续的数值变量(好比 Age )颇有用,可以经过形状以及范围来识别样本特征。直方图还能够指定样本分布的区间,有助于咱们分析特定问题(婴儿的生还率是否更高?)。
X轴:Age
Y轴:Survived
这一阶段的分析帮助咱们证明假设并为后面的工做做出决定。
这是一个很好的开头。经过删除特征,咱们能够处理更少的数据点,提升运行速度,简化分析。
根据咱们的 assumptions 和 decisions ,咱们将删除Cabin(correcting #2)和Ticket(Correcting #1)特征。
注意,在合适的状况下,咱们同时对训练集和测试集执行操做,以保持一致。
print("Before", train_df.shape, test_df.shape, combine[0].shape, combine[1].shape)
# 删除特征 train_df = train_df.drop(['Ticket','Cabin'], axis=1) test_df = test_df.drop(['Ticket','Cabin'], axis = 1) combine = [train_df, test_df] "After",train_df.shape, test_df.shape,combine[0].shape,combine[1].shape
在删除 Name 和 Passengerid 特征以前,咱们尝试从 Name 提取 Title 特征 (头衔/称谓),并测试 Title 和 survival 之间的相关性。
在下面的代码中,咱们使用正则表达式提取 Title 特征。RegEx pattern (\w+\)
匹配 Name 特征中以点字符结尾的第一个单词。expand=false
标志返回 Dataframe。
# 使用正则表达式提取 Title 特征。RegEx pattern (\w+\) 匹配 Name 特征中以点字符结尾的第一个单词。expand=false 标志返回 Dataframe。 for dataset in combine: dataset['Title'] = dataset.Name.str.extract('([A-Za-z]+)\.', expand=False) pd.crosstab(train_df['Title'],train_df['Sex']) # 用更加常见的名称来替换大量 titles ,或者将它们归类为 Rare(稀有的)。 for dataset in combine: dataset['Title'] = dataset['Title'].replace(['Lady','Countess','Capt','Col',\ 'Don','Dr','Major','Rev','Sir','Jonkheer','Dona'],'Rare') dataset['Title'] = dataset['Title'].replace('Mlle','Miss') dataset['Title'] = dataset['Title'].replace('Ms','Miss') dataset['Title'] = dataset['Title'].replace('Mme','Mrs') train_df[['Title','Survived']].groupby(['Title'], as_index=False).mean() # 将分类变量(categorical)转换为顺序变量(ordinal)。 title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5} for dataset in combine: dataset['Title'] = dataset['Title'].map(title_mapping) dataset['Title'] = dataset['Title'].fillna(0) train_df.head()
Embarked 特征涵盖 S、Q、C 值。咱们的训练集缺乏两个值。咱们简单地用众数来进行填充。
# 众数填充 freq_port = train_df.Embarked.dropna().mode()[0] for dataset in combine: dataset['Embarked'] = dataset['Embarked'].fillna(freq_port) # 旋转特征分析 train_df[['Embarked','Survived']].groupby(['Embarked'],as_index=False).mean().sort_values(by='Survived',ascending=False)
结合 Parch 和 Sibsp, 为 FamilySize 建立一个新特征。这使咱们可以从数据集中删除 Parch 和 Sibsp 。
for dataset in combine: dataset['FamilySize']=dataset['SibSp'] + dataset['Parch']+1 train_df[['FamilySize','Survived']].groupby(['FamilySize'],as_index=False).mean().sort_values(by='Survived',ascending=False) # 建立一个名为 IsAlone 的新特征 for dataset in combine: dataset['IsAlone'] = 0 dataset.loc[dataset['FamilySize']==1,'IsAlone']=1 train_df[['IsAlone','Survived']].groupby(['IsAlone'], as_index=False).mean()
如今,将包含字符串的特征转换为数值。这是大多数模型算法所要求的,同时也将帮助咱们实现特征 completing 的目标。
首先,将 sex 特征转换为一个名为 gender 的新特征,其中 female=1,male=0。
for dataset in combine: dataset['Sex'] = dataset['Sex'].map({'female':1, 'male':0}).astype(int) train_df.head()
使用 mode 获取 Fare 特征最常出现的值并填充测试集中存在单个缺失值的 Fare 特征。
test_df['Fare'].fillna(test_df['Fare'].dropna().median(),inplace=True) test_df.head() # 建立新特征 FareBand train_df['FareBand'] = pd.qcut(train_df['Fare'],4) train_df[['FareBand','Survived']].groupby(['FareBand'],as_index=False).mean().sort_values(by='Survived',ascending=True) # 基于 FareBand 将 Fare 特征转换为 顺序级 for dataset in combine: dataset.loc[ dataset['Fare'] <= 7.91, 'Fare'] = 0 dataset.loc[(dataset['Fare'] > 7.91) & (dataset['Fare'] <= 14.454), 'Fare'] = 1 dataset.loc[(dataset['Fare'] > 14.454) & (dataset['Fare'] <= 31), 'Fare'] = 2 dataset.loc[ dataset['Fare'] > 31, 'Fare'] = 3 dataset['Fare'] = dataset['Fare'].astype(int) train_df = train_df.drop(['FareBand'], axis=1) combine = [train_df, test_df] train_df.head(10)
如今,训练模型并预测解决方案。有60多种预测建模算法可供选择。咱们必须了解问题的类型和解决方案的要求,以便将建模算法的选择范围缩小。咱们的问题是一个分类和回归问题,肯定输出(存活与否)与其余变量或特征(性别、年龄、港口…)之间的关系。当咱们使用给定的数据集训练模型时,咱们也在执行一类称为监督学习的机器学习。有了这两个准则——监督学习加上分类和回归,咱们能够将模型的选择范围缩小到少数。其中包括:
随机森林模型是最流行的模型之一。随机森林或随机决策森林是一种用于分类、回归和其余任务的集成学习方法。它在训练时构造多个决策树(n_estimators=100),并经过输出类别(分类)或预测个别树均值(回归)来输出分类结果。-参考维基百科。
到目前为止,随机森林模型的置信度得分是全部模型中最高的。咱们决定使用此模型的输出(y_pred)来提交预测结果。
# Random Forrest random_forest = RandomForestClassifier(n_estimators=100) random_forest.fit(X_train, Y_train) Y_pred = random_forest.predict(X_test) acc_random_forest = round(random_forest.score(X_train, Y_train)*100, 2) acc_random_forest
保存预测结果。
submission = pd.DataFrame({ "PassengerId": test_df["PassengerId"], "Survived": Y_pred }) submission.to_csv('submission.csv', index=False)