TowardsDataScience 博客中文翻译 2020(二百一十二)
如今,越来越多的公司开始在基于云的环境中开发和部署应用程序。云计算的主要动机之一是,它消除了与设置和管理所用硬件和软件相关的所有问题。这是通过远程租用云提供商维护的数据中心的计算机资源来实现的。通过这种方式,公司和个人可以远程使用不同云提供商提供的硬件和软件设置以及工作流,而不必担心购买设备、设置不同的环境以及长期维护它们。因此,使用这种方法,用户可以专注于开发和部署他们的服务(如网站、数据库、应
云金融面试准备和技巧
克里斯蒂娜@ wocintechchat.com 在 Unsplash 上的照片
在云金融工作,经常会遇到这样的问题:“面试要做哪些准备?”。这个问题对我来说很难回答,因为在云金融领域工作与我接触过的其他金融角色非常不同。然而,本文旨在为有兴趣申请云财务经理职位的人提供一些重要的学习资源和技巧。
首先,有很多“云”要覆盖,因为空间非常大,无所不包。清单包括:技术技能、行业趋势、云经济、硬件细节、工程管理/合作伙伴关系、核心财务技能以及许多其他主题。幸运的是,所有这些话题都非常有趣,关于它们的数据可以通过 YouTube 或免费培训网站公开获得,如 EdX、Linkedin Learning 或 AWS/Azure 培训网站。
第二,把这些新话题看作是一个增长和展示你认知灵活性的绝佳机会,而不是把它们看作进入的障碍。今天,云金融行业的许多人都没有预装这方面的知识,而云是如此之大,以至于我们都在不断地学习它。这是令人兴奋的挑战!
为什么分享面试准备对我很重要
鉴于这一小型(但快速增长的)行业所需的知识/技能相对小众,可能会偏向于具有云计算/科技金融背景的候选人,他们有在职经验,回答问题时更具技术性。总的来说,我认为这是不公平的,因为它可能会对已经处于孤立网络中的人产生偏见。这种偏见可以通过改变面试官问的问题来应对和纠正,更多地关注行为问题,鼓励更多的通用财务技能,以及从不同的部门/背景招聘员工。
在消除面试偏见的同时,我相信通过提供更多的面试准备资源并使其易于获取,也有助于提升技能水平。为此,我分享了一些我最喜欢的云金融面试准备,以帮助最大限度地减少群体偏见的影响,并让你跟上速度。
警告:我不是招聘经理,我的信念不能反映我的公司。这些是我从非科技金融工作转向云计算工作时使用的有用培训和技巧。除了这些培训和良好的经历,我还有幸进入了这个行业。
第一:要学习、准备和准备的关键技术主题
数据中心如何工作 —云金融的核心是支持运行“云”并提供基于云的产品和服务的数据中心的扩展、运营和优化。因此,了解什么是数据中心以及它是如何工作的,可以为您的工作提供很多信息。每封电子邮件、每台机器、API 调用、面部识别和 SaaS 订阅都可以追溯到 DC(数据中心)中的一台物理机器。深刻理解基础设施成本将有助于理解下游成本。因此,浏览数据中心是我用来学习的最有用的工具之一。我最喜欢的是谷歌数据中心内的视频漫步——YouTube(5 分钟)。
什么是虚拟机——如今云提供商销售的最大产品是虚拟机。这是在理解数据中心和物理成本的基础上更上一层楼,对于掌握云经济学至关重要。以下是我最喜欢的教程,按深度递增排序。
云经济学基础知识 —您应该能够回答“迁移到云有什么财务好处?”为你的立场辩护。虽然答案可以很清楚地列出来,但这是你将与客户、合作伙伴和同事讨论的更有趣、更深奥的话题之一。
- 简单的答案=将资本支出转化为运营支出在云经济学— YouTube (5 分钟)中有清晰的总结
- 明智的答案=一些硬成本节约+灵活性、安全性和创新的无形价值。这些在 IBM 关于云迁移的快速文章 (2 分钟)和视频中得到强调。(5 分钟)
- 超级深度探索= 云经济学——YouTube(50 分钟)
观看云主题演讲 —这对于把握行业热点话题和趋势非常重要。类似于苹果的开发者大会,这些主题活动是云首席执行官发布闪亮新产品并强调他们在业务增长部分的成功的地方。这些是更长的事件,所以请随意快进,以 1.5 倍观看。注意:每次有人说 AI 时,喝一杯饮料来玩这个游戏。
- AWS re:Invent 2019——Andy Jassy 的主题演讲——YouTube(2 小时)
- 塞特亚·纳德拉的视觉主题演讲|微软 Ignite 2019—YouTube(1 小时)
- 此外,如果你了解你申请的群体,观看关于该行业的分组会议,了解关键术语,并观看产品演示。
上网站 —最后,花点时间浏览公司网站,了解他们的产品和服务。这些都是公开信息,所以招聘经理可能会不小心使用一些行话或产品名称(EC2、计算、认知服务、容器、S3、红移),这些可能是常见的行业知识,但不是常见的你的知识。一次快速的现场参观会帮助你用一个会意的点头代替困惑的畏缩。
- 云计算服务|微软 Azure
- 亚马逊网络服务(AWS)——云计算服务
- 如果你正在制作抽认卡,下面包括一些关键术语和速记定义的列表(没有必要),但是查看更多的词汇表中的一个。
接下来:面试技巧和行为问题
展示你的学习能力 —云是一个快速增长的空间,你将要做的许多工作都是新的(对你和这个世界来说)。你需要展示一些处理模糊任务的能力,并成为一个无所不知的人。
- 分享你以前的学习和发展潜力的例子是一个加分。
- 关于这里的背景,下载 LIBBY app 并阅读 Carol Dweck 的增长思维,这是过去几年的热门商业书籍,也是 Satya 的书的灵感来源。
关注你不同的经历 —你独特的背景和思维方式是一笔财富!技术和云可能会有很多狭隘的想法,所以让外界的人加入进来带来新的视角总是很重要的。
- 例如,云投资是非常资本密集型的,云产品有许多不同的产品 COGS 模型。这与标准软件或 SaaS 公司有着显著的不同,因此在雇佣有资本管理经验或产品知识背景的人时会给予额外的奖励。即使产品体验来自于卖肥皂,产品成本就是产品成本。
温习你的技术技能 — Excel power pivot、Power BI 和基本的数据库技能不是必需的,但它们确实有所帮助。能够用技术来管理技术是未来的技能。在快速发展的企业中,运营工作不断增加,这意味着自动化、简化或消除任务的技术技能具有巨大的价值。如果你把这些技能或其他技能带到聚会上,一定要强调它们帮助你产生的影响。如果没有,可以参加一些免费的在线课程和 youtube 培训,继续充实你的简历。
- 在 excel 中可视化数据 —来自 edX
- Power BI via linkedin 学习!
- 超越权力中枢——这可能有些矫枉过正
人际技能非常重要 —这里有很多工程师,所以展示影响有技术头脑的人的能力会有所帮助。这通常表现为成为一名优秀的沟通者,或者能够简单地总结复杂的话题。
- 准备一些你帮助商业伙伴进行清晰分析的例子,或者你如何影响他们的想法。
- 读《如何赢得朋友和影响他人》从来没有不好的时候。(还是听听吧)
感谢阅读,更多 AI 财经内容,在 Linkedin 上关注或添加我 David Hall | LinkedIn
数据科学家的云基础
云技术基础及其在数据科学中的应用指南
介绍
如今,越来越多的公司开始在基于云的环境中开发和部署应用程序。云计算的主要动机之一是,它消除了与设置和管理所用硬件和软件相关的所有问题。这是通过远程租用云提供商维护的数据中心的计算机资源来实现的。
通过这种方式,公司和个人可以远程使用不同云提供商提供的硬件和软件设置以及工作流,而不必担心购买设备、设置不同的环境以及长期维护它们。因此,使用这种方法,用户可以专注于开发和部署他们的服务(如网站、数据库、应用、数据分析),而不必考虑任何可能的开销。最终,这可以导致更快的/持续的开发和提高的客户满意度,符合共同的 DevOps(开发-操作)原则。
云服务背后的主要思想非常类似于过去开发的任何其他类型的实用程序和基于订阅的系统。例如,在这些日子里,我们每个人都使用公用设施,如电/水/气,而不必担心这些系统是如何工作的,并交付给我们。我们关心的是我们的提供商能给我们一个可靠的服务,我们必须为我们使用多少或不使用所有这些服务付费。
正在使用的一些主要云提供商包括:
所有这些不同的提供者,对于所提供的服务都有他们自己的术语,但是他们都共享本文中概述的相同原则。
云概念
每个不同的云提供商都能够提供各种各样的服务和应用,这些服务和应用可以分为四种主要类型:
- 计算: 虚拟机、容器等…
- 联网: 安全服务使不同的服务相互交互。
- 存储: 为应用程序存储任何类型的文件或数据库的空间。
- 分析: 数据处理和可视化工具,用于从存储的数据中分析和创建洞察。
为了降低资源租用成本并充分利用可用硬件,云服务严重依赖虚拟化技术,如虚拟机和容器。
虚拟机(VM)
虚拟机是为了模拟计算机硬件而创建的(图 1)。可以创建虚拟机的不同实例来同时在一台计算机上运行,每个实例都有一个首选的操作系统、内存和存储分配。一旦创建了虚拟机,就可以使用桌面客户端远程访问,并像任何其他物理计算机一样使用(例如,安装程序、运行应用程序等)。这样,通过将单台计算机用作不同计算机的集合,可以最大限度地利用硬件。
图 1:虚拟机基础设施
在云中使用虚拟机的另一个巨大优势是我们的系统可以变得易于扩展。因此,如果需要比计划更多的资源来完成项目,云提供商可以即时提供额外的内存和存储能力(从而减少部署中任何可能的停机时间)。
此外,如果我们希望确保我们的服务始终运行,也可以创建一个备份虚拟机,在原始虚拟机出现任何问题时自动运行。当在网站或应用程序等服务上添加新功能时,这可能特别有用,我们希望首先向一部分受众提供服务的新版本,以便获得某种反馈,了解变化是否会给服务带来积极影响(A/B 测试)。
容器
虚拟机的一个问题是每个虚拟机都有自己的操作系统。例如,如果我们有一个复杂的应用程序,它的一些操作需要 Windows,而另一些操作需要 Linux,那么我们就需要运行两个独立的虚拟机,并使这两个虚拟机相互通信。因此,这导致了可以避免的资源开销。此外,当在团队中开发一个应用程序时,当从不同的环境转移时,也可能会出现一些包依赖冲突(例如,“它在我的机器上工作”)。
为了避免这些类型的问题,已经构思了容器。容器,将应用程序及其依赖项打包在一起,并将它们部署到容器主机上(容器主机充当抽象操作系统的服务)。通过这种方式,现在可以避免由于拥有多个操作系统而产生的内存开销,并且与使用虚拟机在单台机器上运行相比,可以在单台机器上运行更多的容器。此外,现在我们的应用程序可以轻松地在不同的操作系统之间移动,而不必考虑管理底层的依赖关系。
虚拟机虚拟化硬件,而容器虚拟化操作系统[1]。
为了创建容器,最常用的服务之一是 Docker (图 2)。
图 2:容器基础设施
创建复杂系统的最有效方法之一是将它们分成不同的容器应用程序,每个应用程序都有不同的角色。例如,如果我们正在做一个网站,将网站分成三个主要容器是一个好主意:前端、后端和数据库。每当我们想要引入新的特性时,我们可以更新我们感兴趣的容器,而不必接触其他的容器。随着我们向应用程序添加更多的组件,应用程序的复杂性增加,可能需要更多的容器。为了有效地维护和组织集装箱,Kubernetes 等服务应运而生。
Kubernetes 的开发是为了使基于容器的应用程序能够在基于云的环境中轻松伸缩。Kubernetes 可以提供的服务包括:
- 优化容器之间的工作负载,并根据需求扩展所需的资源数量。
- 如果容器中有任何错误,可以创建一个新实例来替换它。
- 如果在一个新特性发布后,出现了一些问题,可以很容易地回到我们应用程序的前一个版本。
利用 Kubernetes 来编排我们的应用程序,可以让我们遵循 DevOps 实践,例如 【持续集成】 和 持续交付(CD) 。持续集成的主要焦点是确保代码变更与当前的代码信息结构完美集成,而持续交付的焦点是使代码库始终准备好进行部署(能够自动通过任何适当的构建和测试机制)。
云部署和服务类型
一旦在云中创建了应用程序,就可以使用三种不同的云部署方法进行部署:
- 公有云: 在这种场景下,所有使用的资源都由云提供商管理和维护。这是目前最具成本效益和最常见的云部署方法。
- 私有云: 常用于需要高安全性和严格法律合规性的工作任务。在这种情况下,企业可以创建本地云信息结构,从而减少对云提供商的控制(该选项要求企业预先购买自己的硬件设备)。
- 混合云: 在本例中,应用程序的一部分可能由我们的云提供商管理,而其他部分则由私有企业管理(混合了公共云和私有云部署方法)。
最后,云上有三种不同类型的服务可用:
- 信息架构即服务(IaaS): 在 IaaS 类型的服务中,我们租用一些硬件并自行配置,以便完成不同的任务。
- 平台即服务(PaaS): 在 PaaS 类型的服务中,我们租用一些预配置的硬件,并使用它来测试和开发一些应用程序或存储业务数据。
- 软件即服务(SaaS): 在 SaaS,云提供商开发并维护一些软件应用程序,然后使用订阅模式进行分发。SaaS 程序的两个例子是 Skype 和 Office 365。
利用这种基础设施,就有可能轻松地将任何类型的基于软件的业务迁移到云中。
希望你喜欢这篇文章,谢谢你的阅读!
联系人
如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:
文献学
[1]微软学习,Azure 基础。访问:https://docs . Microsoft . com/en-GB/learn/paths/azure-fundamentals/
云运行:谷歌云文本到语音 API
使用 Google Cloud Run 提供智能 API
Google 文本到语音转换 API 服务于云运行。
目录
在谷歌云上运行
Google Cloud Run 于 2019 年 11 月左右正式发布。它提供了一个完全托管的无服务器执行平台,通过 HTTP 驱动的容器来抽象无状态代码部署的基础设施。Cloud Run 是一个 Knative 服务,利用相同的 API 和运行时环境,可以构建基于容器的应用程序,这些应用程序可以在任何地方运行,无论是在 Google cloud 或 Anthos 上部署,还是在云上。作为一个“无服务器执行环境”,Cloud Run 可以根据正在运行的应用程序的计算需求进行扩展。应用代码的即时执行、可扩展性和可移植性是 Cloud Run 的核心特性。
关于谷歌云文本到语音转换 API
Google Cloud Text-to-Speech 公开了一个 API 来从文本合成听起来自然的语音。文本及其相应的语音输出可以是不同的语言,包括英语、法语、俄语和阿拉伯语,仅举几例。这种最先进的 API 为将逼真的高保真文本到语音交互集成到最终用户应用程序中提供了多种机会。
图 1: 谷歌云文本到语音转换 API。
用于身份验证的服务帐户
要使用 Google Cloud 文本到语音转换 API,我们必须创建一个服务帐户密钥用于身份验证。服务帐户对应用程序或虚拟机(VM)进行身份验证,以在 Google 云平台上进行授权的 API 调用。
使用以下链接为云文本到语音转换 API 创建服务帐户。-> 云语音合成服务账号。
图 2: 为文本到语音 API 创建一个服务账户。
使用以下参数:
- **服务账号:**新服务账号。
-服务账户名称:【指定名称】。
**-角色:**不需要角色。
点击Create without role
,将包含密钥的 JSON 文件下载到您的电脑。
在创建并下载您的安全服务帐户密钥之后,将环境变量GOOGLE_APPLICATION_CREDENTIALS
设置为包含您的服务帐户密钥的 JSON 文件的路径(参见图 3)。
应用程序代码
这个项目的代码托管在一个 Github 库中,链接为https://github.com/dvdbisong/text-to-speech-cloud-run。Python 文件app.py
包含了通过 HTTP 访问容器化应用程序的逻辑。代码在text-speech
目录下,可以在**谷歌代码编辑器(云壳的一个组件)**上查看。代码有注释,容易理解。
**图 3:**Python 文件 app.py 中的应用代码。
将服务账户密钥上传至应用程序
上传服务帐户密钥以验证调用文本到语音转换 API 的应用程序。上传后,将密钥放在text-speech
文件夹中。
图 4: 上传服务账号密钥。
文档文件
docker 文件概述了创建容器映像的方法。这个项目的 Dockerfile 文件基于官方的 Python 图像。Dockerfile 指定了构建映像时将安装在容器上的相关包。Flask 应用程序使用gunicorn
包来公开访问容器内应用程序的端口。**在谷歌代码编辑器上,**导航至text-speech
查看 docker 文件。
图 5: Dockerfile 为应用程序容器构建映像。
为了完整起见,下表总结了 Dockerfile 文件中使用的命令。
+------------+-----------------------------------------------------+
| **Command** | **Description** |
+------------+-----------------------------------------------------+
| **FROM** | The base Docker image for the Dockerfile. |
| **RUN** | It executes commands on top of the current image as | | new layers. |
| **COPY** | Copies files from the local machine to the |
| container filesystem. |
| **CMD** | Specifies the command to execute when running the | | container. This command is overridden if another | | command is specified at runtime. |
| **WORKDIR** | Sets the working directory of the container. |
| **ENV** | Set Environment variable as a key-value pair that | | will be available in the container after building. |
+------------+-----------------------------------------------------+
使用云构建构建映像,并上传到容器注册中心
Cloud Build 是一项 GCP 服务,用于自动化代码工件的部署,作为 CI/CD 管道的一部分。这里,Cloud Build 用于构建 Docker 映像,作为一系列构建步骤,完成的映像被推送到 Google 容器注册表。
以下代码使用云构建构建映像,并将映像上传到容器注册。从目录text-speech
运行这段代码。
gcloud builds submit — tag gcr.io/ekabasandbox/ebisong-text-to-speech
其中,
ekabasandbox
为 GCP 项目 ID,ebisong-text-to-speech
为图像名称。
确保根据需要修改这些参数。
图 6: 使用云构建构建映像。
使用云运行部署容器
要将存储在 Google 容器注册表上的容器部署到云运行,请执行以下代码:
gcloud run deploy --image gcr.io/ekabasandbox/ebisong-text-to-speech --platform managed
选择要部署托管云运行计算的地区(例如美国中心 1)。当提示输入服务名时,按Enter
接受缺省值,并在询问是否允许未认证调用时响应y
(yes)。
当容器部署到云运行时,点击 URL 查看正在运行的应用。
你可以继续探索应用了。
图 7: 云 Run 上托管的文本到语音应用。
结论
本文提供了一个在 Cloud Run 上部署进行 API 调用的应用程序的示例。它提供了使用 Google Cloud 文本到语音转换 API 和使用 Flask 运行简单 web 应用程序的示例代码,Flask 被打包成一个容器并部署在 Cloud Run 上。整个应用程序在 https://github.com/dvdbisong/text-to-speech-cloud-run 是开源的。最后,确保删除云运行服务,以及云容器注册表中不再需要的图像。
云 vs 边缘:工业制造的困境
当涉及到为应用程序部署人工智能时,制造商不仅需要深入思考开发什么,还需要思考设想的人工智能系统的物理化身。
图片由 Flickr 提供
通常,深度学习是人工智能应用的子种类,由于在大规模部署现实世界工作人工智能方面的成功,在过去几年中获得了关注,它是作为云支持的软件即服务(SaaS)平台提供的。
这对于许多制造商来说是行不通的,他们倾向于避免依赖云的软件带来的安全性和延迟问题,以管理日常复杂的工作流程。
幸运的是,技术在不断发展,在 2020 年,这个行业将面临挑战,深度学习和人工智能的范式变革将有利于制造业的需求。
但首先,让我们理解我们所说的深度学习是什么意思,以及硬件——云和边缘——如何发挥如此重要的作用。
引擎盖下:艾
人工智能的通用名称隐藏了各种方法,从在分布式云基础设施上处理数据的巨大人工智能模型,到在小型处理器上分析和挖掘数据的小型边缘友好人工智能。
让我们简化一下,把人工智能分成两个主要的类别,重型和轻型。重型人工智能需要大型计算基板来运行,而轻型人工智能可以在小型计算足迹上做重型人工智能能够做的事情。
GPU 等商用处理器的引入,以及后来它们的便携性,使得将人工智能/深度学习/DNN/神经网络算法带到边缘在技术上和经济上都是可行的。
从直觉上来说,边缘人工智能计算是一个伟大的想法:通过将一些生物计算转移到外围,从我们的传感器(例如,眼睛,耳朵,皮肤)到我们的器官和肌肉,大自然母亲已经在亿万年的进化时间里发现了这一点,世界上的大部分“数据”都是在有机体探索他们的世界时产生的。
同样,制造商利用这一特性也很有意义。以工业机器中的质量控制摄像机为例,典型的机器每秒可以处理几十帧,每小时可以处理数百个产品。对于这些相机来说,将所有捕捉到的帧运送到一个中央云进行人工智能处理将是极其浪费和低效的。相反,更智能的策略是在边缘处理它们,并偶尔将相关的、非常重要的帧(例如,具有可能的产品缺陷的帧)发送到中央位置或人工分析师。
带宽、延迟和成本等问题决定了边缘处理的需求。
不过有一个重要的警告:在小型计算边缘运行人工智能——行话中称为推理或“预测”(例如,我看到一个正常的产品与一个有缺陷的产品)不同于在边缘学习。也就是说,使用获得的信息来改变、改进、校正和提炼边缘人工智能不仅困难,而且对于制造商来说,能够快速定制他们的人工智能以实现灵活性是极其重要的
边缘(与云)学习:现实
图片由 Flickr 提供
我第一次意识到与 NASA 的巨大差异是在 2010 年,当时我和我的同事实施了一个小型大脑仿真来控制一个类似火星漫游车的人工智能设备,该设备需要能够在边缘运行和学习。
对于美国宇航局来说,机器人能够完全独立于地球上任何可用的计算能力来学习“新事物”是非常重要的。数据瓶颈、延迟和大量其他问题使得探索自那时以来开发的不同种类的人工智能变得至关重要。能够消化和学习的算法——即,根据可用数据调整人工智能的行为——不需要大量的计算能力、数据和时间。传统的深度神经网络(DNN)模型无法做到这一点。
我们建立了这样的人工智能,我们称之为终身深度神经网络(终身-DNN ),因为它有能力在一生中学习(而传统的 DNN 只能在部署前学习一次)。
我们不知道这个人工智能在地球上会比在火星上更有用。
工业制造商边缘学习的力量
图片由 Flickr 提供
边缘学习解决了当今人工智能实现的一个燃眉之急:它的不灵活性和缺乏适应性。当可用时,人工智能算法可以在大量数据上进行训练,如果所有数据都被事先捕获用于训练,则人工智能算法相当健壮。不幸的是,这并不是制造业的工作方式,因为在生产线上不可预测地出现少数不良产品之前,数据(例如不良产品)通常是不可用的。人工智能需要能够快速利用这些不同的、罕见的数据来适应,但传统的 DNNs 无法在这些现实条件下工作。
诸如 lifetime-DNN(一种能够在计算边缘(如 CPU)进行学习的深度学习范式)等新方法使人工智能相机不仅能够理解向它们提供的数据,而且能够适应和学习。例如,在上述工业机器中,边缘学习将使其数十个摄像机能够学习新产品类型和缺陷,在现实世界的场景中,新产品一直在引入,新的、以前看不到的缺陷出现在生产车间。
不可能存在可以在新创造的产品上预先训练的人工智能。数据根本不存在:AI 需要现场训练!
通过边缘学习,人工智能可以学习识别新的缺陷,而不必从头开始对人工智能进行“重新编程”,直接在需要的边缘进行。
在边缘学习的人工智能是一种范式转变技术,最终将使人工智能真正服务于其目的:将智能转移到需要的计算边缘,其速度、延迟和成本使每个设备都可以负担得起。
这将使制造商能够廉价、快速、直接地在关键位置(边缘)构建其工业 4.0 战略的基石。
云 vs 设备上 AI?也许介于两者之间!
只有在需要放在云上的时候,才把你的 AI 放在云上。
云还是设备智能?或者介于两者之间?在这篇短文中,我们展示了一种简单的移动设备和云之间的协作方法如何帮助您将 50%的宝贵数据卸载到云中,同时实现相同的云级准确性。
云与设备上人工智能:利弊
让我们回顾一下云与设备上人工智能的利弊。设备上的人工智能通过提供更好的隐私和独立于远程资源而使我们受益,但由于缺乏强大的计算资源,该模型可能不是非常准确。另一方面,云人工智能通过提供比移动设备上托管的模型更准确的模型而使我们受益,但需要持久的网络连接,这可能使其不可靠。
云与设备上人工智能的利弊。作者照片。
只在需要使用云 AI 的时候使用云 AI
该方法基于对神经网络的置信度设置阈值。如果网络对它的预测有信心,那么我们就没事了,如果没有,我们需要向更智能的云托管模型寻求帮助!假设您想要对 ImageNet 数据集的 1000 个对象进行分类。假设我们使用 MobileNetV2 作为移动设备上的轻量级模型,使用 ResNext101 作为我们最精确的(但是很大!)云上的模型。方法很简单:
嘿手机!如果你对自己的预测不确定,就把推理卸载到云上吧!
如果你对自己的预测不确定,就把推理卸载到云上吧!作者照片。
我们将 softmax 概率视为预测的置信水平,并在移动预测的置信水平上设置阈值。我们在 ImageNet 上使用 torchvision 预训练模型,对于 MobileNetV2 和 ResNext101 分别有 71.88%和 79.31%的准确率。
该曲线示出了分类准确度相对于决定在移动设备上推断的测试输入的百分比。作者照片。
**曲线解读:**如果所有推理案例都在云服务器上进行,那么准确率将为 79.31%,这是 ResNext101 的准确率。如果所有的推理案例都在移动设备上进行,那么准确率将是 71.88%。如果 49.88%的推理案例在移动设备上执行,其余的在云上执行,那么我们仍然可以实现 79.31%的云级准确率。
简而言之,我们并不总是需要云服务器来为我们的应用程序添加人工智能。我们可以在弱设备上托管小模型,并在预测不确定的情况下调用云服务器。校准神经网络的置信水平可以进一步增加本地执行的推理案例的百分比。
作者要感谢 Mohammad Saeed Abrishami 在这篇博文中的帮助。
Cloudera 认证数据分析师(CCA 159)-指南
Cloudera 是数据分析领域最知名的公司之一。他们提供服务,尤其是在大数据领域,被认为是主要参与者之一。几乎所有的职业都有各自领域的相关证书。认证本质上是证明你是该领域的专家。来自最高权威的认证在简历上很重要,招聘人员总是试图找到有认证的人。像所有其他科技公司一样,Cloudera 提供了一系列大数据分析相关技术的认证。他们的考试都是全动手,在业内口碑极好。
Cloudera 认证数据分析师(CCA 159)是主流大数据工具(如 Apache Hive 和 Apache Impala)的基础考试。本指南适用于任何准备注册 CCA 159 考试的人。我假设您已经对 Cloudera 的生态系统有了一些经验。如果没有,我会鼓励你练习使用 Cloudera 的 quickstart VM ,可以在他们的网站上下载。最后我会写下一些免费的资源做准备。我按照我认为最适合准备的顺序写下这些步骤。
为了了解你将要进入的领域,请访问 Cloudera 网站上的 CCA 主页并仔细阅读。你将了解教学大纲、考试时间等。需要记住的一些重要事项是:
- 考试代金券价格 $295 (自购买之日起一年内有效)。
- 持续时间为 120 分钟,您将在 Cloudera 提供的实时集群上解决8–12动手操作问题。
- 通过标准为 70 % ,CCA 证书的有效期为两年。
Cloudera 创建了一个免费视频课程,告诉你所有关于各种 Cloudera 考试的信息,并提供备考技巧。在这些视频中也有一些简单的问题场景。只需在 Cloudera 大学注册,然后在 Cloudera: CertPrep 101 注册
请务必阅读 CCA 主页上的常见问题部分。你会得到任何问题的答案。如果您有任何进一步的问题,也可以发电子邮件至 certification@cloudera.com。
我会建议在这个时候选择一个考试日期。这样你就会知道你有多少时间准备;所以,可以更好的规划。考试券可以用信用卡直接从 CCA 主页购买。只需点击购买按钮,将其添加到购物车并继续付款。
Cloudera 已经与examples local合作进行考试。所以,你也必须报名参加。很简单:你从 Cloudera 购买考试券,然后在exam local的监督下参加考试。记住你想。使用您在 Cloudera 网站上注册时使用的同一电子邮件地址。
通过 examslocal 选择考试的确切日期非常简单。搜索 CCA 认证,从下拉列表中选择 CCA 159,并选择所需的日期和时间。
****
CCA 考试是在线的,也就是说,你可以在任何地方使用带有网络摄像头和互联网连接的笔记本电脑参加考试。浏览 examslocal 上的FAQ和兼容性检查工具来检查您的笔记本电脑的兼容性。
备考
CCA 考试是实践性的,即你将执行考试中的任务,而不是回答多项选择题。对于 CCA 159,您必须拥有 Cloudera 生态系统的实际知识,特别是 Hive (HQL)、Impala (impala SQL)。你应该非常熟悉数据定义(DDL)、数据查询(DQL)、窗口函数、文件格式等概念。截止到教学大纲的最新变化,Cloudera 已经将 Sqoop 排除在 CCA 159 之外。考试相关信息可以在 CCA 159 主页找到。以下是一些免费的准备资源,供您参考:
- itversity’ s YouTube 播放列表(CCA 159——数据分析师)这是基于他们的 Udemy 课程。您可以免费观看视频,并使用 Cloudera 的 VM 进行练习。
- Packt 还有一个 CCA 159 课程,可以通过 Oreilly 获得。虽然 Oreilly 是一个付费服务,但你可以从他们的免费试用中受益。
- 样题可以看这个 YouTube 播放列表由 Hadoop pass。
- 考试时只能从蜂巢和黑斑羚的官方文档中获得帮助。强烈建议了解如何使用该文档。所以,你必须练习使用它。
- Cloudera 不为任何考试提供模拟考试设施。但是,有第三方网站提供模拟考试。这些都是付费服务,你应该在继续之前检查其真实性。
像这样的考试,时间管理是最重要的。大多数问题都很简单,但是你没有时间了,所以,请记住这一点。在考试期间把自己隔离起来,这样就没有外界的干扰,你可以真正集中注意力。参加考试后,您将在 3 天内通过电子邮件收到报告。成功完成后,将在一周内通过电子邮件收到数字证书和许可证号。
我希望这本指南能成为一个很好的资源。快乐学习!
Cloudera 的 CCA 175—2020 年更新:什么改变了,什么没有改变,以及如何准备考试
Cloudera 的 CCA-175 认证的新版本删除了所有的遗留工具,并将重点完全放在 Apache Spark 上
Cloudera 的标志
几周前,Cloudera 重新推出了他们的 Spark 和 Hadoop 开发人员考试(CCA 175),更新了考试环境和一系列考试内容的关键更新。
考试继续采用动手操作的方式,包括一组 8 至 12 项基于性能的任务,考生需要在 Cloudera Quickstart 虚拟机上使用命令行执行这些任务,并可以访问大多数大数据工具(Hive、Spark 和 HDFS 都可以通过相应的命令访问)。
如果您计划在接下来的几周内参加考试,以下是您在备考时需要记住的关键要素以及最重要的工具和功能:
这都是关于火花
由于某种原因,Cloudera 一直在 CCA 175 考试中给出至少两个与 Sqoop 相关的任务,直到 2019 年的最后几个月。尽管 Sqoop 在过去十年开始时被广泛使用,但几年来它更多的是一种遗留工具,只有非常有限的几家公司仍然希望应聘者熟悉它。
幸运的是,Cloudera 接受了提示,从考试中删除了与 Sqoop 相关的任务。与 Flume 相关的任务(不那么频繁)也被删除,使得考试完全集中在大数据最重要的工具 Apache Spark 的使用上。
2020 版本的关键更新是,Spark 2.4 现在默认在考试环境中提供(而不是 Spark 1.6),可以通过 Spark Shell(对于 Scala)和 Pyspark(对于 Python)访问,或者甚至可以通过 Spark-submit(如果您更喜欢在执行考试任务时使用脚本)访问。Spark 2.4 引入了一组非常有用的功能,使得在考试中表现良好变得更加容易,尤其是在处理 Avro 文件时。
熟悉 Hive 和 HDFS
考试中的某些任务仍然需要阿帕奇蜂巢和 HDFS 的基础知识。主要是,您需要熟悉使用与数据位置(如果要求您创建外部表)及其格式相关的不同选项创建 Hive 表的过程。
此外,在某些时候,考生将需要使用 HDFS 命令(主要是ls
和tail
)来确定输入数据的存储格式,并初步了解他们将处理的数据。
考试的新版本肯定是面向 Spark 的,但不知道基本的 Hive 和 HDFS 命令会让你付出多项任务的代价,并最终阻止你获得证书。
读取、处理、写入
考试的任务其实是同一个问题的不同版本。您必须使用 Spark 以某种格式(主要是文本或拼花)从 HDFS 读取数据,通过过滤器、映射、聚合和连接对其进行处理,然后以不同的格式并使用某种压缩编解码器将其写回 HDFS。
掌握这一过程将保证你在考试时有一个愉快的体验,因为你会被要求在不同的数据集上做多次。
时间管理也是一个重要的因素,所以确保在考试开始时阅读所有的任务,然后立即开始你最熟悉的任务。
总而言之,Cloudera 摆脱了传统技术,设计了一种面向 Spark 的考试,这种考试与当今时代的数据工程任务相关。虽然该考试不需要处理优化或高级 Spark 知识,但它仍然是证明一个人熟悉 Apache Spark 的好方法。
基于聚类的图像分割-Python
个人电脑:Flickr
理解图像分割
最近,我在进行一项图像分类任务,首先我想在将图像输入模型之前,从图像中捕捉感兴趣的区域。我尝试了一种称为基于聚类的图像分割的技术,它帮助我将模型性能提高了一定的水平。让我们看看它是什么和一些样本代码做集群分割,你可以在底部找到 Jupyter 笔记本。
什么是图像分割?
想象一下,你要过马路了,你过马路之前做了什么?
首先,你看到道路的两边,以确定接近的车辆和其他环境物体,然后你对接近速度进行一些惊人的估计,并决定何时以及如何过马路。所有这些都发生在很短的时间内,这是多么不可思议。
- 我们的大脑捕捉道路两边的图像
- 它检测道路上的车辆和其他物体
- 不仅在此之前检测它确定它检测的每个对象的形状==图像分割
我们的大脑是多么神奇,通过确定不同物体的形状,它能够在同一张快照中检测到多个物体。
让我进一步解释,假设我们有图像分类模型,它能够以超过 95%的准确率对苹果和橙子进行分类。当我们输入一个既包含苹果又包含橘子的图像时,预测精度会下降。随着图像中对象数量的增加,分类模型的性能会下降。这就是对象定位发挥作用的地方。
在我们检测图像中的对象并对其进行分类之前,模型需要理解图像中有什么,这就是图像分割有所帮助的地方。它为图像中的对象创建了一个像素级遮罩,这有助于模型在更精细的级别上理解对象的形状及其在图像中的位置。
对象检测与图像分割 PC:中型
细分的类型有哪些?
图像分割大致分为两大类。
- 语义分割
- 实例分割
检测到的对象—语义段—实例段 PC: mc.ai
在第一幅图像中,我们可以看到被检测的对象都是男性。在语义分割中,我们认为所有这些像素属于一类,所以我们用一种颜色来表示它们。另一方面,在实例分割中,那些像素属于同一类,但是我们用不同的颜色表示同一类的不同实例。
根据我们使用的方法,细分可以分为许多更窄的类别。
- 基于区域的分割
- 基于边缘检测的分割
- 基于聚类的分割
- 基于 CNN 的分割等等。
正如我在开头所承诺的,在本文中我只给出一个基于集群的分段的例子。
什么是基于聚类的细分?
回忆一下你对聚类算法的理解。聚类算法用于将彼此更相似的数据点从其他组数据点中更紧密地分组。
现在想象一个包含苹果和桔子的图像。苹果里的像素点大部分应该是红/绿,和橙色的像素值不一样。如果我们能把这些点聚集起来,我们就能正确地区分每个物体。这就是基于聚类的分段的工作方式。现在让我们看一些代码示例。
from skimage.io import imread
from skimage.color import rgb2gray
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from scipy import ndimage# Scaling the image pixels values within 0-1
img = imread('./apple-orange.jpg') / 255plt.imshow(img)
plt.title('Original')
plt.show()
个人电脑:Flickr
对于我们的肉眼来说,图像中有五个颜色段
- 苹果的绿色部分
- 橙子的橙色部分
- 苹果和橘子底部的灰色阴影
- 苹果顶部和右部的亮黄色部分
- 白色背景
让我们看看是否可以使用 scikit-learn 中的 KMeans 算法对它们进行聚类
# For clustering the image using k-means, we first need to convert it into a 2-dimensional array
image_2D = img.reshape(img.shape[0]*img.shape[1], img.shape[2])# Use KMeans clustering algorithm from sklearn.cluster to cluster pixels in image
from sklearn.cluster import KMeans# tweak the cluster size and see what happens to the Output
kmeans = KMeans(n_clusters=5, random_state=0).fit(image_2D)
clustered = kmeans.cluster_centers_[kmeans.labels_]# Reshape back the image from 2D to 3D image
clustered_3D = clustered.reshape(img.shape[0], img.shape[1], img.shape[2])plt.imshow(clustered_3D)
plt.title('Clustered Image')
plt.show()
哇,真管用!!!我们能够将所有五个部分聚集在一起。这就是聚类分割的工作原理。
有许多先进的技术,如 Mask R-CNN,可以进行更细粒度的分割。让我们在其他文章中看到这些主题。我希望您现在对图像分割有了一定程度的了解。
分类任务的先聚类后预测
如何在监督学习问题中利用无监督学习
介绍
监督分类问题需要一个数据集,该数据集具有(a)一个分类因变量(“目标变量”)和(b)一组独立变量(“特征”),这些变量可能(也可能不!)对预测班级有用。建模任务是学习将特征及其值映射到目标类的函数。这方面的一个例子是逻辑回归。
无监督学习采用没有标签的数据集,并试图在数据中找到一些潜在的结构。K-means 就是这样一种算法。在本文中,我将向您展示如何通过使用 k-means 发现数据集中的潜在“聚类”来提高分类器的性能,并使用这些聚类作为数据集中的新特征,或者按聚类对数据集进行分区,并在每个聚类上训练单独的分类器。
资料组
我们首先使用 sklearn 的 make_classification 实用程序生成一个 nonce 数据集。我们将模拟一个多类分类问题,并生成 15 个用于预测的特征。
from sklearn.datasets import make_classificationX, y = make_classification(n_samples=1000, n_features=8, n_informative=5, n_classes=4)
我们现在有一个 1000 行的数据集,有 4 个类和 8 个特征,其中 5 个是信息性的(另外 3 个是随机噪声)。为了便于操作,我们将这些转换成熊猫数据帧。
import pandas as pddf = pd.DataFrame(X, columns=['f{}'.format(i) for i in range(8)])
分为训练/测试
现在,我们可以将数据分为训练集和测试集(75/25)两部分。
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(df, y, test_size=0.25, random_state=90210)
应用 K-均值
首先,您将想要确定给定数据集的最佳 k 。
为了简洁起见,也为了不偏离本文的目的,我向读者推荐这篇优秀的教程:如何确定 K-Means 的最优 K?如果你想进一步了解这件事。
在我们的例子中,因为我们使用了 make_classification 实用程序,所以参数
n_clusters_per_class
已经设置,默认为 2。因此,我们不需要确定最优的k;然而,我们确实需要识别集群!我们将使用以下函数来查找训练集中的 2 个分类,然后为我们的测试集预测它们。
import numpy as np
from sklearn.cluster import KMeans
from typing import Tupledef get_clusters(X_train: pd.DataFrame, X_test: pd.DataFrame, n_clusters: int) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
applies k-means clustering to training data to find clusters and predicts them for the test set
"""
clustering = KMeans(n_clusters=n_clusters, random_state=8675309,n_jobs=-1)
clustering.fit(X_train)
# apply the labels
train_labels = clustering.labels_
X_train_clstrs = X_train.copy()
X_train_clstrs['clusters'] = train_labels
# predict labels on the test set
test_labels = clustering.predict(X_test)
X_test_clstrs = X_test.copy()
X_test_clstrs['clusters'] = test_labels
return X_train_clstrs, X_test_clstrsX_train_clstrs, X_test_clstrs = get_clusters(X_train, X_test, 2)
我们现在有了一个新的特性,叫做“集群”,值为 0 或 1。
缩放比例
在我们拟合任何模型之前,我们需要缩放我们的特征:这确保所有的特征都在相同的数字尺度上。对于像逻辑回归这样的线性模型,在训练期间学习的系数的大小将取决于特征的尺度。如果您有 0-1 范围内的要素,而其他要素的范围为 0-100,则无法可靠地比较这些系数。
为了扩展这些特征,我们使用下面的函数来计算每个特征的 z 分数,并将训练集的学习映射到测试集。
from sklearn.preprocessing import StandardScalerdef scale_features(X_train: pd.DataFrame, X_test: pd.DataFrame) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
applies standard scaler (z-scores) to training data and predicts z-scores for the test set
"""
scaler = StandardScaler()
to_scale = [col for col in X_train.columns.values]
scaler.fit(X_train[to_scale])
X_train[to_scale] = scaler.transform(X_train[to_scale])
# predict z-scores on the test set
X_test[to_scale] = scaler.transform(X_test[to_scale])
return X_train, X_testX_train_scaled, X_test_scaled = scale_features(X_train_clstrs, X_test_clstrs)
我们现在准备运行一些实验!
实验
我选择使用逻辑回归来解决这个问题,因为它非常快,并且通过检查系数可以快速评估特征的重要性。
为了运行我们的实验,我们将在 4 个数据集上构建逻辑回归模型:
- 没有聚类信息的数据集(基本)
- 以“聚类”为特征的数据集(聚类-特征)
- df 的数据集[“群集”] == 0(群集-0)
- df 的数据集[“群集”] == 1(群集-1)
我们的研究是 1x4 组间设计,以数据集[基础、聚类特征、聚类-0、聚类-1]为唯一因素。下面创建我们的数据集。
# to divide the df by cluster, we need to ensure we use the correct class labels, we'll use pandas to do that
train_clusters = X_train_scaled.copy()
test_clusters = X_test_scaled.copy()
train_clusters['y'] = y_train
test_clusters['y'] = y_test# locate the "0" cluster
train_0 = train_clusters.loc[train_clusters.clusters < 0] # after scaling, 0 went negtive
test_0 = test_clusters.loc[test_clusters.clusters < 0]
y_train_0 = train_0.y.values
y_test_0 = test_0.y.values# locate the "1" cluster
train_1 = train_clusters.loc[train_clusters.clusters > 0] # after scaling, 1 dropped slightly
test_1 = test_clusters.loc[test_clusters.clusters > 0]
y_train_1 = train_1.y.values
y_test_1 = test_1.y.values# the base dataset has no "clusters" feature
X_train_base = X_train_scaled.drop(columns=['clusters'])
X_test_base = X_test_scaled.drop(columns=['clusters'])# drop the targets from the training set
X_train_0 = train_0.drop(columns=['y'])
X_test_0 = test_0.drop(columns=['y'])
X_train_1 = train_1.drop(columns=['y'])
X_test_1 = test_1.drop(columns=['y'])datasets = {
'base': (X_train_base, y_train, X_test_base, y_test),
'cluster-feature': (X_train_scaled, y_train, X_test_scaled, y_test),
'cluster-0': (X_train_0, y_train_0, X_test_0, y_test_0),
'cluster-1': (X_train_1, y_train_1, X_test_1, y_test_1),
}
“基础”数据集
“聚类-特征”数据集
“0 类”数据集
“聚类-1”数据集
为了有效地运行我们的实验,我们将使用下面的函数,该函数遍历 4 个数据集,并在每个数据集上运行 5 重交叉遍历。对于每个数据集,我们获得每个分类器的 5 个估计值:准确度、加权精度、加权召回率和加权 f1。我们将绘制这些图来观察总体性能。然后,我们从每个模型各自的测试集上获得分类报告,以评估细粒度的性能。
from sklearn.linear_model import LogisticRegression
from sklearn import model_selection
from sklearn.metrics import classification_reportdef run_exps(datasets: dict) -> pd.DataFrame:
'''
runs experiments on a dict of datasets
'''
# initialize a logistic regression classifier
model = LogisticRegression(class_weight='balanced', solver='lbfgs', random_state=999, max_iter=250)
dfs = []
results = []
conditions = []
scoring = ['accuracy','precision_weighted','recall_weighted','f1_weighted']for condition, splits in datasets.items():
X_train = splits[0]
y_train = splits[1]
X_test = splits[2]
y_test = splits[3]
kfold = model_selection.KFold(n_splits=5, shuffle=True, random_state=90210)
cv_results = model_selection.cross_validate(model, X_train, y_train, cv=kfold, scoring=scoring)
clf = model.fit(X_train, y_train)
y_pred = clf.predict(X_test)
print(condition)
print(classification_report(y_test, y_pred))results.append(cv_results)
conditions.append(condition)this_df = pd.DataFrame(cv_results)
this_df['condition'] = condition
dfs.append(this_df)final = pd.concat(dfs, ignore_index=True)
# We have wide format data, lets use pd.melt to fix this
results_long = pd.melt(final,id_vars=['condition'],var_name='metrics', value_name='values')
# fit time metrics, we don't need these
time_metrics = ['fit_time','score_time']
results = results_long[~results_long['metrics'].isin(time_metrics)] # get df without fit data
results = results.sort_values(by='values')
return resultsdf = run_exps(datasets)
结果
让我们画出我们的结果,看看每个数据集如何影响分类器的性能。
import matplotlib
import matplotlib.pyplot as plt
import seaborn as snsplt.figure(figsize=(20, 12))
sns.set(font_scale=2.5)
g = sns.boxplot(x="condition", y="values", hue="metrics", data=df, palette="Set3")
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.title('Comparison of Dataset by Classification Metric')
pd.pivot_table(df, index='condition',columns=['metrics'],values=['values'], aggfunc='mean')
一般来说,我们的“基本”数据集,没有聚类信息,创建了性能最差的分类器。通过添加我们的二进制“集群”作为特性,我们看到了性能的适度提升;然而,当我们在每个集群上安装一个模型时,我们会看到最大的性能提升。
当我们查看用于细粒度性能评估的分类报告时,画面变得非常清晰:当数据集按集群分段时,我们看到了性能的大幅提升。
base
precision recall f1-score support
0 0.48 0.31 0.38 64
1 0.59 0.59 0.59 71
2 0.42 0.66 0.51 50
3 0.59 0.52 0.55 65
accuracy 0.52 250
macro avg 0.52 0.52 0.51 250
weighted avg 0.53 0.52 0.51 250
cluster-feature
precision recall f1-score support
0 0.43 0.36 0.39 64
1 0.59 0.62 0.60 71
2 0.40 0.56 0.47 50
3 0.57 0.45 0.50 65
accuracy 0.50 250
macro avg 0.50 0.50 0.49 250
weighted avg 0.50 0.50 0.49 250
cluster-0
precision recall f1-score support
0 0.57 0.41 0.48 29
1 0.68 0.87 0.76 30
2 0.39 0.45 0.42 20
3 0.73 0.66 0.69 29
accuracy 0.61 108
macro avg 0.59 0.60 0.59 108
weighted avg 0.61 0.61 0.60 108
cluster-1
precision recall f1-score support
0 0.41 0.34 0.38 35
1 0.54 0.46 0.50 41
2 0.49 0.70 0.58 30
3 0.60 0.58 0.59 36
accuracy 0.51 142
macro avg 0.51 0.52 0.51 142
weighted avg 0.51 0.51 0.51 142
考虑类别“0”,跨四个数据集的 f1 分数为
- 基数—“0”F1:0.38
- 聚类特征—“0”F1:0.39
- 群集-0—“0”F1:0.48
- 群集 1—“0”F1:0.38
对于“0”类,在 cluster-0 数据集上训练的模型显示 f1 分数比其他模型和数据集相对提高了约 23%。
结论和下一步措施
在本文中,我展示了如何利用“先聚类后预测”来解决分类问题,并梳理了一些表明这种技术可以提高性能的结果。在集群创建和结果评估方面,还有很多工作要做。
在我们的例子中,我们有一个包含两个集群的数据集;然而,在您的问题中,您可能会发现更多的集群。(一旦您在数据集上使用肘方法确定了最佳 k !)
在 k > 2 的情况下,您可以将“clusters”特性视为分类变量,并应用一键编码在您的模型中使用它们。随着 k 的增加,如果您决定为每个集群拟合一个模型,您可能会遇到过度拟合的问题。
如果您发现 K-Means 没有提高您的分类器的性能,也许您的数据更适合另一种聚类算法——参见本文介绍不平衡数据集上的层次聚类。
和所有数据科学问题一样,实验,实验,实验!对不同的技术进行测试,让数据指导您的建模决策。
参考
python 中统计计算的数据结构,McKinney,第 9 届科学中的 Python 会议录,第 445 卷,2010 年。
@software{reback2020pandas,
author = {The pandas development team},
title = {pandas-dev/pandas: Pandas},
month = feb,
year = 2020,
publisher = {Zenodo},
version = {latest},
doi = {10.5281/zenodo.3509134},
url = {https://doi.org/10.5281/zenodo.3509134}
}
Harris,C.R .,Millman,K.J .,van der Walt,S.J .等人用 NumPy 进行数组编程。自然 585,357–362(2020)。DOI:10.1038/s 41586–020–2649–2。
sci kit-learn:Python 中的机器学习,Pedregosa 等人,JMLR 12,第 2825–2830 页,2011 年。
J. D. Hunter,“Matplotlib:2D 图形环境”,科学计算&工程,第 9 卷,第 3 期,第 90–95 页,2007 年。
瓦斯科姆,法学硕士,(2021 年)。seaborn:统计数据可视化。《开源软件杂志》,6 卷(60 期),3021 页,https://doi.org/10.21105/joss.03021
将您在 Spotify 上保存的歌曲分成相似歌曲的播放列表
探索音频特征,对情绪进行分类,并建立机器学习方法
答几周前,我偶然看到一篇有趣的文章,题为“使用 Spotify API 和 Python 进行音乐品味分析”。在这篇文章中,作者试图分析他和未婚妻的偏好,以确定数据对此有何说明。因此,他同时比较了 Spotify 的 API 提供的两种不同的音乐特征。在阅读它的时候,我很好奇,不仅分析了我自己的偏好,还玩了我的 Spotify 数据。因此,我想将我在 Spotify 上保存的歌曲集中到单独的播放列表中,这些播放列表将代表我在听这些歌曲时的特定心情。
所以为了完成我的任务,我把我的目标分成几个独立的任务:
- 获取数据
- 构建聚类模型
- 找出一个合适的分类器,并根据获得的数据进行训练
- 对我的歌曲进行分类,并将其分成播放列表
- 将建议分类
首先,值得一提的是,Twitter、Slack 和脸书 Spotify 也为开发者提供了一个 API,用于探索他们的音乐数据库,并深入了解我们的收听习惯。它提供了各种各样的功能;然而,我用了 8 个特征来描述一首歌。
- 声学值:描述一首歌曲的声学程度。
- 可跳舞性 值: " 描述了一首曲目根据音乐元素(包括速度、节奏稳定性、节拍强度和整体规律性)的组合适合跳舞的程度。"因此,我决定不使用 tempo,因为我相信这个特征是从他们那里得到的。
- 活跃度值: “描述歌曲被现场观众录制的概率”。
- **能量值:**代表强度和活跃度的感知度量。通常,充满活力的曲目感觉起来又快又吵。
- 乐器性值:“预测音轨是否不包含人声。”在这种情况下,“Ooh”和“aah”音被视为乐器声。Rap 或口语词轨道明显是“有声的”。“乐器度”值越接近 1.0,轨道不包含声乐内容的可能性就越大。”
- **响度值:**显示音乐的音量有多大。
- 语音值: “检测音轨中是否存在语音单词。”
关于所提供的不同功能的更多信息: 获取音轨的音频功能| Spotify for Developers
实验装置
当我提到每个特征所代表的含义时,我想强调一下我在聚类任务中使用的数据集。聚类将使用 KMeans 聚类算法导出,该算法在 Kaggle 上找到的 Spotify 数据集 1921–2020 上进行了训练。Spotify 数据集 1921–2020 包含从 Spotify Web API 收集的超过 160 000 首歌曲,您还可以在数据部分找到按艺术家、年份或流派分组的数据。
正常化响度
考虑到提到的所有其他特征都具有范围为[0,1]的值,重要的是将响度值的范围从 0 降低到-60 dB。因此,我使用 sklearn MinMaxScaler 将响度特性标准化,使其值介于 0 和 1 之间。
****from** **sklearn** **import** preprocessing
scaler=preprocessing.MinMaxScaler() *#instantiate a scaler*
*#all the feature values are in the range [0,1] ,except of loudnes*
*#so let's scale it to fit the exact same range*loudness=X["loudness"].values
loudness_scaled=scaler.fit_transform(loudness.reshape(-1, 1))**
调整 K-均值聚类算法
我最终使用了 K-Means 聚类算法,该算法用于确定数据的分布。它是一种无监督学习算法,通过计算到质心的距离将相似的数据点分组到 k 组。为了达到这个目标,它寻找预定数量( k )的聚类。
**为了得出一个合适的 k 值,我用了一个众所周知的方法叫做**肘法。因此,通过对 k 的范围(例如1–20)运行 K 均值,我们可以得到下图:
如果我们将碎石图视为一座山,我们需要找出一个点,在那里我们的“山”结束,而“碎石”开始,因为直到该点,我添加的每个聚类的方差都有一个实质性的减少,在该点之后,有一个边际减少。因此,对于我的情况来说,值 5 似乎是最佳的。但也不是完全生动,所以有时候可以由一个人来决定。
使用主成分分析描述和可视化聚类
考虑到我们的聚类任务使用了 8 种不同的特征,很难将数据可视化。因此,有一些常用的技术来降低数据的维度。我使用了主成分分析(PCA ),它降低了维数,但仍然保留了重要的信息。PCA 同样用于加速学习过程;然而,我不打算在这篇文章中深究细节。
使用 KMeans 获得的聚类
上图显示了我们在 2 维空间中的 5 个集群。很明显,群集 0 可能很难与群集 2 和 1 区分开。同时,衍生出的其他聚类之间也存在明显的差异。
- 因为所有歌曲的平均值是 0.87,所以聚类 0 在语音方面非常高。如果一首歌曲的语音度高于 0.66,它可能是由口语词组成的,0.33 到 0.66 之间的分数是一首可能同时包含音乐和词的歌曲,而低于 0.33 的分数意味着这首歌曲没有任何语音。此外,它的工具性较低,但舞蹈性相当高。我想大部分是说唱歌曲。
- 集群 1 的可舞性和能量相对较高,但工具性较低。我期待在那里看到很多充满活力的歌曲。
- 集群 2 音响性很高,但乐器性和响度较低。此外,它还具有相当高的可跳性。所以,我期待看到更平静,或许悲伤的歌曲。
- 第 3 簇的声音和乐器性最高,但语音最低。
- 第 4 组乐器性和能量相当高,可舞性一般。同样,它的语速也相对较低。
识别最佳分类器
考虑到我们获得了标签作为我们的聚类,我们可以轻松地实现一个分类算法,这将有助于对我们在 Spotify 上保存的歌曲进行分类。此外,它将允许我们对推荐的歌曲进行分类,并将它们分成不同的播放列表。
重要提示:同样,只有一个响度特征是用相同的定标器归一化的;然而,重要的是要注意,我们需要使我们的定标器只适合于训练集,并对测试集和训练集都应用转换,以避免数据泄漏。在这篇文章中,我不打算深究细节。
**X_train[:,5]=scaler.fit_transform(X_train[:,5].reshape(-1, 1)).reshape(-1,)
X_test[:,5]=scaler.transform(X_test[:,5].reshape(-1, 1)).reshape(-1,)**
根据准确率得分比较了四种模型,分别是 K 近邻分类器、随机森林分类器、支持向量分类器和朴素贝叶斯。支持向量分类器被证明是在准确性分数方面最好的模型,其组成大约为 0.998,因此我们将使用它来进行未来的分类。
SVC 显示的混淆矩阵
预测我在 Spotify 上保存的歌曲
Spotify 的 API 提供了一套有用的功能。因此,我们能够获得我们保存的所有歌曲的数据集。所以,我会用上面提到的分类器对我喜欢的歌进行分类。最后,我们将我的歌曲分成 5 个不同的播放列表,并尝试分析它们。
**offset = 0
songs = []
names = []
ids = []
**while** **True**:
content = sp.current_user_saved_tracks(limit=50, offset=offset)
songs += content['items']
**if** content['next'] **is** **not** **None**:
offset += 100
**else**:
**break**
**for** i **in** songs:
names.append(i['track']['name'])
ids.append(i['track']['id'])
index=0
audio_features=[]
**while** index < len(ids):
audio_features += sp.audio_features(ids[index:index + 50])
index += 50
features_list = []
**for** features **in** audio_features:
features_list.append([features['acousticness'], features['danceability'],
features['liveness'],features['energy'],
features['instrumentalness'], features['loudness'],
features['speechiness']])
mydf = pd.DataFrame(features_list, columns=["acousticness", "danceability", "liveness","energy", "instrumentalness", "loudness", "speechiness"],index=ids)**
分类歌曲
上图显示了我喜欢的歌曲使用 SVC 分类。最后,我听了每个集群的歌曲列表,得出了以下解释:
- 正如我所料,绝大多数歌曲都是说唱歌曲。因此,如果我想听一些激进的说唱来振奋我的精神,我会听他们。
示例:
- 集群 1 包含大部分精力充沛且适合跳舞的歌曲。
示例:
有趣的是,肖恩·蒙德兹的所有歌曲都属于这一类。
- Cluster 2 由很多缓慢而平静的歌曲组成。因此,我给它贴上平静或浪漫音乐的标签。
示例:
我保存的 Joji 的歌几乎都属于这一类,在我看来已经足够公平了。
- 集群 3 包含了很多通常没有歌词的歌曲。如果我想集思广益或学习,我会听他们。
示例:
- 第四组主要是一些令人放松的歌曲。
示例:
现在让我们分析一下我对 Spotify 上音乐的偏好。
上图展示了我喜欢的歌曲数据集中使用的所有特征的平均值。因此,我推断我通常会听一些可舞性和能量都很高的歌曲。我从未想到过那件事,但现在我意识到那确实是真的。然而,我也时不时听听浪漫的,也许是悲伤的歌曲。
上面的饼状图证明了我喜欢的歌曲中有 80%属于活力/舞曲类。
最后,我把我的歌分成 5 个不同的播放列表,代表这些类别。
**clustered_songs=list(zip(mydf.index,mydf.iloc[:,-1]))sorted_songs=[[],[],[],[],[]]
**for** i **in** range(len(clustered_songs)):
sorted_songs[clustered_songs[i][1]].append(clustered_songs[i][0])playlists=[]
**for** i **in** range(5):
playlist_created=sp.user_playlist_create(username, name="Cluster "+str(i), public=**False**,description='')*#create playlists for a corresponding cluster*
sp.user_playlist_add_tracks(username,playlist_created['id'],sorted_songs[i][:100]) *#add new songs*
playlists.append(playlist_created)**
对推荐歌曲进行分类
作为我们实验的最后一步,我将请求根据我保存的歌曲生成 Spotify 推荐。
**rec_tracks = []
**for** i **in** mydf.index.tolist():
rec_tracks += sp.recommendations(seed_tracks=[i], limit=5)['tracks'] *#get recommendations from Spotify*
rec_track_ids = []
rec_track_names = []
**for** i **in** rec_tracks:
rec_track_ids.append(i['id']) *#extract id and name of songs*
rec_track_names.append(i['name'])
rec_features = []
**for** i **in** range(0,len(rec_track_ids)):
rec_audio_features = sp.audio_features(rec_track_ids[i]) *#extract features*
**for** track **in** rec_audio_features:
rec_features.append(track)
rec_playlist_df = pd.DataFrame(rec_features, index = rec_track_ids) *#make a dataframe***
最后,我对我获得的所有歌曲进行分类,并通过添加新的推荐歌曲来更新我创建的播放列表。让我们看看获得的歌曲是否符合我们的播放列表。
新增
集群 0:
集群 1:
有趣的是,还增加了几首法国歌曲。我认为那是他的风格。
集群 2:
尽管这是一首说唱歌曲,但风格和音乐符合播放列表。
集群 3:
集群 4:
注意:使这个集群不同于上面列出的其他两个集群的特征是它的低速度。
结论
总而言之,这些推荐是基于我保存的所有曲目的数据集(而不是基于单个播放列表)生成的。因此,我相信一个分类器可以很好地将它们分成 5 个不同的播放列表。我认为这项工作非常有趣,对于刚刚开始旅程的人来说是很好的实践,因为它同时包括了 ML 的各个领域。在这项工作中,我在公共 Spotify 数据集上训练了 KMeans 聚类算法。此外,我想出了一个分类器,帮助我将喜欢的歌曲分类到播放列表中,每个播放列表代表一种独特的风格/情绪。
源代码在我的 Github 上有。
创建了指向我的播放列表的链接
- 【https://open.spotify.com/playlist/6dL6xOCcema8DUSzYLfx06】集群 0(说唱):
- Cluster1(活力/舞蹈):https://open.spotify.com/playlist/0LlIHqBd2zOHemZ3c7j6Ov
- Cluster2(冷静/浪漫):https://open.spotify.com/playlist/4mF1KkRP5YITPTf1dakXJP
- 集群 3(学习/思考):https://open.spotify.com/playlist/4xRgEf6Y4iBs3I3WNNofMr
- Cluster4(寒气)【https://open.spotify.com/playlist/5FtCtZ5QrpQDlXxIB9DMEi】:
参考文献:
****[## 重定向你-媒体
编辑描述
medium.com](https://medium.com/r?url=https%3A%2F%2Ftowardsdatascience.com%2Fa-music-taste-analysis-using-spotify-api-and-python-e52d186db5fc)**** **** [## 我的 Spotify 音乐很无聊吗?涉及音乐、数据和机器学习的分析
使用 Spotify 的音频功能 API、数据和机器学习,我调查了我保存的歌曲有多无聊。
towardsdatascience.com](/is-my-spotify-music-boring-an-analysis-involving-music-data-and-machine-learning-47550ae931de) [## 通过 Python 提取您最喜欢的艺术家的 Spotify 数据
Spotify 是世界上最受欢迎的流媒体平台之一。他们也有一个 API 供开发者使用…
medium.com](https://medium.com/@RareLoot/extracting-spotify-data-on-your-favourite-artist-via-python-d58bc92a4330) [## 获取音轨的音频功能|面向开发者的 Spotify
需要路径参数授权。来自 Spotify 帐户服务的有效访问令牌:参见 Web API…
developer.spotify.com](https://developer.spotify.com/documentation/web-api/reference/tracks/get-audio-features/)****
簇状和重叠条形图
为什么和如何
图片由来自 Unsplash 的 Suyehon Choi 提供
1.- 簇状条形图
又名:分组、并排、多集[条形图、条形图、柱形图]
为什么:聚类条形图(CBC)显示一个主要类别和属于第二分类变量的子类别之间的相对比例的数字信息。类似于堆积条形图,它们应该用于比较和比例,但重点是组成。与堆叠条形图不同,构成子类别的元素可能是广泛相关的。当一个整体被分成多个部分时,CBC 特别有效。它们能够在子类别之间进行比较,而堆叠条形图在子类别内进行比较**。**
它们允许可视化子组如何随时间变化,但是随着时间的延长和子类别数量的增加,图表变得难以阅读。它们不应用于关系或分布分析。
如何:和条形图一样,CBC 是二维的,有两个轴:一个轴显示类别,另一个轴显示数值。指示类别的轴没有刻度来突出它指的是离散的(互斥的)组。带有数值的轴必须有一个带有相应测量单位的刻度。
CBC 由多组矩形条表示,这些矩形条可以水平或垂直定向。每个主要类别被分成代表第二分类变量的子类别的条簇和。每个子类别的数量由那些并排放置形成一个簇的矩形条的长度或高度来表示,簇之间的间隙比单个标准条稍宽。
图 1:簇状条形图的示意图。该图形是用 Matplotlib 开发的。
子类别可以是顺序的或名词性的,但同等的子类别在每个聚类中必须有相同的颜色,以免混淆观众。使用合适的调色板、平衡的间距和便于比较的布局是很重要的。因为横条是沉重的视觉标记,仅仅为了改善故事情节,尽量少用网格线。
下图显示了 2016-2019 年期间与销售、费用和利润相关的公司业绩数据。这是一个垂直方向的簇状条形图,以年份作为主要类别。销售额、费用和利润每年表示为一个群集。可视化清晰地突出了 2018 年,即使在费用增加和销售额减少的情况下,利润仍保持相对恒定。
图 2:一家虚构公司在 2016-2019 年期间的经济表现。该图形是用 Matplotlib 开发的。
比较用堆积条形图表示的相同数据是很有趣的。如前所述,当您想要跨子类别进行比较时,CBC 是合适的:2016 年与 2017 年的销售额,2018 年与 2019 年的销售额;2016 年相对于 2017 年相对于 2018 年相对于 2019 年的支出;2016 年与 2017 年、2018 年与 2019 年的利润。相反,堆积条形图只能对接近基线(销售)的部分进行比较,因为费用和利润有不同的初始基线。此外,每个主体条的高度(特定年份的销售总额+费用+利润)没有任何意义。
图 3:具有与图 2 相同数据的堆积条形图。
下一个数字与 2017 年欧盟高等教育统计(EU-28)有关。那一年有 1980 万高等教育学生,其中女性占 54%,尽管获得博士头衔的大多数学生是男性。此外,四分之一的学生从事商业、管理和法律研究。下面的柱状图表明,在教育、社会科学、艺术和人文科学、健康和福利以及商业、管理和法律研究领域,女性人数超过了男性。另一方面,在信息技术和工程、制造和建筑研究领域,男性人数超过女性(欧盟统计局,2020 年)。该图表清楚地显示了广泛教育领域中男女参与高等教育的数字信息。这是一个横向的 CBC,其中教育领域构成主要类别,而性别是第二分类变量。
图 3:2017 年欧洲联盟高等教育学生按领域和性别分布情况。来源(#1)
簇状条形图的主要问题是,它们不能清楚地显示单个部分相对于整体的比例。这样一来,比例就不好评价了。它们的强度与第二分类变量的等价子类之间的直接比较有关。
2.- 重叠条形图
又名:叠加、重叠、叠加【条形图、条形图、柱形图】
为什么:重叠条形图(OVC)用于不同项目或类别之间的比较。OVC 在一张图中对每个项目或类别只比较两个数字变量。数值变量必须密切相关,才能进行比较。它们也用于显示基于相似前提的长期趋势。它们不应用于关系或分布分析。
与 OVC 相关的概念想法是对比两个变量的数值,这两个变量相互重叠,允许用更大的阐释力来描述信息(讲故事)。从这个意义上说,它们比簇状条形图要好,因为这种比较直观上更优越。这种图表非常精确地显示了盈余和短缺,尤其是在添加了适当的网格后。它们通常用于显示相对于目标或基准的进展水平。
图 4:重叠条形图的示意图。该图形是用 Matplotlib 开发的
**How**: it is a two dimensional graph with two axis -similar to every standard bar chart- with rectangular bars that can be oriented horizontally or vertically**.** One axis shows categories, the other axis shows numerical values related with two variables. **Bars representing the same category share the same baseline and the same location on the corresponding axis**. Both numerical variables must be closely related and share the same numerical scale. The width of the bars is different for each numerical variable with the smaller going forward for clarity of reading. The drawback is that for some categories one of the bars is the shorter while it is the longer for others.
图 5:一家虚构公司在 2012 年至 2019 年期间的实际支出与预算支出。该图形是用 Matplotlib 开发的
一些可视化工具允许部分重叠几个数值变量(多个数据序列),这样代表每个连续数值变量的矩形被位于它们前面的其他矩形部分隐藏。从概念上讲,当代表不同数据集的矩形开始重叠而不是并排放置时,它们相当于聚类(分组)条形图。OVC 意味着一个矩形在另一个矩形前面 100%重叠的极端情况。毫无疑问,观众会发现很难对三个或更多部分重叠的条进行比较。当多个子类别的数据必须在单个图表中进行很长时间的比较时,使用它是合理的。
图 6:部分重叠的条形图,来源珀耳帖技术博客(#2)
总而言之,当你想对整体的各个部分进行直接比较时,你可能会使用一个簇状条形图。另一方面,重叠条形图能够很好地比较两个密切相关的数值变量。
和标准条形图一样,我为这两种类型的图表推荐以下提示和警告:
从 0 开始基线:如果条被截断,实际值不能正确反映;
当存在时序数据(时间序列、时间数据)或负数值时,建议采用垂直方向(柱形图)(图 2 和图 5)。另一方面,当绘制大量类别时,尤其是具有非常长的标签时,优选使用水平方向(图 3);
如果较长的条形图总是在较短的条形图后面,部分重叠的条形图只能显示一个好的信息;
避免所有 3D 效果。尽管它们在美学上令人愉悦,但它们违背了适当的数据可视化的所有规则。
如果你对这篇文章感兴趣,请阅读我以前的:
堆积条形图,为什么和如何,讲故事和警告
讲故事和警告
towardsdatascience.com](/stacked-bar-graphs-why-how-f1b68a7454b7)
参考文献:
# 1:https://EC . Europa . eu/Eurostat/statistics-explained/index . PHP/Tertiary _ education _ statistics # Fields _ of _ education
#2:珀尔帖科技博客,【https://peltiertech.com/stacked-vs-clustered/】
聚类算法。第二部分。
奥拉·米先科在 Unsplash 上拍摄的照片
更快、更聪明、更快乐…
扩展我之前的帖子并尝试解决这个问题,这个问题对于大多数传统的聚类算法来说太难了。
这篇文章在很大程度上遵循了我上一篇文章的思路,你可以在下面找到:
深入研究一种新的聚类识别方法。
towardsdatascience.com](/a-fresh-look-at-clustering-algorithms-c3c4caa1a691)
我在这里尝试做的是概括它(一点),加速它(很多!)并将其应用于一个数据集,该数据集会使大多数其他聚类算法脱轨。我还将强调这一过程中的一些挑战,并介绍一种新的预分析方法,它应该有助于选择问题的参数,以获得最佳结果。
系好安全带。这将是一段颠簸的旅程。
优化部分本身并不新鲜——我将在这里浏览一下,因为你可能会发现它很有用,并强调从经验中吸取的一些教训。如果您对此不感兴趣(或者如果您是专家),请直接跳到下一节,深入了解真正擅长颠覆经典聚类算法的数据集。在上一篇文章中,我对我的方法进行基准测试的九个算法都失败了。每一个。单身。一个。
优化代码
当我开始查看一个相当复杂和庞大的数据集时,对算法性能的真正测试开始了。这个数据集是伦敦市中心一平方公里的栅格文件表示,显示了不到 250 座(可识别的)建筑物。每个坐标有 4 个 ln 值,这给我的笔记本电脑带来了很大的压力,计算时间为 5 小时 47 分钟。一点都不好。不得不说,这个算法在这个阶段对于一个蛮力方法来说有点痛苦,所以我需要做一些改进。目前的版本能够在 4 分 40 秒内完成同样的计算。同样的笔记本电脑,没有并行化,只是改进了算法。
那么大部分的性能提升来自哪里呢?
该算法的核心是一个基本的 BFS 实现——在我们空间的图形表示中计算不相连的树。它遵循几个简单的步骤:
- 选择我们想要检查的节点的 id(在这个阶段任何 id 都可以)。
- 识别它的邻居,并检查它们是否属于阈值以上的节点集。
- 将邻居添加到“检查”列表中。
- 将当前节点标记为已访问。
- 更新 id 列表(删除所有“已访问”和“待检查”列表元素)
- 从“检查”列表中选择任意节点,并重复步骤 1-4。
我们这样做,直到“tocheck”列表为空,将所有“已访问”添加到集群字典,然后转到列表中的下一个 id(再次执行步骤 1)。
第一个主要的胜利来自于间歇性地去除了列表和 numpy 数组的使用,并且不得不从一个转换到另一个。当处理 4000 个点的数据集时,这并不是一个大问题,当处理 4,000,000 个点的数据集时,这就成了一个大问题。
所以我从中得到的主要教训是——尽量避免类型转换,至少在有潜在瓶颈的代码部分。这一变化导致了计算时间从的 5 小时 47 分下降到 29 分 37 秒。
第二个胜利来自于认识到,即使字典是处理图/树结构的一个相当明显和直观的选择,但在现实中它们是不必要的和耗费资源的。至少在这个算法的框架内。这都是因为我需要一个简单的 id 来处理每个单元格,并且需要一个简单的方法来识别最近的邻居。
如果你参考我以前的文章中的原始算法的主要步骤——我们采用一个包含所有输入参数的 numpy 数组,为了维护和计数所有的单元格,我们从它们中创建一个字符串 id,然后使用它作为检查一切的密钥。放弃字典也允许我们完全放弃对这些索引的需求。这实际上使整个算法更加通用,因为例如,如果我们想处理 word2vec 的文本表示,我们将得到 300 个维度,因为每个文本块(或单个单词)都由一个 300 长的浮点向量表示。现在想象一下,我们必须对每个维度进行 10 次以上的划分,然后将它们全部粘合到一个字符串 id 中。我们将以一个 600 字符长的字符串来表示每个观察结果。不太好。事实证明,我们可以通过使用原始的 numpy 数组、屏蔽和索引来完成整个计算和循环路径。这一变化带来了另一个重大胜利——从 29 分 37 秒缩短到不到 7 分钟。
最终的改进来自于一个非常小的变化,但仍然很重要。树计数过程的一部分涉及使用屏蔽来选择最近的邻居,然后将它们从仍然需要检查的元素数组中移除。这意味着同一个面具被使用了几次。只需将它传递到变量中,然后在多个需要的地方使用该变量,而不是在运行中进行计算,就又获得了 2 分钟的胜利,使最终执行时间达到 4 分 47 秒。
我们需要做的另一个重要改变是积分归属。我将再次向您推荐上一篇文章的内容,但简单地说,我们只使用通过阈值的细胞来构建我们的树结构。这意味着,一旦我们确定了我们的聚类,我们就剩下一大堆没有分配给任何聚类的点。一方面,我们可以让它们保持原样。另一方面,在某些情况下,我们希望将整个数据集划分到围绕集群创建的组中。在我以前的文章中,我通过识别每个聚类的质心,然后比较每个点到每个质心的距离,然后将其分配给最近的一个质心。这在大多数情况下都很好,我们看到结果非常接近 KMeans 算法获得的结果。然而,有一整类问题,这种方法是行不通的。出于这个原因,我们将转移到一个不同的方法,这是不太依赖于质心。具体来说,我们将查看到最近的标记邻居的距离。也就是说,我们将测量到每个聚类中所有已识别点的距离,看哪一个是最近的,然后分配给最近的一个。
所有的函数,包括两种属性方法都在本文的最后。
这意味着我们已经准备好解决我们原始 blobs 的一个更复杂的问题:
聚类算法禁区
剧透警告——不再是了:)。
经典数据集是简单的同心圆,它几乎颠覆了所有经典聚类算法。事实上,它是存在非线性边界的任何东西,所以在某种程度上,栅格文件簇识别已经是一个有效的例子。同心圆为我们提供了一个很好的简单示例,它还允许我们突出显示建筑物数据集因其规则模式而不会有的一些细微差别。但是我在这里跳向前。让我们从生成数据集开始,快速看一下标准算法是如何制作的。
我们首先加载需要的库:
%matplotlib inline
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
pd.plotting.backend='seaborn'
from IPython.display import clear_output
import time
注意,我们不再需要最新实现的 itertools
生成数据集:
N=4000 #number of observationsr = np.random.random(N) * 0.1 + 1
theta = np.random.random(N) * 2 * np.pi
x = r * np.cos(theta) + 5
y = r * np.sin(theta) + 5r = np.random.random(N) * 0.1 + 0.5
theta = np.random.random(N) * 2 * np.pi
x1=r * np.cos(theta) + 5
y1 = r * np.sin(theta) + 5r = np.random.random(N) * 0.1
theta = np.random.random(N) * 2 * np.pi
x2 = r * np.cos(theta) + 5
y2 = r * np.sin(theta) + 5r = np.random.random(N) * 0.1
theta = np.random.random(N) * 2 * np.pi
x3 = r * np.cos(theta) + 5.8
y3=r * np.sin(theta) + 5
所以我们正在创建两个圆形斑点和两个同心圆。
让我们快速浏览一下:
plt.figure(figsize=(10,10))
plt.scatter(x, y)
plt.scatter(x1, y1)
plt.scatter(x2, y2)
plt.scatter(x3, y3)
还要注意,外圆有相当多的不规则。这可能会给我们带来一些问题(剧透——会的)。
现在,让我们将所有这些组合成一个数据集并进行归一化:
ttf_circles = pd.DataFrame(
{
'x':np.concatenate([x, x1, x2, x3]),
'y':np.concatenate([y, y1, y2, y3])
}
)
ttf_norm = ttf_circles.copy()
ttf_norm['x'] = (
ttf_norm['x'] - np.min(ttf_norm.x)
) / (
np.max(ttf_norm.x) - np.min(ttf_norm.x)
)
ttf_norm['y'] = (
ttf_norm['y'] - np.min(ttf_norm.y)
) / (
np.max(ttf_norm.y) - np.min(ttf_norm.y)
)
快速浏览一下:
ttf_norm.plot(x='x', y='y', kind='scatter', figsize=(10,10))
您可以直接看到为什么这会给基于质心的归因带来问题。我们的三个星团的质心在同一个地方!
让我们首先来看看标准的、现成的方法是如何处理这个问题的。
import sklearn
from sklearn.cluster import AffinityPropagation, AgglomerativeClustering, Birch
from sklearn.cluster import DBSCAN, KMeans, MiniBatchKMeans, MeanShift
from sklearn.cluster import SpectralClustering
from sklearn.mixture import GaussianMixture
- 亲和力传播
X = np.array(ttf_norm[['x','y']].values)
model = AffinityPropagation(damping=0.9)
%%time
model.fit(X)
ttf_norm['Affinity'] = model.predict(X) + 1
出局:
CPU times: user 9min 18s, sys: 22.7 s, total: 9min 40s
Wall time: 9min 55s
并绘制结果:
哎唷…我的意思是——它很有色彩……但是完全没用。
#失败!
其他方法的代码是相同的,所以我只展示结果。
2.结块的
CPU times: user 8.2 s, sys: 804 ms, total: 9 s
Wall time: 9.04 s
我们有正确数量的集群(因为我们告诉它要寻找多少!),只是不是我们要找的人…
#失败!
3.桦树
CPU times: user 827 ms, sys: 50.7 ms, total: 877 ms
Wall time: 752 ms
与#2 相同。相同的结论:
#失败!
4.基于密度的噪声应用空间聚类
CPU times: user 382 ms, sys: 370 ms, total: 752 ms
Wall time: 865 ms
的确非常丰富多彩…只是对我们完全没用。
#失败!
5.KMeans
CPU times: user 662 ms, sys: 57.3 ms, total: 719 ms
Wall time: 366 ms
好吧,你明白了。让我们直接跳到高斯混合。这是我希望会比其他的好一点的一个,但是,唉,在 164 毫秒内,它达到了:
好,那么我们的密度树算法呢?请击鼓…
计算我们的部门数量:
D = int(np.sqrt(len(ttf_norm)))
D
出局:126
该模型运行时间为 374 毫秒,这已经足够了。然而,我们发现…
44 簇!
#失败!
或者是?或者说我们能做点什么吗?
事实上,如果我们仔细观察,这就是正在发生的事情:我们被问题的规模绊倒了。记得我提到过数据中的条纹会给我们带来一些问题。这就是了。我们正在识别由数据稀疏引起的数据中的不规则性。我们可能已经预料到了,因为我们已经尽我们的临界参数所允许的那样细化了。
现在,有没有一种方法可以确定(最好是一种自动化的方法)我们需要进行多少次划分才能得到我们想要的聚类类型。所以对于这样的问题,确定一组参数,让我们得到最细粒度和最小粒度的结果。
事实证明——确实有。
请记住,我们将所有东西都分割成单元,并计算落入每个单元的观察值的数量,以构建我们的聚类。我们可以看看这些划分是多么有效,我们的观察结果是如何被打包到我们的单位细胞中的。所以我们要看的是,有超过 10 个观察值的单胞,与只有一个观察值或根本没有观察值的单胞数量的比率。选择 10 有些武断,用这个数字来看看什么效果最好可能是有意义的,到目前为止,它对我测试的所有问题都足够好了。
我们将浏览多个部门,看看该比例如何变化:
prop=[]
for d in range(1, 500):
Xint = (X * d).astype(int)
unique, counts = np.unique(Xint, axis=0, return_counts=True)
prop.append(
len(
counts[counts > 10]
)/(
len(
counts[counts == 1]
) + len(Xint) - len(unique)
)
)
我在这里使用列表来收集结果,我很抱歉。这一点是快速的,但是的,真的应该翻译成 numpy。
让我们画出这个:
plt.figure(figsize=(12, 8))
plt.plot(list(range(1, 500)), prop)
啊哈!我们有两个峰值。一个 50 左右,一个 200 左右。确切的数字并不重要,我们想知道大概的数字。
只是检查一下:
np.argmax(prop)
出局:49
够近了。
这意味着我们有两个最佳区域。如果我们想尽可能地细化并识别我们观察到的所有聚集点,我们会选择 200。如果我们想要一个更广阔的画面,我们用 49。
然而,这还不完全是结束。我们还想确保我们的宽容也符合我们的意图。对于更广阔的前景,我们希望非常低,否则我们有被过度排斥小数量的单位细胞产生的额外缺口绊倒的风险。对于更详细的前景,我们希望精确,所以我们可能希望使用更高的数字。这部分,暂时来说,还是不够规定性。也许转换到精确计数而不是百分位数会使它更简单。在我的待办事项/实验清单上。
好的,那么如果我们用 50 个除法和第 10 个百分位数会发生什么?
%%time
D = 49
tolerance = 10
ttf_norm['density_trees'] = density_trees_fit_nn(np.array(ttf_norm[['x','y']].values), D, tolerance)
出局:
Processed 100.00% ids
4 clusters found
CPU times: user 76.7 ms, sys: 8.56 ms, total: 85.3 ms
Wall time: 80.7 ms
砰的一声。!!
其他器械包的临界分割值
看一下不同场景下的临界分割值图是有意义的,这样可以获得更多的直觉。
例如,如果我们通过在外环生成更多的数据点来增加外环的密度,会发生什么?理论上,随着我们逐渐填充更多的空间,这应该会使那里的迷你星团不那么明显。
让我们看看会发生什么:
N=4000 #numbner of observationsr = np.random.random(N * 4) * 0.1 + 1
theta = np.random.random(N * 4) * 2 * np.pi
x = r * np.cos(theta) + 5
y = r * np.sin(theta) + 5r = np.random.random(N) * 0.1 + 0.5
theta = np.random.random(N) * 2 * np.pi
x1=r * np.cos(theta) + 5
y1 = r * np.sin(theta) + 5r = np.random.random(N) * 0.1
theta = np.random.random(N) * 2 * np.pi
x2 = r * np.cos(theta) + 5
y2 = r * np.sin(theta) + 5r = np.random.random(N) * 0.1
theta = np.random.random(N) * 2 * np.pi
x3 = r * np.cos(theta) + 5.8
y3=r * np.sin(theta) + 5ttf_circles = pd.DataFrame(
{
'x':np.concatenate([x, x1, x2, x3]),
'y':np.concatenate([y, y1, y2, y3])
}
)ttf_norm = ttf_circles.copy()
ttf_norm['x'] = (
ttf_norm['x'] - np.min(ttf_norm.x)
) / (
np.max(ttf_norm.x) - np.min(ttf_norm.x)
)
ttf_norm['y'] = (
ttf_norm['y'] - np.min(ttf_norm.y)
) / (
np.max(ttf_norm.y) - np.min(ttf_norm.y)
)
好吧,很多代码。本质上,这与我们开始时所做的是一样的,但是当我们生成第一个圆时,我们将点数乘以 4。所以我们会有 4 倍多的观测值。
你看现在外环光滑多了…
临界分裂图变成了:
所以峰值现在移到了右边,max 现在是 86。第二个峰值仍然存在,在 200 左右,但不那么明显了。我们添加的观察越多,它就越不明显,最终会完全消失。
让我们也来看看我们在上一篇文章中看到的四个 blobs:
和临界分裂图:
Max 在这里不太明显,实际的绝对最大值是 45,但我们可能可以达到 80。事实上,在文章中我们使用了临界值 63,这显然已经足够好了。
最后是栅格文件数据集。伦敦市中心的像素化建筑:
因为我们有 4mln 个点,所以计算这个需要一点时间,但是我们可以增加步长使它更容易,所以我显示的结果是使用步长 10:
这个恰好很好很简单,临界除法参数恰好在 525 左右。我们在文章中使用了 501,这是我凭直觉得出的,而不是根据严格的计算得出的。现在,在我们开始之前,我们有了一个非常简单的方法来确定我们问题的正确粒度。
这种方法的好处是——现在我们可以测试数据中的条纹,并在试图找到正确的建模方法之前理解比例和联系。我们可以对任意数量的变量这样做。潜在地,这是非常强大的,可以节省很多时间。
正如我所承诺的,我在这里附上所有的主要功能。请随意使用和改进这些。如果你有一个有趣的项目/数据集,你想使用它,并希望我的投入-请让我知道,我不能保证我会接受它,但我会努力。如果你自己在用,请友好地引用这篇文章。谢谢!快乐聚类!
聚类算法:一站式商店
比较层次聚类、K 均值、K 中值、K 模式、K 原型、DB 扫描和混合高斯模型的快速指南
照片由来自 Pexels 的 Artem Beliakin 拍摄
说到集群,有这么多可供选择的方案。根据任务的不同,理解所有可用技术的结果如何以及为什么会有如此大的差异很容易让人感到困惑。考虑到聚类算法的非监督性质,可能很难区分哪种算法是最合适的。在这篇文章中,我试图揭穿他们之间的主要差异,并强调什么时候一个人可能更适合每项任务。
分层聚类
分层聚类可能是所有算法中最直观的,并且提供了很大的灵活性。
该算法
分层聚类是一种凝聚算法。本质上,在该过程的开始,每个数据点都在自己的群集中。使用相异度函数,该算法在数据集中找到最相似的两个点,并将它们聚集在一起。该算法像这样迭代运行,直到整个数据被聚类。此时,可以使用树状图来解释不同的聚类,并根据需要选择聚类的数量。
根据专门的维基百科页面的树状图示例
最适合…
- 分类数据
- 发现异常值和异常组
- 使用易读的树状图显示结果
- 灵活性,因为有不同的相异函数可用(即完全连锁、单连锁、平均连锁、最小方差等。)各自给出非常不同的结果
棘手的时候…
- 随着数据量的增加,它会变得非常耗费时间/资源,因为它会反复处理每个数据点,每次都会遍历整个数据集。分层聚类不能很好地扩展。
k 均值
K-Means 可能是最流行的聚类算法。由于这一点,以及它的简单性和扩展能力,它已经成为大多数数据科学家的首选。
该算法
用户决定结果聚类的数量(表示为 K)。k 个点被随机分配为聚类中心。从那里,该算法通过选择与该点的欧几里德距离最小的聚类,将数据集中的所有其他点分配给其中一个聚类。接下来,通过取每个点坐标的平均值来重新计算聚类中心。该算法将每个点重新分配给最近的聚类,并重复该过程,直到聚类收敛并且不再变化。
注意,由于随机初始化,结果可能取决于随机选择哪些点来初始化聚类。因此,该算法的大多数实现提供了以不同的“随机开始”多次运行该算法的能力,以便选择最小化这些点及其聚类中心的误差平方和(惯性)的聚类。
使用肘图,也很容易选择正确的集群数量(如果这不是由所涉问题预先确定的话)
我为说明目的而生成的肘图示例
最适合…
- 可能不需要聚类的可解释性的一般情况(即当用作监督问题的特征时)
- 大多数情况下,快速解决方案足以产生深刻见解的问题。K-Means 算法是相对高效的。
- 大数据问题,因为算法可以轻松扩展(scikit-learn 甚至提供了一个特别适合大量数据的小批量 K 均值版本
棘手的时候…
- 数据集包含许多分类变量。K-Means 倾向于聚集在分类变量周围(因为它们在标准化数据集中的方差相对较高)
- 离群值可能会严重扭曲聚类
k-中间值
如上所述,大量异常值的存在可能会显著阻碍算法的效率。
该算法
K-Means 使用聚类中每个点的平均值来计算每个聚类的中心。然而,平均值并不是一个稳健的指标。因此,异常值的存在会使中心偏向异常值。
K-Medians 基于与 K-Means 相同的算法,不同之处在于它不是计算给定聚类中所有点的坐标的平均值,而是使用中值。因此,聚类将变得更加密集,对异常值也更加稳健。
最适合…
- 创建紧密/密集的集群,对异常值具有鲁棒性
棘手的时候…
- 需要一个快速的解决方案,因为它不在 scikit-learn 支持的算法中(需要使用 PyClustering 或自定义代码来实现)
k 模式
当存在分类变量时,K-Means 的表现也不好。至于 K-中位数,存在一个实现来利用分类数据上的 K-均值的效率。
该算法
K-Means 计算两点之间的欧几里德距离,而 K-Modes 试图最小化不相似性度量:它计算不相同的“特征”的数量。使用模式代替手段,K-模式变得能够有效地处理分类数据
最适合…
- 当数据集只包含分类数据时
棘手的时候…
- 数据类型是混合的
- 不一致的重要特征。因为 K-Modes 简单地计算不相似性的数量,所以它与“特征”点不同的算法无关。如果给定的类别特别普遍,这可能会成为一个问题,因为算法在聚类时不会考虑它。
k 原型
K-Prototypes 扩展了 K-Means 和 K-Modes,特别适用于处理包含连续变量和分类变量的混合数据集。
该算法
为了处理分类变量和连续变量,K-Prototypes 使用了一个定制的相异度度量。要最小化的点到其聚类中心(其原型)的距离如下:
用于计算 K 原型中点/簇之间距离的等式
其中 E 是连续变量之间的欧几里德距离,C 是不同分类变量的计数(λ是控制分类变量在聚类过程中的影响的参数)。
最适合…
- 大型混合数据集(即超出了分层聚类的限制)
棘手的时候…
- 需要一个快速的解决方案,因为它不在 scikit-learn 支持的算法中(需要使用 PyClustering 或自定义代码来实现)
- 分类变量的权重可能不清楚
DB 扫描
创建 DB-Scan 是为了解决一个不同的集群问题。它将高密度的簇与低密度的簇隔离开来。
该算法
为了根据密度来划分集群,DB-Scan 首先将数据划分为 n 个维度。对于每个点,该算法在该点周围形成一个形状,计算落入该形状的其他观察值的数量。DB-Scan 迭代地扩展形状,直到某个距离内不再有点,记为 epsilon(为模型指定的参数)
最适合…
- 分离高密度和低密度的集群
- 隔离异常值
棘手的时候…
- 聚类具有相似的密度(因为算法分离密度)
- 数据具有高维性
高斯混合模型(GMM)
高斯混合模型是第一个“基于模型”的聚类算法。该领域仍然相对较新,但高斯混合模型在某些情况下显示出巨大的前景。
该算法
以前的算法将点“硬”分配给特定的聚类,而 GMM 将每个点“软”分配给多个聚类,其中每个分配由属于给定聚类的概率来定义。
该模型假设数据点是由混合高斯分布生成的,并试图使用期望最大化(EM)来找到后一种分布的参数。
使用贝叶斯信息标准(BIC),GMM 还可以找到最佳数量的聚类来最好地解释数据。
最适合…
- 当集群是“隐藏的”/不可直接观察的,并且诸如由其他模型提供的“球形表示”是不够的时,复杂的集群。GMM 提供了额外的灵活性,并且可以提供更加复杂/非线性的聚类。
棘手的时候…
- 处理大量数据(扩展性不好)
- 数据量非常有限(算法需要能够估计协方差矩阵)
总之,存在大量的可用聚类算法,甚至超出了本文快速介绍的范围。其中绝大多数都可以通过开源 python 库(即 Scikit-learn 的多样化选项)轻松访问。它们之间的选择并不总是显而易见的,但是每种技术都有特定的优缺点,应该相应地加以利用。
Scikit-learn 提供了对大多数聚类算法及其一些优点/缺点的很好的总结,以及对其中大多数算法的易于使用的实现。我强烈建议您查看 it ,进一步了解您可能需要的算法以及如何针对您的具体情况进行调整。
PS:我现在是柏克莱大学的工程硕士,我还在学习这方面的知识。如果有什么需要改正或不清楚的地方,请告诉我。你也可以在这里发邮件给我。
使用 INFORM 风险和新冠肺炎数据对国家进行聚类分析
老龄人口、共病和流动是决定国家对新冠肺炎脆弱性的关键因素
图片来源:freepik
作者:纳米塔·希巴&凯瑟琳·洛佩斯
新冠肺炎脆弱性相关风险
自 2020 年初以来,我们一直面临新冠肺炎疫情,它已经蔓延并影响到每个国家。 HDE (人道主义数据交换)产生了 INFORM (风险管理指数)新冠肺炎风险指数,以确定**“面临新冠肺炎健康和人道主义影响的国家,这些影响可能超出当前的国家应对能力,因此需要额外的国际援助”**。我们将这一综合风险指数与其他新冠肺炎数据(包括病例、检测、卫生能力和人口)结合在一起,以更好地了解不同国家的风险及其管理。
数据
我们使用了新冠肺炎的公共数据集列表,如下所示,我们包括了大约 180 个国家和每个国家大约 40 个不同的特征:
- 约翰·霍普斯金大学确诊病例、死亡病例、康复病例
- 测试数据来自我们的数据世界
- 来自世界人口统计的人口和人口密度数据
- 来自全球健康安全指数的健康能力得分,该指数是该国诊所、医院和社区中心的健康能力指数
- 通知来自人道主义数据交换的风险指数数据
基于主成分分析和自组织神经网络的数据预处理
我们在数据预处理中使用主成分分析(PCA)和自组织映射(SOM)来提取独立特征,并将高维数据可视化到低维表示上。
Principal Component Analysis (PCA) is a multivariate analysis technique to transform the original set of multiple features in the data into a smaller set of uncorrelated variables which account for the maximum variance in the data set, and are called principal components. Therefore, PCA is a dimensionality reduction technique for large datasets.
对于我们的数据,我们使用主成分分析来降低维数,同时仍然可以解释数据中 99%的方差。结果我们把变量的数量从 43 个减少到了 24 个。“sklearn”库用于执行 PCA。
Self Organizing Maps (SOM) are unsupervised neural networks that cluster high dimensional data into easy to understand two-dimensional outputs (SOM grid). The SOM grid is a two-dimensional manifold or topological space onto which each observation (row) in the m-dimensional space (where m is the number of variables) is mapped via its similarity with the prototypes (code book vectors) for each node in the SOM grid.
在我们的研究中,数据最初由 178 个观察值和 43 个特征描述,但在应用 SOM 算法时,它被压缩成 7x7x43 的二维图(49 个节点,43 个特征)。高维空间中接近的向量也最终被映射到二维空间中接近的节点。因此,SOM 保留了原始数据的拓扑结构。这意味着在我们的数据中,具有相似性的国家在结果 SOM 中更接近。
图 1: SOM 网格
使用层次聚类的聚类分析
层次聚类是一种聚类分析方法,它试图构建聚类的层次结构。有两种层次聚类策略:
**Divisive Hierarchical clustering**: It is a top-down approach, where all the observations are a part of a single cluster to begin with but then at each iteration the splits are performed and the process is repeated until each cluster contains only a single observation.**Agglomerative Hierarchical Clustering**: It is a bottom-up approach, where in the beginning there are as many clusters as is the number of observations but then at each iteration, the closest pair of clusters are merged and the process is repeated until there is only one cluster left.
我们使用主成分分析和 SOM 结果进行凝聚聚类分析。用这两种方法中的每一种都获得了四个聚类。下面的图 2 示出了使用来自 PCA 的特征作为输入获得的 4 个聚类(A、B、C & D ),图 3 示出了使用来自 SOM 的特征作为输入的 4 个聚类(1、2、3 和 4)。
图 2:作为输入从 PCA 获得的 4 个聚类的树状图
图 3:具有 4 个集群的 SOM 网格
每个国家(分析的 178 个国家中)通过主要成分的等级聚类被分配一个聚类 ID (A、B、C 或 D );和在 SOM 节点上使用分级聚类的另一个聚类 ID (1、2、3 或 4)。
在两种方法中,聚类 A 与聚类 1 一致,聚类 B 与聚类 2 一致,聚类 C 与聚类 3 一致,聚类 D 与聚类 4 一致。在聚类分析**、**所包含的 178 个国家中,有 169 个国家使用 PCA 和 SOM 在聚类分析中显示出一致的结果。总而言之:
- 集群 4/D 包括澳洲、丹麦、德国、冰岛、纽西兰、英国等 45 个国家;
- 集群 3/C 包括 50 个国家,包括阿根廷、巴西、印度、伊朗、墨西哥、美国;
- 第 2/B 组包括 40 个国家,包括印度尼西亚、伊拉克、斐济、利比亚、菲律宾、斯里兰卡、突尼斯;
- 集群 1/A 包括 40 个国家,包括尼日利亚、肯尼亚、埃塞俄比亚、乌干达、赞比亚和津巴布韦。
从 4 组国家中获得的见解
4 个集群的描述摘要:
表 1:4 个集群的新冠肺炎案例相关指标的热图
从上面的热图可以明显看出,根据新冠肺炎相关指标,与其他国家相比,组成第 4/D 类的国家组的平均卫生能力得分以及的每千人累计检测数更高。这些人口密度相当高的国家与其他聚集地相比累计确诊****每百万新冠肺炎病例数也很高。澳大利亚属于这一类(4/D)。类别 3/C 中的国家具有最高的平均人口数(T14)和最高的累计确认数(T16)。
表 2:基于 4 个集群的信息风险因素的热图
上面的热图显示了与信息风险相关的指数,包括与灾害无关的脆弱性(包括与发展和贫困水平相关的脆弱性)和新冠肺炎脆弱性。群组 1/A 中的国家是一组贫穷的国家,如尼日尼亚、辛巴威、埃塞尔比亚,由于缺乏应对新冠肺炎病毒的能力而具有最高的风险,然而,他们并不是新冠肺炎病毒最脆弱的国家。对新冠肺炎来说,最脆弱的群体是集群 4/D,这一群体包括像澳大利亚、德国和英国这样的发达国家。如下图 4 所示,由于总人口中有高** 至少一种与严重新冠肺炎病(共病)相关的潜在疾病的比例,以及无任何潜在疾病的老年人口(65 岁以上)和过度的内部和外部流动,它们具有最高的新冠肺炎脆弱性。**
图 4:4 个集群中 3 个风险指标的分布
我们根据卫生能力、新冠肺炎脆弱性、人口和新冠肺炎病例对 4 个集群进行了命名。
群组 4/D:高新冠肺炎脆弱性和高卫生能力
图 5:群组 4/D 中 6 个代表性国家每日每百万确诊病例的七天平均数
代表国家: 澳大利亚、丹麦、德国、冰岛、新西兰、英国
特征: 因过度的国内国际流动而导致的新冠肺炎脆弱性最高,65+人口中有前提条件的比例最高。最高的国际卫生条例核心能力得分和运营就绪指数,此外还有基于人均公共和私人医疗保健支出的最低风险。这些国家拥有最高的医疗保健能力和最大的每千人检测平均值。尽管每百万人累计确诊病例数很高,但这些国家中的许多国家在大约 2 个月内第一次变平。
群组 3/C:高人口和高病例的高新冠肺炎脆弱性
图 6:群组 3/C 中 6 个代表性国家每日每百万确诊病例的七天平均数
代表国家: 阿根廷、巴西、印度、伊朗、墨西哥、美国
特征: 新冠肺炎脆弱性高,健康能力得分一般,千分检测数高。这一组包括人口极其庞大和每百万人累计确诊病例最高的国家。自新冠肺炎开始以来,这些国家的每日确诊病例持续上升,在超过 3 个月的时间里曲线没有变平。
第 2/B 组:新冠肺炎脆弱性低,新冠肺炎病例低且上升
图 7:群组 2/B 中 6 个代表性国家每日每百万确诊病例的 7 天平均数
代表国家: 印度尼西亚、伊拉克、斐济、利比亚、菲律宾、斯里兰卡、突尼斯
特征: 与其他集群相比,健康容量低,每千人累计检测低;这一群体的新冠肺炎脆弱性低,国内和国际流动有限,并且有先决条件的人口和 65 岁以上年龄组的风险评分低。然而,它们在独立于风险的漏洞方面具有高风险,并且操作准备有限。尽管每日确诊病例数的增长率低于群组 3/C,但由于每日病例数的增加而没有任何曲线弯曲的明确迹象,这一组国家面临着挑战。
群组 1/A:保健能力低,新冠肺炎脆弱性低
图 8:群组 1/A 中 6 个代表性国家每日每百万确诊病例的七天平均数
代表国家: 尼日利亚、肯尼亚、埃塞俄比亚、乌干达、赞比亚、津巴布韦
特征: 卫生容量最低,每千人累计检测最低,每百万人累计确诊病例最低。老龄人口和有先决条件的人口的脆弱性最低,除了最少的旅行活动之外,新冠肺炎的总体脆弱性在这一群体中最低。虽然这些国家在独立应对灾害的能力和有限的运作基础设施方面风险最高,但其中大多数国家每日确诊病例的增长率较低,而且它们也成功地使曲线变平
结论
良好的卫生能力肯定有助于各国应对检测、住院和康复需求。许多国家,特别是发达国家,老年人口和有条件的人口比例很高,由于国内和国际旅行造成的过度流动,比不发达国家更容易受到新冠肺炎的影响。因此,很明显,为了抵御新冠肺炎的严重影响,非常关键的是
“减少和规范运动,保护我们的老年公民”。
我们欢迎您的反馈和评论,在这里 可以随意查看我们之前在数据探索方面的工作,也可以随意访问ka ggle repo和github repo。**
来自《走向数据科学》编辑的注释: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
股票选择的聚类分析
时间抛开复杂的时间序列模型,简单的基本面分析也可以帮助赚钱!!!
马库斯·斯皮斯克在 Unsplash 上的照片
背景
H 你有没有厌倦过通过查看数百个财务比率来选择一只股票?或者你已经厌倦了打磨你的技术分析技巧或改进你的时间序列模型来更好地预测价格?如果答案是肯定的,那你来对地方了。
在本文中,我们将通过一个实验来看看不同维度的财务比率是否真的增加了股票选择的价值。在这个过程中,我们还将看到聚类分析如何帮助我们摆脱财务指标的海洋。
在此之前,我还将向您展示 **(1)下载股票的历史财务比率、**和 (2)股票的每日价格数据,这对许多在不同项目中研究股票数据的人来说非常有用。
下面所有代码的原文,你可以在这里查阅我的 Github 链接。
(1)下载股票的财务指标
首先,我们将使用一个名为 基础分析的库。 关于这个库的详细信息,请参考网站这里。
为了能够使用这个包,我们需要一个来自 FinancialModellingPrep 的 API 密匙,并按照那里的说明获得一个 免费的 API 密匙。请注意,虽然没有时间限制,但这些密钥仅限于每个帐户 250 个请求。所以我强烈建议大家将下载的数据输出为 excel 文件以备将来使用。否则很容易超过限制。
并且由于这个限制,我将实验中的选股范围设定为下面列出的 97 只股票,都是纳斯达克 100 指数的成份股。
上面的代码会生成两个 excel 文件,(a)key _ metrics . xlsx和***(b)financial _ ratios . xlsx***,每只股票在一个单独的表中。这两个文件都存储了过去 10-20 年的各种财务指标,具体取决于公司上市的时间。在后面的步骤中,我们将把它们与收益和价格波动数据结合在一起。
MSFT 关键指标数据的捕获图像
(2)下载股票价格数据
让我们下载价格数据。由于上面的包对请求配额有限制,我们将切换到另一个自由库 yfinance。
上面的代码将下载股票行情表中所有股票的每日价格数据。并选择收盘价来表示价格,输出为 excel 文件, price.xlsx 。
价格数据的捕获图像
(3)将所有数据结合起来使用
最后我们想将准备好的三个 excel 文件合并成一个文件,每个文件在所选期间(2017–2019)内保存一年。我不打算在这里赘述细节,因为这些都只是使用熊猫和 numpy 的一些基本技巧。本节原代码请参考 Github 链接此处中的cluster _ stocks _ data . py**。
尽管如此,我还是想提到一些非常有用的关键技巧,即使是在你从事其他项目的时候。
(a) dataframe.at[index,column name]——为了避免混淆 iloc 或 loc 或任何其他类似的函数,您可以尝试使用函数 ”。在" , 这些直接指的是 dataframe 内的单个单元格。并且可以很容易地用等号设置它的值。
【b】数据帧。t*—如果要交换行和列,转置数据帧。通过应用此功能* 。T" ,那么列名就会变成索引,反之亦然。
©PD . concat()—平行(水平)组合两个数据帧。
(d)data frame . fillna(value = N)—用特定值的 NaN 填充单元格。
经过繁琐的程序后,最终产品将是三个 excel 文件(2017 年、2018 年和 2019 年)。每个都存储特定年份股票行情表中每只股票的回报、价格波动和其他财务指标的数据。
2017 年最终数据集的捕获图像
(4)实验
F 最后,我们可以回到本文的主要内容——(1)检验 **不同维度的财务比率是否真的为选股增值,**和 (2)看看聚类分析如何帮助我们摆脱财务指标的海洋。
与其一行一行地检查冗长的代码,我们不如一起检查这个想法。但是,我还是会举例说明一些关键部分的代码。对于下面介绍的金融概念,如果你有进一步的兴趣,可以参考 Investopedia 了解更多详情。本节代码请参考 Github 链接 中的cluster _ stocks _ analysis . py*。*
第一步:选择一组有代表性的财务指标。 在这个实验中,我选择了以下内容,旨在从不同维度捕捉一家公司的表现或能力。
负债权益比率——公司的杠杆比率
股息收益率——公司支付给股东的持有其股票的金额除以当前股价
企业价值(EV) / EBITDA — 一个常用的倍数来确定公司的价值
净债务与 EBITDA 比率— 表明公司减少债务的能力
净利润率— 净收入占收入的百分比是多少
营业利润率— 在支付可变生产成本(如工资和原材料)后,支付利息或税之前,公司从一美元销售中获得的利润
资产回报率— 通过确定一家公司相对于其总资产的盈利能力,表明该公司利用其资产的情况
第二步:根据以上选择的财务指标进行聚类分析。
不同的人在选择股票时有不同的偏好。有的关心公司盈利能力,有的关心股票是否稳定分红。但是如果我们想了解整体性能呢?那么就很难断定一只股票一定比另一只好,特别是每一个财务指标都代表不同的东西,可能有上百个指标。
在这种情况下,聚类分析可能是拯救我们的一种方法。聚类帮助我们根据财务指标所代表的特征将相似的股票分组在一起。
在本实验中,我们将应用一种最常用的方法——系统聚类,用自底向上的方法、欧几里德距离和沃德方法来计算相似度。对于层次聚类的详细解释,这篇文章给出了一个很好的教训。
(一)标准化
每个财务指标都有自己的标度。例如,EV / EBITDA 可以始终高于资产回报率。因此,为了防止这种规模差异导致无与伦比的权重和不可靠的结论,我们必须首先对数据进行标准化。我们可以通过下面的一行代码简单地做到这一点。
mean() — 计算列内数值的平均值
std() — 计算一列内数值的标准差
(二)执行层次聚类分析
将数据标准化后,我们可以使用一个名为agglomeveclustering的库来执行聚类,这个库的名字意味着自底向上的方法。
为了可视化聚类结果,我们将应用树状图,,它是一个树形图,记录了合并或拆分的顺序。但是,请注意,最终形成的集群数量完全基于您的判断。如果聚类太多,分类可能会太细。如果太少,股票可能无法很好地分类。
树状图绘制如下。
从树状图中,我们可以看到可能有 13 个星团。
有趣的是,四只股票本身形成了独立的集群。
基于该选择,我们接下来对数据集 2017、 应用函数凝聚聚类*,通过将 n_clusters 设置为 13,将亲和力设置为欧几里德距离,将链接设置为沃德方法*** 。
为了说明这 13 个星团的特征,我们可以画一个线图。
从折线图上我们可以看到,2017 年有四个非常有特色的星团,实际上它们都是单独形成的。它们是:
(i) 【灰线】——高净债务/EBITDA 比率和 EV/EBITDA 比率,这意味着公司偿还债务的能力相对较低,基于其较弱的盈利能力对其进行了高估值,这可能意味着其被高估。
(二) IDXX(深蓝线)—负负债率,主要是公司 2017 年权益余额为负。
(三) **DXCM(浅蓝色线)—负 EV / EBITDA 比率,**因 2017 年 EBITDA 为负。
(iv) VRTX(橙色线)——负净债务与 EBITDA 比率,因其 2017 年净债务为负值。
我们不打算调查公司业绩的细节,这可能需要为每只股票单独写一篇文章。我只是想给大家展示一下在选取的财务指标中,聚类可以帮助我们将具有相似特征的股票分组在一起,同时也可以检测出一些离群值。
第三步:根据聚类结果构建投资组合,并与不借助聚类构建的投资组合进行比较
截至 2017 年底,13 个集群的平均绩效表如下所示。
**在进行聚类分析后,需要一个标准来帮助做出投资组合构建的决策。**在这个实验中,收益价格波动率将是唯一遵循的标准。
回报将是一年的回报,通过比较 2017 年末的价格和 2017 年初的价格来计算。价格波动率是 2017 年全年价格的标准差。因此收益-价格波动率比率仅仅是一个收益和风险的度量,也用来模仿夏普比率。
从上表中可以看出,集群 6、8 和 11 将被选中,因为它们的收益价格波动率相对较高。投资组合 A 是通过对这三个组中的所有股票进行相等的加权投资而构建的,总共有 10 只股票。作为比较,我们希望通过选择 2017 年收益价格波动率最高的相应数量的个股来构建另一个投资组合,而无需事先应用聚类分析。
两个投资组合:
(一)2017 年收益率波动率最高的前 3 个集群 ,共 10 只股票(CSCO、FAST、XEL、EXC、COST、QCOM、VRSN、CHKP、FB、VRTX)
(B)2017 年收益价格波动率最高的 10 只股票 (为了公平比较,我们每年都会调整该投资组合的股票数量,以便与投资组合 A 中的股票数量相匹配)(SIRI、、、EBAY、、CSCO、MU、MXIM、NTAP、CMCSA)
现在,我们有兴趣看看哪个投资组合在未来一年(2018 年)产生更高的回报。并且结果显示,投资组合 A 产生了 3.48%的收益,而投资组合 B 遭受了 2.29%的损失。
然而,仍然很难断定基于上述方法的投资组合结构一定会表现更好,尤其是基于一年的数据。因此,我将这个实验延长两个时期(2018–2019 和 2019–2020),结果相当令人惊讶。
两个投资组合在三年内的表现。
显然,在所有三年中,投资组合 A 始终比投资组合 B 产生更高的回报。
(5)性能提高的可能原因
当然,通过财务指标的聚类分析来构建投资组合并不一定能取得优异的业绩。但其持续优于仅考虑回报和风险的选股表现表明,基本面分析确实增加了一些价值,聚类分析有助于简化分析过程。
以下是对更好性能的一些可能解释:
(一)价值基本面分析— 财务指标从不同维度衡量一家公司的业绩。因此,财务表现良好的公司的回报应该比“随机产生的”回报更具可持续性。定期考虑财务指标并更新投资组合配置对其可持续表现非常必要。作为证据,如果我们试图保持 2017 年构建的投资组合的配置在 2019 年前不变,其业绩在 2018-2019 年期间实际上恶化了很多。
(二)多元化收益— 聚类分析有助于区分不同特征的股票。换句话说,所选择的三个集群应该是完全不同的。这种多样化可以防止投资组合在某一时期因某一特定类型公司的低迷而遭受重大损失。
©防范一些公司特有的风险— 将具有相似特征的股票聚集在一起。所以一个过去收益率与价格波动率比值高的群体应该比一只比值高的个股更“具体”。通过这种方法构建的投资组合可能防范了一些公司特有的风险。
(6)结论
构建一个持续表现良好的投资组合总是不容易的,尤其是当有成千上万只股票的时候。有时,我们可能会先缩小范围,但在做出决定之前,仍然需要查看数百个财务指标。
本文介绍了一种可能的方法——聚类分析来帮助我们摆脱财务指标的海洋,并通过一些程序构建了一个完整的财务数据集。我希望这将开启关于如何通过利用一些数据科学技术来改善我们的投资组合分配的讨论。
参考
- 柴坦尼亚·瑞迪·帕特拉。(2018).理解层次聚类技术的概念。
- 达米安·博。(2020).使用 Python 获取最新的股票财务比率。
- 小牛顿达科斯塔,杰弗逊库尼亚和塞尔吉奥达席尔瓦。(2005).基于聚类分析的股票选择
如果你对我写的东西感兴趣,不要错过成为 Medium 会员的机会。您将可以完全访问所有…
medium.com](https://medium.com/@hudsonko/membership)
如果你对时间序列模型更有信心,我的另一篇关于在 LSTM 模型中定制损失函数的文章可能会对你有所帮助。谢了。
[## 定制损失函数,使 LSTM 模型更适用于股票价格预测
损失函数不要只考虑价格差异,方向损失也很重要!!!
towardsdatascience.com](/customize-loss-function-to-make-lstm-model-more-applicable-in-stock-price-prediction-b1c50e50b16c)
免责声明:请注意,投资可能因任何原因而上涨或下跌,股票的过去表现并不能保证未来表现。
本文对任何内容的及时性、准确性或适用性不做任何陈述,也不对任何不规则或不准确之处承担责任。
本文中的股票推荐和评论不代表我对是否买入、卖出或持有任何特定股票的观点。
建议所有投资者在做出投资决定之前进行独立研究。投资者应该考虑任何投资建议的来源和适合性。您使用本文中的任何内容都要自担风险。
圣保罗的汉堡聚集地
使用 Foursquare API、无监督机器学习、树叶地图和单词云绘制见解
丹·戈尔德通过 Unsplash 拍摄的照片
圣保罗是世界上最大的城市之一,人口超过 1200 万,是巴西的经济中心。它有太多的场地和餐厅,供应来自世界各地的特色美食。特别是,有一类餐馆在这个城市非常受欢迎:汉堡店。圣保罗总共有大约 600 家汉堡店,有些街区每个街区有不止一家。
作为我的 IBM 数据科学专业证书期末项目的一部分,我决定将数据科学和我对汉堡的巨大爱好结合起来,以了解一点关于我目前居住的城市圣保罗的汉堡店的情况。
这里的目标是为那些想开一家汉堡店的人,或者已经有一家店并想获得一些关于市场的新信息的人,或者只是为那些对数据如何改变我们对任何主题的看法感到好奇的人提供见解。
所有这些项目都是使用 Python 语言和 Jupyter 笔记本完成的。详细代码在这个 Jupyter 笔记本链接里。目前,我只打算发布一些重要部分的代码片段。
战略:
我对这个项目的设想是从圣保罗的汉堡店中检索数据,根据它们的特点创建场馆群,对它们进行分类,并得出每个场馆群的见解。
为了实现这一目标,本研究分为 4 个部分:
- 数据采集
- 数据预处理和聚类
- 聚类分析
- 结论
数据采集:
获取数据的第一步是使用 geopy 库来检索圣保罗的街区,以便稍后我们可以找到每个街区的汉堡店。
照片通过 Geopy
Geopy 是一个库,Python 开发人员可以使用第三方地理编码器和其他数据源轻松定位全球各地的地址、城市、国家和地标的坐标。
使用 geopy 非常简单,只需写下街区的名称,它就会返回该位置的纬度和经度。下面是一段代码,它使用包含所有街区名称的 excel 文件检索每个街区的所有纬度和经度值:
data_hoods= pd.read_excel('Neighborhoods_SP.xlsx')
geolocator = Nominatim()
from geopy.exc import GeocoderTimedOut
lat=[]
lon=[]
for i in data_hoods['Neighborhood']:
try:
location_hood = geolocator.geocode("{}, Sao Paulo,Sao Paulo".format(i))
print(i)
lat.append(location_hood.latitude)
lon.append(location_hood.longitude)
except GeocoderTimedOut:
location_hood = geolocator.geocode("{}, Sao Paulo,Sao Paulo".format(i))
print(i)
lat.append(location_hood.latitude)
lon.append(location_hood.longitude)
有了这些信息,我们可以使用每个位置来检索每个街区 900 米半径范围内的每个地点。选择该半径是因为较大的半径只会导致场馆重叠,并在数据集中产生更多的重复。下面的代码显示了如何调用 API 来检索所有的场馆、它们的位置、名称和 id:
def getNearbyVenues(names, latitudes, longitudes, radius=900):
venues_list=[]
for name, lat, lng in zip(names, latitudes, longitudes):
print(name)
# create the API request URL
url = 'https://api.foursquare.com/v2/venues/explore?&client_id={}&client_secret={}&v={}&ll={},{}&radius={}&limit={}&query={}'.format(
CLIENT_ID,
CLIENT_SECRET,
VERSION,
lat,
lng,
radius,
LIMIT,
'burguer'
)
# make the GET request
results = requests.get(url).json()["response"]['groups'][0]['items']
# return only relevant information for each nearby venue
venues_list.append([(
name,
lat,
lng,
v['venue']['name'],
v['venue']['location']['lat'],
v['venue']['location']['lng'],
v['venue']['id']) for v in results])
burguer_venues = pd.DataFrame([item for venue_list in venues_list for item in venue_list])
burguer_venues.columns = ['Neighborhood',
'Neighborhood Latitude',
'Neighborhood Longitude',
'Venue',
'Venue Latitude',
'Venue Longitude',
'Venue Id']
return(burguer_venues)
SP_burguer_venues = getNearbyVenues(names=data_hoods['Neighborhood'],
latitudes=data_hoods['lat'],
longitudes=data_hoods['lon']
)
注意,要复制上面的代码,你需要一个 foursquare 开发者账户:http://developer.foursquare.com/。
现在我们可以使用一张地图来看看圣保罗的汉堡店
map_burguers_neigh = folium.Map(location=[latitudeSP,longitudeSP], zoom_start=11)
for lat, lon, name in zip(SP_burguer_venues['Venue Latitude'], SP_burguer_venues['Venue Longitude'], SP_burguer_venues['Venue']):
label = folium.Popup(' name ' + str(name), parse_html=True)
folium.CircleMarker(
[lat, lon],
radius=5,
popup=label,
color='red',
fill=True,
fill_color='red',
fill_opacity=0.7).add_to(map_burguers_neigh)
map_burguers_neigh
在 Foursquare API 注册的汉堡店
上图描绘了圣保罗的汉堡联合市场有多大。在一些地区,这实际上可能是一个饱和的市场,例如在 Itaim Bibi 社区,我们有超过 30 家汉堡店(仅计算在 Foursquare 注册的汉堡店)。
伊泰姆比比社区的汉堡店
现在,这里的想法是收集信息,这将有助于我们了解这些场馆。
- 场馆评级:区分场馆的简单方法。我们将通过从 Foursqaure API 请求场馆评级来检索最佳场馆。该数据是一个从 0 到 10 不等的等级。
- 场馆价格:逗号分隔的价格点列表。目前价格点的有效范围是[1,2,3,4],1 是最便宜的,4 是最贵的。1< 10 USD an entree, 2 is 10 to 20 USD an entree, 3 is 20 to 30 USD an entree, 4 is >主菜 30 美元吗?这个数据也在来自 Foursquare API 响应的 json 中。
- 场地评论:对参加了在 Foursquare 平台注册的特定场地的客户的文本评论。这将有助于我们更深入地了解客户最看重什么。
- 街区平方米价格:这是特定街区每平方米的房地产价格。如果我们假设某个地区的房地产价格越高,居住在该地区的人的购买力就越高,那么这将有助于获取关于在特定地点维护场地的成本以及参加该场地的客户类型的见解。这一特征以雷亚尔(R$)计量。
为了获得这些信息,我们需要再次调用 Foursquare API,但是这一次我们需要使用另一个端点,因为我们需要每个特定地点的信息。进行呼叫的 url 是https://api.foursquare.com/v2/venues/$VENUE_ID&客户端 id &客户端秘密& v 版本。这将以 json 格式返回我们需要的大部分信息。
def getVenuesinfo(venue,names,venue_id):
jsondict={}
for ven,name, v_id in zip(venue,names,venue_id):
print(name)
# create the API request URL
url_venue = 'https://api.foursquare.com/v2/venues/{}?&client_id={}&client_secret={}&v={}'.format(
v_id,
CLIENT_ID,
CLIENT_SECRET,
VERSION
)
# make the GET request
results_venues = requests.get(url_venue).json()
jsondict[v_id]=results_venues
return(jsondict)
在对每个场馆 id 进行调用后,我们将获得每个场馆的评论、价格和评级,只剩下我们要检索的邻近平方米价格。我不得不从圣保罗地区(http://proprietariodireto.com.br)的一个房地产网站手动获取这些信息。现在,我们剩下一个数据框,如下图所示:
包含圣保罗汉堡店信息的数据框
现在我们已经有了所有需要的信息,是时候进入数据预处理并最终创建我们的集群了。
数据预处理和聚类:
在我们开始做一大堆聚类并开始得出结论之前,我们需要问自己:我们有什么类型的数据?哪种聚类算法是最佳选择?我们如何准备数据?我们将如何评估聚类结果?
我们有什么类型的数据?
让我们回忆一下,我们感兴趣的是为我们的聚类算法提供信息的 3 个特征:场馆的价格(范围从 1 到 4,以雷亚尔(R$)为单位的每平方米价格)和等级(范围从 1 到 10)。其中两个特征的问题是它们是有序数据。这使得一些无监督算法很难产生相关结果。例如,k-means 使用欧几里德距离来计算一个簇中元素之间的相异度。这意味着分类数据的这项任务是不可能的,因为我们无法确定类别 A 与类别 B 之间的距离,因为它们是不连续的数据。另一方面,有专门对纯分类数据进行聚类的聚类算法,如 k-modes。但是有序数据是一个特例,因为我们的信息被分成不同的类别,但是有一定的顺序。这给我们留下了一个重要的决定:我们应该将我们的数据视为连续的,还是应该将我们的数据视为混合数据,其中一些将是连续的,一些将是分类的?这两个决定都有利弊,这将最终影响聚类算法的选择。
欧几里德距离公式的例子,照片由克里斯·麦考密克拍摄
哪种聚类算法是最佳选择?
将数据视为纯连续数据会假设一个类别和另一个类别之间的距离相同,就好像它们是连续数据一样,但这有时是不正确的。通过将它们视为混合数据,我们将基本上失去有序数据的排序信息,并将它们视为纯粹的分类数据。对于这种方法(混合数据),我们需要使用 k-prototypes 算法,我会在这篇文章的最后解释。由于我们需要两个分类数据的信息顺序,我们将把它们视为连续的,并使用 k-means 算法对它们进行聚类。
我们如何准备数据?
在继续执行以下步骤之前,检查要素中的空值和重复 id 并删除符合任一情况的行非常重要。然后,我们需要对数据进行标准化,这样在聚类过程中就不会有比其他特征更高的权重。为此,我们将使用 sklearn 的标准标尺。这将通过移除平均值并缩放至单位方差来标准化要素。
cluster_df=SP_burguer_venues.filter(['Rating','Price_M2','Price'], axis=1)
Clus_dataSet=StandardScaler().fit_transform(cluster_df)
现在,我们已经准备好对我们的场馆进行分组:
from sklearn.cluster import KMeans
wcss = []
for i in range(1, 11):
kmeans = KMeans(n_clusters=i, init='k-means++', max_iter=300, n_init=10, random_state=0)
kmeans.fit(Clus_dataSet)
wcss.append(kmeans.inertia_)
plt.plot(range(1, 11), wcss)
plt.title('Elbow Method')
plt.xlabel('Number of clusters')
plt.ylabel('WCSS')
plt.show()
这个代码片段中生成的图将在下一步中有用。
我们将如何评估聚类结果?
用于评估聚类准确性的方法将是肘方法。实际上,我们将最小化所有聚类中的每个数据点到它们各自质心的距离。这将为我们的具体情况提供最佳的集群数量。为了使用肘方法,我们使用不同数量的簇绘制了具有惯性值的图形:
聚类数的平方和
通过查看上图,我们可以得出结论,对于这种情况,4 个集群将是我们的最佳选择。
使用 4 个聚类并再次运行该算法,我们在我们的聚类的 3 个特征内获得以下点分布(该图是使用 plotly 生成的):
import plotly
import plotly.express as px
fig = px.scatter_3d(SP_burguer_venues, x='Rating', y='Price', z='Price_M2',
color='Cluster Labels', size_max=18,
opacity=0.7)
fig.update_layout(margin=dict(l=0, r=0, b=0, t=0))
fig.show()
有了这 3 个可视化,我们就可以开始了解算法是如何对场馆进行聚类的了。在我们继续之前,让我们创建一个叶子地图来可视化圣保罗地图中按集群分隔的场馆:
map_clusters = folium.Map(location=[latitudeSP,longitudeSP], zoom_start=11)
# set color scheme for the clusters
x = np.arange(kclusters)
ys = [i + x + (i*x)**2 for i in range(kclusters)]
colors_array = cm.rainbow(np.linspace(0, 1, len(ys)))
rainbow = [colors.rgb2hex(i) for i in colors_array]
# add markers to the map
markers_colors = []
for lat, lon, poi, cluster in zip(SP_burguer_venues['Venue Latitude'], SP_burguer_venues['Venue Longitude'], SP_burguer_venues['Neighborhood'], SP_burguer_venues['Cluster Labels']):
label = folium.Popup(str(poi) + ' Cluster ' + str(cluster), parse_html=True)
folium.CircleMarker(
[lat, lon],
radius=5,
popup=label,
color=rainbow[cluster-1],
fill=True,
fill_color=rainbow[cluster-1],
fill_opacity=0.7).add_to(map_clusters)
map_clusters
聚集场馆的圣保罗地图。
红色聚类是聚类 0,紫色聚类是聚类 1,聚类 2 用蓝色编码,聚类 3 用米色显示。
将每个地点分配给每个聚类的独立数据框后,我们可以开始分析每个聚类,并开始从生成的结果中获得洞察力。
聚类分析:
好的,我们有集群,但是他们告诉我们什么?要回答这个问题,我们需要经历 2 个步骤:
- 分析每个特征,并在聚类之间进行比较。
- 创建每个集群场馆评论的文字云。
让我们从第一步开始,绘制每个聚类中的要素。从每个集群场馆的平均价格开始:
cluster_labels=['Cluster 0','Cluster 1','Cluster 2','Cluster 3']
cluster_mean_price=[cluster1['Price'].mean(),cluster2['Price'].mean(),cluster3['Price'].mean(),cluster4['Price'].mean()]
cluster_price=pd.DataFrame({'Mean Price':cluster_mean_price,'Clusters':cluster_labels})
fig = px.bar(cluster_price, x='Clusters', y='Mean Price',title="Mean Price of each cluster",color="Clusters")
fig.show()
上图显示第 0 类和第 2 类最贵,主菜价格在 10-20 美元之间。如果我们假设价格等级和实际价格之间的线性关系,则集群 0 平均比第二贵的集群 2 贵大约 17%。
这清楚地区分了集群 0 和 2 以及集群 1 和 3。集群 0 和 2 是最贵的场馆,集群 1 和 3 是最便宜的场馆,特别注意集群 3,它不到集群 0 平均价格的一半。这意味着第三组场馆主菜的平均价格低于 10 美元。
现在,我们来看看每个集群的平均房地产价格:
该图显示了将分类 2 与其他分类区分开来的主要分类特征之一是房地产价格。它的平均价格比第二贵的邻居集群(集群 0)高 75%。
考虑到这一点,与其他集群相比,预计参加集群 2 场馆的人有更大的购买力。
最后,我们有场地评级:
几乎所有的群组在评级上没有相关的百分比差异,所有群组的平均值都在 7.6 到 8.1 之间。可以假设,这些集群的场馆都是非常满意的客户。
另一方面,我们在集群 1 上观察到集群之间的另一个清楚的划分。它的平均评分为 5.86,比排名第二低的集群低 23%。
显然,每个集群都有其特点,但现在是时候回顾一些更定性的东西了,这些东西不仅会带来关于场馆的一些见解,还会带来来自这些场馆本身的客户的一些见解。
输入单词云:
萨姆·斯库勒通过 Unsplash 拍摄的照片
词云是非常美学的工具,可以帮助我们根据某个词在某个文本中的出现频率来检索文本信息。单词云会产生一个图像,其中最常见的单词会显得更大。
使用客户的评论,我们可以生成每个客户的词云,并尝试识别关于场地和客户的特征,找到对我们在特征中获得的价值的解释,还可以发现每个集群的场地的哪些方面最能引起客户的注意。
由于这个项目是与一个说葡萄牙语的国家打交道,对于不懂这种语言的人来说,将很难从单词 cloud 整体上保留信息。也正因如此,这个词云中产生的关键点才会得到解释和恰当的翻译。
为了创建单词云,我们从每个聚类的评论中生成单词列表,对于来自 4 个聚类的每个单词列表,我们将创建一个单词云:
#!conda install -c conda-forge wordcloud --yes
# import package and its set of stopwords
from wordcloud import WordCloud, STOPWORDS
list_tip1=[]
list_tip2=[]
list_tip3=[]
list_tip4=[]
for i in cluster1['Review']:
list_tip1.append(i)
for i in cluster2['Review']:
list_tip2.append(i)
for i in cluster3['Review']:
list_tip3.append(i)
for i in cluster4['Review']:
list_tip4.append(i)
flatList1 = [ item for elem in list_tip1 for item in elem]
flatList2 = [ item for elem in list_tip2 for item in elem]
flatList3 = [ item for elem in list_tip3 for item in elem]
flatList4 = [ item for elem in list_tip4 for item in elem]
import numpy as np
from PIL import Image
unique_string1=(" ").join(flatList1)
unique_string2=(" ").join(flatList2)
unique_string3=(" ").join(flatList3)
unique_string4=(" ").join(flatList4)
#Importing burguer mask
burger_mask = np.array(Image.open('burger_mask.png'))
burguer_wc1 = WordCloud(
background_color='white',
max_words=2000,
stopwords=stopwords,
mask=burger_mask
)
burguer_wc2 = WordCloud(
background_color='white',
max_words=2000,
stopwords=stopwords,
mask=burger_mask
)
burguer_wc3 = WordCloud(
background_color='white',
max_words=2000,
stopwords=stopwords,
mask=burger_mask
)
burguer_wc4 = WordCloud(
background_color='white',
max_words=2000,
stopwords=stopwords,
mask=burger_mask
)
# generate the word cloud
burguer_wc1.generate(unique_string1)
burguer_wc2.generate(unique_string2)
burguer_wc3.generate(unique_string3)
burguer_wc4.generate(unique_string4)
绘制每个词云后,我们得到:
fig = plt.figure()
fig.set_figwidth(50) # set width
fig.set_figheight(50) # set height
fig.add_subplot(4, 2, 1)
plt.axis('off')
plt.title('Cluster 0',fontsize=38,loc='left',verticalalignment='baseline',horizontalalignment= 'left')
plt.imshow(burguer_wc1, interpolation='bilinear')
fig.add_subplot(4, 2, 2)
plt.axis('off')
plt.title('Cluster 1',fontsize=38,loc='left',verticalalignment='baseline',horizontalalignment= 'left')
plt.imshow(burguer_wc2, interpolation='bilinear')
fig.add_subplot(4, 2, 3)
plt.axis('off')
plt.title('Cluster 2',fontsize=38,loc='left',verticalalignment='baseline',horizontalalignment= 'left')
plt.imshow(burguer_wc3, interpolation='bilinear')
fig.add_subplot(4, 2, 4)
plt.axis('off')
plt.title('Cluster 3',fontsize=38,loc='left',verticalalignment='baseline',horizontalalignment= 'left')
plt.imshow(burguer_wc4, interpolation='bilinear')
聚类 0,1,2,3 的词云
从视觉检查中,我们可以看到在每个簇中更常见的单词。虽然这已经给我们带来了一些见解,但还是让我们从每个聚类中找出前 10 个单词。我已经翻译了这些单词,以便让那些不会说这种语言的人更容易理解这一部分。
每个聚类中的前 10 个单词
从这一部分中,我们可以确定在前面步骤中收集的信息之间的一些相似之处,同时对集群进行定量分析。
首先让我们来看看他们排名最高的单词中的所有共同点,这些可能是想开一家汉堡店的人的必备词汇。它们都有“atendimento”这个词,在葡萄牙语中是“服务”的意思。因此,从这一信息中得出的第一个关键信息是,无论你的客户群、价格或位置如何,你都必须提供良好的服务,这个词在所有类别中都排在前三位。另一个出现在所有聚类中的单词是“maionese ”,你可能会猜它是蛋黄酱。
香草蛋黄酱,一种在圣保罗几乎每个汉堡店里都很受欢迎的酱料,图片来自 receitasagora.com
现在,我们来看一下集群之间的差异,我们可以看到除集群 2 之外的所有集群都有单词“preç”,在葡萄牙语中是“价格”的意思。这意味着当访问汉堡店时,集群 2 可能对评估价格作为定义类别没有表现出太大的兴趣。基于每平方米的价格,这是有意义的,因为集群 2 被归类为拥有最富有的客户。另一个有趣的事实是,cluster 2 指的是素食(葡萄牙语中的“素食者”)和布里干酪(至于奶酪),表明他们在选择方面也非常苛刻。
另一个有趣的观察点是薯条在聚类 3 中出现了两次。发生这种情况是因为单词“batata”和“fritas”在上下文中都是指薯条,所以**薯条实际上对这个集群有很大的影响。**聚类 3 还显示了一个没有明确出现在来自其他聚类的任何其他前 10 个单词中的单词,即单词“options”。这可能表明,虽然他们不要求像布里干酪或素食这样的花式调味品,但他们也重视使用传统调味品的不同组合或大小的场所。
既然我们已经对客户谈论最多的话题有了一些了解,我们可以将我们从定量分析和热门词汇中观察到的内容结合起来,得出关于每个集群的一些结论:
群集 0
德韦恩·勒格朗通过 Unsplash 拍摄的照片
高价场地,位于平均价格和高评级的社区。顾客谈论价格、服务和另一个啤酒类别中没有的特点。这向我们表明,参加这些高价场所的人没有集群 2 那么大的购买力,但当他们选择花钱时,很可能是在休闲时间(因此啤酒在热门词汇上),他们重视这种类型的体验(因此评级较高)。
群组 1
菲德尔·费南多通过 Unsplash 拍摄的照片
**平均价格(与其他人相比)、低价社区和低评级。**这一群人不仅在评分中表现出不满意,而且在价格和昂贵位于前 10 名的热门词汇中也表现出不满意。这可能是因为这个群体中的人没有太多的购买力,当他们试图在平均价格的场馆上多花一点钱时,他们通常不会达到他们的预期。第 1 类场馆应注意的要点可能与成本效益相关,给人们带来了并未真正实现的期望。
群组 2
Jakub Kapusnak 通过 Unsplash 拍摄的照片
**高价场地和邻近位置以及高评级。**该集群以高标准和差异化为特征。与第 0 类和第 3 类相比,评级较低的一个解释是,购买力较高且去高价场所的人会提高他们的期望,因此,他们在提交评级时会更少怜悯。基于上面的话,我们可以看到这些场馆的客户注重差异化的调味品和选择。第 2 组场馆应该注意的一点是,优先考虑场馆菜单的独特性,而不是价格。
第 3 组
照片由 Pj Gal Szabo 通过 Unsplash 拍摄
**高收视率的低价街区的低价场馆。**这个集群的目的是降低价格,物有所值。一个没有被讨论但在单词 cloud 上出现在第 15 位的单词是成本效益。这已经向我们表明,顾客正在得到他们所寻找的东西:一顿好饭的好价钱。聚类 3 词云上的价格频率高于所有其他词,从那里,顶部的词突出了汉堡店的基本方面,即薯条、肉、蛋黄酱和许多选择。集群 3 场馆的关键要点是:保持简单和便宜。
结论:
这就结束了对圣保罗汉堡店的研究。虽然有大量的数据可以使这项研究在统计上更加可靠,而且如果我们可以事先标记场地,监督算法可能是一个不错的选择,但这是对圣保罗汉堡联合市场的一个有趣的高水平分析。如果你对所有这些背后的代码感兴趣,我真的建议你看看我为这个项目准备的 Jupyter 笔记本,也可以看看下面的附录,快速概述我使用 k-prototypes 算法而不是 k-means 得到的结果。
欢迎对这里分享的知识提出编辑或补充建议。我希望这篇文章能够启发那些刚开始从事数据科学的人,以及那些只对从数据中得出不同见解感兴趣的人,否则这些数据是不可能用肉眼观察到的。
附录:k 原型算法:
图片来自考古学
k 原型算法基本上是一个 k 均值和 k 模式绑定在一起。k-means 将使用欧几里德距离来计算聚类内元素之间的不相似性,k-modes 将基于每个个体中的特征的模式来计算距离,以计算分类特征之间的不相似性。在处理混合数据时,这是一个非常有用的方法。
k 原型的相异度函数可以表示为:S+γP,其中 S 是数值属性的相异度,P 是类别属性之间的相异度。Gamma (γ)是分类属性在我们的聚类算法中的权重。当然,这是对算法的过度简化,所以请务必查看本节末尾参考书目中黄哲学发表的文章。
我将使用这个算法的 python 实现:https://github.com/nicodv/kmodes
准备数据和运行算法:
对于本节,我们将假设价格层级是明确的,其余的是连续的。为了将平方米价格与评级(我们的连续变量)进行比较,我们需要对它们进行缩放:
scaler = MinMaxScaler(feature_range=(0, 10))
price_M2=cluster_df['Price_M2']
price_M2=price_M2.to_numpy()
price_M2=price_M2.reshape(-1, 1)
price_M2_scaled=scaler.fit_transform(price_M2)
price_M2_scaled=pd.DataFrame(price_M2_scaled)
price_M2_scaled.reset_index(drop=True,inplace=True)
cluster_scaled=cluster_df.filter(['Rating','Price'], axis=1)
cluster_scaled.reset_index(drop=True,inplace=True)
现在,我们可以对数据运行 k-prototypes,并再次使用肘技术来找到最佳的聚类数:
cost = []
K = range(1,10)
for k in K:
kp=KPrototypes(n_clusters=k, init='Huang', n_init=1, verbose=2)
clusters = kp.fit_predict(cluster_scaled, categorical=[1])
cost.append(kp.cost_)
plt.plot(cost)
使用不同 k 值最小化成本函数
好的,那么这一个将选择 2 个集群。让我们再次运行该算法,并用聚类绘制圣保罗地图。
该图显示了由 k 原型制造的两个集群
让我们分别探索这些特性:
显然,与聚类 0 相比,该算法在聚类 1 上划分为高价场所、高价社区和高评级。让我们看看客户评论是否反映了我们在上面观察到的情况:
两个集群的词云
有趣的是,我们可以观察到,使用 k-means 算法,聚类 1 中的单词与聚类 2 中的单词非常相似。另一方面,群集 0 最终是上一节中所有其他群集的混合。
因此,k-原型给了我们一个关于汉堡店的二元视角,就现实中对它们进行分类的最佳方式而言,这可能不一定是真的或假的,但它给我们带来的关于这些场所的见解比 k-means 更少,特别是在这项研究中。
作为这篇文章的总结,这只是一个示范,展示了一个选定的算法如何改变你使用无监督算法得到结果的方式。尤其是使用 k 原型时,有许多因素会影响我们的结果。其中一个因素是 gamma 乘数,它设置分类变量的权重,在本演示中我们使用默认值 0.5。如果我们开始增加 gamma,该算法将尝试根据场地价格进一步分离聚类,这可能会给我们带来失真的结果。
因此,无监督算法的选择和如何使用取决于我们自己的偏见和我们自己对什么可能是真的概念,而不一定是成立的和可以验证的。这是一个重要的收获,因为尽管它们可以为我们所用,通过显示我们无法清楚看到的模式,无监督算法也可能非常误导人。
参考资料:
——黄,哲学。对具有分类值的大数据集进行聚类的 K-Means 算法的扩展。1998 年 1 月,http://citeseerx.ist.psu.edu/viewdoc/download?doi = 10 . 1 . 1 . 15 . 4028&# 38;rep = rep 1&# 38;type=pdf 。
-一个销售和销售平台。proprietariodireto.com.br/.
- Foursquare 开发者。developer.foursquare.com/.
更多推荐
所有评论(0)