前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【机器学习】支持向量机原理及例题详解

【机器学习】支持向量机原理及例题详解

作者头像
全栈程序员站长
发布2022-11-07 10:16:48
6390
发布2022-11-07 10:16:48
举报
文章被收录于专栏:全栈程序员必看

专栏持续更新中,欢迎订阅~ Linux 数据结构与算法 机器学习

文章目录

优化目标

引入

我们先从回顾一下Logistic回归,看看Logistic回归是如何演变为支持向量机的。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

当 y = 1 y=1 y=1时,如果我们希望 h θ ( x ) ≈ 1 h_{\theta}(x)≈1 hθ​(x)≈1,则 θ T x \theta^{T}x θTx远大于0.

当 y = 0 y=0 y=0时,如果我们希望 h θ ( x ) ≈ 0 h_{\theta}(x)≈0 hθ​(x)≈0,则 θ T x \theta^{T}x θTx远小于0.

下面是每个样本的代价函数,注意没有求和,代表每个单独的训练样本对Logistic回归的总体目标函数的贡献

在这里插入图片描述
在这里插入图片描述

然后我们将 h θ ( x ) h_{\theta}(x) hθ​(x)的具体公式带入进去,得到的就是每个训练样本对总体函数的具体贡献:

在这里插入图片描述
在这里插入图片描述

现在我们再来考虑 y = 1 , y = 0 y=1,y=0 y=1,y=0的情况,函数图像如下:

在这里插入图片描述
在这里插入图片描述

下面我们 y = 1 y=1 y=1为例,用两条直线近似等效曲线,来向支持向量机转换,例如我以 z = 1 z=1 z=1为起点,作两条直线近似取代曲线 − l o g 1 1 + e − z -log\frac{1}{1+e^{-z}} −log1+e−z1​,同理 y = 0 y=0 y=0时也一样。

在这里插入图片描述
在这里插入图片描述

当 y = 1 y=1 y=1时,两条直线记为 C o s t 1 ( z ) Cost_1(z) Cost1​(z)。

当 y = 0 y=0 y=0时,两条直线记为 C o s t 0 ( z ) Cost_0(z) Cost0​(z)。

构建支持向量机

这是我们在Logistic回归中使用的正规化代价函数 J ( θ ) J(\theta) J(θ)

在这里插入图片描述
在这里插入图片描述

然后我们用 C o s t 1 ( θ T x ( i ) ) Cost_1(\theta^{T}x^{(i)}) Cost1​(θTx(i))和 C o s t 0 ( θ T x ( i ) ) Cost_0(\theta^{T}x^{(i)}) Cost0​(θTx(i))将 − l o g h θ ( x ( i ) ) -logh_{\theta}(x^{(i)}) −loghθ​(x(i))和 − l o g ( 1 − h θ ( x ( i ) ) ) -log(1-h_{\theta}(x^{(i)})) −log(1−hθ​(x(i)))代替,去掉 1 m \frac{1}{m} m1​,然后对于正规项,我们不再用 λ \lambda λ来控制正规项的权重,而选择用不同的常数C来控制第一项的权重,最后我们得到支持向量机的总体优化目标如下:

在这里插入图片描述
在这里插入图片描述

与Logistic回归不同的是,sigmoid函数输出的不是概率,而是直接输出0或者1。

在这里插入图片描述
在这里插入图片描述

直观理解SVM

这是SVM的代价函数和图像:

在这里插入图片描述
在这里插入图片描述

下面我们来想一下如何让代价函数最小化。

若 y = 1 y=1 y=1,则当 θ T x ≥ 1 \theta^{T}x≥1 θTx≥1时, C o s t 1 ( z ) = 0 Cost_1(z)=0 Cost1​(z)=0.

若 y = 0 y=0 y=0,则当 θ T x ≤ − 1 \theta^{T}x≤-1 θTx≤−1时, C o s t 2 ( z ) = 0 Cost_2(z)=0 Cost2​(z)=0.

下面我们想象一下,如果将常数C设得比较大,例如C=100000,那么当进行最小化时,我们将迫切希望找到一个合适的值,使第一项等于0,那么现在我们试着在这种情况下来理解优化问题。

在这里插入图片描述
在这里插入图片描述

要使第一项为0,则有以下两种情况:

若 y = 1 y=1 y=1,则 θ T x ≥ 1 \theta^{T}x≥1 θTx≥1,即 y = 1 y=1 y=1的样本点在超平面 H 1 : θ T x ≥ 1 H_1:\theta^{T}x≥1 H1​:θTx≥1上。

若 y = 0 y=0 y=0,则 θ T x ≤ − 1 \theta^{T}x≤-1 θTx≤−1,即 y = 0 y=0 y=0的样本点在超平面 H 2 : θ T x ≤ − 1 H_2:\theta^{T}x≤-1 H2​:θTx≤−1上。

如下图所示,在 H 1 、 H 2 H_1、H_2 H1​、H2​上的点就是支持向量:

在这里插入图片描述
在这里插入图片描述

这里两个超平面 H 1 、 H 2 H_1、H_2 H1​、H2​平行,它们中间没有样本点。 H 1 、 H 2 H_1、H_2 H1​、H2​之间的距离成为间隔(margin)。

间隔依赖于分离超平面的法向量 θ \theta θ,等于 2 ∣ ∣ θ ∣ ∣ \frac{2}{||\theta||} ∣∣θ∣∣2​。 H 1 、 H 2 H_1、H_2 H1​、H2​是间隔边界。

核函数(kernel)

简单介绍

如下图,我们需要得到一个非线性的决策边界:

在这里插入图片描述
在这里插入图片描述

按我们之前学的方法,可以通过增加项数来进行拟合,如下:

在这里插入图片描述
在这里插入图片描述

现在我们用一些新的符号 f 1 , f 2 , f 3 . . . f_1,f_2,f_3… f1​,f2​,f3​...来表示新的特征值:

θ 0 + θ 1 f 1 + θ 2 f 2 + θ 3 f 3 + θ 4 f 4 + θ 5 f 5 + . . . ≥ 0 \theta_0+\theta_1f_1+\theta_2f_2+\theta_3f_3+\theta_4f_4+\theta_5f_5+…≥0 θ0​+θ1​f1​+θ2​f2​+θ3​f3​+θ4​f4​+θ5​f5​+...≥0

f 1 = x 1 , f 2 = x 2 , f 3 = x 1 x 2 , f 4 = x 1 2 . . . f_1=x_1,f_2=x_2,f_3=x_1x_2,f_4=x_1^2… f1​=x1​,f2​=x2​,f3​=x1​x2​,f4​=x12​...

现在我们用 f 1 , f 2 , f 3 f_1,f_2,f_3 f1​,f2​,f3​来举例:

如图,我们在图上选择三个标记 l ( 1 ) , l ( 2 ) , l ( 3 ) l^{(1)},l^{(2)},l^{(3)} l(1),l(2),l(3)

在这里插入图片描述
在这里插入图片描述

然后来定义新的特征:

给定一个实例x,然后将 f 1 f_1 f1​定义为度量实例 x x x与标记点 l ( 1 ) l^{(1)} l(1)的相似度

f 1 = s i m i l a r i t y ( x , l ( 1 ) ) = e x p ( − ∣ ∣ x − l ( 1 ) ∣ ∣ 2 2 σ 2 ) f_1=similarity(x,l^{(1)})=exp(-\frac{ {||x-l^{(1)}||}^2}{2\sigma^2}) f1​=similarity(x,l(1))=exp(−2σ2∣∣x−l(1)∣∣2​)

类似地,

f 2 = s i m i l a r i t y ( x , l ( 2 ) ) = e x p ( − ∣ ∣ x − l ( 2 ) ∣ ∣ 2 2 σ 2 ) f_2=similarity(x,l^{(2)})=exp(-\frac{ {||x-l^{(2)}||}^2}{2\sigma^2}) f2​=similarity(x,l(2))=exp(−2σ2∣∣x−l(2)∣∣2​)

f 3 = s i m i l a r i t y ( x , l ( 3 ) ) = e x p ( − ∣ ∣ x − l ( 3 ) ∣ ∣ 2 2 σ 2 ) f_3=similarity(x,l^{(3)})=exp(-\frac{ {||x-l^{(3)}||}^2}{2\sigma^2}) f3​=similarity(x,l(3))=exp(−2σ2∣∣x−l(3)∣∣2​)

这种函数我们称为高斯核函数,后面我们还会学到其他的核函数。

下面来看看这些核函数的表达式有什么含义。

假设现在有一点非常接近与标记点 l ( 1 ) l^{(1)} l(1),那么欧氏距离 ∣ ∣ x − l ( 1 ) ∣ ∣ 2 {||x-l^{(1)}||}^2 ∣∣x−l(1)∣∣2就会接近于0,此时 f 1 ≈ e x p ( 0 ) = 1 f_1≈exp(0)=1 f1​≈exp(0)=1。

相反,如果这点离 l ( 1 ) l^{(1)} l(1)很远,欧式距离 ∣ ∣ x − l ( 1 ) ∣ ∣ 2 {||x-l^{(1)}||}^2 ∣∣x−l(1)∣∣2会变得很大,此时 f 1 ≈ 0 f_1≈0 f1​≈0。

讲完了特征值的定义,接下来我们看看核函数是如何应用于决策边界的。

给定一个训练样本,当 θ 0 + θ 1 f 1 + θ 2 f 2 + θ 3 f 3 ≥ 0 \theta_0+\theta_1f_1+\theta_2f_2+\theta_3f_3≥0 θ0​+θ1​f1​+θ2​f2​+θ3​f3​≥0时,预测 y = 1 y=1 y=1。

假设我们已经得到了参数 θ \theta θ的值:

θ 0 = − 0.5 , θ 1 = 1 , θ 2 = 1 , θ 3 = 0 \theta_0=-0.5,\theta_1=1,\theta_2=1,\theta_3=0 θ0​=−0.5,θ1​=1,θ2​=1,θ3​=0

现在我们有一个实例 x x x(蓝点),落在如图所示位置,显然,该实例与标记点 l ( 1 ) l^{(1)} l(1)间距离很近,故 f 1 = 1 f_1=1 f1​=1,与标记点 l ( 2 ) , l ( 3 ) l^{(2)},l^{(3)} l(2),l(3)相距较远,故 f 2 , f 3 = 0 f_2,f_3=0 f2​,f3​=0,然后我们代入 θ 0 + θ 1 f 1 + θ 2 f 2 + θ 3 f 3 \theta_0+\theta_1f_1+\theta_2f_2+\theta_3f_3 θ0​+θ1​f1​+θ2​f2​+θ3​f3​得 θ 0 + θ 1 = 0.5 > 0 \theta_0+\theta_1=0.5>0 θ0​+θ1​=0.5>0,所以预测 y = 1 y=1 y=1。

在这里插入图片描述
在这里插入图片描述

若一个实例如绿点所示,与 l ( 1 ) , l ( 2 ) , l ( 3 ) l^{(1)},l^{(2)},l^{(3)} l(1),l(2),l(3)的距离都很远,此时 f 1 , f 2 , f 3 = 0 f_1,f_2,f_3=0 f1​,f2​,f3​=0

代入 θ 0 + θ 1 f 1 + θ 2 f 2 + θ 3 f 3 \theta_0+\theta_1f_1+\theta_2f_2+\theta_3f_3 θ0​+θ1​f1​+θ2​f2​+θ3​f3​得 θ 0 = − 0.5 < 0 \theta_0=-0.5<0 θ0​=−0.5<0,所以预测 y = 0 y= 0 y=0。

在这里插入图片描述
在这里插入图片描述

如此,便会得到一个可以区分正负样本的非线性的决策边界。

那么现在大家可能会想如何去得到我们的标记点 l ( 1 ) , l ( 2 ) , l ( 3 ) l^{(1)},l^{(2)},l^{(3)} l(1),l(2),l(3),并且在一些复杂的分类问题中,也许我们需要更多的标记点。

一般情况下,我们会直接选择训练样本作为标记点。

如下给定 m m m个训练样本,然后选定与 m m m个训练样本完全一样的位置作为标记点。

在这里插入图片描述
在这里插入图片描述

转化为向量:

f = [ f 0 f 1 f 2 f 3 . . . ] ∈ R m + 1 f=\left[ \begin{matrix} f_0 \\ f_1 \\ f_2 \\ f_3\\… \end{matrix} \right]∈R^{m+1} f=⎣⎢⎢⎢⎢⎡​f0​f1​f2​f3​...​⎦⎥⎥⎥⎥⎤​∈Rm+1

则当 θ T f ≥ 0 \theta^Tf≥0 θTf≥0时,预测 y = 1 y= 1 y=1.

最小化函数

在这里插入图片描述
在这里插入图片描述

参数选择

  • 首先我们看看参数 C C C,前面我们知道 C C C和 1 λ \frac{1}{\lambda} λ1​作用一样,如果选择了较大的 C C C,则意味着选择了较大的 λ \lambda λ,则是一个高偏差,低方差的模型(欠拟合)。 如果选择了较小的 C C C,则意味着选择了较小的 λ \lambda λ,则是一个高方差,低偏差的模型(过拟合)。
  • 还有一个参数 σ 2 \sigma^2 σ2,如果 σ 2 \sigma^2 σ2比较大,则高斯核函数 e x p ( − ∣ ∣ x − l ( i ) ∣ ∣ 2 2 σ 2 ) exp(-\frac{ {||x-l^{(i)}||}^2}{2\sigma^2}) exp(−2σ2∣∣x−l(i)∣∣2​)相对平滑,模型高偏差低方差。反之则相对陡峭,模型低偏差高方差
在这里插入图片描述
在这里插入图片描述

例题

在本次代码练习中,我们先从基础的线性分类出发,再到非线性分类来熟悉SVM的工作原理,最后再构建区分垃圾邮件的分类器。

代码语言:javascript
复制
import numpy as np
import pandas as pd
import seaborn as sb
import matplotlib.pyplot as plt
import scipy.io as sio

线性SVM

代码语言:javascript
复制
df = sio.loadmat('E:\\happy\\ML&DL\\My_exercise\\ex5-SVM\\data\\ex6data1.mat')
data = pd.DataFrame(df['X'], columns=['X1', 'X2'])
data['y'] = df['y']
data.head()
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
fig = plt.subplots(figsize=(8,6))
plt.scatter(data['X1'], data['X2'], s=50, c=data['y'], cmap='Spectral')
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
from sklearn import svm

C=1

代码语言:javascript
复制
#C=1
svc_1 = svm.LinearSVC(C=1, loss='hinge', max_iter=10000)
svc_1.fit(data[['X1', 'X2']], data['y'])
svc_1.score(data[['X1', 'X2']], data['y'])
代码语言:javascript
复制
0.9803921568627451
代码语言:javascript
复制
#C=1时,画图看看每个类别预测的置信度
data['SVM1 Confidence'] = svc_1.decision_function(data[['X1', 'X2']])
data.head()
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
fig = plt.subplots(figsize=(8,6))
plt.scatter(data['X1'], data['X2'], s=50, c=data['SVM1 Confidence'], cmap='RdBu')
plt.title('SVM (C=1) Decision Confidence')
plt.show()
在这里插入图片描述
在这里插入图片描述

C=100

代码语言:javascript
复制
#C=100时,画图看看每个类别预测的置信度
data['SVM100 Confidence'] = svc_100.decision_function(data[['X1', 'X2']])
fig = plt.subplots(figsize=(8,6))
plt.scatter(data['X1'], data['X2'], s=50, c=data['SVM100 Confidence'], cmap='RdBu')
plt.title('SVM (C=100) Decision Confidence')
plt.show()
在这里插入图片描述
在这里插入图片描述

非线性SVM

代码语言:javascript
复制
#高斯核函数
def gaussian_kernel(x1, x2, sigma):
    return np.exp(-np.power(x1 - x2, 2).sum() / (2 * (sigma ** 2)))
代码语言:javascript
复制
#测试一下
x1 = np.array([1, 2, 3])
x2 = np.array([2, 0, 1])
sigma = 2
gaussian_kernel(x1, x2, sigma)
代码语言:javascript
复制
0.32465246735834974
代码语言:javascript
复制
df = sio.loadmat('E:\\happy\\ML&DL\\My_exercise\\ex5-SVM\\data\\ex6data2.mat')
data = pd.DataFrame(df['X'], columns=['X1', 'X2'])
data['y'] = df['y']
data
代码语言:javascript
复制
fig = plt.subplots(figsize=(8,6))
plt.scatter(data['X1'], data['X2'], s=30, c=data['y'], cmap='Spectral')
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
#用内置的高斯核函数求解
svc = svm.SVC(C=100, gamma=10, probability=True)
代码语言:javascript
复制
svc.fit(data[['X1', 'X2']], data['y'])
svc.score(data[['X1', 'X2']], data['y'])
代码语言:javascript
复制
0.9698725376593279
代码语言:javascript
复制
#选一类按照概率画出来
prob = svc.predict_proba(data[['X1', 'X2']])[:, 0]
代码语言:javascript
复制
fig = plt.subplots(figsize=(8,6))
plt.scatter(data['X1'], data['X2'], s=30, c=prob, cmap='Reds')
在这里插入图片描述
在这里插入图片描述

网络搜索寻找最优参数

代码语言:javascript
复制
#读取训练集和验证集
df = sio.loadmat('E:\\happy\\ML&DL\\My_exercise\\ex5-SVM\\data\\ex6data3.mat')
df.keys()
在这里插入图片描述
在这里插入图片描述

gamma = 1 2 σ 2 \frac{1}{2\sigma^2} 2σ21​

代码语言:javascript
复制
X = df['X']
Xval = df['Xval']
y = df['y']
yval = df['yval']
candidate = [0.01, 0.03, 0.1, 0.3, 1, 3, 10, 30, 100]
gamma_values = [0.01, 0.03, 0.1, 0.3, 1, 3, 10, 30, 100]
best_score = 0
best_params = { 
'C': None, 'gamma': None}
for C in candidate:
for gamma in gamma_values:
svc = svm.SVC(C=C, gamma=gamma)
svc.fit(X, y)
score = svc.score(Xval, yval)
if score > best_score:
best_score = score
best_params['C'] = C
best_params['gamma'] = gamma
best_score, best_params
代码语言:javascript
复制
(0.965, {'C': 0.3, 'gamma': 100})

实现垃圾邮件过滤器

代码语言:javascript
复制
train = sio.loadmat('E:\\happy\\ML&DL\\My_exercise\\ex5-SVM\\data\\spamTrain.mat')
test = sio.loadmat('E:\\happy\\ML&DL\\My_exercise\\ex5-SVM\\data\\spamTest.mat')
train.keys(),test.keys()
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
#X是一个二进制向量,1表示邮件中存在该单词,0表示不存在
X = train['X']
y = train['y'].ravel()
Xtest = test['Xtest']
ytest = test['ytest'].ravel()
代码语言:javascript
复制
svc = svm.SVC()
svc.fit(X, y)
svc.score(Xtest, ytest)
代码语言:javascript
复制
0.987

例题数据和jupyter获取

关注公众号“大拨鼠Code”,回复“机器学习”可领取上面例题的源文件,jupyter版本的,例题和数据也一起打包了,之前的练习也在里面,感谢支持。

参考资料:

[1] https://www.bilibili.com/video/BV164411b7dx

[2] https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/184334.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月8日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 优化目标
    • 引入
      • 构建支持向量机
      • 直观理解SVM
      • 核函数(kernel)
        • 简单介绍
          • 参数选择
          • 例题
            • 线性SVM
              • 非线性SVM
                • 网络搜索寻找最优参数
                  • 实现垃圾邮件过滤器
                  • 例题数据和jupyter获取
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档