SVM用于分类和回归,目的是找到一个超平面,使得离超平面最近的点都有很大的距离,max(最小距离)的意思
SVM是一个二分类方法,但是它可以在有核的情况下分类非线性的数据
大概步骤是这样的:先将数据升维,以便进行线性的分割;接下来,对分割后的数据计算支持向量,进而得到分割线。
其数学原理之精妙,让人叹为观止。
具体原理、推导,可见Jack-Cui的文章:
下面结合示例代码,具体分析一下流程。
1、生成并可视化数据。
import numpy as np
import matplotlib.pyplot as plt
import seaborn;
from sklearn.linear_model import LinearRegression
#from scipy import stats
#import pylab as pl
#seaborn.set()
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=50, centers=2,
random_state=0, cluster_std=0.60)
xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')
# 其实随意给定3组参数,就可以画出3条不同的直线,但它们都可以把图上的2类样本点分隔开
for m, b, d in [(1, 0.65, 0.33), (0.5, 1.6, 0.55), (-0.2, 2.9, 0.2)]:
yfit = m * xfit + b
plt.plot(xfit, yfit, '-k')
plt.fill_between(xfit, yfit - d, yfit + d, edgecolor='none', color='#AAAAAA', alpha=0.4)#alpha for blending
plt.xlim(-1, 3.5)
plt.show()
make_blobs函数是为聚类产生数据集
产生一个数据集和相应的标签
n_samples:表示数据样本点个数,默认值100
n_features:表示数据的维度,默认值是2
centers:产生数据的中心点,默认值3
cluster_std:数据集的标准差,浮点数或者浮点数序列,默认值1.0
center_box:中心确定之后的数据边界,默认值(-10.0, 10.0)
shuffle :洗乱,默认值是True
random_state:官网解释是随机生成器的种子***
作者:你说你要一场
链接:https://www.jianshu.com/p/069d8841bd8e
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
plt.scatter具体参数可以参考https://blog.csdn.net/qi_1221/article/details/73903131
plt.plot参考https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html
2 SVC分类
from sklearn.datasets import make_blobs
from sklearn.svm import SVC
import numpy as np
import matplotlib.pyplot as plt
X, y = make_blobs(n_samples=50, centers=2,random_state=0, cluster_std=0.60)
clf = SVC(kernel='linear')
clf.fit(X, y)
def plot_svc_decision_function(clf, ax=None):
"""Plot the decision function for a 2D SVC"""
if ax is None:
ax = plt.gca()
x = np.linspace(plt.xlim()[0], plt.xlim()[1], 30)
y = np.linspace(plt.ylim()[0], plt.ylim()[1], 30)
Y, X = np.meshgrid(y, x)
P = np.zeros_like(X)
for i, xi in enumerate(x):
for j, yj in enumerate(y):
P[i, j] = clf.decision_function([[xi, yj]])
# plot the margins
CS = ax.contour(X, Y, P, colors='k',
levels=[-1, 0, 1], alpha=0.5,
linestyles=['--', '-', '--'])
ax.clabel(CS, inline=1, fontsize=10)
plt.scatter(X[:, 0], X[:, 1], c=y, s=10, cmap='spring')
plot_svc_decision_function(clf)
plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],s=200, c='r', facecolors='none');
plt.show()
clf = SVC(kernel='linear')
clf.fit(X, y)
这是重点
clf.support_vectors_[:, 0], clf.support_vectors_[:, 1]这两是支持向量
根据官方code.py,核必须是{'linear', 'poly', 'rbf', 'sigmoid', 'precomputed'}之一,或是自定义的。
核函数的选择:
1、特征数量大,和样本数量差不多:此时选LR或者线性核SVM
2、特征数量少,样本数量正常:高斯核
3、特征数量小,样本数量大:手动添加特征变为第一种情况
结果如下:
下面是一个SVM人脸识别的案例
from time import time
import logging
import matplotlib.pyplot as plt
import cv2
#从sklearn导入相关模型和svm算法
from numpy import *
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.decomposition import PCA
from sklearn.svm import SVC
# PICTURE_PATH为图像存放目录位置,注意读者需要修改为自己电脑存放图像的目录
PICTURE_PATH = "./att_faces"
def get_Image(): #读取图像程序
for i in range(1,41): #循环读取所以图片文件
for j in range(1,11):
path = PICTURE_PATH + "\\s" + str(i) + "\\"+ str(j) + ".pgm" #路径
img = cv2.imread(path) #使用imread函数读取图像
#生活中大多数看到的彩色图像都是RGB类型,但是图像处理时,需要用到灰度图、二值图、HSV、HSI等颜色制式,opencv的cvtColor()函数来实现这些功能
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
h,w = img_gray.shape #图像的尺寸信息赋值给变量h和w
img_col = img_gray.reshape(h*w) #使用reshape函数对图像进行处理
all_data_set.append(img_col) #将图像添加到数据集all_data_set中
all_data_label.append(i) #确定图像对应的标签值
return h,w
all_data_set = [] #变量all_data_set初始化为空
all_data_label = [] # 变量all_data_label初始化为空
h,w = get_Image() #调用定义的get_Image()函数获取图像
X =array(all_data_set) #使用all_data_set作为参数定义数组赋值给变量X
y = array(all_data_label) #使用all_data_ label作为参数定义数组赋值给变量y
n_samples,n_features = X.shape #X数组中的图像信息赋值给变量n_samples,n_features
print(X.shape)
n_classes = len(unique(y)) #得到变量y的长度赋值给n_classes
#unique:对于一维数组或者列表,unique函数去除其中重复的元素,并按元素由大到小返回一个新的无元素重复的元组或者列表
target_names = [] #变量target_names初始化为空
for i in range(1,41): #循环读取
names = "person" + str(i) #定义变量names,并赋值
target_names.append(names) #变量target_names不断添加信息的names
#打印输出:数据集总规模,n_samples和n_features
print("Total dataset size:")
print("n_samples: %d" % n_samples)
print("n_features: %d" % n_features)
#程序划分,一部分用于训练集,另一部分用于测试集,这里使用3/4数据用于训练,1/4数据用于测试
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, random_state=42)
n_components = 20
#打印输出信息
print("Extracting the top %d eigenfaces from %d faces"
% (n_components, X_train.shape[0]))
t0 = time()
pca = PCA(n_components=n_components, svd_solver='randomized', #选择一种svd方式
whiten=True).fit(X_train) #whiten是一种数据预处理方式,会损失一些数据信息,但可获得更好的预测结果
print("done in %0.3fs" % (time() - t0))
eigenfaces = pca.components_.reshape((n_components, h, w)) #特征脸
print("Projecting the input data on the eigenfaces orthonormal basis")
t0 = time()
#这是转化后,生成【分类数量,特征数量20】的矩阵
X_train_pca = pca.transform(X_train) #得到训练集投影系数
X_test_pca = pca.transform(X_test) #得到测试集投影系数
print("done in %0.3fs" % (time() - t0)) #打印出来时间
接下来,就是 输出特征脸eigenface
#定义plot_gallery函数
#函数参数为:images, titles, h, w, n_row, n_col
def plot_gallery(images, titles, h, w, n_row=3, n_col=4):
"""Helper function to plot a gallery of portraits"""
plt.figure(figsize=(1.8 * n_col, 2.4 * n_row)) #创建自定义图像
plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35) #对子图之间的间距进行设置
for i in range(n_row * n_col-4): #循环处理多个图像
plt.subplot(n_row, n_col, i + 1) #绘制子图
plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray) #绘制图像
plt.title(titles[i], size=12) #设置图像的标题
plt.xticks(()) #设置x轴文本
plt.yticks(()) #设置y轴文本
eigenface_titles = ["eigenface %d" % i for i in range(eigenfaces.shape[0])] #定义特征脸标题
plot_gallery(eigenfaces, eigenface_titles, h, w) #调用plot_gallery函数绘制特征脸
plt.show() #显示图像
加上分类器SVM之后,整体如下:
from time import time
import logging
import matplotlib.pyplot as plt
import cv2
from numpy import *
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.decomposition import PCA
from sklearn.svm import SVC
PICTURE_PATH = "att_faces"
def get_Image():
for i in range(1,41):
for j in range(1,11):
path = PICTURE_PATH + "\\s" + str(i) + "\\"+ str(j) + ".pgm"
img = cv2.imread(path)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
h,w = img_gray.shape
img_col = img_gray.reshape(h*w)
all_data_set.append(img_col)
all_data_label.append(i)
return h,w
all_data_set = []
all_data_label = []
h,w = get_Image()
X = array(all_data_set)
y = array(all_data_label)
n_samples,n_features = X.shape
n_classes = len(unique(y))
target_names = []
for i in range(1,41):
names = "person" + str(i)
target_names.append(names)
print("Total dataset size:")
print("n_samples: %d" % n_samples)
print("n_features: %d" % n_features)
print("n_classes: %d" % n_classes)
# split into a training and testing set
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, random_state=42)
n_components = 10
print("Extracting the top %d eigenfaces from %d faces"
% (n_components, X_train.shape[0]))
t0 = time()
pca = PCA(n_components=n_components, svd_solver='randomized',
whiten=True).fit(X_train)
print("done in %0.3fs" % (time() - t0))
eigenfaces = pca.components_.reshape((n_components, h, w))
print("Projecting the input data on the eigenfaces orthonormal basis")
t0 = time()
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test)
print("done in %0.3fs" % (time() - t0))
print("Fitting the classifier to the training set")
t0 = time()
param_grid = {'C': [1e3, 5e3, 1e4, 5e4, 1e5],
'gamma': [0.0001, 0.0005, 0.001, 0.005, 0.01, 0.1], }
clf = GridSearchCV(SVC(kernel='rbf', class_weight='balanced'), param_grid)#网格化搜索以上grid里面的数据
clf = clf.fit(X_train_pca, y_train)
print("done in %0.3fs" % (time() - t0))
print("Best estimator found by grid search:")
print(clf.best_estimator_)
print("Predicting people's names on the test set")
t0 = time()
y_pred = clf.predict(X_test_pca)
print("done in %0.3fs" % (time() - t0))
print(classification_report(y_test, y_pred, labels=[i for i in range(40)],target_names=target_names))#labels很重要
print(confusion_matrix(y_test, y_pred, labels=range(n_classes)))
def plot_gallery(images, titles, h, w, n_row=3, n_col=4):
"""Helper function to plot a gallery of portraits"""
plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))
plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35)
for i in range(n_row * n_col-4):
plt.subplot(n_row, n_col, i + 1)
plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray)
plt.title(titles[i], size=12)
plt.xticks(())
plt.yticks(())
# plot the result of the prediction on a portion of the test set
def title(y_pred, y_test, target_names, i):
pred_name = target_names[y_pred[i]-1]
true_name = target_names[y_test[i]-1]
return 'predicted: %s\ntrue: %s' % (pred_name, true_name)
prediction_titles = [title(y_pred, y_test, target_names, i)
for i in range(y_pred.shape[0])]
plot_gallery(X_test, prediction_titles, h, w)
# plot the gallery of the most significative eigenfaces
eigenface_titles = ["eigenface %d" % i for i in range(eigenfaces.shape[0])]
plot_gallery(eigenfaces, eigenface_titles, h, w)
plt.show()
结果如下
SVM的保存与读取
import pickle
model.fit(train_X, train_y)
s=pickle.dumps(model)
f=open('svm.model', "wb+")
f.write(s)
f.close()
print ("Done\n")
模型保存
这里的model已经是生成好的模型了,注意一定要用"wb+",否则会报错
f2=open('svm.model','rb')
s2=f2.read()
model1=pickle.loads(s2)
expected = test_y
predicted = model1.predict(test_X)
模型调用,注意读取方式'rb',否则会报错
————————————————
版权声明:本文为CSDN博主「jessica218」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42595525/article/details/82979076
SVM 多分类问题
clf = svm.SVC(decision_function_shape='ovo')
要改的话 clf.decision_function_shape = "ovr"