• 支持向量机学习笔记(2)参数比较与人脸识别项目


    上期回顾:

    支持向量机(Support Vector Machine, SVM)是一类按监督学习(supervised learning)方式对数据进行的广义线性分类器(generalized linear classifier),其是对学习样本求解的最大边距超平面(maximum-margin hyperplane) 。

    SVM使用铰链损失函数(hinge loss)计算经验风险(empirical risk)并在求解系统中加入了正则化项以优化结构风险(structural risk),是一个具有稀疏性和稳健性的分类器   。SVM可以通过核方法(kernel method)进行非线性分类,是常见的核学习(kernel learning)方法之一  

    (1)线性SVM分类

            通过建立一个超平面,优化模型使最靠近超平面的点的间隔最大,称之为大间隔分类。由于SVM对特征的缩放特别敏感,对函数间隔影响较大,所以要对特征先进行标准化,用于特征的缩放。

    如果将实例严格的分类,让所有的实例都处于正确的一方,称之为硬间隔分类;反之,称之为软间隔分类。

    (2)非线性SVM分类

            处理方法1:使用PolynomialFeatures让高维的特征变成新的特征

            处理方法2:使用支持向量机中的核技巧

    本期讨论SVM中参数问题与人脸识别的实战训练

    参数比较:这里使用的是sklearn.datasets包中的make_blobs来构建数据, 先模拟量三条线,这里通过对x变量进行构建,然后通过zip方法进行函数的模拟, 然后使用画出图像的最大间隔线,这里使用的是svm自带的decision_function函数进行画图,然后进行训练模型,这里使用的核函数是linear,通过改变数据的数量进行绘图,发现只要最大间隔上面的点不改变,画出的线不改变。

    1. ##导入数据包
    2. %matplotlib inline
    3. import numpy as np
    4. import matplotlib.pyplot as plt
    5. from scipy import stats
    6. import seaborn as sns;sns.set()
    7. from sklearn.datasets import make_blobs
    8. X,y=make_blobs(n_samples=50,centers=2,random_state=0,cluster_std=0.6)##cluster_std用于描述数据离散程度
    9. plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap='autumn')##参数解释c:色彩序列,s:数组标量,cmap:图谱
    10. xfit =np.linspace(-1,3.5)
    11. plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap='autumn')
    12. for m ,b in[(1,0.65),(0.5,1.6),(-0.2,2.9)]:
    13. plt.plot(xfit,m*xfit+b,'-k')
    14. plt.xlim(-1,3.5)
    15. def plot_svc_decision_function(model,ax=None,plot_support=True):
    16. if ax is None:
    17. ax=plt.gca()##用于确定坐标轴
    18. xlim=ax.get_xlim()
    19. ylim =ax.get_ylim()
    20. x = np.linspace(xlim[0],xlim[1],30)
    21. y = np.linspace(ylim[0],ylim[1],30)
    22. Y,X = np.meshgrid(y,x)##用x,y两个轴上的点画网格
    23. xy =np.vstack([X.ravel(),Y.ravel()]).T
    24. P =model.decision_function(xy).reshape(X.shape)
    25. ax.contour(X,Y,P,color='k',
    26. levels=[-1,0,1],alpha=0.5,
    27. linestyle=['--','-','--'])
    28. if plot_support:
    29. ax.scatter(model.support_vectors_[:,0],model.support_vectors_[:,1],
    30. s=300,linewidth=1,facecolors='none')
    31. ax.set_xlim(xlim)
    32. ax.set_ylim(ylim)
    33. plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap='autumn')
    34. plot_svc_decision_function(model)
    35. from sklearn.svm import SVC
    36. model =SVC(kernel='linear')
    37. model.fit(X,y)
    38. model.support_vectors_##这个是最大间隔上的点
    39. def plot_svm(N=10, ax=None):
    40. X, y = make_blobs(n_samples=200, centers=2,
    41. random_state=0, cluster_std=0.60)
    42. X = X[:N]
    43. y = y[:N]
    44. model = SVC(kernel='linear', C=1E10)
    45. model.fit(X, y)
    46. ax = ax or plt.gca()
    47. ax.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
    48. ax.set_xlim(-1, 4)
    49. ax.set_ylim(-1, 6)
    50. plot_svc_decision_function(model, ax)
    51. # 分别对不同的数据点进行绘制
    52. fig, ax = plt.subplots(1, 2, figsize=(16, 6))
    53. fig.subplots_adjust(left=0.0625, right=0.95, wspace=0.1)
    54. for axi, N in zip(ax, [60, 120]):
    55. plot_svm(N, axi)
    56. axi.set_title('N = {0}'.format(N))

     

    • 这条线就是我们希望得到的决策边界啦

    • 观察发现有3个点做了特殊的标记,它们恰好都是边界上的点

    • 它们就是我们的support vectors(支持向量)

    • 在Scikit-Learn中, 它们存储在这个位置 support_vectors_(一个属性)

    • 左边是60个点的结果,右边的是120个点的结果
    • 观察发现,只要支持向量没变,其他的数据怎么加无所谓!

     改变成为非线性模型继续测试,并测试核函数变化的情况,切换成为高纬度进行测试, 调节C(惩罚项)参数,当C趋近于无穷大时:意味着分类严格不能有错误,当C趋近于很小的时:意味着可以有更大的错误容忍,调节gamma参数:gamma越大,模型复杂度越高。

    1. from mpl_toolkits import mplot3d
    2. r = np.exp(-(X ** 2).sum(1))
    3. # 可以想象一下在三维中把环形数据集进行上下拉伸
    4. def plot_3D(elev=30, azim=30, X=X, y=y):
    5. ax = plt.subplot(projection='3d')
    6. ax.scatter3D(X[:, 0], X[:, 1], r, c=y, s=50, cmap='autumn')
    7. ax.view_init(elev=elev, azim=azim)
    8. ax.set_xlabel('x')
    9. ax.set_ylabel('y')
    10. ax.set_zlabel('r')
    11. plot_3D(elev=45, azim=45, X=X, y=y)
    12. clf = SVC(kernel='rbf')
    13. clf.fit(X, y)
    14. plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
    15. plot_svc_decision_function(clf)
    16. plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],
    17. s=300, lw=1, facecolors='none');
    18. X, y = make_blobs(n_samples=100, centers=2,
    19. random_state=0, cluster_std=0.8)
    20. plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
    21. X, y = make_blobs(n_samples=100, centers=2,
    22. random_state=0, cluster_std=0.8)
    23. fig, ax = plt.subplots(1, 2, figsize=(16, 6))
    24. fig.subplots_adjust(left=0.0625, right=0.95, wspace=0.1)
    25. # 选择两个C参数来进行对别实验,分别为10和0.1
    26. for axi, C in zip(ax, [10.0, 0.1]):
    27. model = SVC(kernel='linear', C=C).fit(X, y)
    28. axi.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
    29. plot_svc_decision_function(model, axi)
    30. axi.scatter(model.support_vectors_[:, 0],
    31. model.support_vectors_[:, 1],
    32. s=300, lw=1, facecolors='none');
    33. axi.set_title('C = {0:.1f}'.format(C), size=14)
    34. X, y = make_blobs(n_samples=100, centers=2,
    35. random_state=0, cluster_std=1.1)
    36. fig, ax = plt.subplots(1, 2, figsize=(16, 6))
    37. fig.subplots_adjust(left=0.0625, right=0.95, wspace=0.1)
    38. # 选择不同的gamma值来观察建模效果
    39. for axi, gamma in zip(ax, [10.0, 0.1]):
    40. model = SVC(kernel='rbf', gamma=gamma).fit(X, y)
    41. axi.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
    42. plot_svc_decision_function(model, axi)
    43. axi.scatter(model.support_vectors_[:, 0],
    44. model.support_vectors_[:, 1],
    45. s=300, lw=1, facecolors='none');
    46. axi.set_title('gamma = {0:.1f}'.format(gamma), size=14)

    上述代码分别通过设置松弛因子控制参数C的值分别为10,0.1,gamma值分别为10,0.1,可以通过以下的图片进行判断,对于参数C来说,C=10时相当于对分类的要求比较严格,在分类对的前提下,再去寻找最宽的决策边界,虽然分类完全正确,但是决策边界太窄,最大间隔太小,而C=0.1时,虽然有点错误,但是决策边界大。

    而当gamma=10时,训练后的模型十分复杂,虽然分类全部正确,但是决策边界来看可以得出过拟合的几率比较大,但是gamma=0.1时,模型比较简单,虽然出现部分错误分类,但是决策边界比较稳定

     

     

    人脸识别:这里读取了sklearn.datasets.fetch_lfw_people的数据,为了使每个人的样本不至于过少,这里选取了每个人可以有60个样本。

    1. ##进行数据读取
    2. from sklearn.datasets import fetch_lfw_people
    3. faces = fetch_lfw_people(min_faces_per_person=60)
    4. print(faces.target_names)
    5. print(faces.images.shape)
    6. ##数据预处理
    7. from sklearn.model_selection import train_test_split
    8. X_train,X_test,Y_train,Y_test = train_test_split(faces.data,faces.target,random_state=40)

    模型建立:这里使用的是流水线方法进行两个函数的合并,使用了Pipeline与make_pipeline,然后用GridSearchCV进行参数的调优。由于这里使用的是图片数据,图片由像素点构成,会导致特征过多,所以使用PCA方法进行降维,然后使用GridSearchCV进行降维维度的调参。

    1. ##模型建立
    2. from sklearn.pipeline import Pipeline
    3. from sklearn.svm import SVC
    4. from sklearn.decomposition import PCA
    5. pca_svc = Pipeline(steps=[('pca',PCA( whiten=True, random_state=42)),('svc',SVC(class_weight='balanced'))])
    6. from sklearn.model_selection import GridSearchCV
    7. param_grid = [{'pca__n_components':[100,150,200,500],'svc__C': [1,5,10],'svc__gamma':[0.0001,0.0005,0.001],
    8. 'svc__kernel':['linear','poly','rbf','sigmoid']}]
    9. grid_search =GridSearchCV(pca_svc,param_grid)
    10. grid_search.fit(X_train,Y_train)
    11. grid_search.best_params_
    1. from sklearn.pipeline import make_pipeline
    2. pca = PCA( whiten=True, random_state=42)
    3. svc = SVC(class_weight='balanced')
    4. #先降维然后再SVM
    5. model = make_pipeline(pca, svc)
    6. grid_search =GridSearchCV(model,param_grid)
    7. grid_search.fit(X_train,Y_train)
    8. grid_search.best_params_

    注:此处在Pipeline中一定要对两个方法都有参数的调优,否则会报错。

    对训练集进行预测并构造混淆矩阵:

    1. model=grid_search.best_estimator_
    2. y_pred = model.predict(X_test)
    3. from sklearn.metrics import classification_report
    4. print(classification_report(Y_test,y_pred,target_names=faces.target_names))
    5. from sklearn.metrics import confusion_matrix
    6. import seaborn as sns
    7. import matplotlib.pyplot as plt
    8. matrix = confusion_matrix(Y_test,y_pred)
    9. sns.heatmap(matrix.T,square=True,annot=True,fmt='d',cbar=False,
    10. xticklabels=faces.target_names,
    11. yticklabels=faces.target_names)
    12. plt.xlabel('true label')
    13. plt.ylabel('predicted label')

    • 精度(precision) = 正确预测的个数(TP)/被预测正确的个数(TP+FP)
    • 召回率(recall)=正确预测的个数(TP)/预测个数(TP+FN)
    • F1 = 2精度召回率/(精度+召回率)

      从中我们可以看出,在中间的对角线中代表数据预测的正确,也可以从上面Classification_report中得出,对George W Bush 的召回率最高也就是正确率最高,在混淆矩阵中也是他的正确数量最多。

  • 相关阅读:
    找不到x3daudio1_7.dll怎么解决?x3daudio1_7.dll的5个修复方法
    基于微信共享充电桩小程序系统设计与实现 开题报告
    【附源码】计算机毕业设计JAVA学校食堂订餐管理
    DataOps: A New Discipline 数据治理的下一步
    无限上下文,多级内存管理!突破ChatGPT等大语言模型上下文限制
    c# - - - winform 右下角气球提示通知
    【MySQL】3.2-MySQL中的比较运算符
    webpack一些常用的Loader和Plugin
    怎样用图片去搜索商品呢?
    VirtualApp系统升级适配方法论(1)——一切从源码来
  • 原文地址:https://blog.csdn.net/lovexyyforever/article/details/125886559