首页 >> 大全

支持向量机(SVM)简介+SVM15种场景分类实例

2023-11-14 大全 27 作者:考证青年

文章目录

支持向量机简介

支持向量机(SVM)是和 提出的,是基于优美的数学理论的一种机器学习算法。SVM是针对线性可分情景的广义线性回归模型,对于线性不可分的情况,则通过“核技巧”将低维特征空间的线性不可分样本映射到高维空间中,实现对非线性样本进行线性分析。SVM在小样本的情况下表现也不错,但是其计算代价较高,计算速度慢,且性能逐渐被新晋的树类集成算法和深度算法所领先。SVM目前在小样本、非线性、高维的应用场景中仍有一席之地,且其数学理论完备,非常值得学习。

SVM是一个二分类的分类模型,即寻找一个超平面将样本分为两类,若是多分类问题,则通过one vs rest构建多个二分类SVM形成多分类SVM。支持向量机用作回归(SVR)时,即学习得一个超平面函数f(x),使得f(x)尽量与标签y接近,而与传统回归模型不同的是,当f(x)与y的差值大于设定阈值时才开始计算损失。

SVM的重点在于超平面分割、核技巧映射、凸二次规划问题求解等等,推荐这位大佬的理论推导,非常详细。本人数学知识也是比较有限,就不在理论上班门弄斧了。

SVM15种场景分类实例

参考李飞飞在2005年发表的论文《A Model for Scene 》中的bag of words思想,先通过对每张图进行SIFT+聚类+直方图统计构建场景特征的特征库(词库),即每种场景都可由特征库中的特征表示,然后利用SVM对场景进行分类。

这是要用到的15类场景数据库:

主要流程如下:

数据预处理:

1、 读取15个类别共8970张图片建立总数据集

2、分层随机抽样划分训练集与测试集

Bag Of Word词库建立:

1、 对训练集与测试集中每张图进行SIFT特征提取,出于减少计算量的考虑,只计算通过固定步长进行网格采样获得的点的SIFT特征。

2、指定聚类中心即总单词个数后对训练集中的所有SIFT特征向量进行K-Means聚类

3、对训练集与测试集中每张图对应的SIFT特征向量分别进行直方图统计,对应生成直方图统计数据的训练集与测试集

SVM模型构建:

1、调用库中的SVM模型,在默认参数下换用不同的核函数进行训练,并计算其在测试集上的表现。

向量场分析_向量机的描述_

2、对上一步的模型在训练集上进行5折交叉验证的网格调参以提高模型的性能,并计算调参后的模型在测试集上的表现

库SVM中常用的核函数有三种:

=''用于线性可分情形,参数少,速度快

='rbf'主要用于线性不可分情形,参数多,需要调参

='poly'多项式核函数,可用于非线性分类

各SVM的主要调参对象是惩罚系数c,c越小,则允许更多错分样本。

接下来就上代码啦:

import cv2
import numpy as np
import matplotlib.pyplot as plt
import sklearn
from sklearn.model_selection import train_test_split
from sklearn.cluster import KMeans
from sklearn import preprocessing
from sklearn.svm import LinearSVC
import copy
from sklearn.metrics import roc_auc_score,roc_curve,auc,accuracy_score,classification_report,confusion_matrix,f1_score
import itertools
from sklearn.metrics import confusion_matrix
import pandas as pd
from sklearn.svm import SVC
import glob
from sklearn.model_selection import cross_val_score
from sklearn import metrics
from sklearn.model_selection import GridSearchCV

class_names = [name[11:] for name in glob.glob('D:/Computer_Vision/scene15/*')] #读取目录下所有文件夹名
for i in range(len(class_names)):       #提取15个类别名class_names[i]=class_names[i].split('\\')[1]    

class_names = dict(zip(range(0,len(class_names)), class_names))   #对15种类别进行labelencoding
print (class_names)

def load_dataset(path, num_per_class=-1): #通过遍历读取每个文件夹中的图片,num_per_class设置每个类别中读取的图片数,默认全部读取data = []labels = []for id, class_name in class_names.items():  img_path_class = glob.glob(path + class_name + '/*.jpg')if num_per_class > 0:img_path_class = img_path_class[:num_per_class]labels.extend([id]*len(img_path_class))for filename in img_path_class:data.append(cv2.pyrDown(cv2.imread(filename), 0))return data, labels

X, y = load_dataset('D:/Computer_Vision/scene15/') #调用load_dataset()函数构建数据集及标签集
X_num= len(X)train_data,test_data,train_label,test_label= train_test_split(X,y, test_size=0.2,#随机抽取划分训练集与测试集,stratify的设置保留了原数据集中的样本分布shuffle=True, random_state=111, stratify=y)

def computeSIFT(data):x = []for i in range(0, len(data)):sift = cv2.xfeatures2d.SIFT_create()  #构建SIFT特征提取器img = data[i]step_size = 15  #设置固定步长进行网格采样kp = [cv2.KeyPoint(x, y, step_size) for x in range(0, img.shape[0], step_size) for y in range(0, img.shape[1], step_size)]dense_feat = sift.compute(img, kp)  #计算SIFT特征x.append(dense_feat[1])return x

x_train = computeSIFT(train_data) #对训练集和测试集分别计算SIFT特征
x_test = computeSIFT(test_data)

all_train_desc = []           #通过遍历展开训练集的list
for i in range(len(x_train)):for j in range(x_train[i].shape[0]):all_train_desc.append(x_train[i][j,:])
all_train_desc = np.array(all_train_desc)

def clusterFeatures(all_train_desc, k):#k表示聚类中心数即单词数kmeans = KMeans(n_clusters=k, random_state=0,n_jobs=2).fit(all_train_desc) #创建K-means模型,n_jobs指定并行内核数return kmeans

def formTrainingSetHistogram(x_train, kmeans, k): train_hist = []for i in range(len(x_train)):data = copy.deepcopy(x_train[i])predict = kmeans.predict(data)train_hist.append(np.bincount(predict, minlength=k).reshape(1,-1).ravel()) #对每幅图的SIFT特征进行直方图统计return np.array(train_hist)

k = 50
kmeans = clusterFeatures(all_train_desc, k) #进行kmeans聚类

train_hist = formTrainingSetHistogram(x_train, kmeans, k)  #生成训练集和测试集的直方图集
test_hist = formTrainingSetHistogram(x_test, kmeans, k)

scaler = preprocessing.StandardScaler().fit(train_hist) #进行归一化
train_hist = scaler.transform(train_hist)
test_hist = scaler.transform(test_hist)

svm = sklearn.svm.SVC(kernel='linear',class_weight='balanced',probability=True) #使用线性支持向量机进行训练及预测
svm.fit(train_hist, train_label)
predict=svm.predict(test_hist)
print('准确率是:%s'%(accuracy_score(test_label,predict)))
print(classification_report(test_label,predict)) #输出其在测试集上的表现
print(confusion_matrix(test_label,predict))

###########  对linearsvm分类器进行网格调参  ############
param_test1 = {'C': np.arange(0.01, 1.0001, 0.01)   #设定网格搜寻范围        }
gsearch1 = GridSearchCV(estimator = SVC(kernel='linear',class_weight='balanced',probability=True),param_grid = param_test1, scoring ="accuracy",cv=5,n_jobs=5,verbose=2) #cv指定交叉验证折数
gsearch1.fit(train_hist, train_label) 
print(gsearch1.best_params_)
print(gsearch1.best_score_)
print(gsearch1.best_estimator_)

svm_t = sklearn.svm.SVC(C=0.9400000000000001, break_ties=False, cache_size=200, #调参后线性支持向量机性能检验class_weight='balanced', coef0=0.0, decision_function_shape='ovr', degree=3,gamma='scale', kernel='linear', max_iter=-1, probability=True,random_state=None, shrinking=True, tol=0.001, verbose=False)
svm_t.fit(train_hist, train_label)
predict_t=svm_t.predict(test_hist)
print('准确率是:%s'%(accuracy_score(test_label,predict_t)))
print(classification_report(test_label,predict_t))
print(confusion_matrix(test_label,predict_t))

svm_rbf= sklearn.svm.SVC(kernel='rbf',class_weight='balanced',probability=True) #使用径向基支持向量机进行训练及预测
svm_rbf.fit(train_hist, train_label)
predict_rbf=svm_rbf.predict(pd.DataFrame(test_hist))
print('准确率是:%s'%(accuracy_score(test_label,predict_rbf)))
print(classification_report(test_label,predict_rbf)) #输出其在测试集上的表现
print(confusion_matrix(test_label,predict_rbf))

svm_poly= sklearn.svm.SVC(kernel='poly',class_weight='balanced',probability=True) #使用多项式支持向量机进行训练及预测
svm_poly.fit(train_hist, train_label)
predict_poly=svm_poly.predict(pd.DataFrame(test_hist))
print('准确率是:%s'%(accuracy_score(test_label,predict_poly)))
print(classification_report(test_label,predict_poly)) #输出其在测试集上的表现
print(confusion_matrix(test_label,predict_poly))

def plot_confusion_matrix(cm, classes,normalize=False,title='Confusion matrix',cmap=plt.cm.Blues):if normalize:cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]plt.imshow(cm, interpolation='nearest', cmap=cmap)plt.title(title)plt.colorbar()tick_marks = np.arange(len(classes))plt.xticks(tick_marks, classes, rotation=45)plt.yticks(tick_marks, classes)fmt = '.2f' if normalize else 'd'thresh = cm.max() / 2.for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):plt.text(j, i, format(cm[i, j], fmt),horizontalalignment="center",color="white" if cm[i, j] > thresh else "black")plt.tight_layout()plt.ylabel('True label')plt.xlabel('Predicted label')
cnf_matrix = confusion_matrix(np.array([test_label]).T, predict_poly)  #指定不同predict_poly更换不同混淆矩阵画图数据
np.set_printoptions(precision=2)
plt.figure(figsize=(18, 6))
plot_confusion_matrix(cnf_matrix, classes=class_names,title='15 scene Confusion matrix')
plt.figure(figsize=(18, 6))
plot_confusion_matrix(cnf_matrix, classes=class_names, normalize=True,title='15 scene Confusion matrix')
plt.show()

线性支持向量机默认参数在独立测试集上的各项指标如下:

调参后的线性支持向量机性能有少量上升,在实验中可以观察到不同的核函数带来的差异也是不小的,同时,随着单词数的增加性能不断上升,在该应用场景中多项式支持向量机的准确度最高。

要想进一步提高SVM的准确度,可以从特征工程中进行改进,比如参考这篇论文中的空间金字塔特征构建方法,特征大幅度增加后SVM模型的性能也大幅度提高。

如果换用下其它机器学习模型(比如),就会发现SVM的性能真的有点低了。

Scene

《深度学习原理与实践》 黄理灿

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了