尝试用了sklearn的决策树,发现一些问题。决策树算法的一个很大的优势就是可以很轻松的处理离散的分类变量,但CART仅支持数值变量。我看周老师的决策树这章讲的是通过为实例增加权重的方式处理缺失值,sklearn的分类树数据中不能存在缺失值。
所以,为了简单的使用sklearn的决策树,我只能手动给缺失值补值。对有序分类变量,采取直接数值化的方式处理;对无序的,用了binary coding方法处理。在稍微调整了一下sklearn自带的剪枝方法参数后,成绩上升了点
看了一下输出的决策树图,年龄直接-20的处理很粗糙,没有体现出来。后续可能会按照周老师书上的方法,自己写一个。
感觉机器学习真的是很深奥,以前看了机器学习实战的决策树一章,感觉很容易。看了周志华的机器学习决策树这章,感觉哇,决策树原来是这样的。尝试用决策树竞赛的过程中又发现实现起来还有各种各样的问题,比如sklearn为了提升性能,而直接放弃处理分类变量的可能性。而数值化处理分类变量的方法,竟然这么多
import graphviz
import numpy as np
import pandas as pd
from category_encoders import BinaryEncoder
from sklearn import tree
path = 'E:/titanic/'
train = pd.read_csv(path + 'train.csv',index_col=[0])
test = pd.read_csv(path + 'test.csv',index_col=[0])
def data_cleaning(frame):
sex_dict = {'male':0,'female':1}
frame['Sex_num'] = frame.Sex.map(sex_dict)
fun_fix_Cabin = lambda x: 'Z' if x is np.nan else x[0]
frame.Cabin.replace('T',np.nan,inplace=True)
frame['Cabin_fix'] = frame.Cabin.map(fun_fix_Cabin)
frame.Embarked.fillna('S',inplace=True)
frame.Fare.fillna(20,inplace=True)
frame.Age.fillna(-20,inplace=True)
X = frame[['Pclass','Age','SibSp','Parch','Fare','Embarked',
'Sex_num','Cabin_fix']]
y = frame.Survived
enc = BinaryEncoder(cols=['Embarked', 'Cabin_fix']).fit(X, y)
X = enc.transform(X)
return X,y
train_X,train_y = data_cleaning(train)
test_X,test_y = data_cleaning(test)
clf = tree.DecisionTreeClassifier(min_samples_leaf=7)
clf.fit(train_X,train_y)
test_pre = clf.predict(test_X)
score = 1-(test_pre-test_y).abs().sum()/len(test_y)
print('正确率:%.3f'%score)
frame = pd.DataFrame({'PassengerId':test_y.index,'Survived':test_pre})
frame.to_csv('result.csv',index=False)
dot_data = tree.export_graphviz(clf, out_file=None,
feature_names=train_X.columns,
filled=True, rounded=True,
special_characters=True)
graph = graphviz.Source(dot_data)