Kaggle项目Titanic挑战最高分,特征工程

数据挖掘(Data Mining)是要从大量看似无序的数据中通过算法找到其中隐藏的信息和模式的过程,主要包括有监督的分类、预测和无监督的聚类、相关性分组等方法,

比较经典的应用场景如垃圾邮件检测(spam email detection)、“啤酒和尿不湿”故事等。

一般来说,解决数据挖掘类的问题没有一步到位的方法,都要经过不断尝试、反复分析优化的过程。

大致来说,遵循下而这些“套路”:

  • 首先通过数据可视化,利用图形的方式更直观地感受数据,建立起足够的先验经验,
  • 然后利用特征工程方法筛选相关度最高的特征组合,
  • 最后将特征代入多种分类器进行试验,检验不同方法在同一问题上的表现。

数据可视化

面对庞大的数据,仅仅依靠人脑很难建立起对数据的充分认识,使用工具以图形化的形式将数据展示山来,是必不可少的手段。

Titanic 问题的样本数据只有不到1000 条,都有哪些可视化手段呢?下面这几种方式是Kaggle 讨论组中给出的方案,可以作为参考。 ( https://www.kaggle.com/c/titanic/prospector#208

通过性别、客舱等级和是否有家人陪伴三个维度来考察幸存率。

Titanic 数据中是有家人陪伴的幸存率

分析出如下几个结论:

  1. 同等客舱的乘客中,女性乘客的幸存率普遍高于男性乘客。并且一等、二等客舱的女性乘客幸存率都非常高;
  2. 一等、二等客舱的乘客中,有家人陪伴的会比独自乘船的存活率高;
  3. 三等客舱中,独自乘船的乘客比有亲属的幸存率高。其中独自乘船的女性有超过 50% 幸存了下来。
  4. 三等客舱的男性幸存概率具有20%左右

有了这样的分析结果,相信如果仅以创建规则的方式来判断乘客的存活率也能有不错的表现。

另一种有趣的图形化方式是根据姓名,画出乘客的家族结构。

(https://www.kaggle.com/c/titanic/prospector#208)

一等舱乘客的家庭关系,可以看到一等舱乘客某本都是家庭结伴而行的。

再有一种比较有价值的分析是通过图形的方法,查看各个数据字段的重要程度。

上图展示了对于随机森林算法而言,各个数据字段的重要程度,及重要度的标准差。
可以看到,性别一项的重要度最高,其次是年龄。

通过这几种可视化分析的方法,从数据上验证了最初分析时提出的一些基础先验经验,比如女性和儿童的幸在率高,有身份的乘客幸存率高等,对于深入理解问题有极大帮助。

特征工程

对于传统机器学习领域来说,业界流行的说法是数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限的方法。所以若要追求更高的顶测准确度,特征工程是必不可少的步骤。

特征工程是将原始数据的属性转换为特征的过程。

以Titanic 数据为例,属性是指数据的各个维度,比如乘客的性别、年龄、客舱等级, 可以看作一组基础特征, 而例如 “是否为一等客舱的女性乘客” 或 “是否是15岁以下的儿童” 之类的能够更好体现数据本质的表达方式,则是特征工程希望能得到的。

在数据建模时, 如果对原始数据的所有属性进行学习, 由干噪声干扰较大,可能并不能很好地分析出数据的潜在趋势,拟合速度慢。
而特征工程通过对数据进行重组, 可以帮助算法模型减少噪声的干扰,得到更好的拟合效果。事实上, 一组优秀的特征甚至能够帮助我们仅用简单的模型就达到很好的效果。

在上一篇的实战中,我们只用到了6 个变量字段,下面就介绍一下从其他字段中挖掘有用信息的方法。

数据清洗

数据清洗的目的是处理异常样本,如样本存在字段缺失,数据格式错误等问题,例如Titanic 数据中乘客年龄字段就存在数据缺失的情况。

针对这类样本有以下4 种常用的处理方式:

  1. 直接丢弃整行样本数据, 在样本数据足够的时候是优先的选挥;
  2. 当所有样本中某一字段缺失非常严重的时候,可以考虑丢弃整列字段;
  3. 将缺失字段填充为默认值, 如前面处理年龄字段就是补成默认值0, 相当于作为单独一种分类;
  4. 将缺失字段填充为整列数据的平均值,这种做法相当于弱化了缺失项对其他特征的影响。

Titanic 数据就属于样本数虽非常少的情况,训练数据只有891 条,所以选择补齐字段是更合适的做法。

在样本数据中,年龄小于15 岁的儿童有接近60%的幸存,远超成人的38%。而年龄缺失的人群中,幸存率更是低到不足三成。由此可以作出粗略的推断是, 年龄字段缺失的样本应该属于成人,以年龄均值29.6 岁作为标准补全数据即可。

用程序实现补全年龄数据可以利用DataFrame 强大的编辑能力, 两行代码即可完成。

mean_age = data["Age"].mean() # 29. 69
data['Age'][data.Age.isnull()) = mean_age

数据预处理

数据预处理是通过数据进行离散、标准化、归一化、数值变换等方法,使原本凌乱的数据更容易被算法处理。

一般来说,枚举类型或者取值范围是有限集合的字符串类型的字段,都会使用离散化方法转换成数值类型。方法也非常简单,只要构建一个枚举取值到数值的映射表即可。
如前面提到过的 Titanic 数据中的性别字段就使用高散化的方法进行处理,从两个取值“male”和“female”分别转换为数字 1 和 0。

另一个比较有趣的信息可以使用离散化处理,那就是乘客的头衔(Title)。乘客的头衔并不是原始数据中已经单独存在的属性,而是隐藏在乘客姓名中。

乘客姓名一般部会带有 “Mr.”、“Mrs."、“Miss. ”之类的称谓,甚至还有“Countess” 、“Don” 、“Dr.”等之类的尊称。
称谓的不同代表了乘客身份上的差别,带有尊称头衔的乘客一定是贵族,乘坐一等客舱,有超高幸存的概率。
因此,可以在解析姓名得到头衔后,标记该样本是否为贵族,作为一个备选特征。

#  Don: 在西班牙,葡萄牙,意大利使用的荣誉称号
#  Dona:女性形式为don
#  Mme: 夫人 太太
#  Mlle: 小姐 Mademoiselle, Miss
#  Jonkheer (female equivalent: Jonkvrouw) 荷兰人贵族

HONORABLE_TITLES = ['sir', 'lady', 'don', 'dona', 'countess', 'jonkheer',
                    'major', 'col', 'dr', 'master', 'capt']
NORMAL_TITLES = ['mr', 'ms', 'mrs', 'miss', 'mme', 'mlle', 'rev']
TITLES = HONORABLE_TITLES + NORMAL_TITLES

def get_title(name):
    title_search = re.search('([A-Za-z]+)\.', name)
    return title_search.group(1).lower()

data['Title'] = data['Name'].apply(get_title)
# digest.titles = TITLES
data['TitleF'] = data['Title'].apply(digest.titles.index)

data['Honor'] = data['Title'].apply(
        lambda title: int(title in HONORABLE_TITLES))

对于定量的数值型特征而言, 标准化是将整列数据按比例缩放,使之落在一个比较小的区间内,比如将年龄从[O, 100] 的区间等比缩小到[O, 1]区间中。还可以同时对定量特征进行二值化处理,比如以15 岁为阈值,添加是否为儿童的标记特征。

Titanic 数据的一个突出的特点就是数据实在比较少,在没办法取得更多数据的情况下,可以使用采样的方式随机增加一些数据。相比于直接增加训练迭代次数,随机复制样本更不容易造成过拟合。

特征选择

在经过各种变换和处理后,我们将数据原本的几个属性,增加到了几十个特征组合。为了更好地提高计算效率,可能需要通过降维的方式,挑选对于分类结果区分度最大的-些特征组合。

下面列举的是一些最常用的方法:

  1. 根据阈值过滤方差小的变量;
  2. 通过计算变量与标签的相关系数,留下相关性高的特征;
  3. 根据决策树或者随机森林,选择重要程度高的特征;
  4. 利用 PCA 等算法,对数据进行变换,选择区分度最高的特征组合。

特征选择的方法,大部分都在sklearn 库中有对应的实现, 在数据量比较小的情况下可以直接使用。

特征工程在传统机器学的研究中是公认的极其重要的部分。然而,手工的方式组合筛选特征,在像Titanic 这种相对简单、特征维度较少的问题上还能做到不错的程度,但是在更复杂的更高维的问题上就会超出人类大脑能处理的极限。

以图像识别问题为例,虽然对于人类来说, 一个2 岁的小朋友都能轻易而准确地在照片中识别出一只猫,但是很难用形式化的方法向计算机描述猫到底符合什么样的特征。
所以,深度学习之所以强大,就是它可以通过大数据自动学习和提取出计算机才能看懂的特征集合。

多种算法模型

分类问题是机器学习中的基本问题,在经过了几十年的研究后,已经发展出多种分类算法,如Naive Bayes、线性回归、诀策树、逻辑回归、KNN、SVM 、神经网络、随机森林等,这些算法都能够应用于 Titanic 问题。

其实在选择算法模型的时候,并不-定是越复杂的模型越好。
简单模型拟合能力弱,但是收敛速度快,并且不容易发生过拟合,
而复杂的模型虽然有着更灵活的拟合能力,但当数据量不足时更容易发生过拟合的情况。Titanic 题目就是典型的数据不足的例子。多次尝试和“用数据说话” ,是最好的途径。

对于Titanic 这一问题来说,由于数据量实在是非常少, 而且本身存在比较大的随机性,所以在没有人为干顶的情况下,一般能做到79%以上准确率,就已经是非常不错的成绩了。对于个别专家,使用机器学习算法最多也只能做到85%左右的预测准确率,可以以这一标准作为优化的最高目标。
Kaggle 上 Titanic 问题中,高于85%准确率的提交可以认为是经过其他人工方法矫正过的结果,属于作弊成绩。

参考文献

NumPy - 使用 Matplotlib 绘制直方图 · TutorialsPoint NumPy 教程

转载:python中plt.hist参数详解 - 智慧IT人生 - 博客园

python数字图像处理(9):直方图与均衡化 - denny402 - 博客园

Jupyter Notebook 的快捷键 - lawme的专栏

不断地“泰坦尼克号求生”是怎样一种体验? - 知乎专栏

Kaggle and Titanic — one more solution of a task by means of Python — IT daily blog, news, magazine, technologies


技术交流学习,请加QQ微信:631531977
目录