机器学习实战项目7

Q1:SVM如何处理多分类的问题
Q2:PCA+SVM 完成人脸识别任务:使用PCA 提取图像的主成分作为输入特征,使用 SVM 模型进行人脸识别,并尝试使用grid_search来优化调整SVM的参数。

answer1
SVM本身是一个二值分类器,SVM算法最初是为二值分类问题设计的,当处理多类问 题时,就需要构造合适的多类分类器。 目前,构造SVM多类分类器的方法主要有两类,直 接法、间接法。
直接法

直接在目标函数上进行修改,将多个分类面的参数求解合并到一个最优化问题中,通过 求解该最优化问题“一次性”实现多类分类。这种方法看似简单,但其计算复杂度比较高, 实现起来比较困难,只适合用于小型问题中;

间接法

主要是通过组合多个二分类器来实现多分类器的构造,常见的方法有one-against-one 和one-against-all两种。 (1)一对多法(one-versus-rest,简称OVR SVMs) 训练时依次把某个类别的样本归为一类,其他剩余的样本归为另一类,这样k个类别的 样本就构造出了k个SVM。分类时将未知样本分类为具有最大分类函数值的那类。 假如我有四类要划分(也就是4个Label),他们是A、B、C、D。 于是我在抽取训练集的时候,分别抽取
(1)A所对应的向量作为正集,B,C,D所对应的向量作为负集;
(2)B所对应的向量作为正集,A,C,D所对应的向量作为负集;
(3)C所对应的向量作为正集,A,B,D所对应的向量作为负集;
(4)D所对应的向量作为正集,A,B,C所对应的向量作为负集;
使用这四个训练集分别进行训练,然后得到四个训练结果文件。 在测试的时候,把对应的测试向量分别利用这四个训练结果文件进行测试。 最后每个测试都有一个结果f1(x),f2(x),f3(x),f4(x)。 于是最终的结果便是这四个值中最大的一个作为分类结果

优点:
训练k个分类器,个数较少,其分类速度相对较快。
缺点:
①每个分类器的训练都是将全部的样本作为训练样本,这样在求解二次规划问题时,训练 速度会随着训练样本的数量的增加而急剧减慢;
②同时由于负类样本的数据要远远大于正类样本的数据,从而出现了样本不对称的情况, 且这种情况随着训练数据的增加而趋向严重。解决不对称的问题可以引入不同的惩罚因子, 对样本点来说较少的正类采用较大的惩罚因子C;
③还有就是当有新的类别加进来时,需要对所有的模型进行重新训练。

(2)一对一法(one-versus-one,简称OVO SVMs或者pairwise)

其做法是在任意两类样本之间设计一个SVM,因此k个类别的样本就需要设计k(k-1)/2 个SVM
当对一个未知样本进行分类时,最后得票最多的类别即为该未知样本的类别。
Libsvm中的多类分类就是根据这个方法实现的。 假设有四类A,B,C,D四类。在训练的时候我选择A,B; A,C; A,D; B,C; B,D;C,D(每一类都出现同样的次数)——所对应的向 量作为训练集,然后得到六个训练结果,在测试的时候,把对应的向量分别对六个结果进行 测试,然后采取投票形式,最后得到一组结果。
投票是这样的: A=B=C=D=0;
(A,B)-classifier 如果是A win,则A=A+1;otherwise,B=B+1;
(A,C)-classifier 如果是A win,则A=A+1;otherwise, C=C+1;
...
(C,D)-classifier 如果是C win,则C=C+1;otherwise,D=D+1; The decision is the Max(A,B,C,D),即选取A,B,C,D值最高的作为其分类

优点:不需要重新训练所有的SVM,只需要重新训练和增加语音样本相关的分类器。在训练 单个模型时,相对速度较快。
缺点:所需构造和测试的二值分类器的数量关于k成二次函数增长,总训练时间和测试时间 相对较慢。

answer2:

"""
As an example of support vector machines in action,
let's take a look at the facial recognition problem. We will use the Labeled Faces in the Wild dataset
which consists of several thousand collated photos of various public figures.
A fetcher for the dataset is built into Scikit-Learn
"""



from sklearn.datasets import fetch_lfw_people
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA#基于奇异值分解的PCA模型算法
from sklearn.pipeline import make_pipeline
from sklearn.svm import SVC
from sklearn.cross_validation import train_test_split
from sklearn.grid_search import GridSearchCV
import time
from sklearn.metrics import classification_report#分类详细情况的dataframe ,包括F1,召回率,精准率,支持度
from sklearn.metrics import confusion_matrix
import seaborn as sns
faces=fetch_lfw_people(min_faces_per_person=60)##单人的脸的个数最小为60,本身是图片构成的数据集合
# print (faces.target_names)
# print (faces.images.shape)
# #print (faces)#json 格式的字典
#
# fig,ax=plt.subplots(3,5)#fig 指的是3行5列的大画框,ax 返回的是三行五列的数组,每一个都是一个小的图框
# for i,axi in enumerate(ax.flat):##ax.flat 将列表铺开
#     axi.imshow(faces.images[i],cmap='bone')#每一个小画框开始显示图像
#     axi.set(xticks=[],yticks=[],xlabel=faces.target_names[faces.target[i]])##target 的数字对应target_names的索引
# #plt.show()

"""
每个图片【62*47】,也就是特征接近于3000,因此
需要PCA 来将特征进行降维,实际上接近的像素点位置的特征实际上是一致的
因此PCA 采用协方差=0来找到相互独立的特征
"""

pca=PCA(n_components=150,whiten=True,svd_solver='randomized',random_state=42)#whiten 可以提高精准度m默认为True
svc=SVC(kernel='rbf')#多喝函数,可以为sigmoid,linear,poly
model=make_pipeline(pca,svc)#利用管道pipline 构建复合模型

"""
划分数据集
"""
x_train,x_test,y_train,y_test=train_test_split(faces.data,faces.target,test_size=0.2,random_state=42)

"""
优化模型
最后,我们可以使用网格搜索交叉验证来探索参数的组合。在这里,我们将调整C(控制边缘硬度)和γ(控制径向基函数核的大小),并确定最佳模型
"""
param_grid = {'svc__C': [1, 5, 10, 50], 'svc__gamma': [0.0001, 0.0005, 0.001, 0.005]}
grid=GridSearchCV(model,param_grid)
grid.fit(x_train,y_train)
# print(grid.best_params_)

"""
进行测试集合的预测
"""
model=grid.best_estimator_##调整为最优化的训练器
y_pred=model.predict(x_test)
# print (y_pred)对应的target 即维target_name 的对应的人名索引值


"""
最后进行可视化的相关
预测检验
学习这种验证方法
"""

#
# fig,ax=plt.subplots(5,8)
# #
# # for i, axi in enumerate(ax.flat):
# #     axi.imshow(x_test[i].reshape(62,47),cmap='bone')#将数据重塑成62*47,也就是形成图像
# #     axi.set(xticks=[],yticks=[])
# #     axi.set_ylabel(faces.target_names[y_pred[i]],color='black' if y_pred[i]==y_test[i] else 'red')
# #
# # fig.suptitle('Predicted Names; Incorrect Labels in Red', size=14)
# # # plt.show()


"""
接下来就要为该模型进行一个打分
"""
# print (classification_report(y_test,y_pred,target_names=faces.target_names))#参数为真实值,预测值,以及target_name 要求列表形式


"""
最后用一种直观的热力图
来展现,该方法非常值得学习
"""
mat=confusion_matrix(y_test,y_pred)
# print (mat) 首先你会发现他是一个方阵,每一列表示每一类的预测值,而每一行表示每一类的真实值
sns.heatmap(mat,annot=True,square=True,cbar=True,fmt='d',xticklabels=faces.target_names,yticklabels=faces.target_names)
"""
annotate 为True 表示数值会显示在方格里面,square=True 表示为正方形,两个参数都默认为False
fmt字符串的形式传入,当annot 为True的时候,因为本例子为数字,因此传入digit
"""
plt.xlabel('predict label')
plt.ylabel('true label')
plt.show()

最后放一张confusion_matrix的图像


confusion_matrix

之前说的ML of 100 的代码也已经实操完毕,该交作业啦!本周末附上,坚持学习,坚持coding

你可能感兴趣的:(机器学习实战项目7)