python机器学习---监督学习---支持向量机SVM(多用于分类)

目录

1、支持向量机的基本原理

2、支持向量机的核函数和参数选择

3、支持向量机实例---对波士顿房价进行回归分析


备注:本文主要来自于对《深入浅出python机器学习》书籍的学习总结笔记,感兴趣的同学可以购买本书学习

1、支持向量机的基本原理

       由于现实生活中,很多事情不是线性可分的(即画一条直线就能分类的),而SVM就是专治线性不可分,把分类问题转化为平面分类问题。不过我们说分类,不仅仅是将不同的类别样本分隔开,还要以比较大的置信度来分隔这些样本,这样才能使绝大部分样本被分开。比如,我们想通过一个平面将两个类别的样本分开,如果这些样本是线性可分(或者近视线性可分),那么这样的平面有很多,但是如果我们加上要以最大的置信度来将这些样本分开,那么这样的平面只有一条。这里要理解两点:

(1)几何间隔 :几何间隔的概念,简单理解就是样本点到分隔平面的距离
(2)间隔最大化 :想要间隔最大化,我们必须找到距离分隔平面最近的点,并且使得距离平面最近的点尽可能的距离平面最远,这样,每一个样本就都能够以比较大的置信度被分隔开算法的分类预测能力也就越好。显然,SVM算法的关键所在,就是找到使得间隔最大化的分隔超平面

2、支持向量机的核函数和参数选择

SVM关键是选取核函数的类型,主要有线性内核,多项式内核(Polynomial kernel)和径向基内核(Radial basis function kernel,RBF),下面的代码式不同核函数的SVM对比:

import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import load_wine

def make_meshgrid(x, y, h=.02):
    x_min, x_max = x.min() - 1, x.max() + 1
    y_min, y_max = y.min() - 1, y.max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))
    return xx, yy


def plot_contours(ax, clf, xx, yy, **params):
    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    out = ax.contourf(xx, yy, Z, **params)
    return out


# 使用酒的数据集
wine = load_wine()
# 选取数据集的前两个特征
X = wine.data[:, :2]
y = wine.target


C = 1.0  # SVM 正则化参数
models = (svm.SVC(kernel='linear', C=C),
          svm.LinearSVC(C=C),
          svm.SVC(kernel='rbf', gamma=0.1, C=C),
          svm.SVC(kernel='rbf', gamma=1, C=C),
          svm.SVC(kernel='rbf', gamma=10, C=C),
          svm.SVC(kernel='poly', degree=3, C=C))
models = (clf.fit(X, y) for clf in models)


titles = ('SVC with linear kernel',
          'LinearSVC (linear kernel)',
          'SVC with RBF kernel & gamma=0.1',
          'SVC with RBF kernel & gamma=1',
          'SVC with RBF kernel & gamma=10',
          'SVC with polynomial (degree 3) kernel')


fig, sub = plt.subplots(3, 2)
plt.subplots_adjust(wspace=0.6, hspace=0.6)

X0, X1 = X[:, 0], X[:, 1]
xx, yy = make_meshgrid(X0, X1)

for clf, title, ax in zip(models, titles, sub.flatten()):
    plot_contours(ax, clf, xx, yy,
                  cmap=plt.cm.plasma, alpha=0.8)
    ax.scatter(X0, X1, c=y, cmap=plt.cm.plasma, s=20, edgecolors='k')
    ax.set_xlim(xx.min(), xx.max())
    ax.set_ylim(yy.min(), yy.max())
    ax.set_xlabel('Feature 0')
    ax.set_ylabel('Feature 1')
    ax.set_xticks(())
    ax.set_yticks(())
    ax.set_title(title)

plt.show()

python机器学习---监督学习---支持向量机SVM(多用于分类)_第1张图片

从图象结果可以看出,线性SVM的分界是直线,而Poly和RBF的分界是曲线的,它们分别通过参数degree和gamma调节。

对于RBF核函数,gamma值从0.1增加到10,RBF的直径越大,这样更多的点会被模型圈进边界中。

3、支持向量机实例---对波士顿房价进行回归分析

##1-数据准备
#导入sklearn.datasets的load_boston数据集
from sklearn.datasets import load_boston
#导入的数据集是一种Bunch对象,它包括键keys和数值values,它有点类似字典,可用类似字段的方法查看信息
#获取字典的信息-获取字典的键dict.keys(),获取字典的值-dict.values(),获取字典的键值-dict.items(),获取特定键的值dict['键名']
data = load_boston()
#获取字典的键dict.keys()
print(data.keys())    #该数据集跟之前的酒数据集一样,包含数据,目标分类、分类名,详细信息,数据的特征名,文件位置
print('\n')
#获取特定键的值dict['键名']
print('data的特征:',data['feature_names'])
print('\n')
print('data的分类:',data['target'])

dict_keys(['data', 'target', 'feature_names', 'DESCR', 'filename'])
data的特征: ['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
 'B' 'LSTAT']

##2-数据建模
#2.1将数据拆分为训练集和测试集---要用train_test_split模块中的train_test_split()函数,随机将75%数据化道训练集,25%数据到测试集
#导入数据集拆分工具
from sklearn.model_selection import train_test_split
#将数据集的数值和分类目标赋值给x,y
x,y=data['data'],data['target']
#拆分数据集---x,y都要拆分,rain_test_split(x,y,random_state=0),random_state=0使得每次生成的伪随机数不同
x_train,x_test,y_train,y_test=train_test_split(x,y,random_state=0)
#查看拆分后的数据集大小情况
print('x_train_shape:{}'.format(x_train.shape))
print('x_test_shape:{}'.format(x_test.shape))
print('y_train_shape:{}'.format(y_train.shape))
print('y_test_shape:{}'.format(y_test.shape))
print('\n')

##2.2 模型训练/测试
#用for函数一次性完成多个模型训练/测试--算法.fit(x_train,y_train)/算法.score(x_test,y_test)
for kernel in ['linear','rbf']:
    #使用算法
    svr = SVR(kernel=kernel)
     #算法.fit(x,y)对训练数据进行拟合
    svr.fit(x_train, y_train) 
    #打印拟合过程参数
    print(svr.fit(x_train, y_train) )
    #打印训练集得分
    print(kernel,'核函数的模型训练集得分:{:.3f}'.format(
        svr.score(x_train, y_train)))
    #打印测试集得分
    print(kernel,'核函数的模型测试集得分:{:.3f}'.format(
        svr.score(x_test, y_test)))
x_train_shape:(379, 13)x_test_shape:(127, 13)
y_train_shape:(379,)
y_test_shape:(127,)


SVR(C=1.0, cache_size=200, coef0=0.0, degree=3, epsilon=0.1,
  gamma='auto_deprecated', kernel='linear', max_iter=-1, shrinking=True,
  tol=0.001, verbose=False)
linear 核函数的模型训练集得分:0.744
linear 核函数的模型测试集得分:0.564
SVR(C=1.0, cache_size=200, coef0=0.0, degree=3, epsilon=0.1,
  gamma='auto_deprecated', kernel='rbf', max_iter=-1, shrinking=True,
  tol=0.001, verbose=False)
rbf 核函数的模型训练集得分:0.153
rbf 核函数的模型测试集得分:0.005

我们发现线性核函数出现了过拟合的情况,RBF核函数的预测情况十分糟糕。这是什么原因呢,会不会是数据集的各个特征之间的量级差比较大呢?因为SVM算法对数据预处理的要求比较高,那我们先用图形来查看一下各个特征的数量级情况:

##数据预处理
#查看一下各个特征的数量级情况(最大最小值)
plt.plot(x.min(axis=0),'v',label='min')
plt.plot(x.max(axis=0),'^',label='max')
plt.yscale('log')
plt.legend(loc='best')
plt.xlabel('features')
plt.ylabel('feature magnitude')
plt.show()

python机器学习---监督学习---支持向量机SVM(多用于分类)_第2张图片

##数据预处理
#数据标准化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(x_train)
X_train_scaled = scaler.transform(x_train)
X_test_scaled = scaler.transform(x_test)
plt.plot(X_train_scaled.min(axis=0),'v',label='train set min')
plt.plot(X_train_scaled.max(axis=0),'^',label='train set max')
plt.plot(X_test_scaled.min(axis=0),'v',label='test set min')
plt.plot(X_test_scaled.max(axis=0),'^',label='test set max')
plt.yscale('log')
plt.legend(loc='best')
plt.xlabel('scaled features')
plt.ylabel('scaled feature magnitude')
plt.show()

python机器学习---监督学习---支持向量机SVM(多用于分类)_第3张图片

#使用预处理后的数据再来训练一次模型
#用for函数一次性完成多个模型训练/测试--算法.fit(x_train,y_train)/算法.score(x_test,y_test)
for kernel in ['linear','rbf']:
    #使用算法
    svr = SVR(kernel=kernel)
     #算法.fit(x,y)对训练数据进行拟合
    svr.fit(X_train_scaled, y_train) 
    #打印拟合过程参数
    print(svr.fit(X_train_scaled, y_train) )
    #打印训练集得分
    print(kernel,'核函数的模型训练集得分:{:.3f}'.format(
        svr.score(X_train_scaled, y_train)))
    #打印测试集得分
    print(kernel,'核函数的模型测试集得分:{:.3f}'.format(
        svr.score(X_test_scaled, y_test)))
SVR(C=1.0, cache_size=200, coef0=0.0, degree=3, epsilon=0.1,
  gamma='auto_deprecated', kernel='linear', max_iter=-1, shrinking=True,
  tol=0.001, verbose=False)
linear 核函数的模型训练集得分:0.745
linear 核函数的模型测试集得分:0.569
SVR(C=1.0, cache_size=200, coef0=0.0, degree=3, epsilon=0.1,
  gamma='auto_deprecated', kernel='rbf', max_iter=-1, shrinking=True,
  tol=0.001, verbose=False)
rbf 核函数的模型训练集得分:0.720
rbf 核函数的模型测试集得分:0.508

发现RBF核函数模型性能得到了提升,我们进一步调整SVR的参数,看会不会它的表现进一步提升呢

#调参
svr = SVR(C=100, gamma=0.1)
svr.fit(X_train_scaled, y_train)
print('调节参数后的模型在训练集得分:{:.3f}'.format(
        svr.score(X_train_scaled, y_train)))
print('调节参数后的模型在测试集得分:{:.3f}'.format(
        svr.score(X_test_scaled, y_test)))
调节参数后的模型在训练集得分:0.985
调节参数后的模型在测试集得分:0.771

确实,调参之后模型性能有了进一步提升

你可能感兴趣的:(python机器学习)