上一篇文章咱们介绍了使用逻辑回归来处理分类问题,本文咱们讲一个更强大的分类模型。本文依旧侧重代码实践,你会发现咱们解决问题的手段愈来愈丰富,问题处理起来愈来愈简单。 机器学习
支持向量机(Support Vector Machine, SVM)是最受欢迎的机器学习模型之一。它特别适合处理中小型复杂数据集的分类任务。函数
SMV在众多实例中寻找一个最优的决策边界,这个边界上的实例叫作支持向量,它们“支持”(支撑)分离开超平面,因此它叫支持向量机。 学习
那么咱们如何保证咱们获得的决策边界是最优的呢? lua
如上图,三条黑色直线均可以完美分割数据集。由此可知,咱们仅用单一直线能够获得无数个解。那么,其中怎样的直线是最优的呢? spa
如上图,咱们计算直线到分割实例的距离,使得咱们的直线与数据集的距离尽量的远,那么咱们就能够获得惟一的解。最大化上图虚线之间的距离就是咱们的目标。而上图中重点圈出的实例就叫作支持向量。 3d
这就是支持向量机。code
添加引用:blog
import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt
导入数据集(你们不用在乎这个域名):ci
df = pd.read_csv('https://blog.caiyongji.com/assets/mouse_viral_study.csv') df.head()
Med_1_mL | Med_2_mL | Virus Present | |
---|---|---|---|
0 | 6.50823 | 8.58253 | 0 |
1 | 4.12612 | 3.07346 | 1 |
2 | 6.42787 | 6.36976 | 0 |
3 | 3.67295 | 4.90522 | 1 |
4 | 1.58032 | 2.44056 | 1 |
该数据集模拟了一项医学研究,对感染病毒的小白鼠使用不一样剂量的两种药物,观察两周后小白鼠是否感染病毒。get
sns.scatterplot(x='Med_1_mL',y='Med_2_mL',hue='Virus Present',data=df)
咱们用seaborn绘制两种药物在不一样剂量特征对应感染结果的散点图。
sns.pairplot(df,hue='Virus Present')
咱们经过pairplot方法绘制特征两两之间的对应关系。
咱们能够作出大概的判断,当加大药物剂量可以使小白鼠避免被感染。
#SVC: Supprt Vector Classifier支持向量分类器 from sklearn.svm import SVC #准备数据 y = df['Virus Present'] X = df.drop('Virus Present',axis=1) #定义模型 model = SVC(kernel='linear', C=1000) #训练模型 model.fit(X, y) # 绘制图像 # 定义绘制SVM边界方法 def plot_svm_boundary(model,X,y): X = X.values y = y.values # Scatter Plot plt.scatter(X[:, 0], X[:, 1], c=y, s=30,cmap='coolwarm') # plot the decision function ax = plt.gca() xlim = ax.get_xlim() ylim = ax.get_ylim() # create grid to evaluate model xx = np.linspace(xlim[0], xlim[1], 30) yy = np.linspace(ylim[0], ylim[1], 30) YY, XX = np.meshgrid(yy, xx) xy = np.vstack([XX.ravel(), YY.ravel()]).T Z = model.decision_function(xy).reshape(XX.shape) # plot decision boundary and margins ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--']) # plot support vectors ax.scatter(model.support_vectors_[:, 0], model.support_vectors_[:, 1], s=100, linewidth=1, facecolors='none', edgecolors='k') plt.show() plot_svm_boundary(model,X,y)
咱们导入sklearn
下的SVC
(Supprt Vector Classifier)分类器,它是SVM的一种实现。
SVC方法参数C
表明L2正则化参数,正则化的强度与C
的值城反比,即C值越大正则化强度越弱,其必须严格为正。
model = SVC(kernel='linear', C=0.05) model.fit(X, y) plot_svm_boundary(model,X,y)
咱们减小C的值,能够看到模型拟合数据的程度减弱。
SVC方法的kernel
参数可取值{'linear', 'poly', 'rbf', 'sigmoid', 'precomputed'}
。像前文中所使用的那样,咱们能够使kernel='linear'
进行线性分类。那么若是咱们像进行非线性分类呢?
多项式内核kernel='poly'
的原理简单来讲就是,用单一特征生成多特征来拟合曲线。好比咱们拓展X到y的对应关系以下:
X | X^2 | X^3 | y | |
---|---|---|---|---|
0 | 6.50823 | 6.50823**2 | 6.50823**3 | 0 |
1 | 4.12612 | 4.12612**2 | 4.12612**3 | 1 |
2 | 6.42787 | 6.42787**2 | 6.42787**3 | 0 |
3 | 3.67295 | 3.67295**2 | 3.67295**3 | 1 |
4 | 1.58032 | 1.58032**2 | 1.58032**3 | 1 |
这样咱们就能够用曲线来拟合数据集。
model = SVC(kernel='poly', C=0.05,degree=5) model.fit(X, y) plot_svm_boundary(model,X,y)
咱们使用多项式内核,并经过degree=5
设置多项式的最高次数为5。咱们能够看出分割出现了必定的弧度。
SVC方法默认内核为高斯RBF
,即Radial Basis Function(径向基函数)。这时咱们须要引入gamma
参数来控制钟形函数的形状。增长gamma值会使钟形曲线变得更窄,所以每一个实例影响的范围变小,决策边界更不规则。减少gamma值会使钟形曲线变得更宽,所以每一个实例的影响范围变大,决策边界更平坦。
model = SVC(kernel='rbf', C=1,gamma=0.01) model.fit(X, y) plot_svm_boundary(model,X,y)
from sklearn.model_selection import GridSearchCV svm = SVC() param_grid = {'C':[0.01,0.1,1],'kernel':['rbf','poly','linear','sigmoid'],'gamma':[0.01,0.1,1]} grid = GridSearchCV(svm,param_grid) grid.fit(X,y) print("grid.best_params_ = ",grid.best_params_,", grid.best_score_ =" ,grid.best_score_)
咱们能够经过GridSearchCV
方法来遍历超参数的各类可能性来寻求最优超参数。这是经过算力碾压的方式暴力调参的手段。固然,在分析问题阶段,咱们必须限定了各参数的可选范围才能应用此方法。
由于数据集太简单,咱们在遍历第一种可能性时就已经获得100%的准确率了,输出以下:
grid.best_params_ = {'C': 0.01, 'gamma': 0.01, 'kernel': 'rbf'} , grid.best_score_ = 1.0
当咱们处理线性可分的数据集时,能够使用SVC(kernel='linear')
方法来训练数据,固然咱们也能够使用更快的方法LinearSVC
来训练数据,特别是当训练集特别大或特征很是多的时候。
当咱们处理非线性SVM分类时,能够使用高斯RBF内核,多项式内核,sigmoid内核来进行非线性模型的的拟合。固然咱们也能够经过GridSearchCV寻找最优参数。
往期文章: