大师兄的数据分析学习笔记(十七):分类模型(三)
大师兄的数据分析学习笔记(十九):分类集成(一)
四、支持向量机
4.1 关于支持向量机
- 支持向量机(Support Vector Machine, SVM)是一类按监督学习方式对数据进行二元分类的广义线性分类器,其决策边界是对学习样本求解的最大边距超平面。
- 如果把数据的每一个属性当做维度,那个每一条数据就是一个多维空间中的点。
-
假设有两个标注的数据,如果用一条线分开,会有无数种分法。
-
其中区分度最大的方法是,在充分将样本分开的情况下,在两个标注样本中分别找出离这条线最近的点,他们离这条线的距离是一样的,并且他们离这条线的距离之和是最大的。
- 此时,离这条线最近的两个数据的样本,就是支持向量机(Support Vector Machine)中的支持向量。
- 从数学角度分析:
- 多维空间中的维度用向量表示,其分量代表各维度:。
- 代表维度中的面,也叫超平面:。
- 高维面:
- 分界面: ->
-上面公式简化后:- 根据点到面的距离公式:, 公式中的就是维度中的面,也就是。
- 因此,间隔最大的切分也就是 。
4.2 特殊情况处理
-
在真实情况下,正负标注通常不是线性可分的:
- 通常有两种思路解决这类问题:
1. 容忍一部分的错误归类
- 在左上图的示例中,意味着在 公式中,存在一些的情况,也就意味着为无穷大,这是不能容忍的。
- 所以需要在这些最大值的基础上,求一个最小值:,尽量降低错误归类的影响。
2. 扩维
- 如由上图的示例中,可以在的基础上,增加第三维。
- 相当于将每个点的坐标离中心点距离这个特征进行了提取。(点击查看视频)
- 由于标注的可能性比较多,所以在扩围时,需要把可能涉及的维度都考虑到。
- 比如用多项式扩维法从二维扩围到五维:
- 而从三维用同样的方法可以扩展到十九维。
- 所以为了避免维度灾难,需要改变先映射,再计算,使用先计算,再扩围的方式。
- 而这种转换方式需要使用核函数,有以下几种:
- 线性核函数:
- 多项式核函数:^d
- 高斯径向基(RBF)核函数:
- 相对于决策树,支持向量机的模型更平滑:
4.3 问题处理
1.少部分异常
-
如果少数点对分类影响很大,如果忽略他可以获得分隔更大的分类器。
- 在这种情况下可以引入松弛变量,所谓松弛变量就是在原来的公式里加入衡量松弛度的变量。
-
松弛变量为了达到更宽的分界线,可以容忍少量的错分点,减少过拟合的出现。
2.样本不平衡
- 在样本不平衡的情况下,如果用SVM分类,样本会更靠近白色的部分。
- 这种情况需要根据实际业务场景判断,如果是因为采样不科学等操作误差引起的,就需要对不同的标注加权,从而影响超平面的边界位置。
3.多分类问题
- 如果有多个分类的情况,有以下两种解决方式:
- 有几个分类,就建几个SVM,将样本的每个SVM都跑一遍,找成功分类并且离超平面最远的作为正确分类。
- 在分类两两之间分别建立SVM,取出其中被分类次数最多的分类作为正确分类。
4.4 代码实现
>>>import os
>>>import pandas as pd
>>>import numpy as np
>>>from sklearn.model_selection import train_test_split
>>>from sklearn.metrics import accuracy_score,recall_score,f1_score
>>>from sklearn.svm import SVC
>>>models = []
>>>models.append(("SVM Classifier",SVC()))
>>>df = pd.read_csv(os.path.join(".", "data", "WA_Fn-UseC_-HR-Employee-Attrition.csv"))
>>>X_tt,X_validation,Y_tt,Y_validation = train_test_split(df.JobLevel,df.JobSatisfaction,test_size=0.2)
>>>X_train,X_test,Y_train,Y_test = train_test_split(X_tt,Y_tt,test_size=0.25)
>>>for clf_name,clf in models:
>>> clf.fit(np.array(X_train).reshape(-1,1),np.array(Y_train).reshape(-1,1))
>>> xy_lst = [(X_train,Y_train),(X_validation,Y_validation),(X_test,Y_test)]
>>> for i in range(len(xy_lst)):
>>> X_part = xy_lst[i][0]
>>> Y_part = xy_lst[i][1]
>>> Y_pred = clf.predict(np.array(X_part).reshape(-1,1))
>>> print(i)
>>> print(clf_name,"-ACC",accuracy_score(Y_part,Y_pred))
>>> print(clf_name,"-REC",recall_score(Y_part,Y_pred,average='macro'))
>>> print(clf_name,"-F1",f1_score(Y_part,Y_pred,average='macro'))
>>> print("="*40)
0
SVM Classifier -ACC 0.3197278911564626
SVM Classifier -REC 0.2620657705498396
SVM Classifier -F1 0.19869489047039893
========================================
1
SVM Classifier -ACC 0.29591836734693877
SVM Classifier -REC 0.23682033096926713
SVM Classifier -F1 0.18196778711484593
========================================
2
SVM Classifier -ACC 0.2755102040816326
SVM Classifier -REC 0.22332554517133957
SVM Classifier -F1 0.1684558664064194
========================================