下载泰坦尼克数据集,下载地址是:https://www.kaggle.com/c/titanic
这里如果是第一次使用kaggle的话,需要注册,注册时候有一些验证码的问题,可以参考https://www.cnblogs.com/liuxiaomin/p/11785645.html 来解决。
第一步:我们来看看titanic数据集
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
import matplotlib as plt
from sklearn.model_selection import GridSearchCV, train_test_split
# 生存者数据加载
passdata = pd.read_csv('../archive/titanic_data.csv')
print(passdata.info()) # 查看数据的一些统计信息,包括各个列的统计
print(passdata.head()) # 默认展示前5行数据
print(passdata['Sex'][0:10].tolist()) # 想查看某个属性的话,就用这种方式查看
得到数据的统计信息如下:
一共891个样本,每个样本有12个属性,其中类型是object的都是字符串。Age有714个非空值,Cabin缺失太多了,Embarked呢缺失值就只有俩个样本有缺失。
Survived 这一列其实就是标签,能幸存还是不能幸存。
第二步:对数据进行一些预处理
# 特征删选和清洗
passdata.drop(['Cabin', 'Name', 'Ticket'], inplace=True, axis=1) # 把一些跟结果预测没用的列全部删除,原地修改。
passdata['Age'] = passdata['Age'].fillna(passdata['Age'].mean()) # 填充一些略微多的缺失值,假如我们用平均值取填充。fillna 就是fill NAN值
passdata.dropna(inplace=True, axis=0) # 把个位数的(单独几个而已)有缺失的值的样本删除,按行删除
print(passdata.info()) # 查看数据的一些统计信息,包括各个列的统计
把一些跟结果没有多大关系的属性删除,比如Name,Cabin和Ticket
对缺失值进行填充,拿Age的平均值填充,fillna函数就是用力啊填充缺失值的。
剩下还有Embarked属性上俩样本存在缺失值,我么也不猜测了,直接删了,也没督导影响。
得到如下结果:
样本数目变成了889个。
进一步变化。
label_Embarked = passdata['Embarked'].unique().tolist()
print(label_Embarked)
passdata['Embarked'] = passdata['Embarked'].apply(lambda x: label_Embarked.index(x)) # 用唯一的序号代替Embarked离散值
print(passdata['Embarked'][0:10].tolist())
label_Sex = passdata['Sex'].unique().tolist()
print(label_Sex)
passdata['Sex'] = passdata['Sex'].apply(lambda x: label_Sex.index(x)) # 用唯一的序号代替Sex离散值
print(passdata['Sex'][0:10].tolist())
print(passdata.head()) # 默认展示前5行数据
Sex的取值是[‘male’, ‘female’],替换为唯一的数字,就用其下标。
Embarked 的取值[‘S’, ‘C’, ‘Q’] ,替换为唯一的数字,就用其下标。
效果如下:
现在没有字符串,没有缺失值,去掉了不相关的属性。
第三步:从CSV清洗过的数据中分割出测试数据集合训练数据集,并且重置数据的index。
print(passdata.columns) # 打印出所有的列名信息
print(passdata.columns != 'Survived') # 打印出所有的不等于Survived的真值信息
x = passdata.iloc[:, passdata.columns != 'Survived'] # 取出所有行,但是不包含Survived的信息,只把等于True的位置的取出来,具体可以学习iloc,也叫做布尔索引的用法
y = passdata.iloc[:, passdata.columns == 'Survived'] # 取出所有行,但是只包含Survived的信息,布尔索引。
# 把数据进行切分,切分成训练集和测试集合,切分比例一般是7:3
data_train, data_test, target_train, target_test = train_test_split(x, y, test_size=0.3)
data_train.reset_index(drop=True, inplace=True) # 重置索引,虽然没啥用,但是强迫症,避免后续混乱,想要重新重置索引。
data_test.reset_index(drop=True, inplace=True) # 重置索引,虽然没啥用,但是强迫症,避免后续混乱,想要重新重置索引。
target_train.reset_index(drop=True, inplace=True) # 重置索引,虽然没啥用,但是强迫症,避免后续混乱,想要重新重置索引。
target_test.reset_index(drop=True, inplace=True) # 重置索引,虽然没啥用,但是强迫症,避免后续混乱,想要重新重置索引。
print(data_train.shape)
print(target_train.shape)
print(data_test.shape)
print(target_test.shape)
第四步骤:建立模型且进行训练
clf = DecisionTreeClassifier(random_state=20)
score = cross_val_score(clf, x, y, cv=10).mean()
print('初始化的精确度%s' % score) # 太低了,我们来试图调整下参数。
发现一般这样做的话,精确度在70多,不是很高。
我们改变策略,进行调整参数,一个个来调整太慢了,我们直接使用网格搜索。
# 使用网格搜索来帮助我们同事调整多个参数的技术,给个字典,枚举每个参数的列表,进行组合,一个个来尝试,但是非常耗时间。
clf = DecisionTreeClassifier(random_state=20)
param_grid = [
{'criterion': ['entropy', 'gini'],
'max_features': [2, 4, 6, 8],
'max_depth': [1, 2, 3, 4, 5, 6, 7, 8],
'splitter': ['best', 'random'],
'min_samples_leaf': [*range(1, 10, 5)],
'min_impurity_decrease': [*np.arange(0.01, 0.1, 0.01)]}, # 一共有 2x4x8x2x11x10 个超参数组合
]
'''
实例化一个网格搜索,它同时满足了fit, score, 交叉验证三种功能。
第一个参数:我们需要优化的模型,
第二个参数:想要调整的参数和参数的取值范围。
第三个参数:交叉验证的次数
'''
grid_search = GridSearchCV(clf, param_grid, cv=10, n_jobs=2)
grid_search = grid_search.fit(x, y)
score = grid_search.score(data_test, target_test)
print('精度为%s' % score)
print(grid_search.best_params_) # 找到最优的超参数,这里帮我自动选择好了最优的参数列表
print(grid_search.best_estimator_) # 找到最优化的模型,甚至把初始化参数都打印出来了
print(grid_search.best_score_) # 找到最优的结果
发现这时候,精确度上到了80多哈,再仔细调整就会结果会跟好吧。
后面我们可能会使用随机森林来测试,而不是一颗单一的决策树。
网格搜索得出来的结果不一定有我们自行搜索的快哈。时间也慢,一定要自行估计好参数列表,建议小批量的进行搞。