机器学习练习6-支持向量机

本文基于Andrew_Ng的ML课程作业

1-Linear Support Vector Classification: svm.LinearSVC:线性分类的支持向量机

导入库

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

函数:画出决策曲线

def plot_decision_boundary(svc,x1min,x1max,x2min,x2max,data):  #画出决策曲线
    t1=np.linspace(x1min,x1max,1000)
    t2=np.linspace(x2min,x2max,1000)
    cordinates=[(x1,x2) for x1 in t1 for x2 in t2]
    x1_cord,x2_cord=zip(*cordinates)
    h_val=pd.DataFrame({'X1':x1_cord,'X2':x2_cord})
    h_val['hval']=svc.decision_function(h_val[['X1','X2']])
        #函数:svc.decision_function(X):样本X到分割超平面的函数距离,这里就是预测值
    decision=h_val[np.abs(h_val['hval'])<2*10**-3]
    x1plot,x2plot=decision['X1'],decision['X2']
    fig,ax=plt.subplots(figsize=(12,8))
    positive = data[data['y'].isin([1])]
    negative = data[data['y'].isin([0])]
    ax.scatter(positive['X1'], positive['X2'], s=50, marker='o', label="Positive")
    ax.scatter(negative['X1'], negative['X2'], s=50, marker='x', label="Negative")
    ax.scatter(x1plot,x2plot,s=10,c='r',label="Boundary")
    ax.set_title("SVM(C=100) Decision Boundary")
    ax.legend(loc='upper right')
    plt.show()

主函数:

# Linear Support Vector Classification: svm.LinearSVC:线性分类的支持向量机

raw_data=loadmat('ex6data1.mat')
data=pd.DataFrame(raw_data.get('X'),columns=['X1','X2'])    #这里不用X=data['X']然后后面svc.fit(X,y)原因:用Dataframe标明特征名称标签方便单独取某一特征的值data['X1']
    #dict.get(key):利用键获取值,当字典中不存在输入的键时返回None,相比dict[key]程序运行时就不会出异常(这里得到的值是一个n行2列的数组)
data['y']=raw_data.get('y')
svc=svm.LinearSVC(C=1.0,loss='hinge',max_iter=3000)
    #svm.LinearSVC(C=1.0,loss=' ',max_iter= )
    #参数:C:float,(default=1.0)错误项的惩罚参数;loss:'hinge'or'squared_hinge'(default='squared_hinge')指定损失参数,"hinge":标准的SVM损失(例如由SVC类使用);"squared_hinge":hinge损失的平方;max_iter:(default=1000)运行的最大迭代次数
svc.fit(data[['X1','X2']],data['y'])    #data[['X1','X2']]套双中括号才能同时取出X1和X2列的数据,data['X1','X2']无法取数,[data['X1'],data['X2']]分别取不是同时取
    #函数:svc.fit(X,y):根据给定的训练数据拟合SVM模型
print('accuracy={:.2%}'.format(svc.score(data[['X1','X2']],data['y'])))
    #函数:svc.score(X,y):返回给定测试数据和标签的平均精确度
plot_decision_boundary(svc,0,4,1.5,5,data)

预测准确率(C=1)

 决策曲线(C=1)

 决策曲线(C=100)

2-NonLinear Support Vector Classification: svm.SVC:高斯内核的支持向量机

导入库

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

函数:高斯内核函数(scikit-learn中具有内置的高斯内核,故在本project中并未作用)

def gaussian_kernal(x1,x2,sigma):   #高斯内核函数(scikit-learn中具有内置的高斯内核,故在本project中并未作用)
    f=np.exp((-np.sum((x1-x2)**2))/(2*(sigma**2)))
    return f

函数:画出决策曲线

def plot_decision_boundary(svc,x1min,x1max,x2min,x2max,data):  #画出决策曲线
    t1=np.linspace(x1min,x1max,1000)
    t2=np.linspace(x2min,x2max,1000)
    cordinates=[(x1,x2) for x1 in t1 for x2 in t2]
    x1_cord,x2_cord=zip(*cordinates)
    h_val=pd.DataFrame({'X1':x1_cord,'X2':x2_cord})
    h_val['hval']=svc.decision_function(h_val[['X1','X2']])
    decision=h_val[np.abs(h_val['hval'])<2*10**-3]
    x1plot,x2plot=decision['X1'],decision['X2']
    fig,ax=plt.subplots(figsize=(12,8))
    positive = data[data['y'].isin([1])]
    negative = data[data['y'].isin([0])]
    ax.scatter(positive['X1'], positive['X2'], s=50, marker='o', label="Positive")
    ax.scatter(negative['X1'], negative['X2'], s=50, marker='x', label="Negative")
    ax.scatter(x1plot,x2plot,s=10,c='r',label="Boundary")
    ax.set_title("SVM(C=100) Decision Boundary")
    ax.legend(loc='upper right')
    plt.show()

主函数:

# NonLinear Support Vector Classification: svm.SVC:高斯内核的支持向量机

raw_data=loadmat('ex6data2.mat')
data=pd.DataFrame(raw_data.get('X'),columns=['X1','X2'])
data['y']=raw_data.get('y')
svc=svm.SVC(C=100.0,kernel='rbf',gamma=10)
    #svm.LinearSVC(C=1.0,kernel='rbf',degree=3,gamma='auto',coef0=0.0,probability=False,max_iter=-1)
    #参数:C:float,(default=1.0)错误项的惩罚参数;kernel:核函数,默认是rbf(Radial Basis Function,也称为高斯核函数),可以是'linear','poly','rbf','sigmoid';degree:多项式poly函数的维度,默认是3,选择其他核函数时会被忽略
        #gamma:'rbf','poly','sigmoid'的核函数参数;默认是'auto',则会选择1/n features;coef0:核函数的常数项;对于'poly'和'sigmoid'有用;max_iter:最大迭代次数,-1为无限制
svc.fit(data[['X1','X2']],data['y'])
print('accuracy={:.2%}'.format(svc.score(data[['X1','X2']],data['y'])))
plot_decision_boundary(svc,0,1,0.4,1,data)

预测准确率

 决策曲线(C=100)

3-NonLinear Support Vector Classification: svm.SVC:使用训练集拟合模型,使用交叉验证集为SVM模型找到最优参数C和sigma

导入库

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

函数:基于验证集为SVM模型寻找最优参数C和sigma

def find_best_params(X,y,Xval,yval):    #基于验证集为SVM模型寻找最优参数C和sigma
    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_accuracy = 0
    best_params = {'C': None, 'gamma': None}
    for C in C_values:
        for gamma in gamma_values:
            svc = svm.SVC(C=C, kernel='rbf', gamma=gamma)
            svc.fit(X, y)  # 用训练集拟合模型
            accuracy = svc.score(Xval, yval)  # 用交叉验证集寻找最优参数
            if accuracy > best_accuracy:
                best_accuracy = accuracy
                best_params['C'] = C
                best_params['gamma'] = gamma
    print(best_accuracy, best_params)
    return best_params

函数:画出决策曲线

def plot_decision_boundary(svc,x1min,x1max,x2min,x2max,data):  #画出决策曲线
    t1=np.linspace(x1min,x1max,1000)
    t2=np.linspace(x2min,x2max,1000)
    cordinates=[(x1,x2) for x1 in t1 for x2 in t2]
    x1_cord,x2_cord=zip(*cordinates)
    h_val=pd.DataFrame({'X1':x1_cord,'X2':x2_cord})
    h_val['hval']=svc.decision_function(h_val[['X1','X2']])
    decision=h_val[np.abs(h_val['hval'])<2*10**-3]
    x1plot,x2plot=decision['X1'],decision['X2']
    fig,ax=plt.subplots(figsize=(12,8))
    positive = data[data['y'].isin([1])]
    negative = data[data['y'].isin([0])]
    ax.scatter(positive['X1'], positive['X2'], s=50, marker='o', label="Positive")
    ax.scatter(negative['X1'], negative['X2'], s=50, marker='x', label="Negative")
    ax.scatter(x1plot,x2plot,s=10,c='r',label="Boundary")
    ax.set_title("SVM(with best_params C:0.3 gamma:100) Decision Boundary")
    ax.legend(loc='upper right')
    plt.show()

主函数:

# NonLinear Support Vector Classification: svm.SVC:使用训练集拟合模型,使用交叉验证集为SVM模型找到最优参数C和sigma

raw_data=loadmat('ex6data3.mat')
X=raw_data['X']
Xval=raw_data['Xval']
y=raw_data['y'].ravel() #传入svc.fit(X,y)的y要求为一维数组
yval=raw_data['yval'].ravel()
data=pd.DataFrame(raw_data.get('X'),columns=['X1','X2'])
data['y']=raw_data.get('y')

best_params=find_best_params(X,y,Xval,yval)
svc=svm.SVC(C=best_params['C'], kernel='rbf', gamma=best_params['gamma'])
svc.fit(X,y)
plot_decision_boundary(svc,-0.6,0.3,-0.7,0.6,data)

best_accuracy and best_parameters

 决策曲线(with best params)

4-NonLinear Support Vector Classification: svm.SVC:使用训练集拟合模型,使用交叉验证集为SVM模型找到最优参数C和sigma

导入库

import numpy as np
import pandas as pd
from scipy.io import loadmat
from sklearn import svm
import re
from nltk.stem import PorterStemmer

函数:邮件预处理函数1:完成邮件预处理步骤1~6(关于每个步骤的模式字符串pattern即正则表达式修饰符的具体内容并不深究)

def preprocessing1(email):   #邮件预处理函数1:完成邮件预处理步骤1~6(关于每个步骤的模式字符串pattern即正则表达式修饰符的具体内容并不深究)
    # 1.把整封邮件转化为小写
    email=email.lower()
    # 2.移除所有HTML标签(超文本标记语言)
    email=re.sub(r'<.*>','',email)
        #re(regular expression):re.sub(pattern,repl,string)是正则表达式方面的函数,用来实现通过正则表达式,实现比普通字符串的replace更加强大的替换功能,然后返回被替换后的字符串
        #r表示去掉反斜杠的转移机制:比如r"\n"表示普通字符串\n而不表示换行
    # 3.将所有的URL替换为'httpaddr'
    email=re.sub(r'(http|https)://[^\s]*','httpaddr',email)
    # 4.将所有的地址替换为'emailaddr'
    email=re.sub(r'[^\s]+@[^\s]+','emailaddr',email)
    # 5.将所有数字替换为'number'
    email=re.sub(r'[0-9]+','number',email)
    # 6.将所有美元符号($)替换为'dollar'
    email=re.sub(r'[\$][0-9]+','dollar',email)  #移除连接在一起的$和number
    email=re.sub(r'\$','dollar number',email)   #移除单个$
    return email

函数:邮件预处理函数2:完成邮件预处理步骤7~8(关于每个步骤的模式字符串pattern具体内容并不深究)

def preprocessing2(email):  #邮件预处理函数2:完成邮件预处理步骤7~8(关于每个步骤的模式字符串pattern具体内容并不深究)
    stemmer=PorterStemmer() #PorterStemmer():词干提取器,从英语单词中删除较常见的词法和前后缀,可能出现create,created提取后变成creat的情况
    email=preprocessing1(email)
    #将邮件分割为单个单词,re.split()可以设置多种分隔符
    tokens=re.split('[ \@\$\/\#\.\-\:\&\*\+\=\[\]\?\!\(\)\{\}\,\'\"\>\_\<\;\%]',email)
        #re.split(pattern,string):按照所匹配的字符串pattern将字符串string进行切分,返回切分后的字符串列表
    tokenlist=[]
    #遍历每个分割出来的内容
    for token in tokens:
        # 7.移除所有非文字类型,所有的空格(tabs, newlines, spaces)调整为一个空格
        token=re.sub('[^a-zA-Z0-9]','',token)
        # 8.将所有单词还原为词根。例如,"discount","discounts","discounted","discounting"都替换为"discount"
        stemmed=stemmer.stem(token) #PorterStemmer().stem(token)
        if not len(token):continue  #遇到空字符串就跳到下一个token
        tokenlist.append(stemmed)
    return tokenlist

函数:对照单词表得到样例对应的序号列:提取email中存在于vocab.txt(常用单词表1899维)中的单词在vocab.txt中的索引index

def VocabIndex(email,vocab):    #●对照单词表得到样例对应的序号列:提取email中存在于vocab.txt(常用单词表1899维)中的单词在vocab.txt中的索引index
    tokenlist=preprocessing2(email)
    index=[i for i in range(len(vocab)) if vocab[i] in tokenlist]
    return index

函数:提取特征:得到邮件的一个特征向量,x∈R^n=1899

def extractFeature(email):  #●提取特征:得到邮件的一个特征向量,x∈R^n=1899
    df=pd.read_table('vocab.txt',names=['words'])   #这里不用open/f.read()/f.close()读取txt文件因为:len(vocab)时会将每个单词每个字母算作一个长度
        #pd.read_table('',names=['','']):读取txt文件,返回一个二维的DataFrame,.values后返回二维数组(Dataframe内容)
    vocab=df.values
    vector=np.zeros(len(vocab))
    voc_index=VocabIndex(email,vocab)
    for j in voc_index:
        vector[j]=1
    return vector

函数:完成垃圾邮件过滤器前三大步骤的整合函数

def create_one_feature_vector():    #完成垃圾邮件过滤器前三大步骤的整合函数
    # Preprocessing of Emails
    # 0.读取样例邮件并查看
    f = open('emailSample1.txt', 'r')  # file.open( ,'r'):打开文件,读取模式
    email = f.read()  # file.read([size]):读取文件,size表示读取的字符或字节数,为None或负数时读取到EOF文件结尾处
    f.close()  # file.close():关闭打开的文件
    # 这里不用pd.read_table()读取txt文件因为:pd会将email放进Dataframe形式的表格里,但是一段话显然不能放进表格里

    vector = extractFeature(email)
    print("One feature vector:" + str(vector))
    print('length of vector = {}\nnum of non-zero = {}'.format(len(vector), int(vector.sum())))

主函数:

# Building a spam classifier with SVM:使用SVM构建垃圾邮件过滤器

#●邮件预处理
#0.读取样例邮件并查看
#1.把整封邮件转化为小写
#2.移除所有HTML标签(超文本标记语言)
#3.将所有的URL替换为'httpaddr'
#4.将所有的地址替换为'emailaddr'
#5.将所有数字替换为'number'
#6.将所有美元符号($)替换为'dollar'
#7.移除所有非文字类型,所有的空格(tabs, newlines, spaces)调整为一个空格
#8.将所有单词还原为词根。例如,"discount","discounts","discounted","discounting"都替换为"discount"
#●对照单词表得到样例对应的序号列
#●提取特征:得到邮件的一个特征向量,x∈R^n=1899
#●训练SVM。用训练集训练出模型,再在测试集上测试

create_one_feature_vector() #因为只有一个样本,所以只能创造一个特征向量,实际上我们需要很多个样本,这里只是举例如何处理一个样本,后续我们直接使用已经提供的特征向量集

#●训练SVM。用训练集训练出模型,再在测试集上测试
spam_train=loadmat('spamTrain.mat')
spam_test=loadmat('spamTest.mat')
X=spam_train['X']   #(4000,1899):每个文档是一个样本,1899个维(特征)对应于垃圾邮件词汇表中的1899个单词,它们的值为二进制,表明文档中是否存在某单词
Xtest=spam_test['Xtest']    #(1000,1899)
y=spam_train['y'].ravel()   #(4000,)
ytest=spam_test['ytest'].ravel()    #(1000,)
svc=svm.SVC()   #参数默认
svc.fit(X,y)
print('Training accuracy={:.2%}'.format(svc.score(X,y)))
print('Test accuracy={:.2%}'.format(svc.score(Xtest,ytest)))

构造的一个特征向量

 训练集准确率、测试集准确率

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值