PCA的一个重要应用是特征提取。特征提取背后的思想是,可以找到一种数据表示,比给定的原始表示更适合于分析。特征提取很有用,它的一个很好的应用实例就是图像。图像由像素组成,通常存储于红绿蓝强度。图像中的对象通常由上千个像素组成,它们只有放在一起才有意义。
下面给出PCA对图像做特征提取的一个简单应用,即处理Wild数据集Labeled Faces(标记人脸)中的人脸图像。这一数据集包含很多互联网上下载下来的名人脸部图像,首先看一下这些图像:
people=fetch_lfw_people(data_home = "C:\\Users\\86185\\Downloads\\",min_faces_per_person=20,resize=.7)
image_shape=people.images[0].shape
fix,axes=plt.subplots(2,5,figsize=(15,8),
subplot_kw={'xticks':(),'yticks':()})
for target,image,ax in zip(people.target,people.images,axes.ravel()):
ax.imshow(image)
ax.set_title(people.target_names[target])
plt.show()
一共有3023张图像,每张的像素为87*65,分别属于62个不同的人:
print('人脸图片数据集shape:{}'.format(people.images.shape))
print('个数:{}'.format(len(people.target_names)))
但这个数据集有些偏斜,其中包含部分人的大量图像:
counts=np.bincount(people.target)
for i,(count,name) in enumerate(zip(counts,people.target_names)):
print('{0:25}{1:3}'.format(name,count),end=' ')
if (i+3)%3==0:
print()
为了降低数据偏斜,我们对没人选取最多50张图像:
mask=np.zeros(people.target.shape,dtype=np.bool_)
for target in np.unique(people.target):
mask[np.where(people.target==target)[0][:50]]=1
X_people=people.data[mask]
y_people=people.target[mask]
X_people=X_people/255
人脸识别的一个常见任务就是看某个前所未见的人脸是否属于数据库中的某个已知人物。这在照片收集、社交媒体和安全应用中都有应用。解决这个问题的方法之一就是构建一个分类器,每个人就是一个单独类别。但人脸数据库中通常有许多不同的人,而同一个人的图像很少。这使得大多数分类器的训练都很困难。另外,通常要能够轻松添加新的任务,而不需要重新训练一个模型。
一种简单的解决方法就是使用单一最近邻分类器,寻找与你要分类的人脸最为相似的人脸。这个分类器原则上可以处理每个类别只有一个训练样例的情况。
下面以KNeighborsClassifier举例:
from sklearn.neighbors import KNeighborsClassifier
X_train,X_test,y_train,y_test=train_test_split(X_people,y_people,stratify=y_people,random_state=0)
knn=KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train,y_train)
print('精度:{:.2f}'.format(knn.score(X_test,y_test)))
可以看到得到的精度为0.22,平均4-5次识别才能正确识别一个人。