吴恩达机器学习课后作业——SVM支持向量机

支持向量机

一、作业内容

在本练习的前半部分,您将对各种示例2D数据集使用支持向量机(svm)。使用这些数据集进行试验将帮助您直观地了解支持向量机的工作方式,以及如何在支持向量机中使用高斯核。在练习的下一部分中,您将使用支持向量机构建一个垃圾邮件分类器。

数据集下载位置(包含吴恩达机器学课后作业全部数据集):data

二、作业分析

1、支持向量机(SVM)(鲁棒性,大间距分类器)

支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的 间隔最大的线性分类器 ,间隔最大使它有别于感知机;SVM还包括 核技巧 ,这使它成为实质上的非线性分类器。 SVM的的学习策略就是间隔最大化,可形式化为一个求解凸二次规划的问题,也等价于正则化的合页损失函数的最小化问题。 SVM的的学习算法就是求解凸二次规划的最优化算法。

2、假设函数:
θ T θ^T θTX ≥ ≥ 1, h θ h_θ hθ(x) = 1
θ T θ^T θTX ≤ ≤ -1, h θ h_θ hθ(x) = 0

3、定义y=1时,代价函数为 c o s t 1 cost_1 cost1(z)。定义y=0时,代价函数为 c o s t 0 cost_0 cost0(z)
在这里插入图片描述
在这里插入图片描述
4、支持向量机的代价函数:
在这里插入图片描述
C:误差项惩罚系数
越大,容错率越低,越易过拟合,低偏差,高方差

5、SVM又称为大间隔分类器

向量的基本知识:
(1) u T u^T uTv=p*||u|| (向量的内积=v在u上投影的长度*u向量的模长)
(2) u T u^T uTv= u 1 u_1 u1 v 1 v_1 v1+ u 2 u_2 u2 v 2 v_2 v2 (线代公式)
(3) p(v在u上投影的长度)是有方向的,如果大于90度则为负值。

假设 θ 0 θ_0 θ0=0,且特征数n=2,对于上一节最后的代价函数进行变形,我们可以得到以下等式:
在这里插入图片描述
于是我们可以得到SVM决策边界:
在这里插入图片描述
在这里插入图片描述
6、核函数:
将低维空间映射到高维空间
可以在低维空间计算出高维空间的点积结果

当出现非线性决策边界时,我们不知道几阶的多项式适合我们,我们可以使用核函数来构造新的特征。

(1) 首先我们定义了一些标记 l 1 l^1 l1 l 2 l^2 l2 l 3 l^3 l3
(2) 接着我们构建了新的特征 f 1 f_1 f1 f 2 f_2 f2 f 3 f_3 f3
在这里插入图片描述
在这里插入图片描述

当x和l近似相等时,f等于1。当x和l距离比较远的话,f等于0

基于此,我们假设我们已经求出了最优的参数θ,下面就解释一下如何来进行分类:
在这里插入图片描述
(1) 首先是定义了三个标签 l 1 l^1 l1 l 2 l^2 l2 l 3 l^3 l3。接着我们放入样本x。
(2) 可以观察到x和 l 1 l^1 l1比较近,所以相似度比较高,则 f 1 f_1 f1≈1。而x和 l 2 l^2 l2 l 3 l^3 l3比较远,所以相似度较低则 f 2 f_2 f2≈0、 f 3 f_3 f3≈0。
(3) 接着,我们代入表达式就可以计算出等于0.5,是大于0的,所以会分类为1。
(4) 同理我们可以将其他样本进行分类。

7、在实际应用中,我们如何选取标签 l 1 l^1 l1 l 2 l^2 l2 l 3 l^3 l3
(1) 将我们拥有的每一个样本点作为新的标记点
(2) 给新特征x,计算x与标记点的距离之和
(3) 构建完成后,使用支持向量机来进行预测
在这里插入图片描述得到 θ T f θ^Tf θTf ≥ 0,判断y = 1。

8、C和标准差σ的选择
在这里插入图片描述
(1) 当C很大的时候,就相当于λ很小,也就相当于没有正则化,所以可能会出现过拟合(低偏差,高方差)。同理可得到相反情况。

(2) 当σ比较大的时候,高斯分布比较缓和,所得到的的曲线也比较缓和,所以会出现欠拟合现象(高偏差,低方差)。当σ比较小的时候,曲线没有那么缓和,就可能出现过拟合现象(低偏差、高方差)。

σ 2 σ^2 σ2
(1) σ 2 σ^2 σ2大,特征变化较缓,高偏差,低方差。
(2) σ 2 σ^2 σ2小,特征变化较快,低偏差,高方差

9、逻辑回归与SVM比较
逻辑回归对异常值敏感,SVM对异常值不敏感(抗噪能力强)——支持向量机改变非支持向量样本并不会引起决策面的变化;但是逻辑回归中改变任何样本都会引起决策面的变化。

对于大部分情况神经网络表现都很好,但是训练慢。且SVM是凸优化问题,因此总会找到一个全局最小值,不用担心局部极小的情况。

选择
当特征数量多、训练集数量较少时,一般选用逻辑回归或者不带核函数的SVM(线性核函数)
当特征数量少、训练集数量适中时,一般选用带高斯核函数的SVM
当特征数量少、训练集数量很大时,一般选用逻辑回归或者不带核函数的SVM(如果用高斯核函数可能过慢)

10、在python中使用高斯核函数:

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

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

(3) gamma越小,模型复杂度越低,gamma越大,模型复杂度越高。

三、代码实战

在本练习中,我们将使用支持向量机(SVM)来构建垃圾邮件分类器。 我们将从一些简单的2D数据集开始使用SVM来查看它们的工作原理。 然后,我们将对一组原始电子邮件进行一些预处理工作,并使用SVM在处理的电子邮件上构建分类器,以确定它们是否为垃圾邮件。

引入所需函数库

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

首先我们要看一下这个简单的二维数据集,看看线性SVM如何对数据集进行不同的C值(类似于线性/逻辑回归中的正则化项)

我们将其用散点图表示,其中类标签由符号表示(+表示正类,o表示负类)。

# 加载数据
raw_data = loadmat('data/ex6data1.mat')

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

positive = data[data['y'].isin([1])]
negative = data[data['y'].isin([0])]

fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(positive['X1'], positive['X2'], s=50, marker='x', label='Positive')
ax.scatter(negative['X1'], negative['X2'], s=50, marker='o', label='Negative')
ax.legend()
plt.show()

在这里插入图片描述
我们注意到,还有一个异常的正例在其他样本之外。 这些类仍然是线性分离的,但它非常紧凑。 我们要训练线性支持向量机来学习类边界。

在这个练习中,我们没有从头开始执行SVM的任务,所以我要用scikit-learn。

我们先设定误差项惩罚系数C=1

svc = svm.LinearSVC(C=1, loss='hinge', max_iter=1000)
svc.fit(data[['X1', 'X2']], data['y'])
svc.score(data[['X1', 'X2']], data['y'])

结果:

0.9803921568627451

然后,让我们将C的值增大到100

svc2 = svm.LinearSVC(C=100, loss='hinge', max_iter=1000)
svc2.fit(data_1[['X1', 'X2']], data_1['y'])
print(svc2.score(data_1[['X1', 'X2']], data_1['y']))

结果:

0.9411764705882353

这次我们得到了训练数据的完美分类,但是通过增加C的值,我们创建了一个不再适合数据的决策边界。

我们可以通过查看每个类别预测的置信水平来看出这一点,这是该点与超平面距离的函数。

C=1的置信水平

data_1['SVM 1 Confidence'] = svc.decision_function(data_1[['X1', 'X2']])
fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(data_1['X1'], data_1['X2'], s=50, c=data_1['SVM 1 Confidence'], cmap='seismic')
ax.set_title('SVM (C=1) Decision Confidence')
plt.show()

在这里插入图片描述

C=100的置信水平

data_1['SVM 2 Confidence'] = svc2.decision_function(data_1[['X1', 'X2']])
fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(data_1['X1'], data_1['X2'], s=50, c=data_1['SVM 2 Confidence'], cmap='seismic')
ax.set_title('SVM (C=100) Decision Confidence')
plt.show()

在这里插入图片描述

现在我们将从线性SVM转移到能够使用内核进行非线性分类的SVM。 我们首先负责实现一个高斯核函数。 虽然scikit-learn具有内置的高斯内核,但为了实现更清楚,我们将从头开始实现。

# 高斯核函数
def gaussian_kernel(x1, x2, sigma):
    return np.exp(-(np.sum((x1 - x2) ** 2) / (2 * (sigma ** 2))))

实现一个高斯函数验证训练结果是否与预期值相符

x1 = np.array([1.0, 2.0, 1.0])
x2 = np.array([0.0, 4.0, -1.0])
sigma = 2

gaussian_kernel(x1, x2, sigma)
0.32465246735834974

该结果与练习中的预期值相符。

接下来,我们将检查另一个数据集,这次用非线性决策边界。

raw_data_2 = loadmat('ex6data2.mat')

data_2 = pd.DataFrame(raw_data_2['X'], columns=['X1', 'X2'])
data_2['y'] = raw_data_2['y']

positive = data_2[data_2['y'].isin([1])]
negative = data_2[data_2['y'].isin([0])]

fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(positive['X1'], positive['X2'], s=30, marker='x', label='Positive')
ax.scatter(negative['X1'], negative['X2'], s=30, marker='o', label='Negative')
ax.legend()
plt.show()

在这里插入图片描述

对于该数据集,我们将使用内置的RBF内核构建支持向量机分类器,并检查其对训练数据的准确性。

为了可视化决策边界,这一次我们将根据实例具有负类标签的预测概率来对点做阴影。

svc = svm.SVC(C=100, gamma=10, probability=True)
svc.fit(data_2[['X1', 'X2']], data_2['y'])
data_2['Probability'] = svc.predict_proba(data_2[['X1', 'X2']])[:,0]

fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(data_2['X1'], data_2['X2'], s=30, c=data_2['Probability'], cmap='Reds')
plt.show()

在这里插入图片描述
从结果可以看出,它们大部分是正确的。

对于第三个数据集,我们给出了训练和验证集,并且基于验证集性能为SVM模型找到最优超参数。

# 加载数据
raw_data_3 = loadmat('ex6data3.mat')
X = raw_data_3['X']
Xval = raw_data_3['Xval']
y = raw_data_3['y'].ravel()
yval = raw_data_3['yval'].ravel()
# 基于验证集性能为SVM模型找到最优超参数
C_values = [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 C_values:
    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
print(best_score, best_params)

得出最优超参数

0.965 {'C': 0.3, 'gamma': 100}

现在,我们将进行第二部分的练习。 在这一部分中,我们的目标是使用SVM来构建垃圾邮件过滤器。

# 加载数据集
spam_train = loadmat('spamTrain.mat')
spam_test = loadmat('spamTest.mat')

每个文档已经转换为一个向量,其中1899个维对应于词汇表中的1,899个单词。 它们的值为二进制,表示文档中是否存在单词。

# 每个文档已经转换为一个向量
# 它们的值为二进制,表示文档中是否存在单词
X = spam_train['X']
Xtest = spam_test['Xtest']
y = spam_train['y'].ravel()
ytest = spam_test['ytest'].ravel()

训练评估是用一个分类器拟合测试数据的问题。

使用SVM来构建垃圾邮件过滤器

svc = svm.SVC()
svc.fit(X, y)

计算训练集和测试集的精确度。

# np.round()浮点数取整
# 一般该函数遵循四舍五入原则,但是需要特别注意的是,当整数部分以0结束时,round函数一律是向下取整
# 例:np.round(10.5) >>> 10.0
print('Training accuracy = {0}%'.format(np.round(svc.score(X, y) * 100, 2)))
print('Test accuracy = {0}%'.format(np.round(svc.score(Xtest, ytest) * 100, 2)))

结果;

Training accuracy = 99.32%
Test accuracy = 98.7%

参考链接:https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes
https://blog.csdn.net/weixin_41799019/article/details/118355127?spm=1001.2014.3001.5502

  • 1
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作业一(Matlab) 假设x=(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20),y=( 2.94, 4.53, 5.96, 7.88, 9.02, 10.94, 12.14, 13.96, 14.74, 16.68, 17.79, 19.67, 21.20, 22.07, 23.75, 25.22, 27.17, 28.84, 29.84, 31.78).请写出拟合的直线方程,并画图(包括原数据点及拟合的直线),请打印出来。 请使用线性回归模型来拟合bodyfat数据。数据集介绍可阅读:https://www.mathworks.com/help/nnet/examples/body-fat-estimation.html 在matlab中,在命令行中输入[X,Y] = bodyfat_dataset; 即可获得一个拥有13个属性,252个样本的数据集。使用前200个样本来获得模型,并写出你所获得的模型。使用后52个样本做测试,汇报你所获得的泛化误差。 编程实现对数回归,并给出教材89页上的西瓜数据集3.0上的结果。要求采用4折交叉验证法来评估结果。因为此处一共17个样本,你可以去掉最后一个样本,也可以用所有数据,然后测试用5个样本。在汇报结果时,请说明你的选择。请在二维图上画出你的结果(用两种不同颜色或者形状来标注类别),同时打印出完整的代码。 作业二 采用信息增益准则,基于表4.2中编号为1、2、3、6、7、9、10、14、15、16、17的11个样本的色泽、根蒂、敲声、文理属性构建决策树。(本次作业可以用笔算,鼓励编程实现,但都需要列出主要步骤,其中log2(3)=1.585,log2(5)=2.322,log2(6)=2.585,log2(7)=2.807,log2(9)=3.17,log2(10)=3.322,log2(11)=3.459) 用表4.2中编号为4、5、8、11、12、13的样本做测试集,对上题的训练数据采用预剪枝策略构建决策树,并汇报验证集精度。 用表4.2中编号为4、5、8、11、12、13的样本做测试集,对题1所构建的决策树进行后剪枝,并汇报验证集精度。 作业三(Matlab) 试编程实现累积BP算法,在西瓜数据集2.0上(用训练数据)训练一个单隐层网络,用验证集计算出均方误差。要自己实现,不能直接调用现成的库函数。 作业四 下载并安装libsvm,http://www.csie.ntu.edu.tw/~cjlin/libsvm/ ,在西瓜数据集3.0a上分别用线性核训练一个SVM。用正类1-6和负类9-14作为训练集,其余作为测试集。C取不同的值,其它参数设为默认值。作出测试正确率随C取值变化的图,C=[1 100 10000 10^6 10^8]。 换成高斯核(宽度设为1),重复上题的步骤。 作业五 以西瓜数据集2.0(见教材76页表4.1)中样本1--16为训练集训练一个朴素贝叶斯分类器,对测试样本17进行分类。请写出详细的计算过程。 假设x_k是一个班上学生的分数,对应的分数及其分布是 x_1=30, P1=0.5,一共有14个学生; x_2=18, P2=mu,有6个学生; x_3=20, P3=2mu,有9个学生; x_4=23, P4=0.5-3mu,有10个学生; 通过最大对数似然法求出mu的值。 作业六(Python) 1 使用PCA对Yale人脸数据集进行降维,并分别观察前20、前100个特征向量所对应的图像。请随机选取3张照片来对比效果。数据集http://vision.ucsd.edu/content/yale-face-database

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值