0%

机器学习实战 — 支持向量机

要解决的问题

与「机器学习实战 — 决策树」的问题一样

前情回顾

在上一次中,随机森林的效果最好,最终效果如下:
RF_finally_auc.jpg

特征工程

特征工程与第二次作业一样,但增加了最后一步「特征归一化」,步骤概述如下:

  1. 特征选取
  2. 删除无用特征
  3. 空值处理
  4. 处理重要特征
  5. 特征标签化
  6. 特征归一化

特征归一化

使用 StandardScaler 和 MinMaxScaler 的差别不大,最终使用的是 StandardScaler。因为特征基本上都是符合正态分布的,而且 StandardScaler 对数据变动时引入新的极值点更友好。

1
2
3
# 使用 z-score 标准化特征
ss = preprocessing.StandardScaler()
X = ss.fit_transform(X)

特征归一化的好处有以下两点:

  1. 模型训练速度更快
    能够使参数优化时能以较快的速度收敛。
    归一化前后的 SVM(linear 核) 的耗时对比,数据集 (2783, 54),即 2783 条数据,54 个特征。归一化前后的耗时分别为:1083s,0.44s,可见归一化对计算速度的提升非常大。
  2. 模型的准确率提升
    将特征缩放到同一尺度的量级,能够使搜索的跳跃更加平滑,避免反复震荡的情况,提高准确率。可以参考下图形象化的解释:
    features_normalization_gradient_descent.jpg

对于不同数量的训练集,训练 SVM,LR,DT,RF 四个模型。随着数据集的数量增加,特征归一化后的模型,其准确率提升如下图所示:
features_normalization_analysis.jpg

通过这个图,也会发现特征归一化也不是能够提升所有模型的准确率,对于 DT 和 RF 就没有效果,这是因为决策树的分支只是计算信息熵,而不考虑整体特征的分布情况。

最终数据集

经过一系列处理后可用的数据集有 30w,但由于 SVM 运行地太慢了,从中选取 2w 数据来作为本次作业的数据集。

SVM

核函数介绍

常见的核函数有:

  1. linear:主要用于线性可分的情形。参数少,速度快,对于一般数据,分类效果已经很理想了。
  2. rbf:将样本映射到更高维的空间,目前应用最广的一个,对大小样本都有比较好的性能,而且参数较少。linear 是 rbf 的一个特例。
  3. poly:多项式核函数,将低维的输入空间映射到高纬的特征空间,参数多,当多项式的阶数比较高时,计算复杂度会非常大。
  4. sigmod:支持向量机实现的就是一种多层神经网络。

Andrew Ng 的建议:

  1. 如果Feature的数量很大,跟样本数量差不多,这时候选用LR或者是Linear Kernel的SVM
  2. 如果Feature的数量比较小,样本数量一般,不算大也不算小,选用SVM+Gaussian Kernel
  3. 如果Feature的数量比较小,而样本数量很多,需要手工添加一些feature变成第一种情况

本次作业的数据集特征少,数据大。结合上述建议,再加上取了少部分(1k~5k)的数据进行了初步对比,决定重点调优 rbf 的参数。

SVM RBF 参数搜索

训练集数据量: 2w。搜索最优参数,用时 12.3 小时,将 搜索过程的数据记录 绘制成下图所示,纵轴代表搜索得分,横轴代表 {C, gamma} 两个参数的取值。

SVM_GridSearch_result.jpg

C = 10, gamma = 0.1 时的效果最好。如上图中红圈所示,对于 C = 0.1, 100, 1000 时,都是gamma = 0.1 这个位置时效果最好。

常用核函数

在本次作业的数据集中,linear 核函数的运算速度相当慢,所以对于常用核函数,仅对比了 rbf,poly 和 sigmoid 三个核函数。针对 2w 条数据,运行结果如下:

SVM_normal_model_auc.jpg

其中,rbf 效果最好,AUC 有 0.82,但相比起之前 AUC 0.9 的 RF 来还是不理想。

自定义核函数

由于常用核函数的效果不够理想,所以尝试使用自定义的核函数,参考前人总结出的各种核函数,放入模型中进行尝试。核函数的公式见原代码,任取两个核函数的说明如下:

Rational quadratic kernel

1
2
3
4
5
6
7
8
9
10
"""
Rational quadratic kernel,
K(x, y) = 1 - ||x-y||^2/(||x-y||^2+c)
where:
c > 0
"""
def rational_quadratic(data_1, data_2):
_c = 1
dists_sq = euclidean_dist_matrix(data_1, data_2)
return 1. - (dists_sq / (dists_sq + _c))

Inverse multiquadratic kernel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
"""
Inverse multiquadratic kernel,
K(x, y) = 1 / sqrt(||x-y||^2 + c^2)
where:
c > 0
as defined in:
"Interpolation of scattered data: Distance matrices and conditionally positive definite functions"
Charles Micchelli
Constructive Approximation
"""
def inverse_multiquadratic(data_1, data_2):
_c = 1 ** 2
dists_sq = euclidean_dist_matrix(data_1, data_2)
return 1. / np.sqrt(dists_sq + _c)

仍然是对于这 2w 条数据,将所有核函数放入 SVM 中训练,最终每个核函数的准确率和耗时对比表格如下:

SVM_model_compare.jpg

可以发现 rbf, inverse_multiquadratic 和 cauchy 这三个核函数的效果较好,其中 rbf 训练速度最快,inverse_multiquadratic 准确率最高。

总结

SVM 准确率的思考

最终,使用 inverse_multiquadratic 核函数可以将 SVM 模型的 AUC Score 最高调至 0.822,相比于第二次作业中 Random Forest 模型的 AUC Score 结果 0.902 还有差距。可能是由于核函数选取的仍然不够合适,在映射后的空间中数据不是那么线性可分,降低了模型的泛化能力,导致准确率不如 RF。而对于核函数的选取,需要更多地理解特征,并列举出所有可能的核函数,再进行对比选择,在选取核函数这一点上,没有很好的捷径可走。

提升 SVM 训练速度的心得

  1. 特征标签化和归一化
  2. SVC 的 cache_size 设置到 7000 (M)
  3. 核函数是 SVM 的关键,先用少部分数据来选核函数,再用全量数据训练
  4. SVM 的 C 参数不要设置的太大

参考文档

1.4. Support Vector Machines — scikit-learn 0.20.1 documentation
RBF SVM parameters — scikit-learn 0.20.1 documentation
逻辑斯蒂回归VS决策树VS随机森林 - 简书
https://www.csie.ntu.edu.tw/~r95162/guide.pdf
https://github.com/gmum/pykernels

觉得不错,就打赏一下吧