svm 初入

本文详细介绍了支持向量机(SVM)的优化目标,包括损失函数的简化和大间隔的概念。通过引入大间隔,解释了为何SVM能够构建出具有强泛化能力的决策边界。此外,还探讨了核函数的作用,特别是高斯核函数,如何用于解决非线性分类问题。最后,通过实例展示了线性SVM和非线性SVM(如RBF核)在实际数据集上的应用和效果差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

svm

优化函数:

​ 对于线性回归的损失函数,我们有:
C o s t ( h θ ( x ) , y ) = y i l o g ( h θ ( x i ) ) − ( 1 − y i ) ( 1 − l o g ( 1 − h θ ( x i ) ) ) Cost(h_\theta(x),y) = y^{i}log(h_\theta(x^{i})) - (1-y^{i})(1-log(1-h_\theta(x^{i}))) Cost(hθ(x),y)=yilog(hθ(xi))(1yi)(1log(1hθ(xi)))
当y=1时,我们有:
C o s t ( h θ ( x ) , y ) = l o g ( 1 1 + e − θ T x ) Cost(h_\theta(x), y) = log(\frac{1}{1+e^{-\theta^Tx}}) Cost(hθ(x),y)=log(1+eθTx1)
它的函数图像如图:

cost_sigmoid

θ T x = z \theta^T x = z θTx=z,当z较小时,我们函数图像则可以近似成一条直线我们取某一个临界值,左边使用斜率相当的直线代替,右边则取零来代替原损失函数,这样就可以将损失函数简化,那么当y=0时,我们同理可以得出相同的结论。我们使用 c o s t 1 ( z ) cost_1(z) cost1(z) c o s t 0 ( z ) cost_0(z) cost0(z)来代替两边。由此得出我们的新损失函数:
∑ i = 1 m y ( i ) c o s t 1 ( z ) + ( 1 − y ( i ) ) c o s t 0 ( z ) + λ 2 m ∑ i = 0 n θ j 2 \sum_{i=1}^m y^{(i)}cost_1(z)+(1-y^{(i)})cost_0(z)+\frac{\lambda}{2m}\sum_{i=0}^n \theta_j^2 i=1my(i)cost1(z)+(1y(i))cost0(z)+2mλi=0nθj2
一般我们将m省略(约定俗成),这样对最小化参数并没有影响。在svm中,我们更关心前面一项的优化,因此我们改变参数限制
C ∑ i = 1 m y ( i ) c o s t 1 ( z ) + ( 1 − y ( i ) ) c o s t 0 ( z ) + 1 2 ∑ i = 0 n θ j 2 C\sum_{i=1}^m y^{(i)}cost_1(z)+(1-y^{(i)})cost_0(z)+\frac{1}{2}\sum_{i=0}^n \theta_j^2 Ci=1my(i)cost1(z)+(1y(i))cost0(z)+21i=0nθj2
上面就是我们的优化目标。与线性回归不同的是,svm并不会输出概率来表示这是1还是0,它会直接得出这是1还是0


大间隔:

​ 由上,当y = 1时,如果我们想让损失函数足够的小,我们只需要保证Z > N(大约在1左右),此时损失函数就是比较小的情况了。

​ 当我们做线性回归时,可能有如下的情况:

image-20210808144358192

对于这样的分类问题我们有很多种分法,例如:

image-20210808144523379

相较起来明显是后者更佳,因为有更好的区分度,或者说距离样本的间隔足够的远。我们称为大间隔。

只有在正则化参数非常大的时候,才会有大间隔,此时对异常点会有异常的敏感。


大间隔的推导:

​ 为什么会产生大间隔呢?在这里我们对它进行一次推导:

image-20210808150904145

对于如图的两个向量,我们要计算 u T v u^Tv uTv,有如下的公式:
u T v = p × ∥ u ∥ u^Tv = p \times \|u \| uTv=p×u
其中p为v在u上的投影, ∥ u ∥ \| u\| u为u向量的范数。

那么对于上述的内容推导,我们有,当y = 1时,有 θ T x ≥ 1 \theta^Tx \ge 1 θTx1时满足损失函数最小,结合上述公式:
θ T x = x × ∥ θ ∥ ≥ 1 \theta^Tx = x \times \| \theta\| \ge 1 θTx=x×θ1
如若出现以下情况:

image-20210808144523379

此时我们作一条辅助垂直线,最靠近边界线的那个样本必然在垂直线上的投影极其小,又因为 θ T x ≥ 1 \theta^Tx \ge 1 θTx1

∥ θ ∥ \| \theta\| θ必须要极其大,这有悖于我们缩小 θ \theta θ的初衷,因此支持向量机会构建出一个大间隔的决策界限.


核函数:

对于较复杂的回归问题,我们可能需要构造比较复杂的非线性曲线去拟合数据,在这里我们推导如何通过核函数构造一个比较好的非线性函数。

image-20210808160011154

我们如何构建呢,我们假设函数形式如下:
x = f 1 + f 2 + f 3 ( 忽 略 x 0 ) x = f_1+f_2+f_3(忽略x_0) x=f1+f2+f3x0
我们根据特征项选取三个标签点:

image-20210808160905081

我们定义 f = K ( x ) f = K(x) f=K(x), K ( x ) K(x) K(x)如下:
e − ∥ x − l ∥ 2 2 σ 2 e^{-\frac{\|x - l \|^2}{2 \sigma^2}} e2σ2xl2
这是一个高斯核函数,当x距离标记点l较远时,整个值就趋于0,当x距离标记点较近时,则值趋于1,又根据上述的内容我们有
θ 0 + θ 1 f 1 + θ 2 f 2 + θ 3 f 3 ≥ 0 \theta_0+\theta_1f_1+\theta_2f_2+\theta_3f_3 \ge 0 θ0+θ1f1+θ2f2+θ3f30
这样我们就能构建出一个较好的非线性曲线出来。即,距离越远那么该值就越小。


svm demo
载入数据:
def loadData(filename):
    data = sci.loadmat(filename)
    return data


def reshapeData(data):
    x = data["X"]
    y = data["y"]
    return x, y.flatten() # 一维化
绘制曲线:
def plotData(x, y):
    pos = x[y == 1]
    neg = x[y == 0]
    plt.scatter(pos[:, 0], pos[:, 1], marker="+", label="y==1")
    plt.scatter(neg[:, 0], neg[:, 1], marker="o", label="y==0")
    plt.legend()

主函数代码

    data = loadData("ex6data1.mat")
    x, y = reshapeData(data)
    plotData(x, y)
    plt.show()

如图:

svm_data1

线性svm训练:

    model = SVC(C=1, kernel="linear") # from sklearn.svm import SVC
    model.fit(x, y)
线性化并绘制曲线:
def visualizeBoundaryLinear(x, y, model):
    w = model.coef_
    b = model.intercept_
    xp = np.linspace(0.08640, max(x[:, 1]), 100) # 生成
    yp = -(w[0][0] * xp + b) / w[0][1]
    plotData(x, y)
    plt.plot(xp, yp, "-b")

主函数代码

    visualizeBoundaryLinear(x, y, model)
    plt.show()

如图

svm_c=100

更改C为1再运行一遍

svm_c=1

可以看出明显的区别,C比较大时,样本对于曲线的影响越大


高斯核函数:
def gaussianKernel(x1, x2, sigma):
    x1 = x1.flatten()
    x2 = x2.flatten()
    x = x1 - x2
    sim = np.exp(-np.dot(x, x) / (2 * sigma * sigma))
    return sim

主函数测试:

    x1 = np.array([1, 2, 1])
    x2 = np.array([0, 4, -1])
    sigma = 2
    sim = gaussianKernel(x1, x2, sigma)
    # 结果应该接近0.32465246735834974
更换数据:
    data = loadData("ex6data2.mat")
    x, y = reshapeData(data)
    plotData(x, y)
    plt.show()
svm_data2
训练模型:
    c = 1
    sigma = 0.1
    model = SVC(gamma=np.power(sigma, -2)) # 默认则为RBF高斯核函数,gamma为核函数系数
    model.fit(x, y)
边界处理:
def visualizeBoundary(x_min, x_max, y_min, y_max, x, y, model):
    h = 0.02
    plotData(x, y)
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    z = model.predict(np.c_[xx.ravel(), yy.ravel()])
    z = z.reshape(xx.shape)
    plt.contour(xx, yy, z, level=[-1, 0, 1], colors='r')

主函数:

    visualizeBoundary(0, 1, 0.4, 1.0, x, y, model)
    plt.show()

结果:

svm_RBI

更换数据与RBF

​ 步骤与上面大致相同,这里就直接粘代码了

    data = loadData("ex6data3.mat")
    x, y = reshapeData(data)
    plotData(x, y)
    model = SVC(C=c, kernel='rbf', gamma=np.power(sigma, -2))
    model.fit(x, y)
    visualizeBoundary(-0.6, 0.3, -0.8, 0.6, x, y, model)
    plt.show()

结果如图:

svm_data3 svm_RBF
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值