5.吴恩达机器学习作业-支持向量机

2023-10-27

1. SVM原理

SVM算法的本质就是最大化离超平面最近点(支持向量)到该平面的距离。如图所示(以二分类为例):
在这里插入图片描述
转化为数学问题就是: m a x w , b ( m i n x i y i ( w T x i + b ) ∣ w ∣ ) max_{w,b}(min_{x_i}\frac{y_i(w^Tx_i+b)}{|w|}) maxw,b(minxiwyi(wTxi+b))
注意:

  • 这里的 y i y_i yi 就是标签(这里以二分类为例),其值是 1 和 -1,其保证了不论样本属于哪一类 y i ( w T x i + b ) y_i(w^Tx_i+b) yi(wTxi+b) 的值都是大于 0 的
  • y i ( w T x i + b ) y_i(w^Tx_i+b) yi(wTxi+b) 称为函数距离, y i ( w T x i + b ) ∣ w ∣ ) \frac{y_i(w^Tx_i+b)}{|w|}) wyi(wTxi+b)) 称为几何距离,这里之所以要使用几何距离是因为:当 w , b w, b w,b 成倍增加时,函数距离也会相应的成倍的增加,而几何距离则不会。
    由于这里涉及到求两个最值问题,比较麻烦,为简化问题,这里不妨就将最近点到超平面的函数距离设为 1,自然其他非最近点的函数距离便大于 1,于是以上问题转化为:
    在这里插入图片描述
    而这明显时一个在有不等式约束下最小值优化的问题,因此,这里可以使用 KKT 条件。
1. 求解最小值的优化问题

(1)若约束条件为等式–拉格朗日乘子法
假设给定最小值优化问题为: m i n f ( x ) minf(x) minf(x),满足的约束条件为: g ( x ) = 0 g(x)=0 g(x)=0。(为方便分析,假设 f ( x ) f(x) f(x) g ( x ) g(x) g(x) 都是连续可导函数)
求解步骤为:
  ①写出其拉格朗日函数: L ( x , λ ) = f ( x ) + λ g ( x ) L(x,\lambda)=f(x)+\lambda g(x) L(x,λ)=f(x)+λg(x),其中 λ ≢ 0 \lambda\not≡0 λ0
  ②根据最优解的必要条件可得如下方程: { ∇ x L = ∂ L ∂ x = ∇ f + λ ∇ g = 0 ∇ λ L = ∂ L ∂ λ = g ( x ) = 0 \begin{cases} \nabla_xL = \frac{\partial L}{\partial x}=\nabla f+\lambda\nabla g=0 \\ \nabla_{\lambda}L = \frac{\partial L}{\partial \lambda}=g(x)=0 \end{cases} {xL=xL=f+λg=0λL=λL=g(x)=0
  ③解上述方程便可得到 λ \lambda λ 的值,并可求解 m i n f ( x ) minf(x) minf(x)
(2)若约束条件为不等式–KKT
假设给定最小值优化问题为: m i n f ( x ) minf(x) minf(x),满足的约束条件为: g ( x ) ≤ 0 g(x)\leq0 g(x)0(称为原始可行性)。
求解步骤为:
  ①写出其拉格朗日函数: L ( x , λ ) = f ( x ) + λ g ( x ) L(x,\lambda)=f(x)+\lambda g(x) L(x,λ)=f(x)+λg(x),其中 λ ≢ 0 \lambda\not≡0 λ0
  ②据此我们定义可行域 K = x ∈ R n ∣ g ( x ) ≤ 0 K=x\in R^n|g(x)\leq0 K=xRng(x)0。假设 x ∗ x^* x 为满足约束条件的最优解,分开两种情况讨论:
    1) g ( x ∗ ) < 0 g(x^*)<0 g(x)<0,最佳解位于 K K K 的内部,称为内部解,这是约束条件是无效的。
    2) g ( x ∗ ) = 0 g(x^*)=0 g(x)=0,最佳解落在 K K K 的边界,称为边界解,此时约束条件是有效的。
  这两种情况的最佳解具有不同的必要条件。
    1)内部解:在约束条件无效的情形下, g ( x ) g(x) g(x) 不起作用,约束优化问题退化为无约束优化问题,因此驻点 x ∗ x^* x 满足 ∇ f = 0 \nabla f=0 f=0 λ = 0 \lambda=0 λ=0
    2)边界解:在约束条件有效的情形下,约束不等式变成等式 g ( x ) = 0 g(x)=0 g(x)=0,这与前述拉格朗日乘子法的情况相同,我们可以证明驻点 x ∗ x^* x 发生于 ∇ f ∈ s p a n ∇ g \nabla f\in span\nabla g fspang,换句话说,存在 λ \lambda λ 使得 ∇ f = − λ ∇ g \nabla f=-\lambda\nabla g f=λg,但这里 λ \lambda λ 的正负号是有其意义的。因为我们希望最小化 f f f,梯度 ∇ f \nabla f f(函数 f f f 在点 x x x 的最陡上升方向)应该指向可行域 K K K 的内部(因为你的最优解最小值是在边界取得的),但 ∇ g \nabla g g 指向 K K K 的外部(即 g ( x ) > 0 g(x)>0 g(x)>0 的区域,因为你的约束是小于等于0),因此 λ ≥ 0 \lambda\geq0 λ0,称为对偶可行性。
  因此,不论是内部解或边界解, λ g ( x ) = 0 \lambda g(x)=0 λg(x)=0 恒成立,称为互补松弛性。整合上述两种情况,最佳解的必要条件包括拉格朗日函数 L ( x , λ ) L(x,\lambda) L(x,λ) 的定常方程式、原始可行性、对偶可行性以及互补松弛性: { ∇ x L = ∂ L ∂ x = ∇ f + λ ∇ g = 0 g ( x ) ≤ 0 λ ≥ 0 λ g ( x ) = 0 \begin{cases} \nabla_xL = \frac{\partial L}{\partial x}=\nabla f+\lambda\nabla g=0 \\ g(x)\leq0 \\ \lambda \geq 0 \\ \lambda g(x) = 0 \end{cases} xL=xL=f+λg=0g(x)0λ0λg(x)=0
  这些条件合称为Karush-Kuhn-Tucker (KKT)条件。如果我们要最大化 f ( x ) f(x) f(x) 且受限于 g ( x ) ≤ 0 g(x)\leq0 g(x)0,那么对偶可行性要改成 λ ≤ 0 \lambda\leq0 λ0。上面结果可推广至多个约束等式与约束不等式的情况。考虑标准约束优化问题(或称非线性规划):在这里插入图片描述
  定义Lagrangian 函数
在这里插入图片描述
  其中 λ i \lambda_i λi 是对应 g i ( x ) = 0 g_i(x)=0 gi(x)=0 的Lagrange乘数, μ k \mu_k μk是对应 h k ( x ) ≤ 0 h_k(x)\leq0 hk(x)0 的Lagrange乘数(或称KKT乘数)。KKT条件包括
在这里插入图片描述

2. 松弛因子

实际上很多样本数据都不能够用一个超平面把数据完全分开。如果数据集中存在离群点的话,那么在求超平面时会出现很大问题。从下图中可以看出,其中一个蓝点偏差太大,如果把它作为支持向量的话所求出来的 m a r g i n margin margin 就会比不算入它时要小得多。更糟糕的情况是如果这个蓝点落在了红点之间那么就找不出超平面了。
在这里插入图片描述
因此引入一个松弛变量 ξ \xi ξ 来允许一些数据可以处于分隔面错误的一侧。这时新的约束条件变为: y i ( w T x i + b ) ≥ 1 − ξ i , i = 1 , 2 , . . . , m y_i(w^Tx_i+b)\geq1-\xi_i,i=1,2,...,m yi(wTxi+b)1ξi,i=1,2,...,m
式子中 ξ i \xi_i ξi 的含义为允许第 i i i 个数据点偏离的间隔。如果让 ξ \xi ξ 任意大的话,那么任意的超平面都是符合条件的了。所以在原有目标的基础之上,我们也尽可能的让 ξ \xi ξ 的总量小。所以新的目标函数变为: m i n 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 m ξ i       s . t .     ∑ i = 1 m α i y i = 0    a n d    0 ≤ α ≤ C min\frac{1}{2}||w||^2+C\sum_{i=1}^m{\xi_i}{\,}{\,}{\,}{\,}{\,} s.t.{\,}{\,}{\,} \sum_{i=1}^m{\alpha_iy_i}=0 {\,}{\,}and {\,}{\,}0\leq\alpha\leq C min21w2+Ci=1mξis.t.i=1mαiyi=0and0αC
其中的 C C C 是用于控制“最大化间隔”和“保证大部分的点的函数间隔都小于1”这两个目标的权重。将上述模型完整的写下来就是: m i n 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 m ξ i       s . t .     ξ i ≥ 0    a n d    y i ( w T x i + b ) ≥ 1 − ξ i , i = 1 , 2 , . . . , m min\frac{1}{2}||w||^2+C\sum_{i=1}^m{\xi_i}{\,}{\,}{\,}{\,}{\,} s.t.{\,}{\,}{\,}\xi_i\geq0{\,}{\,}and{\,}{\,}y_i(w^Tx_i+b)\geq1-\xi_i,i=1,2,...,m min21w2+Ci=1mξis.t.ξi0andyi(wTxi+b)1ξi,i=1,2,...,m
新的拉格朗日函数变为: L ( w , b , ξ , α , τ ) = 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 m ξ i − ∑ i = 1 m α i ( y i ( w T x i + b ) − 1 + ξ i ) − ∑ i = 1 m τ i ξ i L(w,b,\xi,\alpha,\tau)=\frac{1}{2}||w||^2+C\sum_{i=1}^m{\xi_i}-\sum_{i=1}^m{\alpha_i(y_i(w^Tx_i+b)-1+\xi_i)}-\sum_{i=1}^m{\tau_i\xi_i} L(w,b,ξ,α,τ)=21w2+Ci=1mξii=1mαi(yi(wTxi+b)1+ξi)i=1mτiξi
接下来将拉格朗日函数转化为其对偶函数,首先对 L L L 分别求 w , b , ξ w,b,\xi w,b,ξ 的偏导,并令其为0,结果如下: { ∂ L ∂ w = 0 ⇒ w = ∑ i = 1 m α i y i x i ∂ L ∂ b = 0 ⇒ ∑ i = 1 m α i y i = 0 ∂ L ∂ ξ i = 0 ⇒ C − α i − τ i = 0 \begin{cases} \frac{\partial L}{\partial w} = 0 \Rightarrow w=\sum_{i=1}^m{\alpha_iy_ix_i} \\ \frac{\partial L}{\partial b} = 0 \Rightarrow \sum_{i=1}^m{\alpha_iy_i}=0 \\ \frac{\partial L}{\partial \xi_i} = 0 \Rightarrow C-\alpha_i-\tau_i=0 \end{cases} wL=0w=i=1mαiyixibL=0i=1mαiyi=0ξiL=0Cαiτi=0
代入原式化简之后得到和原来一样的目标函数: m a x L ( α ) = ∑ i = 1 m α i − 1 2 ∑ i , j = 1 m α i α j y i y j x i T x j max L(\alpha)=\sum_{i=1}^m{\alpha_i}-\frac{1}{2}\sum_{i,j=1}^m{\alpha_i\alpha_jy_iy_jx_i^Tx_j} maxL(α)=i=1mαi21i,j=1mαiαjyiyjxiTxj
但是由于我们得到 C − α i − τ i = 0 C-\alpha_i-\tau_i=0 Cαiτi=0,而 τ i ≥ 0 \tau_i\geq0 τi0,因此有 α i ≤ C \alpha_i\leq C αiC,所以对偶问题写成: L ( α ) = 1 2 ∑ i , j = 1 m α i α j y i y j x i T x j − ∑ i , j = 1 m α i α j y i y j x i T x j − b ∑ i , j = 1 m α i y i + ∑ i = 1 m α i = ∑ i = 1 m α i − 1 2 ∑ i , j = 1 m α i α j y i y j x i T x j L(\alpha)=\frac{1}{2}\sum_{i,j=1}^m{\alpha_i\alpha_jy_iy_jx_i^Tx_j}-\sum_{i,j=1}^m{\alpha_i\alpha_jy_iy_jx_i^Tx_j}-b\sum_{i,j=1}^m{\alpha_iy_i}+\sum_{i=1}^m{\alpha_i}=\sum_{i=1}^m{\alpha_i}-\frac{1}{2}\sum_{i,j=1}^m{\alpha_i\alpha_jy_iy_jx_i^Tx_j} L(α)=21i,j=1mαiαjyiyjxiTxji,j=1mαiαjyiyjxiTxjbi,j=1mαiyi+i=1mαi=i=1mαi21i,j=1mαiαjyiyjxiTxj
经过添加松弛变量的方法,我们现在能够解决数据更加混乱的问题。通过修改参数 C C C,我们可以得到不同的结果而 C C C 的大小到底取多少比较合适,需要根据实际问题进行调节。

3. 核函数

以上讨论的都是在线性可分的情况下进行讨论的,但是实际问题中给出的数据并不是都是线性可分的,比如有些数据可能是如下图样子:
在这里插入图片描述
那么这种非线性可分的数据是否就不能用 SVM 算法来求解呢?答案是否定的。事实上,对于低维平面内不可分的数据,放在一个高维空间中去就有可能变得可分。以二维平面的数据为例,我们可以通过找到一个映射将二维平面的点放到三维平面之中。理论上任意的数据样本都能够找到一个合适的映射使得这些在低维空间不能划分的样本到高维空间中之后能够线性可分。我们再来看一下之前的目标函数: m a x    L ( α ) = ∑ i = 1 m α i − 1 2 ∑ i , j = 1 m α i α j y i y j x i T x j      s . t .      ∑ i = 1 m α i y i = 0    a n d    α i > 0 , i = 1 , 2 , . . . , m max{\,}{\,}L(\alpha)=\sum_{i=1}^m{\alpha_i}-\frac{1}{2}\sum_{i,j=1}^m{\alpha_i\alpha_jy_iy_jx_i^Tx_j}{\,}{\,}{\,}{\,}s.t.{\,}{\,}{\,}{\,}\sum_{i=1}^m{\alpha_iy_i}=0{\,}{\,}and{\,}{\,}\alpha_i>0,i=1,2,...,m maxL(α)=i=1mαi21i,j=1mαiαjyiyjxiTxjs.t.i=1mαiyi=0andαi>0,i=1,2,...,m
定义一个映射使得将所有映射到更高维空间之后等价于求解上述问题的对偶问题: m a x    L ( α ) = ∑ i = 1 m α i − 1 2 ∑ i , j = 1 m α i α j y i y j < ϕ ( x i ) , ϕ ( x j ) >      s . t .      ∑ i = 1 m α i y i = 0    a n d    0 ≤ α i ≤ C , i = 1 , 2 , . . . , m max{\,}{\,}L(\alpha)=\sum_{i=1}^m{\alpha_i}-\frac{1}{2}\sum_{i,j=1}^m{\alpha_i\alpha_jy_iy_j<\phi(x_i),\phi(x_j)>}{\,}{\,}{\,}{\,}s.t.{\,}{\,}{\,}{\,}\sum_{i=1}^m{\alpha_iy_i}=0{\,}{\,}and{\,}{\,}0\leq\alpha_i\leq C,i=1,2,...,m maxL(α)=i=1mαi21i,j=1mαiαjyiyj<ϕ(xi),ϕ(xj)>s.t.i=1mαiyi=0and0αiC,i=1,2,...,m
这样对于线性不可分的问题就解决了,现在只需要找出一个合适的映射即可。当特征变量非常多的时候,在高维空间中计算内积的运算量是非常庞大的。考虑到我们的目的并不是为找到这样一个映射而是为了计算其在高维空间的内积,因此如果我们能够找到计算高维空间下内积的公式,那么就能够避免这样庞大的计算量,我们的问题也就解决了。实际上这就是我们要找的和函数 K ( x i , x j ) K(x_i,x_j) K(xi,xj),即两个向量在隐式映射后的空间中的内积。
那么怎样的函数才可以作为核函数呢?下面的一个定理可以帮助我们判断。
Mercer定理:任何半正定的函数都可以作为核函数。其中所谓半正定函数 f ( x i , x j ) f(x_i, x_j) f(xi,xj) 是指拥有训练集数据集合,我们定义一个矩阵的元素 α i j = f ( x i , x j ) \alpha_{ij}=f(x_i,x_j) αij=f(xi,xj),这个矩阵是 n × n n\times n n×n 的矩阵,如果这个矩阵是半正定的,那么 f ( x i , x j ) f(x_i,x_j) f(xi,xj) 就称为半正定函数。
值得注意的是,上述定理中所给出的条件是充分条件而非充要条件。因为有些非正定函数也可以作为核函数。
下面是一些常用的核函数:
在这里插入图片描述
现在我们已经了解了一些支持向量机的理论基础,我们通过对偶问题的的转化将最开始求 w , b w,b w,b 的问题转化为求 α \alpha α 的对偶问题。只要找到所有的 α \alpha α (即找出所有支持向量),我们就能够确定 w , b w,b w,b。然后就可以通过计算数据点到这个超平面的距离从而判断出该数据点的类别。
SMO算法是支持向量机学习的一种快速算法,其特点是不断地将原二次规划问题分解为只有两个变量的二次规划子问题,并对子问题进行解析求解,直到所有变量满足KKT条件为止。这样通过启发式的方法得到原二次规划问题的最优解。因为子问题有解析解,所以每次计算子问题都很快,虽然计算子问题次数很多,但在总体上还是高效的。

2. SVM算法实现

1. 线性SVM

①导入各种第三方库

import numpy as np
import pandas as pd
import sklearn.svm
import seaborn as sns
import scipy.io as sio
import matplotlib.pyplot as plt

②加载并构建数据集

mat = sio.loadmat('../data/ex6data1.mat')

data = pd.DataFrame(mat.get('X'), columns=['X1', 'X2'])
data['y'] = mat.get('y')

data.head()

在这里插入图片描述
③可视化数据

plt.style.use('seaborn')
fig, ax = plt.subplots(figsize = (8, 6))
# 参数c:数字在[0,1]之间,代表颜色由浅入深
ax.scatter(data['X1'], data['X2'], s=50, c=data['y'], cmap='Reds')
ax.set_title('Raw data')
ax.set_xlabel('X1')
ax.set_ylabel('X2')
plt.show()

在这里插入图片描述
④当C=1时,模型的分数

class sklearn.svm.LinearSVC(penalty='l2', loss='squared_hinge', dual=True, tol=0.0001, C=1.0, multi_class='ovr', 
                            fit_intercept=True, intercept_scaling=1, class_weight=None, verbose=0, random_state=None,
                            max_iter=1000)

参数:
penalty:正则化参数,l1 和 l2 两种参数可选,仅 LinearSVC 有
loss:损失函数,有 ‘hinge’ 和 ‘squared_hinge’ 两种可选,前者又称L1损失,后者称为L2损失,默认是是 ’squared_hinge’,其中 hinge 是 SVM 的标准损失,squared_hinge 是 hinge 的平方。
dual:是否转化为对偶问题求解,默认是 True。
tol:残差收敛条件,默认是0.0001,与线性回归中的一致。
C:惩罚系数,用来控制损失函数的惩罚系数,类似于线性回归中的正则化系数。
multi_class:负责多分类问题中分类策略制定,有 ‘ovr’ 和 ‘crammer_singer’ 两种参数值可选,默认值是 ‘ovr’,‘ovr’ 的分类原则是将待分类中的某一类当作正类,其他全部归为负类,通过这样求取得每个类别作为正类时的正确率,取正确率最高的那个类别作为正类;'crammer_singer‘ 是直接针对目标函数设置多个参数值,最后进行优化,得到不同类别的参数值大小。
fit_intercept:是否计算截距,与线性回归模型中的意思一致。
class_weight:与其他模型中参数含义一样,也是用来处理不平衡样本数据的,可以直接以字典的形式指定不同类别的权重,也可以使用 balanced 参数值。
verbose:是否冗余,默认是 False。
random_state:随机种子的大小。
max_iter:最大迭代次数,默认是1000。
返回值:
coef_:各个特征之前的系数。
intercept_:截距。
方法:
decision_function(self, X):预测样本的信心分。
densify(self):将系数矩阵转换为稠密数组格式。
fit(self, X, y, sample_weight):根据训练数据集训练模型。
get_params(self, deep):得到模型的参数。
predict(self, X):在样本数据中预测类别的标签。
score(self, X):返回模型的平均准确率。
set_params(self, params):设置模型的参数。
sparsify(self):将系数矩阵转换为稀疏格式。

svc1 = sklearn.svm.LinearSVC(C=1, loss='hinge')
svc1.fit(data[['X1', 'X2']], data['y'])     # 训练模型
svc1.score(data[['X1', 'X2']], data['y'])

此时,模型的分数为:0.9803921568627451
⑤根据模型自信度将样本数据进行可视化展示

data['SVM1 Confidence'] = svc1.decision_function(data[['X1', 'X2']])

fig, ax = plt.subplots(figsize=(8, 6))
ax.scatter(data['X1'], data['X2'], s=50, c=data['SVM1 Confidence'], cmap='RdBu')
ax.set_title('SVM (C=1) Decision Confidence')
plt.show()

在这里插入图片描述
⑥当C=100时,模型的分数
当C很大时,可能会出现过拟合的情况

svc100 = sklearn.svm.LinearSVC(C=100, loss='hinge')
svc100.fit(data[['X1', 'X2']], data['y'])
svc100.score(data[['X1', 'X2']], data['y'])

此时,模型的分数为:1.0
⑦根据模型自信度将样本数据进行可视化展示

data['SVM100 Confidence'] = svc100.decision_function(data[['X1', 'X2']])

fig, ax = plt.subplots(figsize=(8, 6))
ax.scatter(data['X1'], data['X2'], s=50, c=data['SVM100 Confidence'], cmap='RdBu')
ax.set_title('SVM (C=100) Decision Confidence')
plt.show()

在这里插入图片描述
⑧查看两种C时的模型自信度

data.head()

在这里插入图片描述

2. 高斯核函数

①导入各种第三方库

import matplotlib.pyplot as plt
from sklearn import svm
import numpy as np
import pandas as pd
import seaborn as sns
import scipy.io as sio

②定义高斯核
高斯核函数为: K ( x i , x j ) = e − ( x i − x j ) 2 2 σ 2 K(x_i, x_j)=e^{-\frac{(x_i-x_j)^2}{2\sigma^2}} K(xi,xj)=e2σ2(xixj)2

def gaussian_kernel(x1, x2, sigma):
    return np.exp(-np.power(x1-x2, 2).sum() / (2 * (sigma ** 2)))

③示例:计算x1与x2的高斯核函数值

x1 = np.array([1,2,1])
x2 = np.array([0,4,-1])
sigma = 2

gaussian_kernel(x1, x2, sigma)    # 0.32465246735834974

④加载数据

mat = sio.loadmat('../data/ex6data2.mat')

data = pd.DataFrame(mat.get('X'), columns=['X1', 'X2'])
data['y'] = mat.get('y')

data.head()    # 863条数据

在这里插入图片描述
⑤数据可视化展示

sns.set(context='notebook',style='darkgrid',palette='deep',font='sans-serif',font_scale=1,color_codes=True)

context:控制默认的画幅大小,分别有{paper, notebook, talk, poster}四个值。其中,poster > talk > notebook > paper。
style:控制默认样式,分别有{darkgrid, whitegrid, dark, white, ticks},你可以自行更改查看它们的不同。默认是darkgrid。
palette:预设的调色板。分别有{deep, muted, bright, pastel, dark, colorblind}等,你可以自行更改查看它们的不同。
font:设置字体。
font_scale:设置字体大小。
color_codes:不使用调色板而采用先前的 ‘r’ 等色彩缩写。

seaborn.lmplot(x, y, data, hue=None, col=None, row=None, palette=None, col_wrap=None, height=5, aspect=1, markers=’o’, sharex=True, sharey=True, hue_order=None, col_order=None, row_order=None, legend=True, legend_out=True, x_estimator=None, x_bins=None, x_ci=’ci’, scatter=True, fit_reg=True, ci=95, n_boot=1000, units=None, seed=None, order=1, logistic=False, lowess=False, robust=False, logx=False, x_partial=None, y_partial=None, truncate=True, x_jitter=None, y_jitter=None, scatter_kws=None, line_kws=None, size=None)

X, y:此参数是数据中的列名。
hue, col, row:数据的定义子集,这些子集将绘制在网格的不同面上。
data:此参数是DataFrame。
fit_reg:若为True,则估计并绘制与x和y变量相关的回归模型。
scatter_kws:词典。

sns.set(context='notebook', style='white', palette=sns.diverging_palette(240,10,n=2))   # 设置图的背景与格式
sns.lmplot('X1', 'X2', hue='y', data=data, size=5, fit_reg=False, scatter_kws={"s":10})  # 将散点图绘制到FacetGrid上

plt.show()

⑥设置SVM参数并训练模型

sklearn.svm.SVC(C=1.0, kernel='rbf', degree=3, gamma='auto', coef0=0.0, shrinking=True, probability=False, 
				tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, 
				decision_function_shape=None,random_state=None)

参数:
C:惩罚参数,C越大,相当于惩罚松弛变量,希望松弛变量接近0,即对误分类的惩罚增大,趋向于对训练集全分对的情况,这样对训练集测试时准确率很高,但泛化能力弱。C值小,对误分类的惩罚减小,允许容错,将他们当成噪声点,泛化能力较强。
kernel:核函数,默认是rbf,可以是‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’
degree:多项式poly函数的维度,默认是3,选择其他核函数时会被忽略。
gamma: ‘rbf’,‘poly’ 和‘sigmoid’的核函数参数。默认是’auto’,则会选择1/n_features。
cef0:核函数的常数项。对于‘poly’和 ‘sigmoid’有用。
probability:是否采用概率估计.默认为False。
shrinking:是否采用shrinking heuristic方法,默认为true
tol:停止训练的误差值大小,默认为1e-3。
cache_size:核函数cache缓存大小,默认为200。
class_weight:类别的权重,字典形式传递。设置第几类的参数C为weight*C(C-SVC中的C)。
verbose:是否允许冗余输出。
max_iter:最大迭代次数。-1为无限制。
decision_function_shape:‘ovo’, ‘ovr’ or None, default=None3。
random_state:数据洗牌时的种子值,int值。

svc = svm.SVC(C=100, kernel='rbf', gamma=10, probability=True)
svc.fit(data[['X1', 'X2']], data['y'])
svc.score(data[['X1', 'X2']], data['y'])   # 0.9698725376593279

⑦结果可视化

# svc.predict_proba二分类则得到分别表示预测为0的概率和预测为1的概率
predict_prob = svc.predict_proba(data[['X1', 'X2']])[:, 0]

fig, ax = plt.subplots(figsize=(8, 6))
ax.scatter(data['X1'], data['X2'], s=30, c=predict_prob, cmap='Reds')
plt.show()

在这里插入图片描述

3. 寻找最优参数

①导入第三方库

from sklearn import svm
from sklearn.model_selection import GridSearchCV
from sklearn import metrics
import numpy as np
import pandas as pd
import scipy.io as sio

②加载数据

mat = sio.loadmat('../data/ex6data3.mat')

training = pd.DataFrame(mat.get('X'), columns=['X1', 'X2'])
training['y'] = mat.get('y')

cv = pd.DataFrame(mat.get('Xval'), columns=['X1', 'X2'])
cv['y'] = mat.get('yval')

training.head()

在这里插入图片描述
③设置候选C和gamma的参数组合

candidate = [0.01, 0.03, 0.1, 0.3, 1, 3, 10, 30, 100]

# 设置gamma遵守sklearn参数名
combination = [(C, gamma) for C in candidate for gamma in candidate]
len(combination)        # 81

④手动寻找最优参数组合

search = []
for C, gamma in combination:
    svc = svm.SVC(C=C, gamma=gamma)
    svc.fit(training[['X1', 'X2']], training['y'])
    search.append(svc.score(cv[['X1', 'X2']], cv['y']))

best_score = search[np.argmax(search)]
best_param = combination[np.argmax(search)]
best_score, best_param    # 0.965, (0.3, 100)

⑤展示准确率、召回率和f1值

best_svc = svm.SVC(C=100, gamma=0.3)
best_svc.fit(training[['X1', 'X2']], training['y'])
ypred = best_svc.predict(cv[['X1', 'X2']])

print(metrics.classification_report(cv['y'], ypred))

在这里插入图片描述
⑥利用GridSearch寻找最优参数

# 介绍GridSearchCV
sklearn.model_selection.GridSearchCV(estimator, param_grid, *, scoring=None, n_jobs=None, iid='deprecated', 
									 refit=True, cv=None, verbose=0, pre_dispatch='2*n_jobs', error_score=nan,
									 return_train_score=False)

参数:
estimator:选择使用的分类器,并且传入除需要确定最佳的参数之外的其他参数。每一个分类器都需要一个scoring参数,或者score方法

estimator = RandomForestClassifier(min_sample_split=100,min_samples_leaf = 20,max_depth = 8,max_features = 'sqrt' , random_state =10)

param_grid:需要优化的参数的取值,值为字典或者列表
scoring=None:模型评价标准,默认为None,这时需要使用score函数;或者如scoring = ‘roc_auc’,根据所选模型不同,评价准则不同,字符串(函数名),或是可调用对象,需要其函数签名,形如:scorer(estimator,X,y);如果是None,则使用estimator的误差估计函数。
n_jobs = 1: n_jobs:并行数,默认为1,当n_jobs = -1:表示使用所有处理器(建议)。
refit=True:默认为True,程序将会以交叉验证训练集得到的最佳参数,重新对所有可能的训练集与开发集进行,作为最终用于性能评估的最佳模型参数。即在搜索参数结束后,用最佳参数结果再次fit一遍全部数据集(不用管即可)。
cv=None:交叉验证参数,默认None,使用五折交叉验证。指定fold数量,默认为5(之前版本为3),也可以是yield训练/测试数据的生成器。
属性:
cv_results_:具有键作为列标题和值作为列的dict,可以导入到DataFrame中。注意,“params”键用于存储所有参数候选项的参数设置列表。
best_estimator_:通过搜索选择的估计器,即在左侧数据上给出最高分数(或指定的最小损失)的估计器,估计器括号里包括选中的参数。如果refit = False,则不可用。
best_score_:best_estimator的最高分数
best_params_:在保存数据上给出最佳结果的参数设置
best_index_:对应于最佳候选参数设置的索引(cv_results_数组)

parameters = {'C':candidate, 'gamma':candidate}
svc = svm.SVC()
# GridSearchCV:自动调参,把参数输进去,输出最优化结果和参数(适合于小数据集)
clf = GridSearchCV(svc, parameters, n_jobs=-1)
clf.fit(training[['X1', 'X2']], training['y'])
clf.best_params_        # {'C': 30, 'gamma': 3}
clf.best_score_         # 0.9194905869324475
ypred = clf.predict(cv[['X1', 'X2']])
print(metrics.classification_report(cv['y'], ypred))

在这里插入图片描述
奇怪的是,它们的结果并不相同?
  事实证明,GridSearch 会将部分数据作为简历,并使用它来找到最佳候选人。因此,不同结果的原因只是 GridSearch 在这里只是使用部分训练数据进行训练,因为它需要部分数据作为验证集。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

5.吴恩达机器学习作业-支持向量机 的相关文章

随机推荐

  • Vmware虚拟机网络模式原理及配置详解

    概述 VMware为我们提供了三种网络工作模式 它们分别是 bridged 桥接模式 host only 仅主机模式 nat 网络地址转换模式 打开VMware Workstation 我们可以在选项栏的 编辑 下的 虚拟网络编辑器 中看到
  • 915. 分割数组-动态规划算法

    915 分割数组 动态规划算法 给定一个数组 nums 将其划分为两个连续子数组 left 和 right 使得 left 中的每个元素都小于或等于 right 中的每个元素 left 和 right 都是非空的 left 的长度要尽可能小
  • 跨境做独立站,如何低成本引流?你的流量密码在这

    大家都知道 海外的消费习惯与国内不同 独立站一向是海外消费者的最喜欢的购物方式之一 这也吸引了许多跨境商家开设独立站 独立站不同于其他的第三方平台 其他平台可以靠平台自身流量来获得转化 而独立站本身没有流量 需要卖家从各大社媒平台进行自主引
  • 史上最牛独立开发者:花20美元狂赚100万美元

    Joe Kaufman 是一个名副其实的独立开发者 只有一个同伴 他一人处理所有的设计 美术 动画 尽管如此 他的游戏还是获得了巨大成功 Grisly Manor 恐怖庄园的秘密 的下载量已达400万 Lost City 失落之城 的也已经
  • 如何统计Visual Studio Code项目的代码行数

    背景 年底到了 公司一年一度做述职报告的时间又到了 每到此时小伙伴们都想方设法的去做一些代码层面的汇总 在此交给大家个小妙招 走过路过不要错过哈 解决方案 使用Visual Studio Code自带的在文件中查找功能中的正则表达式实现代码
  • Android新手入门 FAQ

    Q 什么是Android A Android一词的本义指 机器人 同时也是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称 该平台由操作系统 中间件 用户界面和应用软件组成 号称是首个为移动终端打造的真正开
  • Openstack Qos

    Openstack network qos 1 配置QOS 此处网络为provider网络 无self server网络 无L3 只有控制节点和计算节点 控制节点上 vim etc neutron neutron conf service
  • 立体匹配 -- PSM-Net 网络模型代码剖析

    只熟悉流程跑通代码不重要 重要的是理解网络的思想 GC Net提出了3D CNN编解码的形式做 cost volum 后处理的过程 PSM Net 加入图像金字塔的模块结合3D CNN 输出图像视差图 一 特征提取模块 作者用 3层 33的
  • 2023华为OD机试真题【组装数组】

    题目描述 给你一个整数M和数组N N中的元素为连续整数 要求根据N中的元素组装成新的数组R 组装规则 1 R中元素总和加起来等于M 2 R中的元素可以从N中重复选取 3 R中的元素最多只能有1个不在N中 且比N中的数字都要小 不能为负数 输
  • SpringBoot实现原理

    一 什么是SpringBoot SpringBoot是一个快速开发框架 快速的将一些常用的第三方依赖整合 原理 通过Maven子父工程的方式 简化XML配置 全部采用注解形式 内置Http服务器 Jetty和Tomcat 最终以java应用
  • 二叉树实现按层 s型打印

    题目阐释 s型打印 重要的是将binary tree 逐层遍历 获取每层的node 思路 将树的遍历转化为 压栈出栈 每次将列表内的node全部出栈 获取子元素 然后全部再入栈 如此反复迭代 应用 当树有层次信息时候 可以如此操作 代码如下
  • 【Spring源码】Spring流程

    1 初始化AnnotationBeanDefinitionReader 2 初始化ClassPathBeanDefinitionScanner 3 执行register 注册配置类 4 执行refresh 先初始化比如BeanFactory
  • 在校园网中配置路由器的lan口上网

    使用的是mercury路由器 在配置路由器的时候可以先按重置按钮 几秒之后路由器就重新启动了 在连接的时候可以首先进行登陆 melogin cn 或者 192 168 1 1 不同的路由器可能会有所不同 设置好登陆密码和无线密码之后可以重新
  • E - Dist Max 2(二分)

    E Dist Max 2https vjudge csgrandeur cn problem AtCoder abc215 f AC代码 include
  • jQuery:hasClass() 方法检查被选元素是否包含指定的 class;after()在某元素之后插入新元素

    Html代码1 div class PL20 style display div
  • layui 表格中实现照片预览,点击查看原图

    人员表格中实现照片预览 并且可点击放大 查看原图 table class layui hide table js 定义列 var cols type radio width 60 type numbers width 50 field or
  • Python练习-求两个给定正整数的最大公约数和最小公倍数

    题目描述 求两个给定正整数的最大公约数和最小公倍数 题目要求 输入格式 输入在两行中分别输入正整数x和y 输出格式 在一行中输出最大公约数和最小公倍数的值 例如 输入100 1520 输出20 7600 题目解析 1 几个整数中公有的约数
  • Canal快速入门

    Canal 一 Canal 入门 1 1 什么是 Canal 阿里巴巴 B2B 公司 因为业务的特性 卖家主要集中在国内 买家主要集中在国外 所以衍生出了同步杭州和美国异地机房的需求 从 2010 年开始 阿里系公司开始逐步的尝试基于数据库
  • kettle处理大数据量表-分页抽取数据

    概述 总job 分三步 第一 先清空目标表 第二 根据源表总的数据行 结合服务器配置 kettle每次能抽取插入多少行 算出需要分n次抽取 并生成1到n的序列值列表 ps 生成1 2 3 n 的数据列 然后把每个值赋值给变量var page
  • 5.吴恩达机器学习作业-支持向量机

    1 SVM原理 SVM算法的本质就是最大化离超平面最近点 支持向量 到该平面的距离 如图所示 以二分类为例 转化为数学问题就是 m a x w b