Support Vector Machines :支持向量机是主要用于解决分类问题的学习模型。
其基本模型定义为特征空间上的间隔最大的线性分类器,即支持向量机的学习策略便是间隔最大化,最终可转化为一个凸二次优化问题的求解。
或者简单的可以理解为就是在高维空间中寻找一个合理的超平面将数据点分隔开来,其中涉及到非线性数据到高维的映射以达到数据线性可分的目的。
该代价函数与逻辑回归代价函数相似,把原来的log(h)和log(1-h)换成了cost1和cost2,再加上正则化项,把原有的正则化系数λ换成了C,C和λ成反比关系。
那么将 C 设定为非常小的值,相应的将会给 后一项比给前一项更大的权重。
下面是支持向量机的两个参数 C 和 σ (平滑程度)的影响:
C 较大时,相当于 λ 较小,可能会导致过拟合,高方差;
C 较小时,相当于 λ 较大,可能会导致低拟合,高偏差;
σ 较大时,导致高方差;
σ 较小时,导致高偏差。
C 与λ成负相关:
C增大,λ减少;C增大,λ减少
σ 与λ成正相关:
σ增大,λ增加; σ减少,λ减少
如果有一个正样本,y 等于1,则只有在z 大于等于1 时,代价函数cost1(z)才等于0。
反之,如果y 是等于0 的,观察一下,函数cost0(z),它只有在z<=-1的区间里函数值为0。
这是支持向量机的一个有趣性质。相当于在支持向量机中嵌入了一个额外的安全因子。或者说安全的间距因子。
这个距离叫做间距(margin)。
当画出这两条额外的蓝线,我们看到黑色的决策界和训练样本之间有更大的最短距离。
然而粉线和蓝线离训练样本就非常近,在分离样本的时候就会比黑线表现差。因此,这个距离叫做支持向量机的间距,而这是支持向量机具有鲁棒性的原因,因为它努力用一个最大间距来分离样本。
因此支持向量机有时被称为大间距分类器。
当我们使用高阶数的多项式模型来解决无法用直线进行分隔的分类时,我们需要一系列的新特征的加入,那么我们除了对原有的特征进行组合以外,如何用更好的方法来构造这些特征,这就引入核函数。
常用的核函数:
核函数的选择
从逻辑回归模型,到支持向量机模型,在两者之间应该如何选择呢?
n为特征数,m为训练样本数。下面是一些普遍使用的准则:
(1)当m
(3)当m>n时,且n较小,m较大。例如:n在1-1000之间,而m大于50000,则使用支持向量机会非常慢,解决方案是创造、增加更多的特征,然后使用逻辑回归或不带核函数的支持向量机。
SVM算法的主要优点有:
1) 解决高维特征的分类问题和回归问题很有效,在特征维度大于样本数时依然有很好的效果。
2) 仅仅使用一部分支持向量来做超平面的决策,无需依赖全部数据。
3) 有大量的核函数可以使用,从而可以很灵活的来解决各种非线性的分类回归问题。
4) 样本量不是海量数据的时候,分类准确率高,泛化能力强。
SVM算法的主要缺点有:
1) 如果特征维度远远大于样本数,则SVM表现一般。
2) SVM在样本量非常大,核函数映射维度非常高时,计算量过大,不太适合使用。
3) 非线性问题的核函数的选择没有通用标准,难以选择一个合适的核函数。
4) SVM对缺失数据敏感。
import numpy as np
from sklearn.svm import SVC
import matplotlib.pyplot as plt
import sklearn.datasets as dt
#加载数据
data = dt.load_iris()#调用鸢尾花数据集:150个数据,4个特征,3个类别用0,1,2
X = data.data #获取特征值
y = data.target #获取实际y值
# 选取特征和类别
X = X[y!=2,1:3] #特征0,1,2,3 1:3是表示的第2个特征和第3个特征
y = y[y!=2]
#洗牌
np.random.seed(3)
order = np.random.permutation(len(X))
X = X[order]
y = y[order]
#特征缩放
X -= np.mean(X,0)
X /= np.std(X,0,ddof=1)
#数据集切分
num = int(0.7*len(X))
train_X,test_X = np.split(X,[num])
train_y,test_y = np.split(y,[num])
#构建模型
model = SVC(C=1,kernel='linear')
model.fit(train_X,train_y)
predict_y = model.predict(test_X)
print('测试集的预测结果:',predict_y)
print('训练集的精度=',model.score(train_X,train_y))
print('测试集的精度=',model.score(test_X,test_y))
print('支持向量索引:',model.support_)
print('支持向量的个数:',model.n_support_)
print('coef:',model.coef_)
#指定画布范围
minx1,maxx1 = min(X[:,0]),max(X[:,0])
minx2,maxx2 = min(X[:,1]),max(X[:,1])
#把画布分成200*200的网格
x1,x2 = np.mgrid[minx1:maxx1:200j,minx2:maxx2:200j]
#计算网格中心到超平面的距离
x1x2 = np.c_[x1.ravel(),x2.ravel()] #(40000, 2)
z = model.decision_function(x1x2) #(200,)
z = z.reshape(x1.shape)
#画训练集的样本图
plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.Paired,edgecolors='k',zorder=5)
#画测试集样本图
# edgecolors='k'边框为黑色;facecolor='none'不给样本填充颜色
plt.scatter(test_X[:,0],test_X[:,1],s=100,edgecolors='k',facecolor='none',zorder=10)
#画等值面
plt.contourf(x1,x2,z>=0,cmap=plt.cm.Paired)
#画等值线
plt.contour(x1,x2,z,levels=[-1,0,1],linestyles=['--','-','--'],colors=['r','g','b'])
plt.show()