作者:侠天
来源:神机喵算
原文链接:机器学习模型选择如此简单
写在之前:有些概念跟平时你见过的机器学习文章描述的可能不太一样,但是它会给你一种“心里一颤“的感觉。
机器学习的讨论经常会涉及到的问题是:什么机器学习模型才是最好的?是逻辑回归模型,随机森林模型,贝叶斯方法模型,支持向量机模型?抑或是神经网络模型?每个人似乎都有自己心中最爱!但这些讨论试图把机器学习的挑战缩减为单个问题,而这对机器学习的初学者带来了特别严重的误解。
选择一个好的机器学习模型固然重要,但这远远不够。在缺乏领域知识,基本假设,数据选型和实际的应用的情况下,还是值得商榷的。关于机器学习模型评价这部分将留在下一篇文章阐述。
feature engineering (FE),algorithm selection (AS),and parameter tuning (PT);
能训练一个“合适”的模型和预测是相当依赖特征工程、参数调优和模型选择。模型选择是机器学习过程比较难的部分,复杂、迭代,经常不断的去“试错”和重复。
相信大家对Scikit-Learn“如何选择Estimator”里的流程图非常熟悉了,不熟悉的点开链接读读。这个流程图是给初学者一个选择机器学习算法的最佳实践的参考手册。
首先,看下我们的数据集(三个数据集参考上篇《可视化图表让机器学习“biu”的一样简单:特征分析》)的样本数是否够50。
print len(occupancy) # 8,143 print len(credit) # 30,000 print len(concrete) # 1,030 |
很显然这个条件是满足的。接着看下是否我们是否预测类别。对于房屋入住和信用卡数据集来说是判断类别;而混凝土数据集,缓凝土的抗压强度是连续数据,所以预测的是数量。因此,为前两个数据集选择分类器(classifier);为后者选择回归模型(regressor)。
因为我们的两个判断类别的数据集都小于100K,接着按图选择sklearn.svm.LinearSVC(其会将数据集映射到高维特征空间);如果失败,就再选择sklearn.neighbors.KNeighborsClassifier(其会分配样本到它的K领域)。你应该还记得房屋入住数据集单位不统一,所以这里引入scale进行归一化:
from sklearn.preprocessing import scale from sklearn.svm import LinearSVC from sklearn.neighbors import KNeighborsClassifier def classify(attributes, targets, model): # Split data into 'test' and 'train' for cross validation splits = cv.train_test_split(attributes, targets, test_size=0.2) X_train, X_test, y_train, y_test = splits model.fit(X_train, y_train) y_true = y_test y_pred = model.predict(X_test) print(confusion_matrix(y_true, y_pred)) # Divide data frame into features and labels features = occupancy[['temp', 'humid', 'light', 'co2', 'hratio']] labels = occupancy['occupied'] # Scale the features stdfeatures = scale(features) classify(stdfeatures, labels, LinearSVC()) classify(stdfeatures, labels, KNeighborsClassifier()) |
对于信用卡数据集使用相同的classify,根据上篇的特征分析经验,我们这里需要先进行数据缺失处理。
features = credit[[ 'limit', 'sex', 'edu', 'married', 'age', 'apr_delay', 'may_delay', 'jun_delay', 'jul_delay', 'aug_delay', 'sep_delay', 'apr_bill', 'may_bill', 'jun_bill', 'jul_bill', 'aug_bill', 'sep_bill', 'apr_pay', 'may_pay', 'jun_pay', 'jul_pay', 'aug_pay', 'sep_pay' ]] labels = credit['default'] stdfeatures = scale(features) classify(stdfeatures, labels, LinearSVC()) classify(stdfeatures, labels, KNeighborsClassifier()) |
对于混凝土数据集,我们得决定是否所有的特征都重要,或者只有一部分重要。如果选择所有的特征都很重要,那根据流程图手册路线应该选择sklearn.linear_model.RidgeRegression或者sklearn.svm.SVR(有点类似LinearSVC classifier);如果觉得只有部分特征重要,那就选择sklearn.linear_model.Lasso(其会在预测时舍弃部分特征)或者sklearn.linear_model.ElasticNet(其介入 Lasso方法和Ridge方法之间,L1和 L2惩罚的线性组合)。
下面来试试看咯:
from sklearn.linear_model import Ridge, Lasso, ElasticNet def regress(attributes, targets, model): splits = cv.train_test_split(attributes, targets, test_size=0.2) X_train, X_test, y_train, y_test = splits model.fit(X_train, y_train) y_true = y_test y_pred = model.predict(X_test) print('Mean squared error = {:0.3f}'.format(mse(y_true, y_pred))) print('R2 score = {:0.3f}'.format(r2_score(y_true, y_pred))) features = concrete[[ 'cement', 'slag', 'ash', 'water', 'splast', 'coarse', 'fine', 'age' ]] labels = concrete['strength'] regress(features, labels, Ridge()) regress(features, labels, Lasso()) regress(features, labels, ElasticNet()) |
正如上面代码展示的那样,Scikit-Learn API使得我们可以快速的发布我们需要的模型,这是Scikit-Learn一个强有力的魔力。
Scikit-Learn流程图非常有用是因为其提供了使用路径地图,但是它不能提供各种模型的函数。因而另外两幅图成为Scikit-Learn的权威:分类器比较和聚类比较。
多个小图形很容易比较出不同的数据集适合的聚类算法:
类似的,分类器比较图很好的帮助我们对不同的数据集选择哪种合适的分类器:
一般来说,这些图形仅仅是证明了各种模型对不同数据集的优化;但我相信大家都希望有一种可视化工具可以对同一个数据集使用不同的模型的情况进行比较。
首先给出“模型”这个词的定义,它包括三方面:
模型簇是由特征空间决定的;模型形式是通过试验和统计检验来选择的;拟合模型是由参数调优和机器计算生成的。
我们讨论的这些,模型形式的试验会在后续文章中讲到,这部分是我们期望能够得到回报的想象空间。模型形式是指出我们的特征是如何和模型簇相关。
我喜欢的模型展示工具之一是Dr. Saed Sayad的可交互的“数据挖掘地图”。它比Scikit-Learn的流程图手册综合性更高,并且结合里模型簇和模型形式的概念。除了预测方法外,Sayad地图也包含了统计方法部分。
这里给出一个普适的流程图,它旨在结合Sayad地图和 Scikit-Learn流程图。颜色和等级代表模型形式和模型簇:
通过在同一个数据集上比较和对比不同模型的性能,我们能从模型簇中直观的选取模型形式。
下期将会讲解拟合模型和调参的可视化工具。
PS:这周深入的“研究”了下Flume,日志收集利器,但是对Hadoop版本的支持太低,填了不少坑……希望我写的对部分人有用,如果是这样,请让我知道,谢谢。