首页 > 编程语言 >【Python机器学习】聚类算法的对比与评估——在人脸数据集上比较算法

【Python机器学习】聚类算法的对比与评估——在人脸数据集上比较算法

时间:2024-06-30 18:28:31浏览次数:26  
标签:people Python labels mask eps label 算法 聚类 pca

数据探查:

我们将k均值、DBSCAN和凝聚聚类算法应用于Wild数据集中的Labeled Faces,并查看它们是否找到了有趣的结构。我们将使用数据的特征脸表示,它由包含100个成分的PCA(whiten=True)生成:


people=fetch_lfw_people(data_home = "C:\\Users\\86185\\Downloads\\",min_faces_per_person=20,resize=.7)
image_shape=people.images[0].shape
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]

pca=PCA(n_components=100,whiten=True,random_state=0)
pca.fit_transform(X_people)
X_pca=pca.transform(X_people)

与原始像素相比,这是对人脸图像的一种语义更强的表示,它的计算速度更快。

用DBSCAN分析人脸数据:

dbscan=DBSCAN()
labels=dbscan.fit_predict(X_pca)
print('标签:{}'.format(np.unique(labels)))

可以看到,所有返回的标签的-1,因此所有数据都被DBSCAN标记为噪声。我们可以改变两个参数来改进这一点:

1、增大eps,从而扩展每个点的邻域;

2、缩小min_samples,从而将更小的点视为簇。

首先尝试改变min_samples:

dbscan=DBSCAN(min_samples=3)
labels=dbscan.fit_predict(X_pca)
print('标签:{}'.format(np.unique(labels)))

可以看到,由3个点构成的组,所有点也被标记为噪声,因此需要增大eps:

dbscan=DBSCAN(min_samples=3,eps=15)
labels=dbscan.fit_predict(X_pca)
print('标签:{}'.format(np.unique(labels)))

使用更大的eps(15),只得到了单一簇和噪声点。我们可以利用这一结果找出噪声相对于其他数据的形状。

print('噪声、簇内点:{}'.format(np.bincount(labels+1)))

可以看到,噪声只有37个,因此可以查看所有的噪声点:


noise=X_people[labels==-1]
fig,axes=plt.subplots(5,9,subplot_kw={'xticks':(),'yticks':()},figsize=(12,4))
for image,ax in zip(noise,axes.ravel()):
    ax.imshow(image.reshape(image_shape),vmin=0,vmax=1)
plt.show()

可以看到,有些人脸图像在喝水(拿杯子)或者戴帽子等,猜测这就是被标记为噪声的原因。

这种类型的分析(尝试找出“奇怪的那一个”)被称为异常值检测。如果这是一个真实的应用,那么我们可以去尝试更好的裁切图像,以得到更均匀的数据。

如果想找到更有趣的簇,而不是一个非常大的簇,可以把eps设置的更小。

来看一下不同eps取值的结果:


for eps in [1,3,5,7,9,11,13]:
    print('\neps:{}'.format(eps))
    dbscan=DBSCAN(eps=eps,min_samples=3)
    labels=dbscan.fit_predict(X_pca)
    print('簇类别:{}'.format(np.unique(labels)))
    print('簇的大小:{}'.format(np.bincount(labels+1)))

对于较小的eps,所有的点都被标记为噪声。

eps=7时,会得到很多噪声点和一些较小的簇;

eps=9时,仍然会得到很多噪声点,但是会得到一个比较大的簇和一个较小的簇;

从eps=11开始,就只能得到一个较大的簇和一些噪声。

较大的簇从来没有超过过一个,最多有一个较大的簇包含大多数点,还有一些较小的簇。

我们可以通过研究eps=7时,将7个较小的簇中的点全部可视化来深入研究这个聚类:


dbscan=DBSCAN(min_samples=3,eps=7)
labels=dbscan.fit_predict(X_pca)
for cluster in range(max(labels)+1):
    mask=labels==cluster
    n_images=np.sum(mask)
    fig,axes=plt.subplots(1,n_images,figsize=(n_images*1.5,4),subplot_kw={'xticks':(),'yticks':()})
    for image,label,ax in zip(X_people[mask],y_people[mask],axes):
        ax.imshow(image.reshape(image_shape),vmin=0,vmax=1)
        ax.set_title(people.target_names[label].split()[-1])
    plt.show()

有一些簇对应这个数据集中一些脸部非常不同的人。

每个簇的人脸方向和面部表情也是固定、相似的。而有些簇中虽然包含多个人的面孔,但他们的方向和表情都比较相似。

用k均值分析人脸数据:

我们可以看到,利用DBSCAN无法创建多余一个较大的簇。凝聚聚类和k均值更可能创建均匀大小的簇。但我们需要设置簇的目标个数。

我们可以将簇设置为数据集中的已知个数,虽然无监督聚类算法不太可能完全得到他们。相反,我们可以先设置一个比较小的簇个数,这样我们可以分析每个簇:


km=KMeans(n_clusters=10,random_state=0)
label_km=km.fit_predict(X_pca)

print('簇的大小(k均值):{}'.format(np.bincount(label_km)))

可以看到,k均值聚类将数据划分为大小相似的簇,大小在60到363之间,这与DBSCAN非常不同。

通过将簇中心可视化来进一步分析k均值的结果。

由于我们是在PCA生成的表示中进行聚类,因此我们需要使用pca.inverse_transform将簇中心旋转回到原始空间并可视化:


fig,axes=plt.subplots(2,5,subplot_kw={'xticks':(),'yticks':()},figsize=(12,4))
for center,ax in zip(km.cluster_centers_,axes.ravel()):
    ax.imshow(pca.inverse_transform(center).reshape(image_shape),vmin=0,vmax=1)
plt.show()

k均值找到的簇中心是非常平滑的人脸。因为每个簇中心都是60到363张人脸图像的平均。使用降维的PCA表示,可以增加图像的平滑度。聚类似乎捕捉到人脸的不同方向、不同表情、以及是否有衬衫扣子之类的特征。

我们对每个簇中心给出了簇中5张最经典的图像(也就是该簇中与簇中心距离最近的图像)与5张最不典型的图像(也就是该簇中与簇中心距离最远的图像):

mglearn.plots.plot_kmeans_faces(km,pca,X_pca,X_people,y_people,people.target_names)
plt.show()

可以看到,“非典型的”点与簇中心不太相似,似乎分配有些随意。这可以归因于一下原因:k均值对所有数据点进行划分,不想DBSCAN那样具有噪声点的概念。

利用更多数量的簇,算法可以找到更细微的区别,但添加更多的簇会使得人工检查更为困难。

用凝聚聚类分析人脸数据:

下面看一下凝聚聚类的结果:

agglomerative=AgglomerativeClustering(n_clusters=10)
label_agg=agglomerative.fit_predict(X_pca)

print('簇的大小(凝聚聚类):{}'.format(np.bincount(label_agg)))

凝聚聚类生成的也是大小相近的簇,大小在49到553之间,这比k均值生成的簇更不均匀,但比DBSCAN生成的簇更加均匀。

我们可以通过计算ARI来度量凝聚聚类和k均值给出的两种数据划分是否相似:

km=KMeans(n_clusters=10,random_state=0)
label_km=km.fit_predict(X_pca)

print('ARI:{:.2f}'.format(adjusted_rand_score(label_agg,label_km)))

ARI只有0.09,说明labels_agg和labels_km这两种聚类的共同点很少,原因在于:对于k均值,原理簇中心的点似乎没有什么共同点。

下面绘制树状图,但是限制了数的深度,要不然全部呈现2063个数据点,图像无法阅读:

linkage_array=ward(X_pca)
plt.figure(figsize=(20,5))
dendrogram(linkage_array,p=7,truncate_mode='level',no_labels=True)
plt.xlabel('数据点')
plt.ylabel('簇 间距')
plt.show()

想要创建10个簇,我们要在顶部有10条竖线的位置将树横切。

我们将10个簇可视化。

在凝聚聚类内,没有簇中心的概念(虽然我们计算了平均值),我们芝士给出了每个簇的前几个点。


n_cluster=10
for cluster in range(n_cluster):
    mask=label_agg==cluster
    fig,axes=plt.subplots(1,10,figsize=(15,8),subplot_kw={'xticks':(),'yticks':()})
    axes[0].set_ylabel(np.sum(mask))
    for image,label,asdf,ax in zip(X_people[mask],y_people[mask],label_agg[mask],axes):
        ax.imshow(image.reshape(image_shape),vmin=0,vmax=1)
        ax.set_title(people.target_names[label].split()[-1],fontdict={'fontsize':9})
    plt.show()

虽然某些簇似乎具有语义上的主题,但其实很多簇都太大而实际上很难是均匀的。

为了得到更均匀的簇,我们可以再次运行算法,把簇设置为40个,并挑选一些特别的簇。

n_cluster=40
for cluster in [10,13,19,22,36]:
    mask=label_agg==cluster
    fig,axes=plt.subplots(1,15,figsize=(15,8),subplot_kw={'xticks':(),'yticks':()})
    cluster_size=np.sum(mask)
    axes[0].set_ylabel('#{}:{}'.format(cluster,cluster_size))
    for image,label,asdf,ax in zip(X_people[mask],y_people[mask],label_agg[mask],axes):
        ax.imshow(image.reshape(image_shape),vmin=0,vmax=1)
        ax.set_title(people.target_names[label].split()[-1],fontdict={'fontsize':9})
    for i in range(cluster_size,15):
        axes[i].set_visible(False)
    plt.show()

可以看到,被挑选的第一个是“笑脸”的簇,第二个是向右看,第三个是眯着眼,第四个基本都是大胡子。

标签:people,Python,labels,mask,eps,label,算法,聚类,pca
From: https://blog.csdn.net/weixin_39407597/article/details/139958370

相关文章

  • 动手学深度学习(Pytorch版)代码实践 -计算机视觉-44目标检测算法综述:R-CNN、SSD和YOLO
    41~44目标检测算法综述:R-CNN、SSD和YOLO1.区域卷积神经网络(R-CNN系列)1.1R-CNN使用启发式搜索算法来选择锚框。使用预训练模型对每个锚框提取特征(每个锚框视为一张图片,使用CNN提取特征)。训练SVM进行类别分类(在神经网络之前进行)。训练线性回归模型预测边界框偏移......
  • 月薪90k!第一批卷多模态算法的已成功上岸!
    当前,多模态大模型(MLLM)在多项视觉任务上展现出了强大的认知理解能力,也成为CVPR2024备受瞩目的热门领域之一。我整理了210篇多模态最新研究成果,140份多模态和大模型报告读者福利:如果大家对大模型感兴趣,这套大模型学习资料一定对你有用对于0基础小白入门:如果你是零基础小......
  • Python教程--基本技能
    】@TOC5.1解析命令行参数在Python中,解析命令行参数是一项常见的任务,尤其是在开发命令行工具或脚本时。Python标准库提供了argparse模块,它可以帮助你轻松地编写用户友好的命令行接口。下面是使用argparse模块解析命令行参数的基本步骤:引入argparse模块首先,你需要引入arg......
  • Python基础之网络编程
    目录1网络编程1.1简介1.2socket()1.3TCP简单实例单向交互1.3.1服务端1.3.2客户端1.4TCP双向交互1.4.1服务端1.4.2客服端1.5UDP连接1.6PythonInternet模块1网络编程1.1简介Socket又称套接字,应用程序通常通过套接字向网络发出请求或者应答网络请求,使主机间或者......
  • Python——比 Seaborn 更好的相关性热力图:Biokit Corrplot
    目录前言:我们需要更好的相关性热力图对比PythonSeaborn与Rcorrplot传统的Seaborn相关性热力图R语言中的相关性热力图关于Biokit简介库的安装相关性热图的绘制基本使用方法详述一些绘图参数的问题及细节关于order_method参数关于order_metric参数关于cmap参数改进B......
  • 【Python3.8.10打包exe】【Windows】
    Python3.8.10打包exe打包命令pyinstaller-Fxxx.py查看Package及版本号piplist查看Python版本号python-V打包需要用的Package及版本#python版本#3.8.10#wheel版本#0.43.0#pyinstaller版本#6.8.0常用链接chatgptPython标准库—Python3.8.19文档PyPI......
  • [oeasy]python021_赛博宝剑铭文大赏_宝剑上的铭文_特殊符号和宝物
    继续运行......
  • 《最新出炉》系列入门篇-Python+Playwright自动化测试-52- 字符串操作 - 下篇
    1.简介在日常的自动化测试工作中进行断言的时候,我们可能经常遇到的场景。从一个字符串中找出一组数字或者其中的某些关键字,而不是将这一串字符串作为结果进行断言。这个时候就需要我们对字符串进行操作,宏哥这里介绍两种方法:正则和字符串切片函数split()。2.测试场景宏哥在这里......
  • 【Python爬虫实战项目】Python爬取Top100电影榜单数据并保存csv文件(附源码)
    前言今天给大家介绍的是Python爬取Top100电影榜单数据保存csv文件,在这里给需要的小伙伴们帮助,并且给出一点小心得。开发工具Python版本:3.6相关模块:requests模块time模块parsel模块csv模块环境搭建安装Python并添加到环境变量,pip安装需要的相关模块即可。文中......
  • Python教程:开箱即用的Python os模块知识
    1.简介注:文末有福利领取哦Python的os模块提供了许多接口用于与操作系统进行交互,包括文件操作、目录操作、路径操作、环境变量操作、系统信息获取等。以下是os模块中常用的接口及其解释:文件和目录操作:os.remove(path):删除指定路径的文件。os.rename(src,dst):......