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

您所在的位置:网站首页 用户场景例子 支持向量机(SVM)简介+SVM15种场景分类实例

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

2024-07-03 09:30| 来源: 网络整理| 查看: 265

文章目录 支持向量机简介SVM15种场景分类实例Reference

支持向量机简介

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

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

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

SVM15种场景分类实例

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

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

在这里插入图片描述

主要流程如下:

数据预处理:

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

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

Bag Of Word词库建立:

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

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

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

SVM模型构建:

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

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

sklearn库SVM中常用的核函数有三种: kernel='linear'用于线性可分情形,参数少,速度快 kernel='rbf'主要用于线性不可分情形,参数多,需要调参 kernel='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模型的性能也大幅度提高。 在这里插入图片描述 如果换用下其它机器学习模型(比如LightGBM),就会发现SVM的性能真的有点低了。

Reference

Spatial Pyramid Matching Scene Recognition

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



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3