第07周:吴恩达机器学习课后编程题ex6支持向量机——Python

1 Support Vector Machines支持向量机

在本练习的前半部分,您将使用支持向量机 (SVM) 具有各种示例 2D 数据集。 试验这些数据集 将帮助您直观地了解 SVM 的工作原理以及如何使用高斯 带有 SVM 的内核。 在练习的下半部分,您将使用支持 向量机来构建垃圾邮件分类器。

1.1 Example Dataset 1 第一个数据集例

我们将从一个 2D 示例数据集开始,该数据集可以由线性决策边界区分。在这个数据集,正样本的位置(用 + 表示)和 反例的位置(用 o 表示)由空隙自然分离。 但是,请注意有一个异常正例 + on 最左边大约 (0.1, 4.1)。 作为本练习的一部分,还将看到这个异常值如何影响SVM决策边界。

import numpy as np
import matplotlib.pyplot as plt
import scipy.io as sio

# 导入数据
data1 = sio.loadmat('ex6data1.mat')
data2 = sio.loadmat('ex6data2.mat')
data3 = sio.loadmat('ex6data3.mat')

X1, y1 = data1['X'], data1['y'].flatten()
X2, y2 = data2['X'], data2['y'].flatten()
X3, y3 = data3['X'], data3['y'].flatten()
Xval, yval = data3['Xval'], data3['yval'].flatten()

# 看看这些向量的维度
print(X1.shape,y1.shape)  # (51, 2) (51,)
print(X2.shape,y2.shape)  # (863, 2) (863,)
print(X3.shape,y3.shape)  # (211, 2) (211,)
print(Xval.shape,yval.shape)  # (200, 2) (200,)

# 可视化这些样本
def plot_data(x,y):
    n = x[y == 0]
    p = x[y == 1]
    plt.scatter(p[:,0],p[:,1],c='r',marker='+',label='y=1')
    plt.scatter(n[:,0],n[:,1],c='yellow',marker='o',label='y=0')
    plt.legend()
    plt.show()

plot_data(X1,y1)

可视化后的数据:

 在这部分练习中,将尝试使用支持向量机的参数C 的不同值。 非正式地,C 参数是一个正值, 控制对错误分类训练示例的惩罚。 C 发挥作用类似于\frac{1}{\lambda },其中 λ 是我们前用于逻辑回归的正则化参数.

先假设C=1和C=100,看看它在这两种情况下对于数据集1的决策边界的影响。

用sklearn拟合并预测 : Scikit-learn(sklearn)是机器学习中常用的第三方模块,对常用的机器学习方法进行了封装,包括回归(Regression)、降维(Dimensionality Reduction)、分类(Classfication)、聚类(Clustering)等方法。里面包含了SVM的程序,直接调用调节参数即可。

 svm.SVC( ) 可以选择C值,以及核函数,调用之后先fit,再predict,predict时输入为一个二维数组,因此在画等高线的时候需要先把网格展开成二维数组进行predict再重新组成网格画图。在选择核函数时可以自己定义,例如:svm.SVC(kernel=my_kernel),内置核函数默认为rbf高斯核,其中包含一个gamma关键词,gamma默认为1/n_features。

# 用sklearn拟合并预测
from sklearn.svm import SVC
svc1 = SVC(C = 1, kernel = 'linear') # 选用线性核函数
svc1.fit(X1, y1.flatten())

print(svc1.predict(X1))  # [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#  0 0 0 0 0 0 0 0 0 0 0 0 0 0]
print(svc1.score(X1, y1.flatten()))  # 0.9803921568627451

# 画出决策边界
def plot_boundary(svc, x,y):
    n = x[y == 0]
    p = x[y == 1]
    plt.scatter(p[:, 0], p[:, 1], c='r', marker='+', label='y=1')
    plt.scatter(n[:, 0], n[:, 1], c='yellow', marker='o', label='y=0')
    plt.legend()
    u = np.linspace(np.min(X1[:,0]),np.max(X1[:,0]),500)
    v = np.linspace(np.min(X1[:,1]),np.max(X1[:,1]),500)
    x,y = np.meshgrid(u,v) # 将x,y化为网格(500*500)
    z = svc.predict(np.c_[x.flatten(),y.flatten()])
    z = z.reshape(x.shape) # 重新转为网格
    plt.contour(x, y, z, 1, colors='blue')
    plt.title('Decision Boundary C=1')
    plt.show()

plot_boundary(svc1, X1, y1)

当C=时的决策边界:

当C=100时的决策边界:

 当 C = 1 时,应该发现 SVM 将决策边界置于两个数据集之间(而且距离两边的样本很好),但是异常点没有进行正确的分类。

当 C = 100 时,应该发现 SVM 现在可以对每个样本的分类都正确,但决策边界似乎不是很适合数据。

1.2 SVM with Gaussian KernelsSVM和高斯核函数

在这部分练习中,您将使用 SVM 进行非线性分类。 特别是,您将使用具有高斯核的 SVM 不是线性可分的数据集。

1.2.1 Gaussian Kernel高斯核函数

为了使用 SVM 找到非线性决策边界,我们需要首先实现一个高斯核。 您可以将高斯核视为衡量一对样本 (x(i) , x(j) )之间的“距离”的相似函数。 高斯核函数也由参数 σ 决定相似性度量降低(到 0)的速度,因为这些例子相距甚远。高斯核函数定义为:

1.2.2 Example Dataset 2

 先可视化一下数据集2,它是非线性可分的。

# 可视化data2
plot_data(X2, y2)

在定义高斯核函数:
# 定义高斯函数
def gaussianKernel(x1,x2,sigma):
    return np.exp(-((x1-x2).T@(x1-x2))/(2*sigma*sigma))

训练模型:

# 训练模型,这里用到了内置高斯核函数
svc2 = SVC(C=100, kernel='rbf', gamma=np.power(0.1, -2)/2)  # sigma=0.1 此处算的是高斯核函数的分母
svc2.fit(X2, y2)

print(svc2.predict([[0.4,0.9]])) # 预测一点 1
print(svc2.score(X2, y2.flatten()))  # 0.9976825028968713

画出非线性的决策边界:

# 画出决策边界
def plot_boundary2(svc, x,y):
    n = x[y == 0]
    p = x[y == 1]
    plt.scatter(p[:, 0], p[:, 1], c='r', marker='+', label='y=1')
    plt.scatter(n[:, 0], n[:, 1], c='yellow', marker='o', label='y=0')
    plt.legend()
    u = np.linspace(np.min(X2[:,0]),np.max(X2[:,0]),500)
    v = np.linspace(np.min(X2[:,1]),np.max(X2[:,1]),500)
    x,y = np.meshgrid(u,v) # 将x,y化为网格(500*500)
    z = svc.predict(np.c_[x.flatten(),y.flatten()])
    z = z.reshape(x.shape) # 重新转为网格
    plt.contour(x, y, z, 1, colors='blue')
    plt.title('Decision Boundary C=100')
    plt.show()

plot_boundary2(svc2,X2,y2)

 1.2.3 Example Dataset 3

在提供的数据集 ex6data3.mat 中,给定变量 X, y,Xval,yval。使用训练集 (X, y)和以下方法训练 SVM 分类器 。你的任务是使用交叉验证集 Xval, yval 来确定要使用的最佳 C 和 σ 参数。 您应该编写额外的代码来帮助您搜索参数 C 和 σ。 对于 C 和 σ,我们建议在乘法步骤中尝试值(例如,0.01、0.03、0.1、0.3、1、3、10、30)。 请注意,您应该尝试所有可能的 C 和 σ 值对(例如,C = 0.3 和 σ = 0.1)。 例如,如果您尝试上面列出的 C 的 8 个值中的每一个 对于 σ2,你最终会进行训练和评估(在交叉验证中 集)总共 64 个不同的模型。 在确定要使用的最佳 C 和 σ 参数之后,您应该确定最佳参数。

先可视化以下数据集3和数据集3的交叉验证集:

# 可视化数据集3
plot_data(X3, y3)
plot_data(Xval, yval)

 找出最优的参数对C和σ:

# 找出最优的一对参数C和σ
gammas = [0.01, 0.03, 0.1, 0.3, 1, 3, 10, 30, 100]  # length=9
C = [0.01, 0.03, 0.1, 0.3, 1, 3, 10, 30, 100]  # length=9
best_score = 0
best_parameters = (0, 0)
for c in C:
    for gamma in gammas:
        svc3 = SVC(c, kernel='rbf')
        svc3.fit(X3, y3)
        score = svc3.score(Xval, yval)
        if score > best_score:
            best_score = score
            best_parameters = (c, gamma)

print(best_score, best_parameters) #  0.96 (30, 0.01)

 画出决策边界:

# 画出决策边界
plt.figure(3)
def plot_boundary3(svc, x, y):
    n = x[y == 0]
    p = x[y == 1]
    plt.scatter(p[:, 0], p[:, 1], c='r', marker='+', label='y=1')
    plt.scatter(n[:, 0], n[:, 1], c='yellow', marker='o', label='y=0')
    plt.legend()
    u = np.linspace(np.min(X3[:, 0]), np.max(X3[:, 0]), 500)
    v = np.linspace(np.min(X3[:, 1]), np.max(X3[:, 1]), 500)
    x, y = np.meshgrid(u, v)  # 将x,y化为网格(500*500)
    z = svc.predict(np.c_[x.flatten(), y.flatten()])
    z = z.reshape(x.shape)  # 重新转为网格
    plt.contour(x, y, z, 1, colors='blue')
    plt.title('Decision Boundary C=100')
    plt.show()

plot_boundary3(svc3, X3, y3)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值