本文基于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)))
构造的一个特征向量
训练集准确率、测试集准确率