机器学习算法——SVM支持向量机(基于sklearn代码实现)

SVM在解决分类问题具有良好的效果,出名的软件包有libsvm(支持多种核函数),liblinear。

此外python机器学习库scikit-learn也有svm相关算法sklearn.svm.SVC和sklearn.svm.LinearSVC 分别由libsvm和liblinear发展而来。

使用SVM的一般步骤为:

  1. 读取数据,将原始数据转化为SVM算法软件或包所能识别的数据格式;
  2. 将数据标准化;(防止样本中不同特征数值大小相差较大影响分类器性能)
  3. 选择核函数,在不清楚何种核函数最佳时,推荐尝试RBF
  4. 利用交叉验证网格搜索寻找最优参数(C, γ);(交叉验证防止过拟合,再利用网格搜索在指定范围内寻找最优参数)
  5. 使用最优参数来训练模型;
  6. 测试得到的分类器。

0、SVC参数含义

sklearn.svm.SVC(C=1.0, kernel='rbf', degree=3, gamma='auto', coef0=0.0, shrinking=True,probability=False,tol=0.001,cache_size=200,class_weight=None,verbose=False,max_iter=-1,decision_function_shape=None,random_state=None)
"""
sklearn.svm.SVC(C=1.0, kernel='rbf', degree=3, gamma='auto', coef0=0.0, shrinking=True,probability=False,tol=0.001,cache_size=200,class_weight=None,verbose=False,max_iter=-1,decision_function_shape=None,random_state=None)

参数:
l  C:C-SVC的惩罚参数,默认值是1.0。C越大,相当于惩罚松弛变量,希望松弛变量接近0,即对误分类的惩罚增大,趋向于对训练集全分对的情况,这样对训练集测试时准确率很高,但泛化能力弱。C值小,对误分类的惩罚减小,允许容错,将他们当成噪声点,泛化能力较强。

l  kernel :核函数,默认是rbf,可以是‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’ 

    0 – 线性:u'v

    1 – 多项式:(gamma*u'*v + coef0)^degree

    2 – RBF函数:exp(-gamma|u-v|^2)

    3 –sigmoid:tanh(gamma*u'*v + coef0)

l  degree :多项式poly函数的维度,默认是3,选择其他核函数时会被忽略。

l  gamma : ‘rbf’,‘poly’ 和‘sigmoid’的核函数参数。默认是’auto’,则会选择1/n_features

l  coef0 :核函数的常数项。对于‘poly’和 ‘sigmoid’有用。

l  probability :是否采用概率估计.默认为False

l  shrinking :是否采用shrinking heuristic方法,默认为true

l  tol :停止训练的误差值大小,默认为1e-3

l  cache_size :核函数cache缓存大小,默认为200

l  class_weight :类别的权重,字典形式传递。设置第几类的参数C为weight*C(C-SVC中的C)

l  verbose :允许冗余输出

l  max_iter :最大迭代次数。-1为无限制。

l  decision_function_shape :‘ovo’, ‘ovr’ or None, default=None3,ovo指一对一,ovr指一对剩余的

l  random_state :数据乱序时的种子值,int类型

因此,主要调节的参数有:C、kernel、degree、gamma、coef0。
"""

1、利用LinearSVC分类鸢尾花

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

iris = datasets.load_iris()
# 为简单起见,选取前两个特征作为分类的输入特征,以便在二维空间画出决策曲线
X = iris.data[:, :2]
y = iris.target

# 设置分类器为LinearSVC,penalty指惩罚项,C为松弛变量,利用fit函数拟合输入数据,得到所需的分类器
svc = svm.LinearSVC(penalty='l2', C=0.5).fit(X, y)

# 绘图参数
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
h = (x_max / x_min) / 100
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                     np.arange(y_min, y_max, h))
plt.subplot(1, 1, 1)

# 利用已有分类器进行预测
Z = svc.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
# 绘制等高线并填充轮廓
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
# 限制x的取值范围,便于显示
plt.xlim(xx.min(), xx.max())
plt.title('LinearSVC test result')
plt.show()

运行结果如下所示:
在这里插入图片描述

将下面这段代码更改

svc = svm.LinearSVC(penalty='l2', C=0.5).fit(X, y)

使用SVC实现线性分类,运行结果如下所示。

svc = svm.SVC(kernel='linear', C=1,gamma='auto').fit(X, y)

在这里插入图片描述

2、利用RBF作为核函数

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

iris = datasets.load_iris()
# 为简单起见,选取前两个特征作为分类的输入特征,
# 以便在二维空间画出决策曲线
X = iris.data[:, :2]
y = iris.target

# 设置分类器SVC,核函数为rbf,gamma设置为自动调整
svc = svm.SVC(kernel="rbf", C=1, gamma="auto").fit(X, y)

# 绘图参数
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
h = (x_max / x_min) / 100
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                     np.arange(y_min, y_max, h))
plt.subplot(1, 1, 1)

# 利用已有分类器进行预测
Z = svc.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
# 绘制等高线并填充轮廓
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
# 限制x的取值范围,便于显示
plt.xlim(xx.min(), xx.max())
plt.title('LinearSVC test result')
plt.show()

运行结果如下所示
在这里插入图片描述

修改gamma的值,代码如下,观察gamma值对拟合结果的影响

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

iris = datasets.load_iris()
# 为简单起见,选取前两个特征作为分类的输入特征,以便在二维空间画出决策曲线
X = iris.data[:, :2]
y = iris.target

# 设置分类器SVC,核函数为rbf
svc = svm.SVC(kernel='rbf', C=1,gamma=10).fit(X, y)

# 绘图
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
h = (x_max / x_min)/100
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
 np.arange(y_min, y_max, h))
plt.subplot(1, 1, 1)
Z = svc.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('SVC with rbf kernel and gamma = 10')
plt.show()

运行结果如下所示
在这里插入图片描述

svc = svm.SVC(kernel='rbf', C=1,gamma=100).fit(X, y)
# create a mesh to plot in
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
h = (x_max / x_min)/100
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
 np.arange(y_min, y_max, h))
plt.subplot(1, 1, 1)
Z = svc.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('SVC with rbf kernel and gamma = 100')
plt.show()

在这里插入图片描述

同样的,修改C的值,代码如下,观察C值对拟合结果的影响

svc = svm.SVC(kernel='rbf', C=10,gamma='auto').fit(X, y)

x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
h = (x_max / x_min)/100
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
 np.arange(y_min, y_max, h))
plt.subplot(1, 1, 1)
Z = svc.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('SVC with rbf kernel and C = 10')
plt.show()

在这里插入图片描述

svc = svm.SVC(kernel='rbf', C=100,gamma='auto').fit(X, y)

x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
h = (x_max / x_min)/100
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
 np.arange(y_min, y_max, h))
plt.subplot(1, 1, 1)
Z = svc.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('SVC with rbf kernel and C = 100')
plt.show()

在这里插入图片描述

3、使用poly核函数

svc = svm.SVC(kernel='poly', C=1,gamma='auto').fit(X, y)

在这里插入图片描述

4、利用管道pipeline来进行多项式核函数的SVM算法

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.svm import LinearSVC
from sklearn.pipeline import Pipeline
from matplotlib.colors import ListedColormap

# 利用sklearn自带的数据生成器,添加部分噪声,生成两个半圆的叠加,共1000个数据
x, y = datasets.make_moons(n_samples=1000, noise=0.2, random_state=2020)

plt.figure()
plt.scatter(x[y == 0, 0], x[y == 0, 1], color="b")
plt.scatter(x[y == 1, 0], x[y == 1, 1], color="r")
plt.show()


# 绘制边界曲线
def plot_decision_boundary(model, axis):
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1] - axis[0]) * 100)).reshape(-1, 1),
        np.linspace(axis[2], axis[3], int((axis[3] - axis[2]) * 100)).reshape(-1, 1)
    )
    x_new = np.c_[x0.ravel(), x1.ravel()]
    y_pre = model.predict(x_new)
    zz = y_pre.reshape(x0.shape)

    # 设置颜色
    cus = ListedColormap(["#BA55D3", "#FF69B4", "#FFE4C4"])
    plt.contourf(x0, x1, zz, cmap=cus)


# 利用管线
def polyniomailSVC(degree, C=1.0):
    return Pipeline([("poly", PolynomialFeatures(degree=degree)),
                     ("std_scaler", StandardScaler()),
                     ("LinearSVC", LinearSVC(C=C))
                     ])


# 绘图
p = polyniomailSVC(degree=3)
p.fit(x, y)
plot_decision_boundary(p, axis=([-1.5, 2.5, -1.2, 1.5]))
plt.scatter(x[y == 0, 0], x[y == 0, 1], color="b")
plt.scatter(x[y == 1, 0], x[y == 1, 1], color="r")
plt.show()

运行结果如下所示:
在这里插入图片描述
在这里插入图片描述

利用多项式核函数,直接利用sklearn中自带的多项式核函数SVM算法,主要的参数kernel=“poly”

from sklearn.svm import SVC
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from matplotlib.colors import ListedColormap

# 利用sklearn自带的数据生成器,生成两个半圆的叠加,共1000个数据
x, y = datasets.make_moons(n_samples=1000, noise=0.2, random_state=2020)


# 绘制边界曲线
def plot_decision_boundary(model, axis):
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1] - axis[0]) * 100)).reshape(-1, 1),
        np.linspace(axis[2], axis[3], int((axis[3] - axis[2]) * 100)).reshape(-1, 1)
    )
    x_new = np.c_[x0.ravel(), x1.ravel()]
    y_pre = model.predict(x_new)
    zz = y_pre.reshape(x0.shape)

    # 设置颜色
    cus = ListedColormap(["#BA55D3", "#FF69B4", "#FFE4C4"])
    plt.contourf(x0, x1, zz, cmap=cus)


def polynomialkernelSVC(degree, C=0.1):
    return Pipeline(
        [
            ("std_canler", StandardScaler()),
            ("kernelsvc", SVC(kernel="poly", degree=degree, C=C))
        ]
    )


p1 = polynomialkernelSVC(degree=3)
p1.fit(x, y)
plot_decision_boundary(p1, axis=([-1.5, 2.5, -1.2, 1.5]))
plt.scatter(x[y == 0, 0], x[y == 0, 1], color="r")
plt.scatter(x[y == 1, 0], x[y == 1, 1], color="g")
plt.show()

运行结果如下:
在这里插入图片描述

使用sklearn中的高斯核函数RBF核

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from matplotlib.colors import ListedColormap
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split

x, y = datasets.make_moons(n_samples=1000, noise=0.25, random_state=2020)  # 生成1000个数据样本
plt.figure()
plt.scatter(x[y == 0, 0], x[y == 0, 1], color="r")
plt.scatter(x[y == 1, 0], x[y == 1, 1], color="g")
plt.show()

x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=2020)


# 绘制边界曲线
def plot_decision_boundary(model, axis):
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1] - axis[0]) * 100)).reshape(-1, 1),
        np.linspace(axis[2], axis[3], int((axis[3] - axis[2]) * 100)).reshape(-1, 1)
    )
    x_new = np.c_[x0.ravel(), x1.ravel()]
    y_pre = model.predict(x_new)
    zz = y_pre.reshape(x0.shape)

    # 设置颜色
    cus = ListedColormap(["#BA55D3", "#FF69B4", "#FFE4C4"])
    plt.contourf(x0, x1, zz, cmap=cus)


def RBFkernelSVC(gamma):
    return Pipeline([
        ("std", StandardScaler()),
        ("svc", SVC(kernel="rbf", gamma=gamma))
    ])


sv = RBFkernelSVC(gamma=1)
sv.fit(x_train, y_train)
plot_decision_boundary(sv, axis=([-1.8, 2.5, -1.4, 1.8]))
plt.scatter(x[y == 0, 0], x[y == 0, 1], color="r")
plt.scatter(x[y == 1, 0], x[y == 1, 1], color="g")
plt.show()
# 打印出分数
print(sv.score(x_test, y_test))

d = datasets.load_iris()
x = d.data
y = d.target

x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=2020)
sv = RBFkernelSVC(gamma=10)
sv.fit(x_train, y_train)
# 打印出分数
print(sv.score(x_test, y_test))

在这里插入图片描述
在这里插入图片描述

5、核函数的选择

如果训练样本的特征数量过于庞大,也许就不需要通过RBF等非线性核函数将其映射到更高的维度空间上,直接利用非线性核函数也并不能提高分类器的性能。
此时,利用linear核函数就可以获得足够好的结果,此外,线性核函数只需寻找一个合适参数C。而利用RBF核函数取得与线性核函数一样的效果的话,需要寻找两个合适参数(C, γ)。因此,对于核函数的选择,一般遵循以下的经验,主要有以下几种情况:

1、若样本数量远小于特征数量,则利用linear核效果会高于RBF核。
2、若样本数量和特征数量一样大,则线性核合适,且速度快,同样的,liblinear也适合。
3、若样本数量远大于特征数量,则利用 非线性核RBF等较佳。

搜索最优参数时,可以利用网格搜索法寻找。然而,网格大小如果设置范围大且步长密集的话难免耗时,但是不这样的话又可能找到的参数不是很好,针对这解决方法是,先在大范围,大步长的粗糙网格内寻找参数。在找到的参数左右在设置精细步长找寻最优参数。这样既可以避免一开始就使用大范围,小步长而导致分类器进行过于多的计算而导致计算时间的增加。

  • 4
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
情感识别系统是一种可以自动判断和分类文本或语音中所表达的情感的算法支持向量机(SVM)是一种常用的机器学习方法,在情感识别中也广泛应用。 SVM基于对数据进行特征映射,将数据从低维空间转化为高维空间,以便更好地进行分类。在情感识别中,我们可以将文本或语音数据转化为特征向量表示,然后使用SVM进行分类。通常选择常用的特征表示方法如词袋模型或者TF-IDF进行特征提取。 下面给出一个用Matlab实现情感识别系统的示例代码: ```matlab % 导入情感数据集 data = importdata('emotion_data.txt'); % 划分训练集和测试集 trainRatio = 0.8; trainSize = int32(length(data) * trainRatio); trainData = data(1:trainSize,:); testData = data(trainSize+1:end,:); % 提取特征和标签 trainFeatures = trainData(:,1:end-1); trainLabels = trainData(:,end); testFeatures = testData(:,1:end-1); testLabels = testData(:,end); % 创建SVM模型 svmModel = fitcsvm(trainFeatures, trainLabels); % 在测试集上进行预测 predictedLabels = predict(svmModel, testFeatures); % 计算准确率 accuracy = sum(predictedLabels == testLabels) / length(testLabels); disp(['准确率:' num2str(accuracy*100) '%']); ``` 以上代码中,我们首先导入情感数据集,然后将数据划分为训练集和测试集。接着我们提取特征和标签,即将文本数据转化为特征向量表示。 然后我们使用fitcsvm函数来创建SVM模型,并通过predict函数在测试集上进行预测。最后我们计算准确率来评估模型的性能。 这是一个简单的情感识别系统的实现示例,实际情感识别会有更多的特征提取方法和模型调参等工作。希望这个回答能对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值