第一次看到SVM还是初次接触到机器学习的时候,感觉这个算法很高级,什么超平面,核函数之类,搞得挺晕乎的,接着又用这个算法,感觉性能比决策树等一般的机器学习算法并没有什么优势,所以也没啥兴趣学这玩意,这次在数据分析实战四十五讲上看到这个算法的讲解,就顺便做个笔记吧,我也只能算粗略地了解下这个算法,所以这篇文章中并没有什么复杂的数学公式推导,这种网上也是一艘一大堆。
概念和基本理解
SVM的英文全称是Support Vector Machines,我们叫它支持向量机。支持向量机是我们用于分类的一种算法,是属于有监督的学习算法。
SVM不光可以处理线性可分的数据,还可以处理非线性可分的数据。所谓的线性可分,就是可以找到一个线,将样本分成两个部分;对于非线性可分的数据,比如在一个平面中红球和白球混在一起,这时候没办法找到直线将样本分开,对于SVM算法来说可以找一个核函数,将数据映射到更高的维度,然后找到超平面将样本分开,就像将平面拍下,让球都弹起来,如果红球和白球的质量不同,则质量轻的弹的更高,这样就可以把两种球找到了。
分类间隔:如果在二维平面上,划分一条线可以将样本分为两类,如果是多维空句,直线就变成了决策面,这样的直线或决策面不是一个,在平移的时候,可以找到非常靠近两类的极限位置,超过这个位置,就会分类错误,这两个极限位置中间的距离称为分类间隔,中间的分类线就是我们找最优分类决策面。
如果我们在转动最优决策面,可能存在多个最优决策面,我们就找最大分类间隔的决策面,那么最优决策面离两类的距离才最远,这样分类器的泛化能力才最好,因为样品毕竟是这个部分的,不是所有的数据。
支持向量:支持向量是上面说的最靠近两类数据的样本,这些样本数据决定了决策面,其他的样本对结果影响不大。
超平面: 在二维空间分开两类数据是一条线(线性情况下),在三维空间中就是一个平面,维数还可能更多,我们给这个线性的函数起个名字就叫“超平面”。
SVM算法就是去找一个超平面,使用分类间隔的距离最大。
比如下图中,右面的分类间隔更大,显然中间的那条线就是我们要找到的超平面。
硬间隔:SVM分类器分的是完全准确的没有错误的。
软间隔:准许存在一定量的样本是分类错误的。
例子
在sklearn中同样有SVM算法的工具包可以使用,SVM既可以做回归,也可以做分类。做回归的时候使用的是SVR或LinearSVR;做分类的时候可以用的是SVC即Support Vector Classification。
model = svm.SVC(kernel='rbf',C=1.0,gamma='auto'
说明:
kernel 表示核函数 取值如下:
linear:线性函数,用于线性可分场景,速度快效果好。
poly:多项式函数, 将数据从低维空间映射到高维度空间,参数多,计算量大。
rbf:高斯核函数(默认),同样将样本映射到高维空间,但是参数少,性能更好。
sigmoid:sigmoid核心函数,此函数通常用在神经网络中,实现的是多层神经网络。参数C 表示惩罚的系数,C越大,分类错误惩罚越大,数据拟合更好,但是容错性毕竟差。
C越小,泛化能力强,分类准确度不高。参数gamma表示核函数系数,一般取值为样本数量的倒数。
利用老师课上的例子,数据见链接:https://github.com/cystanford/breast_cancer_data/
探索数据:
数字越接近1相关性越大,通过相关性视图我们有两种方式来选特征:
- 相关性大的特征我们可以选择其中一个代表,其他的删除。
- 找和结果值相关性大的特征。
根据上面的相关性分析,我选择了下面的特征:
features_remain = ['radius_mean','perimeter_mean','area_mean','concave points_mean','radius_worst','perimeter_worst','area_worst','concave points_worst']
目前选择是采用第二种方法,如果想进一步减少,还可以分析下这里面的特征的相关性,去掉相关性大的特征。
在原有代码上稍加改动代码示例:
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 加载数据集,你需要把数据放到目录中
data = pd.read_csv("./data.csv")
# 数据探索
# 因为数据集中列比较多,我们需要把dataframe中的列全部显示出来
##显示所有列
pd.set_option('display.max_columns', None)
#显示所有行
pd.set_option('display.max_rows',None)
#大概浏览下数据
#print(data.columns)
#print(data.head(5))
#print(data.describe())
features_mean= list(data.columns[1:32])
# 数据清洗
# ID列没有用,删除该列
data.drop("id",axis=1,inplace=True)
# 将B良性替换为0,M恶性替换为1
data['diagnosis']=data['diagnosis'].map({'M':1,'B':0})
# 将肿瘤诊断结果可视化
sns.countplot(data['diagnosis'],label="Count")
plt.show()
'''
参数1:method:可选值为{‘pearson’, ‘kendall’, ‘spearman’}
pearson:Pearson相关系数来衡量两个数据集合是否在一条线上面,即针对线性数据的相关系数计算[默认]
kendall:用于反映分类变量相关性的指标,即针对无序序列的相关系数,非正太分布的数据
spearman:非线性的,非正太分析的数据的相关系数
参数2:min_periods:样本最少的数据量
返回值:各类型之间的相关系数DataFrame表格。
'''
# 用热力图呈现features_mean字段之间的相关性
corr = data[features_mean].corr(method='kendall',min_periods=1)
print('=========================================')
sorted_features = corr['diagnosis'].sort_values(ascending=False)
plt.figure(figsize=(32,32))
# annot=True显示每个方格的数据
sns.heatmap(corr, annot=True)
plt.show()
print(sorted_features.index)
chose_features = []
#选择相关性最大的top10数据
for i in sorted_features[1:10].index:
print (i+":"+str(sorted_features[i]))
chose_features.append(i)
print(chose_features)
利用SVM算法进行训练和预测
# -*- coding: utf-8 -*-
# 乳腺癌诊断分类
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn import svm
from sklearn import metrics
from sklearn.preprocessing import StandardScaler
# 加载数据集,你需要把数据放到目录中
data = pd.read_csv("./data.csv")
# 数据清洗
# ID列没有用,删除该列
data.drop("id",axis=1,inplace=True)
# 将B良性替换为0,M恶性替换为1
data['diagnosis']=data['diagnosis'].map({'M':1,'B':0})
#特征选择
all_mean= list(data.columns[0:32])
corr = data[all_mean].corr(method='pearson')
sorted_features = corr['diagnosis'].sort_values(ascending=False)
chose_features = []
#选择相关性最大的top10数据
feture_num = 10
for i in sorted_features[1:feture_num].index:
chose_features.append(i)
print(chose_features)
# 抽取30%的数据作为测试集,其余作为训练集
train, test = train_test_split(data, test_size = 0.3)# in this our main data is splitted into train and test
# 抽取特征选择的数值作为训练和测试数据
train_X = train[chose_features]
train_y=train['diagnosis']
test_X= test[chose_features]
test_y =test['diagnosis']
# 采用Z-Score规范化数据,保证每个特征维度的数据均值为0,方差为1
ss = StandardScaler()
train_X = ss.fit_transform(train_X)
test_X = ss.transform(test_X)
# 创建SVM分类器
#0.9707602339181286
#model = svm.LinearSVC()
#0.9532163742690059
#model = svm.SVC(kernel='rbf', degree=2, gamma=1.7)
#0.8187134502923976
#model = svm.SVC(kernel='poly', degree=2, gamma=1.7)
#0.9532163742690059
model = svm.SVC(kernel='linear',gamma = 1/feture_num)
# 用训练集做训练
model.fit(train_X,train_y)
# 用测试集做预测
prediction=model.predict(test_X)
print('准确率: ', metrics.accuracy_score(prediction,test_y))
参考
https://wenku.baidu.com/view/fa8e7f2eccbff121dd368336.html
https://www.cnblogs.com/sharryling/p/9429589.html
https://www.cnblogs.com/sharryling/p/9429589.html
padas 数据相关性解释:https://blog.csdn.net/walking_visitor/article/details/85128461