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

news2024/12/27 14:19:12

数据探查:

我们将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()

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1863641.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT API技术教程OpenAI APIKey在线对接-Chat Completion对象

表示模型根据提供的输入返回的聊天完成响应。 {"id": "chatcmpl-123","object": "chat.completion","created": 1677652288,"model": "gpt-3.5-turbo-0125","system_fingerprint": "fp…

锂价跌至近3年最低,大型能源公司已出手抄底,巴菲特也在参与

长远来看,随着电动化进程的深入推进,锂的战略地位依然不可替代。但短期内,供需失衡和价格波动可能会持续,行业参与者需要调整策略以应对当前的挑战。 锂业,正经历自2021年以来最为严峻的调整期。作为电动汽车电池的关…

SpringBoot学习03-[Spring Boot与Web开发]

Spring Boot与Web开发 RestTemplateMockMvc在SPringBoot中使用 SpringBoot整合swagger2SpringBoot的springmvc自动配置底层原理包含ContentNegotiatingViewResolver和BeanNameViewResolverContentNegotiatingViewResolverBeanNameViewResolver 支持提供静态资源,包括…

Inner Transitions

Inner Transitions 内部转换是指不退出源状态的转换。当为具有异或分解的超状态定义时,内部转换是强大的。 使用内部转换可以极大地简化Stateflow图表,如以下示例所示: 使用内部转换之前 使用内部转换到连接结点之后 使用内部转换到历史节点…

【线上】如何解决积压消费?

我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!​​​​​​​ Hello, 各位亲爱的读者朋友们!我是你们的小米,一个积极活泼的技术分享达人,今天我们要聊聊一个大家在分布式系统中经常遇到的棘手问题…

Maven私服批量上传pom和jar实操

Maven私服上传pom和jar实操-CSDN博客 Maven私服上传jar实操_maven fakepath-CSDN博客 之前写过两篇向maven私服上传jar的操作,看到阅读量还可以,觉得应该有很多人有这个需求,所以这次再放一个大招,通过批量的方式向私服传jar和p…

STM32F4 STD标准库串口接收例程

STM32F4 STD标准库串口接收中断空闲中断例程 🔖工程基于STM32F446 ✨用惯了STM32CubeMX傻瓜式配置,突然改用标准库写代码,初始化外设内容,总是丢三落四的。 本文将提供3种串口接收和发送模式:串口接收中断空闲中断、串…

PostgreSQL 用户及授权管理 06:启用 SSL 及验证

PostgreSQL 用户及授权管理 06:启用 SSL 及验证 安全在外企中是非常受重视的,一般外企都会要求所有可以使用加密的地方都使用加密。本小节我们启用 PostgreSQL 的 SSL 加密连接并进行抓包验证。 SSL 连接加密 安全套接字层 (SSL) 允许 PostgreSQL 接受…

Vite响应Ajax请求

Vite响应Ajax请求 陈拓 2024/06/20-2024/06/24 1. 概述 http-server、live-server 等常用于本地测试和开发的http服务器不能很好的支持 ES 模块,在测试ES 模块时浏览器控制台经常显示错误: Failed to load module script: Expected a JavaScript modu…

element-ui侧边栏:default-openeds

element-ui侧边栏实现路由跳转后展开对应侧边栏:default-openeds 当菜单是在本地写死时,如果想展开第一块内容、里面就只写1 :default-openeds"[‘1’]" 当菜单是动态获取时,点击跳转之后如何展开对应的菜单,在watch中监…

three.js围绕中心点的旋转动画代码和案例

在 Three.js 中,可以通过设置对象的旋转中心点来实现围绕一个中心点旋转。具体的实现步骤如下: 首先,创建一个场景、相机和渲染器: // 创建一个场景 var scene new THREE.Scene();// 创建一个透视相机 var camera new THREE.P…

Vite打包速度为什么比webpack快,打包的优劣势在哪里?

大家都有被webpack打包速度搞崩溃的时候,修改一处地方,想预览效果,要等上半天。 Vite比Webpack快的原因 ESM(ES Module)原生支持: Vite基于ESM构建,利用浏览器原生支持的ESM模块加载方式&…

【技术解码】百数SRM:如何助力企业快速优化供应链管理?

SRM应用是企业优化供应链管理的重要工具,它帮助企业全面管理供应商关系,从评估、选择到协同合作和绩效监控,确保供应链的稳定性和效率。 对于企业来说,通过全面管理供应商关系,可以降低采购风险,提升产品质…

Open AI 前 Superalignment部门研究员Leopold Aschenbrenner的关于Superintelligence担忧的真挚长文

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

002_unsigned long数据比较的坑?

【背景】 unsigned long 类似数据的比较问题,先上一段代码,如下图所示: 就是图中框出的部分,眨眼一看,应该没啥问题,而且我也在本地的编译器vs2019上编译了,确实也没有报错,所以就修…

基于java+springboot+vue实现的宠物商城网站(文末源码+Lw)273

摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,商品信息因为其管理内容繁杂,管理数量繁多导致手工进行处理不能满足广…

java启动命令与参数配置

1. java启动命令 运行一个java应用程序的语法分两种,分别为: 执行类:java [-options] class [args…] 执行jar文件:java [-options] -jar jarfile [args…] 其中 [-options] 配置 JVM参数,[args…] 配置 Java 运行参…

11.xss之href输出

11.xss之href输出 后台配置文件中的代码 xss之href输出绕过:javascript:alert(1111) 直接代入a标签herf里面一样可以绕过htmlspecialchars 输入攻击代码 javascript:alert(1111)点击蓝色字体直接会弹窗,如图所示:

Javac编译器

Java语言的编译器是一段不确定的操作过程,可能是讲Java文件转变为class文件的过程,也可能是指虚拟机的后端编译,讲字节码转换为机器码的过程,还肯是静态提前编译器直接讲Java文件编译为本地机器代码的过程。 前端编译器&#xff…

HTML5五十六个民族网站模板源码

文章目录 1.设计来源高山族1.1 登录界面演示1.2 注册界面演示1.3 首页界面演示1.4 中国民族界面演示1.5 关于高山族界面演示1.6 联系我们界面演示 2.效果和源码2.1 动态效果2.2 源代码2.3 源码目录 源码下载 作者:xcLeigh 文章地址:https://blog.csdn.ne…