机器学习——特征工程

使用特征工程去提高此前的泰坦尼克生存预测的ACC

前言

在此之前我们在Kaggle上完成了我们的第一个Kaggle竞赛,得分仅有0.76555,接下来我们借助特征工程的方法来进行优化。

什么是特征工程

特征工程是将原始数据转化为更能代表问题本质的、适合机器学习模型输入的特征(通常是表格中的列)的过程。
简单来说,模型只认识数字,而且希望这些数字已经包含了问题的规律。特征工程的任务就是通过“加工”数据,让模型能更轻松地学到规律。
它的核心目标有两个:

1.提升模型性能:让模型达到更高的准确率。
2.降低计算复杂度:减少无用或冗余的数据,让模型训练更快、更高效。

常见的特征工程步骤包括:

·数据清洗:处理缺失值(如填充或删除)、异常值和重复数据。

·特征变换:将数据缩放到相同范围(标准化、归一化)、对长尾分布的数据取对数、将文本或类别变成数值(如独热编码)。

·特征构建:从现有特征中创造更有意义的新特征,比如从“年月日”中提取“星期几”,或计算“面积 = 长 × 宽”。

·特征选择:筛选出对预测目标最有用、最相关的特征,剔除无关或冗余的特征(如通过相关系数、随机森林特征重要性等方法)。

·特征降维:在保留大部分信息的前提下,将高维特征压缩到低维(如使用PCA主成分分析)。

特征工程为什么有用

在此前的泰坦尼克生存预测数据集的处理中,我直接drop掉了’Name’这个属性,认为:人的名字怎么会影响生存率呢?

然而,与中文语境不同的是,英文的名字是能够反映一个人的社会地位的!

Miss 和 Mrs, Mme, Ms 的姓名前缀分别代表了未婚与已婚,那么已婚的乘客会有丈夫陪同,生存率是不是会更高呢?

这就是问题所在了!

在原有的,我们认为没有意义的数据中创造更有意义的新特征,这就是特征工程做的事情

实践

1
2
3
4
# 从 Name 列中提取称谓(如 Mr., Mrs., Miss., Master.)
# 称谓往往能反映年龄、社会地位和性别,可能影响获救优先级
train_data['Title'] = train_data['Name'].str.extract(' ([A-Za-z]+)\.', expand=False)
test_data['Title'] = test_data['Name'].str.extract(' ([A-Za-z]+)\.', expand=False)

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Sex         0    1
Title
Capt 0 1
Col 0 2
Countess 1 0
Don 0 1
Dr 1 6
Jonkheer 0 1
Lady 1 0
Major 0 2
Master 0 40
Miss 182 0
Mlle 2 0
Mme 1 0
Mr 0 517
Mrs 125 0
Ms 1 0
Rev 0 6
Sir 0 1

含义如下:

Capt: Captain,船长或陆军上尉(男性)
Col: Colonel,陆军上校(男性)
Countess: 伯爵夫人(女性)
Don: 西班牙语/意大利语中的尊称,先生,贵族头衔(男性)
Dr: Doctor,博士/医生(男女均可,但表中男性多)
Jonkheer: 荷兰语,相当于“Esquire”或年轻贵族,男性
Lady: 女士,贵族女性(女性)
Major: 少校(男性)
Master: 对年轻男孩的称谓(男性,表中男性40,无女性)
Miss: 未婚女性(女性)
Mlle: 法语 Mademoiselle,未婚女性(女性)
Mme: 法语 Madame,已婚女性(女性)
Mr: Mister,先生(男性)
Mrs: 夫人(已婚女性)
Ms: 现代女性称谓,不指明婚姻状况(女性)
Rev: Reverend,牧师(男性居多,表中男性6)
Sir: 爵士(男性)

那么我们就可以对以上的身份进行分组(分组是提高泛化能力,现有数据集相对较小,仅出现一次的如Don、Sir等如果单独去做one-hot,可能会导致过拟合)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 将称谓进行分类
title_mapping = {
'Capt': 'elite', 'Col': 'elite', 'Countess': 'elite', 'Don': 'elite',
'Jonkheer': 'elite', 'Lady': 'elite', 'Major': 'elite', 'Sir': 'elite',
'Dr': 'professional', 'Rev': 'professional',
'Mr': 'male_adult',
'Mrs': 'married_female', 'Ms': 'married_female', 'Mme': 'married_female',
'Miss': 'unmarried_female', 'Mlle': 'unmarried_female',
'Master': 'child'
}
train_data['TitleGroup'] = train_data['Title'].map(title_mapping)
test_data['TitleGroup'] = test_data['Title'].map(title_mapping)

print(train_data.groupby('TitleGroup')['Survived'].mean())
1
2
3
4
5
6
7
TitleGroup
child 0.575000
elite 0.500000
male_adult 0.156673
married_female 0.795276
professional 0.230769
unmarried_female 0.701087

可以看到,unmarried_female生存率确实低于married_female,male_adult生成率低的吓人!

最后,去做one-hot编码就可用于训练啦!

1
2
train_data = pd.get_dummies(train_data, columns=['TitleGroup'])
test_data = pd.get_dummies(test_data, columns=['TitleGroup'])

总结

特征工程不只局限于我上面说的,除此之外还能包括更细粒度的东西。
如Name中体现出是已婚女性,其配偶(属性Sibsp,同辈亲属数量)真的在船上吗?如果不在的话存活率是否会降低?毕竟,同辈兄弟姐妹对你的重视程度可能不如你的爱人?

总之,我认为特征工程是一个很考验人想象力的东西,落到具体的领域上需要对应的知识(如社会学、心理学之类的),好的特征工程能够有效提升模型的泛化能力和学习效果。