SVM既可以做回归,也可以做分类器。
如何创建一个 SVM 分类器呢?
首先使用 SVC 的构造函数:model = svm.SVC(kernel=‘rbf’, C=1.0, gamma=‘auto’),
这里有三个重要的参数 kernel、C 和 gamma。
kernel 代表核函数的选择,它有四种选择,只不过默认是 rbf,即高斯核函数。
1. linear:线性核函数 。 解决线性问题。
2. poly: 多项式核函数 解决偏线性问题。
3. rbf: 高斯核函数(默认)。 解决非线性问题。
4. sigmoid:双曲正切核函数。 解决偏非线性问题。
选用的数据集:点击下载
威斯康星州乳腺癌(诊断)数据集 ,乳腺癌数据集一共有569个样本,30个特征(10个平均值,10个标准差,10个最值),标签为二分类。其中良性benign为357个,恶性malignant为212个。
可以直接下载数据集,用data = pd.read_csv("./data.csv") 导入,也可以直接从sklearn的数据库下载。
from sklearn.datasets import load_breast_cancer
cancers = load_breast_cancer() #下载乳腺癌数据集
具体见参考博客。
# SVM 分类
# 乳腺癌诊断分类
from sklearn.datasets import load_breast_cancer
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import numpy as np
from sklearn.preprocessing import StandardScaler
import time
cancers = load_breast_cancer() #下载乳腺癌数据集
X = cancers.data #获取特征值
Y = cancers.target #获取标签
原博客在这一步没有进行数据规范化处理。通过对比,规范化处理后的预测结果更好。未规范化处理时,使用多项式poly核函数没有运行出结果(也许是时间太长)。
# 训练集占80%,测试集占20%
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.2)
# 采用Z-Score规范化数据,保证每个特征维度的数据均值为0,方差为1
ss = StandardScaler()
x_train = ss.fit_transform(x_train)
x_test = ss.transform(x_test)
绘制 X[:, 0], X[:, 1] 的点图, 可以看出特征值与目标结果分布具有一定相关性。可选取任意2个特征值绘制点图观察。选择不同的特征值,大体上可以看出,特征值越高,恶性样本数越多。
np.unique(Y) # 查看label都由哪些分类 (unique去除数组中的重复数字,并进行排序之后输出)
plt.scatter(X[:, 0], X[:, 1], c= Y ) #任选某2个特征 与 良性恶性的关系
plt.show() #显示图像
线性核、多项式核、高斯核:gamma代表核函数的系数,默认为样本特征数的倒数,这里使用默认。
# 线性核
model_linear = SVC(C=1.0, kernel='linear')
# 多项式核
#degree表示使用的多项式的阶数
model_poly = SVC(C=1.0, kernel='poly', degree=3)
# 高斯核(RBF核)
#gamma是核函数的一个参数,gamma的值会影响测试精度
#model_rbf = SVC(C=1.0, kernel='rbf', gamma=0.1)
model_rbf = SVC()
sigmoid核函数的gamma系数通过程序测试,得到一个精度最高的取值。gamma_dis=np.logspace(-100,-1,200) 是测试取值的范围, 不同的数据相应对范围进行处理,若数据未进行规范化处理,这个取值范围也是不同的。
# sigmoid核
gammalist=[] #把gammalist定义为一个数组
score_test=[] #把score_test定义为一个数组
gamma_dis=np.logspace(-100,-1,200)
#gamma_dis 从10^(-100)-10^(-1) 平均取200个点
for j in gamma_dis:
model_sigmoid = SVC(kernel='sigmoid', gamma=j,cache_size=5000).fit(x_train, y_train) #cache_size 为内存 MB
gammalist.append(j)
score_test.append(model_sigmoid.score(x_test, y_test))
#找出最优gammalist值
print("分数--------------------",score_test)
print("测试最大分数, gammalist",max(score_test),gamma_dis[score_test.index(max(score_test))])
plt.plot(gammalist,score_test) #横轴为gammalist纵轴为score_test
plt.show()#显示图片
#根据测试出的最佳精度,重新建立训练函数
model_sigmoid = SVC(kernel='sigmoid', gamma=gamma_dis[score_test.index(max(score_test))])
输出结果如下, 说明当gamma取不同值时,预测精度不同,选择预测精度最大的取值,重新建立训练模型。当gamma = 0.010116379797661989,测试精度最高,为0.9649122807017544,测试精度最高时,我们把对应的gamma值叫做最优gamma值。
3.5 输出训练分数、测试分数、运行时间
#输出训练分数以及测试分数
t = time.time()
model_linear.fit(x_train, y_train)
train_score = model_linear.score(x_train, y_train)
test_score = model_linear.score(x_test, y_test)
print('linear: train_score:{0}; test_score:{1}'.format(train_score, test_score))
print('time:' ,time.time() - t)
t = time.time()
model_poly.fit(x_train, y_train)
train_score = model_poly.score(x_train, y_train)
test_score = model_poly.score(x_test, y_test)
print('poly: train_score:{0}; test_score:{1}'.format(train_score, test_score))
print('time:' ,time.time() - t)
t = time.time()
model_rbf.fit(x_train, y_train)
train_score = model_rbf.score(x_train, y_train)
test_score = model_rbf.score(x_test, y_test)
print('rbf: train_score:{0}; test_score:{1}'.format(train_score, test_score))
print('time:' ,time.time() - t)
t = time.time()
model_sigmoid.fit(x_train, y_train)
train_score = model_sigmoid.score(x_train, y_train)
test_score = model_sigmoid.score(x_test, y_test)
print('sigmoid: train_score:{0}; test_score:{1}'.format(train_score,test_score))
print('time:' ,time.time() - t)
输出结果如下:
结论:线性核(linear)核高斯(rbf)测试精度较高。sigmoid核测试精度与gamma值密切相关。多项式核(poly) 精度较低。
若把数据规范化去掉(ss = StandardScaler() 这几行),运行结果:(poly没运行出来,太慢了)
可以看出:1.数据规范化后,所有核函数运算时间都大大减少,尤其是对于线性核和多项式核。
2.规范化后,rbf表现增加明显。 rbf和poly不擅长处理量纲不统一的数据集。
参考文章:
1.机器学习sklearn-支持向量机2_kongqing23的博客-CSDN博客
2.基于SVM的乳腺癌数据集分类_ZHW_AI课题组的博客-CSDN博客_乳腺癌数据集3. https://blog.csdn.net/c1z2w3456789/article/details/105247565
完整的代码
#原文链接:https://blog.csdn.net/m0_37758063/article/details/123647182
# SVM 分类
# 乳腺癌诊断分类
from sklearn.datasets import load_breast_cancer
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import numpy as np
from sklearn.preprocessing import StandardScaler
import time
cancers = load_breast_cancer() #下载乳腺癌数据集
X = cancers.data #获取特征值
Y = cancers.target #获取标签
# 训练集占80%,测试集占20%
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.2)
# 采用Z-Score规范化数据,保证每个特征维度的数据均值为0,方差为1
ss = StandardScaler()
x_train = ss.fit_transform(x_train)
x_test = ss.transform(x_test)
np.unique(Y) # 查看label都由哪些分类 (unique去除数组中的重复数字,并进行排序之后输出)
plt.scatter(X[:, 0], X[:, 1], c= Y ) #任选某2个特征 与 良性恶性的关系
plt.show() #显示图像
#下面是四种核函数的建模训练
# 线性核
model_linear = SVC(C=1.0, kernel='linear')
# 多项式核
#degree表示使用的多项式的阶数
model_poly = SVC(C=1.0, kernel='poly', degree=3)
# 高斯核(RBF核)
#gamma是核函数的一个参数,gamma的值会影响测试精度
model_rbf = SVC(C=1.0, kernel='rbf', gamma=0.1)
# sigmoid核
gammalist=[] #把gammalist定义为一个数组
score_test=[] #把score_test定义为一个数组
#gamma_dis=np.logspace(-100,-5,50)
#gamma_dis从10^(-100)到10^(-5)平均取50个点, 未进行数据Z-Score规范处理时使用。
gamma_dis=np.logspace(-100,-1,200)
for j in gamma_dis:
model_sigmoid = SVC(kernel='sigmoid', gamma=j,cache_size=5000).fit(x_train, y_train) #cache_size 为内存 MB
gammalist.append(j)
score_test.append(model_sigmoid.score(x_test, y_test))
#找出最优gammalist值
print("分数--------------------",score_test)
print("测试最大分数, gammalist",max(score_test),gamma_dis[score_test.index(max(score_test))])
plt.plot(gammalist,score_test) #横轴为gammalist纵轴为score_test
plt.show()#显示图片
#根据测试出的最佳精度,重新建立训练函数
model_sigmoid = SVC(kernel='sigmoid', gamma=gamma_dis[score_test.index(max(score_test))])
#输出训练分数以及测试分数
t = time.time()
model_linear.fit(x_train, y_train)
train_score = model_linear.score(x_train, y_train)
test_score = model_linear.score(x_test, y_test)
print('linear: train_score:{0}; test_score:{1}'.format(train_score, test_score))
print('time:' ,time.time() - t)
t = time.time()
model_poly.fit(x_train, y_train)
train_score = model_poly.score(x_train, y_train)
test_score = model_poly.score(x_test, y_test)
print('poly: train_score:{0}; test_score:{1}'.format(train_score, test_score))
print('time:' ,time.time() - t)
t = time.time()
model_rbf.fit(x_train, y_train)
train_score = model_rbf.score(x_train, y_train)
test_score = model_rbf.score(x_test, y_test)
print('rbf: train_score:{0}; test_score:{1}'.format(train_score, test_score))
print('time:' ,time.time() - t)
t = time.time()
model_sigmoid.fit(x_train, y_train)
train_score = model_sigmoid.score(x_train, y_train)
test_score = model_sigmoid.score(x_test, y_test)
print('sigmoid: train_score:{0}; test_score:{1}'.format(train_score,test_score))
print('time:' ,time.time() - t)
另外一个简短的程序:
参考资料:机器学习sklearn-支持向量机2_kongqing23的博客-CSDN博客目录非线性SVM和核函数如何选择最佳核函数SVC在乳腺癌数据上的表现非线性SVM和核函数非线性SVM的损失函数的初始形态为:同理,非线性SVM的拉格朗日函数和拉格朗日对偶函数也可得:这种变换非常巧妙,但也带有一些实现问题。 首先,我们可能不清楚应该什么样的数据应该使用什么类型的映射函数来确保可以在变换空间中找出线性决策边界。极端情况下,数据可能会被映射到无限维度的空间中,这种高维空间可能不是那么友好,维度越多,推导和计算的难度都会随之暴增。其次,即使已知适当的映射函数https://blog.csdn.net/kongqing23/article/details/122580620
from sklearn.datasets import load_breast_cancer
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from time import time
data = load_breast_cancer()
X = data.data
y = data.target
X = StandardScaler().fit_transform(X)#标准化数据
Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3,random_state=420)
Kernel = ["linear","poly","rbf","sigmoid"] #多项式核函数跑不出来
for kernel in Kernel:
time0=time()
clf=SVC(kernel=kernel,gamma='auto',cache_size=5000).fit(Xtrain,Ytrain) #cache_size 为内存 MB
print("The accuracy under kernel {} is {}".format(kernel, clf.score(Xtest,Ytest)))
time1=time()
time2 = time1-time0
print("{} time: {}".format(kernel,time2))