用机器学习判断泰坦尼克上的乘客是否幸存?
这里我们以泰坦尼克号幸存者数据集进行第一个机器学习项目
数据集的下载地址为:
导包,导入数据集并分割数据集
import pandas
from sklearn.model_selection import train_test_split
titanic = pandas.read_csv('./titanic_train.csv')
输出输出的前几行,查看各列属性等
titanic.head()
下面简单介绍一下各列属性的含义,详细信息请见链接:https://www.kaggle.com/c/titanic/data
Variable | Definition | Key |
---|---|---|
survival | Survival | 0 = No, 1 = Yes |
pclass | Ticket class | 1 = 1st, 2 = 2nd, 3 = 3rd |
sex | Sex | |
Age | Age in years | |
sibsp | # of siblings / spouses aboard the Titanic | |
parch | # of parents / children aboard the Titanic | |
ticket | Ticket number | |
fare | Passenger fare | |
cabin | Cabin number | |
embarked | Port of Embarkation | C = Cherbourg, Q = Queenstown, S = Southampton |
下一步分离数据特征和预测目标
y = titanic['Survived']
x = titanic.drop(['Survived'], axis=1)
print(x.shape)
print(y.shape)
(891, 11)
(891,)
统计缺失数据,数据类型等情况。
print(x.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 891 non-null int64
1 Pclass 891 non-null int64
2 Name 891 non-null object
3 Sex 891 non-null object
4 Age 714 non-null float64
5 SibSp 891 non-null int64
6 Parch 891 non-null int64
7 Ticket 891 non-null object
8 Fare 891 non-null float64
9 Cabin 204 non-null object
10 Embarked 889 non-null object
dtypes: float64(2), int64(4), object(5)
memory usage: 76.7+ KB
None
从上面的输出信息可以看到:
- 数据中一共有11个属性列,891个训练样本。
- 这些数据类型中有2个属性的数据类型为
float
,4个属性的数据类型为int
,5个属性的数据类型为字符串类型,即为分类变量。 - 这些属性列中,
Age
属性,Cabin
属性和Embarked
属性列有空值,需要进一步处理。
下面对空值进行处理,数据类型和文本类型的处理手段不同。Age
属性使用已有的年龄属性的平均值进行填充。
字符串类型的空值统一标记为Unknown
。
x['Age'].fillna(x['Age'].mean(), inplace=True)
x.fillna('Unknown', inplace=True)
print(x.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 891 non-null int64
1 Pclass 891 non-null int64
2 Name 891 non-null object
3 Sex 891 non-null object
4 Age 891 non-null float64
5 SibSp 891 non-null int64
6 Parch 891 non-null int64
7 Ticket 891 non-null object
8 Fare 891 non-null float64
9 Cabin 891 non-null object
10 Embarked 891 non-null object
dtypes: float64(2), int64(4), object(5)
memory usage: 76.7+ KB
None
可以看到数据被补全了,可以进行下一步操作。
下一步分割数据集,25%
的数据用于测试集,75%
的数据用于训练集。
X_train, X_test, y_train, y_test = train_test_split(x, y, train_size=.75, random_state=33)
下一步要处理的是分类变量,即建立分类变量的编码问题,这里选择使用DictVectorizer
。
DictVectorizer
的处理对象是符号化(非数字化)的但是具有一定结构的特征数据,如字典等,将符号转成数字0/1
表示。
from sklearn.feature_extraction import DictVectorizer
vec = DictVectorizer()
X_train = vec.fit_transform(X_train.to_dict(orient='record'))
X_test = vec.transform(X_test.to_dict(orient='record'))
print(len(vec.feature_names_))
1352
输出建立分类变量的数据
print(X_train.toarray()[:10, :5])
[[47. 0. 0. 0. 0. ]
[40. 0. 0. 0. 0. ]
[29.69911765 0. 0. 0. 0. ]
[22. 0. 0. 0. 0. ]
[23.5 0. 0. 0. 0. ]
[47. 0. 0. 0. 0. ]
[27. 0. 0. 0. 0. ]
[24. 0. 0. 0. 0. ]
[29.69911765 0. 0. 0. 0. ]
[29.69911765 0. 0. 0. 0. ]]
我们不难发现,DictVectorizer
对非数字化的处理方式是,借助原特征的名称,组合成新的特征,并采用0/1
的方式进行量化,而数值型的特征转化比较方便,一般情况维持原值即可。
对数据处理完毕后,开始对模型进行训练。这里我们使用随机森林模型对所有特征进行预测,并作性能评估。这里使用循环的方法找到最佳的参数max_depth
。
from sklearn.ensemble import RandomForestClassifier
maxid, maxval = 0, 0
for i in range(10, 45):
forest = RandomForestClassifier(max_depth=i, random_state=33)
forest.fit(X_train, y_train)
score = forest.score(X_test, y_test)
if maxval < score:
maxval = score
maxid = i
print(maxid, maxval)
28 0.874439461883408
这里,我们选择max_depth=10
为树的最大深度。开始训练模型:
best_forest = RandomForestClassifier(max_depth=10, random_state=33)
best_forest.fit(X_train, y_train)
score = best_forest.score(X_test, y_test)
print(score)
0.8026905829596412
总体来讲,良好的数据特征组合不需太多便可以使得模型的性能表现突出。比如,我们“良/恶性乳腺癌肿瘤预测”问题中,仅仅使用两个描述肿瘤形态的特征便可以取得很高的识别率。冗余的特征虽然不会影响到模型的性能,不过却使得CPU的计算做了无用功。比如,主成分分析主要用于去除多余的那些线性相关的特征组合,原因在于这些冗余的特征组合并不会对模型训练有更多贡献。而不良的特征自然会降低模型的精度。
特征筛选与PCA
这类通过选择主成分对特征进行重建的方法略有区别:对于PCA
而言,我们经常无法解释重建之后的特征;但是特征筛选不存在对特征值的修改,而更加侧重于寻找那些对模型的性能提升较大的少量特征。
这里我们在代码中继续沿用 Titanic据集,这次试图通过特征筛选来寻找最佳的特征组合,并且达到提高预测准确性的目标。
从sklearn
中导入特征筛选器
from sklearn import feature_selection
fs = feature_selection.SelectPercentile(feature_selection.chi2, percentile=20)
X_train_fs = fs.fit_transform(X_train, y_train)
best_forest.fit(X_train_fs, y_train)
fs_score = best_forest.score(fs.transform(X_test), y_test)
print(fs_score)
0.8295964125560538
可以看到结果,在选择了前20%
的属性进行模型的训练得到了一个比全属性进行训练更好的结果。准确率达到了82.96%
。
这样,我们就完成了一个简单的模型,虽然没有对模型做过多的优化,后续的优化环节,在后续的博客中进行介绍。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!