SVM(支持向量机)

分类

监督学习、分类问题

算法原理

当样本线性可分的时候,寻找能切分样本并且最大间距的一个直线、平面或者超平面。
当样本非线性可分的时候,通过核函数映射到高维空间中,让样本线性可分。

代码实现

样本线性可分的情况:

from sklearn import svm
x=[[2,0],[1,1],[2,3]]#样本特征
y=[0,0,1]#样本标签
clf = svm.SVC(kernel = "linear")#线性核函数,其实就是没有使用核函数。
clf.fit(x,y)#训练模型
print(str(type(clf)))
print(clf.support_vectors_)#所有的支持向量
print(clf.support_)#支持向量对应的下表
print(clf.n_support_)#两侧向量个数
print(clf.predict([[6,6]]))#预测

更多点的线性可分的情况

import numpy as np
import pylab as pl
from sklearn import svm
#让每次执行的时候,随机数不变
np.random.seed(0)
x=np.r_[np.random.randn(20,2)-[2,2],np.random.randn(20,2)+[2,2]]
y=[0]*20+[1]*20
clf=svm.SVC(kernel="linear")
#训练SVM模型
clf.fit(x,y)

#库函数拟合出来的函数是W0*X0+W1*X1+b=0,一下步骤是为了构造y=ax+b方程,方便画图
w=clf.coef_[0]
print("w:"+str(w))
a=-w[0]/w[1]
#等距构造x点
xx=np.linspace(-5, 5)
#求出y值
yy=a*xx-(clf.intercept_[0])/w[1]

#b及时支持向量的坐标
b=clf.support_vectors_[0]
print(b)
yy_down=a*xx+(b[1]-a*b[0])
b=clf.support_vectors_[-1]
print(b)
yy_up=a*xx+(b[1]-a*b[0])

#画图
pl.plot(xx,yy,"k-")
pl.plot(xx,yy_down,"k--")
pl.plot(xx,yy_up,"k--")

#画圆圈
pl.scatter(clf.support_vectors_[:,0], clf.support_vectors_[:,1] , s=80 , facecolors="none")
pl.scatter(x[:,0],x[:,1],c=y,cmap=pl.cm.Paired)
pl.axis("tight")
pl.show()

非线性可分的而情况

# coding=gbk
from __future__ import print_function

from time import time
import logging
import matplotlib.pyplot as plt

from sklearn.cross_validation import train_test_split
from sklearn.datasets import fetch_lfw_people
from sklearn.grid_search import GridSearchCV
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.decomposition import RandomizedPCA
from sklearn.svm import SVC
from bokeh.util.logconfig import level
from pandas.tests.groupby.test_function import test_size
from blaze.expr.expressions import shape
from scipy.cluster.vq import whiten
from dask.delayed import right
from docutils.nodes import image

logging.basicConfig(level=logging.INFO,format='%(asctime)s %(message)s')
# min_faces_per_person=70:提取的数据集将仅保留至少具有min_faces_per_person不同图片的人的照片
# resize=0.4 ::(float,可选,默认为0.5)用于调整每张脸部图片大小的比例。
lfw_people = fetch_lfw_people(min_faces_per_person=70, resize=0.4)
#通过images.shape返回数据集有多少:实例个数 n_samples=1288 高 h=50 宽 w=37
n_samples,h,w=lfw_people.images.shape

# 特征向量矩阵:每一行是一个实例 每一列是一个特征值  (1288*1850)
X = lfw_people.data
#X的列数即特征向量的维度
n_features = X.shape[1]
print("shape:"+str(X.shape))
#提取每个实例对应每个人脸,目标分类标记,不同的人的身份
y = lfw_people.target
target_names = lfw_people.target_names
n_classes = target_names.shape[0]#多少行,shape就是多少行,多少个人,多少类

print("target_names.shape:"+str(target_names.shape))
print("target_names:"+str(target_names))
print("target_names.type:"+str(type(target_names)))
print("Total dataset size:")
print("n_sample:%d"%n_samples)
print("n_features:%d"%n_features)
print("n_classes:%d"%n_classes)

#下面开始拆分数据,分成训练集和测试集,有个现成的函数,通过调用train_test_split;来分成两部分
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.25)

#数据降维,因为特征值的维度还是比较高
n_components = 150

print("Extracting the top %d eigengaces from %d faces"%(n_components,X_train.shape[0]))
t0=time()
#经典算法,高维降低为低维的
pca = RandomizedPCA(n_components=n_components,whiten=True).fit(X_train)
print("pca.type:"+str(type(pca)))
print("done in %0.3fs"%(time()-t0))
#对于人脸的一张照片上提取的特征值名为eigenfaces
eigenfaces = pca.components_.reshape((n_components,h,w))

print("Projecting the input data on thee eigenfacees orthonormal basis")
t0 = time()
X_train_pca = pca.transform(X_train)#特征量中训练集所有的特征向量通过pca转换成更低维的矩阵
X_test_pca = pca.transform(X_test)
print("done in %0.3fs" %(time()-t0))

print("Fitting the classifier to the training set")

t0=time()
#C:对于错误部分进行处罚
#gamma:多少的feature启动
#param_grid把参数设置成了不同的值,C:权重;gamma:多少的特征点将被使用,因为我们不知道多少特征点最好,选择了不同的组合
param_grid = {'C':[1e3,5e3,1e4,5e4,1e5],'gamma':[0.0001,0.0005,0.001,0.005,0.01,0.1],}
#把所有我们所列参数的组合都放在SVC里面进行计算,最后看出哪一组函数的表现度最好
clf = GridSearchCV(SVC(kernel='rbf',class_weight='balanced'),param_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, target_names=target_names))
print(confusion_matrix(y_test, y_pred, labels=range(n_classes)))
#把数据可视化的可以看到,把需要打印的图打印出来
def plot_gallery(images,titles,h,w,n_row=3,n_col=4):
    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):
        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()
#把预测的函数归类标签和实际函数归类标签,比如布什       
def title(y_pred,y_test,target_names,i):
    pred_name = target_names[y_pred[i]].rsplit(' ',1)[-1]
    true_name = target_names[y_test[i]].rsplit(' ',1)[-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)
eigenface_titles=["eigenface %d" % i for i in range(eigenfaces.shape[0])]
#提取过特征向量之后的脸是什么样子
plot_gallery(eigenfaces, eigenface_titles, h, w)
plt.show()

你可能感兴趣的:(machine,learning)