01 机器学习-支持向量机(SVM)

目录

1.1 基本概念

1.2 关键词

1.3 公式推导

1.4 算法优点与缺点

1.5 案例分析

1.5.1 模型调参

1.5.2 检查过拟合

1.5.3 null accuracy

1.5.4 小结

1.5.5 混淆矩阵

1.5.6 分类报告

1.5.7 ROC-AUC

1.5.8 小结

1.5.9 k折交叉验证

1.5.10 基于GridSearch CV的超参数优化

1.5.11 小结

1.6 附录(数据集及源代码)

1.7 参考资料


1.1 基本概念

支持向量机(Support vector machines, SVM)是一种二分类模型,它将实例的特征向量映射为空间中的一些点,SVM 的目的就是想要画出一条线,以 “最好地” 区分这两类点,以至如果以后有了新的点,这条线也能做出很好的分类。

1.2 关键词

线性可分:我们把实例的特征向量映射到n维空间中的样本点,如果以二维平面为例,利用一条直线可以将样本点分为两类,我们称这个样本线性可分。

决策分界线:将两类样本点分开的线。

超平面:把二维平面推广到n维空间,此时样本空间的划分就不是一条线了,决策分界线成为超平面。

支持向量:映射到n维空间距离超平面最近样本点的向量。  

核函数:以二维平面为例,当我们将其推广到n维欧式空间时,需要利用函数将二维样本点映射到n维空间,这个函数称之为核函数(Kernel Function)。

线性核函数:kernel=‘linear’

多项式核函数:kernel=poly

径向基核函数:kernel=‘rbf’

sigmod核函数:kernel=‘sigmod’

支持向量回归:Support Vector Regression, SVR

支持向量分类:Support Vector Classification,SVC

1.3 公式推导

链接:【机器学习】支持向量机 SVM(非常详细) - 知乎 (zhihu.com)

1.4 算法优点与缺点

优点:1. 可以利用内积核函数处理高维空间的非线性映射;

           2. 对于小样本案例具有高效的解决方法,从训练样本到预报样本,不同于传统的从归纳到演绎;

           3. 少数的支持向量决定了最后的结果,可以帮助我们抓住关键样本,剔除冗余样本,从而使得模型具有较好的鲁棒性:

                1) 增、删非支持向量样本对模型没有影响;

                2) 支持向量样本集具有一定的鲁棒性;

                3) 有些成功的应用中,SVM 方法对核的选取不敏感;

缺点:1.处理海量数据时,SVM运算量巨大,效率低下;

           2. 在处理某些非线性问题时,核函数难以寻找;

           3. 经典的SVM一般用于解决二分类问题,对于多分类问题难以下手。我们面对这种多分类问题一般构造多个分类器或利用SVM决策树进行处理,主要为了克服经典SVM客观存在的缺点,结合其他算法的优势与经典SVM进行互补,提高模型分类精度。

1.5 案例分析

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import matplotlib.pyplot as plt # for data visualization
import seaborn as sns # for statistical data visualization

#忽略警告信息
import warnings
warnings.filterwarnings('ignore')

#导入数据
data = 'pulsar_stars.csv'
df = pd.read_csv(data)

df.columns = df.columns.str.strip()  #删除列空格
col_names = df.columns

df.columns = ['IP Mean', 'IP Sd', 'IP Kurtosis', 'IP Skewness', 
              'DM-SNR Mean', 'DM-SNR Sd', 'DM-SNR Kurtosis', 
              'DM-SNR Skewness', 'target_class']  #简化列名称

df['target_class'].value_counts() #检索目标列不同数值的个数
df['target_class'].value_counts()/np.float(len(df)) #检索目标列数值占比

#分析数据 数量 平均值 方差 中位数...
round(df.describe(),2)

#提取目标函数以及特征向量
X = df.drop(['target_class'], axis=1) #删除target_class这列 axis=1时为删除列 默认删除行
y = df['target_class']

#将数据分割为单独的训练集和测试集
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)

#数据预处理 特征向量归一化
cols = X_train.columns  #寄存列标签
print(cols)

#标准化数据 归一化数据
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
print("处理前")
print(X_train)
X_train = scaler.fit_transform(X_train) 
print("处理后")
print(X_train)
X_test = scaler.transform(X_test)

#整理归一化后的训练集和测试集数据
X_train = pd.DataFrame(X_train, columns=[cols]) 
X_test = pd.DataFrame(X_test, columns=[cols])
X_train.describe()  #分析数据 数量 平均值 方差 中位数...

图1 归一化后的训练集数据分析
#利用SVM训练数据 
# 默认惩罚程度C=1.0  
# 核函数使用径向基核函数(RBF)kernel=‘rbf  
# RBF的Gamma参数控制单个训练点的影响距离

from sklearn.svm import SVC  #利用SVC求解分类超平面
from sklearn.metrics import accuracy_score  #准确性评价


# 实例化分类器
svc=SVC() 


# 训练数据拟合模型
svc.fit(X_train,y_train)


# 对测试集预测
y_pred=svc.predict(X_test)


# 打印精度
print('Model accuracy score with default 
hyperparameters: {0:0.4f}'. 
format(accuracy_score(y_test, y_pred)))

图2 模型精度:0.9827  C=1.0 kernel=RBF

1.5.1 模型调参

我们在前期分析数据时可以观察到,这个数据集存在较多的异常点,如图3所示:

图3 异常点观测

 在SVC中参数C为惩罚系数,用于调整损失函数,因为异常点较多,我们把C调高,运行结果如下:

图4 模型精度:0.9832  C=100.0 kernel=RBF
图5 模型精度:0.9816  C=1000.0 kernel=RBF

尝试使用其他核函数进行模型拟合:

图6 模型精度:0.9830  C=1.0 kernel=linear

图7 模型精度:0.9830  C=1.0 kernel=poly

1.5.2 检查过拟合

现在,我们比较训练集和测试集的准确性,以检查过拟合。利用Y text和Y pre的Accuracy Score与Y Pre train和Y train的Accuracy Score,如图8所示:

图8 SVM 模型框架

 在这里,我们以C=1000,kernel="linear"为例进行验证:

#过拟合验证
linear_svc=SVC(kernel='linear',C=1000) 
linear_svc.fit(X_train, y_train)
y_pred=linear_svc.predict(X_test)
y_pred_train = linear_svc.predict(X_train)
print('Training set score: {:.4f}'.format(linear_svc.score(X_train, y_train)))
print('Test set score: {:.4f}'.format(linear_svc.score(X_test, y_test))

训练集准确度得分为0.9783,测试集准确度得分为0.9830。这两个值相近。所以,不存在过拟合的问题。

1.5.3 null accuracy

即使这样,我们还不能得出这个模型很好的结论,我们必须再观察一下null accuracy,null accurracy是测试集中最多那一类的占比。我们测试集的预测结果:

print(y_test.value_counts())
图9 分类结果
null_accuracy = (3306/(3306+274))

print('Null accuracy score: {0:0.4f}'. format(null_accuracy))
图10 null accuracy

1.5.4 小结

经过以上几次参数调整的比较,我们得出采用RBF和C=100.0的参数可以得到较高精度,accuracy为0.9832。基于以上分析我们可以得出,我们的模型预测精度非常高,预测类标签方面做的很好。

但实际上我们的精度并不是真的高,我们的数据集是不平衡的,即两类数据量相差较大。在数据不平衡的情况下,准确度不足以量化模型的预测性能。

因此,我们必须探索在选择模型时提供更好指导的替代量。评估不平衡数据模型的一个很好的方法是混淆矩阵。


1.5.5 混淆矩阵

混淆矩阵也称误差矩阵,是表示精度评价的一种标准格式,用n行n列的矩阵形式来表示。

例如:我们利用训练好模型进行苹果的图像识别,建立混淆矩阵对模型进行评估如下:

表1 混淆矩阵举例说明
混淆矩阵样本是苹果样本不是苹果
预测结果是苹果TPFN
预测结果不是苹果FPTN

精度:也称准确率,

Accuracy=\frac{TP+TN}{ALL}

查全率:也称召回率,

Recall=\frac{TP}{TP+FN}

查准率:也称精准率,

Precision=\frac{TP}{TP+FP}

F1度量:在一些应用中,对查准率和查全率的重视程度有所不同。F1度量能表达出对查准率/查全率的不同偏好,

F_{\beta }=\frac{(1+\beta ^{2})\times P\times R)}{(\beta ^{2}\times P)+R}

我们利用混淆矩阵对我们训练好的模型进行评估:

#利用混淆矩阵验证模型
y_pre_test=linear_svc.predict(y_test)
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pre_test)

print('Confusion matrix\n\n', cm)
print('\nTrue Positives(TP) = ', cm[0,0])
print('\nTrue Negatives(TN) = ', cm[1,1])
print('\nFalse Positives(FP) = ', cm[0,1])
print('\nFalse Negatives(FN) = ', cm[1,0])

cm_matrix = pd.DataFrame(data=cm, 
            columns=['Actual Positive:1', 'Actual Negative:0'], 
            index=['Predict Positive:1', 'Predict Negative:0'])
sns.heatmap(cm_matrix, annot=True, fmt='d', cmap='YlGnBu')
图11 案例混淆矩阵

1.5.6 分类报告

分类报告是评估模型的另一种方法,它可以将模型的精度、召回率、f1和支持度分数等表示出来。

下面我们将模型准确度(精度)、错误率、精准率(查准率)、召回率(查全率)、真阳率、

假阳率、特异度进行计算。

#分类报告
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pre_test))
TP = cm[0,0]
TN = cm[1,1]
FP = cm[0,1]
FN = cm[1,0]
#准确率
classification_accuracy = (TP + TN) / float(TP + TN + FP + FN)
print('Classification accuracy : {0:0.4f}'.format(classification_accuracy))
#错误率
classification_error = (FP + FN) / float(TP + TN + FP + FN)
print('Classification error : {0:0.4f}'.format(classification_error))
#精准率(查准率)
precision = TP / float(TP + FP)
print('Precision : {0:0.4f}'.format(precision))
#召回率(查全率)
recall = TP / float(TP + FN)
print('Recall or Sensitivity : {0:0.4f}'.format(recall))
#真阳率
true_positive_rate = TP / float(TP + FN)
print('True Positive Rate : {0:0.4f}'.format(true_positive_rate))
#假阳率
false_positive_rate = FP / float(FP + TN)
print('False Positive Rate : {0:0.4f}'.format(false_positive_rate))
#特异度
specificity = TN / (TN + FP)
print('Specificity : {0:0.4f}'.format(specificity))
图12 分类报表

1.5.7 ROC-AUC

ROC是评估分类器效果的一个指标。在介绍ROC前,我们先对真正例率(True Positive Rate, TPR)和假正例率(Flase Positive Rate, FPR)进行理解。在混淆矩阵中,我们定义:

TPR=\frac{TP}{TP+FN}

FPR=\frac{FP}{FP+TN}

分类器对一组数据集进行分类,得到其预测值,然后对其进行混淆矩阵的建立,获取这组数据集的TPR和FPR。建立以FPR为横轴、TPR为纵轴的直角坐标系。这组数据集预测后的结果在坐标系上就表示为一个点(FPR,TPR)。

这个点还对应着一个变量,概率输出(threshold),即表示分类器认为某个样本具有多大的概率属于正样本。

我们在现实任务中利用有限个测试样例进行ROC图的绘制,这仅能获得有限个坐标对,当测试样例不断增多时图像趋向于光滑,如图13所示。

图13 ROC曲线 源自周志华-机器学习

我们利用roc_curve()对ROC曲线进行绘制,对该函数输入两个变量:测试集真实值y_test和预测值y_pred_test,绘制出ROC曲线上的一个点。

#绘制ROC曲线
from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(y_test, y_pred_test)
plt.figure(figsize=(6,4))
plt.plot(fpr, tpr, linewidth=2)
plt.plot([0,1], [0,1], 'k--' )
plt.rcParams['font.size'] = 12
plt.title('ROC curve for Predicting a Pulsar Star classifier')
plt.xlabel('False Positive Rate (1 - Specificity)')
plt.ylabel('True Positive Rate (Sensitivity)')

plt.show()
图14 ROC曲线

AUC为ROC曲线与横轴围成的面积,通常情况下一个模型的AUC越大,则该模型的分类性能越理想。

#计算AUC
from sklearn.metrics import roc_auc_score
ROC_AUC = roc_auc_score(y_test, y_pre_test)
print('ROC AUC : {:.4f}'.format(ROC_AUC))
图15 AUC计算结果

1.5.8 小结

我们模型的AUC接近于1。 因此,我们可以得出结论,我们的分类器在对pulsar_stars进行分类方面做得很好。  

1.5.9 k折交叉验证

初始采样分割成K个子样本,一个单独的子样本被保留作为验证模型的数据,其他K-1个样本用来训练。交叉验证重复K次,每个子样本验证一次,平均K次的结果或者使用其它结合方式,最终得到一个单一估测。

#K折交叉验证
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score

kfold=KFold(n_splits=5, shuffle=True, random_state=0)
#利用线性核函数验证
linear_svc=SVC(kernel='linear')
linear_scores = cross_val_score(linear_svc, X, y, cv=kfold)
print('Stratified Cross-validation scores with rbf kernel:\n\n{}'.format(linear_scores))
print('Average stratified cross-validation score with rbf kernel:{:.4f}'.format(linear_scores.mean()))

rbf_svc=SVC(kernel='rbf')
rbf_scores = cross_val_score(rbf_svc, X, y, cv=kfold)
print('Stratified Cross-validation scores with rbf kernel:\n\n{}'.format(rbf_scores))
print('Average stratified cross-validation score with rbf kernel:{:.4f}'.format(rbf_scores.mean()))
图16 5折交叉验证结果

1.5.10 基于GridSearch CV的超参数优化

Grid Search:一种调参手段,在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果。其原理就像是在数组里找最大值。

#利用GridSearch CV进行超参数优化
from sklearn.model_selection import GridSearchCV
# import SVC classifier
from sklearn.svm import SVC
# instantiate classifier with default hyperparameters with kernel=rbf, C=1.0 and gamma=auto
svc=SVC() 
# declare parameters for hyperparameter tuning
parameters = [ {'C':[1, 10, 100, 1000], 'kernel':['linear']},
               {'C':[1, 10, 100, 1000], 'kernel':['rbf'], 'gamma':[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]},
               {'C':[1, 10, 100, 1000], 'kernel':['poly'], 'degree': [2,3,4] ,'gamma':[0.01,0.02,0.03,0.04,0.05]} 
              ]
grid_search = GridSearchCV(estimator = svc,  
                           param_grid = parameters,
                           scoring = 'accuracy',
                           cv = 5,
                           verbose=0)
grid_search.fit(X_train, y_train)


# best score achieved during the GridSearchCV
print('GridSearch CV best score : {:.4f}\n\n'.format(grid_search.best_score_))
# print parameters that give the best results
print('Parameters that give the best results :','\n\n', (grid_search.best_params_))
# print estimator that was chosen by the GridSearch
print('\n\nEstimator that was chosen by the search :','\n\n', (grid_search.best_estimator_))
# calculate GridSearch CV score on test set
print('GridSearch CV score on test set: {0:0.4f}'.format(grid_search.score(X_test, y_test)))
图17 GridSearch CV参数优化结果

1.5.11 小结

我们的原始模型测试精度为0.9832,而GridSearch CV在测试集上的得分为0.9835。  因此,GridSearch CV有助于模型参数优化。

1.6 附录(数据集及源代码)

SVM案例(包括数据集)-机器学习文档类资源-CSDN文库

1.7 参考资料

01 (7条消息) 机器学习算法(一)SVM_yaoyz105-CSDN博客_svm

02  SVM核方法--这是我见过最好的一个视频。。核技巧核函数_哔哩哔哩_bilibili

03 【机器学习】支持向量机 SVM(非常详细) - 知乎 (zhihu.com)

04 (8条消息) 支持向量机(SVM)的优缺点_浆果吖的博客-CSDN博客_svm的优缺点

05 支持向量机(SVC) - 知乎 (zhihu.com)

06 SVM Classifier Tutorial | Kaggle

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我本逍遥Kurt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值