转载自:http://blog.sina.com.cn/s/articlelist_1654066213_0_1.html
1. scikit-learn SVM算法类库概述
其中m为样本个数,我们的样本为。w、b是分离超平面
的系数,为第i个样本的松弛系数, C为惩罚系数。为低维到高维的映射函数。
3) 高斯核函数(Gaussian Kernel),在SVM中也称为径向基核函数(Radial Basis Function, RBF),它是libsvm默认的核函数,当然也是scikit-learn默认的核函数。表达式为:,其中,大于0,需要自己调参定义。
1) 一般推荐在做训练之前对数据进行归一化,当然测试集中的数据也需要归一化。
2) 在特征数非常多的情况下,或者样本数远小于特征数的时候,使用线性核,效果已经很好,并且只需要选择惩罚系数C即可。
3) 在选择核函数时,如果线性拟合不好,一般推荐使用默认的高斯核’rbf’。这时我们主要需要对惩罚系数C和核函数参数γ进行艰苦的调参,通过多轮的交叉验证选择合适的惩罚系数C和核函数参数γ。
4) 理论上高斯核不会比线性核差,但是这个理论却建立在要花费更多的时间来调参上。所以实际上能用线性核解决问题我们尽量使用线性核。
# 读取Mnist数据集, 测试SVM的分类模型
mnistSet = mnist.loadLecunMnistSet()
train_X, train_Y, test_X, test_Y = mnistSet[0], mnistSet[1], mnistSet[2], mnistSet[3]
m, n = np.shape(train_X)
idx = range(m)
np.random.shuffle(idx)
print “\n**********测试LinearSVC类**********”
model = LinearSVC(C=0.0000001)
# 拟合训练数据集
model.fit(train_X, train_Y)
# 预测训练集
train_Y_hat = model.predict(train_X[idx])
print “训练集精确度: “, accuracy_score(train_Y[idx], train_Y_hat)
# 预测测试集
test_Y_hat = model.predict(test_X)
print “测试集精确度: “, accuracy_score(test_Y, test_Y_hat)
print “\n**********测试SVC类**********”
model = SVC(C=10, gamma=0.0000001, cache_size=1000)
# 拟合训练数据集
model.fit(train_X, train_Y)
# 预测训练集
train_Y_hat = model.predict(train_X[idx])
print “训练集精确度: “, accuracy_score(train_Y[idx], train_Y_hat)
# 预测测试集
test_Y_hat = model.predict(test_X)
print “测试集精确度: “, accuracy_score(test_Y, test_Y_hat)
print “\n**********测试NuSVC类**********”
model = NuSVC(gamma=0.0000001, cache_size=1000)
# 拟合训练数据集
model.fit(train_X, train_Y)
# 预测训练集
train_Y_hat = model.predict(train_X[idx])
print “训练集精确度: “, accuracy_score(train_Y[idx], train_Y_hat)
# 预测测试集
test_Y_hat = model.predict(test_X)
print “测试集精确度: “, accuracy_score(test_Y, test_Y_hat)
# 读取CCPP数据集, 测试SVM的回归模型
data = pd.read_excel(“data/CCPP/Folds5x2_pp.xlsx”)
# AT:温度, V:压力, AP:湿度, RH:压强, PE:输出电力
# 样本特征X
X = data[[‘AT’, ‘V’, ‘AP’, ‘RH’]]
# 数据归一化
X = StandardScaler().fit_transform(X)
# 样本输出Y
Y = data[[‘PE’]]
# 划分训练集和测试集,将数据集的70%划入训练集,30%划入测试集
train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.3, random_state=1)
m, n = np.shape(train_X)
idx = range(m)
np.random.shuffle(idx)
print “\n**********测试LinearSVR类**********”
model = LinearSVR(C=10.0)
# 拟合训练集
model.fit(train_X, train_Y.values.ravel())
# 预测测试集
test_Y_pred = model.predict(test_X)
print “测试集MSE:”, mean_squared_error(test_Y, test_Y_pred)
print “测试集RMSE:”, np.sqrt(mean_squared_error(test_Y, test_Y_pred))
print “\n**********测试SVR类**********”
model = SVR(C=100.0, gamma=0.1, cache_size=500)
# 拟合训练集
model.fit(train_X, train_Y.values.ravel())
# 预测测试集
test_Y_pred = model.predict(test_X)
print “测试集MSE:”, mean_squared_error(test_Y, test_Y_pred)
print “测试集RMSE:”, np.sqrt(mean_squared_error(test_Y, test_Y_pred))
print “\n**********测试NuSVR类**********”
model = NuSVR(C=100.0, nu=0.3, gamma=0.1, cache_size=500)
# 拟合训练集
model.fit(train_X, train_Y.values.ravel())
# 预测测试集
test_Y_pred = model.predict(test_X)
print “测试集MSE:”, mean_squared_error(test_Y, test_Y_pred)
print “测试集RMSE:”, np.sqrt(mean_squared_error(test_Y, test_Y_pred))
上面3篇文章详细介绍了支持向量机(SVM)的算法。本文介绍一下scikit-learn中的SVM算法类库。
scikit-learn中的SVM算法库分为两类,一类是分类的算法库,包括SVC, NuSVC和LinearSVC 3个类;另一类是回归算法库,包括SVR, NuSVR和LinearSVR 3个类。相关的类都包含在sklearn.svm模块之中。
对于SVC, NuSVC和LinearSVC 这3个用于分类的类,SVC和NuSVC差不多,区别仅仅在于对损失的度量方式不同,而LinearSVC从名字就可以看出,它是线性分类,也就是不支持各种低维到高维的核函数,仅仅支持线性核函数,对线性不可分的数据不能使用。
同样地,对于SVR, NuSVR和LinearSVR 这3个用于回归的类, SVR和NuSVR差不多,区别也仅仅在于对损失的度量方式不同。LinearSVR是线性回归,只能使用线性核函数。
我们使用这些类的时候,如果有经验知道数据是可以线性拟合的,那么使用LinearSVC去分类或者LinearSVR去回归,它们不需要我们去慢慢的调参去选择各种核函数以及对应参数, 速度也快。如果我们对数据分布没有什么经验,一般使用SVC去分类或者SVR去回归,这就需要我们选择核函数以及对核函数进行调参了。
什么特殊场景需要使用NuSVC分类和NuSVR回归呢?如果我们对训练集训练的错误率或者说支持向量的百分比有要求的时候,可以选择NuSVC分类和NuSVR回归。它们有一个参数来控制这个百分比。
2. 回顾SVM分类算法和回归算法
我们先简要回顾一下SVM分类算法和回归算法,因为这里面有些参数对应于算法库中的参数,如果不先复习,下面对参数的讲解可能会有些难以理解。
对于SVM分类算法,其原始形式是:
其中m为样本个数,我们的样本为。w、b是分离超平面
的系数,
通过拉格朗日函数以及对偶化后的形式为:
通过拉格朗日函数以及对偶化后的形式为:
3. SVM核函数概述
在scikit-learn中,内置的核函数一共有4种。
一般情况下,对非线性数据使用默认的高斯核函数会有比较好的效果,如果你不是SVM调参高手,建议使用高斯核来做数据分析。
4. SVM分类算法类库参数小结
这里我们对SVM分类算法类库的重要参数做一个详细的解释,重点讲述调参的一些注意点。
5. SVM回归算法库参数小结
SVM回归算法类库的重要参数绝大部分和分类算法类库相似,因此这里重点讲述和分类算法类库不同的部分,对于相同的部分可以参考上一节对应的参数。
参数 | LinearSVR | SVR | NuSVR |
惩罚系数C | 即为我们第2节中SVM分类模型原型形式和对偶形式中的惩罚系数C,默认为1,通常需要通过交叉验证来选择一个合适的C。一般来说,如果噪声点较多时,C需要小一些。大家可能注意到在分类模型里面,NuSVC使用了nu这个等价的参数控制错误率,就没有使用C,那么为什么NuSVR仍然有这个参数呢,不是重复了吗?这里的原因在于在回归模型里面,除了惩罚系数C还有一个距离误差ϵ来控制损失度量,因此仅仅一个nu不能等同于C,也就是说分类错误率是惩罚系数C和距离误差ϵ共同作用的结果。后面我们可以看到NuSVR中nu的作用。 | ||
nu | LinearSVR和SVR没有这个参数,用ϵ控制错误率。 | nu代表训练集训练的错误率的上限,或者说支持向量的百分比下限,取值范围为(0,1],默认值是0.5。通过选择不同的错误率可以得到不同的距离误差ϵ,也就是说这里nu的使用与LinearSVR和SVR的ϵ参数等价。 | |
距离误差epsilon | 即第2节回归模型中的ϵ,训练集中的样本需满足。 | NuSVR没有这个参数,用nu控制错误率。 | |
是否用对偶形式优化dual | 这是一个布尔变量,控制是否使用对偶形式来优化算法,默认值是True,即采用第2节的分类算法对偶形式来优化算法。如果我们的样本量比特征数多,此时采用对偶形式计算量较大,推荐dual设置为False,即采用原始形式优化。 | SVR和NuSVR没有这个参数。 | |
正则化参数penalty | 仅仅对线性拟合有意义,可以选择’l1’即L1正则化或者’l2’即L2正则化。默认是L2正则化,如果我们需要产生稀疏化的系数时,可以选L1正则化,这和线性回归里面的Lasso回归类似。 | SVR和NuSVR没有这个参数。 | |
核函数 kernel | LinearSVR没有这个参数,LinearSVR限制了只能使用线性核函数。 | 核函数有四种内置选择,第3节已经讲到:’linear’即线性核函数,’poly’即多项式核函数,’rbf’即高斯核函数,’sigmoid’即sigmoid核函数。如果选择了这些核函数,对应的核函数需要单独调参。默认是高斯核’rbf’。 还有一种选择为’precomputed’,即我们预先计算出所有的训练集和测试集的样本对应的Gram矩阵,这样K(x,z)直接在对应的Gram矩阵中找对应位置的值。 当然我们也可以自定义核函数。 |
|
核函数参数degree | LinearSVR没有这个参数,LinearSVR限制了只能使用线性核函数。 | 如果我们在kernel参数使用了多项式核函数’poly’,那么我们就需要对这个参数进行调参。这个参数对应中的d。默认是3。一般需要通过交叉验证选择一组合适的值。 | |
核函数参数gamma | LinearSVR没有这个参数,LinearSVR限制了只能使用线性核函数。 | 如果我们在kernel参数使用了多项式核函数’poly’,高斯核函数’rbf’或者sigmoid核函数,那么我们就需要对这个参数进行调参。 多项式核函数中这个参数对应中的γ。一般需要通过交叉验证选择一组合适的γ,r,d。 高斯核函数中这个参数对应中的γ。一般需要通过交叉验证选择合适的γ。 sigmoid核函数中这个参数对应中的γ。一般需要通过交叉验证选择一组合适的γ,r。 γ默认为’auto’,即1/特征维度。 |
|
核函数参数coef0 | LinearSVR没有这个参数,LinearSVR限制了只能使用线性核函数。 | 如果我们在kernel参数使用了多项式核函数’poly’或者sigmoid核函数,那么我们就需要对这个参数进行调参。 多项式核函数中这个参数对应中的r。一般需要通过交叉验证选择一组合适的γ,r,d。 sigmoid核函数中这个参数对应中的r。一般需要通过交叉验证选择一组合适的γ,r。 coef0默认为0。 |
|
样本权重class_weight | 指定样本各类别的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策过于偏向这些类别。这里可以自己指定各个样本的权重,或者用’balanced’,如果使用’balanced’,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。当然,如果你的样本类别分布没有明显的偏倚,则可以不管这个参数,选择默认值’None’即可。 | ||
损失函数度量loss | 可以选择’epsilon_insensitive’和’squared_epsilon_insensitive’,如果选择’epsilon_insensitive’,则损失度量满足,即和第2节的损失度量一样。它是默认的SVM回归的损失度量标准形式。 如果选择为’squared_epsilon_insensitive’,则损失度量满足,此时少了一个松弛系数。其目标函数优化过程和《支持向量机(SVM)的回归模型》中所讲的过程是相似的。 一般用默认的’epsilon_insensitive’就足够了。 |
SVR和NuSVR没有这个参数。 | |
缓存大小cache_size | LinearSVR计算量不大,因此不需要这个参数。 | 在大样本的时候,缓存大小会影响训练速度,因此如果机器内存大,和SVC,NuSVC一样,推荐用500MB甚至1000MB。默认是200,即200MB。 |
6. SVM算法库其他调参要点
前面已经对scikit-learn中SVM类库的参数做了说明,这里对其它的调参要点做一个小结。
7. 使用Mnist数据集测试scikit-learn的SVM分类算法类库
代码如下所示:
—————————————————————————————————
from sklearn.svm import SVC, NuSVC, LinearSVC
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import accuracy_score
import numpy as np
import mnist
if __name__ == “__main__”:
—————————————————————————————————
8. 使用CCPP数据集测试scikit-learn的SVM回归算法类库
代码如下所示:
—————————————————————————————————
from sklearn.svm import SVR, NuSVR, LinearSVR
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import numpy as np
import pandas as pd
if __name__ == “__main__”:
—————————————————————————————————