本文主要是介绍sklearn中SVM的可视化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 第一部分:如何绘制三维散点图和分类平面
- 第二部分:sklearn中的SVM参数介绍
- 第三部分:源代码and数据
最近遇到一个简单的二分类任务,本来可用一维的线性分类器来解决,但是为了获得更好的泛化性能,我选取了三个特征,变成了一个三维空间的二分类任务。目的就是使两类样本之间的间隔再大一些,为了满足这种需求,自然而然的想到使用SVM作为分类器,并且该任务是线性可分,自然的选用LinearSVM——核函数为线性函数。为了充分理解SVM,我还对SVM的分类平面、支持向量、bad case均进行可视化,通过本文可以了解:
1 .如何用matplotlib绘制三维散点图
2 .sklearn中SVM的核函数
先看图:
其中蓝色的是负样本,红色为正样本,带绿色圈圈的是支持向量,蓝色平面就是分类平面;
再看测试集,其中绿色圈圈,圈出来的是分类错误的样本:
第一部分:如何绘制三维散点图和分类平面
这里采用sklearn里面的SVC作为我的分类器,由于分类任务较为简单,几乎是线性可分,所以采用线性核函数,通过以下语句构建SVM并训练:
cls = svm.SVC(kernel='linear', C=1.5)
cls.fit(x_train, y_train)
其中C为惩罚因子,C越大,模型越不能容忍错误,则会使模型更容易过拟合,反之C越小,模型对错误样本容忍性很强,可能导致模型欠拟合。关于系数C的理论可以参考博客,点这里呀
训练好我们的cls之后就是如何绘制分类平面了,这就得知道我们分类平面的表达式是什么。SVM分类平面通式为Wφ(X)+b = 0 ,当采用线性核函数时,分类平面简化为:WX+b=0 (φ(X)=X),其中W,X为向量,b为标量,想进一步了解核函数作用的朋友可以参考博客,点这里呀
本文用例X是一个三维向量,因此W也应该是一个三维的向量,W和b 分别可从cls的coef_ , intercept_这两个属性中获取,具体如下:
w = cls.coef_
b = cls.intercept_
则绘制分类平面步骤:
ax = plt.subplot(111, projection='3d')x = np.arange(0,1,0.01)y = np.arange(0,1,0.11)x, y = np.meshgrid(x, y)z = (w[0,0]*x + w[0,1]*y + b) / (-w[0,2])surf = ax.plot_surface(x, y, z, rstride=1, cstride=1)
首先,创建一个3d的画布,其次要构建分类平面表达式 z = (w[0,0]x + w[0,1]y + b) / (-w[0,2])
其实是这样演变的:
Wφ(X)+b = 0 $ \Rightarrow $ WX+b=0 $ \Rightarrow $ w1x1+w2x2+w3*x3 + b = 0
有了分类平面,我们还想知道,支持向量是哪些,那么可以通过cls中的support_ 属性获取支持向量的idx,然后依据idx去训练集中找到我们的支持向量
第二部分:sklearn中的SVM参数介绍
SVM中最关键的就是核函数的选择,上一部分中仅仅采用了最简单的线性核函数(其实等于没用核函数,哈哈哈),SVM中常用的核函数有高斯核(rbf,径向基)、多项式核以及sigmoid核。在这里就简单介绍sklearn中SVM的这些核函数具体使用方法。
1.高斯核(rbf) 表达式:$ K(x,z)=exp(−γ||x−z||^{2})$
涉及参数 γ,默认值为 1/特征维度
创建一个高斯核的SVM分类器:
cls = svm.SVC(kenerl = ‘rbf’,gamma = 0.5 )
2.sigmoid核函数表达式: K ( x , z ) = t a n h ( γ x ∙ z + r ) K(x,z)=tanh(γx∙z+r) K(x,z)=tanh(γx∙z+r)
涉及两个参数:γ,r
γ通过gamma设置,默认值为1/特征维度; r通过coef0设置,默认值为0;
创建一个sigmoid核函数的SVM:
cls = svm.SVC(kenerl = ‘sigmoid’,gamma = 0.3,coef0=0)
3.多项式核表达式: K ( x , z ) = ( γ x ∙ z + r ) d K(x,z)=(γx∙z+r)^{d} K(x,z)=(γx∙z+r)d
涉及三个参数:γ,r,d
γ通过gamma设置,默认值为1/特征维度; r通过coef0设置,默认值为0;,d通过degree设置,默认值为3
创建一个二阶多项式核的SVM:
cls = svm.SVC(kenerl = ‘poly’,gamma = 0.3,coef0=0,dgree=2 )
在SVC中还有一个参数可以控制样本的权重,用以解决unbalance问题,class_weight,具体参考官方文档:
http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html
推荐博客:
https://www.cnblogs.com/pinard/p/6117515.html
最后留下一个疑问,倘若我采用非线性核,如高斯核函数,我应该如何绘制分类平面?
我的思路是这样的,分类平面表达式:Wφ(X) + b =0, 当采用非线性核的时候,我们如何能知道这个映射函数φ(·)呢?
第三部分:源代码and数据
代码+数据文件可从:
1.CSDN下载:https://download.csdn.net/download/u011995719/10557270
2.百度云: https://pan.baidu.com/s/1s5Xu_h2nlTSum7jeoKniGQ 密码: gtc8
代码:
# coding: utf-8
import numpy as np
import csv
from sklearn import svm
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D"""
采用 sklearn 中的svm
"""
train_path = './train_set.csv'
test_path = './test_set.csv'def load_data(data_path):X,Y = [],[]csv_reader = csv.reader(open(data_path,'r'))for row in csv_reader:a = row[0][1:-1].split()X.append(np.array(a))Y.append(np.array(row[1]))return X, Ydef find_badcase(X, Y):bad_list = []y = cls.predict(X)for i in range(len(X)):if y[i] != Y[i]:bad_list.append(i)return bad_listif __name__=="__main__":# load datax_train, y_train = load_data(train_path)x_test, y_test = load_data(test_path)# trainingcls = svm.SVC(kernel='linear', C=1.5)cls.fit(x_train, y_train)# accuracyprint('Test score: %.4f' % cls.score(x_test, y_test))print('Train score: %.4f' % cls.score(x_train, y_train))# print bad case idbad_idx = find_badcase(x_test,y_test)n_Support_vector = cls.n_support_ # 支持向量个数sv_idx = cls.support_ # 支持向量索引w = cls.coef_ # 方向向量Wb = cls.intercept_# plot# 绘制分类平面ax = plt.subplot(111, projection='3d')x = np.arange(0,1,0.01)y = np.arange(0,1,0.11)x, y = np.meshgrid(x, y)z = (w[0,0]*x + w[0,1]*y + b) / (-w[0,2])surf = ax.plot_surface(x, y, z, rstride=1, cstride=1)# 绘制三维散点图x_array = np.array(x_train, dtype=float)y_array = np.array(y_train, dtype=int)pos = x_array[np.where(y_array==1)]neg = x_array[np.where(y_array==-1)]ax.scatter(pos[:,0], pos[:,1], pos[:,2], c='r', label='pos')ax.scatter(neg[:,0], neg[:,1], neg[:,2], c='b', label='neg')# 绘制支持向量X = np.array(x_train,dtype=float)for i in range(len(sv_idx)):ax.scatter(X[sv_idx[i],0], X[sv_idx[i],1], X[sv_idx[i],2],s=50,c='',marker='o', edgecolors='g')# 绘制 bad case# x_test = np.array(x_test,dtype=float)# for i in range(len(bad_idx)):# j = bad_idx[i]# ax.scatter(x_test[j,0], x_test[j,1], x_test[j,2],s=60,# c='',marker='o', edgecolors='g')ax.set_zlabel('Z') # 坐标轴ax.set_ylabel('Y')ax.set_xlabel('X')ax.set_zlim([0, 1])plt.legend(loc='upper left')ax.view_init(35,300)plt.show()
再次强调:请问如何绘制非线性核的分类平面呢??
这篇关于sklearn中SVM的可视化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!