1.模型算法选择路径图

机器学习模型算法选择 - 图1

  1. Image('sklearn.png')

2.数据处理基础

  1. # 读取数据 nrows 前一百行
  2. df = pd.read_csv(
  3. 'https://labfile.oss.aliyuncs.com/courses/1283/telecom_churn.csv'nrows=100)
  4. # pd.factorize() 获取字符数字化表示
  5. df['International plan'] = pd.factorize(df['International plan'])[0]
  6. df['Voice mail plan'] = pd.factorize(df['Voice mail plan'])[0]
  7. df['Churn'] = df['Churn'].astype('int')
  8. states = df['State']
  9. y = df['Churn']
  10. # 去掉一些列
  11. df.drop(['State', 'Churn'], axis=1, inplace=True)
  12. # 数据集划分
  13. X_train, X_holdout, y_train, y_holdout = train_test_split(df.values, y, test_size=0.3,
  14. random_state=17)
  15. # 网格搜索 + 5折交叉验证
  16. from sklearn.model_selection import GridSearchCV, cross_val_score
  17. tree_params = {'max_depth': range(5, 7),
  18. 'max_features': range(16, 18)}
  19. tree_grid = GridSearchCV(tree, tree_params, cv=5, n_jobs=-1, verbose=True)
  20. tree_grid.fit(X_train, y_train)
  21. #列出交叉验证得出的最佳参数和相应的训练集准确率均值。
  22. tree_grid.best_params_
  23. tree_grid.best_score_
  24. accuracy_score(y_holdout, tree_grid.predict(X_holdout))

3.可视化基础

  1. import matplotlib.pyplot as plt
  2. f, axes = plt.subplots(1, 4, sharey=True, figsize=(16, 6))
  3. for i in range(4):
  4. axes[i].imshow(X[i, :].reshape([8, 8]), cmap='Greys')
  5. plt.show()

4.评测指标(有监督)

1分类指标评价计算示例

  1. ## accuracy 准确率
  2. import numpy as np
  3. from sklearn.metrics import accuracy_score
  4. y_pred = [0, 1, 0, 1]
  5. y_true = [0, 1, 1, 1]
  6. print('ACC:',accuracy_score(y_true, y_pred))

ACC: 0.75

  1. ## Precision,Recall,F1-score
  2. from sklearn import metrics
  3. y_pred = [0, 1, 0, 0]
  4. y_true = [0, 1, 0, 1]
  5. print('Precision',metrics.precision_score(y_true, y_pred))
  6. print('Recall',metrics.recall_score(y_true, y_pred))
  7. print('F1-score:',metrics.f1_score(y_true, y_pred))

Precision 1.0
Recall 0.5
F1-score: 0.666666666667

  1. ## AUC
  2. import numpy as np
  3. from sklearn.metrics import roc_auc_score
  4. y_true = np.array([0, 0, 1, 1])
  5. y_scores = np.array([0.1, 0.4, 0.35, 0.8])
  6. print('AUC socre:',roc_auc_score(y_true, y_scores))

AUC score : 0.75

2回归指标评价计算示例

平均绝对误差 平均绝对误差(Mean Absolute Error,MAE):平均绝对误差,其能更好地反映预测值与真实值误差的实际情况,其计算公式如下:

机器学习模型算法选择 - 图2

均方误差 均方误差(Mean Squared Error,MSE),均方误差,其计算公式为:

机器学习模型算法选择 - 图3%5E2%0A#card=math&code=MSE%3D%5Cfrac%7B1%7D%7BN%7D%E2%88%91_%7Bi%3D1%7D%5E%7Bn%7D%28y_i%E2%88%92%5Chat%7By%7D_i%29%5E2%0A&id=aprJt)

R2(R-Square)的公式为: 残差平方和:机器学习模型算法选择 - 图4%5E2#card=math&code=SS%7Bres%7D%3D%E2%88%91%28y_i%E2%88%92%5Chat%7By%7D_i%29%5E2&id=PYjFT) 总平均值:![](https://g.yuque.com/gr/latex?SS%7Btot%7D%3D%E2%88%91(yi%E2%88%92%5Cbar%7By%7D_i)%5E2#card=math&code=SS%7Btot%7D%3D%E2%88%91%28y_i%E2%88%92%5Cbar%7By%7D_i%29%5E2&id=xVvSc)

其中机器学习模型算法选择 - 图5表示y的平均值 得到机器学习模型算法选择 - 图6表达式为:

机器学习模型算法选择 - 图7%5E2%7D%7B%E2%88%91(yi%E2%88%92%5Cbar%7By%7D)%5E2%7D%0A#card=math&code=R%5E2%3D1%E2%88%92%5Cfrac%7BSS%7Bres%7D%7D%7BSS_%7Btot%7D%7D%3D1%E2%88%92%5Cfrac%7B%E2%88%91%28y_i%E2%88%92%5Chat%7By%7D_i%29%5E2%7D%7B%E2%88%91%28y_i%E2%88%92%5Cbar%7By%7D%29%5E2%7D%0A&id=Y9UMa)

机器学习模型算法选择 - 图8用于度量因变量的变异中可由自变量解释部分所占的比例,取值范围是 0~1,机器学习模型算法选择 - 图9越接近1,表明回归平方和占总平方和的比例越大,回归线与各观测点越接近,用x的变化来解释y值变化的部分就越多,回归的拟合程度就越好。所以机器学习模型算法选择 - 图10也称为拟合优度(Goodness of Fit)的统计量。

机器学习模型算法选择 - 图11表示真实值,机器学习模型算法选择 - 图12表示预测值,机器学习模型算法选择 - 图13表示样本均值。得分越高拟合效果越好。

  1. # coding=utf-8
  2. import numpy as np
  3. from sklearn import metrics
  4. # MAPE需要自己实现
  5. def mape(y_true, y_pred):
  6. return np.mean(np.abs((y_pred - y_true) / y_true))
  7. y_true = np.array([1.0, 5.0, 4.0, 3.0, 2.0, 5.0, -3.0])
  8. y_pred = np.array([1.0, 4.5, 3.8, 3.2, 3.0, 4.8, -2.2])
  9. # MSE
  10. print('MSE:',metrics.mean_squared_error(y_true, y_pred))
  11. # RMSE
  12. print('RMSE:',np.sqrt(metrics.mean_squared_error(y_true, y_pred)))
  13. # MAE
  14. print('MAE:',metrics.mean_absolute_error(y_true, y_pred))
  15. # MAPE
  16. print('MAPE:',mape(y_true, y_pred))

MSE: 0.287142857143
RMSE: 0.535857123815
MAE: 0.414285714286
MAPE: 0.14619047619

  1. ## R2-score
  2. from sklearn.metrics import r2_score
  3. y_true = [3, -0.5, 2, 7]
  4. y_pred = [2.5, 0.0, 2, 8]
  5. print('R2-score:',r2_score(y_true, y_pred))

R2-score: 0.948608137045

5.评测指标(无监督)

聚类评价指标

(1)轮廓系数:机器学习模型算法选择 - 图14%3D%5Cfrac%20%7Bb(i)-a(i)%7D%20%7Bmax%5Cleft%20%5C%7B%20a(i)%2Cb(i)%20%5Cright%20%5C%7D%7D#card=math&code=s%28i%29%3D%5Cfrac%20%7Bb%28i%29-a%28i%29%7D%20%7Bmax%5Cleft%20%5C%7B%20a%28i%29%2Cb%28i%29%20%5Cright%20%5C%7D%7D&id=ItwVa)

轮廓系数是聚类效果好坏的一种评价方式。最佳值为1,最差值为-1。接近0的值表示重叠的群集。负值通常表示样本已分配给错误的聚类,因为不同的聚类更为相似。

(2) 熵:机器学习模型算法选择 - 图15%20%3D%20Entropy(p1%2C…p_n)%20%3D%20-%20%5Csum%7Bi%3D1%7D%5E%7Bn%7Dpilog_2(p_i)#card=math&code=Entropy%28S%29%20%3D%20Entropy%28p_1%2C…p_n%29%20%3D%20-%20%5Csum%7Bi%3D1%7D%5E%7Bn%7Dp_ilog_2%28p_i%29&id=RoZmN)

熵越小,数据越纯;熵越大,数据越混乱。

注:熵为0的时候,所有样本的目标属性取值相同

(3)纯度:机器学习模型算法选择 - 图16 ,其中 机器学习模型算法选择 - 图17#card=math&code=Pi%20%3D%20max%28P%7Bij%7D%29&id=qHiey)

6.决策树

分割质量标准(分类)

  • 熵:机器学习模型算法选择 - 图18%20%3D%20Entropy(p1%2C…p_n)%20%3D%20-%20%5Csum%7Bi%3D1%7D%5E%7Bn%7Dpilog_2(p_i)#card=math&code=Entropy%28S%29%20%3D%20Entropy%28p_1%2C…p_n%29%20%3D%20-%20%5Csum%7Bi%3D1%7D%5E%7Bn%7Dp_ilog_2%28p_i%29&id=WshNp)
  • 基尼不确定性(Gini uncertainty):机器学习模型算法选择 - 图19%5E2#card=math&code=G%20%3D%201%20-%20%5Csum%5Climits_k%20%28p_k%29%5E2&id=cpj5c)
  • 错分率(Misclassification error):机器学习模型算法选择 - 图20 几乎不用

二元分类问题的熵和基尼不确定性为:

机器学习模型算法选择 - 图21%20%5Clog2%7B(1%20-%20p%7B%2B%7D)%7D%0A#card=math&code=S%20%3D%20-p%2B%20%5Clog_2%7Bp%2B%7D%20-p-%20%5Clog_2%7Bp-%7D%20%3D%20-p%2B%20%5Clog_2%7Bp%2B%7D%20-%281%20-%20p%7B%2B%7D%29%20%5Clog_2%7B%281%20-%20p%7B%2B%7D%29%7D%0A&id=thElh)

机器学习模型算法选择 - 图22%5E2%20%3D%202p%2B(1-p%2B)%0A#card=math&code=G%20%3D%201%20-%20p%2B%5E2%20-%20p-%5E2%20%3D%201%20-%20p%2B%5E2%20-%20%281%20-%20p%2B%29%5E2%20%3D%202p%2B%281-p%2B%29%0A&id=PmJVq)

熵的图像和两倍的基尼不确定性图像非常接近。因此,在实践中,这两个指标的效果基本上是一样的。

sklearn.tree.DecisionTreeClassifier 类的主要参数为:

  • max_depth 树的最大深度;
  • max_features 搜索最佳分区时的最大特征数(特征很多时,设置这个参数很有必要,因为基于所有特征搜索分区会很「昂贵」);
  • min_samples_leaf 叶节点的最少样本数。
  1. from sklearn.tree import DecisionTreeClassifier
  2. # max_depth参数限制决策树的深度
  3. clf_tree = DecisionTreeClassifier(criterion='entropy', max_depth=3,
  4. random_state=17)
  5. # 训练决策树
  6. clf_tree.fit(train_data, train_labels)
  7. predicted = clf_tree.predict(val_data)
  8. # 可视化树
  9. from sklearn import tree
  10. tree.plot_tree(clf_tree)

绘制所得决策树

  1. dot_data = StringIO()
  2. export_graphviz(tree_grid.best_estimator_, feature_names=df.columns,
  3. out_file=dot_data, filled=True)
  4. graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
  5. Image(value=graph.create_png())

回归问题中的决策树

当对数值变量进行预测时,我们构造决策树的思路和分类问题时所用的思路是一样的,但衡量决策树好坏的质量标准改变了,现在它的质量标准如下:

机器学习模型算法选择 - 图23%5E2%2C%20%0A#card=math&code=D%20%3D%20%5Cfrac%7B1%7D%7B%5Cell%7D%20%5Csum%5Climits%7Bi%20%3D1%7D%5E%7B%5Cell%7D%20%28y_i%20-%20%5Cfrac%7B1%7D%7B%5Cell%7D%20%5Csum%5Climits%7Bj%3D1%7D%5E%7B%5Cell%7D%20y_j%29%5E2%2C%20%0A&id=k7ESR)

其中,机器学习模型算法选择 - 图24 是叶节点中的样本数,机器学习模型算法选择 - 图25 是目标变量的值。简单来说,通过最小化方差,使每个叶子中的目标特征的值大致相等,以此来划分训练集的特征。

决策树使用分段的常数函数逼近数据

  1. from sklearn.tree import DecisionTreeRegressor
  2. n_train = 150
  3. n_test = 1000
  4. noise = 0.1
  5. def f(x):
  6. x = x.ravel()
  7. return np.exp(-x ** 2) + 1.5 * np.exp(-(x - 2) ** 2)
  8. def generate(n_samples, noise):
  9. X = np.random.rand(n_samples) * 10 - 5
  10. X = np.sort(X).ravel()
  11. y = np.exp(-X ** 2) + 1.5 * np.exp(-(X - 2) ** 2) + \
  12. np.random.normal(0.0, noise, n_samples)
  13. X = X.reshape((n_samples, 1))
  14. return X, y
  15. X_train, y_train = generate(n_samples=n_train, noise=noise)
  16. X_test, y_test = generate(n_samples=n_test, noise=noise)
  17. reg_tree = DecisionTreeRegressor(max_depth=5, random_state=17)
  18. reg_tree.fit(X_train, y_train)
  19. reg_tree_pred = reg_tree.predict(X_test)
  20. plt.figure(figsize=(10, 6))
  21. plt.plot(X_test, f(X_test), "b")
  22. plt.scatter(X_train, y_train, c="b", s=20)
  23. plt.plot(X_test, reg_tree_pred, "g", lw=2)
  24. plt.xlim([-5, 5])
  25. plt.title("Decision tree regressor, MSE = %.2f" %
  26. (np.sum((y_test - reg_tree_pred) ** 2) / n_test))
  27. plt.show()

随机森林

  1. from sklearn.ensemble import RandomForestClassifier
  2. forest = RandomForestClassifier(n_estimators=100, n_jobs=-1,
  3. random_state=17)
  4. np.mean(cross_val_score(forest, X_train, y_train, cv=5))
  5. forest_params = {'max_depth': range(8, 10),
  6. 'max_features': range(5, 7)}
  7. #------------分割线-------------------------------
  8. forest_grid = GridSearchCV(forest, forest_params,
  9. cv=5, n_jobs=-1, verbose=True)
  10. # 输出最优参数(必要时需要加print())
  11. forest_grid.fit(X_train, y_train)
  12. forest_grid.best_params_, forest_grid.best_score_
  13. accuracy_score(y_holdout, forest_grid.predict(X_holdout))

7.最近邻方法

在最近邻方法中,为了对测试集中的每个样本进行分类,需要依次进行以下操作:

  • 计算训练集中每个样本之间的距离。
  • 从训练集中选取 k 个距离最近的样本。
  • 测试样本的类别将是它 k 个最近邻中最常见的分类。

在回归问题中应用最近邻方法很简单,仅需将上述步骤做一个小小的改动:第三步不返回分类,而是返回一个数字,即目标变量在邻居中的均值或中位数。

这一方式的显著特点是它具有惰性:当需要对测试样本进行分类时,计算只在预测阶段进行。由于这种特点,最近邻方法事先并不基于训练样本创建模型,这与上文提到的决策树不同。决策树是基于训练集构建的,在预测阶段仅通过遍历决策树就可以实现快速地分类。

最近邻方法的实际应用

  • 在某些案例中,k-NN 可以作为一个模型的base-line。
  • 在 Kaggle 竞赛中,k-NN 常常用于构建元特征(即 k-NN 的预测结果作为其他模型的输入),或用于堆叠/混合。
  • 最近邻方法还可以扩展到推荐系统等任务中。
  • 在大型数据集上,常常使用逼近方法搜索最近邻。

k-NN 分类/回归的效果取决于一些参数:

  • 邻居数 k。
  • 样本之间的距离度量(常见的包括 Hamming,欧几里得,余弦和 Minkowski 距离)。注意,大部分距离要求数据在同一尺度下,例如「薪水」特征的数值在千级,「年龄」特征的数值却在百级,如果直接将他们丢进最近邻模型中,「年龄」特征就会受到比较大的影响。
  • 邻居的权重(每个邻居可能贡献不同的权重,例如,样本越远,权重越低)。

scikit-learn 的 KNeighborsClassifier 类

sklearn.neighbors.KNeighborsClassifier 类的主要参数为:

  • weights:可设为 uniform(所有权重相等),distance(权重和到测试样本的距离成反比),或任何其他用户自定义的函数。
  • algorithm(可选):可设为 brute、ball_tree、KD_tree、auto。若设为 brute,通过训练集上的网格搜索来计算每个测试样本的最近邻;若设为 ball_tree 或 KD_tree,样本间的距离储存在树中,以加速寻找最近邻;若设为 auto,将基于训练集自动选择合适的寻找最近邻的方法。
  • leaf_size(可选):若寻找最近邻的算法是 BallTree 或 KDTree,则切换为网格搜索所用的阈值。
  • metric:可设为 minkowski、manhattan、euclidean、chebyshev 或其他。

使用交叉验证对 k-NN 的 k 值(即邻居数)进行调优。

  1. from sklearn.pipeline import Pipeline
  2. from sklearn.preprocessing import StandardScaler
  3. knn_pipe = Pipeline([('scaler', StandardScaler()),
  4. ('knn', KNeighborsClassifier(n_jobs=-1))])
  5. knn_params = {'knn__n_neighbors': range(6, 8)}
  6. knn_grid = GridSearchCV(knn_pipe, knn_params,
  7. cv=5, n_jobs=-1,
  8. verbose=True)
  9. knn_grid.fit(X_train, y_train)
  10. # 最优结果输出
  11. knn_grid.best_params_,knn_grid.best_score_knn_grid.best_params_
  12. accuracy_score(y_holdout, knn_grid.predict(X_holdout))

对比:决策树和最近邻方法的优势和劣势

决策树

优势:

  • 生成容易理解的分类规则,这一属性称为模型的可解释性。例如它生成的规则可能是「如果年龄不满 25 岁,并对摩托车感兴趣,那么就拒绝发放贷款」。
  • 很容易可视化,即模型本身(树)和特定测试对象的预测(穿过树的路径)可以「被解释」。
  • 训练和预测的速度快。
  • 较少的参数数目。
  • 支持数值和类别特征。

劣势:

  • 决策树对输入数据中的噪声非常敏感,这削弱了模型的可解释性。
  • 决策树构建的边界有其局限性:它由垂直于其中一个坐标轴的超平面组成,在实践中比其他方法的效果要差。
  • 我们需要通过剪枝、设定叶节点的最小样本数、设定树的最大深度等方法避免过拟合。
  • 不稳定性,数据的细微变动都会显著改变决策树。这一问题可通过决策树集成方法来处理(以后的实验会介绍)。
  • 搜索最佳决策树是一个「NP 完全」(NP-Complete)问题。了解什么是 NP-Complete 请点击 这里。实践中使用的一些推断方法,比如基于最大信息增益进行贪婪搜索,并不能保证找到全局最优决策树。
  • 倘若数据中出现缺失值,将难以创建决策树模型。Friedman 的 CART 算法中大约 50% 的代码是为了处理数据中的缺失值(现在 sklearn 实现了这一算法的改进版本)。
  • 这一模型只能内插,不能外推(随机森林和树提升方法也是如此)。也就是说,倘若你预测的对象在训练集所设置的特征空间之外,那么决策树就只能做出常数预测。比如,在我们的黄球和蓝球的例子中,这意味着模型将对所有位于 >19 或 <0 的球做出同样的预测。

最近邻方法

优势:

  • 实现简单。
  • 研究很充分。
  • 通常而言,在分类、回归、推荐问题中第一个值得尝试的方法就是最近邻方法。
  • 通过选择恰当的衡量标准或核,它可以适应某一特定问题。

劣势:

  • 和其他复合算法相比,这一方法速度较快。但是,现实生活中,用于分类的邻居数目通常较大(100-150),在这一情形下,k-NN 不如决策树快。
  • 如果数据集有很多变量,很难找到合适的权重,也很难判定哪些特征对分类/回归不重要。
  • 依赖于对象之间的距离度量,默认选项欧几里得距离常常是不合理的。你可以通过网格搜索参数得到良好的解,但在大型数据集上的耗时很长。
  • 没有理论来指导我们如何选择邻居数,故而只能进行网格搜索(尽管基本上所有的模型,在对其超参数进行调整时都使用网格搜索的方法)。在邻居数较小的情形下,该方法对离散值很敏感,也就是说,有过拟合的倾向。
  • 由于「维度的诅咒」,当数据集存在很多特征时它的表现不佳。