TowardsDataScience-博客中文翻译-2021-九十二-
TowardsDataScience 博客中文翻译 2021(九十二)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
揭示 Spotify 算法的工作原理
原文:https://towardsdatascience.com/uncovering-how-the-spotify-algorithm-works-4d3c021ebc0?source=collection_archive---------2-----------------------
Spotify 算法的背后是什么?从基于内容过滤的自然语言处理到协同过滤。
来源:亚历山大·沙托夫在 Unsplash 上拍摄的照片
2008 年,Spotify 通过引入音乐流媒体开始改变音乐世界。从那以后,CD 和 DVD 上的音乐已经离开了我们的生活,音乐产业也发生了很大的变化。
如今,Spotify 是最大的玩家(拥有 3.65 亿。用户和 1.65 亿。但必须在苹果(Apple Music)、亚马逊(Amazon Music)和谷歌(YouTube Music)等美国巨头之间保持自己的地位。为此,Spotify 必须关注两个对等群体:艺术家和用户。为了给他们提供最好的服务,Spotify 的核心有一样东西:算法和机器学习。Spotify 越了解用户,客户体验越好,用户就越容易被说服,转化为付费客户,并成为客户。换句话说,数据和算法是 Spotify 不被苹果、亚马逊和谷歌挤压的机会,迄今为止它们做得相当好。所以,让我们仔细看看 Spotify 算法是如何工作的,但首先是基础知识:
Spotify 主屏幕
在 Spotify 的中心,推荐系统是主屏幕,上面点缀着许多定制的播放列表和推荐。推荐的播放列表包括 Discover weekly、B Side、Release Radar、your mixtapes 等等。巧妙安排的主屏幕的其他部分是**跳回,最近播放,或今天推荐。**主屏幕由一个名为 BaRT (作为治疗的推荐的强盗)的人工智能创建和策划,这将进一步详细解释。Spotify 的跳回这样的板块也叫货架。
推荐系统出现的地方。来源:自己的图像。
在这些推荐的播放列表旁边,有推荐歌曲(自动播放列表继续)部分,你可能也会喜欢每个播放列表和每张专辑下面的。因此,你几乎可以在每个 Spotify 屏幕上找到一个定制部分。
为了向客户推荐音乐,并预测主屏幕内外适合的歌曲,Spotify 必须依靠数据。所以让我们来看看可用的数据来源。
数据
Spotify 收集和使用的数据相当广泛。在 Spotify,几乎所有东西都被跟踪。你可能已经温和地体验过了:Spotify 的一年回顾。在这个部分你可以看到你一年来听的分钟数,所有流派,最喜欢的艺术家,新人,热门播放列表,最喜欢的播客,老实说,这只是冰山一角。在 Spotify 的例子中,大多数用户对被跟踪没有意见,因为他们受益于良好的用户体验、良好的统计数据和一流的推荐。
Spotify 一年回顾。来源:自己的图像。
现在让我们更详细地看看收集的数据。先说艺术家。当然,Spotify 存储艺术家输入的所有数据:歌曲名称、描述、流派、图像、歌词和歌曲文件。除了这种从“提供商端”输入的数据之外,Spotify 还收集并跟踪对方——消费者——的数据。这些数据包括消费者的收听历史、跳过的歌曲、歌曲播放的频率、存储的播放列表、下载的音乐、社交互动,如共享播放列表或共享音乐,以及更多变量。除了这两个“内部”数据来源,Spotify 可能还使用外部数据,如文章、博客帖子或其他关于歌曲或艺术家相关主题的文本数据。
https://medium.com/@hucker.marius/membership
Spotify 使用的数据和模型。来源:自己的图像
Spotify 的收购
2014 年,Spotify 以 1 亿美元收购了麻省理工学院音乐智能相关初创公司 Echonest。Echonest 在 2014 年已经拥有超过 1 个关于歌曲和艺术家的数据。[4]
2012 年,Echonest 创始人 Brian Whitman 表示,他们的系统每天都会对 1000 万个音乐相关网站进行评分,以分析音乐市场上的趋势和动态。除了 Echonest,Spotify 还加强了其 M&A 战略,并在 2015 年收购了数据科学和分析咨询公司 Seed Scientific,以获得内部知识和专业技能。[5]他们人工智能道路上的另一项重大收购是在 2017 年,Spotify 合并了音频检测初创公司 Sonalytic 。[6]音频检测您可能从 Shazam 或类似的应用程序中了解到,这些应用程序可以帮助您识别您不知道其名称的歌曲。此外,音频检测系统也可以用于防止侵犯版权。Spotify 使用音频检测来增强播放列表和歌曲的个性化,以“将歌曲与作品相匹配,并改善其发布数据系统”。[6]
Spotify 的敏锐度。来源:自己的图像。
上述所有收购一直是 Spotify 构建其复杂推荐系统的基础。
推荐系统
推荐系统一点都不新鲜,你在互联网的每个角落都会遇到它们:网飞、谷歌、亚马逊、电子商务商店等等。每当你得到可能合适的产品、服务或人员的推荐时,我们就谈论推荐系统。在 LinkedIn 的例子中,推荐系统根据你的社交网络、工作经历和兴趣推荐人,网飞算法推荐最适合你的电影风格的电影和连续剧,亚马逊为你提供类似的产品或其他顾客与手头产品一起购买的补充产品。
因此,推荐系统所做的只是根据系统所跟踪的行为或特征提供建议。正如 Spotify 研究团队所言,“用户被在线观看、购买、阅读和收听的内容所淹没”,因此推荐系统对于帮助导航和促进决策过程是必要的[2]。
亚马逊的推荐系统。来源:自己的图像
推荐系统基本上可以分为 3 种类型:
- 协作过滤(Collaborative-filtering):协作过滤是基于这样一种假设,即过去同意的人将来也会同意,而且他们会像过去一样喜欢相似种类的对象。
- **基于内容:**基于内容的推荐系统依靠用户-项目关系的可用“特征”来建立模型,例如性别年龄等。
- **混合型:**这种类型显然结合了两个世界,基于内容和协同过滤。
Spotify 利用了协同过滤和基于内容的推荐系统,但还有更多值得探索的地方。现在这只是一个理解基础知识的一般性介绍,让我们来看看算法背后的更多细节!
Spotify 的巴特解释道——那是什么?
Spotify 定制背后的系统被称为 BaRT(“作为治疗的建议的强盗”)。BaRT 模式有两种模式:开采和勘探。
TL;dr: 当系统使用它收集的关于你(用户)的信息,例如你的跳过,你最喜欢的歌曲等时,就使用了利用..相反,当系统基于系统可以使用的所有其他信息(例如,其他用户听了什么、已经建立了什么播放列表、什么是流行的、发布了什么等等)向您建议歌曲时,使用探索。
开发模式是基于协同过滤的推荐系统使用的常规模式。在有足够的用户历史数据和用户听了什么的情况下,这种模式是完美的。开发模式使用关于用户和项目的所有可用数据,例如跳过的歌曲、歌曲播放的频率、共享的歌曲、播放列表等。仅基于开发的系统的主要问题之一是物品相关性。如果几乎没有关于用户或项目(在这种情况下是某首歌曲)的数据,例如该歌曲没有被经常播放,则系统不确定是推荐(利用)还是不推荐(忽略)。
来源:[2]
这就是班迪特算法出现的地方,也是第二种模式成为焦点的地方:探索。由于开发模式在存在不确定性(没有足够的数据)时表现不佳,因此探索模式正好涵盖了这些情况。“Exploration 推荐预测用户参与度不确定的内容,以收集更多信息。近年来,探索的重要性已经得到认可,尤其是在有新用户、新项目、非固定偏好和属性的环境中。”[2]
换句话说,如果一首新歌还没有经常播放,你需要数据来验证这首歌是否有潜力。因此,Spotify 的 BaRT 通过 exploration 推荐这些歌曲,并为新歌收集信息。一首歌曲在 30 秒后被认为是正面推荐。这意味着如果你听一首歌少于半分钟,它被认为是负面的。如果你听了超过 30 秒,你会得到积极的反馈。
来源:[2]
从上图可以看出,当歌曲的相关性确定性较低时,探索模式是必要的,并且比利用模式更有帮助。
BaRT 模型能够“学习和预测满意度”,这可以通过点击率和消费概率来衡量。它不断地记录、重新训练,并从自己的错误中学习。[2]
因此,换句话说,BaRT 基于强化学习,并试图获得反馈,以最大限度地提高用户满意度,并纠正预测的建议。为此,BaRT 模型使用了一个多臂强盗,它被训练来执行某个动作 A,该动作 A 获得奖励 r 的概率最高。因此,每个动作 A 都依赖于之前的动作和奖励。“多臂土匪(MAB)的目标是选择报酬总和最大化的行动”[2]。传统的 MAB 忽略了它们的上下文,例如一天中的时间、设备、播放列表、用户特征等。,完全。这就是为什么 Spotify 团队推出了背景多臂强盗 T4。它关注上下文信息,并在决定执行动作之前评估这些信息。
来源:[2]
来源:[2]
对于一个表现出色的背景强盗来说,四个要素是至关重要的:当然是背景、奖励模式、训练程序和开发政策。[2]“在奖励模型中存在三个参数:解释 e(解释为什么选择该项目)、项目 j(歌曲)和上下文 x
奖励模式。来源:[2]
其中θ表示逻辑回归的系数,
并且 1_i”表示在索引“[2]处具有单个 1 的 0 的独热向量
来源:[2]
现在这个奖励功能对行动产生了影响。在某个上下文 x 中,用户 u 执行最佳动作
来源:[2]
对于探索方法,作者使用ε-贪婪。这“为有效性集合 f (e,x)中的所有非最优项目赋予了相等的概率质量,并且为最优动作(j∫,e∫)赋予了(1-ε)额外的质量。”[2]策略设置为“同时利用或探索项目和解释”[2]。
来源:[2]
训练程序本身没什么特别的。BaRT“定期以批处理方式进行重新训练。”[2]
协同过滤对于已经上传了一首歌或听过一首歌的用户和音乐来说效果很好。但是如果一个艺人是全新的,甚至还没有任何歌曲呢?这种类型被称为冷启动问题。对于新的和不受欢迎的歌曲,推荐系统失败。
Spotify 如何解决冷启动问题
在这种情况下,唯一有帮助的是分析原始音频文件。尽管这可能是最复杂的推荐类型,并且计算量也很大,但它在创建行业领先的推荐系统中起着至关重要的作用。
Spotify 的一名员工 Sander Dieleman 在 2014 年写了一篇关于他创建的一个模型的博客文章。它由四个卷积层和三个密集层组成。机器学习模型的输入不是原始音频文件,而是它们的表示,称为频谱。所以每首歌都被转换成 mel-spectorgram,这是一个独立的模式,有点像指纹(正如你在下图中看到的)。
一部电影。来源:光谱图
Mel 频谱图是音频的时间-频率图。mel 标度背后的想法是复制人类的听觉反应。
Dieleman 在他的博客文章中描述的网络如下(有四个 conv 层和三个密集层):[6]
来源:[6]
如图中两个 conv 层之间的小 MPs 所示,Dieleman 在每个卷积层后实现了一个池层。在四个 conv 层的最后一个之后,他设置了另一个全局时态池层,该层“跨越整个时间轴进行池化”。然后,将生成的要素放入三个完全连接的密集图层中,并使用经过校正的线性单元。最后一层输出 40 个潜在因素。
总共执行大约 750000 次梯度更新。我不记得这种特殊的架构花了多长时间来训练,但我尝试过的所有架构都花了 18 到 36 个小时。”—桑德·迪勒曼
Dielenman 的网络学习不同的过滤器,仅在第一 conv 层多达 256 个过滤器。正如他所说,一个过滤器学习颤音唱法,另一个学习铃声环境,第三个学习低音鼓,另一个学习三分之一声乐(多个歌手和声音)。其他过滤器有噪音、失真、特定音高、低音、特定和弦(如 A 和弦)等等。
你可能已经想知道 Dielenman 引用的文章和解释是 2014 年的,所以已经过时了。我确实相信,理解 Spotify 的算法还是有好处的。当然,7 年后,模型更加复杂,Spotify 在如何跟踪和分析方面获得了更多的洞察力,但在其主要特征方面,系统可能是相似的。
自然语言处理和音乐智能
你已经认为这是最后一款了吗?不,当然,Spotify 也使用 NLP。如上所述,Spotify 收购了 Echonest,从而收购了其音乐智能平台。而这个平台显然是基于网页抓取和自然语言处理的。这有助于 Spotify 跟踪超过 1000 万个网站,并通过自然语言处理分析它们的内容。这些网站包括博客、艺术家网站、社交媒体、论坛等等。最终,Spotify 可以设法观察讨论,跟踪什么是趋势,什么是新的,人们喜欢什么,人们不喜欢什么。甚至他们使用哪种语言来跟踪某些国家或地区的讨论。[8]
该系统识别与歌曲或艺术家相关的描述性术语和名词短语,并将这些关键词分类为文化向量和顶级术语。这产生了一组术语,这些术语基于权重显示了每个术语对于艺术家和歌曲的重要性。[8]
来源:https://notes . variogr . am/2012/12/11/how-music-recommendation-works-and-donts-work/
结论
依靠 NLP、基于内容的过滤和协作过滤的三重策略是一种非常复杂的确定客户音乐品味的方法。未来,Spotify 必须依赖并更加专注于分析音频数据,这比协作过滤更复杂,计算量更大。尽管如此,这三种类型都非常重要,随着越来越多的数据和更复杂的模型,Spotify 将能够越来越好地预测我们的音乐品味。
在私下使用 Spotify 时,我可以说他们在提供大量定制内容和推荐方面已经做得很好了。从推荐部分开始,一年来在 reverse Stories,the week 的混音中,当然还有很多更个性化的播放列表,基于我听的和其他人听的(有类似音乐品味的)。当然,Apple Music 或 Amazon Music 也可以提供这些服务,但最终,推荐系统的质量对用户体验至关重要。Spotify 尚未赢得这场战斗,但他们有一个清晰的战略,看起来很有希望。老实说,我希望 Spotify 能够战胜科技巨头。
https://medium.com/@hucker.marius/membership
消息来源
[1]公司信息(未注明)。https://newsroom.spotify.com/company-info/
[2] MCInerney,j .等人(2018 年)。探索,利用和解释:个性化的强盗可解释的建议。https://static 1 . squarespace . com/static/5a E0 d0b 48 ab 7227d 232 C2 bea/t/5ba 849 E3 c 83025 fa 56814 f 45/1537755637453/bartrecsys . pdf
[3]https://chaitanyabelhekar . medium . com/recommendation-systems-a-walk-trough-33587 fecc 195
[4]https://www . br . de/puls/musik/aktuell/Spotify-the-echo-nest-discover-weekly-100 . html
[5]https://TechCrunch . com/2015/06/24/把数据地毯从苹果下面拉出来/
[6]https://TechCrunch . com/2017/03/07/Spotify-acquisites-audio-detection-startup-sonalytic/
https://www.univ.ai/post/spotify-recommendations
[8]https://outside insight . com/insights/how-ai-helps-Spotify-win-in-the-music-streaming-world/
使用 Matminer 和 Pymatgen 发掘材料数据的潜力
原文:https://towardsdatascience.com/uncovering-the-potential-of-materials-data-using-matminer-and-pymatgen-83126fadde1c?source=collection_archive---------23-----------------------
基于 python 的材料库解读材料化学的步骤
材料四面体:图片由作者提供,灵感来自马库斯·斯皮斯克在 Unsplash 上的一张照片
简介
不同类型设备的使用是我们日常生活不可或缺的一部分。并且这些装置由构成日常应用材料的元素的无数组合制成。材料科学家从事这些材料的加工,研究它们的结构和性质。例如,为了开发一种新的半导体,材料科学家需要从元素周期表的调色板中选择最佳的成分组合,以使新的半导体具有正确的特性。
此外,材料的性能取决于从电子尺度到宏观尺度的三位一体的加工条件、结构及其各种结构和功能特性。于是,材料科学家们提出了**材料四面体的概念,其中顶点代表加工、结构、性质和性能,连接这些顶点的线表示它们之间的相互关系。这些相互连接也被称为 PSPP 连杆机构。**
一个全面的已发现材料库及其 PSPP 联系将极大地有利于材料科学家和工程师,他们的目标是设计下一代超级材料,如比现有锂离子电池更有效的电池,或比新特斯拉汽车更轻更坚固的汽车。
因此,从这些相互关联的参数中提取有意义的数据成为设计和发现高性能尖端材料的关键步骤。参数的数量可能如此多样,以至于很难提取所有这些参数之间基于物理学的因果关系。在这种情况下,机器学习(ML)可以通过提取这些参数之间的有用相关性来促进新知识的发展。
材料数据
不管使用什么算法,ML 的第一步也是最关键的一步是导入和预处理数据。干净的数据增加了训练的可靠性,并为成功的部署建立了机器学习模型。这些数据进一步分类为输入变量(在 ML 语言中也称为预测器/描述符)和结果(称为目标/响应)。
Image by author
材料数据包括一系列广泛的描述符。这些包括
- 加工条件: 成分与组成元素、温度、压力、升温和降温速率、相对湿度等。
- 结构信息: 原子或晶体结构的排列,微观结构和织构图案跨越长度尺度跨越几个 埃( 1 埃= 10 ⁻ ⁰ 米)和几百个 微米 (1 微米= 10 ⁻ ⁶米)。
- 物理性质: 密度、粘度、折射率、导热导电率等等。
- 机械性能: 韧性、硬度、屈服强度、弹性刚度、断裂韧性、延展性、硬度及其他。
目标或响应通常是决定材料整体性能的性质。
从给定数据集中挖掘重要特征是开发健壮的数据驱动模型的最关键和最具挑战性的步骤。否则,模型将遵循 GIGO (垃圾入垃圾出)规则。
我们可以用一个非常简单的例子来说明材料数据集中特征化的重要性。让我们考虑包含几种材料的化学式及其密度的数据集。化学式是由元素及其原子比例的组合来表示的。例如,化学式(AᵢBⱼCₖDₗ)包含四种元素 a、b、c 和 d,其中它们相应的下标 I、j、k 和 l 代表每种元素的原子数。例如,水的分子式是 H₂O,这意味着两个氢原子(h 是元素符号)和一个氧原子(用符号 o 表示)。
现在,为了了解特征之间的相关性,并从这些数据中设计超密度材料,我们需要挖掘每个元素对密度的贡献。这些单独的元素贡献成为目标变量预测的特征(描述符),在本例中为密度。因此,需要将配方分解成各个成分(或元素)及其相应的量。在诸如编码的传统 ML 技术中没有直接的方法来实现这个任务。然而,多亏了基于 Python 的素材库 Pymatgen 和 Matminer,这有助于实现这个目标。
在本文中,我将演示如何借助上述材料库从公式中导入组成元素及其数量。
预处理的逐步指南
在逗号分隔(csv)或 Excel 文件(XLSX)中列出描述符和目标变量是组织机器学习数据的好方法。一旦 csv/ excel 文件准备就绪,我们就可以将其导入到任何机器学习环境中。在这里,我将显示所有的步骤,写和运行,在 Jupyter 笔记本。出于同样的目的,你也可以选择谷歌 Colab 笔记本。
第一步:导入库
第一步也是最重要的一步是导入所有需要的基本库,如 Pandas、NumPy、Matplotlib。此外,安装材料数据挖掘( Matminer )和材料分析( Pymatgen )的专用库,然后导入必要的模块。Matminer 和 Pymatgen 都是开源的 python 库。
**import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from matplotlib.pyplot import figure**
第二步:加载数据
(这里使用的数据集是 原始数据集 的子集)。)
导入基本库之后,我们需要使用 pandas 从它们的文件路径加载和读取包含数据的 csv 或 excel 文件。在下面的代码片段中,前三列是指定为 X 的描述符变量,而最后一列是指定为 y 的目标变量。
**ds_PF_ZT = pd.read_csv('TE/csv/PF_ZT.csv')
X = ds_PF_ZT.iloc[:, 0:3]
y = ds_PF_ZT.iloc[:, -1]
ds_PF_ZT**
输出片段
现在,我们需要添加组成材料的单个元素(在上面的数据框架中表示为公式)作为预测值。这些基本因素与其他变量的协同作用导致了结果或反应。下面是 Pymatgen 和 Matminer 工具的应用程序,这些工具具有诸如 core.composition 和 featurizers.composition 之类的特性,可以将给定的公式分解成单个的元素。在进行编码活动之前,让我先介绍一下 Matminer 和 Pymatgen。
Pymatgen 和 Matminer:有益于素材数据预处理的库
Pymatgen 和 Matminer 都是用于材料数据挖掘和分析的开源 Python 库。
Pymatgen 有许多模块和子模块以及它们各自的类,帮助分析材料的结构和功能特性。我们将查看这样一个模块的应用:pymatgen . core . Composition和它的类: Composition 。这个类将数据集中的每个成分映射到单个元素,并以不可变和可哈希的形式映射到元素的数量,而不是像 Python 字典那样。在 Python 中,数据有两种类型: 可变和不可变 。可变数据的值可以被改变/变异,而不可变数据的值不能。可变数据的几个例子是列表、字典。另一方面,元组是不可变数据的典型例子。所有不可变的对象都是可散列的,这意味着这些对象都有唯一的标识号,以便于跟踪。
Matminer 有助于应用各种特征提取复杂的材质属性。几乎有超过 70 个特征器(matminer.featurizers)将材质属性转换成数字描述符或向量。我们将关注组合特征器和它的元素分数类来预处理我们的数据集。所述类计算成分中的单个元素的元素分数。
第三步:安装 Pymatgen 和 Matminer
**pip install pymatgen
pip install matminer**
注意:Matminer 和 Pymatgen 需要 Python 版本。
步骤 4:使用 Pymatgen 映射元素及其数量
**Compositionpymatgen 类将给定数据集中的每个公式拆分成组成元素及其数量。我们来看第一个公式,Ca0.98Bi0.02Mn0.98Nb0.02O3.0,在第 1 列第 1 行:
每个元素及其数量的映射
**from pymatgen.core.composition import Composition
ds_PF_ZT['Formula']
Comp = []
for value in ds_PF_ZT['Formula']:
Comp.append(Composition(value))
Comp**
输出片段
一个附加成分列被添加到仅包含对应于每个成分的组成元素的原始数据集中。
**ds_PF_ZT['Composition'] = Comp
ds_PF_ZT**
输出片段
步骤 5:使用 ElementFraction 类计算原子分数
我们现在需要在数据帧中添加单个元素及其原子分数,以进行机器学习。mat miner . featurezer . composition 中的一个名为“ElementFraction”的类服务于上述目的。
**from matminer.featurizers.composition import ElementFraction
ef = ElementFraction()**
然后,我们使用featureze _ data frame函数创建一个数据帧,它包含周期表的所有元素以及其他变量。dataframe 的尺寸增加到了 573 X 108 (在下面显示的代码片段的输出中用橙色圈起来)。
**ds_PF_ZT = ef.featurize_dataframe(ds_PF_ZT,'Composition')
ds_PF_ZT**
输出片段
让我详细说明元素分数计算。让我们考虑第一个组合(在给定数据集的公式列中)。该组合物 Ca0.98Bi0.02Mn0.98Nb0.02O3.0 具有五种元素:Ca(钙)、Bi(铋)、Mn(锰)、Nb(铌)和 O(氧)。公式中存在的 Ca 的量是 0.98,并且通过考虑公式中存在的其它元素的量来计算 Ca 的元素分数。因此,Ca 的元素分数为 0.196((0⋅98)/(0.98+0.02+0.98+0.02+3.0))。类似地,Bi、Mn、Nb 和 O 的元素分数分别为 0.004、0.196、0.004 和 0.6。对于这个公式,周期表中其余元素的元素分数保持为零。
步骤 6:降维并显示最终的、干净的、预处理过的数据
Photo by Tim Peterson on Unsplash
请注意,上面的数据帧包含许多只有零值的列。这是因为在给定数据集中的成分中不存在这样的元素。因此,这些零列从数据帧中省略,这导致数据帧的维度从 573 行×108 列减少到 573 行×57 列。
**ds_PF_ZT = ds_PF_ZT.loc[:, (ds_PF_ZT != 0).any(axis=0)]
ds_PF_ZT**
输出片段
上述预处理的干净数据帧是机器学习的最终形式。将响应或目标列作为最终数据帧中的最后一列是一个很好的做法。
代码发布于Github。**
结束语
在当代世界,“数据是新的石油”——这是英国数学家克莱夫·亨比创造的一个短语。因此,挖掘这个宝藏以获得最大的有用的潜在信息对于技术进步是必要的。从材料科学的角度来看,大量的材料属性、加工参数和元素构成了一个完整的数据集。这些细节构成了材料信息学的一部分,在新的高性能材料的发现中发挥着巨大的作用。揭示组成元素在材料属性中的作用是一项关键但棘手的工作。Matminer 和 Pymatgen 使这项任务变得更加容易。在这里,我描述了使用这些素材库的一些相关模块从原始数据集中收集基本信息。我希望这篇文章是信息丰富的,特别是对从事新材料设计和发现的工程师和科学家来说。
如果您需要任何澄清,请随时联系,并分享您的反馈和建议。
感谢您的阅读!
解开数据:使用 SQL 扩展聚合数据
原文:https://towardsdatascience.com/uncubing-data-using-sql-to-expand-aggregated-data-3a339194d88?source=collection_archive---------37-----------------------
用于分解聚集数据集的 SQL 技术
作者创建的图像
任何时候聚合数据,都会丢失包含在更细粒度中的信息。在 Sisu Data ,我们不断应用新技术来防止我们客户的信息丢失,因为我们知道有了更多的功能,分析可以更加全面和准确。
虽然广泛的平面数据是理想的,但有时你可能只能访问聚合数据,比如谷歌或脸书广告报告。这些工具导出摘要数据,其中主键是 utm_campaign 和 day(如下表所示),而不是点击甚至销售线索级别的粒度。
这些报告必须提供总体数据,因为粒度数据对于大多数用户来说太难处理。事实上,这种类型的表是现成的,可以用来可视化度量的日常性能,但是没有为更深入的分析留下多少空间。例如,您只能通过合计一天的花费,然后除以销售线索数,向上合计到每天的每销售线索成本(CPL)指标:
出局:
但是,如果我们需要快速获得不同因子值的许多不同子人群的平均 CPL,要求分组可能会很乏味。理想情况下,我们可以使用 AVG 来聚合行,使用 WHERE 子句来选择任何子群体。
分解表格以简化查询并找到准确的见解
为了详细说明,我们假设您想知道原始表中 student_special 活动的平均 CPL。如果您使用了查询
您将生成一个错误答案$530.50。正确答案是 ($183 + $1000) / 4 或 $295.75 ,因为 2020 年 12 月 5 日与 2020 年 12 月 6 日的销售线索数量不同。CPL 指标需要根据销售线索的数量进行适当加权。
正确的方法是按 utm_campaign 分组,并用 SUM(支出)除以 SUM(销售线索)得出平均 CPL。但是,如果我想在不同因子值的许多不同子人群中选择任何不同的平均 CPL,查询的复杂性会迅速增加。
相反,我们可以以不同的粒度对数据建模,并通过将每一行等同于一个销售线索来分解表格。这种方法将生成一个类似于下图的表:
此表支持简单的 cost_per_lead 平均值,而不必分组并使用 SUM(spend) / SUM(leads)。现在,如果我们在这个新表上再次使用上面的查询,
SELECT AVG(cost_per_lead) FROM campaign_table WHERE utm_campaign = 'student_special'
它将返回准确的 CPL,而不需要使用 GROUP BY。虽然为每个销售线索生成一个新行的表会占用更多的空间,但是向云数据仓库的转移会使额外的成本变得微不足道。
分解的 SQL 方法
虽然在 Python 中使用简单的行乘法命令将每一行分隔开很简单,但是在 SQL 中做同样的事情就比较复杂了。这里有一种用 SQL 解决这个问题的方法:
让我们来分解这个查询。前两个 cte ten _ numbers 和 gen_numbers 创建一个单列表格,列出从 0 到 99999 的数字。Ten_numbers 是十个数字的列表。然后,通过将其自身连接几次,我们扩展了十个数字的列表,使得每个十个数字的集合出现在数字中的不同占位符中:
- “ WHERE 1=1 ”子句创建 10 个数字的初始向量与不同列中相同的 10 个数字的所有可能组合,即[0,0];[0,1]…[0,10];[1,0];[1,1]…[10,10]
- 顶部的“选择”语句确保每个组合出现在数字中的不同占位符处,例如,一位数、十位数、百位数等。
有了这个数字矩阵,最后的代码片段扩展并复制了这些行:
SELECT campaign_table.* FROM campaign_table AS t JOIN gen_numbers AS g ON 1 = 1 WHERE g.gen_num <= t.leads
通过再次连接 1=1,我们创建了 campaign_table 中的行与 gen_numbers 表中的每个数字的所有可能组合,自动将 campaign_table 中的每一行复制 99,999 次。然后,通过使用 WHERE g.gen_num ⇐ t.leads,我们缩小了重复项的数量,使其与原始表中的 leads 数量相对应。
使用秤重来处理巨大的桌子
这种分解表的方法是内存密集型的,如果行需要复制数百万次,这种方法就不太值得了。但是,我们可以通过提取销售线索的数量并创建一个简单的权重列,轻松地将这种类型的权重精确到某个百分点。
例如,在下表中,您不需要创建 1700 万行。
相反,您可以创建一个新列,将 leads 值除以所有 leads 的总和,并指定一个浮点小数,这将得到该特定组贡献的 leads 占总 leads 的比例。
然后,将 leads proportion 列乘以 100 或 1,000,根据需要得到 1%或 0.1%的精确度。因此,gen_numbers 表可以从 99,999 个初始副本缩小到 99 个,精度为 1%,或者 999 个,精度为 0.1%。
gen_numbers AS ( SELECT (100 * t3.num) + (10 * t4.num) + t5.num AS gen_num FROM ten_numbers AS t3 ON 1 = 1 JOIN ten_numbers AS t4 ON 1 = 1 JOIN ten_numbers AS t5 ON 1 = 1 WHERE (100 * t3.num) + (10 * t4.num) + t5.num > 0 ORDER BY gen_num )
现在,在初始自连接中,每行只能复制 999 次。
有了一个被人工分解到更低粒度的聚合表,计算权重变得更快更容易,比如销售线索的数量或支出的金额。现在,我们可以用一个简单的 WHERE 子句获得多个子群体的平均值,这使得跨不同因子、列和日期周期的扫描变得更加容易。这极大地扩大了表的大小,但由于廉价的存储和闪电般的计算,这是一个值得做出的权衡。
希望利用您的粒度和聚合数据做更多事情?查看我们的设计更好的数据集指南或与团队取得联系,以帮助分析您的关键指标。
本帖原载于 Sisu Data 博客 。
一个不被重视的 ML/AI 工作流工具:MLOps 气流
原文:https://towardsdatascience.com/under-appreciated-workflow-tool-airflow-a078a3c71a67?source=collection_archive---------23-----------------------
介绍
Airflow 是一种工作流管理工具,在 MLOps 中经常被低估和较少使用。我在各种任务中使用 airflow 来自动化其中的许多任务,从以特定间隔运行人工智能模型,到重新训练模型,批处理,抓取网站,投资组合跟踪,定制新闻提要等。在这篇文章中,我们将回顾气流的基础知识以及如何开始。
布雷特·乔丹在 Unsplash 上的照片
什么是气流?
Airflow 是开发人员调度、执行和监控工作流程的工具。Airflow 最初由 Airbnb 开发,目前是 Apache 孵化器项目。Airflow 的最大优势是可以使用纯 python 代码创建工作流。它为开发人员提供了灵活性,可以根据需要阐明工作流,并以特定的频率调度或运行它。
Airflow 还可以连接从 AWS Lambda 到 GCP 数据流的云服务。在大多数场景中,大到中等规模的组织使用 Airflow 来处理大量的数据,并在其上执行一些数据操作。它也可以在集群模式下运行。AWS 和 GCP 提供了气流的管理实例,以便与其他云服务一起使用。
- AWS 管理的气流工作流程
- GCP 云作曲
气流术语
DAG:DAG 是一个有向无环图,代表一个单独的工作流。Dag 指示执行的工作流顺序。
操作符:操作符表示 DAG 的每一步正在执行什么任务。如 python_operator、s3_file_transform_operator 等。您可以在这里查看操作员列表
装置
安装可以在本地完成,也可以在基于云 Linux 的实例中轻松完成。否则气流码头集装箱可供您使用。
气流安装:https://air flow . Apache . org/docs/Apache-air flow/stable/installation . html
需要安装一些系统包,可以在上面的链接中看到,最后,在虚拟环境中安装 python 包。
pip install apache-airflow
在设置上可能会有一些挑战。但是,一旦您调试并修复了它,您可能会在启动 web 界面后看到如下所示的 web 界面。
作者图片
经营者
操作员是气流工作流程的核心部分。运算符可以是不同的类型。一些常用的运算符有
BashOperator
- Bash 命令被执行PythonOperator
-调用 python 函数EmailOperator
-发送电子邮件SimpleHttpOperator
-发送一个 HTTP 请求
这样的例子不胜枚举。你可以点击查看的完整列表。你可能会注意到一些云运营商也在列表中。所以你不需要从头开始写代码。
执行
可以使用 web UI、命令行或按计划触发工作流。
默认参数
下面是我们可以定制的一些参数。
按作者列出的工作流参数
气流代码
这里我们将使用一个简单的 dag 来安排它。Python 运算符可用于调用带有附加参数的 python 函数。
作者的简单 Dag 代码
您还可以在气流门户中看到气流的执行。下面是我的本地主机门户,它显示了 DAG 的执行。红色表示执行失败。
按作者列出的 Dag 执行
频繁调度
通常一次性设置是为了测试或开发。实时设置和自动交易需求不涉及日常设置,而实时系统会出现在画面中。理想情况下,我喜欢一切都自动化,所以它不需要我的干预。这是气流闪耀的地方。在下面的部分中,您可以执行一系列计划选项。
你甚至可以一分钟一分钟地计划。但是,我觉得有点矫枉过正。气流可以安装在云中持续执行。
按作者安排工作流
云中的设置
Airflow 可用作云提供商的托管服务,或用于在云中执行 airflow 的定制安装。查看这篇好的文章,了解在 EC2 实例中安装的分步说明。
用例
检查我的其他文章,看看气流用例。在这里,我们将回顾气流的一些使用案例:
- 经常运行人工智能模型预测
- 创建服务的完整产品安装
- 执行数据工程操作,如数据迁移
- 基于某些触发条件购买股票/密码
- 基于条件和人工智能的自动投资组合再平衡
- 基于反馈开始人工智能模型训练
这样的例子不胜枚举。
最后的想法
Airflow 是一个很棒的工作流工具,它为想要自动化大量工作的 python 开发人员和技术投资者提供了更大的灵活性。选项是无限的,以自动化的方式涵盖了各种各样的使用案例。
参考文献:
https://medium . com/@ Abraham . pabba thi/air flow-on-AWS-ec2-instance-with-Ubuntu-aff8d 3206171
请订阅我的 简讯 获取我的文章和其他更新的免费工作代码。
引擎盖下:相关性和共线性
原文:https://towardsdatascience.com/under-the-hood-correlation-and-collinearity-b6674b1fb33b?source=collection_archive---------26-----------------------
使用相关性充分利用您的数据和建模
unsplash.com/alinnnaaaa 摄
在我的上一篇文章中,我讨论了基尼系数,以及它如何帮助你建立决策树模型。然而,数学知识并不局限于解释机器学习算法的结果和性能。更重要的是,没有什么数据科学的概念不值得重新审视或更深入地研究。我们经常被新的、令人兴奋的项目和挑战所吸引,但有时回到我们认为已经理解的基础上是值得的。这是本文的驱动力;我希望讨论一个我们都认为自己了解冷的概念(我知道我以为我了解!),这样做可以为数据科学家工具箱中一个非常常用的工具增加更多深度。
在这篇文章中,我将讨论在任何建模之前的探索性数据分析的开始阶段,为了特征选择和潜在的特征工程的目的,对我们的数据中的相关性概念进行稍微深入的思考是如何有所帮助的。其中包括一个注意事项,并简要讨论了只关注高(或低)相关系数分数而忽略潜在的共线性会如何给你带来麻烦。
相关系数对你的数据说明了什么?
对于大多数数据科学家来说,这似乎是一个显而易见的问题,一个我们都很熟悉的问题。相关系数表示一个变量与另一个变量之间的关系强度:当一个值增加时,它如何影响另一个值?可能的值范围从-1 到 1。-1 表示完全负相关(x 增大,y 减小),1 表示完全正相关(x 增大,y 增大),0 表示完全不相关的数据(x 和 y 完全相互独立)。这是一种非常常用的方法来分析数据,并在探索性数据分析阶段识别强学习者以传递到模型中。事实上,对于我们这些 Python 用户来说,调用 pandas 的 df.corr() ,以及在 seaborn 或 matplotlib 中构建热图和散点图来可视化目标的特征,这些代码行对于数据科学家来说是如此常见,以至于我们甚至可以在不看键盘的情况下通过肌肉记忆来键入这些代码行(就在那里有*)。read_csv()* !).
然而,如果你调用 df.corr() 你得到的相关系数,比我上面提到的更微妙更具体。默认情况下,这种方法在分析相关性时会将 P 厄森相关系数应用到您的数据中。这是皮尔逊系数公式(或它的一种形式):
严格来说,这是对 x 和 y 之间的线性关系的强度(或存在/不存在)的测量。对于许多数据项目来说,这是识别数据相关性的合适方法。但是,通过使用皮尔逊系数,您假设线性的标准假设,例如同方差性(您的数据具有相等的方差,而不是在其他点或多或少地变化),并且您的数据近似呈正态分布。此外,该系数旨在应用于连续变量,虽然它对一些二进制分类变量(0 或 1)仍然有效,但它不适用于顺序变量(大于 0 或 1,也称为排序的变量)。最后一点,皮尔逊系数对于非正态分布的数据以及离群值非常不稳健。这是因为它度量的是线性相关性,当所度量的数据不能线性表达时,这个度量就不能准确描述相关性。
那么,如果你的数据不是线性的,你该怎么办呢?如果您计划首先应用非参数模型,那么度量线性关系有意义吗?例如,如果我计划运行支持向量机或 k 近邻模型,我为什么要关心线性度?在这些情况下,是时候调整熊猫的默认参数了。corr()方法。
斯皮尔曼的 Rho
Spearman 系数专门用于计算有序数据。您可以通过将 method = 'spearman '参数传入。corr()(df . corr(method = ' spearman ')。公式如下:
其中 D 是等级差,n 是样本量。和皮尔逊系数一样,斯皮尔曼系数的范围是-1 到 1,解释非常相似。然而,重要的是,这不是所描述的线性关系,而是单调关系。这是什么意思?在很高的层面上,记住不是每个函数都是线性的(比如指数曲线和复杂的公式)。在这些情况下,相对于 y 绘制的 x 的函数将不具有有意义的线性,但是这并不意味着该函数通常不趋向于正或负。这就是斯皮尔曼系数所描述的。例如,斯皮尔曼系数 1 表示当 x 增加时,y 总是增加,即使它没有增加相同的固定量(如曲线)。斯皮尔曼系数-1 正好相反:当 x 增加时,y 总是减少一些。系数为 0 意味着没有单调关系(x 的变化和 y 的变化之间没有一致的关系)。抛物线就是一个例子,增加 x 的负值会减少 y,但增加 x 的正值会增加 y。
简而言之,单调的关系表示关系在一个方向上的一致变化,但不假设线性。从寻找强学习者的数据科学家的角度来看,这里的要点是,当您的数据不是线性的、包含有序(分级)特征和/或您计划使用非参数估计器(如 KNN)时,在分析数据的相关性时应用 Spearman 系数。您得到的相关系数值将更加合适,并可能有助于您为模型识别更好的要素,这反过来意味着(希望)在需要考虑诸如增强或正则化等因素之前,模型会表现出更少的偏差和方差。
肯德尔的τ
同样,可以选择应用肯德尔的 Tau 系数(df . corr(method = ' Kendall '))。和斯皮尔曼的 rho,肯德尔的 tau 有很多相似之处。例如,Kendall 的 Tau 不做线性假设,因此在试图分析离散变量的相关性时是一个合适的选择。肯德尔的 Tau 测量变量的“一致性”(concordance),这同样是这些变量一起移动的趋势的指示(同样,随着 x 增加,y 也有增加的趋势),因此可以类似于其他两种方法进行解释。
就 Spearman 的 rho 和 Kendall 的 Tau 之间的差异而言,深入探究数学差异超出了本文的范围。然而,同样在高层次上,值得注意的是,Kendall 的 Tau 往往给出比 Spearman 的 rho 更低的值(不太可能得到接近 1 或-1 的值),但同时,Kendall 的 Tau 对数据中的错误和差异(如异常值)不太敏感。因此,如果您已经看到了与上述类似的情况,尤其是比较有序数据和非线性数据,但您还怀疑可能会产生误导性结果的差异和异常值,这是在探索数据和搜索模型中的理想特征时考虑使用肯德尔τ的绝佳案例。
关于特征选择相关性的注意事项
因此,您需要仔细分析您的数据,运行适当的相关系数,并选择最有希望的要素,即那些与您的目标具有最强正相关或负相关的要素。你训练并评估这个模型,然后…它显示出很高的方差。是时候应用正则化了,对吗?也许吧,但是你花在相关性分析上的时间是值得的,因为此时此刻相关性对你有利。
https://en.wikipedia.org/wiki/Multicollinearity多重共线性是回归中两个或两个以上解释变量相互高度线性相关的术语。尤其是在线性回归的情况下,这可能会导致模型中出现更高的方差。这是因为这些高度相关变量的微小变化会导致你的反应变量发生夸大的变化。这种夸大实际上会给模型的预测添加噪声,从而导致模型无法很好地利用验证数据进行概括。如果您的模型显示出较高的方差,请花时间检查您的要素之间的关系,因为这有助于识别要删除和/或聚合的良好要素,从而简化您的模型。快速检查一下你的回归模型的性能是否遭受多重共线性是方差膨胀因子(VIF) 。这是 VIF 公式:
简而言之,这会产生一个比率,该比率表示与没有多重共线性时的预期值相比,您在模型中预期会看到的方差膨胀程度。例如,VIF 为 2 意味着与要素中不包含多重共线性的模型相比,差异大约是前者的两倍。根据上面的文章,解释 VIF 时的一个很好的经验法则是:1 分完全不相关,多重共线性使 1-5 分略微膨胀,超过 5 分则高度膨胀。请务必利用这些工具,为您的决策提供信息!诚然,监管是一个强有力的工具,但无法与做出合理的统计和量化决策相提并论。
即使不做回归模型,也值得花时间检查解释变量之间是否高度相关,尤其是如果您的早期模型显示出高方差。当然,VIF 是无法计算的,因为在分类模型中没有 R 分数,但是检查解释变量的相关性仍然可以使用 df.corr() 进行相互比较。在试图简化模型时,使用这些信息做出正确的决策!
总之
很容易被数据项目中的“大问题”分散注意力,或者在试图最大化其性能时完全专注于模型及其超参数。通常,项目中更“简单”的部分,比如数据的相关性,很容易被忽略。这可能是一个很大的错误,这是一个例子,说明耐心和明智的决策实际上可以使你成为一个更有效的数据科学家,而不是仅仅依赖网格搜索和微调各种参数,希望找到模型的最佳性能。
**使用 df.corr() 分析要素的相关性就是一个很好的例子。如果没有使用合适的系数来测量相关性,将不会收到任何错误消息或警告,因此很容易认为根据这些结果在模型中构建要素没有问题。然而,这可能会导致一个次优模型,您现在必须花费数小时或数天来调整、微调和令人沮丧地与之搏斗,如果您选择了更合适的功能(或排除了潜在的问题),它可能会“开箱即用”地工作得更好。永远不要忘记,作为一名数据科学家,你不是一个拿工资打字的按钮工。将()"放入脚本中。一个伟大的数据科学家不仅知道数据背后的数学原理,还有点像哲学家;询问“这对我的数据意味着什么?”从这个角度来看,正如我的导师和导师经常告诉我的那样,我们甚至是艺术家,几乎是在用我们处理的数据画画。对你遇到的数据要有耐心和深思熟虑,并使用你所掌握的工具,你将会比匆忙地跳过“简单”的步骤更有效和高效。
引擎盖下——神经网络到底是如何工作的?
原文:https://towardsdatascience.com/under-the-hood-how-do-neural-networks-really-work-7b48b171dc8c?source=collection_archive---------14-----------------------
使用 MNIST 数据集理解神经网络背后的数学——这是我从 fast.ai 中获得的主要收获
神经网络构成了深度学习的核心,这是机器学习的一个子集,我在我的上一篇文章中介绍了。接触过人工智能的人通常对神经网络如何工作有一个很好的高层想法——数据从神经网络的一层传递到下一层,这些数据从最顶层传播到底层,直到以某种方式,算法输出关于图像是吉娃娃还是松饼的预测。
看不出区别吗?图像识别软件可能比人类更难做到。图片来自 FreeCodeCamp (BSD-3 许可证)。
似乎很神奇,不是吗?令人惊讶的是,计算机视觉模型的神经网络可以用高中数学 来理解。它只需要以最简单的方式进行正确的解释,让每个人都明白神经网络是如何在引擎盖下工作的。在本文中,我将利用 MNIST 手写数字数据库来解释从头开始利用神经网络创建模型的过程。
在我们开始之前,重要的是强调一下为什么我们需要理解神经网络是如何工作的。任何有抱负的机器学习开发者都可以简单地使用 10 行代码👇来区分猫和狗——那么为什么要费心去了解它们下面发生了什么呢?
以下是我的观点:如果不能完全理解机器学习中发生的事情,我们将 1)永远无法完全定制所需的代码,并使其适应现实世界中的不同问题,2)调试将是一场噩梦。
简而言之,一个初学者使用一个复杂的工具却不了解这个工具是如何工作的,他仍然是一个初学者,直到他完全理解大多数事情是如何工作的。
在本文中,我将介绍以下内容:
- 深度学习预测如何工作的概述
- 完成导入的先决条件,并处理数据
- 深入 7 个步骤创建一个单层机器学习模型
- 使用激活功能创建多个层
对计算机生成的预测如何工作的高层次理解
为了完全理解这一点,我们必须回到术语“机器学习”首次流行的地方。
根据人工智能的早期先驱之一、世界上第一个成功的自学程序的创造者亚瑟·塞缪尔的说法,他是这样定义机器学习的:
假设我们安排一些自动方法来测试任何当前权重分配在实际性能方面的有效性,并提供一种机制来改变权重分配以最大化性能。我们不需要研究这样一个过程的细节,就可以看出它是完全自动化的,并且看出这样编程的机器会从它的经验中“学习”。
从这句话中,我们可以确定机器学习的 7 个基本步骤。在识别任意两个手写数字“2”或“9”的上下文中:
- 初始化重量
- 对于每张图片,使用这些权重来预测它是 2 还是 9。
- 从所有这些预测中,找出模型有多好。
- 计算梯度——测量每个重量,改变重量将如何改变损失
- 根据计算结果改变所有权重
- 返回步骤 2,重复
- 迭代直到决定停止。
我们可以在下图中看到这 7 个步骤的流程:
图片作者。
是的,看这个有点让人不知所措,因为有很多新的技术术语可能不熟悉。什么是重量?什么是时代?请继续关注我,我将在下面一步一步地解释这些。这些步骤可能没有太多意义,但是坚持住!
先决条件—导入、处理数据
首先,让我们完成所有的先决条件—导入必要的包。这是开始创建任何计算机视觉模型的最基本步骤。我们将使用 PyTorch 和 fast.ai。由于 fast.ai 是一个构建在 PyTorch 之上的库,本文将解释fast . ai 内置函数的一些是如何编写的(例如,上述要点第 9 行的 learner 类)。
from fastai.vision.all import *
from fastbook import *
其次,让我们从 MNIST 数据集中抓取图像。对于这个特殊的例子,我们必须从手写数字 2 和 9 的训练目录中检索数据。
在谷歌 Colab 笔记本^.上图片作者。
为了找出文件夹包含的内容,我们可以使用。 fast.ai 中的 ls()函数。然后,我们打开图片,看看它到底是什么样子-
图片作者。
如你所见,这只是一个手写数字“2”的图像!
然而,计算机无法识别像这样传递给它们的图像——计算机中的数据被表示为一组数字。我们可以在这个例子中说明:
这说明了图像“2”是如何在张量(列表的列表)中表示的。图片作者。
现在,所有这些数字代表什么?让我们使用熊猫为我们提供的一个方便的功能来看看它:
正如你可以模糊地辨认出手写数字的轮廓,上面张量中显示的数字是不同像素的激活,0 代表白色,254 代表黑色。图片作者。
如上所示,计算机解读图像的主要方式是通过像素形式的**,像素是任何计算机显示器的最小构建块**。这些像素以数字的形式记录下来。
既然我们对计算机如何真正解释图像有了更好的理解,让我们深入研究如何操纵数据来给出我们的预测。
数据结构和数据集
在计算预测之前,我们必须确保数据以相同的方式组织,以便程序处理所有不同的图像。让我们确定我们有两个不同的张量,每个都代表数据集中所有的 9 和 2。
使用 torch.stack 将不同的张量组合在一起。
在进一步深入之前,我们必须讨论一下张量到底是什么。名字里第一次听说张量这个词 TensorFlow ,是个(完全!)我们正在使用的独立库。在这种情况下,PyTorch 张量是一个多维数据表,所有数据项都属于同一类型。列表或数组与 PyTorch 张量之间的区别在于,这些张量完成计算的速度比使用传统 Python 数组快得多(几千倍)。
解析所有我们收集的作为模型训练数据的数据并不能解决问题——因为我们需要一些东西来检查我们的模型。我们不希望我们的模型在我们的训练数据上过度训练或过度拟合,在训练中表现非常好,但在训练数据之外遇到从未见过的情况时就会崩溃。因此,我们必须将数据分成训练数据集和验证数据集。
为此,我们会:
正在为数字“2”和“9”创建验证张量堆栈。图片作者。
此外,我们必须创建变量——自变量和因变量来跟踪这些数据。
train_x = torch.cat([stacked_twos, stacked_nines]).view(-1, 28*28)
这个 train_x 变量基本上会把我们所有的图像作为自变量(也就是我们要测的东西,想想:5 年级科学!).
然后我们创建因变量,赋值‘1’代表手写的 2,赋值‘0’代表数据中手写的 9。
train_y = tensor([1]*len(twos) + [0]*len(nines)).unsqueeze(1)
然后,我们创建一个基于自变量和因变量的数据集,将它们组合成一个元组,一种不可变列表的形式。
然后,我们对验证数据集重复该过程:
图片作者。
然后,我们将两个数据集加载到一个具有相同批处理大小的数据加载器中。
现在我们已经完成了数据的设置,我们可以开始用我们的模型处理这些数据了。
创建一层线性模型
我们已经成功地完成了数据的设置。回到机器学习的七个步骤,我们现在可以慢慢地完成它们。
步骤 1:初始化权重
什么是重量?权重基本上是变量,权重分配是对这些变量的值的特定选择。可以想到的是,为了使程序正常工作,每个数据点都被赋予了重点。换句话说,改变这些权重集将改变模型,以针对不同的任务表现不同的行为。
这里,我们为每个像素随机初始化权重—
权重和偏差(由于权重有时可能为零而存在,我们希望避免这种情况)一起构成了参数。
有件事困扰着我——与输入一个随机数相比,有没有更好的初始化权重的方法?
原来,神经网络中的随机初始化是一个特定的特征,而不是错误。在这种情况下,随机优化算法(将在下面解释)在向下搜索之前使用随机性来选择搜索的起始点。
第二步:预测——对于每张图片,预测这是 2 还是 9。
然后我们可以继续计算我们的第一个预测:
接下来,我们使用*小批量:*计算其余数据的预测
在这种情况下,小批量包含 4 个值,因此有 4 个输出值。以上图片由作者提供。
👆这一步是至关重要的,因为它有能力计算预测,并且是任何神经网络的两个基本方程之一。
第三步:利用损失函数来理解我们的模型有多好
为了找出模型有多好,我们必须使用损失函数。这是“根据实际表现测试任何当前权重分配的有效性”的条款,并且是模型将如何更新其权重以给出更好预测的前提。
考虑一个基本的损失函数。我们不能使用准确度作为损失函数,因为准确度只会在对图像是“2”还是“9”的预测完全改变的情况下才会改变——在这种意义上,准确度不会捕捉到模型预测结果的置信度或确定性的微小更新。
然而,我们可以做的是创建一个函数,该函数记录模型给出的的预测值(例如,对于它正在解释的图像更接近于 2 而不是 9 的相当确定的预测,它给出 0.2)和与之相关的实际标签(在这种情况下,它将是 0,因此预测值和模型之间的原始差值损失将是 0.2)。
但是等等!正如您从输出中看到的,并不是所有的预测 w 都在 0 和 1 之间,其中一些可能真的很远。我们想要的是另一个函数,它可以挤压 0 和 1 之间的值。
嗯,有一个方便的函数——它被称为 Sigmoid 函数。它基本上是一个数学函数,由(1/ 1+e^(-x)给出,包含 0 到 1 之间的所有正数和负数。
Sigmoid 函数的可视化。图片来自维基百科。
Sigmoid 函数在这里非常方便,因为我们可以使用随机梯度下降法(下一节)来计算任意输入处的曲线梯度。
现在,可能有些人在通过介绍性视频学习机器学习时会有一种误解——我当然有一些。如果你在网上用谷歌搜索,Sigmoid 函数通常是不被认可的,但是在批评它之前,了解一下使用 Sigmoid 函数的上下文是很重要的。在这种情况下,它只是作为一种压缩损失函数在 0 和 1 之间的数字的方法。我们而不是使用 Sigmoid 作为激活函数,这将在后面讨论。
因此,我们可以计算我们的*小批量:*的损失
步骤 4:计算梯度——随机梯度下降的原理
由于我们可能从任何给定的权重(随机权重)开始,机器学习模型的要点是在模型的训练限制内达到最低可能损失的**。**
这听起来可能很复杂,但实际上只需要高中数学就能很好地理解这个概念。假设我们的损失函数是任意的二次函数 y = x,我们想最小化这个损失函数。我们会立即想到这个函数的导数或梯度为零的点,这个点恰好在最低点(或“谷”)。在这一点上画一条与曲线相切的线,就会得到一条直线。我们希望程序不断更新自己,以达到最小点。
达到任何给定损失函数的最小值是至关重要的。
梯度下降的本质。以上图片由作者提供。
这是机器学习中损失最小化的主要方式之一,它提供了如何快速加快模型训练的广泛概述。
为了计算梯度(不,我们不需要手动计算,所以你不需要翻出你的高中数学笔记),我们编写以下函数:
步骤 5:基于计算的梯度改变权重(步进权重)
为了改变 calc_grad 函数的权重,我们必须步进该函数,使我们的值接近损失函数的最小值。我们通过一段非常重要的代码来实现这一点,如下所示:
如果你已经走了这么远,就是这样!这些是以线性方式训练模型一次所需的原始步骤。步骤 1 到 5 基本上是遍历一次数据需要的基本步骤,遍历一次数据的周期称为“epoch”。
随机梯度下降(SGD) 和梯度下降(GD) 的区别是“对于 xb,yb 在 dl 中”这条线——SGD 有,GD 没有。梯度下降将计算整个数据集的梯度,而 SGD 计算不同大小的小批量的梯度。
现在,为了简单起见,我们将所有其他函数(验证、准确性)合并到更高级别的函数中,并将不同的批处理放在一起:
步骤 6:从步骤 2 开始重复
然后,我们将所有函数传递到一个 for 循环中,重复这个过程一定次数,直到我们的精度提高到最佳水平。
到第 25 次迭代时,我们的模型现在可以达到几乎 100%的准确率——这意味着它几乎可以肯定地预测手写数字是“2”还是“9”!
**耶!我们刚刚建立了一个线性(一层)网络,它能够在很短的时间内训练出惊人的精确度。
为了优化这一过程并减少低级函数的数量(当然,也为了让我们的代码看起来更好),我们使用了预建的函数(例如,一个名为学习者的类),这些函数与之前的代码行具有完全相同的功能。
使用激活功能创建多个层
我们如何从线性分层程序发展到多层程序?关键在于一行简单的代码-
这被称为激活函数,它将两个线性层组合成一个双层网络。
人工神经网络与生物神经元的可视化。图片来自斯坦福的 cs231n。
特别是这个 res.max 函数也被称为整流线性单元(ReLU) ,这是一种“将所有负数转换为零,保留正数不变”的花哨说法。这是一个这样的激活函数,还有很多其他的——比如 Leaky ReLU、Sigmoid(不赞成专门用作为激活函数)、tanh 等等。
ReLU,观想。图片来自维基百科。
既然我们已经了解了如何将两个不同的线性层结合在一起,现在我们可以创建一个简单的神经网络:
然后我们最终可以使用我们的双层人工神经网络来训练我们的模型:
更有趣的是,我们甚至可以看到模型在这个简单的网络架构的各个层中试图处理什么图像!
在这种情况下,它正在识别手写“9”数字的曲线:)
结论
理解人工神经网络内部的情况起初似乎令人生畏,但如果我们必须从头开始构建一个模型,这是定制和理解模型的哪些部分出错的关键。要深入研究人工智能,需要的只是决心、一台正常工作的计算机,以及对高中数学概念的一些基本理解。
如果你想玩玩代码,看看它是如何工作的,点击这个链接自己试试吧!或者,您可以在这里查看我的 github 存储库:https://github . com/danielcwq/mni ST 2-9/blob/main/mni ST 2 _ 9 . ipynb
请随时联系我的网站!
在应用程序编程接口(API)的掩盖下
原文:https://towardsdatascience.com/under-the-hood-of-application-programming-interfaces-apis-30f5be4b996f?source=collection_archive---------39-----------------------
简化 API 的行话
马库斯·温克勒在 Unsplash 上的照片
T 他的文章谈到了应用程序编程接口(API)。今天,API 是现代软件开发的核心。它们变得如此普遍,以至于像“嘿!为此使用一个 API 或*“已经有一个 API 了”*在软件人的对话中经常使用。事实上,围绕 API 的行话也已经开始在日常语言中使用。但有时“不太懂技术”的人可能会发现很难理解这些术语。因此,本文试图以一种易于理解和联系的方式解释 API 背后的概念。
什么是 API?
在回答这个问题之前,我们先从概念层面来思考一个软件程序。从根本上说,软件程序是一堆代码,它们接受一些输入,进行一些处理,并给出一些输出。通常,这些代码是可重用单元的集合,如函数、模块或例程。
假设我们有一个软件程序,它接受一个文本字符串作为输入,并返回一组匹配的数据。所以,也许我们输入“冰淇淋”作为搜索项,程序会返回喜欢冰淇淋的顾客的名字。
作者图片
现在,假设我们有一个将输出(在这个例子中是名字)翻译成日语的需求。怎么做?
一种选择是,我们雇用一组人工翻译人员,他们获取输出,手动翻译并将其存储回数据库。这将是非常繁琐和低效的。下一个选择是修改软件,添加一些可以自动将输出翻译成日语的代码。这将是一个理想的解决方案,但同样需要大量的技术和语言专业知识来开发它。
我们认识一个朋友,他拥有一个软件程序,可以完全满足我们的需求。他的软件程序可以将文本作为输入,并将日文翻译文本作为输出。
作者图片
如果我们能以某种方式使用我们朋友的程序,我们的问题就解决了。但是当然,我们的朋友不会把他的软件程序原样给我们。这是他的知识产权。但是,他可以做一个安排。如果我们的程序可以将英文名字发送给他的程序,而他的程序会将翻译好的日文文本返回给我们,那会怎么样呢?我们不需要知道他的软件程序里面有什么。我们可以根据需要简单地使用这个程序的功能。我们只需要确保我们以一种他的程序能够理解的特定方式或格式给出英文名字。这就像他给自己的程序提供了一个 【接口】 ,然后程序可以翻译这些名字,并返回给我们(或给我们)译文。这种一个程序从另一个程序获取服务的安排叫做 API。真的!!正如 GUI(图形用户界面)是人与软件交互的工具一样,API 是一个软件程序与另一个软件程序交互并使用其功能的工具。
用技术术语来说,我们的朋友可以让我们访问他的软件的 API。我们可以在程序中使用这个 API 来满足我们的需求。我们**“调用”这个 API,API 给我们一个“响应”**。
作者图片
API 有什么用?
不同的公司根据他们的专业领域解决不同的问题。谷歌地图是查找位置的绝佳应用。你可以输入一个地址,它会显示你的位置(基本上,它可以找出这个地方的纬度和经度)。比方说,一家公司正在开发一个应用程序,其需求之一是找出一个地方的位置。他们可以简单地使用谷歌地图 API 并继续他们的其他开发,而不是为这一需求开发自己的软件。这将节省他们大量的时间和精力。此外,他们可以更专注于自己的专业领域。这是一个使用 供应商 API 或第三方 API 的例子,即我们与外部公司合作使用他们的服务。
由于与 API 的交互使事情变得如此高效和省时,公司可以决定将他们的应用程序或软件作为一组交互的 API 来设计和开发。例如,如果我们正在构建一个预订电影票的应用程序,我们可以决定围绕不同的 API 来构建我们的代码——每个 API 执行一个特定的操作。
作者图片
我们的内部团队可以在应用程序的其他部分使用这些 API,如果需要,甚至可以在公司内部的其他项目中使用。这些 API 被称为内部 API。
这种将软件构建为一堆交互 API 的方法最近变得非常流行。有人称之为微服务。
一些公司可能决定向公众免费提供他们的 API。这些被称为公共 API。例子有 Twitter API 或者 PubMed API 。他们发布了开发者可以遵循的关于如何使用这些 API 的说明。
如何构建一个 API?
API 的主要好处:它可以被许多人使用,跨许多应用程序,不需要理解它里面写了什么。为了使它如此通用,API 的开发者应该遵循一个标准的方法或者一套通用的规则。这就是所谓的协议。最常见的协议称为 REST ,使用该协议构建的 API 称为REST API。(还有其他协议,比如 SOAP,但它们不再像 REST 那样流行)
REST 代表RepresentationSstateTtransfer。这不是一个非常直观的缩写。要记住的主要事情是,它是一组规则*,通过这些规则构建一个 API。规则如:*
- 通过 API 发出请求有一种特定的方式或格式
- 接收来自 API 的响应有一种特定的方式或格式
- API 以特定的方式或格式表示响应的内容
- 有一种使用 API 进行身份验证的特定方式
以预订电影票的应用程序为例,我们的“搜索电影”REST API 类似于:
https://dummy movie company/movies
这被称为*“终点”——*这将向我们展示数据库中可用的电影列表
每个 REST API 请求也需要一个*【方法】*来指定它到底需要什么。有 4 种最常用的方法:
***获取:*从服务器读取数据
***上传:*在服务器上保存数据
发布:开始一个动作(例如预定电影)
***删除:*从服务器中删除数据
在下面的帖子中解释了用 Python 从头开始构建 REST API 的一步一步的例子。
* *
理解 API——它们是什么,它们如何交互,以及它们做什么,是在当前软件开发环境中必须掌握的技能。希望这篇文章能对不熟悉这些概念的读者有所帮助。
我现在将把我支持 API 的理由搁置起来!:)
梯度增强及其 Python 实现
原文:https://towardsdatascience.com/under-the-hood-of-gradient-boosting-and-its-python-implementation-99cc63efd24d?source=collection_archive---------9-----------------------
助推技术
机器学习中的助推算法——第三部分
唐纳德·詹纳蒂在 Unsplash 上的照片
到目前为止,我们已经在第一部分中讨论了升压的一般含义和一些重要的技术术语。我们还在第 2 部分的中讨论了 AdaBoost(自适应增强)的 Python 实现。
今天我们来讨论另一个重要的 boosting 算法:梯度 Boosting 。它是 AdaBoost 的一个很好的替代方案,有时甚至超过 AdaBoost。
梯度增强使用梯度下降算法,它试图通过梯度下降来最小化误差(残差)。
就像其他提升技术一样,在梯度提升的训练过程中,通过纠正先前树的错误,每个新树都被添加到集成中。
与 AdaBoost 相反,梯度增强中的每个新树都适合于由先前树的预测产生的 残差 。
有一个增强版本的梯度增强,称为 XGBoost(极限梯度增强),将在第 4 部分讨论。
残差
在讨论梯度增强是如何工作的之前,我们想了解一下残差背后的想法。
数学上,模型中的残差可以定义为实际值和预测值之间的差异。
**Residual = Actual value — Predicted value**
残差可以是正数,也可以是负数。
梯度增强的手动实现
为了理解梯度增强是如何工作的,我们需要手动实现该算法。为此,我们使用加州房价数据集做了一个回归任务。请注意,梯度增强也适用于分类任务。
数据集的前几行如下所示:
import pandas as pddf = pd.read_csv('cali_housing.csv')
df.head()
(图片由作者提供)
目标列是最后一列(MedHouseVal)。因此,我们将 X(特征矩阵)和 y(目标列)定义如下:
X = df.drop(columns='MedHouseVal')
y = df['MedHouseVal']
然后,我们为 X 和 y 创建训练集和测试集
现在,我们准备好手动实现梯度推进。
**第一步:**在集成中训练初始决策树。这棵树被称为基础学习者。用 max_depth=1 调节。所以,这棵树被专门称为决策树桩。
**第二步:**对第一棵树进行预测。
tree_1_pred = tree_1.predict(X_train)
**第三步:**计算第一棵树的预测残差。
tree_1_residuals = y_train - tree_1_pred
**第四步:**在第一棵树的残差上训练第二棵树,进行预测,计算残差。
同样,我们可以根据第二棵树的残差训练第三棵树,进行预测并计算残差。
这是第三次迭代的结尾。我们继续构建新的树,直到残差接近 0。整个过程可能包含由 n_estimators 定义的数百或数千次迭代(这将在后面讨论)。
第三次迭代后,我们可以计算 RMSE 值。
(图片由作者提供)
y 单位的近似值为 0.86。我们可以通过增加迭代次数来最小化这个值。但是,我们不能手动操作。Scikit-learn 提供了以下特殊类来轻松实现梯度增强。
- 【GradientBoostingRegressor()—用于回归
- GradientBoostingClassifier()—用于分类
Scikit-learn 梯度增强的实现
现在,我们使用 Scikit-learn 的GradientBoostingRegressor()类在同一数据集上训练梯度增强模型。
(图片由作者提供)
在使用 100 次迭代后,RMSE 值显著降低!然而,这也取决于最大深度和学习率**。让我们测量每个超参数的影响。**
测量 n 估计量的效果
在 1 到 500 的范围内,我们将测量 n_estimators 的效果,并绘制由梯度推进模型给出的测试 RMSE 值。
(图片由作者提供)
随着估计器数量的增加,RMSE 值逐渐减小,并在 400 次迭代后保持不变。最好选择 300 到 500 之间的值。如果选择更高的值,模型将需要很长时间来完成训练过程。
测量 max_depth 的效果
在 1 到 5 的范围内,我们将测量 max_depth 的效果,并绘制由梯度推进模型给出的测试 RMSE 值。
(图片由作者提供)
****最大深度的最佳值为 2。
衡量学习率的影响
在 0.1 到 1.0 的范围内,我们将测量 learning_rate 的效果,并绘制梯度增强模型给出的测试 RMSE 值。
(图片由作者提供)
最好的学习率是 0.4 或 0.7。
使用随机搜索找到最佳超参数值
在这里,我们用 随机搜索 一下子找到最优的超参数值。我们也可以使用网格搜索,但这需要几个小时才能完成。
(图片由作者提供)
您可以将这些超参数值与之前逐个获得的值进行比较。
摘要
到目前为止,我们已经完成了 2 个 boosting 算法。在梯度增强中,RMSE 值受 n_estimators 、 max_depth 和 learning_rate 的值影响很大。
最佳超参数值将根据您拥有的数据集和许多其他因素而变化。
有时,梯度增强可以胜过 AdaBoost。但是,梯度推进比随机森林好得多。
在第 4 部分中,我们将讨论 XGBoost(极限梯度增强),一个梯度增强的增强版本。下一个故事再见。祝大家学习愉快!
我的读者可以通过下面的链接注册成为会员,以获得我写的每个故事的全部信息,我将收到你的一部分会员费。
**https://rukshanpramoditha.medium.com/membership
非常感谢你一直以来的支持!
特别感谢 Unsplash 上的 Donald Giannatti ,为我提供了这篇文章的封面图片。
鲁克山普拉莫迪塔
2021–10–24**
模式识别和机器学习的基本方法
原文:https://towardsdatascience.com/under-the-hood-of-modern-machine-and-deep-learning-d76fc1249467?source=collection_archive---------6-----------------------
现代深度和机器学习“在引擎盖下”有许多经典的方法。内森·范·埃格蒙德在 Unsplash 上拍摄的照片
在机器和深度学习的引擎盖下
经典 ML 方法综述
现代深度学习方法每天都会产生非凡的结果。为了理解它的基础,最好也理解经典的模式识别和机器学习方法。在 2020/21 年的冬季学期,我教了一门关于这个主题的课,这是完全可以作为开放存取材料获得的。你可以在 Zenodo 上找到 PDF 格式的幻灯片,在 github 上找到相应的 TeX 源文件。所有材料都通过许可证在 CC 4.0 下获得许可。在这篇文章中,我将对所有材料进行概述,并对每一章进行简短介绍,同时提供相应的视频和文字记录链接。
经典模式识别将学习过程分为训练和测试阶段。这对于任何有监督的、无监督的或强化学习方法都是一样的。图片来源:维基共享下 CC BY 4.0
第 1 章—简介
在第一章中,我们回顾了机器学习和模式识别的基本原理。尼曼的模式识别管道使用每个机器学习系统中基本出现的基本步骤引入了这一思想,并从数据处理的角度引入了对监督、非监督和强化学习系统有效的概念。基于这些观察,给出了详细的课程概述,并介绍了基本概念,如贝叶斯定理,最佳分类和评估措施。
模式识别流水线— 视频 — 抄本
模式识别公设— 视频 — 抄本
详细课程概述— 视频 — 抄本
贝叶斯定理— 视频 — 抄本
最优分类器— 视频 — 抄本
评价措施
高斯钟形曲线通常用于模拟类别分布。图片来源:维基共享资源
第 2 章——阶级分布和阶级界限
机器学习方法的一个关键要素是如何对底层分类问题建模。在本章中,我们介绍了逻辑函数(也称为 sigmoid 函数),它是两个概率分布相交的一般结果,即两个类别之间的决策边界。如果使用高斯钟形曲线对类进行建模,则它们之间的决策边界通常会产生二次函数。对于指数族的所有分布,我们可以观察到类别之间的判定边界是线性的,如果它们共享相同的分散参数,例如高斯分布的相同协方差矩阵。基于这些观察,我们可以证明,我们可以使用嵌入到逻辑函数中的回归问题来直接估计类之间的决策边界。本章以朴素贝叶斯分类器的描述结束,该分类器假设所有类的对角协方差矩阵。
逻辑函数— 视频 — 抄本
高斯人&他们的交集— 视频 — 抄本
指数家庭— 视频 — 抄本—
逻辑回归&损失函数— 视频 — 抄本
逻辑回归—函数拟合— 视频 —
并不是每一个低维度的投影都能够保留类别信息(这里是:颜色)。图片来源:维基共享资源
第 3 章—类最佳特征变换
在本章中,我们将讨论特征转换及其对后续分类任务的影响。如果我们能够将所有类别转换到一个空间中,在该空间中,它们共享它们的分散参数,则所有决策边界都将是线性的,并且随后的分类任务将更容易解决。线性判别分析(LDA)是一种变换,它假设情况是这样的,并确定进入这种分离超空间的最佳投影。
线性判别分析简介— 视频 — 抄本
线性判别分析—属性— 视频 — 抄本
约束、凸优化&正则化— 视频 — 抄本
降秩形式的 LDA—视频 — 抄本
LDA —原公式— 视频 —
即使对于高度非线性的问题,我们能找到最优和唯一的决策边界吗?内核技巧有助于解决这个问题。图片来源:维基共享资源
第四章——最优且唯一的分离超平面
在这一章中,我们研究是否能找到唯一的最优决策边界。为了做到这一点,我们首先要重温几个基本的数学原理。正则化是一种数学工具,它允许我们找到唯一的解决方案,即使是对于高度不适定的问题。为了使用这个技巧,我们回顾了规范以及它们如何被用来指导回归问题。Rosenblatt 的感知器和多层感知器(也称为人工神经网络)天生就有这种不适定性。作为一种补救措施,通常可以采用适当的规范和正规化。在大多数情况下,产生的优化问题是使用梯度下降程序解决的。有趣的是,规范的使用也会影响到最终梯度的方向。有了这些新的理论见解,我们接着引入支持向量机的概念。他们使用对偶,即原始问题到对偶变量的映射,即拉格朗日乘数,来解决问题。这允许找到全局最优的、唯一的解决方案。支持向量公式的一个副作用是,原始问题也可以被映射到高维空间,其中非线性决策边界变成线性边界。这被称为内核空间。使用 Mercer 定理,我们探索了不同的选择来构建这样一个空间,包括序列核。此外,核技巧可以用于机器学习中的其他众所周知的概念,例如主成分分析(PCA ),并且它甚至可以与流形学习相结合,从而产生拉普拉斯支持向量机。
正则化回归— 视频 — 抄本
规范和单位球— 视频 — 抄本
规范依赖回归— 视频 — 抄本
罗森布拉特的感知器— 视频 — 抄本
多层感知器— 视频 — 抄本【T23
支持向量机的概念— 视频 — 抄本
优化中的对偶— 视频 — 抄本
支持向量机—优化— 视频 — 抄本
梅塞定理和核 SVM — 视频 — 抄本
核 PCA 和序列核— 【T55
使用期望最大化算法可以稳健地估计高斯混合模型的参数。图片来源:维基共享资源
第 5 章——期望最大化、隐藏信息及其应用
模式识别中的另一个关键问题是估计隐藏的、不可观察的信息。期望最大化算法是解决这类问题的通用方法。我们首先推导出高斯混合的情况下,其次是该方法的一般推导。
独立分量分析也揭示了一种隐藏的信息。它基于独立分量的混合可能产生高斯分布的观察。因此,ICA 使用这种先验知识,通过最大化变换分量的非高斯性来解开混合信息。ICA 的典型应用是盲源分离,例如几个声源的分离。
高斯混合 EM 算法— 视频 — 抄本
期望最大化算法— 视频 — 抄本
EM 算法应用实例— 视频 — 抄本
独立分量分析简介— 视频 — 抄本
独立分量分析与高斯性— 视频
训练数据很贵。我们能做什么来处理有限的数据?图片由 1820796 来自 Pixabay
第 6 章——有限数据及其处理方法
在这最后一章中,我们重温选择最佳分类方法的一般问题。“没有免费的午餐”——定理证明这样的方法在一般情况下是不存在的。然而,偏差-方差权衡告诉我们,只有先验知识才能同时减少两个误差源。一般来说,在几乎所有的模式识别问题中,我们都必须使用有限的数据源。为了估计有效的误差估计,必须使用重采样方法。基于对重采样的观察,boosting 制定了一种方法,旨在重新加权来自先前训练迭代的错误分类实例,以提高通用分类器的性能。有趣的是,这种方法实际上等同于使用指数损失函数。最后,我们来看看 boosting 在 Viola-Jones 人脸检测算法中最流行的应用。
没有免费的午餐定理&偏差-方差权衡— 视频 — 抄本
有限数据上的性能度量— 视频 — 抄本—Adaboost 的概念— 视频 — 抄本
Adaboost &指数损失— 视频 — 抄本
维奥拉-琼斯算法—
如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中获得文字记录,试试自动博客。
引擎盖下的 GCP 应用引擎
原文:https://towardsdatascience.com/under-the-hood-with-gcps-app-engine-82d862cb3691?source=collection_archive---------37-----------------------
更深入地了解如何配置应用程序引擎和解读相关成本
照片由胡佛·董在 Unsplash 拍摄
Google 的 App Engine 服务是一个很好的方法,可以让 web 应用程序轻松启动并运行。事实上,我有一篇文章介绍如何在这个平台上用大约 10 分钟的时间构建一个 Node.js 应用程序。这项服务是谷歌免费层的一部分,开始使用应用引擎很容易,但人们可能很难理解不同的配置选项和定价结构。本文分三个部分概述了在 App Engine 平台上配置和部署应用程序时需要考虑的问题。
托管选项 —配置和部署 App Engine 应用程序时要记住的事情。
定价—App 引擎费用是如何产生的。
其他注意事项 —部署 App Engine 应用程序时的一些其他注意事项。
让我们开始吧。
托管选项
部署应用程序时,您必须通过app.yaml
配置文件向应用程序引擎提供使用何种设置的说明。本节旨在帮助您理解部署选项的差异以及如何在该文件中指定它们。
下面是一个app.yaml
文件的例子:
runtime: nodejs14
env: standard
instance_class: F1
service: my-node-app
automatic_scaling:
max_instances: 2
min_instances: 0
min_idle_instances: 0
max_idle_instances: 1
运行时间
部署应用程序时,必须指定运行时语言。关于支持运行时环境的文档可以在这里找到并且在配置文件中使用了runtime
属性——这里是一个使用 Node.js v14 的部署示例:
runtime: nodejs14
env: standard
instance_class: F1
service: my-node-app
automatic_scaling:
max_instances: 2
min_instances: 0
min_idle_instances: 0
max_idle_instances: 1
环境
您可以从两种不同的环境类型中选择— 标准和灵活。本文档概述了两个选项之间的详细差异。简而言之,灵活的环境的运行成本会高得多,只有当你使用的语言不受标准环境支持时,才推荐使用这种环境。以下是支持的语言列表:
- Python 2.7、Python 3.7、Python 3.8、Python 3.9(预览版)
- Java 8,Java 11
- Node.js 8、Node.js 10、Node.js 12 和 Node.js 14(预览)
- PHP 5.5、PHP 7.2、PHP 7.3 和 PHP 7.4
- Ruby 2.5、Ruby 2.6 和 Ruby 2.7
- Go 1.11,Go 1.12,Go 1.13,Go 1.14,Go 1.15(预览)
还有其他原因让我们变得灵活,但这应该是个例外。您可以在此处找到完整的特性矩阵对比环境类型能力。环境类型可以通过env
属性在app.yaml
文件中指定——值可以是 flex 或 standard :
runtime: nodejs14
env: standard
instance_class: F1
service: my-node-app
automatic_scaling:
max_instances: 2
min_instances: 0
min_idle_instances: 0
max_idle_instances: 1
实例类
像大多数其他云服务一样,当部署一个 App Engine 应用程序时,你可以选择一个类,它将决定分配的资源和功能选项。
作者图表
重要的是要记住,谷歌的免费等级包括每天 28 小时的 f1 或 9 小时的 B1 实例免费使用。
作者图表
F 实例被视为“前端实例”, B 实例被视为“后端实例”。正如您在上表中看到的,主要区别是可用的缩放选项。实例类型可以通过instance_class
属性在app.yaml
文件中指定:
runtime: nodejs14
env: standard
instance_class: F1
service: my-node-app
automatic_scaling:
max_instances: 2
min_instances: 0
min_idle_instances: 0
max_idle_instances: 1
服务
App Engine 将应用程序作为服务运行。您的第一个 App Engine 部署与默认的服务相关联,但是您随后部署的任何东西都必须与专用的服务名相关联。如果指定的服务不存在,将创建一个新的服务,如果存在,则推送的应用程序将取代它的位置。未能在您的app.yaml
文件中指定服务将会覆盖您的默认服务应用程序。您可以在 App Engine 仪表盘中查看正在运行的服务列表。
作者图表
环境类型可以通过service
属性在app.yaml
文件中设置:
runtime: nodejs14
env: standard
instance_class: F1
service: my-node-app
automatic_scaling:
max_instances: 2
min_instances: 0
min_idle_instances: 0
max_idle_instances: 1
缩放类型
实例伸缩是一个需要理解的非常重要的配置,因为它会显著影响您的成本和性能。如上所述, F 型实例支持自动缩放,而 B 型实例可以利用手动或基本缩放。您可以在这里找到选项的矩阵,在这里可以找到配置标志的详细信息。以下是总结。
自动伸缩 —基于请求和性能创建和终止实例。配置可能会有点复杂,但我建议至少使用max_instances
、min_instances
、min_idle_instances
和max_idle_instances
属性设置总实例和空闲实例的最小和最大设置。这应该可以防止产生意外的费用。还有其他标志,如target_cpu_utilization
和max_pending_latency
,应用引擎可以使用它们来优化性能和触发缩放变化。下面是一个运行 0 到 2 个实例和最多 1 个空闲实例的限制的示例:
runtime: nodejs14
env: standard
instance_class: F1
service: my-node-app
automatic_scaling:
max_instances: 2
min_instances: 0
min_idle_instances: 0
max_idle_instances: 1
基本伸缩 —实例随着应用程序负载的波动而上下旋转。在app.yaml
文件中,可以使用max_instances
属性设置实例的最大数量,使用idle_timeout
属性设置空闲周期,如下所示:
runtime: nodejs14
env: standard
instance_class: B1
service: my-node-app
basic_scaling:
max_instances: 11
idle_timeout: 10m
手动扩展 —加速并维护一组实例,而不管服务上的负载如何。在app.yaml
文件中,可以使用instances
属性设置实例的数量,如下所示:
runtime: nodejs14
env: standard
instance_class: B1
service: my-node-app
manual_scaling:
instances: 5
成本和定价
Google 在其免费层中提供了一定数量的应用引擎正常运行时间,但是,根据您的应用程序的设置,即使您的应用程序只运行了指定时间的一小部分,您也可能会产生费用。了解这些费用的来源有时是一个挑战——关于成本的详细文件可以在这里找到,但我将在下面概述关键要素。
实例正常运行时间费用
从今天起,Google 将按如下方式向您收取实例正常运行时间费用:
作者图表
你最终可能会被起诉,阅读以下三条警告可能会让你省去无数个挠头、漫无目的地在网上搜索答案的时间。
图片由谢栋豪在 Unsplash 上拍摄
正如文档中概述的这里的,您将为正常运行时间加上一个实例停止运行时的额外 15 分钟付费。
如果您的实例在一个小时内收到四个间隔均匀的请求(每隔 15 分钟一次),并且只花了 一秒钟 来处理每个请求,然后就停止运行,尽管只使用了 4 秒钟的正常运行时间 ,您仍然需要支付 60 分钟 的费用。
如果启用了使用高峰和扩展,您的应用程序可能会扩展到多个实例。在这种情况下,您可能会看到每小时的费用是上述成本表的倍数。
应用程序版本也可能产生一些意想不到的费用。默认情况下,应用程序引擎维护应用程序的所有版本历史,并使每个版本映射到唯一的端点。如果不使用,这些历史版本应该只消耗存储资源,但是如果针对历史版本发出请求,它们将会启动专用实例—这当然会带来额外的利用成本。
定额
App Engine 通过配额限制应用程序的资源利用率。配额有三种类型:免费、每日和每分钟,如果你正在部署爱好应用程序,你不太可能会接近超过这些配额。如果您确实超过了配额限制,您的应用程序将不可用,直到资源在期限结束时重置,您可以在这里阅读有关此的更多信息。
其他考虑
谷歌云存储
App Engine 利用 GCS 有几种不同的方式:
staging.<project-id>.appspot.com
桶用于在部署应用程序时存放一些对象us.artifacts.<project-id>.appspot.com
桶用于存储构建工件- 一些应用程序可能使用桶来存储运行时对象
- 存储桶可用于存储应用引擎部署的源代码构建文件
GCS 有一个很好的免费使用层,如这里的所述。
其他服务
应用程序引擎可能会利用其他一些谷歌云平台服务进行常规操作。这些服务的使用应包含在免费层中,但重要的是要了解这些服务是什么,以防您开始看到收费。你可以在这里看到完整的列表。
结论
尽管 App Engine 是让您的应用程序在高度可伸缩的平台上运行的好方法,但了解如何正确配置您的部署和成本可能会有点令人困惑。在这篇文章中,一些光照在初学者通常陷入困境的几个领域。我希望我的帖子是信息丰富的,并为您节省一些头痛和谷歌搜索。
祝好运,编码快乐!
原载于 2021 年 5 月 14 日 http://www.theappliedarchitect.comhttps://www.theappliedarchitect.com/under-the-hood-with-gcps-app-engine/。
被低估的统计分析指标
原文:https://towardsdatascience.com/underrated-metrics-for-statistical-analysis-bbd34bd134dc?source=collection_archive---------14-----------------------
对鲜为人知但非常有用的数据分析指标的概述。
https://unsplash.com/photos/NDfqqq_7QWM
介绍
S 统计分析已经成为全球企业决策和分析处理的重要工具。近年来,科学在商业和技术领域的应用越来越有用。有很多不同的方法来统计分析数字。尽管如此,许多数据科学家和数据分析师倾向于避免探索统计的奇妙世界。
这方面最流行的测试是学生 T 测试。学生 T 检验是一种行业标准,用于获得具有统计显著性的概率值。通常在大学里,这是所学的统计学的第一个应用。这是有充分理由的,因为配对 T 检验和独立 T 检验都可以提供许多关于数据的非常有价值的信息,人们可能很容易处理这些数据。
尽管通常使用 T 检验来寻找统计意义,但统计世界还有更多需要经常使用的东西。根据所处理的数据,有许多不同的测试有自己的应用。今天,我想介绍一些我在分析经验中发现非常有用的指标。
标志测试
我想谈的第一个指标是符号测试。符号检验是一种统计检验,它使用二项分布来返回概率。这项测试是通过获得一些正值和负值,然后将它们通过二项式分布的程序密度函数(PDF)来完成的。
这是一个非常酷的测试,因为它可以用比大多数典型的统计测试少得多的数据提供准确的读数。另一件很棒的事情是,它背后的数学相对简单,通常可以手工完成,同时仍然保持推理和事实的性质。这个测试的唯一显著障碍是编程有多难。二项式分布非常注重阶乘的计算。这对现代计算来说是个问题,因为众所周知阶乘很难用计算机来计算。在大多数情况下,编程语言中的阶乘函数应用递归来一致地循环并添加计数。这意味着在更大的数据集上使用符号测试可能意味着多次巨大的阶乘计算。
虽然符号测试在性能方面有其不足之处,但它肯定是你的武器库中的一个伟大的测试。每当数据计数较小时,这甚至更加有效,因为有时在没有固定数量的样本的情况下,很难从其他测试中获得可靠的读数。如果你想了解更多关于符号测试本身的知识,我很久以前写过一篇关于它的文章,详细阐述了如何使用这个测试:
普通 PDF/CDF
如果你已经在统计领域工作了一天,很有可能你已经和正态分布有过接触。正态分布是一种 PDF 非常容易计算的分布。正态分布通常作为大多数统计数据的基础,并将数据转换为代表平均值标准偏差的值。
令人惊讶的是,这种分布作为分析知识的来源相对较少使用,但是您可以从这种分布中了解到许多关于您正在处理的数据的信息。首先,PDF 可以告诉你很多关于特定值的标准偏差。通常,当一个值具有统计显著性时,它最终会偏离平均值大约两个标准偏差或更多。实际测量值是 1.96,但一般来说,我说你应该寻找一个 2 左右的数字,一旦你达到它,它可能表明有统计学意义。这是一种相当容易的分析数据的方法,并且通常非常快,但是没有例子的描述通常是令人困惑的。
让我们考虑一个例子,我们有一个直接来自县区民主投票的法案。我们想知道一个县是否更有可能以这种或那种方式获得选票,所以首先我们通常分配该县所有投票的总体人口。之后,我们可以分离该县每个地区的样本,并比较这些值之间的平均值,平均值高于 2 或低于负 2 的样本最有可能具有统计显著性。为了验证一个潜在的假设,当然需要进一步的测试,但是使用这种分析知识肯定有助于首先形成假设——这有时可能是分析数据和发现见解最困难的部分。
除了 PDF 提供的分析能力,我们还有 z 检验。z 检验将使用正态分布的累积分布函数(CDF)。为了得到累积分布的概率,几乎总是使用这些函数。正态分布的 CDF,bnv 上 CDF(不确定是否正则化)对于提供丰富的见解非常有价值,因为它实际上比典型的学生 T 检验更难通过。
所有这一切意味着,z 分数验证的统计数据往往比那些由典型学生 T 检验的概率支持的统计数据更现实,甚至更有效。这是为什么呢?这是因为正态分布的尾部通常要小得多。这也是 T 检验更常用的部分原因。然而,一个有效的 z 得分概率通常比典型的 T 检验显示出更多的统计意义。
f 检验
尽管 T 检验更为常见,但许多科学家和统计学家都坚信 f 检验。正如您所想象的,这个测试使用了 f 分布。f 分布具有将统计意义的焦点放在数据可变性上的独特能力。如果差异足够显著,统计学家可以得出两个值的平均值不相等的结论,这可能表明连续的统计显著性。大多数 F 测试都是通过考虑一组数据的方差分解而产生的。
有很多很好的理由来利用 f 检验,并将其添加到您的统计测试团队中。f 检验通常被认为比学生 T 检验严格得多,也更有声望。更好的是,分布在回归中有应用,当然可以用来告诉更多的数据。此外,f 检验是 ANOVA 或方差分析背后的主要超能力。
威尔科克斯秩和
另一个被低估的统计检验是 Wilcox 秩和检验。检验是通过对样本和总体的等级求和来完成的。然后我们从两个群体中得到这些等级的总和,并对两者进行比较。不用说,这个测试背后的数学非常简单,并且不太适合方差很小的数据。
这意味着这些类型的测试肯定有它们的应用。我通常喜欢用正态分布来评估这个测试是否适用。我们可以计算离平均值几个标准差的值。这些值可能表明总体中的平均值和其余数据之间存在很大差异。当然,另一种我们可以完成的方法是方差分析,甚至是 ANOVA。
皮尔逊相关
我想谈及的最后一个指标是相关系数,在统计学中也普遍标有 r。这个值可能为许多机器学习工程师或数据科学家所熟悉,因为通常 r 是用于评估连续模型性能的度量。
相关系数能够以一种非常简单的方式说明两组不同的连续数据之间的相关性。平方它实际上可以返回一个百分比,这个百分比将表明这两个集合的相关程度。这也是我们评估模型的方式,因为这个百分比精度通常用作回归模型的基于百分比的精度数字的基础。
结论
统计的世界是广阔而迷人的,我认为探索它是一生的旅程。与数据科学工作的任何其他部分一样,总有一些新的和令人兴奋的东西需要学习——这是我如此热爱它的部分原因。人们很容易陷入大多数统计学家正在进行的普通测试的窠臼,但探索和利用数学所提供的一切并将其应用到您的工作中,正是这将使您与其他使用相同数据的科学家区分开来。感谢您的阅读!
了解主动学习:交互式可视化面板
原文:https://towardsdatascience.com/understand-active-learning-an-interactive-visualization-panel-a3e8029d288a?source=collection_archive---------26-----------------------
一个聪明的工具来阐明主动学习是如何工作的,为什么它是好的(或坏的),并且可以做得更多
介绍
在这篇文章中,我们旨在介绍一种交互式可视化工具,帮助用户更好地理解传统主动学习的工作方式和原因。这项工作与我们最近在 NeurIPS 2021 以人为中心的人工智能研讨会上发表的一篇论文有关。
以人为中心的机器学习
在过去的几十年里,机器学习已经成为一个时髦词。最近的许多进展都集中在使模型更加精确和有效。与此同时,人类能够解释他们为什么工作至关重要,特别是在一些敏感领域,如自动驾驶、金融投资和医疗保健管理。如果我们不能说服自己为什么这些智能机器工作良好,领域专家将不会完全相信他们的预测。
不幸的是,仍然有许多机器学习应用程序,其中最先进的模型可以实现强大的预测能力,但准确性的提高是以透明度为代价的,并且所达成的决定缺乏可解释性。直到最近,我们才开始看到一种转变,即让高级算法变得具有交互性和可解释性。换句话说,我们希望放大和增强人类的能力,旨在保持人类的控制,并使机器学习更加高效、有趣和公平。这个想法得到了几个知名机构的支持,比如斯坦福以人为中心的人工智能研究所和谷歌人&人工智能研究。
主动学习
主动机器学习。鸣谢:受张懿主动学习幻灯片的启发。
如果你读过我之前在 R 发表的关于主动学习的帖子,你会知道我的研究热情是促进主动学习的可解释性。在这里,我想快速更新一下什么是主动学习:一种交互式方法,它查询 oracle(通常是人类注释者)来标记最“有价值”的数据,以便用最少的标记样本训练准确的机器学习模型。
主动学习的大部分理论工作都是在分类问题上进行的,发展了许多基本的和成功的算法,如不确定性抽样和委员会查询。为了评估主动学习,最常见的方法是通过查询的数量来绘制准确度,其中我们期望准确度随着更多样本被查询而提高。不限于分类,最近的研究也采用了一些类似的算法进行回归,标准的性能指标是均方误差 (MSE)。
问题:许多主动学习论文呈现了高度相似的准确度/均方误差曲线,然而却报道了几个相互矛盾的发现。从精度/MSE 图反映的信息既有限又可能对用户有偏见。
例子摘自最近的 CVPR 论文
例如,CVPR 最近的一篇论文中的 CIFAR10 实验(第一个图)显示了所有查询方法(除了“随机”)几乎相同的性能。一个合理的假设是,即使曲线是重叠的,这些主动学习方法也不会同样地改进分类模型。一个支持的证据是它们在其他实验中表现各异。但问题是:我们如何测试它,并实际观察不同的算法是否工作不同?
OOur 方法&实验
在我们在 NeurIPS 2021 以人为中心的人工智能研讨会上发表的论文中,我们提出了一种新颖的交互式可视化工具,让人们更好地理解主动学习为什么以及如何在某些分类和回归任务上工作。
在本节中,我们将通过一个生动的例子来简要分享这些见解是如何构建的(不要担心,不会有任何太专业或复杂的定义!).
测试数据集的主成分分析
在机器学习实验中,准确性或 MSE 是基于最初划分的测试集生成的。例如,“准确度=(准确预测的样本数/测试集中所有样本数)。”因此,第一个任务是布局所有测试样本,并创建一个用于可视化的二维特征嵌入。PCA 等降维技术会有所帮助。
实验设置
**数据集:**在我们的论文中,我们用真实世界的数据进行了主动学习回归问题: CASP 。它最初包含 45,730 个实例,我们在测试集中随机选择了 9,730 个(21%)。
机器学习模型:回归器是一个纯粹的随机树模型,具体来说,来自 NeurIPS 2019 年论文中的蒙德里安树。
主动学习过程:我们从一个空的训练集开始,每次迭代批量查询 500 个,15 批(共 7500 个)后停止。考虑了三种基本的查询策略:基于树的主动算法(al)、不确定抽样(uc)和随机抽样(rn)。
左:主动学习实验的 MSE 图。右侧:所有测试样本的 PC1 与 PC2
PCA 图显示了所有测试样本之间明显的聚类模式。更重要的是,用户可以用 PCA 图选择一部分(一组)感兴趣的测试数据点。
左侧的 MSE-Query 图显示了理想的下降趋势。主动采样策略是最好的,但不确定性采样似乎具有竞争力,有超过 3,500 个样本被标记。
交互式可视化面板
在我们的案例中,我们想回答这个问题:*主动抽样策略是否与不确定性抽样同样有效?*这个问题可以通过预测值在每次查询迭代中如何变化来直接解释,这促使我们构建一个交互式可视化工具。
我们将预测值排列成一个二维网格图: x 轴表示查询过程(单元可以是单个或批量查询); y 轴代表所选测试样本的指标;每个像素根据三个标准显示预测差异,这三个标准是:
1。当前模型与原始模型:如果模型不断改进,并从查询的实例中学习,我们预计预测值会逐渐变得越来越不同。这可以通过更加丰富多彩的网格图来体现。
2。当前模型与先前模型:对于某些策略,我们预计稍后查询的样本对改变模型的影响较小。这可以通过图上较浅的颜色反映出来。
3。当前模型与事实真相:随着查询更多样本,我们期望模型做出更好的预测,更接近事实真相。这也可以通过一个较轻的情节体现出来。
(这些标准有严格的定义。如果您有兴趣了解更多信息,请查看我们的论文!)
小数值例子上三种人工智能策略的预测变化图
假设我们从 PCA 图中选择一组小值点(用红点标记)。3 为每行中三种策略(“al”、“uc”和“rn”)的预测变化图提供了 3 个面板图。
观察
查看三种查询算法的 first 预测变化图,很明显它们在改变回归模型时表现不同,即使它们在之前的图中有相似的 MSE 曲线。“al”的表现比“uc”或“rn”更有规律,与初始模型相比,始终具有较大的值(20 个纯红色行中的 18 个)或较小的值(20 个纯蓝色行中的 1 个)。
在“uc”的第二预测-变化图中,我们首先看到暗像素,在 5 个查询批次后看到相当亮的接近白色的像素。这表明“uc”倾向于在第一阶段显著地改变模型,并且在后面的查询中影响较小。
第三个预测变化图始终显示红色像素,这直观上是有意义的,因为我们选择的暗点具有接近 0 的小真值。树形回归往往用比事实更大的预测来拟合结构。
然而,与低值组的不同性能不同,三种算法对大值组表现出几乎一致的性能。
大值点上三种人工智能策略的预测变化图(实际用户界面)
讨论
这只是我们在最初发布的论文中举例说明的一个玩具。我们展示了可视化面板工具是如何工作的,并基于 CASP 实验提供了一些有趣的见解。到目前为止,我们只进行了一些实证实验。事实上,该工具可以揭示更多信息,例如:
1.某些主动学习方法是否总是对某些数据子群有效?
2.对于拟合大值点(或者,来自稀疏区域的数据点),树模型从查询的样本中学习得好吗
……
虽然我们已经开始在其他不同的数据集上使用我们的工具,但还需要我们做更多的工作来严格回答这些问题。此外,还需要对不同的主动学习策略进行更深入的分析。它们与主动学习中几个相当重要的术语有关:信息量、代表性和多样性。未来,我们希望扩展这个项目,在一些主要会议上发表一些更有价值的作品。
限制
还有几个问题,既有内在的,也有评论者和用户指出的。我们注意到的主要一点是,可视化工具的性能依赖于 PCA 图上测试样本的一些清晰关联:如果显示了清晰的聚类,则更容易得出结论。如果测试样本在降维图中没有显示任何清晰的关联或聚类组,则由于没有清晰的决策边界,AL 任务将更加复杂,这进一步使我们的图更难区分。
摘要
尽管如此,我们高兴地看到,以人为中心的人工智能和机器学习正受到研究人员越来越多的关注。我们真的希望这个可视化工具可以接近、可用,并有助于用户测试传统的精度/MSE 图。它不仅定义简单明了,而且可以灵活地适用于几乎所有的分类和回归问题。
承认
我要感谢我的本科生荣誉导师马丁·埃斯特博士,感谢他指导我完成这个兼职项目。我也非常感谢陆家林和奥利弗·斯诺,感谢他们在过去的八个月里对我们的帮助。
来源
这个工具的 GitHub 演示可以在:https://GitHub . com/AndyWangSFU/Active _ Learning _ Visualization _ Demo获得。如果你喜欢这个帖子,请留下一颗星,非常感谢!
了解并比较云功能与云运行
原文:https://towardsdatascience.com/understand-and-compare-cloud-functions-vs-cloud-run-5afc2beb2fb?source=collection_archive---------3-----------------------
您是否对哪些 GCP 组件更合适感到困惑?
克里斯蒂安·斯塔尔在 Unsplash 上拍摄的照片
介绍
作为一名数据科学家,您需要决定如何执行模型部署步骤,这可能涉及转换您的脚本并将它们作为微服务进行部署。就我而言,我不知道应该使用哪些 GCP 组件来部署微服务。我应该部署在云运行还是云功能上?两者都是 GCP 的无服务器产品,易于部署和处理 HTTP 请求/事件。因此,我决定进行一些研究,在云功能和云运行上部署相同的微服务,并观察差异。在本文中,我将分享云功能和云运行之间的区别以及部署这两个组件的方法。
在深入研究这两个组件之间的区别之前,让我们先了解一下这两个组件。
云函数
云功能第一次公测发布是在 2017 年 3 月。云功能是一个事件驱动的无服务器平台,是一个支持个性化服务的轻量级解决方案,可以通过 HTTP 请求调用,也可以基于后台事件触发。云功能只支持 JavaScript、Python、Go 等特定语言。代码需要打包成一个功能,云功能组件将处理代码的打包、部署和执行。由于对于每个实例,云功能一次只处理一个请求,因此只有在用例是单一目的工作负载时,它才是合适的。
云运行
Cloud Run 测试版的发布晚于 Cloud Function,后者于 2019 年 4 月首次推出,是对其他 GCP 无服务器产品的补充。Cloud Run 是一个完全托管的计算平台,适合部署容器化的应用程序。Cloud Run 允许用户根据自己喜欢的编程语言编写脚本,然后将其推送到 Cloud Build 并打包成一个容器。与一次仅支持一个请求的云功能相比,云运行能够被配置为在单个容器实例上支持多个并发请求,这允许节省时间和成本。
在云功能和云运行上部署简单的服务
让我们测试部署一个简单的服务,该服务可以通过 HTTP 端点触发,并基于两个平台上的用户输入返回一条消息——云功能和云运行。
预期的输出将根据用户输入返回一条消息:
创建的微服务的预期输出(图片由作者提供)
云功能部署步骤:
我们可以用接收用户请求的 python 脚本创建一个 HTTP 触发器,并在云函数上进行设置。
(1)创建一个函数并测试它*(我使用的环境是 GCP 的 Vertex AI Jupyternotebook)
创建 python 函数(作者图像)
(2)进入谷歌云控制台的云功能,选择创建功能、*(如果是第一次,请启用云功能 API 和云构建 API)
- 为您的云功能命名
- 选择一个区域
- 选择 HTTP 触发器
- 如果您想从浏览器*触发并调用服务,请允许未经验证的调用(不建议用于生产管道,但在开发时更容易看到输出)
云功能配置(作者图片)
(3)下一步,在代码部分-选择运行时到 Python 3.9 ,指向函数名 print_message ,并将您的 Python 函数添加到 main.py 文件中。
- 请注意,要在云函数中传递参数,您将需要使用 request.args.get() 更改函数以处理和检索参数
def print_message(request):
message = request.args.get('msg')
final_message = f"My Name is {message}, Nice meeting you! "
return final_message
更新云功能源代码(作者图片)
(4)代码更新后,通过选择底部的“部署”按钮来部署该函数——然后该函数将开始在您的 GCP 环境中部署。
部署云功能“云功能-演示”(作者图片)
(5)在浏览器中测试并调用新部署的功能
- 您可以在部署的云功能的触发选项卡下检索您的 HTTP URL。
检索已部署的云功能 HTTP URL(按作者列出的图像)
- 从您的浏览器调用端点,并通过 URL 传入您的输入。
测试部署的云功能(作者提供的图像)
恭喜,感谢您陪我完成了将微服务部署到云功能所需的步骤。现在,让我们看看在云运行时创建相同的微服务所需的步骤。
云运行时部署步骤:
在云运行时创建微服务的方法将需要准备几个文件,这些文件是:
- main.py
- 文件
(1)准备主副本文件和备审文件
main.py 文件由 web 框架(FastAPI)和接收用户输入并返回消息的 python 函数组成。
import uvicorn
from fastapi import FastAPI
import osapp = FastAPI()
[@app](http://twitter.com/app).get("/{msg}")
async def print_message(msg:str):
message = msg
final_message = f"My Name is {message}, Nice meeting you! "
return final_message
文件:
在部署和创建微服务的云运行中,需要将 python 脚本部署到 Docker Container 中。Dockerfile 指定在容器启动时如何创建容器并运行 web 服务。
# Use official lightweight Python image as base OS.
FROM python:3.7-slim# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./# Install production dependencies.
RUN pip install fastapi uvicorn[standard] gunicornENV PORT 8080#Run the web service on container startup using gunicorn webserver.
CMD exec gunicorn --bind :$PORT --workers 1 --worker-class uvicorn.workers.UvicornWorker --threads 8 main:app
(2)构建和部署码头工人形象
在 Google Cloud Console 上可以使用不同的方法来构建和部署云运行微服务。在我之前的文章中,我分享了通过云壳编辑器部署云运行微服务的方法。在本文中,我将从 Vertex AI Jupyternotebook 环境进行部署。
- 在您的笔记本中,创建一个特定的文件夹并上传文件——main . py & docker file
将所需文件上传到 Jupyternotebook(图片由作者提供)
- 在 Jupyternotebook 中启动/打开终端控制台
启动终端控制台(图片来自作者)
- 在终端中,导航到包含文件的文件夹
cd cloud-run-demo
导航到目标文件夹(按作者排序的图像)
- 配置和设置将部署微服务的区域。
gcloud config set run/region asia-southeast1
配置和设置区域(图片由作者提供)
- 运行命令在所选区域构建新的 docker 映像。这个过程需要几分钟。
gcloud builds submit --tag gcr.io/sue-gcp-learn/cloud-run-demo
构建 Docker 图像(由作者创建的图像)
- 部署新构建的映像,并提供云运行服务名称。
gcloud run deploy --image gcr.io/sue-gcp-learn/cloud-run-demo --platform managed
部署 Docker 图像并提供服务名(图像由作者提供)
(3)检查和测试部署的云运行服务
- 微服务 URL 将在完成部署后提供。该服务也可从云运行控制台获得。
云运行控制台上部署的服务(图片由作者提供)
- 从浏览器测试并调用云运行端点,并通过 URL 传入您的输入。
测试部署的云运行(图片由作者提供)
恭喜您,与我一起完成了将微服务部署到云运行所需的步骤。现在,您已经掌握了在两个不同的 GCP 组件上创建微服务的知识。
比较云函数和云运行
- 云功能允许用户基于支持的几种语言部署代码,而云运行没有这种限制,因为您将能够基于用户选择的语言构建和部署容器映像。
- 对于每个云功能实例,云功能一次仅支持一个请求,而云运行能够同时处理多个请求,并且能够根据需求进行扩展。
- 云功能能够处理特定的触发器,如 FireStore 事件和基于云存储上的更改的触发器,而 Cloud Run 不具备此附加功能。
我个人的结论/偏好
我有组件云功能和云运行的经验,我更喜欢云运行,因为它的灵活性和处理并发的能力。因为 cloud run 使用容器化,所以它被认为是可移植的,可以很容易地部署到另一个环境中,比如本地、另一个地区等。这减少了将来的返工。
尽管如此,我强烈建议您在这两个组件上测试创建您的微服务,如果您有额外的时间,并从您自己的角度比较它们。
感谢你阅读我的文章,如果你喜欢并愿意支持我:
- 跟我上 中 🙆🏻
- 通过我的推荐链接成为 Medium 会员🙋
参考文献&链接:
[1]https://cloud . Google . com/blog/topics/developers-从业者/cloud-run-story-server less-containers
[2]https://data tonic . com/insights/cloud-functions-cloud-run-model-serving/
理解中心极限定理
原文:https://towardsdatascience.com/understand-central-limit-theorem-e5d47959c163?source=collection_archive---------24-----------------------
教育
简单的英语解释,以及确保您不会在数据科学面试中被难住的关键假设
鸟瞰本帖中的假设示例(图片由作者提供)
尽管是数据科学中少数几个基本概念之一,中心极限定理(CLT)仍然被误解。
围绕这些基本统计概念的问题确实会在数据科学访谈中出现。然而,你会惊讶地发现,有抱负的数据科学家经常将他们的学习时间投入到最新趋势和新算法上,但由于没有重温基本概念而错过了窍门,并在面试中被难住了。
这篇文章将帮助你在直观的层面上更好地理解 CLT 定理。它还会帮助你更好地理解它的重要性,以及使用它时的关键假设。
简单的英语解释
用一种有点正式的语言,
中心极限定理说明,任何分布的均值的抽样分布都将是正态的,前提是样本量足够大。
让我们用一个更具体的例子,用更简单的词语来解释上面的定义。
想象一个假设的国家,有 200 万个家庭,分成两个关键区域:汤姆和杰瑞。为简单起见,让我们假设 100 万个家庭住在汤姆地区,100 万个家庭住在杰里地区。
一家受欢迎的快餐连锁店已经聘请你来帮助他们决定是否应该在该国投资并开设分店。如果他们这样做,他们应该打开它在汤姆或杰里地区。
让我们假设评估每个地区人们现有饮食习惯的一个有用指标是每个家庭每周光顾快餐店的次数。你的任务是为汤姆、杰瑞和整个国家解决这些问题。
在我们假设的国家中,Tom 的平均每周家庭访问次数是 1.5 次,其分布如图 1 所示。
图 1:汤姆地区每周光顾快餐店的次数分布(图片由作者提供)
Jerry 的平均每周家访次数为 3.5 次,分布如图 2 所示。
图 2:杰里地区每周光顾快餐店的次数分布(图片由作者提供)
总体而言,每周平均访问次数的分布如图 3 所示,平均值为 2.5 次
图 3:全国(即汤姆和杰瑞地区)每周光顾快餐店的次数分布(图片由作者提供)
理论上,我们可以询问这个国家每个人的饮食习惯,然后计算平均每周访问率。然而,这在现实世界的项目中是不可行的。
相反,我们所做的是从总人口中“取样”。所谓“抽样”,我们的意思是我们可以从全部人口中只去问一小组人(通常是出于正当理由随机选择的)。
假设我们从汤姆地区随机抽取 100 个家庭,然后计算平均值。这是一个实验。
如果我们重复同样的实验,我们会得到不同的平均值。如果我们重复同样的实验 100 次,我们会得到 100 个不同的(样本)平均值。
如果我们绘制这些样本均值的分布图,它将看起来像一个正态分布。这个样本分布的平均值将非常接近真实的总体平均值。
图 4 显示了来自 Tom 区域的 10,000 个平均值的分布(在 R 中模拟)。每个平均值是通过 抽样 随机选择 100 户家庭计算出来的。
图 4:Tom 样本均值的分布,其中每个样本均值是通过从 Tom 地区随机抽样 100 户家庭计算的(图片由作者提供)
图 5 显示了杰里地区 10,000 个平均值的分布。同样,每个平均值是通过 抽样 100 个随机选择的家庭计算的。
图 5:Tom 样本均值的分布,其中每个样本均值是通过从 Tom 地区随机抽样 100 户家庭计算的(图片由作者提供)
图 4 和图 5 中的分布都是正态分布。此时,您可能会认为这些样本分布是正态的,因为总体分布(从中得出这些分布)是正态的。
然而,这对初学者来说可能是一个惊喜。
人口(原始)分布是什么并不重要。如果我们抽样,并且样本足够大,样本均值的最终分布将是正态分布。此外,该抽样分布的平均值将近似等于总体平均值。
你刚刚读到的是简单明了的 CLT 定理。
让我们用前面的例子来演示 CLT。让我们从由汤姆和杰里地区组成的整个国家中随机选择 100 个家庭并计算平均值,并将相同的实验重复 100,000 次。图 6 显示了这 10,000 个平均值的分布。
图 6:整个国家样本均值的分布(汤姆和杰里),其中每个样本均值是通过随机抽样 100 个家庭计算的(图片由作者提供)
显然,这个国家的人口分布是不正常的。即使这样,抽样分布也是正态的,平均值非常接近总体平均值。
这就是 CLT 的魅力。我们不需要知道随机变量的基本分布是什么。我们仍然可以通过抽样,并正确地假设抽样分布将是近似正态的,来找出总体的平均值。
是什么让 CLT 有用?
在大多数有用的、真实世界的项目中,由于时间和资源的限制,我们不能出去从整个人群中收集数据。然而,CLT 让我们能够自信地走出去,从人口的子集收集数据,然后使用统计数据得出关于人口的结论。
CLT 是假设检验的基础,假设检验是推断统计学的一个分支,它帮助我们仅从具有代表性的数据子集得出关于总体的结论。
最后的想法
在假设的例子中,Tom 和 Jerry 的人口分布是正态的,而整个国家的人口分布是不正态的(它有两个峰值)。然而,在这三种情况下,抽样分布都是正态的。这是中心极限定理的结果。不考虑总体分布, 均值 的抽样分布是正态分布,前提是样本足够大。在大多数实际应用中,大于 30 的样本量通常被认为是足够的。
只有当要建模的分布的均值和方差是有限的时,CLT 定理才有效。因此,这个定理不适用于柯西分布的情况。如果您想深入了解,请查看两个示例的模拟演练,一个示例适用于 CLT,另一个示例不适用。
这篇文章中的所有数字都是用 r 语言生成的。带有注释的代码可以在我的 GitHub 上找到。
快乐学习!
*https://ahmarshah.medium.com/membership *
理解决策树分类器
原文:https://towardsdatascience.com/understand-decision-tree-classifier-8a7497d4c5b3?source=collection_archive---------35-----------------------
理解决策树分类器如何用简单的语言和最少的数学公式工作。从头开始弄清楚基尼不纯和信息增益是如何工作的。
我的儿子查尔斯·朱
与神经网络等机器学习模型相比,我认为决策树分类器应该是最简单的一种。但是我错了,这个模型比我想象的要复杂一点。该模型也为其他高级模型如 LightBGM 和随机森林决策树奠定了基础。所以,我花了一些时间学习它,并试图弄清楚决策树分类器是如何工作的。
决策树如何工作
该模型的工作方式非常类似于人类思维对现实世界中的物体进行分类的方式。
苹果和柠檬,图片来自 Unsplash
当你看到上面的水果时,你会立刻从苹果中辨别出柠檬水。但是,怎么做呢?通过遵循决策树模型,你的大脑会在一瞬间问两个问题。
- 这看起来像什么颜色?
- 这个水果有多大?
一种简化的水果标识符决策树
决策树已经很好地保存在你的记忆中,它将引导你找到正确的答案。
但是,当你试图教一个计算机模型做类似的事情时,如何建立一个这样的决策树呢?或者让我们在另外两个更具体的问题中问同样的问题。
- 先问哪个问题?(以哪个功能列为目标)
- 我应该问什么问题?(什么是数据分区规则)
决策树分类器的关键是构建如上所示的决策树。
一个有 3 个水果的盘子——样本数据
假设我们手头有一个训练数据集。这次,我们盘子里有三种水果:苹果、葡萄和柠檬。如下所示:
熊猫数据框中的 3 个水果,图片由安德鲁提供
解决问题:我如何知道先问哪个问题?还是先问颜色问题还是直径问题?并设置正确的数据分割点?
我们可能希望我们的第一个问题是划分数据集,以便更好地成形。如果你有清洁孩子玩具的经验,我们问的问题应该最好区分乐高和木块。或者用另一种说法,我们希望这个问题能引出下一个层次的多样性更少的数据。
维基百科会告诉你衡量多样性的公制叫做 基尼杂质 。
什么是基尼系数,为什么它会这样
例如,你面前有两个水果阵列。哪种水果阵列更多样?
水果阵列 A,图片来自 Unsplash
水果阵列 B,图片来自 Unsplash
很明显,我们的人脑会很快找到数组 b 的答案。但是,我们怎么能以数量的方式来衡量多样性呢?我建议你停下来,在继续前进之前,试着想出你的解决方案。
…
一个简洁的解决方案是计算每种水果的概率,然后计算概率的平方。求和数将有一个属性,数组的多样性越多,该数就越低。
例如,在水果数组 a 中。
然后将平方概率相加。
现在,在水果数组 b 中,使用相同的逻辑,您将得到平方概率之和为 0.5。
看到了吗?更多样的数组将产生更低的结果。吉尼杂质很简单:
现在,你可能会问,为什么要把概率平方?如果没有正方形,数组 A 和数组 B 将生成相同的结果。(你可以试一试)。
使用信息增益来确定要问的正确问题
让我们回到果盘,我们所能产生的基尼杂质在其初始状态下是 0.64。
接下来,假设我们有一个问题要问,这个问题会将数据集划分为两个子集。
在一个真实的程序中,我们可以使用 nest 2-for 循环来尝试所有的细胞并产生所有的基尼杂质#。
什么是信息增益?信息增益是一种度量,用于度量一个问题减少了多少不确定性。
在上面的示例中。通过“果实直径≥3?”问题获得的信息是:
假设我们有最好的问题要问,这个问题必须最大程度地降低基尼系数,或者换句话说,获得最多的信息。
递归构建决策树
现在您已经有了吉尼和信息增益解决方案,您可以递归地将该过程应用于您的数据集,直到该过程无法生成更多的信息增益。在上面的示例中,右边的子对象只包含葡萄。你不能再减少杂质(或获取信息),因为不需要问任何问题。
最终,您将拥有一个能够接受新数据并为您预测水果类型的功能决策树模型。
链接和代码
- 决策树学习:https://en.wikipedia.org/wiki/Decision_tree_learning
- 让我们从头开始写一个决策树分类器:https://www.youtube.com/watch?v=LDRbO9a6XPU&t = 306s
- 决策树分类器的 Python 实现:
了解差异化编程
原文:https://towardsdatascience.com/understand-differentiable-programming-54f11bfb574?source=collection_archive---------22-----------------------
一种编程范例,允许程序使用基于梯度的优化来重建自身的部分
图片来自 wikipedia.org
自 2014 年首次出现以来,可微分编程曾经是一个花哨的术语,在本文的中被描述为“可微分函数编程”。Yann Lecun 将其描述为“深度学习的推广”[1],许多知名的人工智能研究人员认为这种类型的编程是软件工程的未来,也称为软件 2.0。
在经典编程中,我们过去常常明确地列举 CPU 需要执行的指令集,以便创建我们的算法。这意味着,在运行时,程序有足够的知识来实现其预期目标。
对于可微分编程,我们希望使用加权参数网络构建一种新的程序,通过基于梯度的优化[2]的示例进行训练。这些程序能够以一种更优化的方式,沿着一个梯度重写它们自身的部分。
在引擎盖下,它们可以被视为处理输入和输出的连续可微函数的复杂组合。因为每个表达式都是可微分的,所以可以使用链规则传播模型中的优化。像在经典的监督学习中一样,可以通过关于每个加权参数的损失梯度的反向传播来训练模型。因此,每个表达式应该实现一个向前行为,这是解决问题所需的实际计算,以及一个向后行为,其目标是更新用于计算向前传递的权重。
实际上,当编写一个可微分程序时,你正在编写一个程序*,它在运行时构建另一个程序 B 。程序 A 基本上是一组定义可微分计算图的规则和函数。程序 B 然后计算这个图并自己更新所有的参数,所以它正在构建自己的最优架构来解决问题。*
作者图片
请记住,这些参数被视为可微分函数,而不是循环、条件、赋值等不被视为函数的常见操作。
计算梯度
图片由 researchgate.net 拍摄
为了优化我们的可微分程序,我们将计算损失函数的梯度,这是一个系数向量。每个值给我们两条信息:斜率的意义(值的符号)和为了优化程序我们需要增加/减少参数的量(实际值)。
为了计算梯度,存在不同的实现方式:
符号微分:f '(x)= 2x | f '(cos(x))=-sin(x)……
难以在实际项目中应用,因为依赖于已知的有限的导数集(实际项目可能使用复杂的函数,如泰勒级数展开)。更多信息。
数值微分:f '(x)= lim(f(x+h)-f(x))/h
计算梯度的最简单的方法之一,但是很慢(需要计算 2 次函数 f +离散化的风险+由于变量 h 可能产生的舍入误差)。更多信息。
自动微分:
考虑将程序区分为包含算术和基本运算(+、-、、log、sin、cos…)的代码块,并使用链式法则计算整体导数。工程上任意程序,运行速度快,结果是准确的。更多信息。*
在实践中,自动微分是最常用的微分算法,这得益于它的精度和效率。Tensorflow [3]和 PyTorch [4]等机器学习框架实现了这种技术来计算梯度。
可微分编程语言
尽管基于梯度的优化和自动微分已经使用了很多年,但是可微分编程还是最近的事情,即使它与这两种技术紧密相关。大多数流行的语言没有实现本机可微分函数,尽管有些框架存在:
- 张量流, PyTorch
- 用于 Swift 的Swift 4 传感器流量
- 【Swift 的差异化编程宣言
- 张量
- 【Scala 的灯笼
- 用于物理模拟的 DiffTaichi
什么是神经网络?
差异化编程应该被看作是每个软件工程师在编写代码时应该考虑的一个工具。当从示例中学习算法模式比枚举详尽的规则列表更容易时,应该使用这种范例,枚举规则列表对于某些任务来说可能极其复杂。这些任务中的大部分是试图使用机器学习(例如 NLP、计算机视觉等)来解决的经典问题,但可能与特定的用例有关。神经网络可以被视为使用权重和偏差层的差分编程技术的具体实现,但是我们可以想象使用差分的不同架构,而不是神经网络。
可区分编程也是软件工程和数据科学之间的前沿,在未来看到更多的团队合并这两个方面也就不足为奇了!
参考
[1] 乐存对甲方的回答 LikeLizLemon ,2018
[2] 可微规划张量网络,2019
[3] TensorFlow:大规模机器学习的系统,2016
[4] PyTorch:命令式风格,高性能深度学习库,2019
理解广义线性模型,以及它与线性、逻辑和泊松回归的关系
原文:https://towardsdatascience.com/understand-generalized-linear-models-and-how-it-relates-to-linear-logistic-and-poisson-regression-53f3aea8a9d?source=collection_archive---------5-----------------------
教育
永远不要再混淆线性回归和广义线性回归,带着清晰的思路离开。
亚历山大·杜默在 Unsplash 上拍摄的照片
2021 Kaggle 调查显示,与去年一样,数据科学界最常用的算法是线性或逻辑回归。我一点也不惊讶。不同特征的加权求和毕竟是最直观的做法。然而,对于大多数初学者来说,线性回归和其他类型的回归之间的区别变得不那么明显了。
当你读完这篇文章后,你会对线性回归与逻辑回归和泊松回归的区别有一个非常清晰的概念。此外,你也会清楚地理解当它用于分类任务时,我们仍然称之为逻辑“回归”的原因。
如果你以前曾经对这些不同类型的回归感到困惑,那么你来对地方了。然而,我请求你在接下来的几分钟内暂停你对这个主题的先验知识。如果你做到了,我保证你会带着水晶般的清澈离开。让我们开始吧。
什么是广义线性模型?
简而言之,广义线性模型(GLM)是一种数学模型,它将输出(响应变量的函数,稍后将详细介绍)与一个或多个输入变量(也称为探索变量)联系起来。下面的等式显示了输出如何与 n 预测变量的线性求和相关。有相应的 n+1 个系数项(每个系数项对应于 n 个预测变量,还有一个附加项帮助对任何偏移进行建模)
GLM 方程(图片由作者提供)
无论是进行线性回归、逻辑回归还是泊松回归,上述等式的右边(输入要素的加权组合)保持不变。
让我们来谈谈等式的左边,即输出。这是随机成分。它是响应变量期望值的函数。为简单起见,我们称期望值为 Y 。
GLM 方程中的输出部分(图片由作者提供)
函数, g(。),称为链接功能。正是这个链接功能使得 Y 的分布与右侧兼容(输入的线性组合)。
当函数 **g(.)**是一个恒等函数,那么 GLM 方程就简化为一个正规的线性回归方程。
当函数 g 是恒等式时,GLM 方程就相当于一个简单的线性回归
换句话说,当连接函数是恒等式时,常规线性回归是广义线性模型的特例。
常规线性回归和 GLM 的主要区别
正如我前面提到的,常规线性回归是 GLM 的特例。然而,在进一步讨论之前,让我们快速地解释一下这两者之间的一些关键区别。
常规线性回归的关键假设是输出 Y 的每个值都是独立的,输出是正态分布的,并且 Y 的平均值通过线性组合与预测变量相关。在 GLM 中,输出不局限于正态分布,而是可以属于指数族的任何成员。
要解决常规线性回归问题,您可以采用最小二乘法或最大似然估计。它们会给出相同的结果。然而,GLM 只能用最大似然估计法求解。
最后,正则线性回归模型有时也被称为标准最小二乘模型,是由高斯在 1809 年发明的,而 GLM 是由内尔德和威德伯恩在 1972 年发明的。
GLM 与线性回归、逻辑回归和泊松回归有什么关系?
既然你开始将线性回归视为 GLM 的一个特例,我们可以继续并确定 GLM 的其他情况。
当连接函数是 logit(比例的自然对数)时,我们最终得到一个逻辑回归方程。
逻辑回归方程,其中输出是“赔率”的自然对数(图片由作者提供)
当结果是二元的(例如,成功/失败,有疾病/没有疾病)时,逻辑回归是最合适的。在这样的应用中,比率(Y/(1-Y*)*类似于成功概率与失败概率的比率(也称为“赔率”)。
当关联函数是比率的自然对数时,我们最终得到一个泊松回归方程。
当结果是给定时间间隔内的计数或给定时间内发生的事件数时,泊松回归最适合。
链接函数与激活函数的关系
链接功能 g(。) 是一个可逆函数,它转换输出的期望值,使其与线性预测器部分(GLM 等式的右边)兼容。然而,在机器学习社区中,我们经常首先被介绍到链接函数的逆函数。这就是所谓的激活功能。
带有激活函数的 GLM 方程,它是链接函数的反函数(图片由作者提供)
链接功能的逆功能与激活功能相同。术语“链接函数”在统计学文献中很常见,而术语“激活函数”在机器学习文献中更常见。
例如,如果您对逻辑回归的 GLM 方程(如前所示)的两边取指数,并应用简单的代数运算,您将最终得到以下逻辑回归方程(在机器学习文献中更常见)。
逻辑回归方程,它在机器学习文献中的表达方式(图片由作者提供)
最后的想法
人们经常混淆和混淆这些概念。更糟糕的是,当用于分类时,人们经常称之为逻辑回归。这部分是因为我们,在机器学习社区,已经将监督学习分为分类(当输出是离散的)和回归(当输出是连续的)。
当然,逻辑回归用于分类,但它仍然是一种回归技术。只有当你理解了广义线性模型,一个更重要的概念,这才有意义。
最终,您将不同的输入变量组合成一个加权和,无论使用线性、逻辑还是泊松回归,都需要确定未知系数。
https://ahmarshah.medium.com/membership
理解并在 Python 中实现逻辑回归
原文:https://towardsdatascience.com/understand-implement-logistic-regression-in-python-c1e1a329f460?source=collection_archive---------9-----------------------
Sigmoid 函数、线性回归和参数估计(对数似然和交叉熵损失)
梅格·波尔登在 Unsplash 上的照片
目标
这篇文章的主要目的是理解二元逻辑回归是如何工作的。
- 我将在高层次上回顾理解逻辑回归所涉及的基本数学概念和函数。
- 在此过程中,我将介绍两种众所周知的梯度方法(上升/下降),以使用对数似然和交叉熵损失函数来估计𝜃参数。
- 我将使用 Kaggle 的泰坦尼克号数据集从头创建一个逻辑回归模型来预测乘客存活率。train.csv 和 test.csv 文件可以在 Kaggle 的 Titanic 数据页面上找到。为了加快模型构建,我将只使用三个特征,年龄(连续)、p 类(第一类= 1,第二类= 2,第三类= 3),以及性别(女性= 1,男性= 0)。
图 0:图片由作者提供;数据来源: Kaggle 的泰坦尼克号数据
目录
- 算法概要
- 数学概念和函数
- 行动中的代码
- 最后的想法
算法概要
逻辑回归是一种分类算法,它输出一组给定实例的预测概率,这些实例的特征与优化的𝜃参数和偏差项配对。这些参数也称为权重或系数。概率被转换成预测例如成功(“1”)或失败(“0”)的目标类别(例如,0 或 1)。虽然我将仔细研究二元逻辑回归模型,但是逻辑回归也可以用于进行多类预测。
**我们如何获取线性组合的输入特征和参数,并进行二元预测?**答案是自然对数(以 e 为底的对数)。更确切地说,对数概率。对线性组合的输入要素和参数求和,以生成对数优势形式的值。然后,对数优势值被插入到 sigmoid 函数中,并生成一个概率。就其核心而言,像许多其他机器学习问题一样,这是一个优化问题。使用梯度上升(例如,最大化对数似然)或下降(例如,最小化交叉熵损失)来估计最佳参数,其中选择的目标(例如,成本、损失等。)功能决定梯度接近。
数学概念和函数
为了让一切变得更简单,我们必须深入数学。在逻辑回归中,sigmoid 函数起着关键作用,因为它输出一个介于 0 和 1 之间的值,非常适合概率。因此,这种表示通常被称为逻辑 sigmoid 函数。请记住,在自然环境中还有其他具有不同有界范围的 sigmoid 函数。并且因为响应是二元的(例如,真对假,是对否,幸存对未幸存),所以响应变量将具有伯努利分布。此外,每个响应结果由预测的成功概率决定,如图 5 所示。
**关于数学符号:*小写的“I”将表示数据集中的行位置,而小写的“j”*将表示数据集中的特征或列位置。你还会碰到小写粗体非斜体的“ x ”。这代表一个特征向量。更具体地说,当“I”伴随有“x”(xI)时,如图 5、6、7、9 所示,这代表一个向量(一个实例/单行)具有所有特征值。
当您在图 8 和图 10 中看到小写斜体“x”(Xi,j)的“I”和“j”时,该值是第 I 个(单个特征向量)实例中第 j 个特征的表示。数据集中要素(列)的数量将表示为“n ”,而实例(行)的数量将表示为“m”变量。
Sigmoid 函数
在图 1 中,第一个方程是 sigmoid 函数,它创建了我们经常在逻辑回归中看到的 S 曲线。给定 x ,输出等于条件概率 y = 1,由𝜃.参数化在这种情况下, x 是表示为特征向量的单个实例(训练集中的观察值)。
图 1: Sigmoid 函数[sigma(z)]和[1—sigma(z)];图片作者作者
向量中的每个特征将具有使用优化算法估计的相应𝜃参数。稍后我会在梯度上升/下降部分详细讨论这一点。还需要注意的是,通过求解 log(odds)= log(p/(1-p))中的 p ,我们得到了具有 z = log(odds)的 sigmoid 函数。
图 2:s 形曲线;图片作者作者
proba1, proba0 = [], []
feature_example = [i for i in range(-10, 11)]for instance in feature_example:
p1 = 1/(1 + np.exp(-instance)) # sigmoid function
p0 = 1 — p1
proba1.append(p1)
proba0.append(p0)plt.figure(figsize=(12,6))
plt.plot(feature_example, proba1, marker=’.’, label=’predict proba “1”’)
plt.plot(feature_example, proba0, marker=’.’, linestyle=’dashed’, label=’predict proba “0”’)
plt.title(‘Sigmoid Curve’)
plt.xlabel(‘feature_example (in log-odds)’)
plt.ylabel(‘probability’)
plt.legend(prop={‘size’: 12});
赔率和对数赔率
使用线性回归函数估计的 y 值(y-hat)代表对数优势。围绕比值或比值比包装对数的过程被称为 logit 变换。关键是对数几率是无限的(-无穷大到+无穷大)。但是,我们需要一个介于 0 和 1 之间的值来预测概率。所以,本质上,对数概率是弥合线性和概率形式之间差距的桥梁。
图 3:线性回归函数和 y 估计值的对数比;图片作者作者
什么是对数概率?我们首先要知道赔率的定义——成功的概率除以失败的概率,P(成功)/P(失败)。例如,对于一枚普通硬币,正面和反面的概率都是 0.5。因此,几率是 0.5/0.5,这意味着得到反面的几率是 1。如果我们使用一个偏向反面的硬币,其中反面的概率现在是 0.7,那么得到反面的几率是 2.33 (0.7/0.3)。如图 3 所示,赔率等于 p/(1-p)。下一步是将赔率转换成对数赔率。
将概率转换为比值以及将比值转换为对数比值的一个基本要点是,这些关系是单调的。当概率增加时,几率增加,反之亦然。当赔率增加时,对数赔率也增加,反之亦然。在图 4 中,我使用 Titanic 训练集和 Scikit-Learn 的逻辑回归函数创建了两个图来说明这一点。我们可以清楚地看到概率、赔率和对数赔率之间的单调关系。
为什么这很重要?log-odds 值越高,概率越高。在图 2 中,我们可以非常清楚地看到这一点。任何等于或大于 0 的对数优势值都有 0.5 或更高的概率。这是由于我们在图 4 中观察到的单调关系。当我们解释估计的参数时,这也会派上用场。
图 4:概率 vs .赔率&赔率 vs .对数赔率;图片由作者
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
import matplotlib.pyplot as plt
plt.style.use(‘ggplot’)
%matplotlib inlinelogreg = LogisticRegression(random_state=0)
model_pipe = make_pipeline(StandardScaler(), logreg)
X = train[[‘age’,’pclass’,’sex’]]
y = train[‘survived’]
model_pipe.fit(X, y)
model_pipe.predict_proba(X)y_pred_proba_1 = model_pipe.predict_proba(X)[:,1]
y_pred_proba_0 = model_pipe.predict_proba(X)[:,0]
odds = y_pred_proba_1 / y_neg_pred_proba_0
log_odds = np.log(odds)fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16,6))
ax1.set_title(‘Probability vs. Odds’)
ax1.set(xlabel=’Probability’, ylabel=’Odds’)
ax1.scatter(y_pos_pred_proba, odds)
ax2.set_title(‘Odds vs. Log Odds’)
ax2.set(xlabel=’Odds’, ylabel=’Log Odds’)
ax2.scatter(odds, log_odds);
Sigmoid 组合概率、似然和对数似然
我们覆盖了很多领域,现在我们处于理解高层次逻辑回归的最后一英里。图 5 中的概率函数 P(Y=yi|X=xi)捕捉到了 Y=1 和 Y=0 的形式。基于 Y (0 或 1),点积中的一项变为 1 并下降。这种组合形式对理解可能性至关重要。
图 5:概率函数作为 Y=0 和 Y=1 项的组合形式;图片由作者
让我们来看看我们是如何得到 可能性 、L(𝜃).的对于训练集中的每个实例,我们使用随机估计参数(𝜃's) 计算对数优势,并使用对应于特定二元目标变量(0 或 1)的 sigmoid 函数预测概率。这些概率的乘积将给出所有实例的概率和可能性,如图 6 所示。重要的是要注意,可能性被表示为𝜃的可能性,而概率被指定为 y 的概率
图 6:似然函数;来源阅读:克里斯皮赫,CS109 @斯坦福大学;图片由作者
结果,通过最大化可能性,我们收敛到最优参数。换句话说,最大化似然估计最佳参数,我们直接最大化 y 的概率,这就是所谓的最大似然估计(MLE)。因此,当达到最大值时,初始参数值将逐渐收敛到最优值。收敛是由优化算法——梯度上升/下降驱动的。
对数似然法如何适应这种情况?取似然函数的对数,就变成了求和问题对乘法问题。我们知道 log(XY) = log(X) + log(Y)和 log(X^b) = b * log(X)。因此,我们可以轻松地将似然性(L(𝜃)转换为对数似然性(LL(𝜃),如图 7 所示。因为似然性到对数似然性是一种单调变换,最大化对数似然性也将产生最佳参数,这被称为最大对数似然性。请记住,这是我们正在优化的𝜃的对数似然。
图 7:对数似然函数;来源阅读:克里斯皮赫,CS109 @斯坦福大学;图片由作者
如何使用对数似然达到最大值?我们对每个𝜃参数取对数似然函数的偏导数。换句话说,你为每个参数取梯度,它有大小和方向。例如,在 Titanic 训练集中,我们有三个特征加上一个偏差项,所有实例的 x0 都等于 1。图 8 中的偏导数表示训练集中的单个实例( i) 和单个𝜃参数( j) 。 x (i,j) 表示实例中与其对应的𝜃 ( i,j )参数配对的单个特征。因此,对于单个实例,总共创建了四个偏导数——偏差项、pclass、性别和年龄。这些组成了梯度向量。
η是学习率,它决定了梯度上升算法每次迭代的步长。我们不希望学习率太低,需要很长时间才能收敛,也不希望学习率太高,会超调,会跳来跳去。学习率也是一个可以优化的超参数,但是我将在 Titanic 练习中使用固定的学习率 0.1。
一旦有了梯度向量和学习率,两个实体相乘并添加到当前要更新的参数中,如图 8 中的第二个等式所示。本质上,我们是在梯度方向上一小步一小步地缓慢而坚定地到达顶峰。这个更新步骤重复进行,直到参数收敛到它们的最优值——这是梯度上升算法在起作用。因为对数似然函数是凹的,最终,小的上坡步骤将达到全局最大值。
图 8:每个𝜃参数的偏导数和梯度上升算法;图片作者作者
**最小化成本函数怎么样?**我们经常听到我们需要最小化成本或损失函数。它也被称为目标函数,因为我们试图最大化或最小化某个数值。在成本或损失函数的上下文中,目标收敛到全局最小值。例如,通过在对数似然函数前面放置一个负号,如图 9 所示,它就变成了交叉熵损失函数。目标是使用 梯度下降算法 (图 10 中的第二个方程)最小化这个负函数。这个过程与最大化对数似然相同,只是我们通过下降到最小值来最小化它。
图 9:交叉熵损失函数或负对数似然(NLL)函数;来源阅读:机器学习:概率视角凯文·p·墨菲 —第 8 章;图片由作者
一旦每个𝜃参数的偏导数(图 10)被导出,形式与图 8 相同。最大的区别是减法项,它用 sigmoid 预测概率减去实际 y (0 或 1)重新排序。该项然后乘以 x (i,j) 特征。该过程与上面的梯度上升部分中描述的过程相同。因此,我们将得到训练集中每个实例的四个偏导数。并且使用梯度下降算法,我们更新参数直到它们收敛到它们的最优值。
图 10:每个θ参数的偏导数和梯度下降算法;来源阅读:丹·茹拉夫斯基、詹姆斯·h·马丁著《言语与语言过程》(第三版草稿) —第五章;图片由作者
幸运的是,交叉熵损失函数是凸的,自然有一个全局最小值。最终,在坡度方向(最陡的下坡方向)迈出足够小的步伐后,它将到达山脚。
行动中的代码
既然我们已经回顾了相关的数学知识,那么现在只需要用代码来展示逻辑回归和梯度算法的能力。先说我们的数据。我们有来自卡格尔的泰坦尼克号挑战的训练和测试设备。如前所述,我只使用三个特征——年龄、阶级和性别——来预测乘客存活率。
首先,我们需要扩展特性,这将有助于融合过程。我将使用标准化方法来缩放数字要素。在标准化中,我们取每个数字特征的平均值,并从每个值中减去平均值。然后将该项除以特征的标准偏差。接下来,我们将添加一个全 1 的列来表示 x0。这是偏向项。
特征标准化代码由作者
使用上面的代码,我们已经准备好了训练输入数据集。我们现在知道 log-odds 是线性回归函数的输出,这个输出是 sigmoid 函数的输入。唯一缺失的是𝜃参数。因为我们将使用梯度上升和下降来估计这些参数,我们选择四个任意值作为我们的起点。我将用四个零作为初始值。我们还需要在代码中定义 sigmoid 函数,因为这将生成我们的概率。
# sigmoid function where z = log-odds
def sigmoid(z):
predict_proba = 1 / (1 + np.exp(-z))
return predict_proba
我们已经准备好了所有的东西。**接下来,我们将把对数似然函数、交叉熵损失函数和梯度转换成代码。**我们还需要确定我们要对训练集进行多少次检查。我们需要定义历元的数量(在下面的代码中指定为 n_epoch,这是一个帮助学习过程的超参数)。**什么是纪元?**在梯度上升/下降算法的背景下,历元是单次迭代,其中它确定多少训练实例将通过梯度算法来更新𝜃参数(如图 8 和 10 所示)。
因此,我们通常会遇到三种梯度上升/下降算法:批量、随机和小批量。对于泰坦尼克号练习,我将使用批处理方法。这意味着,对于每个时期,整个训练集将通过梯度算法来更新𝜃参数。
梯度上升代码由作者
给你!通过利用梯度上升算法最大化对数似然,我们已经为泰坦尼克号训练集导出了预测乘客存活率的最佳𝜃参数。
- 𝜃0: -0.89362715(偏差项)
- 𝜃1: 1.41685703(pclass)
- 𝜃2: 1.24119596(性别)
- 𝜃3: -0.60707722(年龄)
让我们想象一下最大化的过程。在图 11 中,我们可以看到,在第一个时期后,我们达到了最大值,并继续保持在这个水平。
图 11:最大化每个历元迭代的对数似然函数;图片作者作者
x_axis = [i for i in range(1, 11)]
plt.figure(figsize=(14,6))
plt.title(‘Maximizing Log-Likelihood’)
plt.xticks(x_axis)
plt.xlabel(‘epoch iteration’)
plt.ylabel(‘log-likelihood’)
plt.plot(x_axis, log_likelihood_vals, marker=’o’)
plt.tight_layout()
我们还可以看到每次历元迭代的𝜃参数收敛。正如我们在图 11 中看到的,对数似然在第一个时期后达到最大值;我们应该看到同样的参数。在图 12 中,我们看到参数在第一个时期后收敛到它们的最佳水平,并且最佳水平随着代码在剩余时期的迭代而保持。迭代训练集一次就足以达到最佳𝜃参数。让我们检查一下在每个时期间隔期间发生了什么。
图 12 右侧的曲线显示了𝜃参数值快速向其最佳值移动。当它继续迭代通过每个时期中的训练实例时,参数值上下振荡(时期间隔用黑色垂直虚线表示)。在每个时期结束时,我们以最佳参数值结束,并且保持这些值。
图 12:每个时期(左)和每个实例(右)的𝜃参数收敛;图片由作者
图 12 —由作者编写的代码
是时候使用该模型进行预测,并生成准确度分数来衡量模型性能了。有几个衡量性能的指标,但现在我们将快速了解一下准确性。下面的代码产生了 79.8%的准确率。
from sklearn.metrics import accuracy_scoredef make_predictions(X, thetas):
X = X.copy()
predictions = []
for x_row in X:
log_odds = sum(thetas * x_row[:4])
pred_proba = sigmoid(log_odds)
# if probability >= 0.5, predicted class is 1
predictions.append(1 if pred_proba >= 0.5 else 0)
return predictionsy_train = X_train[:, -1]
y_predict = make_predictions(X_train[:, :4], thetas)
accuracy_score(y_train, y_predict)
**交叉熵损失函数呢?**最小化交叉熵损失函数的结果将与上面相同。只有几行代码更改,然后代码就可以运行了(参见下面代码中的' # changed ')。这是代码。
梯度下降代码作者作者
让我们看看使用梯度下降最小化交叉熵损失函数。我们在第一个时期后达到最小值,正如我们观察到的最大对数似然。最大的不同是,我们正朝着最陡下降的方向前进。这就是我们经常读到和听到的——最小化成本函数来估计最佳参数。我们现在已经具备了从头构建二元逻辑回归模型的所有组件。我希望这篇文章能帮助你,就像我帮助我加深对逻辑回归和梯度算法的理解一样。
图 13:最小化交叉熵损失函数;图片由作者
x_axis = [i for i in range(1, 11)]
plt.figure(figsize=(14,6))
plt.title(‘Minimizing Cross-Entropy Loss’)
plt.xticks(x_axis)
plt.xlabel(‘epoch iteration’)
plt.ylabel(‘cross-entropy loss’)
plt.plot(x_axis, ce_loss_vals, marker=’o’)
plt.tight_layout()
最后的想法
在这篇文章中,我的目标是提供一个坚实的二元逻辑回归模型和估计最佳𝜃参数的两种方法的介绍性概述。正如我们在泰坦尼克号的例子中看到的,主要的障碍是估计最佳的𝜃参数来拟合模型,并使用这些估计来预测乘客的存活率。我们使用梯度上升算法检验了(最大)对数似然函数。我们还使用梯度下降算法检查了交叉熵损失函数。当然,您可以将其他成本函数应用到这个问题上,但是我们已经讨论了足够多的内容,以了解我们试图通过梯度上升/下降实现的目标。
我们将何去何从?在改进模型方面,我们可以探索几个领域。我们可以从学习率开始。学习率是一个超参数,可以调整。在许多情况下,随着梯度上升/下降算法向前发展,引入学习速率表来减小步长。
如果数据集很大,批处理方法可能并不理想。理解随机和小批量梯度下降算法的机制会更有帮助。然而,一旦理解了批量梯度下降,其他方法就相当简单了。除了我在本文中使用的标准化方法之外,还有不同的特性扩展技术。
如果你遇到任何问题或有反馈给我,请随时留下评论。感谢阅读!
了解逻辑回归
原文:https://towardsdatascience.com/understand-logistic-regression-c883e0d84693?source=collection_archive---------26-----------------------
入门
一个基于案例研究的介绍,带你从直觉到实现
**Table of Contents**· [Purpose](#f825)
· [Why Should You Read On?](#1fb3)
· [Logistic Regression in the Big Picture](#7e95)
· [Why Logistic Regression?](#ee06)
· [The Case Study](#9db8)
· [Logistic Regression Under the Hood](#8237)
∘ [The Classification Task](#1204)
∘ [The Rationale for Using Multiple Features](#f3aa)
∘ [Data Visualization](#bf8a)
∘ [The Linear Equation](#c9f1)
∘ [The Logistic Function](#c902)
∘ [The Cost Function](#2423)
∘ [The Optimization](#6ccb)
∘ [The Prediction](#c7c5)
∘ [Implementation from Scratch](#aee7)
· [Summary](#a069)
目的
本文将通过一个受现实世界例子启发的案例研究,帮助您直观地理解逻辑回归。您还将能够从头开始实现您自己版本的逻辑回归(如果您愿意)。这篇文章假设没有机器学习的先验知识,将带你从基础(专注于直觉)开始,一路帮助你用自己选择的编程语言实现它。提供了相关的代码(在我的 GitHub 库),这样任何人,如果感兴趣,都可以下载代码并使用这个案例研究来学习如何实现逻辑回归,并真正理解幕后发生的事情。一旦你读完这篇文章,你将有望开始看到并想象使用逻辑回归进行分类任务背后的数学原理(如果它是为了帮助你分类,你为什么要称之为回归呢?继续读下去),并有足够的信心将其应用到自己的工作中。
你为什么要继续读下去?
如果你是一名有抱负的数据科学家,并认真学习这门手艺,你将需要投入一些时间,试图更好地理解直觉和一些算法的工作原理。将机器学习技术视为黑盒只能带你走这么远。你至少应该对基本原理有所了解,这样你就能在这个领域卓有成效地工作,并对使用什么技术、何时使用以及如何解释结果做出更好的决定。如果有一个算法你应该有一个清晰的理解,在引擎盖下,它是逻辑回归(如果你想知道为什么,在所有的技术中,它必须是逻辑回归)。
大背景下的逻辑回归
让我们从绝对的开始说起,数据科学的大图景。机器学习(ML)是数据科学的一个子集,位于计算机科学和数学的交叉点,该领域的核心和灵魂是从数据中学习。
要获得更有哲理、更详细的概述,请查看我的另一篇文章:
机器学习本身可以根据学习的类型分为三个子领域:监督学习、非监督学习和强化学习。这些学习类型中最广泛和公认的是监督学习。在监督学习中,解决的两种主要问题是分类和回归。在分类(这有助于将数据分为不同的类)中,您可以进一步将其分为生成模型和判别模型。在判别模型中,最常用的方法是逻辑回归。
展示逻辑回归在整个生态系统中的位置的数据科学景观(图片由作者提供)
为什么是逻辑回归?
正如我提到的,在 ML 中,最常见的学习类型是监督学习,该领域中解决的最常见和公认的问题是分类(猫对狗,垃圾邮件对火腿,疾病对健康等)。).你可能想知道,为什么在众多的技术中,你还要费心去学习逻辑回归。有两个主要原因可以解释为什么你应该在深入学习之前花时间学习逻辑回归。
首先,如果任何高级算法没有附加价值,那么尝试实现它是没有意义的(在建模任何东西时,永远记住奥卡姆剃刀)。需要有一个简单、可解释的算法,您可以轻松、快速地在您的数据集上实现,以作为您的基准。用于分类的逻辑回归是作为基准的理想算法。一旦有了基准,只有这样,您才能投入资源来改进您的基准解决方案(否则,当您不知道除了简单、可解释且易于实现的算法之外,实现更复杂的算法是否有任何价值时,这是对资源的不良利用)。
其次,如果你是该领域的新手,你可能会感到惊讶,在你的数据集上,支持向量机(SVM)等更高级的算法不一定总是比逻辑回归(LR)做得更好。事实上,在一些应用中,LR 做得相当好,并且当使用 SVM 或任何其他算法时,没有获得改进。底线是,在所有的可能性中,当你开始解决一个问题时,你应该使用 LR 作为你的分类算法,它对于分类的重要性不能被夸大。因此,绝大多数关于机器学习的课程在早期就教授 LR 也就不足为奇了。当你进一步阅读时,你会很快意识到 LR 非常直观并且易于实现。
案例研究
你可以在我们发表在《医学互联网研究杂志》(JMIR,医学信息学的知名研究期刊之一)上的论文中了解更多这方面的内容。
https://www.jmir.org/2017/3/e69/
简而言之,慢性阻塞性肺病(COPD)是一种长期疾病,患者的肺部受到不可逆的损害,以至于日常活动可能会使他们喘不过气来。这种疾病无法治愈,患有慢性阻塞性肺病的人将在余生中一直处于这种状态。然而,如果 COPD 患者能够通过监测他们的症状并在需要时及时服药来自我管理他们的病情,他们仍然可以生活得很好并获得高质量的生活。虽然 COPD 症状很常见,但是在事情恶化到患者最终住院的程度之前,需要及时处理症状的持续恶化。患者如何识别自己的病情是否正在恶化?一种方法是使用一个小的手指探针(称为脉搏血氧计),可以测量心率,血液中的含氧量(称为氧饱和度)和呼吸频率。我们的任务是在患者病情恶化时,仅使用脉搏血氧仪向患者提供早期预警。
问题的概念图(图片由作者提供)
**免责声明:**首先,数据集(您可以在 github 上找到)是模拟数据,而不是来自我们研究的实际数据。然而,它是使用论文中公布的类似平均值生成的(并可公开获得)。其次,在这篇文章中,我将挑战简化为只关注心率和呼吸率的二维问题,因为在二维空间中更容易可视化数据点。然而,一旦你理解了二维的概念,你就可以很容易地把它扩展到三维或更多维,并且基本原理不会改变。
幕后的逻辑回归
现在,你对大局有了很好的认识,逻辑回归在更大的事物计划中的位置,并且你对我们试图解决的问题有了理解,让我们进入一些细节。
分类任务
我们现在面临的挑战是,通过结合两种信息:心率和呼吸率,在患者病情恶化之前向他们提供早期预警。我们希望以最佳方式将这两种测量方法结合起来,以确定患者的病情是否在恶化。为简单起见,我们将这些情况称为“异常”。(在最初的论文中,他们被称为“前驱”)。当病人的情况稳定并且没有恶化的危险时,这一时期被称为正常时期。因此,我们现在的问题归结为基于两种测量来发现患者是正常还是异常:心率(HR)和呼吸率(BR)。
分类目标:使用患者的心率和呼吸率来识别患者是正常还是异常。
使用多种功能的基本原理
首先要问的问题是:为什么我们甚至需要两种不同的测量方法?难道我们不能用 BR 或 HR 来做决定吗?为什么使用多种测量方法会使我们的生活变得复杂?如果你有一种情况,单次测量导致正常和异常之间的完美分离,你不需要第二次测量。从图形上看,应该是这样的:
心率在两类中的分布,在一个假设的情况下,完美的分离是可能的,现实世界的例子不像这些(图片由作者提供)
事实上,为此你甚至不需要任何机器学习。您可以绘制数据,并直观地看到一个简单的规则可以将这两种情况分开。在单次测量的情况下,这个简单的规则在图形上是一条垂直线。在上图中,这相当于 HR 为 78。如果患者的心率高于 78,患者将被视为异常,如果患者的心率低于 78,患者将被视为正常。你在图中看到的这条垂直线被称为“决策边界”。对于这种情况,当你有一个单一的测量和如此明确的分离,任何垂直线都可以完美地分开两者(决策边界在 77,78 或 79 都同样完美)。然而,现实世界的问题是困难的(并且是问题),因为这种分离并不直接,并且有许多重叠。因为对于单个测量来说重叠是很多的,因此,我们对同一患者进行不同类型的测量,虽然有很多重叠,但是我们希望每个测量都有独立的信息,并且通过组合不同的测量,我们希望找到更好的决策边界,与仅使用单个测量相比,可以导致更少的误差。例如,检查案例研究中呼吸率、心率和氧饱和度的重叠(如果有人有兴趣使用,可以在我的 github 存储库中找到这些数据。它是使用本文前面引用的原始论文中可以看到的相同数据分布进行模拟的。
正常和异常(前驱)情况下心率(脉率)、呼吸率和血氧饱和度(SpO2)的概率分布(图片由作者提供)
为了简单起见,我们将使用另一个模拟数据集,该数据集受到相同问题的启发,但它显示了正常和异常之间更多的分离(如前所述,仅使用心率和呼吸率)。让我们从分别绘制两种情况下的心率和呼吸率分布开始。
正常和异常情况下的心率和呼吸率的概率分布,请注意正常和异常情况下的呼吸率和心率存在重叠(图片由作者提供)
数据可视化
如您所见,存在重叠,HR 或 BR 的单一阈值会导致相当大的误差。让我们在一个单独的图中绘制 HR 和 BR,以便您可以直观地看到问题。
在我们的案例研究中,心率与呼吸频率的散点图(图片由作者提供)
线性方程
如果我们将 HR 和 BR 结合起来帮助我们找到“最优”决策边界,我们能做的最简单的事情是什么?最简单的方法是将呼吸率和心率进行线性组合。从数学上讲,这相当于求一个加权和,如下式所示:
呼吸率和心率的加权和,其中 A 和 B 是未知参数(图片由作者提供)
从图形上看,这相当于在二维图上找到一条直线。因此,问题归结为找到正确的值 A 和 B 来拟合一条线(决策边界),这条线可以帮助我们区分正常和异常情况。
只是有一点需要注意:如果我们只需要将这个问题简化为寻找 A 和 B ,那么得到的直线将总是通过原点。为了消除这种限制,我们可以添加一个“偏差”项,因此,最终的等式变成如下:
为了确保“决策边界”不仅限于通过原点,我们添加了一个“偏差”项,这是一个需要在“学习”过程中确定的附加参数。在上面的等式中,“偏置”项是 c。
因此,分类问题在概念上可以被看作是寻找能够最好地分离正常和异常情况的直线方程的未知参数。
物流功能
我们仍然需要对一些事情进行排序,包括找出我们如何找到找到最佳线的方法(对于 2-D 情况,这在目前看起来可能是显而易见的,但请记住,这是一个有助于可视化的更简单的问题,一旦我们理解了这一点,相同的原则将适用于更高维度的问题,因此我们需要找到一种自动和有原则的方法来找到这一点)。
如你所知,心率和呼吸率的线性组合的输出没有限制。它可以取任何值,完全取决于 HR 和 BR 的值。
如果方程的输出可以转换成概率不是很方便吗?
事实证明,有一种方法可以迫使心率和呼吸率的线性组合的输出限制在 0 和 1 之间(这可以解释为一种概率)。为了实现这个目标,我们所要做的就是将线性组合的输出作为一个新函数的输入,该函数可以将从-无穷大到+无穷大之间的任何值作为输入,然后输出一个介于 0 和 1 之间的值。“逻辑”回归中使用的一个函数就是“逻辑”函数(该函数也称为 sigmoid 函数)。
逻辑函数及其与使用特征的线性组合的关系(图片由作者提供)
您可以将此过程视为制作一个要素线性组合包,然后将该包交给逻辑函数,该函数会将输出转换为 0 到 1 之间的变量。然而,这种转换不是随机的。如果你仔细观察逻辑函数,你会注意到它为任何正输入输出值 > 0.5 ,为任何负输入输出值 < 0.5 。因此,我们需要做的就是找到 A,B,C 的值(根据前面定义的等式),使得线性等式在真实值为 0 的情况下输出非常大的负值(按照惯例,我们将 0 分配给正常情况),当真实值为 1 时输出非常大的正值(1 对应于患者异常的情况)。或者用更简单的话来表述:我们需要找到 A,B,C 的值,使得逻辑函数的输出接近实际值。
成本函数
一种方法是定义一个“成本”函数。并且该成本函数需要确保当来自逻辑函数的输出与实际值非常不同时它输出大的值(假设实际值是 1 并且逻辑函数输出非常小的值,接近 0,或者如果实际值是 0 并且逻辑函数输出接近 1 的大值)。相反,这个成本函数需要输出一个非常小的值,当输出与实际值匹配时,理想情况下为 0。如果我们可以有这样一个成本函数,那么我们所要做的就是找到导致最小成本函数的参数 A、B、C 的值。
优化
寻找成本函数最小值的过程称为“最优化”。我们要怎么做?我们可以使用微积分(更具体地说,是一种梯度下降算法,可以帮助我们找到函数的最小值)。虽然在理论上,我们可以使用几个具有这种特性的数学函数(当差异高时,成本值高,当差异低时,成本值低),但我们还需要确保函数是“凸的”。这有助于我们使用微积分轻松找到成本最小的参数值。如果我们没有凸函数,那么我们不一定能找到全局最小值,它也不会是最优解。令人欣慰的是,逻辑回归的成本函数的要求已经被很好地研究和计算出来了,从图形上看,当实际输出为 1 时,它看起来像下面这样。为了强调这些概念,我给这幅图贴上了标签。成本函数取决于预测值,从图中我们可以看到,当实际产量和预测产量完全匹配时,成本为 0,随着预测值和实际值之间的差异增加,成本逐渐增加。
实际输出为 1 时使用的成本函数。请注意,当预测输出 y 为 1(实际值和预测值完全匹配)时,成本为 0。然而,随着预测产量接近 0(实际值和预测值完全不匹配),成本逐渐增加。(图片由作者提供)
如果您已经掌握了上面的成本函数图,那么下一个应该马上就清楚了(它是前面图的镜像,描绘了实际输出为 0 时的场景)。
实际输出为 0 时使用的成本函数。请注意,当预测输出 y 为 0(实际值和预测值完全匹配)时,成本为 0。然而,随着预测产量接近 1(实际值和预测值完全不匹配),成本逐渐增加。(图片由作者提供)
一旦你定义了成本函数,你现在需要做的就是运行一个优化算法,找到未知的值,可以帮助你得到最小值。为了开始优化过程,我们需要将未知数的值初始化为一些值。随后,我们可以运行该函数并获得未知参数的值,对于这些参数,成本函数是最小值。运行这个,在我们的问题中,我们得到下面的决策边界。
使用成本函数最小的 A、B 和 C 值得到的决策边界。(图片由作者提供)
预测
最后,如果我们需要对一个新的数据集进行预测,我们需要做的就是得到它们的 HR 和 BR,并使用学习时找到的参数值 (A,B,C) 找出预测输出, y 。从图形上看,这相当于确定新数据点位于决策边界的哪一侧。如果高于该线,则可认为患者正常。如果低于该线,则可认为患者异常。
从头开始实施
为了保持帖子简短,我将分享如何从头实现逻辑回归的要点。然而,你可以查看我的 github 库来访问产生这篇文章中的图片的代码(在 Matlab 中实现)。如果有兴趣的话,我随后也会在资源库中分享 Python 和 R 代码。关键的实施步骤是:
㈠以矩阵形式获取数据
(二)可视化数据(散点图以查看相关性,直方图或密度图以更好地了解数据的分布)
㈢增加截距(偏差)项
(iv)初始化未知参数(在这种情况下,任何随机数都可以)
(v)定义成本函数并运行优化例程(您会发现在您选择的任何编程语言中都有内置的例程来实现这一点)
㈥划定决策界限
㈦进行预测
这里的帖子中已经给出了需要实现的各种方程(见两个成本函数图)。结合代码阅读本文应该很简单,可以帮助您找出完整的管道并自己实现它。
摘要
本文假设没有机器学习的先验知识,并从数据科学的大背景出发介绍了逻辑回归。然后,它证明了为什么任何有抱负的数据科学家都应该投入时间来理解逻辑回归是如何工作的。然后,它继续解释逻辑回归的关键概念,并提供了数学方程和图形表示,以帮助理解。这些概念都解释了作者自己的研究工作启发的案例研究的帮助。
https://ahmarshah.medium.com/membership
直观地理解 MapReduce
原文:https://towardsdatascience.com/understand-mapreduce-intuitively-1301287e7677?source=collection_archive---------32-----------------------
了解处理大数据的商业秘密
安德鲁·尼尔在 Unsplash 上拍照
介绍
大数据到底有多大?根据里奥纳尔迪·钱德拉塞塔的说法,他在处理大数据时的经验是128 Pb。这么大的数据量实在让人无法理解。如果您从未处理过这种规模的数据,我推荐您阅读他的文章,它也是这篇文章的灵感来源。
简单来说,逐行执行操作在万亿级别是不够的。当处理不可逾越的数据量时,需要某些技术来计算各种统计数据,以及强大的计算集群。有许多方法可以提高性能,但最常用的技术是 MapReduce。在了解其工作原理或为何如此有效之前,我们先来了解并行化。
简而言之,并行化
假设您有一个 Python 脚本要运行,但没有关于如何运行的具体指令,它会连续运行。串行计算意味着每个进程都按照指定的顺序运行。然而,我们可以看到,对于大量的数据,这可能是一个严重的问题。然而,并行化允许同时或并行处理批量数据。
机器上的大多数 CPU 都有多线程能力。这意味着一个 CPU 有许多线程或内核,允许更多数据流通过进行并行处理。事实上,我的笔记本电脑是 2015 年制造的,它有 8 个核心。
假设您在一台拥有 16 个 CPU 内核的计算机上工作。你的机器允许数据被分割成 16 个不同的线程进行处理。如果在使用 16 个内核后仍有更多数据,下一批将被分配给第一个分配的内核,之后的一批将被分配给第二个内核,并且该过程将继续,直到所有数据都被处理完。
这使得每个 CPU 核心成为一个工作节点。工作节点被分配了许多要提前执行的作业,并且所有节点同时完成它们的作业。如我们所见,这允许同时操作大量数据,从而实现更快的性能。但是这和 MapReduce 有什么关系呢?
MapReduce
Map 过程获取相关的数据集,并使用过滤或排序将其转换为另一个更小的数据集。每个数据点将被分配一个 ID,让计算机知道它将被分配到哪个工作节点。在 Reduce 步骤之前,有一个称为 Shuffle 过程的中间过程。这将获取经过排序/筛选的数据,并重新分配这些数据,以确保将它们分配给适当的工作人员。一旦完成,Reduce 过程可以是许多过程中的一个,但是顾名思义,就是将新的映射数据集简化为有问题的解决方案。
值得注意的是,您可以利用单核的 MapReduce 过程。然而,它并没有表现出比在没有 MapReduce 的情况下实现函数本身更快。简而言之,MapReduce 是一个在并行计算中发挥其最大潜力的过程。SunLab 的下图很好地展示了这一过程。
照片由太阳实验室提供
结论
随着 MapReduce 的直觉开始形成,很容易看到它在数据科学和机器机器学习中的效用。最简单的用例可能是找到某个汇总统计数据。这可能像均值一样简单,也可能像发现一首歌的可舞性一样复杂。
在数据科学中,特征提取是关键。当处理数 Pb 的数据时,以有效的方式找到必要的特征不仅会使您作为数据科学家的工作变得容易得多,而且还会让您找到以前从未梦想过的洞察力。
https://learningfrommachines.substack.com/welcome
使用简单的 python 理解 Q-Q 图
原文:https://towardsdatascience.com/understand-q-q-plot-using-simple-python-4f83d5b89f8f?source=collection_archive---------2-----------------------
可视化数据的有效方法
作者图片
简介
工程师和科学家处理数据。没有数据,他们无法得出任何结论。现在是每天从我们生活的各个方面创造数据的时代。有些数据是随机的,有些是有偏差的。由于数据收集过程,有些人可能会有偏见。数据的一个非常重要的方面是分布概况。收集的数据可能呈正态分布,也可能远离正态分布。它也可以向一侧倾斜,或者可以遵循多模态模式。它可以是离散的,也可以是连续的。对于连续数据,正态分布相比于它的对应物有很多优势。各种推断统计过程都假设分布是正态的。钟形曲线很容易用均值和标准差来描述。
典型的正态分布数据(图片由作者提供)
为什么要阿 q 情节?
由于正态分布如此重要,我们需要检查收集的数据是否正态。在这里,我们将演示 Q-Q 图来检查数据偏态的正态性。Q 代表分位数,因此,Q-Q 图代表分位数-分位数图。为了确定正态性,也有一些统计检验,如科尔莫戈罗夫-斯米尔诺夫检验和夏皮罗-维尔克检验。本文范围仅为 Q-Q 剧情。
简要说明
我们现在知道 Q-Q 图是分位数-分位数图,但首先分位数是什么?当对整个数据进行排序时,第 50 个分位数意味着 50%的数据低于该点,50%的数据高于该点。这是中间点。当我们说第一分位数时,只有 1%的数据低于该点,99%的数据高于该点。第 25 和第 75 分位数点也称为四分位数。数据集有三个四分位数。
Q1 =第一个四分位数=第 25 个四分位数
Q2 =第二个四分位数=第 50 个四分位数=中位数
Q3 =第三个四分位数=第 75 个四分位数
分位数有时被称为百分位数。下面是一个典型的 Q-Q 图。让我们解释一下这个看起来几乎是一条直线的图。
Q-Q 图(图片由作者提供)
轴
Q-Q 图的 x 轴代表标准正态分布的分位数。假设我们有一个正常的数据,我们想标准化它。标准化意味着从每个数据点中减去平均值,然后除以标准差。结果也称为 z 分数。让我们对这些 z 值进行排序,然后再进行绘图。下图显示 x 轴现在以 0°为中心,并在每侧延伸至 3 个标准差。据统计,99.7%的数据都在这个范围之内。
标准化正态数据的分布(图片由作者提供)
找到 Q-Q 图的 x 轴值的第一步是确定该正态分布标准数据的分位数/百分位数。这样,我们就可以得到在所有 Q-Q 图中非常标准的分位数。当我们使用这些 z 分数时,x 轴将大致从-3 延伸到+3。
一旦我们获得了沿 x 轴绘制的值,我们就需要对感兴趣的数据应用相同的方法。因此,我们将绘制 out 数据的 z 得分与标准正态数据的 z 得分。如果我们的数据是正常的,绘图将是一条直线,因为我们正在绘制非常接近的值。如果数据不是正态分布的,线就会偏离直线轨道,发出不同情景的信号。
右侧数据失真(图片由作者提供)
例如,如果数据偏高(如上所示),我们将获得类似下图的 Q-Q 图。
偏斜数据的 Q-Q 图(图片由作者提供)
如果数据显示双峰,Q-Q 图也会显示这一点。
双峰数据(图片由作者提供)
双峰数据的 Q-Q 图(图片由作者提供)
本文的教程链接是这里的。
用 python 实现
Python 有 stastsmodels 库,里面有方便的 qqplot 模块可以使用。
Statsmodels 正常数据的 Q-Q 图(图片由作者提供)
为了更好地理解,我还将展示代码块的分解,以便简单地实现它。一旦我们有了数据框架中的数据,我们需要将其标准化。
接下来,我们需要找到分位数/百分位数。
最后,我们需要对输出和绘图进行排序。
就是这样。我们可以使用这个 Q-Q 图快速查看数据的正态性。
结论
Q-Q 图是一个非常有用的工具,可以确定数据的正态性或数据偏离正态性的程度。此图表示沿 x 轴的标准正态分布的 z 得分以及所获得数据的相应 z 得分。有时,也可以沿 y 轴绘制样本分位数,而不是 z 得分。
Github 页面
感谢阅读。
理解支持向量机
原文:https://towardsdatascience.com/understand-support-vector-machines-5bfe800a0e03?source=collection_archive---------17-----------------------
一个初学者友好的 SVM 方程推导与直观的解释
正交投影给出了我们从一个点到一个平面的最短距离,就像我们在日常生活中所习惯的一样(图片由作者提供)
"真正的知识来自对一个主题及其内部运作的深刻理解."[人名]阿尔伯特·爱因斯坦(犹太裔理论物理学家)
为什么我要费心学习 SVM 背后的数学?
有许多可用的库可以帮助我使用 SVM,而不必担心底层的概念。
当然可以!你完全正确。你不需要理解 SVM 就能使用它。您甚至可以应用 SVM 来解决分类问题,而无需理解其背后的基本概念。有大量的工具随时可用。再也没有人在现实世界的项目中从头开始实现 SVM 了。
然而,如果你是一个有抱负的数据科学家,你应该花一些时间学习这些基本概念,以了解各种代数和几何参数如何最终成为一种算法。
学习或遵循每个算法的本质是不可能的,但有一些绝对基本的概念,任何认真的从业者都应该接触到。这样的曝光将新手和熟练者区分开来。
SVM 只是一个工具。就像锤子是木匠的工具一样。然而,拥有锤子并不会让每个人都成为有用的木匠。同样,把访问 SVM 作为一种工具并不一定会让你成为有用的数据科学家。
数据科学既是一门艺术,也是一门科学。作为一名数据科学家,如果你想精通你的技术,那么我建议你必须花一些时间去理解一些精选的、众所周知的算法的数学和几何论证。
这正是这篇文章的目的:使用高中数学和几何推导 SVM 方程,并使用直观和易于理解的论点!
SVM 是理解监督机器学习的几何观点和巩固向量代数在机器学习中的使用的理想算法。让我们开始吧!
如果你能仔细阅读这篇文章,那么你应该最终对 SVM 背后的数学有一个清晰的理解,并且(希望)认识到 SVM 数学只是看起来吓人,但实际上非常简单!
在以前的文章中,我已经给出了一个非常温和的介绍,仅提供几何直观。如果你不太熟悉 SVM 的基本概念(或者对 SVM 与逻辑回归的区别有点生疏),那么我建议你先读一读我以前关于这个主题的文章。
线性可分的两类
帮助解释 SVM 概念的最基本的场景是解决一个二元分类问题,其中两个类是线性可分的。相应的解决方案也称为“硬”SVM。这是因为一旦找到了“最优”决策边界,就不会有错误。所有训练点都在决策边界的正确一侧。这与“软余量”SVM 形成对比,当我们处理不是线性可分的分类任务并且允许一些错误时。
SVM 方程(从技术上讲,是一个方程和一个不等式)是:
硬边界支持向量机方程(图片由作者提供)
文章的其余部分将推导出上述内容。先来个数学鸟瞰!
注:知名的机器学习书籍中有很多关于这个话题的优秀资源。根据您查看的资源,您会发现在使用的符号方面有细微的变化。为了让这篇文章易于理解,我选择了“机器学习的数学”所采用的符号,可以在 GitHub 上免费获得。
分类的高级数学视图
您可以将分类任务视为一个映射,该映射接受一个 n 维输入(特征向量, x )并输出一个 1 维类标签, y (假设一个类为正,另一个类为负)。
实数的 n 维向量空间(输入)被映射到 1 维向量空间(输出)的函数;(图片由作者提供)
为了进一步挖掘,我们需要理解超平面的概念!
超平面
什么是超平面?在二维情况下,超平面是一条分隔线。在一个三维的 T21 案例中,它是一个平面。在 n 维的情况下,它是一个 (n-1) 维的向量空间(一个超平面)。
内积是表示超平面的一种方便的符号
我们需要在 x 中找到一些不同特征的线性组合,一个方便的向量符号是使用内积(在这种情况下,这也被称为标量或点积)。因此,我们对于分离超平面的表达式变成:
超平面的表达式;(图片由作者提供)
在上面的表达式中, w 是权重向量, x 是特征向量, b 是偏差项(进一步阅读可以理解这些术语的几何意义)。两个向量之间的内积是一种紧凑的表示,它将每个单独的对应分量相乘,然后将所有的乘积相加。例如,如果我们正在处理二维情况,我们可以将超平面表达式表示为:
二维超平面的表达(图片由作者提供)
本例中,w*=(w₀,w* ₁ ),以及x*=(x₀,x* ₁ )。 说白了, w 和 x 都是向量,各有两个分量。
超平面不等式和方程
我们对超平面表达式本身不感兴趣,而是使用它来帮助我们将 n 维空间划分成区域。我们可以通过指定带有不等式的条件来做到这一点。
在我们的具有 n 个特征的两类线性可分分类问题中,让我们假设这两个类被标记为+1 或-1(我们可以假设不同的数字来表示每个类,但是这种选择使得随后的数学变得简单)。我们想从超平面中得到的是保证任何属于一类的点(比如说+1)在超平面的一边(比如说正边),属于另一类的点(比如说当 yn=-1 时)在负边。
数学上,对于正类,超平面不等式变成:
类为+1 时的超平面不等式(图片由作者提供)
对于消极阶层来说,
类为-1 时的超平面不等式(图片由作者提供)
我们可以将上述两个不等式表示为一个不等式:
以上两个超平面不等式的紧凑表示,方程 A(图片由作者提供)
(如果你对你的高中数学有点生疏的话,紧凑表示法相当于上面的两个表达式,因为当我们将一个不等式乘以一个负数时,不等式的符号会改变)
简单地说,上述不等式说明了属于这两类的点位于超平面的相对两侧的条件。
满足上述约束的特定超平面将是超平面方程。
超平面方程(作者图片)
超平面的几何视图
任何超平面都可以用一个权重向量、 w、 和一个偏差项、 *b、*来表示,从图形上看,一个超平面在 3D 中看起来就像下图。权重向量 w 垂直于(成 90 度角)平面,偏移项 b 是平面到原点的距离(偏移),并且 x ₘ和 x ₙ是平面上的两个点(平面上的任意两个点!).
3D 中的分离超平面,改编自 Deisenroth,Marc Peter,A. Aldo Faisal 和 Cheng Soon Ong。机器学习的数学 。”(图片由作者提供)
如果你把上面的三维图形投影到一个平面上,这就变得很清楚了。你可以直观地认为投影是从边缘看同一个图形,这样平面看起来就像一条线。从那边看,连接ₘ和ₙ的线将会是一条线。
从侧面看的分离超平面(图片由作者提供)
此时,你可能会奇怪为什么重量向量, w, 垂直于平面。对此的一个简单证明就是,想象超平面上的任意两点,然后算出 w 与平面上两点连接形成的向量的内积为 0。换句话说, w 和在超平面上的任何一个向量的点积将会是 0。当两个向量的内积为零时,那么这两个向量总是正交的。下图以较慢的速度提供了相同的证明。
为什么超平面方程中的 w 与平面正交的证明(图片作者提供)
要记住的底线是这样的:
超平面方程由一个矢量和一个偏差项表示。等式中的向量与超平面正交,偏差项表示从原点的偏移量。
点到超平面的距离
我们现在几乎完成了。记住 SVM 的目的:找到导致最大利润的超平面。边缘只不过是最近的类数据点和超平面之间的距离。这正是我们现在要做的:找出点到超平面的距离。
让我们考虑一个点, xₐ ,属于其中一类。当我们说从一个点到一个平面的距离时,我们指的不是任何距离,而是最短的距离。
想象一下把你的手机放在桌子上方。当我们说手机到桌子的距离时,我们指的是最短的距离, 的直线距离,而不是 的任何其他距离。
正交投影给出了点到平面的最短距离(图片由作者提供)
同样的概念也适用于此。我们感兴趣的是这个点到超平面的最短距离(这也叫点在平面上的正交投影)。在下图中,让我们将此标记为 x'ₐ 。
点(xₐ)和平面之间距离的概念,说明了正交投影的概念,改编自" Deisenroth、Marc Peter、A. Aldo Faisal 和 Cheng Soon Ong。机器学习的数学 (图片由作者提供)
x'ₐ 和 xₐ 之间的矢量可以看作是由 r(边距)缩放的单位正交矢量(从 w 导出)。使用简单的向量加法和减法,我们得到:
等式 1(图片由作者提供)
在哪里
作者图片
是单位缩放矢量。如果你对向量加减法有点生疏,那么可以把等式(1)看作是从原点到达 x'ₐ的两种等价方式。基于等式(1)的左手边,你可以直接沿着矢量 x'ₐ.走基于等式(1)的右手边,你可以沿着 xₐ走,然后沿着-r*(w/| | w | |)。在这两种情况下,你都将从原点出发,最终到达同一点,x'ₐ.*
SVM 方程,最后
我们现在几乎完成了。想想下面显示的场景:
帮助推导利润公式的插图,改编自" Deisenroth、Marc Peter、A. Aldo Faisal 和 Cheng Soon Ong。机器学习的数学 (图片由作者提供)
让我们假设 xₐ是离超平面最近的点,离正类的距离为 1。给定为 x'ₐ的 xₐ的投影位于超平面上,因此:
等式 2(图片由作者提供)
将等式(1)代入等式(2):
等式 3(图片由作者提供)
展开等式(3)中的各项并重新排列,我们得到:
等式 4(图片由作者提供)
使用非常简单的简化方法(如下所示),
方程式 4 的简化(图片由作者提供)
我们得到:
用垂直于超平面的向量表示的边距,等式 B(图片由作者提供)
因此,SVM 要求是最大化余量(等式 B)并确保点位于正确的一侧,如前面的不等式所示(等式 A)。
为了数学上的方便,我们没有最大化等式 B,而是最小化它的倒数(和平方)并添加 1/2 项(这不会改变优化函数,但在计算梯度时只会导致更整洁的解)。因此,目标是:
硬边界 SVM 方程(图片由作者提供)
好了,这些是 SVM 方程,你可以在几本机器学习的书中找到。它包括服从约束的最小化(即找到导致最大余量的 w 的值)。该约束表示在不等式中,该不等式确保来自正类和负类的数据点都在超平面的正确侧。这是一个约束优化问题,可以用语言乘数法来解决!
“任何领域的专家都曾是初学者”海伦·海丝
祝贺你,你向成为数据科学专家又迈进了一步!
*https://ahmarshah.medium.com/membership *
理解支持向量机
原文:https://towardsdatascience.com/understand-support-vector-machines-6cc9e4a15e7e?source=collection_archive---------18-----------------------
系列的第 1 部分,提供全面介绍的简短文章;不假设任何先验知识
SVM 试图找到最大边界(图片由作者提供)
概观
这是 5 篇短文的第 1 部分,全面介绍了支持向量机(SVM)。该系列的目的是帮助你彻底了解 SVM,并能够自信地在你自己的项目中使用它。该序列假设没有机器学习(ML)的先验知识,并且熟悉高中数学足以跟随和理解。
大局
如果你是数据科学的绝对初学者,并且还不理解监督学习和非监督学习之间的区别,那么我建议你阅读我之前的文章,该文章假设完全没有先验知识,并使用一个故事来帮助你理解这些术语。
在数据科学的生态系统中,SVM 是一种非常受欢迎的算法,可以帮助你解决监督学习中的两种类型的机器学习问题:分类和回归。在分类中,我们希望开发一种算法,可以帮助我们预测一个“类”(从一组离散的可能性中做出的特定预测)。分类的一些例子是垃圾邮件与非垃圾邮件,从图像中识别 0-9 位数字中的任何一个,有病与没病(希望你明白)。在回归分析中,我们预测的是一个“连续的”输出(例如,房子的价格,或者从大脑信号预测的力量)。
从概念上讲,回归和分类是相似的。在这两种情况下,我们都有一组数据点或属性(通常称为特征),然后使用它们来预测输出。如果输出是离散的,我们称之为分类。如果输出是连续的,我们称之为回归。
SVM 可以帮助我们解决分类和回归问题。然而,SVM 背后的数学初看起来可能很可怕,但它有非常清晰的几何直觉(希望一旦你看完这个系列文章,SVM 背后的数学就不会看起来那么可怕)。
SVM 是生成性的还是歧视性的?
概括地说,有两种分类方法。我们可以学习每一类数据的统计属性,然后使用该知识来识别特定数据点属于哪一类。这被称为生成方法,因为我们试图学习每个类的底层概率模型(如果我们有每个类的概率模型,那么我们可以使用该模型来“生成”新的数据点,因此得名生成模型)。
或者,我们可以尝试直接学习可以帮助我们确定特定数据点属于哪个类的决策边界。这是解决分类问题的“判别”分析方法。这相当于将数据点的“空间”划分为不同的区域,其中每个区域属于一个特定的类。
等等,我说的“空间”是什么意思?…
空间只是一个帮助我们表示数据点的概念构造。例如,考虑一个由两个元素组成的数据点:心率和呼吸率。我们可以在二维空间上表示这个数据点,其中一维是心率,另一维是呼吸率。
一个二维空间,其中每个数据点由一对值表示(图片由作者提供)
不一定是心率和呼吸频率。它可以是任何东西,取决于手头的问题。例如,考虑一个使用建筑面积和卧室数量的房价预测问题。在这种情况下,两个维度将是地板面积,并且卧室的数量和 2 维空间中的每个数据点将对应于唯一的数据点。此外,我们并不局限于二维空间,同样的概念可以扩展到更多的维度。
需要注意的关键点是:对于一个具有 n 个特征的问题,每个数据点在概念上都可以用一个 n 维空间来表示。
一个判别模型,如 SVM,试图找到一个边界来帮助我们划分这个 n 维空间(其中空间中的每个区域将属于一个特定的类别)。数学上,这个决策边界是一个 n -1 子空间,它被称为超平面(例如,如果我们有一个 2 维空间,那么决策边界的超平面将是 1 维空间,一条线;如果我们有一个三维空间,那么决策边界的超平面将是一个二维平面)。
我们如何确定决策边界?
问题归结为在一个 n 维空间中找到一个决策边界。从概念上讲,我们通过尝试识别不同的可能决策界限,然后选择最合适的一个来实现这一点。从数学上来说,这相当于找到一个“成本”函数的最小值,当预测很差时,该函数具有高值,而当预测很好时,该函数具有低值。(我之前关于 logistic 回归的文章已经更详细的介绍了成本函数的概念)。因此,所有的神奇之处就在于我们如何定义“成本”函数。
这也是 SVM 不同于另一个著名的分类技术,逻辑回归的地方。在逻辑回归中,数学公式是这样的,我们取所有的数据点来寻找能给我们最小成本的决策边界。然而,在 SVM,我们试图找到导致判定边界(超平面)和两个类的最近(到超平面)数据点之间的最大距离(称为余量)的判定边界。(这些最接近的数据点“支撑”着超平面,就像一根柱子支撑着一座建筑)。
SVM 背后的数学概述
如果 SVM 的数学令人不快,这里是 SVM 文字背后的数学鸟瞰图(我们将在本系列的后续文章中推导相关方程)。如前所述,将 SVM 与其他算法(如逻辑回归)区分开来的真正魔力在于“成本”函数。对于逻辑回归,我们定义一个“凸”的成本函数(这意味着它有一个 U 形和一个单一的最小点;这样的问题很好解决)。对于 SVM,我们有两个要求:
(I):我们希望最大化利润(优化)
(ii):我们希望确保这些点位于决策边界的正确一侧(一个约束)
因此,SVM 问题是一个“约束”优化问题,我们希望最大限度地提高利润(I),但也确保满足约束(ii)。语言乘数法为我们提供了一种解决约束优化问题的方法(通过将其转化为无约束问题,然后我们可以用微积分来解决;我们将在本系列的后续文章中推导相关方程)。
支持向量机可以公式化为一个约束优化问题,目标是最大限度地增加利润,同时确保点位于超平面的正确一侧(图片由作者提供)
总之,SVM 是一个最大边际分类器。本文提供了一个简单的介绍,并使用一个简单的线性可分案例来说明基本概念。本系列的后续文章将向您展示 SVM 背后的数学是如何从几何直觉中推导出来的,并涵盖数据点不是线性可分的情况。敬请期待!
如果你喜欢读这篇文章,那么你可以考虑阅读下一篇文章,在这篇文章中,SVM 方程是用几何直觉推导出来的。
https://ahmarshah.medium.com/membership
通过克罗内克乘积和线性方程理解李亚普诺夫方程
原文:https://towardsdatascience.com/understand-the-lyapunov-equation-through-kronecker-product-and-linear-equation-bfff9c1e59ab?source=collection_archive---------14-----------------------
李雅普诺夫方程是一类矩阵方程,它在控制理论的许多分支中非常著名,如稳定性分析和最优控制。李亚普诺夫方程的术语来源于俄罗斯数学家亚历山大·李亚普诺夫的名字。他因发展和成就了动力系统的稳定性理论,以及对数学物理和概率论的许多贡献而闻名于世[1]。
亚历山大·李亚普诺夫(1857-1918)。俄罗斯数学家、机械学家和物理学家。
在这篇文章中,我们计划重温李亚普诺夫方程。具体来说,我们将
- 从线性代数角度引入李雅普诺夫方程,
- 利用 Kronecker 积和矩阵向量化建立李雅普诺夫方程和最简单线性方程之间的联系。
矩阵计算中的 Kronecker 积
Kronecker 积是矩阵计算中一个著名的运算[2]。虽然 Kronecker 积的概念在线性代数中并不广为人知,但该运算常用于矩阵计算。克罗内克积的基本思想很容易理解。例如,如果我们有两个矩阵 A 和 B ,它们的大小分别为 2 乘 2 和 2 乘 3,就像这两个矩阵:
然后根据克罗内克积的定义,我们可以计算克罗内克积如下:
在这个操作中,遵循克罗内克积的思想并不困难。我们可以用矩阵 A 中的每个元素乘以矩阵 B 。以这种方式,得到的矩阵的数据大小是 4 乘 6。
在 Python 中,我们可以使用 Numpy 来计算两个矩阵之间的 Kronecker 积,让我们来试试:
import numpy as npA = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6, 7], [8, 9, 10]])
print(np.kron(A, B))
输出将是:
[[ 5 6 7 10 12 14]
[ 8 9 10 16 18 20]
[15 18 21 20 24 28]
[24 27 30 32 36 40]]
结果和上面的例子完全一样。
重温李亚普诺夫方程
如上所述,李雅普诺夫方程是一种特定类型的矩阵方程。形式上,我们可以把它写成
其中 A 和 W 都是已知矩阵,它们是 n -by- n 。 n -by- n 矩阵 X 未知。这里的问题是,如果W都已知,如何获得 X 的解。
一种简单的方法是使用克罗内克乘积和矩阵向量化。矩阵向量化用于将给定的矩阵转换成向量。让我们看一个关于矩阵矢量化的简单示例:
这是一个列向量化。
事实上,有一个方程可以建立矩阵方程和向量形式方程之间的联系:
这里,方程包括克罗内克乘积和矩阵向量化。
因此,我们可以将李亚普诺夫方程改写为
和
其中 I 表示单位矩阵。
我们知道,这确实是一个线性方程问题,其解由下式给出
李亚普诺夫方程的一个玩具例子
我们可以用 Kronecker 积和矩阵向量化写出李雅普诺夫方程问题的封闭解。在某些情况下,如果我们想把某个方程理解清楚,可以试着解一些简单的例子。这里,第一个冲动是考虑一个简单的例子来说明:
在这个例子中,根据克罗内克积的定义(请自行尝试:),我们有
根据矩阵向量化的原理,我们有
因此, X 的解为
以矩阵的形式,它是
如果想用 Python 重现,可以阅读并尝试以下代码:
*import numpy as np
A = np.array([[-4, -1, -1, 0], [1, -2, 0, -1],
[1, 0, -2, -1], [0, 1, 1, 0]])
b = np.array([-1, 0, 0, -1])
x = np.linalg.inv(A) @ b*
请自己尝试一下,这样你会更熟悉李亚普诺夫方程。
简短的讨论
李亚普诺夫是许多科学和工程领域中重要的矩阵方程之一。还有一些其他类型的矩阵方程,如西尔维斯特方程。使用李雅普诺夫方程的上述解不能产生有效的计算,因为克罗内克乘积和矩阵向量化会产生大的矩阵。上述解决方案的复杂性是 O(n⁶).在实践中,我们可以使用 Bartels-Stewart 算法来求解李雅普诺夫方程,因为该算法的复杂度为 O(n)。
这篇博文将是从克罗内克乘积和线性方程的角度理解李雅普诺夫方程的一个良好开端。如果您有任何问题,请随时给我反馈。感谢您的阅读!
参考
[1]维基百科上的亚历山大·李亚普诺夫:https://en.wikipedia.org/wiki/Aleksandr_Lyapunov
[2]维基百科上的克罗内克积:https://en.wikipedia.org/wiki/Kronecker_product
只需点击几下鼠标,就能了解是什么推动了您的客户行为
原文:https://towardsdatascience.com/understand-what-drives-your-customer-behavior-in-clicks-9929f9d1b8e7?source=collection_archive---------40-----------------------
使用 PowerBI 进行关键驱动因素分析
弗兰基·查马基在 Unsplash 上拍摄的照片
如果您是产品经理或营销专业人士,想要了解是什么驱动了特定的客户行为,您只需点击几下鼠标就能找到答案。
是什么驱使你的客户流失?是什么导致了令人惊叹的体验?是什么让他们购买你的产品?简而言之,理解驱动您感兴趣的指标的因素。Power BI 很好地利用了机器学习和人工智能的能力来分析你的数据,对重要的因素进行排序,并将它们显示为关键影响因素。它还根据各种因素的组合对客户进行智能细分。
好的一面是——你不需要有数据科学方面的专业知识。你所需要做的就是上传或连接你的原始数据,然后点击几下。让我们以 ka ggle-https://www.kaggle.com/blastchar/telco-customer-churn上的电信客户流失数据集为例。目标变量是流失率,即上个月内离开的客户。数据集包括以下信息:
- 上个月内离开的客户—这一列称为流失
- 每位客户已注册的服务—电话、多条线路、互联网、在线安全、在线备份、设备保护、技术支持以及流媒体电视和电影
- 客户账户信息——他们成为客户的时间、合同、支付方式、无纸化账单、每月费用和总费用
- 客户的人口统计信息—性别、年龄范围,以及他们是否有伴侣和家属
让我们试着了解是什么因素导致了客户流失。
步骤 1:在 PowerBI 中加载数据
文件->获取数据->文本/CSV
有 7043 行和 19 列具有客户属性,我们将使用它们作为输入因子,最后一列“客户流失”作为输出变量。
第二步:拖动&放下
点击插入部分下的关键影响者。将目标变量(此处为变动)拖到“分析”下,将您想要保留的所有因素拖到“解释者”下。在下图中,我将所有 19 个变量作为因子进行了拖动。
步骤 3:读取结果
3.1 了解关键影响者
您会发现,当您在列表中添加或删除变量时,结果会自动更新。让我们来看看关键的影响者。正如我们在图中看到的,逐月合同是导致客户流失的首要因素。准确地说,与其他合同类型(一年期、两年期)相比,逐月合同的客户 6.32 更有可能流失。
第二个最重要的因素是在线安全性,其次是技术支持,其中 3.63 和 3.51 分别是流失率的提升。
到目前为止,您已经看到了不同的分类变量。“合同”是一个分类变量,有三个标签:逐月、一年和两年。Power BI 在右窗格中显示了所选变量的更多详细信息,您可以在这里看到每个标签对客户流失可能性的比较效果。虚线表示平均值。除所选关键因素之外的所有值的变动百分比(合同是逐月的)。
让我们看看变量连续时的细节——例如总费用。第四个最重要的因素是“总费用为 68.45–96.45”。请注意,PowerBI 已经自动将装入连续变量。右窗格中的分布显示总费用和流失之间的关系不是线性的。我发现这个最佳宁滨非常有用。作为保留经理,您可以特别关注总费用为 68.45-96.45 英镑的客户群。
到目前为止,我们探索了“关键影响因素”选项卡,以单独评估每个因素并对其进行排名。但实际上,影响指标的是个因素的组合。让我们来探索 PowerBI 的这一强大功能,它通过对关键影响者进行分组来进行细分。
3.2 提取用户细分
单击 Top segments 选项卡,查看各种因素的组合如何影响客户流失。根据满足条件的记录的百分比对这些段进行分级。每个区段气泡的大小表示区段中有多少记录(人口计数)。
在我们的例子中,发现了 5 个段。这些细分市场按照细分市场中“流失”的百分比进行排名。例如,细分市场 1 中有 75.9%的客户都曾抱怨过。泡沫越高,低收视率比例越高。选择一个气泡会显示该段的详细信息。让我们理解第一部分。
正如我们所看到的,第 1 部分用户是“按月”订购的用户,拥有光纤,并且是新用户(租期不超过 4 个月)。在这一细分市场中,75.9%的客户发生了流失,比平均水平高出 49 个百分点。段 1 也包含大约 7.2%的数据,因此它代表了人口中可寻址的部分。
您可以点击“了解有关该细分市场的更多信息”,进一步深入了解该细分市场,并查看影响该细分市场的其他因素。同样,我们可以理解创建的其他 4 个细分市场。
思绪
我发现这个 PowerBI 工具非常方便快捷。它是完全交互式的,这意味着您可以使用滤镜、切片器和其他视觉效果上的选择来影响结果。毫无疑问,让产品和营销策略师能够在没有技术诀窍的情况下利用 ML/AI 。在我的组织中,我用 A/B 测试实验数据制作了一个自动化的 PowerBI 仪表板。关键驱动因素分析是其中的重要部分。它有助于产品和营销经理理解是什么驱动他们的实验成功或失败,也有助于优化未来的实验。
不用说——作为一名数据科学家,我仍然喜欢用不同的方法处理原始数据——决策树、分类算法等等。关键驱动因素分析不仅仅是一种技术。如果你有兴趣知道 PowerBI 是如何做到这一点的,这里是我找到的链接-
https://dotnet.microsoft.com/apps/machinelearning-ai/ml-dotnet/customers/power-bi
- 保持连接在LinkedIn和 中
使用 Grad-CAM 了解您的算法
原文:https://towardsdatascience.com/understand-your-algorithm-with-grad-cam-d3b62fce353?source=collection_archive---------0-----------------------
当它是一个黑匣子时,我们为什么要足够信任 AI 来驾驶汽车,检测疾病,识别嫌疑人?
Grad-CAM 解读猫狗(图片由作者提供)
介绍
人工智能仅仅是一个黑匣子,我们开始信任它足以驾驶汽车,检测疾病,识别嫌疑人,只是因为大肆宣传吗?
你可能听说过网飞的纪录片, 编码偏差 (这里可以看电影)。这部电影批评了深度学习算法固有的偏见;特别是他们没有发现深色皮肤和女性的脸。这部电影表明解决问题的办法在政府。“推动美国有史以来第一部针对影响我们所有人的算法偏见的立法。”是深度学习算法本身存在固有的偏见,还是训练数据中的偏见问题?虽然对人工智能监管的需求存在,但解决方案的很大一部分取决于机器学习工程师。我们需要让我们的深度学习算法更具可解释性,找到弱点和偏见的领域,并改进我们的算法。
如何才能理解我们的卷积神经网络(黑盒)在做决策时看到和理解的东西?
这篇博客文章完全是关于制作视觉解释热图,这将帮助我们理解深度学习算法如何做出决策。在专注于建筑安全和安保的建筑技术初创公司 Forsight ,我们的计算机视觉团队使用视觉解释来改进我们的数据集和模型。点击阅读更多关于我们工作的信息。现在,我们要探讨的是视觉解释算法: Grad-CAM 。
在本文中,我们将向您展示如何使用 Grad-CAM 解读一组猫狗图像。您可以轻松地扩展这个示例,并使用它来调试您自己的模型。我们将向您展示如何通过查看模型中早期图层的 Grad-CAM 热图来提高现有文献的准确性和精确度。最后,我们将研究模型的错误,看看 Grad-CAM 如何帮助我们改进模型。让我们跳进来。
补充Google Colab笔记本会帮你重现这里制作的热图。请随意复制代码并将其用于您自己的项目!
数据集和模型
在将 Grad-CAM 解释应用于复杂的数据集和任务之前,让我们用一个经典的图像分类问题来简化它。我们将使用来自 kaggle 的高质量数据集对猫&狗进行分类。这里我们有一个包含 37,500 张图像的大型数据集(25,000 次训练& 12,500 次测试)。数据包含两类:猫&狗。这些数据包含了各种背景下的猫和狗,不同的亮度水平,以及参与不同的活动,这将考验我们的视觉解释!
在 Google Colab 笔记本上,你将加载一个预先训练好的模型,它已经可以对猫&狗进行分类。对于那些对模型架构感兴趣的人来说:它由标准化的重新缩放层组成,随后是先前在 COCO 数据集上训练的 MobileNetV2 层。在基本模型之后,我们包括了一个全局平均池层、一个 10%漏失的漏失层和一个密集预测层。在下图中,您可以看到培训后的所有评估集指标。提醒误报表明猫被错误地归类为狗。同样,假阴性表示狗被错误地归类为猫。一个经过训练的模型已经准备好了,我们可以开始研究这个问题:它是如何做出决策的?
模型指标(作者图片)
摄像机
Grad-CAM 由 Ramprasaath R. Selvaraju 等人对 arxiv.org 进行概述
警告,Grad-CAM 可能很难把你的头缠在上。
梯度加权类激活映射(Grad-CAM)使用流入最终卷积层的任何目标概念(比如分类网络中的“狗”或字幕网络中的单词序列)的梯度来产生粗略的定位图,该定位图突出显示图像中的重要区域以预测概念。
该技术在通用性和准确性方面比以前的方法有所改进。这很复杂,但幸运的是,输出很直观。从高层次来看,我们将一幅图像作为输入,并创建一个模型,该模型在我们想要创建 Grad-CAM 热图的层被切断。我们附加完全连接的层用于预测。然后,我们通过模型运行输入,获取图层输出和损失。接下来,我们找到我们期望的模型层的输出相对于模型损耗的梯度。从那里,我们采取有助于预测的梯度部分,减少,调整大小,并重新缩放,以便热图可以与原始图像重叠。你可以遵循下面代码中的具体步骤,并在这里查看概述完整数学的学术论文。
gradModel = Model(inputs=[model.inputs],outputs=[model.get_layer(layer_name).output,model.output])with tf.GradientTape() as tape: # cast the image tensor to a float-32 data type, pass the # forward propagate the image through the gradient model, and grab the loss # associated with the specific class index inputs = tf.cast(img_array, tf.float32) (convOutputs, predictions) = gradModel(inputs) loss = predictions[:, 0]# use automatic differentiation to compute the gradientsgrads = tape.gradient(loss, convOutputs)# compute the guided gradientscastConvOutputs = tf.cast(convOutputs > 0, "float32")castGrads = tf.cast(grads > 0, "float32")guidedGrads = castConvOutputs * castGrads * grads# the convolution and guided gradients have a batch dimension# (which we don't need) so let's grab the volume itself and# discard the batchconvOutputs = convOutputs[0]guidedGrads = guidedGrads[0]# compute the average of the gradient values, and using them# as weights, compute the ponderation of the filters with# respect to the weightsweights = tf.reduce_mean(guidedGrads, axis=(0, 1))cam = tf.reduce_sum(tf.multiply(weights, convOutputs), axis=-1)# grab the spatial dimensions of the input image and resize# the output class activation map to match the input image# dimensions(w, h) = (img_array.shape[2], img_array.shape[1])heatmap = cv2.resize(cam.numpy(), (w, h))# normalize the heatmap such that all values lie in the range# [0, 1], scale the resulting values to the range [0, 255],# and then convert to an unsigned 8-bit integernumer = heatmap - np.min(heatmap)denom = (heatmap.max() - heatmap.min()) + epsheatmap = numer / denom
配备了 Grad-CAM 生成代码,我们带着预先训练好的模型和验证集去看看我们的模型对猫&狗了解多少。
我们开始为模型中的最后一个卷积层 conv 1 创建 Grad-CAM 热图。理论上,该层的热图应该显示被模型分类的对象的最准确的视觉解释。
grad-CAM conv 1 层热图(图片由作者提供)
在梯度数学中,我们捕捉所有通向最后一个卷积层的连续特征图的重要性。我们注意到,虽然热图强调了分类对象,在本例中是一只猫,但它并不十分精确。被强调的区域(红色)包围了猫的区域,但是不太精确地适合猫。该区域包括人的衬衫、人的手和背景的部分。我们知道模型看到了一只猫,但是我们不太确定是这只猫的什么让模型相信这确实是一只猫。我们怎样才能使 Grad-CAM 热图更精确?
你会注意到上面的代码已经被包装在 Google Colab 笔记本的一个函数中,以允许 Grad-CAM 在不同的模型层中重现。让我们使用这个函数来探索早期的模型层。
所有模型层的 Grad-CAM 热图的 GIF(GIF 由作者提供)
这里有很多东西需要消化。当我们研究热图时,模型学习的逻辑开始出现。前 10 层(块 1 到块 3)检测图像中的轮廓和边界。深度方向层不强调对象,而投影和扩展层不强调轮廓。接下来的大约 20 层(块 4 到 11)是检测图像中的概念。Block 4 expand relu 就是一个很好的例子。
block_4_expand_relu 图层的 Grad-CAM 热图(图片由作者提供)
在模型架构的这一点上,定义猫的特征的形状开始从图像中的一般轮廓中脱颖而出。你可以看到猫的胡须、耳朵和眼睛是如何用红色和黄色的阴影强调的,而图像的其余部分是蓝色和绿色的。当我们深入模型的各层时,你可以看到模型是如何推理猫的定义特征如何区分这张图像的。最后的~16 层(块 12 到 16)尝试使用来自最早层的空间信息和最近开发的概念来识别图像中的对象。模型中的最后一层,Conv_1,确实正确地识别了物体的大致区域,但是它没有拾取存在于早期 Grad-CAM 热图中的物体的细微差别。我们用人类的直觉代替 Grad-CAM 的数学,它改进了 Grad-CAM 的结果。
为了合并早期的图层,我们将来自所有模型图层的 Grad-CAM 热图平均在一起。你可以在下面看到结果。
Grad-CAM 热图改进(图片由作者提供)
Grad-CAM 热图现在强调猫的脸、眼睛和爪子,不强调人的手臂。总的来说,我们有一个更精确的重点区域来定位猫。我们知道,该模型根据其内在特征将该图像分类为猫,而不是图像中的一般区域。
模型给人印象特别深刻,因为这是一个很难的图像!这个人穿着一件黑白相间的衬衫,和猫的颜色一样。然而,该模型可以区分黑猫脸和黑色人类衬衫。通过全层 Grad-CAM,我们了解了模型的优势。我们如何使用 Grad-CAM 来了解我们模型的弱点?
让我们仔细看看下面 7 张被错误归类为狗的猫的图片。
模型误报(图片由作者提供)
我们可以使用 Grad-CAM 热图来为我们提供线索,了解为什么模型在进行正确分类时遇到了困难。当一只猫坐在笼子后面时,这个模型似乎在区分它时遇到了一些困难。我们可以从 Grad-CAM 中看到,模型强调笼子的栅栏,很难找到猫的特征。在 5 和 6 中,猫尾巴是图像中的显著特征。但是从 Grad-CAM 中,我们可以看到模型很难识别这个特征,因为它带有绿色和蓝色的阴影。Grad-CAM 热图所能提供的最明显的例子在# 1 中。模特被猫玩的玩具弄糊涂了。从热图中我们可以看到,模型认为玩具是猫的一部分。这种混乱造成了模型的错误分类。使用这些知识,我们可以找到更多的猫玩玩具的例子,并将其包含在我们的数据集中,这将有助于我们的模型学习和改进。
改进模型
注意到我们的模型在笼子方面有问题,我们从 google images 中拿出了一些更具体的例子;特别是运输板条箱。
这个模型在运输工具上有问题(图片由作者提供)
从 grad-CAM 热图上的红色区域可以看出,模型关注的是猫周围的运输箱,而不是猫本身,这导致了错误的分类。当猫在运输板条箱中时,我们如何帮助模型区分它们?
我们从谷歌图片中创建了一个补充数据集,包括运输板条箱中的猫和狗。使用相册 *,*我们用额外的图像增强来增强数据集。有了我们需要的数据,我们开始实验。我们用原始数据集创建了一系列模型,并添加了 25%、50%、75%和 100%的补充运输板条箱数据集。在我们实验的每一次迭代中,我们都回到 Grad-CAM,看看模型是否在原始图像上调整了它的重点区域。
为了查看模型真正锁定的位置,我们创建了一个遮罩,使用阈值来捕捉 Grad-CAM 中最强烈的(红色)区域。然后,我们使用蒙版分割出原始图像中最重要的像素。
随着我们从扩充的集合中添加数据,模型得到了改进
正如您从上面的过滤图像中看到的,随着我们从补充数据集向训练数据集添加更多图像,模型的焦点从板条箱转移到猫的面部和特征。而且不需要很长时间,模型就开始得到正确的分类!当模型在原始数据集加上仅 25%的补充运输器板条箱数据集上训练时,模型指定上面的图像是猫的概率为 90%。
使用同样的实验,我们观察了笼子里的猫的其他图像,看看我们是否可以在模型焦点中找到相同的进展。下面是一些突出的例子。
作者 GIF
作者 GIF
结论
在这篇博客文章中,我们希望使用 Grad-CAM 为卷积神经网络可视化解释提供一些有用的见解和工具。在猫和狗的帮助下,我们探索了一个模型如何区分类别。通过考虑模型所有层的热图,我们改进了最终卷积层的 Grad-CAM 结果。我们用 Grad-CAM 瞄准了模型中的偏差和弱点。最重要的是,我们使用 Grad-CAM 来改进我们的算法。机器学习是一个迭代过程,我们的模型永远不够好。我们希望这里介绍的技术将有助于在整个改进过程中提供更多的透明度,并在模型中建立更多的信任。在 Forsight,我们使用 Grad-CAM 热图来识别模型中的错误重点区域。
为了帮助 ML/AI 爱好者,以及任何有兴趣帮助解决这个问题的人,我们创建并分享了一个 Google Colab 笔记本,它让你能够摆弄和制作我们在这篇博客中展示的 Grad-CAM 热图。
如果你对这个话题感兴趣,并且你愿意致力于深度学习算法的解释,请 联系我们 。
参考
- Ramprasaath R. Selvaraju 等人,2019 年,“Grad-CAM:通过基于梯度的定位从深度网络进行视觉解释”,https://arxiv.org/pdf/1610.02391.pdf
- 狗对猫,https://www.kaggle.com/c/dogs-vs-cats/data
- 马克·桑德勒等人,2019,“MobileNetV2:反向残差和线性瓶颈”,https://arxiv.org/abs/1801.04381
- 编码偏差,2020,https://www.codedbias.com/
了解 CSV 文件从您的终端与 XSV
原文:https://towardsdatascience.com/understand-your-csv-files-from-your-terminal-with-xsv-65255ae67293?source=collection_archive---------18-----------------------
用一行代码通过你的终端快速理解你的 CSV 文件
由作者创建
动机
你是否曾经试图通过盯着 CSV 文件来对其有一个大致的了解,但最终却没有理解你的文件?您可以打开一个 Jupyter 笔记本来分析您的 CSV 文件,但是仅仅为了理解一个 CSV 文件而打开笔记本是非常耗时的,尤其是当您主要使用 Python 脚本和终端时。
有没有一种方法可以让你在终端上用一行代码快速分析你的 CSV 文件?
$ xsv stats bestsellers.csv | xsv table
这就是 xsv 派上用场的时候了。
xsv 是什么?
xsv 是一个命令行程序,用于索引、切片、分析、分割和连接 CSV 文件。我喜欢 xsv,因为它使处理 CSV 文件变得非常快捷和容易。
在这里找到安装 xsv 的说明。在本教程中,我将以 Kaggle 的亚马逊 2009-2019 年 50 大畅销书为例,向您展示如何操作和分析您的数据。
下载并解压缩 CSV 文件。将文件名改为bestsellers.csv
,这样我们更容易操作。
现在,我们的任务是尝试理解我们的 CSV 文件
键入xsv -h
获取命令。您应该会看到类似这样的内容
Commands:
cat Concatenate by row or column
count Count records
fixlengths Makes all records have same length
flatten Show one field per line
fmt Format CSV output (change field delimiter)
frequency Show frequency tables
headers Show header names
help Show this usage message.
index Create CSV index for faster access
input Read CSV data with special quoting rules
join Join CSV files
sample Randomly sample CSV data
search Search CSV data with regexes
select Select columns from CSV
slice Slice records from CSV
sort Sort CSV data
split Split CSV data into many files
stats Compute basic statistics
table Align CSV data into columns
快速浏览一下你的数据
要获得 10 条数据记录的随机样本,请使用
$ xsv sample 10 bestsellers.csv
输出:
输出难以阅读。让我们通过添加xsv table
来美化输出
$ xsv sample 10 bestsellers.csv | xsv table
现在输出看起来更容易阅读了!
我们可能只是想看看书名、作者、用户评分和价格来决定我们应该买哪本书。要选择特定的列,使用xsv select col1,col2
$ xsv sample 10 bestsellers.csv | xsv select Name,Author,'User Rating',Price | xsv table
如果您喜欢每行查看一个字段,请使用xsv flatten
而不是xsv table
$ xsv sample 2 bestsellers.csv | xsv flatten
查看统计数据
我们总共有多少记录?让我们用xsv count
算出来
$ xsv count bestsellers.csv
550
我们总共有 550 行数据。我们还想获得数据的统计(例如,平均用户评级是多少)。我们怎么才能找到呢?
我们可以使用xsv stats
来查看统计数据,比如总和、最小值、最大值、平均值和标准偏差
$ xsv stats bestsellers.csv | xsv table
酷!我们在 0.010 秒内创建了一个汇总表!但是,如果我们只关心用户评级的统计数据呢?我们可以使用xsv search
选择相关的行
$ xsv stats bestsellers.csv | xsv search "User Rating" | xsv table
如果我们只想提取用户评分的平均值,我们可以使用xsv select
$ xsv stats bestsellers.csv | xsv search "User Rating" | xsv select mean | xsv table
注意xsv search
用于选择行,而xsv select
用于选择列。
查找频率
看起来有些书被提到不止一次。让我们找出每本书的频率。使用--limit number
指定输出数量。
$ xsv frequency bestsellers.csv --limit 20| xsv search Name | xsv table
我们的数据中有 10 个美国心理协会出版手册,第 6 版!怎么会这样
过滤数据
xsv 的美妙之处在于我们可以重用同一个命令来执行不同的功能。我们将使用xsv search -s column string_to_search
在一列中搜索与搜索字符串“美国心理学协会出版手册,第 6 版”匹配的行。
$ xsv search -s Name "Publication Manual of the American Psychological Association, 6th Edition" bestsellers.csv | xsv table
酷!原来美国心理协会出版手册,第 6 版出版于 10 个不同的年份。作者和收视率还是一样的。
获取指定范围内的行
您可能不希望获得数据的随机样本,而是希望获得前 10 行。要获得特定范围内的行,使用xsv slice
。下面是用法
$ xsv slice --help
如果没有指定范围的开始,那么切片从 CSV 数据中的第一个
记录开始。要获取前 10 行,请使用
$ xsv slice -e 10 bestsellers.csv | xsv table
要获取从第 2 行到第 10 行的数据,请使用
$ xsv slice -s 2 -e 10 bestsellers.csv | xsv table
注意-s
代表start
,而-e
代表end
。
排序数据
您还可以基于一列或多列对数据进行排序。要根据列User Rating
对数据进行逆序排序,请使用
$ xsv sort -s 'User Rating' -R bestsellers.csv | xsv slice -e 10 | xsv table
注意-s
代表select
而-R
代表reverse
。
正如标题中所承诺的,我们在一行代码中得到我们想要的东西!
结论
恭喜你!您刚刚学习了如何使用 xsv 操作和分析您的 CSV 文件。如果您不记得上面显示的命令,只需使用xsv --help
或xsv <command> --help
,如xsv search --help
。
即使 xsv 不能取代其他复杂的特性工程方法,如果您只想从终端快速分析您的 CSV 文件,xsv 是一个不错的选择!
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 T2 Twitter 上与我联系。
星这个回购如果你想检查我写的所有文章的代码。在 Medium 上关注我,了解我的最新数据科学文章,例如:
💔-python-tricks-to-read-create-and-run-multiple-files-automatically-5221ebaad2ba>
理解 A*路径算法并使用 Python 实现
原文:https://towardsdatascience.com/understanding-a-path-algorithms-and-implementation-with-python-4d8458d6ccc7?source=collection_archive---------7-----------------------
a算法是最有效的路径查找算法之一,用于查找两点之间的最短路径。它由彼得·哈特、尼尔斯·尼尔森和伯特伦·拉斐尔于 1968 年首次出版。虽然它最初可以被看作是 T2·迪杰斯特拉算法的扩展,但它已经成为今天最常用的寻路算法之一。*
Via Pixabay
A*算法基本上通过计算起始节点和结束节点之间所有其他节点的位置来达到最优结果。此外,由于启发式函数[2],它比 Dijkstra 的算法更快。
f(n) = g(n) + h(n)
f(n):计算出的路径总开销
g(n):第一个节点和当前节点之间的路径成本
h(n):启发式函数
如果我们想使用上面的函数找到图 2 中的最短路径;
图二。样本路线
假设我们试图从点 X 到达点 y,由于点 X 没有被移动到不同的节点,g(n)成本没有发生,其值为 0。这个点的启发值是写在红色节点上的值 5。在这样的问题中,启发值通常是当前节点和期望节点之间的空中距离。从 x 点到 A 点有两个点
在去 A 点的情况下,g(n) = 5(路径代价),因为它移动到了一个新的节点。试探被设置为 h(n) = 1。发现 A 点的 f(n)值为 5+1 = 6。如果我们想用这种方法找到所有点的 f(n)值,
X— A ⇒ g(A) + f(A) = 5 + 1 = 6,
A — Y=> g(Y) + f(Y) = 6+ 0= 6,
X— B ⇒ g(B) + f(B) = 1+ 4= 5,
B — C ⇒ g(C) + f(C) = 3+ 2= 5,
C — Y=> g(Y) + f(Y) = 5 + 0= 5,
如上面简单的例子所示,最短路径是 X-B-C-Y 路线。这条路的成本是 5 个单位,而备选的 X-A-Y 路线的成本是 6 个单位。一旦我们完全理解了如何使用上述等式,就可以更详细地研究图 3 中的例子。
图 3。示例路线 v2
假设我们想从节点 j 到达节点 A。有 2 个点(B 和 F),可以从点 A 到达。计算间接费用,我们得到 f(B) = 8 + 6 = 14,f(F) = 3+6 =9。因为最小成本在 F 点,A算法从这里继续。f 点有 2 条路径,f(G) = 4 +5 = 9,f(H) = 10 + 3 = 13。因为最小成本在 g 点,我们可以从那点开始。然后,沿着 I 和 J 节点,我们得到 f(I) = 7 + 1 = 8,f(J) = 10。由于转到 F 节点后得到的所有值都小于 f(B)节点,所以没有返回到 B 节点。但是在不同的场景下,我们假设在节点 F 和 G 之后 f(I)大于 F(B)(F(I)> 14)。在这种情况下,根据 A算法,该过程在这里被中断,并且路径继续到 B 节点。这里,一旦 f(C) > f(I),路径确定过程再次从 I 节点继续。
用 Python 实现
以下所有代码均可从https://github . com/ademakdogan/Implementation-of-A-Algorithm-Visualization-via-Pyp5js-获得
首先,创建网格结构。这里的一些节点被标记为障碍。然后确定开始和结束节点,并使用 A*算法[3]找到这两点之间的最短路径。该算法的工作逻辑基本上基于两个名为 open_set 和 closed_set 的列表。虽然存在可以在 open_set 中处理的节点,但是存在在 closed_set 中处理的节点路径,因此不应该重复(在一些方法中,障碍也被直接扔进 closed_set 列表中,而在一些方法中,它可以被添加为作为对象产生的每个节点的合格属性之一。).作为各种过程的结果,这些列表被填充和清空,并到达最终结果。
所有阶段的伪代码都可以在维基百科上查看。
图 4。A*算法示例- 链接
开源代码库
图 4 显示了 A算法的 python 实现。Pyp5js 库被用来可视化这项工作。此外,A算法可以根据要具体给出的障碍列表、起始和结束节点的坐标以及网格结构的大小来工作。因此,这个项目也可以用来对抗特定的问题。
python AStar.py -c 25 -r 25 -s 1 -q 3 -e 23 -t 21 -l True
因此,
The way found!!!
23 20
23 19
23 18
23 17
23 16
23 15
23 14
23 13
23 12
23 11
23 10
23 9
23 8
23 7
23 6
23 5
23 4
23 3
22 3
21 3
20 3
19 3
18 3
17 3
16 3
15 3
14 3
13 3
12 3
11 3
10 3
9 3
8 3
7 3
6 3
5 3
4 3
3 3
2 3
1 3
Pyp5js
Pyp5js 是一个在浏览器上可视化 python 代码的框架。它支持通过 Python 的 Transcrypt 使用 p5.js javascript 库。完成必要的安装后,只需使用以下命令运行即可。
$ SKETCHBOOK_DIR**=**'~/my-custom-sketchbook' pyp5js serve
之后,通过 http://localhost:5000/ 访问接口部分进行必要的配置设置。在指定的文件夹(SKETCHBOOK_DIR)中,根据与项目名称同名的 python 文件中的代码执行操作。如果想详细考察这个项目,可以去 https://berinhard.github.io/pyp5js/的[看看。](https://berinhard.github.io/pyp5js/)
因此,A算法是最常用的路径查找算法之一。本文讨论了该算法的工作原理及其 python 编码。所有代码都可以在 github 找到。pyp5js 库用于可视化算法。在接下来的文章中,将讨论不同路径确定算法与 A算法的比较。
Github:https://github.com/ademakdogan
领英:https://www.linkedin.com/in/adem-akdo%C4%9Fan-948334177/
参考
[1]哈特,体育;新泽西州尼尔森;拉斐尔,B. (1968)。“启发式确定最小成本路径的形式基础”。IEEE 系统科学与控制论汇刊。4(2):100–107。
[2]曾,w;丘奇,R. L. (2009 年)。“在真实道路网络上寻找最短路径:A*的情况”。国际地理信息科学杂志。23(4):531–543。
[3]赫特兰德,马格努斯·列(2010), Python 算法:掌握 Python 语言中的基本算法 ,Apress,第 214 页,ISBN9781430232377。
理解准确性、回忆性、精确性、F1 分数和混淆矩阵
原文:https://towardsdatascience.com/understanding-accuracy-recall-precision-f1-scores-and-confusion-matrices-561e0f5e328c?source=collection_archive---------11-----------------------
这篇文章还包括显示你的困惑矩阵的方法
艾米丽·莫特在 Unsplash 上的照片
介绍
准确度、召回率、精确度和 F1 分数是用于评估模型性能的指标。尽管这些术语听起来很复杂,但它们的基本概念非常简单。它们基于简单的公式,很容易计算。
本文将对以下每个术语进行讨论
- 说明
- 为什么相关
- 公式
- 不用 sklearn 计算
- 使用 sklearn 来计算它
在教程的最后,我们将讨论混淆矩阵以及如何呈现它们。我在文章末尾提供了 google colab 的链接。
数据📈
让我们假设我们正在分类一封电子邮件是否是垃圾邮件
我们将有两个数组,第一个数组将存储实际值,而第二个数组将存储预测值。这些预测值是从分类器模型中获得的。模型的类型并不重要,我们感兴趣的是模型做出的预测。
# Actual Value
labels = [1, 0, 0, 1, 1, 1, 0, 1, 1, 1]# Predicted Value
predictions = [0, 1, 1, 1, 1, 0, 1, 0, 1, 0]
0 -电子邮件不是垃圾邮件(负面)
1 -电子邮件是垃圾邮件(阳性)
关键术语🔑
真正积极的➕ ➕
当标签为正时,我们的预测值也为正时,就会出现这种情况。在我们的场景中,当电子邮件是垃圾邮件并且我们的模型也将其分类为垃圾邮件时。
真正的条件
TP = 0
for i in range(0,len(labels)):
if labels[i] == predictions[i] and labels[i] == 1:
TP+=1
print("True Positive: ", TP) # 3
假阳性➖ ➕
当标签为负,但我们的模型预测为正时,就会出现这种情况。在我们的场景中,当电子邮件不是垃圾邮件,但我们的模型将其归类为垃圾邮件时。
假阳性的条件
FP = 0
for i in range(0,len(labels)):
if labels[i] == 0 and predictions[i] == 1:
FP+=1
print("False Positive: ", FP) # 3
真阴性➖ ➖
这类似于真正,唯一的区别是标签和预测值都是负的。在我们的场景中,当电子邮件不是垃圾邮件并且我们的模型也将其分类为非垃圾邮件时。
真阴性的条件
TN = 0
for i in range(0,len(labels)):
if labels[i] == predictions[i] and labels[i] == 0:
TN+=1
print("True Negative: ", TN) # 0
假阴性➕ ➖
当标注为正时,但预测值为负时,会出现这种情况。在某种程度上,与假阳性相反。在我们的场景中,当电子邮件是垃圾邮件,但我们的模型将其分类为非垃圾邮件。
假阴性的条件
FN = 0
for i in range(0,len(labels)):
if labels[i] == 1 and predictions[i] == 0:
FN+=1
print("False Negative: ", FN) # 4
正确的预测💯
这种情况的唯一条件是标签和预测值相同。在我们的例子中,当模型将垃圾邮件分类为垃圾邮件,将非垃圾邮件分类为非垃圾邮件时。
正确预测的条件
正确的预测也可以计算为真阳性和真阴性的总和
计算正确的预测
CP = 0
for i in range(0,len(labels)):
if labels[i] == predictions[i]:
CP+=1
print("Correct Prediction: ", CP) # 3
print(CP == TP + TN) # True
不正确的预测❎
这种情况的条件是标签和预测值必须不相等。在我们的场景中,错误的预测是当我们的模型将垃圾邮件分类为非垃圾邮件,将非垃圾邮件分类为垃圾邮件。
不正确预测的条件
不正确的预测也可以计算为假阳性和假阴性的总和
计算不正确的预测
ICP = 0
for i in range(0,len(labels)):
if labels[i] != predictions[i]:
ICP+=1
print("Incorrect Prediction: ", ICP)# 7
print(ICP == FP + FN) # True
准确(性)🎯
准确度是正确预测与预测总数的比率。这是模型最简单的度量之一。我们必须以模型的高精度为目标。如果一个模型有很高的准确性,我们可以推断该模型在大多数情况下做出了正确的预测。
精确度公式
精确度公式
没有 Sklearn
accuracy = (TP + TN)/(TP + FP + TN + FN)
print(accuracy*100)
使用 Sklearn
from sklearn.metrics import accuracy_score
print(accuracy_score(labels , predictions)*100)
回忆📲
准确性可能会产生误导的情况
高精度有时会产生误导。考虑下面的场景
labels = [0,0,0,0,1,0,0,1,0,0]
predictions = [0 ,0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 ,0]
print(accuracy_score(labels , predictions)*100) # 80
与非垃圾邮件相比,垃圾邮件很少出现。因此,label = 0 的出现次数高于 label = 1 的出现次数。在上面的代码中,我们的标签数组包含 8 封非垃圾邮件和 2 封垃圾邮件。如果我们的模型总是将电子邮件分类为非垃圾邮件,它将达到 80%的准确率。这是非常误导的,因为我们的模型基本上无法检测垃圾邮件。
计算回忆分数
Recall 计算预测阳性与阳性标签总数的比率。
召回公式
召回公式
在上面的例子中,我们的模型将有 0 个召回,因为它有 0 个真阳性。这告诉我们,我们的模型在垃圾邮件上表现不佳,我们需要改进它。
没有 Sklearn
recall = (TP)/(TP+FN)
print(recall*100)
使用 Sklearn
from sklearn.metrics import recall_score
print(recall_score(labels,predictions))
精确🐾
回忆分数可能具有误导性的情况
高召回率也可能是高度误导性的。考虑一下我们的模型被调整为总是返回正值预测的情况。它本质上将所有的电子邮件分类为垃圾邮件
labels = [0,0,0,0,1,0,0,1,0,0]
predictions = [1,1,1,1,1,1,1,1,1,1]
print(accuracy_score(labels , predictions)*100)
print(recall_score(labels , predictions)*100)
尽管上述案例的准确率较低(20%),但召回率较高(100%)。
计算精度
精度是正确的正面预测与正面预测总数的比率
精度公式
精度公式
在上面的例子中,精度会很低(20%),因为模型总共预测了 10 个阳性,其中只有 2 个是正确的。这告诉我们,尽管我们的召回率很高,并且我们的模型在正面案例(即垃圾邮件)上表现很好,但在非垃圾邮件上表现很差。
我们的准确度和精确度相等的原因是因为模型预测的都是阳性。在现实世界中,模型可以正确预测一些负面情况,从而提高准确性。然而,精度将仍然保持不变,因为它仅取决于正确的肯定预测和总的肯定预测
没有 Sklearn
precision = TP/(TP+FP)
print(precision)
使用 Sklearn
from sklearn.metrics import precision_score
print(precision_score(labels,predictions)*100)
F1 分数🚗
F1 分数取决于召回率和精确度,它是这两个值的调和平均值。
F1 分数公式
我们考虑调和平均值而不是算术平均值,因为我们希望较低的召回率或精确度产生较低的 F1 分数。在我们之前的例子中,我们的召回率是 100%,准确率是 20%,算术平均值是 60%,而调和平均值是 33.33%。调和平均值更低,更有意义,因为我们知道模型很糟糕。
AM = (1 + 0.2)/2
HM = 2*(1*0.2)/(1+0.2)
print(AM)# 0.6
print(HM)# 0.333
没有 Sklearn
f1 = 2*(precision * recall)/(precision + recall)
print(f1)
使用 Sklearn
from sklearn.metrics import f1_score
print(f1_score(labels, predictions))
混淆矩阵❓
https://towards data science . com/understanding-mission-matrix-a9ad 42 dcfd 62
混淆矩阵是表示真阳性、假阳性、真阴性和假阴性数量的矩阵
假设我们正在处理以下数据
# Actual Value
labels = [1, 0, 0, 1, 1, 1, 0, 1, 1, 1]# Predicted Value
predictions = [0, 0, 1, 1, 1, 0, 1, 0, 1, 0]
混淆矩阵示例
使用 sklearn 计算混淆矩阵
from sklearn.metrics import confusion_matrix
confusion = confusion_matrix(labels, predictions)
FN = confusion[1][0]
TN = confusion[0][0]
TP = confusion[1][1]
FP = confusion[0][1]
你也可以传递一个参数 normalize 来归一化计算出来的数据。
将混淆矩阵显示为条形图
plt.bar(['False Negative' , 'True Negative' , 'True Positive' , 'False Positive'],[FN,TN,TP,FP])
plt.show()
条形图形式的混淆矩阵
将混淆矩阵显示为热图
import seaborn as sns
sns.heatmap(confusion , annot=True , xticklabels=['Negative' , 'Positive'] , yticklabels=['Negative' , 'Positive'])
plt.ylabel("Label")
plt.xlabel("Predicted")
plt.show()
混乱矩阵作为热图
使用熊猫显示混淆矩阵
import pandas as pd
data = {'Labels' : labels, 'Predictions': predictions}
df = pd.DataFrame(data, columns=['Labels','Predictions'])
confusion_matrix = pd.crosstab(df['Labels'], df['Predictions'], rownames=['Labels'], colnames=['Predictions'])
print (confusion_matrix)
使用熊猫的混淆矩阵
使用 Sklearn 生成分类报告👔
from sklearn.metrics import classification_report
print(classification_report(labels,predictions))
下面是输出
代码输出
结论
准确性本身并不能决定一个模型是好是坏,但是准确性与精确度、召回率和 F1 分数的结合可以给出一个关于模型性能的好主意。
链接到 Google Colab
https://colab.research.google.com/drive/1QNKn117M7erJZvJ2BruubTxPKtmrvNM1?authuser=1#scrollTo=ehuf7RJm-PWv
我最近用 WordPress 创建了一个博客,如果你能看看的话,我会很高兴的😃
查看我的关于偏差、方差以及它们如何与欠拟合、过拟合相关的教程
在 LinkedIn 上与我联系
https://www.linkedin.com/in/rahulbanerjee2699/
原载于 2021 年 1 月 2 日 https://realpythonproject.comhttps://realpythonproject.com/understanding-accuracy-recall-precision-f1-scores-and-confusion-matrices/。
理解 AdaSum:用于扩展分布式训练的自适应求和方法
原文:https://towardsdatascience.com/understanding-adasum-adaptive-summation-method-for-scaling-distributed-training-eb1440c5a165?source=collection_archive---------30-----------------------
深度神经网络的数据并行分布式训练将训练数据集划分为 N 个子集,其中 N 个计算节点中的每一个训练数据的子集。通过设置小批量等于单节点训练中的小批量,我们实质上将有效批量增加了 N 倍,从而提高了训练吞吐量。
然而,增加有效批量将对【1】中讨论的训练准确性产生负面影响。[1]中提出的解决方案是将学习速率与总批量成比例。然而,它仍然会达到一个上限,在该上限处,即使学习率缩放,训练也不能收敛。
论文【2】标题为自适应求和缩放分布式训练对造成单节点训练和分布式训练精度差异的一个关键因素给出了非常直观的解释。然后,提出了一种基于下降方向对梯度求和的增强算法,并表明它可以帮助减少 30%的收敛时间。
动机示例
图一。两个数据批次上的 SGD。
图二。分布式训练中两个数据批次的 SGD。
图一。显示了对单个节点上的两批数据顺序执行梯度下降的示例。从 w0 开始,在第一步执行梯度下降后,损耗移动到w1;并在第二步后从 w1 移动到 w2 。图二。显示了使用相同的批处理大小,但同时在两个训练节点上执行梯度下降的示例。在这种情况下,两个训练节点上的梯度下降都开始于 w0 。一步之后,一个节点中的损耗在 w1 处结束,另一个节点中的损耗在 w3 处结束。在分布式训练中,来自两个节点的梯度的算术平均值被应用于原始权重 w0 ,并且得到的权重*w2’被用于更新两个节点上的权重。在大多数情况下,这个更新的权重w2’*将不同于 w2 ,作者在【2】中认为这是单节点训练和分布式训练之间准确性差异的来源。
论文接着研究了 w2 和*w2’差异最大的情况。他们在图 3 中观察到。以下说明当 w1 和 w3 为两个正交向量时,可以忽略 w2 和w2’之差;但当它们沿同一方向时, w2 和w2’*之间的差异非常显著。
图 3。梯度向量求和的不同情况。
基于这一观察,该论文建议我们应该考虑梯度向量之间的相关性,而不是使用简单的 allreduce 运算来聚合梯度。作者提出了一种称为 AdaSum 的方法,当梯度向量正交时相加,当梯度向量方向平行时执行算术平均。关于这个算法的更多细节,请参考原始论文[2]。
结果
作者在[2]中表明,使用 AdaSum 运算,BERT 大训练比常规 Allreduce 收敛速度快 30%。与 *NCCL 缩减法、*相比,该操作符大约有 10~15%的延迟开销,但这通常只是总步进时间中微不足道的一部分。 AdaSum 操作符在 Horovod 分布式培训库中实现并准备使用。
[1] Priya Goyal 等人,精确、大型迷你批量 SGD:1 小时训练 ImageNet(2017),CVPR 2017。
[2] Saeed Maleki 等人,自适应求和的缩放分布式训练 (2021),MLSys 2021。
理解阿尔法、贝塔和统计能力
原文:https://towardsdatascience.com/understanding-alpha-beta-and-statistical-power-525b84453687?source=collection_archive---------1-----------------------
如何在假设检验中最小化错误和最大化结果
托马斯·凯利在 Unsplash 上的照片
介绍
对于任何有抱负的数据科学家来说,知道如何设置和进行假设检验是一项关键技能。起初,试图理解 alpha、beta、power 和 I 型或 II 型错误可能会感到困惑。我在这篇文章中的目标是帮助你建立直觉,并提供一些视觉参考。
首先,让我们设想建立一个标准的 A/B 实验,其中 A 组是控制组,B 组是实验组。我们的零假设是两组是相等的,应用于 B 组的变化没有显著影响(A = B)。我们的另一个假设是,这两个组是不一样的,应用于 B 组的改变实际上引起了显著的差异(A ≠ B)。我们可以将采样分布形象化为如下形式:
作者创造的形象
置信水平和 Alpha
置信水平 (CL)是指在我们拒绝零假设之前,我们希望有多确定(在我们说实验有重大影响并实施 B 组的改变之前,我们希望有多确定)。这是事先挑选的,以概率百分比表示。为了拒绝空值,我们要有 95%的把握吗?也许我们需要 99%的把握。置信水平将取决于你的测试,以及如果你错了,后果会有多严重。通常,标准的起始置信水平值为 95% (.95)。
α值表示为 1-CL。如果置信水平是 0.95,那么 alpha 值将是 0.05 或 5%。这表示当零假设实际上是正确的时候,我们愿意拒绝它的概率。换句话说,如果我们有 5%的 alpha 值,那么我们愿意接受 5%的可能性,即当实际上没有差异时,我们会得出有差异的结论。像这样的错误被称为假阳性或第一类错误。让我们再看一遍我们的图片,获得一个视觉上的直觉。
作者创造的形象
置信度/alpha 值创建了一个决策边界。高于边界的值将被视为分布 B 的一部分并支持替代假设,低于边界的值将被视为分布 A 的一部分并支持零假设。现在,您可以从图表的阴影部分看到,alpha 值如何表示我们愿意错误归类为分布 b 一部分的值的百分比。我们必须设置这一决策界限,并为这些错误答案做好准备,因为两个分布之间存在重叠,会产生歧义。阴影部分是那些事实上支持零假设的值(分布 A 的一部分),但我们误认为支持替代假设(我们将它们误解为分布 B 的一部分)。这就是为什么我们称它们为假阳性——它们错误地支持阳性检测。为了更好地理解这一点,如果我们的置信水平为 95%,alpha 为 5%,这意味着图像中的阴影区域将是分布曲线 a 下面积的 5%。
统计功效和β
假设检验的功效是检验将正确支持替代假设的概率。换句话说,功效是属于分布 B 的条目被正确识别的概率。功率计算为 1-β。那么什么是β呢? Beta 是我们接受零假设的概率,即使另一个假设实际上是真的。在我们的例子中,这是我们将一个值误认为是分布 A 的一部分的概率,而它实际上是分布 b 的一部分。标准的功率度量通常是 0.8 或 80%,这使得β为 0.2 或 20%。同样,在决定适合你的测试级别时,你需要考虑你自己的测试。让我们想象一下贝塔。
作者创造的形象
阴影区域代表β。您可以看到这些值是如何被认为是分布 A 的一部分(支持零假设),从而得到一个否定的测试结果。这就是为什么它们被认为是假阴性。这种类型的测试误差被称为II 型误差。
组装在一起
照片由格雷格·罗森克在 Unsplash 上拍摄
在了解了α和β之后,你就可以看到这两者之间往往是一种平衡。如果我们想避免假阳性或 I 型错误,那么我们可以提高我们的信心水平。但是我们在避免假阳性方面越严格,那么我们得到假阴性或 II 型错误的可能性就越大。在尝试解决这个问题时,您可以考虑以下几点:
- 您可以考虑您的特定测试,以及哪种类型的错误会更糟糕。想象一个新冠肺炎测试作为例子。如果你要对某人进行新冠肺炎病毒测试,假阴性比假阳性更糟糕,因为某人携带病毒但被告知没有携带(假阴性),可能最终会感染许多其他人,因为他们认为自己没有携带病毒。最好是错误地将人们识别为病毒携带者(假阳性),因为最糟糕的情况是,即使没有必要,他们也会呆在家里进行隔离。因此,新冠肺炎的测试应该优先考虑较低的 beta 值。但是,也许一家测试网站的公司会希望最大限度地减少 I 类错误或误报,因为做出改变可能是一项充满风险的昂贵努力,除非他们非常确定它会产生预期的积极影响,否则不值得。他们可能会错过一些机会,但他们会避免代价高昂的错误。通过考虑你的特殊问题,你可以最小化或最大化对你最重要的错误。
- 对于你的问题,你可以考虑你所关心的最小差异量。假设你正在做一个测试,看看一个网站的改变是否会增加转化率。如果转换率只有微小的变化,就很难发现假设检验中的差异,你也更有可能出错。通过设置一个阈值来衡量指标需要改进多少才能值得进行更改,您将创建一种情况,在这种情况下,两个分布之间的重叠会更少,模糊和错误的区域也会更小。如果在实验中测量的变化非常小,那么产生错误的风险更高,因为两个分布之间可能有更多的重叠。
- 你可以考虑增加样本的大小。通过在您的实验中使用更大的样本量,您的实验更容易找出两种分布之间的差异。如果小的差异对你来说仍然很重要的话,用大量的样本也更容易发现小的差异。你也可以使用互联网上的计算器,根据期望的 alpha、功效和最小效果大小,计算出所需的样本大小。
结论
我希望这是对这些不同因素以及它们如何相互影响的充分解释。你的家庭作业是在网上玩一个互动工具来帮助你建立直觉。如果这些概念现在让你感到困惑,那么要知道它们一开始让每个人都感到困惑。只需要一点点练习。
了解最接近的政策优化(舒尔曼等人,2017 年)
原文:https://towardsdatascience.com/understanding-and-implementing-proximal-policy-optimization-schulman-et-al-2017-9523078521ce?source=collection_archive---------5-----------------------
作为一名初学者,我是如何自下而上地接触 PPO 文件的
近年来,政策梯度方法的研究一直很流行,TRPO、GAE 和 A2C/A3C 等算法显示了优于 Q-learning 等传统方法的最新性能。这个策略梯度/行动者-批评家领域的核心算法之一是 OpenAI 实现的近似策略优化算法。
在这篇文章中,我试图做到以下几点:
- 通过对政策梯度方法和信赖域方法(TRPO)提供一个初学者友好的概述来讨论 PPO 背后的动机
- 了解 PPO 的核心贡献:削减替代目标和多时代政策更新
目的
破坏性策略更新
我们首先需要理解如下定义的策略梯度方法的优化目标:
政策损失函数(舒尔曼等人,2017 年)
策略 pi 是我们的神经网络,它将来自环境的状态观察作为输入,并建议要采取的行动作为输出。优点是对当前状态下所选动作的相对值的估计,因此 hat 超过 A。它被计算为折扣奖励(Q) —价值函数,其中价值函数基本上给出了奖励折扣总额的估计值。在训练时,这个代表价值函数的神经网络将经常使用我们的代理在环境中收集的经验进行更新。然而,这也意味着值估计会由于网络引起的变化而非常嘈杂;网络并不总是能够预测该状态的精确值。
将政策产出和优势函数的对数概率相乘,给了我们一个巧妙的优化函数。如果优势为正,意味着代理人在样本轨迹中采取的行动导致了高于平均水平的回报,政策梯度将为正,以增加我们在遇到类似情况时再次选择这些行动的概率。如果优势是负的,政策梯度将是负的,以做完全相反的事情。
在一批收集的经验中不断地执行梯度下降步骤是很有吸引力的,它将经常更新参数,使之远远超出导致**“破坏性大的策略更新”的范围**
信任区域策略优化
防止这种破坏性策略更新的方法之一是 信任区域策略优化(舒尔曼等人,2015) 。在本文中,作者实现了一种算法来限制策略梯度步骤,使其不会偏离原始策略太多,从而导致经常完全破坏策略的过大更新。
首先,我们将 r(θ)定义为当前策略下的动作与先前策略下的动作之间的概率比。
舒尔曼等人,2017 年
给定一系列采样动作和状态,如果特定动作对于当前策略比对于旧策略更有可能,则 r(θ)将大于 1。对于我们当前的策略,当行动的可能性较低时,它将介于 0 和 1 之间。
现在,如果我们将这个 r(θ)乘以前面提到的优势函数,我们会以更易读的格式得到 TRPO 的目标:
(舒尔曼等人,2017 年)
在这个 TRPO 方法中,我们注意到它实际上非常类似于左边的普通政策梯度方法。实际上,这里唯一的区别是 log 运算符被替换为当前策略的动作概率除以前一个策略下的动作概率。优化这个目标函数在其他方面是相同的。
此外,TRPO 添加了 KL 约束,以限制梯度步长使策略远离原始策略。这导致梯度停留在我们知道一切正常的区域,因此命名为“信任区域”然而,已知这个 KL 约束增加了我们的优化过程的开销,这有时会导致不期望的训练行为。
近似策略优化(PPO)
剪切替代目标
基于上述动机,近似策略优化试图简化优化过程,同时保留 TRPO 的优点。本文的主要贡献之一是删减的替代目标:
删减的替代目标(舒尔曼等人,2017 年)
这里,我们计算最少两项的期望值:正常 PG 目标和削波 PG 目标。关键部分来自第二项,其中正常的 PG 物镜被 1-ε和 1+ε之间的限幅操作截断,ε是超参数。
由于 min 运算,当优势估计为正或负时,此目标表现不同。
(舒尔曼等人,2017 年)
让我们首先来看看左图,它描绘了积极优势:当选定的行动对结果产生了比预期更好的影响时的情况。在图表中,当 r 变得太高或者当在当前政策下比在旧政策下更有可能采取行动时,损失函数变平。我们不想因为走得太远而使动作更新过度,所以我们“剪辑”了目标以防止这种情况,同时用一条平线阻挡渐变。
当优势估计为负时,这同样适用于右图。当 r 接近零时,损失函数将变平,这意味着在当前政策下不太可能采取特定行动。
尽管这种方法很聪明,但裁剪操作也有助于我们“撤销”政策的错误。例如,右图中突出显示的部分显示了这样一个区域,在该区域中,最后一个梯度步骤使所选操作更有可能发生,同时也使策略变得更糟,如负优势所示。令人欣慰的是,我们的裁剪操作将友好地告诉梯度走在另一个方向,与我们搞砸的数量成比例。这是唯一一个min()
里面第一项比第二项低的部分,作为备用方案。最棒的是,PPO 无需计算额外的 KL 约束就能完成所有这些工作。
所有这些想法都可以在最终损失函数中进行总结,将这个删减的 PPO 目标和两个附加项相加:
(舒尔曼等人,2017 年)
c1 和 c2 是超参数。第一项是负责更新基线网络的价值函数的均方误差。第二个术语,可能看起来不熟悉,是一个熵术语,用于确保我们的代理有足够的探索。这个术语将推动政策更自然地运行,直到目标的另一部分开始起主导作用。
策略更新的多个时期
最后,让我们一起来看看算法及其并行演员的优点:
PPO 算法(舒尔曼等人,2017 年)
该算法由两个大线程组成:米色线程和绿色线程。米色线程收集数据,计算优势估计值,并为绿色线程提供小批量样本。一个特别之处是:这些是由 N 个并行的角色各自独立完成自己的任务。
对样本运行梯度下降的多个时期并不常见,因为存在破坏性的大规模策略更新的风险。然而,在 PPO 的剪切代理目标的帮助下,我们可以利用并行参与者来提高采样效率。
每隔一段时间,绿色线程就会启动,对我们的削波损失函数运行随机梯度下降。又一次特殊拍摄?我们可以在相同的轨迹样本上运行 K 个优化时期。在 PPO 之前也很难做到这一点,因为在本地样本上采取大步骤的风险,但 PPO 防止了这一点,同时允许我们从每个轨迹中了解更多。
参考
[1] 近端政策优化(舒尔曼等,2017)
[2] 信任区政策优化(舒尔曼等,2015)
最初发表于
https://blog . tylertaewook . com/posts/proximal-policy-optimization
理解和解释 Python 中的数据
原文:https://towardsdatascience.com/understanding-and-interpreting-data-in-python-db67b11865a0?source=collection_archive---------18-----------------------
Python 中的探索性数据分析
弗兰基·查马基在 Unsplash 上拍摄的照片
作为数据科学家,我们都必须处理大量不同的数据集。要在数据集上拟合任何预测模型,我们需要先了解数据集的复杂性,然后再决定使用哪个预测模型来获得最佳性能。但是,数据集通常很大,手动理解数据集中的每个数据点是不可能的。因此,我们需要一些度量和可视化来帮助我们理解数据的本质,并给我们一个简要的概述。
探索性数据分析(EDA)对数据进行分析和可视化,以从中获取洞察力。它可以被描述为一个总结数据的重要特征以便更好地理解的过程。为了了解 EDA 的过程,我们将使用住房数据集,可在这里获得。我们将详细了解 EDA 的每个必要步骤,为什么需要它,以及如何实现它。
我们还将通过对数据集执行探索性数据分析来探索数据集。本博客涉及的主要话题如下:
- 统计洞察力
- 删除重复项
- 异常值处理
- 单变量分析的可视化
- 二元分析的可视化
统计洞察力
这里我们将分析数据统计,即均值、方差、分位数、唯一元素等。在我开始之前,让我们先看看 python 代码需要的库,以及如何加载数据。
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as npdf = pd.read_csv("train.csv")
为了简要了解数据,我们将检查以下参数:
- 数据集的前 5 行
- 存储在每列中的变量的数据类型。
- 平均值、中间值和其他统计属性,
- 每行中的唯一元素。
要获得前 5 行,请使用以下命令:
df.head()
作者图片
输出如上图所示。这个函数为我们提供了关于数据集中存在的列以及每一列中存在的值的基本概念。
为了更好地理解每一列中的值的数据类型,我们使用下面的命令。
df.info()
作者图片
这个列表很大,有 81 列。但我只给出了前 10 列的截图。
下一步是检查数据的统计汇总,我们使用下面的函数。
df.describe()
作者图片
该函数的输出具有以下形式:
它在列中显示计数、平均值、标准差、最小值、25%百分点值、中值(50%百分点值)、75%百分点值和最大值。这里解释一些不太常见的术语:
- Count 列中存在的非空值的总数。
- 25%百分位— 25%的数据小于该值
- 50%百分位— 50%的数据小于该值,也与中位数相同
- 75%百分比— 75%的数据小于该值
现在我们已经有了关于每一列的基本信息,让我们看看如何找出数据集中某一列的唯一元素。
df["OverallQual"].unique()
作者图片
标题为“总体平等”的列只有很少的独特元素。列中的元素是离散的,最大值为 10,这可以从上图中得到验证。
删除重复项
所谓重复,我指的是数据集中的两行,每一列都包含相同的值。在数据集中有重复项是不可取的,这通常会导致过度拟合。因此需要移除它们。
df.duplicated().sum()
作者图片
df.duplicated()提供了一个布尔列表,指示一行是否重复。然后 sum()将给出数据集中重复行的总数。在我们的例子中,它是 0,如图所示。但是如果有重复的行,可以按如下方式删除它们
df.drop_duplicates(inplace=True)
异常值处理
异常值是一般情况下不会出现的极端观察值,只有在非常特殊的情况下才会出现。我们训练的预测模型实际上是用来寻找一般情况下的输入和输出之间的关系,而不是特殊情况。因此,使用异常值来训练这种预测模型可能会导致性能恶化。因此,我们必须消除它们。
找出异常值的标准过程是
- 找到 Q1 和 Q3 四分位数。
- 将两个列表相减,找出内部四分位数范围( IQR )。
- 任何小于Q1-1.5 iqr或大于 Q3+1.5IQR 的点都被视为异常值。
为了找出异常值,我们将使用“销售价格”列。
作者图片
因此,数据集中出现的异常值总数为 61,我们应该在使用数据集进行训练之前删除它们。
处理缺失数据
缺失数据意味着数据集中几乎没有未填充的位置。首先,我们来看看如何找出缺失的数据。
df.isnull().sum()
作者图片
df.isnull()提供一个布尔数组,然后。sum()给出列中存在的空值的总数。由于有很多列,我不能在这个截图中显示所有的信息。
那么我们如何处理这些丢失的数据呢?这里,我将只讨论包含整数和浮点类型变量的列。如果一个列包含字符串,那么所有这些方法可能都不适用。
- Drop — 我们将删除丢失的值,也就是说,如果特定行中有任何丢失的值,将删除整行。此方法仅适用于缺少值的行数非常少的情况。
df.dropna(subset=["BsmtQual"], inplace=True)
它将删除列“BsmtQual”包含空值的行。
- 用统计参数估算— 用平均值、中值或众数替换缺失值。这里通常使用平均值,但是在这一步之前检查异常值的数量是非常可取的。如果有很多异常值,那么使用中位数更为可取。
df["$NA"][df["$NA"].isnull()] = df["$NA"].dropna().mean()
将$NA 替换为要用 mean 替换其中缺失值的列名。
- 插值— 根据一列对数据集进行排序,“最重要的一列”,这通常是您想要预测的列。然后使用线性插值来填充缺失的值。
单变量分析的可视化
单变量分析是分析数据的最简单形式。这里“uni”代表一个变量。因此,在这里我们将看到如何可视化和分析一列数据。我们将讨论以下可视化
- 箱形图
- 柱状图
箱形图
箱形图仅用一个数字就包含了大量关于数据的统计信息。
方框图描述(图片由作者提供)
箱线图告诉我们中值、上四分位数、下四分位数、最大值、最小值和异常值,因此涵盖了所有的统计参数。
sns.boxplot(df["SalePrice"])
作者图片
对于我在这里展示的情况,方框图是水平的。请注意,所示的箱形图在下部区域有异常值。
柱状图
直方图显示了变量的频率分布。它将数值数据划分到称为“箱”的桶中,然后计算落入每个箱中的数据点的数量。因此,纵轴实际上代表每个箱中数据点的数量。
我们将可视化数据集中的“BedroomAbvGr”列。
作者图片
上面的直方图基本上表明,在给定的数据集中,大多数房子都有 3 间卧室。
二元分析的可视化
双变量分析用于理解数据集中存在的两个或多个变量之间的关系。例如,随着房屋整体质量的变化,分析房价的变化。让我们看看如何直观地理解两个变量之间的关系。我们将要讨论的可视化如下:
- 相关矩阵
- 回归图
相关矩阵
相关性用于衡量一个变量相对于另一个变量的变化程度。为了更好地理解这一点,考虑上面的例子。房子的价格会随着整体品质的变化而发生怎样的变化?我们基本上是找到数据集中存在的所有数值变量之间的相关性来构造相关矩阵。
作者图片
混淆矩阵对我们的数据集来说是巨大的,因为有很多变量。白色表示相关值为 1,这意味着这两个变量是相同的。可以看出,对角线是白色的,这是合乎逻辑的,因为对角线值表示元素与其自身的相关性,该相关性将为 1。黑色表示相关值为-1,这意味着两个变量完全相关,但方向相反。也就是说,如果一个值增加,另一个值就会减少,反之亦然。黑色和白色之间的一种特殊颜色表示相关值为 0,这意味着两个变量完全独立。现在,当您重新访问上述相关矩阵时,可以检查浅色块具有正相关值,深色块具有负相关值。在预测“销售价格”时,与“销售价格”相关的绝对值较高的特征是有益的。
回归图
它用于理解两个变量之间的关系。它与分析两个变量之间的相关性相同,但它只用于分析两个变量,这与相关矩阵不同。这可以看作是一个正常的图表,我们绘制所有的数据点,然后找到最佳拟合线。
sns.regplot(x='BedroomAbvGr',y='SalePrice',data=df)
作者图片
这是总体质量与房价的回归图。由于斜率增加,这意味着相关值为正。此外,斜率值越高,表示绝对相关值越大。
作者图片
现在从这两个图表中,我们可以观察到以下情况:
- 房子的整体质量和价格之间的相关性,以及卧室数量和房子价格之间的相关性是正相关的。
- 房屋整体质量与价格的相关性高于卧室数量与房屋价格的相关性。
太激烈了!!
但是现在我们知道一列中有多少异常值,如何识别和删除这些异常值,整个数据中有多少行存在缺失数据,一个变量如何影响另一个变量,哪些特征对于预测来说是最重要的等等。
我希望这篇博客能帮助你理解我们是如何探索数据并从中提取信息的。我建议在找到合适的预测模型之前使用这些技巧,因为每次理解和探索您的数据是至关重要的。
如果您喜欢这些内容,并希望了解数据科学的广阔领域,请关注我们的 medium 。
成为 介质会员 解锁并阅读介质上的许多其他故事。
了解阿帕奇蜂房 LLAP
原文:https://towardsdatascience.com/understanding-apache-hive-llap-fa6d93f73032?source=collection_archive---------26-----------------------
来源: Unsplash
当你看的时候,Apache Hive 是一个复杂的系统,但是一旦你去寻找更多的信息,它比复杂更有趣。Hive 有多种查询引擎,在查询引擎之上还有 LLAP,使实时、交互式查询更加可行。当你了解更多的时候,长寿和过程,或者 LLAP,是一个令人敬畏的概念和执行。
这正是我所做的,我读了一些关于 LLAP 的文件和其他帖子,对它有了更好的了解。我也理解 Tez 查询引擎,并期待很快看到关于它的帖子。在这篇文章中,我将展示我对 LLAP 的了解,以及如果你使用它会有多棒。
配置单元查询引擎
Hive 有三个查询引擎:
- MapReduce (MR)
- 阿帕奇技术中心
- 阿帕奇火花
MapReduce (MR)
MapReduce 是 Hive 附带的第一个查询引擎,也是最慢的一个。当您使用 MR 作为查询引擎提交一个 Hive 查询时,每个查询都会被转换成 MapReduce 作业并提交给 YARN 容器。YARN 或另一种资源协商器在 MR 和 Tez 查询引擎之间是常见的。但是 MR 查询引擎的问题是所有的查询都需要转换成 MR jobs。转换本身需要时间。因此,您可以想象这个查询引擎是如何因为大量的延迟而变得缓慢的。
阿帕奇技术中心
为了克服这个延迟问题,Tez 作为一个查询引擎被引入到 Hive 的更高版本中。Tez 使用有向无环图(Dag)来处理查询,而不是 MapReduce 作业。这大大减少了延迟并缩短了查询响应时间。在最新版本的 Hive 中,尽管不推荐使用 MR 查询引擎,但它是默认引擎。但是,每当您输入 Hive shell 时,都会收到反对警告,并建议您切换到 Tez 或 Spark 作为查询引擎。而且普遍建议改用 Tez。我们将在我的下一篇文章中看到原因。
阿帕奇火花
最后,我们有 Apache Spark 作为第三个查询引擎选项。到目前为止,Spark 是其中最快的。有人声称 Spark 可以将 Hive 的性能提高 100 倍,这是一个非常大胆的说法。Tez 没有提供如此高的性能提升,公认的提升是 10 倍。所以你可能会说,好吧,火花是明显的赢家,对不对?嗯,那得看情况!Tez 和 Spark 都使用 Dag 来优化 MR 的查询性能,因此两者都可以并行或并发执行大量任务。
在 Tez 和 Spark 之间选择一个查询引擎完全取决于您的应用程序和需求。但是无论你选择什么,LLAP 和坐在那个查询引擎的上面并且更好的性能甚至更多。例如,我们知道,如果我们再次需要数据,Spark 可以在内存或磁盘上缓存(持久化)数据。但是这种缓存在同一个 Spark 作业中是可用的,另一个 Spark 作业不能访问该数据。如果我告诉你 LLAP 也有这种可能呢?我知道,这太疯狂了。所以,让我们看看 LLAP 还能做什么。
长寿和进步(LLAP)
我们终于要谈谈 LLAP 了。首先你需要知道,就像我已经说得很清楚的,LLAP 不是一个查询引擎。它位于查询引擎之上,使查询和数据处理更快。如果你把不同的蜂巢组件想象成一个堆栈,HDFS 在底部,纱线在顶部,蜂巢在顶部。现在想象一下在 HDFS 之上有一层缓存和内存处理。这意味着很多请求根本不会发送到 HDFS。这就是 LLAP 在很高层次上所做的。
当我说 LLAP 是一个缓存和内存处理层时,我肯定是把事情过于简化了。肯定有更好的说法。我来详细说明一下。
你可以把 LLAP 想象成另一个运行在 Hadoop 集群中所有数据节点上的 YARN 应用。唯一的区别是 LLAP 是一个长期的过程(因此得名)。但这并不意味着它会耗尽你所有的资源。它可以被配置成一个非常小的进程来处理简单的查询,或者它可以被配置成在需要的时候动态地伸缩。与 Spark 相比,这带来了非常大的不同。因为 LLAP 仍然致力于纱线,它带来了纱线的所有优点,如分布式和容错。
LLAP 在数据节点上运行守护进程,这些守护进程不依赖于发出配置单元查询的用户。这是一个非常重要的区别,因为这允许 LLAP 跨用户重用缓存的数据。所以你和我都在同一个表上执行类似的查询,LLAP 将能够使用已经可用于我们两个查询的缓存,这将提高我们两个的性能。如果没有 LLAP,这两个查询将不得不分别执行相同的操作。你可以想象这是多么的不理想。
LLAP 不是一个查询引擎,它是可选的
你现在应该意识到了,LLAP 是完全可以选择的。使用 LLAP 进行配置单元查询并不是强制性的。只有当您希望在交互和批处理模式下提高配置单元查询的响应能力时,才使用 LLAP。即使使用 LLAP,也不像查询的所有部分都在 LLAP 执行。LLAP 不是用来做这个的,这才是查询引擎的用途。LLAP 接受部分查询,这些查询可以通过使用缓存或长寿命进程而受益。
LLAP 没有承诺它会自己执行整个查询。事实上,是查询引擎决定了什么可以进入 LLAP,什么不可以。目前,查询引擎 Tez 和 Pig 等其他框架可以在其堆栈中使用 LLAP。不幸的是,对 MapReduce 的支持还没有计划,不要对此抱太大希望。
而且因为 LLAP 仍然是为了和 YARN 一起工作而建立的,资源分配完全在 YARN 的控制之中。这也是 LLAP 守护进程节点能够相互通信并跨节点共享数据的原因。这里的另一个优点是守护进程本身不需要很多资源来运行。YARN 分配进程本身所需的最少资源,并会根据工作量在需要时增加资源分配。为了避免堆问题或 JVM 内存问题,缓存的数据总是保存在堆外的大缓冲区中。因此,与查询引擎相比,LLAP 对 group by 和 joins 等聚合的处理要快得多。
查询片段
我已经提到过,LLAP 通常执行部分查询,而不是整个查询。查询的这些部分被称为查询片段。这些片段包括过滤器、数据转换、部分聚合、投影、排序、分桶、连接、半连接、散列连接等。需要注意的是,LLAP 只接受某些“受祝福的”UDF 和 Hive 代码。
为了流程的稳定性和数据的安全性,LLAP 不本地化任何代码,并且动态执行。因为守护进程不依赖于任何特定的用户(如前所述),所以 LLAP 节点可以允许跨查询和会话并行执行各种查询片段。这是性能提高的主要原因之一。另一个好消息是,特别是对开发人员来说,LLAP API 可以通过客户端 SDK 直接获得。您可以使用这些 API 直接指定关系转换。
输入和输出
正如我已经提到的,守护进程本身占用的内存非常小,这是因为其他的事情大部分都是通过将工作卸载给多线程来完成的。例如,输入和输出被卸载到线程。和转换是在单独的线程中完成的。因此,一旦 I/O 线程准备好数据,数据就被传递给单独的线程进行处理。这使得 I/O 线程可用于新的 I/O 操作。
数据在进程中以游程编码(RLE)列格式进一步传递给其他线程。这在很大程度上减少了跨线程和进程复制数据。通过扩展,缓存也是同样的 RLE 格式。你可以从这里开始看到好处。
I/O 和缓存在很大程度上依赖于存储数据的文件格式。如果 I/O 和缓存必须是高性能的,这是必要的。所以 LLAP 借助插件将这些知识具体化了。ORC 是 LLAP 支持的第一种文件格式。这就是为什么越来越多地采用 ORC 作为外部 Hive 表的首选文件格式的原因之一。
说到缓存,元数据和数据本身都会被缓存。正如我在前面几节中提到的,数据被缓存在堆外以避免其他潜在的问题。但是另一方面,元数据作为 Java 对象存储在进程中。这确保了即使数据本身被逐出缓存,元数据仍然在内存中,以避免一些开销。
我提到了缓存中的数据驱逐。如您所料,有各种各样的数据驱逐策略。默认情况下,使用 LRFU 策略。但是您可以随时插入任何其他策略。
处理
这是 Hive 中争论的一大领域,交易还是不交易。但这是另一篇博文的主题。就 LLAP 而言,它理解交易。它足够智能,可以在数据被缓存之前执行转换(比如合并或增量文件)。如果在同一个表上执行各种事务(这种情况很常见),LLAP 可以为每种变化存储多个版本的数据。并且将根据查询动态地从缓存中获取正确的版本。这将确保不会对相同的数据一次又一次地执行相同的转换集,从而减少大量的处理时间。
了解 LLAP 不止于此。还有更多,你越想理解它,它就变得越有趣。随着我探索的深入,我打算写更多关于它的东西。但现在,这是我的全部。理解 LLAP 的工作方式将使编写查询变得容易得多,而且编写查询的方式可以利用这些优化来减少延迟。我希望这对你的 Hadoop 或 Hive 之旅有一点帮助。
如果你喜欢这里看到的,或者在我的个人博客和 Dev 上看到的。要写博客,并希望在未来看到更多这样有用的技术帖子,请考虑在 Github 上关注我。
原载于 2021 年 11 月 18 日【https://blog.contactsunny.com】。
理解 Python 中的*args 和**kwargs
原文:https://towardsdatascience.com/understanding-args-and-kwargs-in-python-321937f49c5b?source=collection_archive---------12-----------------------
了解如何在 Python 中向函数传递可变数量的参数
照片由克里斯里德在 Unsplash 拍摄
如果您是一名初级 Python 程序员,您可能会遇到带有如下所示参数的函数声明:
def do_something(num1, num2, ***args**, ****kwargs**):
上面的*
和**
操作符允许您向函数传递可变数量的参数。然而,这个特性经常给 Python 程序员带来很多困惑。本文将试图阐明*
和**
操作符的用途,以及如何在日常编程任务中使用它们。
使用* 传递可变数量的参数
首先,考虑以下函数定义:
def do_something(num1, num2, *args):
print(num1)
print(num2)
要调用 do_something() ,需要传入:
- 两个强制参数,后面是,
- 可选的可变参数数量
让我们试试这个,看看会发生什么。我们可以先这样调用 do_something() :
# calling the function with two mandatory arguments
do_something(5,6)
您现在应该看到:
5
6
您也可以在前两个参数后传递附加参数,如下所示:
do_something(5,6,**7,8,9**)
第三个参数向前传递到 do_something() 函数中的 args 变量中。 args 的数据类型为元组。因此,您可以在函数中使用一个 for-in 循环来提取传入的单个可选参数:
def do_something(num1, num2, *args, **kwargs):
print(num1)
print(num2)
**for arg in args:
print(arg)**
因此,您的输出将如下所示:
5
6
7
8
9
以下对 do_something() 函数的调用都是有效的:
do_something(5,6,**7**)
do_something(5,6,**7,8**)
do_something(5,6,**7,8,9**)
do_something(5,6,**7,8,9,True**)
do_something(5,6,**7,8,9,True,3.14**)
虽然您可以为可选参数传入不同类型的不同参数,但传入相同类型的参数更常见(也更符合逻辑)。例如,您可能有一个名为 average() 的函数来计算一组数字的平均值:
def average(*args):
return sum(args) / len(args)print(average(1,2)) # 1.5
print(average(1,2,3)) # 2.0
print(average(1,2,3,4,5)) # 3.0
print(average(1,2,3,4,5, 6.1)) # 3.516666666666667
在这种情况下,传入相同类型(数值类型)的参数很有意义。
值得一提的是,变量参数的命名并不局限于“ args ”。您可以使用自己的变量名来命名它。
使用*解包参数
在上一节中,您看到了如何向函数传递可变数量的参数,如下所示:
do_something(5,6,**7,8,9**)
如果您的可选参数存储在一个列表或元组中,如下所示:
values = (7,8,9) # tuple
在这种情况下,要将 values 变量传递给 do_something() 函数,您可以使用*****
操作符来解包值,以便可以将它们传递给函数:
do_something(5,6,***values**)
*
操作符也处理列表:
values = **[**7,8,9**]** # list
do_something(5,6,*values)
使用**传入“带关键字的”参数
可变参数的第二种形式对初学者来说稍微有点混乱。考虑以下函数定义:
def do_something(num1, num2, ****kwargs**):
kwargs 中的 kw 代表 k ey w orded。同样,您可以使用自己喜欢的名称给这个变量命名。
除了传入前两个强制参数之外,现在还可以传入一个可选的“关键字”参数。一个例子可以说明这一点:
do_something(5,6,**x=7**)
do_something(5,6,**x=7,y=8**)
就个人而言,我更喜欢称 x=7 和 y=8 为键/值对。
在上面的例子中,您可以通过指定键(x
和y
)和它们相应的值(7 和 8)来传递额外的参数。
在这个函数中,关键字对作为一个字典被传递给**kwargs**
。因此,您可以使用 for-in 循环提取它们,如下所示:
def do_something(num1, num2, ****kwargs**):
print(num1)
print(num2)
**for k,v in kwargs.items(): # get each key/value pair one at a
print(k,v) # time**
当然,您也可以提取键,然后像这样提取值:
def do_something(num1, num2, **kwargs):
print(num1)
print(num2)
**for k in kwargs.keys(): # retrieve all the keys
print(k, kwargs[k]) # then get the value based on the key**
在任一情况下,输出将如下所示:
5
6
**x 7
y 8**
**kwargs
的用途
关于**kwargs
的一个常见问题是它的用例。****kwargs**
在什么情况下有用?考虑以下情况,其中您有一个包含四列的数据帧:
import pandas as pd
import numpy as npdf = pd.DataFrame(np.random.randn(5,4),
columns=['Summer','Winter','Autumn','Spring'])
df
数据帧看起来像这样:
以熊猫数据为例
假设您被要求编写一个函数,比如说 **fetch_data(),**允许用户从一个或多个单元格包含的值大于某些特定值的列中提取行。例如,您希望从 Summer 列中提取值大于 0.5 的所有行。此外,您可能还想从 Winter 列中提取值大于 0.2 的行。在这些情况下,您的函数应该足够灵活,可以指定多个列名和值,如下所示:
fetch_data(Summer=0.5) # retrieve only the Summer column
fetch_data(Summer=0.5, Winter=0.2) # retrieve the Summer and Winter
# columns
要实现此功能,您的函数可以使用关键字对接受这些列和值,如下所示:
def fetch_data(****kwargs**):
for k,v in kwargs.items():
print(df[[k]][df[k]>v]) # df[[k]] first returns the specified column (k) as a
# dataframe, then [df[k]>v] retrieves all the rows whose
# cell value is more than the value specified (v)
所以下面调用 fetch_data() :
fetch_data(Summer=0.5, Winter=0.2)
产生以下输出:
Summer
0 0.842614
2 0.767157
4 0.935648
Winter
0 0.843960
3 0.663104
使用**解包参数
正如您可以使用*
操作符解包值列表并将其传递给具有可变参数的函数一样,您也可以使用**
操作符解包 dictionary 对象并将其传递给接受关键字参数的函数,如下所示:
**kwpairs = {'Summer':0.5, 'Winter':0.2} # dictionary
fetch_data(**kwpairs)** # same as
fetch_data(Summer=0.5, Winter=0.2)
可变参数和关键字参数的顺序
在函数声明中,可以有以下类型的参数:
- 强制参数,和/或
- 可变参数,和/或
- 关键词论据
然而,如果一个函数接受带关键字的参数,它必须总是放在函数声明的最后处。以下函数声明无效:
def do_something(**kwargs, *args):
...def do_something(*args, **kwargs, num1):
...def do_something(**kwargs, num1):
...
如果一个函数接受带关键字的参数,它必须总是放在函数声明的最后。
以下示例显示了一些有效的函数声明:
def do_something(num1, *args, **kwargs):
...def do_something(num1, num2, *args):
...def do_something(*args, **kwargs):
...def do_something(**kwargs):
...def do_something(*args, num1):
...def do_something(*args, num1, **kwargs):
...
我将把它作为一个练习留给读者,让他们尝试上面的函数声明,并探索如何将值传递给它们。
我希望你现在对*args
和**kwargs
有更好的理解!
使用 PyCaret 的 ARIMA 模型实用指南—第 1 部分
原文:https://towardsdatascience.com/understanding-arima-models-using-pycarets-time-series-module-part-1-692e10ca02f2?source=collection_archive---------8-----------------------
奠定统计基础
由阿格巴洛斯在 Unsplash 上拍摄的照片
📚简介
PyCaret 是一个用 Python 编写的开源、低代码的机器学习库,可以自动化机器学习工作流。这是一个端到端的机器学习和模型管理工具,可以成倍地加快实验周期,提高您的工作效率。
PyCaret 最近发布了一个时间序列模块,它附带了许多方便的特性,使得时间序列建模变得轻而易举。你可以在这篇文章中了解更多。
在这个由多个部分组成的系列文章中,我们将重点讨论如何使用 PyCaret 这样的“低代码”库来更深入地理解 ARIMA 模型的工作原理。在第一部分中,我们将对 ARIMA 模型及其参数进行概述。然后,我们将从一个简单的 ARIMA 模型开始,为这个模型的预测和预测区间创建一个理论框架,以发展对其工作的直觉。最后,我们将使用 PyCaret 构建这个 ARIMA 模型,并将理论计算与模型输出进行比较。将模型的输出与我们的理论框架联系起来,有望加深我们对模型的理解,并为后续文章中更详细的分析奠定基础。
📖建议的先前阅读
本文推荐给那些对时间序列有基本了解(例如,季节性、自相关 ACF、白噪声、训练-测试-分割等概念)但有兴趣了解更多 ARIMA 模型的人。如果你不熟悉这些概念,我建议你先阅读这些短文。这将有助于理解这篇文章。
👉时间序列中的季节性和自相关性
👉什么是「白噪音」?
👉时间序列交叉验证
1️⃣ ARIMA 模型概述
ARIMA 是一个经典的时间序列模型,用于模拟时态数据的自回归特性。自回归意味着依赖于自身过去的值。时间序列可能依赖于(1)其最近的过去值,或者(2)可能表现出季节性行为,并在一定数量的时间点过去后重复自身。
直观上,(1)的一个例子是股票数据。这是时间数据,明天的价格受今天(或最近的过去)价格的影响很大,而与一个月或一年前发生的事情没有太大关系。类似地,( 2)的一个例子可以是在零售店销售冬装。这通常在冬季前达到高峰,在夏季逐渐减弱。因此,它表现出季节性模式。今年冬天的销售额将与去年冬天的销售额高度相关。
现在我们已经看到了一些基本的例子,让我们看看这是如何在模型中表示的。经典的 ARIMA 模型有几个超参数,但我们将重点关注其中的两个主要参数— order
和seasonal_order
。
**order:** iterable or array-like, shape=(3,), optional (default=(1, 0, 0))
The (p,d,q) order of the model for the number of AR parameters, differences, and MA parameters to use.**seasonal_order:** array-like, shape=(4,), optional (default=(0, 0, 0, 0))
The (P,D,Q,s) order of the seasonal component of the model for the AR parameters, differences, MA parameters, and periodicity.
现在,你可能想知道这些术语与我们上面强调的例子有什么联系,以及order
和seasonal_order
中的三个和四个术语分别是什么意思。在非常高的层次上,order
与上面的例子(1)相关,其中下一个值与紧接的前一个值强相关。seasonal_order
与上面的示例(2)相关,其中下一个值与过去一个或多个季节的数据相关。
但这仍然没有回答什么是(p, d, q)
和(P, D, Q, s)
的问题。这正是我们将在这一系列文章中试图回答的问题。
注意:本系列文章采用“代码优先”的方法来理解 ARIMA 模型。我强烈建议读者也参考[5],以便从理论角度更好地理解。
2️⃣基线 ARIMA 模型
为了更好地理解 ARIMA 模型的各种超参数,让我们从一个非常简单的 ARIMA 模型开始——一个没有任何自回归属性的模型。这通常用于表示白噪声(即数据中没有任何信号)。你可以在[1]和[2]中找到更多关于它的信息。该模型由以下超参数表示:
##############################################
#### Baseline ARIMA Model Hyperparameters ####
##############################################(p, d, q) = (0, 0, 0)
(P, D, Q, s) = (0, 0, 0, 0)
理论上,由于时间序列数据没有任何信号,未来预测(样本外)的最佳表示是用于训练模型的数据的平均值(详细信息请参见[2])。同样,样本内预测的最佳估计也是用于训练模型的数据的平均值。
我们可以通过计算样本内拟合的残差来获得这些预测的预测区间。残差表示实际样本内数据(即用于训练的数据)和由该模型产生的样本内估计(在这种情况下是训练数据的平均值)之间的差异。
好吧,理论是一回事,但一张图胜过千言万语。所以让我们来实践一下。我们将使用 PyCaret 的时间序列模块来更深入地了解这个模型。注意,可以在这里的 和参考资料部分找到代码的笔记本 。
3️⃣使用 PyCaret 了解 ARIMA 模型
PyCaret 的时间序列模块提供了超过 2000 个已知属性的时间序列的数据游乐场。我们将使用来自这个操场的“白噪声”数据集来解释这个例子。
👉步骤 1:设置 PyCaret 时间序列实验
#### Get data from data playground ----
y = get_data("1", folder="time_series/white_noise")
实验的白噪声数据(仅前 5 行)[图片由作者提供]
接下来,让我们设置一个时间序列实验来探索和建模这个数据集。“时间序列实验”是一个一站式商店,用户可以在这里执行探索性分析(EDA) 、模型构建、模型适合度评估以及部署——同时遵循引擎盖下的最佳建模实践。
在这个设置中,我将预测范围fh
设置为 30(即我们打算预测接下来的 30 个时间点)。我还暂时将seasonal_period
设置为 1。注意,如果您的数据有一个DatetimeIndex
或PeriodIndex
指数(这里不是这种情况),那么季节周期是自动推断的。如果是别的什么,我们需要度过季节期。我还传递了一个会话 ID,它充当种子并使实验可重复。
#### Setup experiment ----
exp = TimeSeriesExperiment()
exp.setup(data=y, seasonal_period=1, fh=30, session_id=42)
[图片由作者提供]
该设置从一开始就为我们提供了一些方便的信息。
(1)我们看到我们的数据有 340 个数据点。在这个实验中,pycaret 保留了最后 30 个数据点(与预测时间范围相同)作为“测试集”,剩余的 310 个数据点用于训练。
(2)我们通过了季节性周期 1,但是在内部测试季节性之后,没有检测到它。这是意料之中的,因为这是没有季节性的白噪声数据。
(3)内部进行了白噪音的永盒测试(见前面的读数),确定数据与白噪音一致。同样,这也是我们所期望的,因为我们是从白噪音领域中挑选数据的。
👉步骤 2:执行 EDA
接下来,我们可以对这些数据进行快速 EDA:
# `plot_model` without any estimator works on the original
exp.plot_model()
绘制数据[图片由作者提供]
# Plot ACF ----
exp.plot_model(plot="acf")
ACF 图显示没有显著的自相关[图片由作者提供]
ACF 数据显示没有显著的自相关,并且与白噪声一致。这也是意料中的事(详见前面的内容)。
👉第三步:理论计算
接下来,让我们从实验中获得一些数据统计,并添加上面我们框架中的理论计算。
注意:训练和测试数据分割可以使用实验对象的“get_config”方法获得,如下所示。
# Get Train Data
y_train = exp.get_config("y_train")# Get Test Data
y_test = exp.get_config("y_test")#########################################################
# Convert into dataframe & add residual calculations ----
#########################################################train_data = pd.DataFrame({"y":y_train})
train_data['preds'] = y_train.mean()
train_data['split'] = "Train"test_data = pd.DataFrame({'y': y_test})
test_data['preds'] = y_train.mean()
test_data['split'] = "Test"data = pd.concat([train_data, test_data])data['residuals'] = data['y'] - data['preds']
data.reset_index(inplace=True)
接下来,让我们计算进行理论预测和计算预测区间所需的计算。
#######################################################
#### Compute values based on theoretical equations ----
#######################################################y_train_mean **=** data**.**query("split=='Train'")['y']**.**mean()
resid **=** data**.**query("split=='Train'")['residuals']
resid_sigma2 **=** (resid******2)**.**sum()**/**len(resid)
print(f"Mean of Training Data: {y_train_mean}")
print(f"Residuals Sigma2: {resid_sigma2}")***>>> Mean of Training Data: 176.01810663414085
>>> Residuals Sigma2: 0.9769567915901368***######################################
#### Compute Prediction Intervals ----
######################################import scipy.stats as st
alpha = 0.05# 2 sided multiplier
multiplier = st.norm.ppf(1-alpha/2)lower_interval **=** np**.**round(y_train_mean **-** multiplier ***** resid_sigma2******0.5, 2)
upper_interval **=** np**.**round(y_train_mean **+** multiplier ***** resid_sigma2******0.5, 2)
print(f"Prediction Interval: {lower_interval} - {upper_interval}")***>>> Prediction Interval: 174.08 - 177.96***
👉步骤 4:构建模型
既然我们已经完成了理论计算,让我们使用 PyCaret 构建这个模型并检查结果。模型创建就像从实验对象调用create_model
方法一样简单。此外,此时您还可以将特定的超参数传递给模型。在我们的例子中,我们正在建模没有任何自回归属性的数据,所以我们将为order
和seasonal_order
传递全零。如果你想了解更多关于如何用 PyCaret 创建时间序列模型,以及如何定制它们,请参考[3]。
model1 = exp.create_model(
"arima",
order=(0, 0, 0),
seasonal_order=(0, 0, 0, 0)
)
👉第五步:分析结果
接下来,我使用 PyCaret 一行程序编写了一些小的包装器函数来帮助进行模型评估(参见附录中的定义)。这些是
(1) summarize_model
:生成模型的统计概要
(2) get_residual_properties
:绘制并显示残差的方差
(3) plot_predictions
:绘制样本外和样本内预测
如果你想知道更多关于这些功能是如何工作的,特别是summarize_model
,请参考【4】。
现在,让我们看看当我们通过这些助手函数运行模型时会得到什么
summarize_model(model1)
get_residual_properties(model1)
ARIMA 模型的统计摘要[图片由作者提供]
模型残差和残差方差[图片由作者提供]
上面显示了模型的统计摘要。截距是训练数据的平均值。它与我们上面的理论框架中的计算相吻合!
sigma2 是残差的方差。我们怎么知道?检查get_residual_properties
功能的输出。它显示了残差的方差。这个值与统计概要完全匹配,也与我们的理论框架的计算完全匹配!
但是预测呢?接下来让我们检查一下。
plot_predictions(model1)
样本外预测和预测区间[图片由作者提供]
在样本预测中[图片由作者提供]
默认情况下,PyCaret 使用plotly
库提供交互式绘图,因此我们可以通过悬停在绘图上来快速验证值。我们可以很快看到,样本外和样本内预测值都等于 176.02,这与我们理论框架的计算结果相匹配。预测区间也与我们理论框架中的值相匹配!
🚀结论
希望这个简单的模型为我们理解 ARIMA 模型的内部运作打下了良好的基础。在下一组文章中,我们将开始逐一介绍其他参数,并查看它们对模型行为的影响。在那之前,如果你愿意在我的社交渠道上与我联系(我经常发布关于时间序列分析的文章),你可以在下面找到我。暂时就这样了。预测快乐!
🐦推特
📘 GitHub
喜欢这篇文章吗?成为 中等会员 继续 无限制学习 。如果你使用下面的链接, ,我会收到你的一部分会员费,而不会给你带来额外的费用 。
https://ngupta13.medium.com/membership
🔖建议下次阅读
使用 PyCaret 的时间序列模块理解 ARIMA 模型—第二部分
📗资源
- Jupyter 笔记本 包含这篇文章的代码
📚参考
[1] 诊断 PyCaret 中的“白噪声”
[2] 在 PyCaret 中建模“白噪声”
[3] 创建和定制时间序列模型
[4] 了解 PyCaret 时间序列模块的底层架构
[5] 第八章 ARIMA 模型,《预测:原理与实践》,罗伯 J 海曼和乔治阿萨纳索普洛斯
📘附录
- 助手功能
**def summarize_model(model):**
"""
Provides statistical summary for some statistical models
"""
# Statistical Summary Table
try:
print(model.summary())
except:
print("Summary does not exist for this model.")**def get_residual_properties(model):**
"""
Plots and displays variance of residuals
"""
*#### Residuals ----*
try:
plot_data = exp.plot_model(
model,
plot="residuals",
return_data=True
)
resid = plot_data['data']
resid_sigma2 = (resid**2).sum()/(len(resid))
print(f"Residual Sigma2: {resid_sigma2}")
except:
print("Residuals can not be extracted for this model.")**def plot_predictions(model):**
"""
Plots out-of-sample and in-sample predictions
"""
# Out-of-Sample Forecast
exp.plot_model(model) # In-Sample Forecast
exp.plot_model(model, plot="insample")
使用 PyCaret 的 ARIMA 模型实用指南—第 2 部分
原文:https://towardsdatascience.com/understanding-arima-models-using-pycarets-time-series-module-part2-308ea7bfecf6?source=collection_archive---------10-----------------------
理解趋势术语
贾斯汀·摩根在 Unsplash 上的照片
📚介绍
在上一篇文章中,我们看到了 ARIMA 模型及其各种超参数的简要概述。我们从一个非常简单的 ARIMA 模型开始,这个模型没有表现出时间依赖性。本文将着眼于 ARIMA 模型的“趋势”部分,看看这是如何建模的,它代表了什么。
📖建议的先前阅读
本系列的前一篇文章可以在下面找到。我建议读者在继续阅读本文之前先浏览一遍。本文建立在前一篇文章中描述的概念的基础上,并且重用了前一篇文章中完成的一些工作。
使用 PyCaret 的 ARIMA 模型实用指南—第 1 部分
ARIMA 模型中的 1️⃣“趋势”概述
顾名思义,趋势决定了时间序列如何随时间变化。在 ARIMA 模型中,这可以使用下面的基本方程[1]来建模。“a”称为“截距”,“b”称为“漂移”项。“漂移”不过是直线的斜率。
图片由作者使用https://latex2png.com/
有几种方法可以用这个方程来模拟趋势。
(1)不随时间变化的趋势分量。在这种情况下,漂移“b”= 0。
(2)从 0 开始并随时间线性变化的趋势分量(零截距“A”和非零斜率/漂移“b”)。
(3)不从 0 开始并随时间线性变化的趋势分量(非零截距“A”和非零斜率/漂移“b”)。
2️⃣️使用 PyCaret 理解趋势项
为了更好地理解这个概念,我们将使用在本系列的上一部分中使用的相同数据集。回顾一下,这个数据集是一个“白噪音”数据集。详细内容可以在本文的 Jupyter 笔记本中找到(可在文章末尾找到)。
白噪声数据集[图片由作者提供]
👉步骤 1 & 2:设置 PyCaret 时间序列实验并执行 EDA
因为我们已经在上一篇文章中执行了这些步骤,所以我们不再赘述。详情请参考上一篇文章。
👉第三步:理论计算
如上所述,ARIMA 模型中的“趋势”可以用 3 种方法计算。
(1)趋势组件固定的第一种方法与上一篇文章中介绍的模型相同。因此,同样的理论计算也适用于这种情况。作为复习,预测的估计值(样本内和样本外)是训练数据集的平均值(即“a”= 176.02)。预测区间的估计值为 174.08–177.96。
(2)第二种方法将趋势分量建模为截距“a”= 0 的直线。为了从理论上对此建模,我们可以使用 scikit-learn 的线性回归模型来重新创建它。当我们最终使用 ARIMA 模型对此进行建模时,我们预计会看到相同的结果。
X_train = np.arange(len(y_train)).reshape(-1, 1)
reg = LinearRegression(**fit_intercept=False**).fit(X_train, y_train)
print(f"Expected Intercept: {reg.intercept_}")
print(f"Expected Slope: {reg.coef_}")***>>> Expected Intercept: 0.0
>>> Expected Slope: [0.85317393]***
(3)第三种方法将趋势分量建模为截距“a”不为 0 的直线。我们可以使用 scikit-learn 如下再次创建它。
X_train = np.arange(len(y_train)).reshape(-1, 1)
reg = LinearRegression(**fit_intercept=True**).fit(X_train, y_train)
print(f"Expected Intercept: {reg.intercept_}")
print(f"Expected Slope: {reg.coef_}")***>>> Expected Intercept: 175.95815015173943
>>> Expected Slope: [0.00038807]***
👉第四步:建立模型
现在,我们已经讨论了理论计算,让我们看看这些模型的实践。
**# Trend with method 1 ----**
model2a = exp.create_model(
"arima",
order=(0, 0, 0),
seasonal_order=(0, 0, 0, 0),
**trend="c"**
)**# Trend with method 2 ----**
model2b = exp.create_model(
"arima",
order=(0, 0, 0),
seasonal_order=(0, 0, 0, 0),
**trend="t"**
)**# Trend with method 3 ----**
model2c = exp.create_model(
"arima",
order=(0, 0, 0),
seasonal_order=(0, 0, 0, 0),
**trend="ct"**
)
👉第五步:分析结果
我们将重用在上一篇文章中创建的相同的助手函数来分析结果。
方法一:trend = "c"
summarize_model(model2a)
get_residual_properties(model2a)
作者图片
这些结果与我们的理论计算相符,并与上一篇文章中的结果完全相同。我们将不再详细讨论它们。您可以参考本文末尾的 Jupyter 笔记本了解更多详细信息。
方法二:trend = "t"
**summarize_model**(model2b)
**get_residual_properties**(model2b)
方法二:统计汇总[图片由作者提供]
正如我们可以看到的,模型的漂移(0.8532)与使用 scikit-learn 的理论计算相匹配。
方法 2:残差和 sigma 2[图片由作者提供]
类似地,残差 Sigma2 (~ 7777)手动计算与模型中的计算相匹配。需要注意的一点是,对于这个数据集来说,这不是一个好的模型,因为无法解释的方差(sigma2)比以前高得多。让我们也来看看预测。
**plot_predictions**(model2b)
方法 2:样本内预测[图片来源
方法 2:样本外预测[作者图片]
我们可以看到,预测(样本内)从接近 0 开始,线性增加。PyCaret 提供了交互式图表,因此用户可以放大预测的各个部分,以更详细地分析它们。例如,可以将鼠标悬停在连续的点上,注意到它们的漂移值相差 0.8532。
样本外预测是样本内预测的延续,再次以 0.8532 的斜率/漂移线性上升。
对于目光敏锐的观察者来说,这是一个细微的差别。第一个样本内预测不为 0。它从值 0.8532(漂移值)开始。你能解释一下为什么吗?
方法三:trend = "ct"
**summarize_model**(model2c)
**get_residual_properties**(model2c)
方法三:统计汇总[图片由作者提供]
我们可以看到,模型的截距(175.9578)和漂移(0.0004)与使用 scikit-learn 的理论计算相匹配。漂移如此接近 0 是意料之中的,因为这是白噪声数据。此外,我们可以看到,该模型与方法 1 中的模型之间的“拟合优度”(较低的σ2 =更好的拟合)几乎没有差异。
让我们也来看看预测。除了小斜率/漂移部分之外,它们应该与方法 1 中的非常相似。同样,PyCaret 中的交互式绘图允许轻松检查结果,如下面的缩放结果所示。
方法 3:样本外预测(缩放)[图片由作者提供]
此外,这可能是显而易见的,但值得明确指出的是,尽管方法 1 和方法 3 在这种情况下给出了类似的拟合(假设数据是白噪声),但情况并不总是如此。当数据呈现线性趋势时,与方法 1 相比,方法 3 通常会给出更好的拟合。我鼓励读者创建一个虚拟的线性数据集并尝试一下。
🚀结论
希望这个简单的模型为我们理解 ARIMA 模型中趋势部分的内部运作打下了良好的基础。在下一组文章中,我们将开始逐一介绍其他参数,并查看它们对模型行为的影响。在那之前,如果你愿意在我的社交渠道上与我联系(我经常发布关于时间序列分析的文章),你可以在下面找到我。暂时就这样了。预测快乐!
🐦推特
📘 GitHub
喜欢这篇文章吗?成为 中等会员 继续 无限制学习 。如果你使用下面的链接, ,我会收到你的一部分会员费,而不会给你带来额外的费用 。
https://ngupta13.medium.com/membership
📗资源
- Jupyter 笔记本 包含这篇文章的代码
📚参考
[1]R 中的常数和 ARIMA 模型,Hyndsight
[2] 第八章 ARIMA 模型,《预测:原理与实践》,罗布·J·海德曼和乔治·阿萨纳索普洛斯
理解音频:什么是声音,我们如何利用它。
原文:https://towardsdatascience.com/understanding-audio-what-sound-is-and-how-we-can-leverage-it-1e03d29cd7ce?source=collection_archive---------33-----------------------
使用人工智能和声音的物理属性来处理音频。
戈弗雷·尼安杰奇在 Unsplash 上拍摄的照片
音频无处不在。虽然音频处理已经存在了几十年,但人工智能和大数据的兴起让我们能够揭开音频的隐藏秘密,为企业和最终用户提供以前无法获得的见解。
更好地理解音频可以帮助我们在客户服务行业,让企业最大限度地提高客户满意度。情绪分析算法可以识别客户服务电话中客户的语气,并分析根本原因,使企业能够改变策略,以更好地支持他们的消费者。
另一个例子是美国宇航局的 SoundSee,该计划旨在为几个迷你机器人配备一系列麦克风,以监控国际空间站上的机器音频。使用人工智能,这些机器人识别违规行为,通知各方解决问题,充当系统故障的第一道防线。
在本文中,我们将探索声音到底是什么,如何测量它,以及如何使用人工智能来利用它。
那么,什么是声音呢?
简而言之,当振动的物体导致空气分子相互碰撞时,就会产生声音。这些空气分子的振荡在空气分子内产生微小的压差,这有效地产生声波。这些波也称为机械波,通过介质传播,将能量从一个位置传递到另一个位置。如果你想一想,这恰恰是为什么太空中没有声音;在真空的空间中,根本没有可以传播声音的介质。
来源:https://www . research gate . net/figure/压力-声波-空气传播 _fig2_334784649
在上图中,底部的粒子图代表了声音在空气中造成的低压和高压区域。低压区域的颗粒密度较低,高压区域的颗粒密度较高。基于这种压力差,可以生成一条曲线,在具有较高气压的区域具有峰,在具有低气压的区域具有谷。
这种声波的可视化被称为波形,它提供了关于声音的大量细节,当试图从音频中提取特征时,可以利用这些细节。其中一些最基本的功能是:
频率
在一个波中,周期是完成一个周期所需的时间(参考下图)。频率是周期的倒数,用 Hz 表示,转换为每秒的周期数。本质上,完成一个周期所需的时间越短,频率就越高,反之亦然。从视觉上看,波峰彼此靠近的波比波峰较远的波频率更高。
来源:https://www . future learn . com/info/courses/presenting-data-with-images-and-sound/0/steps/53151
但是我们如何感知频率呢?
我们对频率的感知通常用声音的音高来表示。虽然频率描述了波形循环重复率的数值度量,但音高更多的是我们用来描述声音的主观术语。频率越高,声音的音高越高,频率越低,声音的音高越低。
强度
就像频率一样,强度是理解声音构成的另一个重要维度。声强描述的是声音在一个区域内移动的声功率,单位是瓦特每平方米。声音的功率是声音在单位时间内传递能量的速率。简而言之,强度本质上是声音所转移的能量。
现在,就像频率一样,我们感知强度的方式更加主观。我们通常将强度较高的声音视为较响,强度较低的声音视为较柔和。然而,所有听众的音量并不一致。持续时间、频率和听者的年龄等混杂因素会影响声音的音量。
音色
到目前为止,我们已经讨论了两个一维声音属性:频率和强度。与这些容易量化的属性不同,音色是一种相当神秘的声音属性,它描述了赋予声音特性的众多属性。音乐家喜欢把音色描述为声音的颜色,这是一个有趣但模糊的描述。
为了探究什么是音色,我们来看一个简单的例子。想象一个小号以和小提琴相同的音高、持续时间和强度演奏一个音符。虽然这两种声音有着大部分相同的特性,但对你我来说,这两种声音听起来明显不同。将这两种声音分开的特征的组合可以称为声音的音色。
从物理世界到数字世界
现在,我们对声音的物理性质及其属性有了基本的了解,我们如何利用这些属性并进行一些音频处理呢?首先,我们需要能够将音频转换成某种数字信号,其中包含操作和处理音频所需的信息。
麦克风的工作原理:模数转换(ADC)
自然,所有音频都是模拟信号。模拟信号是时间与声音振幅的连续图,在每个无限小的时间单位内具有无限值。存储原始模拟信号几乎是不可能的,需要无限的存储空间。相反,我们以固定的时间间隔执行一系列操作来从模拟信号中提取值。这使得我们可以在一小部分内存中存储数字格式的信号,同时收集足够的数据来再现声音。这一过程称为模数转换(ADC),它使用采样和量化来收集任意给定模拟信号的有限数值。
采样:采样不是收集连续模拟信号中的每个值,而是以固定的等距时间间隔提取值。音频最常见的采样速率是 44.1 kHz,即声音每秒 44,100 个值。这个采样速率最好地允许我们提取人类听觉范围内存在的所有数据值。
量化:采样侧重于沿水平轴以固定的时间间隔提取值,而量化将波形垂直轴上的值划分为一系列固定的等距值。当在给定的时间间隔选择一个值时,量化将给定时间的精确值舍入到最接近的量化值。量化值的数量也称为分辨率,以位为单位。普通的 CD 具有 16 位的位深度或分辨率,这意味着它具有 65,500 个量化值。量化期间的位深度越高,将模拟信号转换为数字信号时的动态范围就越大。
当麦克风拾取音频时,麦克风内部的振膜振动,形成模拟信号,该信号被发送到声卡。这个声卡执行 ADC,并将新生成的数字信号发送到计算机进行操作或处理。
利用人工智能进行音频处理
我们知道什么是音频,以及如何将音频从物理格式转换成数字格式,但我们如何利用它做任何事情呢?虽然有各种不同的方法来处理音频,但我们将专注于人工智能如何渗透到音频领域,让我们更好地理解、增强和再现音频。
虽然我们不会详细讨论如何在音频处理中实现人工智能,但我们将讨论人工智能应用于音频的不同方式。
整体而言,人工智能是指计算机能够完成通常比一系列逻辑过程需要更高智能水平的任务。深度学习是人工智能的一个子集,模仿人脑的复杂算法本质上是从海量数据中学习。
为了让深度学习算法真正提供有价值的音频见解,我们需要访问大量的音频数据。这些数据集不仅需要很大,还需要整洁有序。大而干净的数据集与高效的人工智能算法的完美结合将为任何人工智能过程产生最佳结果。使用这些大型数据集,人工智能模型将观察这些不同声音的属性模式,如频率、持续时间、强度和音色。
语音识别
目前,人工智能在音频领域最常见的用途之一是语音识别。亚马逊 Alexa、谷歌 Home 和苹果的 Siri 等个人助理都利用人工智能将一个人的语音转换为文本,理解他们请求的含义,并产生听觉响应。
语音/音乐合成
语音识别只是 AI 在音频行业带来的机会的一小部分。目前,研究人员正在实现能够完全从零开始创造声音的人工智能模型。这种能力对于任何使用语音合成产生音频的文本到语音转换程序来说都是非常有用的。深度学习模型在数百小时的演讲及其抄本上进行训练。最终,他们学会了每个单词和字符听起来如何与他们的上下文相关,并能在给定一段文本时产生语音。
同样,人工智能正被用于音乐行业,在给定一组参数的情况下制作复杂的音乐作品。音乐合成的一个很好的例子是谷歌最近的 Blob Opera 应用程序,不管用户组织 Blob 的方式如何,它都能产生美妙的声音和声。
语音增强
它不止于此。我们可以使用人工智能来智能地操纵数字音频,以改善现有的音频,满足我们的需求。例如,人工智能可以用于通过从一些音频中删除任何背景噪音或不必要的人工噪声来创建更干净的语音。音频超分辨率是音频增强的另一个方面,它允许我们通过增加保真度来显著增强低质量的音频。所有这些功能都可以改善通话过程中的音频质量,并提高录制不佳的音频的清晰度。
结论
今天,我们讲述了什么是声音以及声音背后的物理原理。具体来说,我们研究了声音的频率、强度和音色。理解声音和波形的属性对于构建更好的人工智能声音处理算法至关重要。
这个行业的潜力是无限的,随着越来越多的研究人员和开发人员认识到这一前景,我们可以期待在每个行业都看到人工智能音频处理。
感谢您花时间阅读本文。一如既往,我感谢您的任何意见/反馈。
最初发表于 Audo AI 。
了解自相关
原文:https://towardsdatascience.com/understanding-autocorrelation-ddce4f0a9fda?source=collection_archive---------18-----------------------
乔纳森·丹尼尔斯在 Unsplash 上拍摄的照片
及其对数据的影响(举例)
T4:最近我一直在处理自相关数据。在金融领域,某些时间序列(如房价或私人股本回报率)是出了名的自相关。正确考虑这种自相关对于构建稳健的模型至关重要。
一、什么是自相关?自相关是指过去的观察对当前的观察有影响。例如,如果你可以使用苹果公司上周的回报来可靠地预测其本周的回报,那么你可以说苹果公司的股价回报是自相关的。用数学术语来说:
y = B0 + B1*y_lag1 + B2*y_lag2 + ... + Bn*y_lagn + errorIf any of B1 to Bn is significantly nonzero, then we can say that the time series represented by y is autocorrelated.
我们为什么要关心自相关?
我想到两个原因:
- 许多事情都是自相关的。因此,当我们试图通过构建模拟(例如经济的蒙特卡罗模拟)来研究世界时,我们需要将自相关性考虑在内。否则我们的模型会产生错误的结果(原因见原因 2)。
- 自相关导致波动性被低估,尤其是在复合时。自相关随机变量的复合乘积,即(1+r1)*(1+r2)…可以比没有自相关的随机变量具有更宽的结果分布。
通货膨胀数据的例子
我们用一些实际数据来研究一下这个。我从 FRED(圣路易斯美联储银行的数据仓库)下载了一些 CPI 数据。看起来是这样的:
CPI(资料来源:圣路易斯美联储银行,图片由作者创作)
每当分析像 CPI 这样的时间序列数据时,你应该从变化率开始(使其更加平稳)。让我们这样做:
Here's what my raw CPI data looks like (stored in df):values
date
1950-01-01 23.51
1950-02-01 23.61
1950-03-01 23.64
1950-04-01 23.65
1950-05-01 23.77
1950-06-01 23.88
1950-07-01 24.07
1950-08-01 24.20
1950-09-01 24.34
1950-10-01 24.50# My CPI data is stored in a dataframe called df
# The following line calculates the monthly rate of change
df_chg = (df/df.shift(1)-1).dropna()
结果看起来像这样(有一些明显的季节性,我们今天将忽略):
CPI 月度变化(来源:圣路易斯美联储银行,图表由作者创作)
我们可以通过观察 CPI 的月度变化与其滞后值的相关性来检查自相关性。我们可以使用移位方法来创建滞后。
df_chg.rename({'values': 'unlagged'}, axis=1, inplace=True)lags = 10for i in range(lags):
if i > 0:
df_chg['lag_'+str(i)] = df_chg['unlagged'].shift(i)
绘制 CPI 变化的未标记值与其各种滞后之间的相关性,我们看到存在显著的自相关性:
大量的自相关(由作者创建的图形)
忽略自相关,风险自负
Let’s do a quick simulation to see what happens if we ignore autocorrelation. The monthly change in inflation has a standard deviation of 0.32%. If it were a normally distributed random variable, we can annualize the 0.32% by multiplying it by the square root of 12 (because we are going from monthly to annual) — which gives us an annualized standard deviation of 1.11%. That’s a pretty low standard deviation and would imply that extreme events such as hyperinflation are virtually impossible.
The following code simulates a year’s worth of inflation 10,000 times so we can look at the difference in outcomes between including autocorrelation and ignoring it.
# c is the regression constant, a.k.a. the mean value
# we will set c to zero to simplify things
c = 0# List to store autocorrelated simulation results
auto_correl_list = []
# List to store normally distributed simulation results
normal_list = []# Run 10,000 scenarios
for sims in range(10000):
# In each scenario, generate 12 months of "inflation"
shocks = np.random.normal(0, target_vol, (12,))
y_list = []
# This loop takes the 12 shocks and adds autocorrelation
for i, e in enumerate(shocks):
if i == 0:
y = c + betas[0]*0 + betas[1]*0 + e
y_list.append(y)
elif i == 1:
y = c + betas[0]*y_list[i-1] + betas[1]*0 + e
y_list.append(y)
else:
y = c + betas[0]*y_list[i-1] + betas[1]*y_list[i-2] + e
y_list.append(y)
# Calculate the compounded products
auto_correl_list.append(((pd.Series(y_list)+1).cumprod()-1).iloc[-1])
normal_list.append(((pd.Series(shocks)+1).cumprod()-1).iloc[-1])
Let’s take a look at the distribution of outcomes. Look at how much wider the autocorrelated version (in blue) is than the normal (in orange). The simulated standard deviation of the normal (the standard deviation of the orange histogram) is basically what we calculated earlier — 1.11%. The standard deviation of the autocorrelated version is 7.67%, almost seven times higher. Notice also that the means for both are the same (both zero) — autocorrelation impacts the variance but not the mean. This has implications for regression, which I will cover in a future article.
Finally, let’s talk a bit about why this occurs. When something is autocorrelated (and the correlation coefficients are positive), it’s much more susceptible to feedback loops. Trends tend to snowball — for example, in cases where the last few observations were high, the next observation tends to be high as well because the next is heavily impacted by its predecessors.
We can see this snowball effect by looking at a few of the individual paths from our CPI simulation (this time simulated out to 60 months instead of just 12). In the autocorrelated version, once things get out of hand, it tends to stay that way, either going to the stratosphere or to -100%.
Feedback loops can produce extreme results (Graphic created by author)
The normal version of our CPI simulation fails to capture this snowball effect and therefore understates the range of possible outcomes:
Assuming no autocorrelation understates volatility (Graphic created by author)
Which is closer to reality? My autocorrelated simulation definitely overstates the likely range of outcomes for inflation — it’s a simple simulation that fails to account for some of inflation’s other properties such as mean reversion. But without autocorrelation, you would look at your simulation results and assume that extreme phenomena like hyperinflation or persistent deflation are statistical impossibilities. That would be a grave mistake.
If you liked this article and my writing in general, please consider supporting me by signing up for Medium via my referral link here. Thanks!
理解时间序列分析中的自相关
原文:https://towardsdatascience.com/understanding-autocorrelation-in-time-series-analysis-322ad52f2199?source=collection_archive---------6-----------------------
对于初学者来说,理解自相关是如何工作的是非常重要的,这样可以使他们的时间序列分析之旅更加容易。
克里斯·利维拉尼在 Unsplash 上的照片
两年前我开始了我的时间序列分析之旅。最初,我开始通过 YouTube 视频学习,在那里我遇到了自相关,这是时间序列分析的一个基本概念。根据一些视频,自相关的定义是时间序列与其先前版本的关系/相关性。很少有人说,因为我们需要两个变量来计算相关性,但在一个时间序列中我们只有一个变量,我们需要计算时间序列与其自身第 k 个滞后版本的相关性。
什么是第 k 个滞后?
这是我想到的第一个问题。随着我的继续,我知道了一个有第 k 个滞后的时间序列(y)是它在时间上落后第 t-k 个周期的版本。具有滞后(k=1)的时间序列是原始时间序列在时间上落后一个周期的版本,即 y(t-1)。
这些视频大多以股票市场每日价格为例来解释时间序列分析。这些价格每天都有记录。他们解释说,股票价格的自相关性是当前价格与过去“k”个时期价格的相关性。所以,具有滞后(k=1)的自相关是与今天的价格 y(t)和昨天的价格 y(t-1)的相关性。类似地,对于 k=2,计算 y(t)和 y(t-2)之间的自相关。
现在主要问题来了
我们如何计算今天的价格与昨天的价格的相关性(甚至协方差)?因为相关性只能在具有多个值的变量之间计算。如果我试图计算两个单值之间的相关性,我会得到一个“NaN”。另外,这两个变量必须有相同的长度(值的个数),所以,我甚至不能计算 y(起点到 t)和 y(起点到 t-1)之间的相关性。
然后,我开始寻找自相关的理论解释,偶然发现了如下所示的自相关公式。
作者图片
作者图片
理解公式
- 自相关公式与相关公式相似(但不完全相同)。
- 分子类似于时间序列的当前版本和滞后版本之间的协方差(但没有“N-1”作为分母)。对分子的两个组成部分进行更仔细的检查表明,从它们中减去的是原始时间序列的平均值,即 mean(y),而不是分别减去 mean(y(t))和 mean(y(t-k))。这使得公式的分子与协方差有点不同。
- 分母类似于原始时间序列的标准差(也称为方差)的平方(但没有“N-1”作为分母)。
让我们来回答这个问题,如何计算自相关?通过用 Python 实现它
我们将使用 Nifty(跟踪 50 只股票的印度股票指数)从 2007 年 9 月 17 日到 2021 年 7 月 30 日的收盘价数据。这些数据以 csv 格式从雅虎财经下载。我们将首先为时间序列分析准备数据。
俏皮的时间序列情节(作者图片)
我们将定义一个名为“autocorr”的函数,通过将时间序列数组和第 k 个滞后值作为输入,返回单个滞后的自相关(acf)。此函数将嵌套在另一个名为“my_auto_corr”的函数中,该函数通过调用“autocorr”函数来计算每个滞后值的 acf,从而返回滞后[k,0]的 acf。
让我们通过传递‘nifty’时间序列数据帧和 nlags=10 作为参数来调用‘my _ auto _ corr’函数。我们还将比较' my_auto_corr '函数和' statsmodels '的' acf '方法的输出。
作者图片
“my_auto_corr”的结果与“statsmodels”的“acf”方法的结果相同。让我们再来看一下我们之前看到的自相关公式,并试着去理解它。
作者图片
- 分母非常简单,它类似于原始时间序列的方差,但分母中没有“N-1”。它在代码中用‘分母’变量来表示。
- 如前所述,分子类似于时间序列的当前版本和滞后版本之间的协方差(没有 N-1 作为分母)。让我们来了解一下如何计算分子。
作者图片
- 棕色矩形代表分子第一部分的 y(t) 。从原始时间序列的平均值中减去 mean(y) 。第一部分由公式中的代码& y(t)-mean(y)中的‘分子 _ P1’表示。 y(t)固定在底部,滞后(k)每增加一个单位,其顶部向下移动 1。
- 同样,绿色矩形代表分子第二部分的 y(t-k) 。它也是从原始时间序列的平均值中减去的, mean(y)。第二部分由代码& y(t-k)中的‘分子 _ p2’——公式中的均值(y)表示。y(t-k)在顶部是固定的,滞后(k)每增加一个单位,其底部就向上移动 1。
然而,正如我们前面看到的,公式的分子与协方差并不完全相同。然而,分母类似于原始时间序列的方差,但分母中没有“N-1”。因此,计算棕色和绿色矩形的协方差并除以原始时间序列的方差并不能得到自相关系数。
将自相关公式分解成片段并在 Python 中实现有助于我们更好地理解它。我们看到了分子中的协方差是如何在时间序列的当前版本和滞后版本之间计算的。因此,为了更好地理解一个概念,无论是机器学习算法还是统计学中的一个概念,了解其本质是很重要的。
理解反向传播
原文:https://towardsdatascience.com/understanding-backpropagation-abcc509ca9d0?source=collection_archive---------5-----------------------
允许神经网络学习的方程的可视化推导
(图片由作者提供)
在最基本的情况下,神经网络获取输入数据并将其映射到输出值。无论你看的是图像、文字还是原始的数字数据,网络看到的都是数字,它只是在这些数字中寻找模式。输入数据通过权重矩阵进行过滤,权重矩阵是网络的参数,其数量可以是数千到数百万或数十亿。微调这些权重以识别模式显然不是任何人想做或能做的任务,因此设计了一种方法来做这件事,几次,但最著名的是在 1986 年[1]。该方法采用神经网络输出误差,并通过网络反向传播该误差,确定哪些路径对输出具有最大影响。这当然是反向传播。
反向传播识别出哪些路径对最终答案更有影响,并允许我们加强或削弱连接,以达到预期的预测。这是深度学习的一个基本组成部分,它总是会在你选择的包中为你实现。所以你真的可以在一无所知的情况下创造出令人惊叹的东西。同样徒劳的是,你也可以像我们许多人一样驾驶你的汽车,而丝毫不知道发动机是如何工作的。你不必去想它,仍然可以毫无问题地驾驶……直到你在路边抛锚。那你肯定希望你能明白引擎盖下发生了什么。
那辆坏掉的车,或者用现在的比喻来说,坏掉的模型把我带到了这一步。我需要理解,所以我开始挖掘,快速的维基百科搜索很快揭示了神经网络如何学习的内部工作原理:
本质上,反向传播将成本函数的导数的表达式评估为从左到右的每层之间的导数的乘积——“向后”——每层之间的权重梯度是部分乘积的简单修改(“向后传播误差”)。"
你说什么?我喜欢维基百科,但这是一个严重的拗口。很快就变得很清楚,反向传播不是一个简单的概念,确实需要一些认真的努力来消化将扔给你的概念和公式。虽然在你亲自动笔之前,你永远不会完全理解某些东西,但这里的目标是提供一种资源,使这样一个至关重要的概念更容易被那些已经在使用神经网络并希望“在引擎盖下达到顶峰”的人所理解。基本面不应该隐藏在公式的面纱后面,如果只是以一种连贯的方式呈现,将呈现一个路线图,而不是一个路障。
在理解反向传播的情况下,我们得到了一个方便的视觉工具,实际上是一张地图。这张地图将直观地引导我们完成推导,并把我们带到最终目的地,反向传播公式。我所指的图是神经网络本身,虽然它不遵循与计算图相同的约定,但我将以大致相同的方式使用它,并将它称为计算图,而不是图,以将其与更正式的图结构区分开来。这种视觉方法只有在读者能够看到过程发生时才真正受到启发,在一系列步骤中写下来会遇到常见的陷阱,即生成一大堆公式,其中的联系不是立即可见的,读者会不知所措。需要说明的是,我们最终仍然会得到许多公式,这些公式本身看起来令人生畏,但是在观察了它们演化的过程之后,每个公式都应该是有意义的,事情变得非常系统化。
这里用来传达这种视觉信息的工具是 manim,这是一个数学动画库,由来自 3Blue1Brown YouTube 频道的 Grant Sanderson 创建。我还必须从他的神经网络系列的网络类中使用一些代码。如果你不熟悉他的频道,帮自己一个忙,去看看吧( 3B1B 频道)。虽然 manim 是我选择的工具,但它不是最容易的,在某种程度上介于“我已经走得太远了,现在不能停下来”和“我已经超出了我的能力范围”之间。我可能后悔这个决定,但我们在这里。如果你刚开始学习神经网络和/或需要复习前向传播、激活函数之类的东西,请参见[参考中的 3B1B 视频。2 获得一些立足点。一些微积分和线性代数也会对你有很大的帮助,但是我试着解释一些基本的东西,所以希望你仍然掌握基本的概念。虽然用代码实现神经网络对理解有很大的帮助,但是你可以在没有真正理解它的情况下很容易地实现反向传播算法(至少我是这样做的)。相反,这里的重点是详细了解反向传播实际上在做什么,这需要理解数学。
网络和符号
使用一个简化的模型来说明概念,以避免过程过于复杂。使用了一个 2 输入、2 输出、2 隐藏层网络,如图 1 所示。输出节点用表示误差的 e 表示,尽管你也可以看到它们通常用 C 表示成本函数。这通常是一个函数,如均方误差(MSE)或二进制交叉熵。 E 节点是 e ₁和 e ₂.的总误差或总和与典型的神经网络布局相比,这里的主要区别在于,我已经明确地将隐藏节点分成两个独立的函数,加权和( z 节点)和激活( a 节点)。这些通常被分组在一个节点下,但是为了更清楚,这里需要单独显示每个功能。我假设我们一直在处理一个训练示例,实际上,您必须对训练集中的所有训练示例进行平均。
图 1:示例神经网络设置(图片由作者提供)
现在,成功的一半是把符号弄清楚。图 2 显示了示例网络中节点和权重的符号。上标表示层,下标表示节点。
图 2:索引符号(作者图片)
权重下标索引可能会向后显示,但在我们构建矩阵时会更有意义。以这种方式索引允许矩阵的行与神经网络的行对齐,并且权重索引符合典型的(行、列)矩阵索引。
在我们开始数学之前,最后说明一下,为了传达推导的视觉本质,我使用了 GIF。有时你可能想停止或放慢一个动画,GIF 显然不是理想的,所以也请参见附带的 YouTube 视频以更好地控制速度。
最终层方程
反向传播的最终目的是找到误差相对于网络中权重的变化。如果我们在寻找一个值相对于另一个值的变化,那就是导数。对于我们的计算地图,每个节点代表一个函数,每个边在连接的节点上执行一个操作(乘以权重)。我们从错误节点开始,一次向后移动一个节点,取当前节点相对于前一层中的节点的偏导数。每一项都链接到前一项上以获得整体效果,这当然是链式法则。
图 3:追踪 w11 的地图错误(图片由作者提供)
注意:该层上的权重仅影响₁e或₂e中的一个输出,因此在最终方程中仅出现相关误差。
在图 4 中,对从错误节点到最终层中每个权重的每条路径都进行了这种边和节点的追踪,并快速通过该路径。
图 4:追踪最终图层中剩余权重的地图(图片由作者提供)
在这一点上,我们现在有一堆公式,如果我们不做一些簿记工作,这些公式将很难保持跟踪。这意味着将术语放入矩阵中,这样我们可以更容易地管理/跟踪术语。图 5 显示了术语是如何分组的,值得注意的是 Hadamard 运算符的使用(圆圈内有一个点)。这用于元素式矩阵乘法,有助于简化矩阵运算。
图 5:将术语排列成矩阵(图片由作者提供)
矩阵符号的最终方程如图 6 所示,我用大写字母表示变量的矩阵/向量形式。右边的前两项被重新分解为一个 delta 项。当我们追踪前面的层时,这些项会重复出现,因此计算一次并将其存储为 delta 变量以备将来使用是有意义的。
图 6:最终图层的最终矩阵(图片由作者提供)
更深层
对于更深的层,同样的方法适用于两个关键的更新:1)增量项再次出现在后面的层中,因此我们将进行适当的替换;2)现在从总误差节点到感兴趣的权重将有两条路径。当多个分支汇聚在一个节点上时,我们将添加这些分支,然后继续乘以剩余的函数链。图 7 显示了第一层权重之一的过程。
图 7:第一层链规则示例(图片由作者提供)
现在,如果我们仔细观察,您会注意到重复的项,图 8 回顾了以前的层方程以及我们当前的 w₁₁ 方程,并显示了哪些项是重复的,并将它们作为 delta 因子。
图 8:在最后一层和前一层计算中找到相似的项,并将其分解为增量项(图片由作者提供)
所有后续等式都遵循相同的方法。因为这变得相当重复,并且因为我只能把这么多的长度塞进 GIF,所以在图 9 中对所有剩余的权重快速重复这个过程。
图 9:第一层剩余的渐变计算(不要眨眼)
我们又一次有了一大堆公式,我们将通过把它们输入矩阵来整理它们。一般分组遵循与第一层相同的模式。
图 10:第一层的矩阵分组(作者图片)
最左边的矩阵当然可以进一步分解,我们需要单独的 delta 值,这样我们就可以简单地插入从前一层计算的值。现在,按照图 11,您必须回忆点积,它是行乘以列,所以我们还添加了一个转置到 delta 项。
图 11:分解增量并最终确定矩阵公式(图片由作者提供)
添加矩阵符号给出最终公式
图 12:第一层的最终矩阵方程(图片由作者提供)
现在,无论激活函数是什么,图 12 中的一些导数项都是相同的。由边连接的节点产生线性输出,然后将其馈送到激活函数以引入非线性。给定函数的线性性质,找到节点函数相对于前一节点的导数是简化的,并且可以直观地确定。取 dz/da 项,这个导数告诉我们输出( z ₁)相对于输入、 a ₁.如何变化这些功能只通过边缘w₁₁连接,所以权重是唯一的方式,其中 a ₁可以改变 z ₁也就是 dz/da = w ₁₁.图 13 表示由边连接的节点,并将边值代入矩阵作为导数项的解。
图 13:节点之间连接的可视化指示和结果衍生(图片由作者提供)
对于 dz/dw 来说也是类似的情况。在这种情况下,导数是相对于边而不是节点的,但同样的逻辑成立,只有一个通过边连接的函数影响 z 节点,那就是输入(我将它标记为 x⁰,但也可以标记为 a⁰).然后,导数解可以代入图 14 的矩阵方程。
图 14:第一个节点和输入层之间连接的可视化指示,以及将导数解代入矩阵方程的结果(图片由作者提供)
我们终于有了最终层和初始层的方程。
图 15:两层网络的最终方程(图片由作者提供)
广义方程
如果你在阅读迈克尔·尼尔森的优秀在线书籍[3],他会像 3B1B [4]一样注意到一些更通用的等式。这里的方程同样可以进一步推广。这里,上标 1 表示当前层( l) ,上标 0 表示前一层 (l-1) 。顶部等式中的上标 2 指的是下一层( l+1 ),而在底部等式中,它指的是最后一层(L)…或者只看图 16 中的替换。
图 16:推广任意层深的方程(图片由作者提供)
偏见
尽管跳过偏见并告诉你这很简单并且是从上面得出的很有诱惑力,但看到它至少被解决一次确实很有帮助。因此,我将在图 17 中介绍一个例子。
图 17:描绘出一个偏向梯度(图片由作者提供)
如你所见,过程是一样的。需要注意的重要一点是,对于给定的层,除了最后一项,所有的项都与我们刚刚找到的关于给定权重的方程相同。最后一项只是偏差,其值为 1(偏差权重项用于调整偏差)。这使我们能够相对容易地简化和推广偏置方程,如图 18 所示。
图 18:归纳偏见术语(作者图片)
将所有方程组合起来,我们就得到矩阵形式的最终广义方程组。
图 19:最终的反向传播方程(图片由作者提供)
结束语
如果一张图片胜过千言万语,那么一打以上的 GIF 肯定更有价值(或者你可能再也不想看到另一张 GIF 了)。我真的希望这有助于阐明一个棘手的概念。如果你喜欢这个,我希望很快会有更多的内容。这篇文章实际上是我的原始项目的一个迂回,我的原始项目是建立一个单一的拍摄对象探测器,在几个点上打破了导致我进入这个兔子洞。
与本文相关的其他资源:
- Github 链接到源代码
- 随行的 YouTube 视频
参考
[1] D. Rumelhart,G. Hinton 和 R. Williams,通过反向传播错误学习表征 (1986),自然
[2] G. Sanderson,但是什么是神经网络呢?深度学习,第一章 (2017),3Blue1Brown
[3] M. Nielsen,神经网络与深度学习—第二章,决心出版社 2015
[4] G. Sanderson,反向传播微积分——深度学习,第 4 章 (2017),3Blue1Brown
贝多芬定理是我用过的一个 YouTube 频道,里面有很多关于使用 Manim 的有用视频。
理解人工智能系统中的偏见和公平
原文:https://towardsdatascience.com/understanding-bias-and-fairness-in-ai-systems-6f7fbfe267f3?source=collection_archive---------8-----------------------
公平和偏见
对关键问题的一些基本概念的图解介绍
当人工智能成为头条新闻时,往往是因为偏见和公平的问题。一些最臭名昭著的问题与面部识别、警务和医疗保健有关,但在许多行业和应用中,我们已经看到了机器学习在创造一个一些群体或个人处于不利地位的社会方面的失误。那么,我们如何开发人工智能系统来帮助做出导致公平和公正结果的决策?在 Fiddler,我们发现它始于对人工智能中的偏见和公平的清晰理解。因此,让我们用一些例子来解释我们使用这些术语的意思。
如果你更喜欢看视频而不是读文章,看看这个视频吧!此外,视频中有一些我在本文中提到的偏见类型的具体、真实的例子。
AI 中的偏见是什么?
偏差可以以多种形式存在,并且可以在模型开发流程的任何阶段引入。从根本上来说,偏见存在于我们周围的世界,并被编码到我们的社会中。我们无法直接解决世界上的偏见。另一方面,我们可以采取措施从我们的数据、我们的模型和我们的人工审查过程中剔除偏见。
作者图片
数据偏差
数据中的偏差有几种表现形式。以下是罪魁祸首:
历史偏见是世界上已经存在的偏见,已经渗透到我们的数据中。即使给定完美的采样环境和特征选择,这种偏差也可能发生,并且倾向于出现在历史上处于不利地位或被排斥的群体中。2016 年的论文“男人对于计算机程序员就像女人对于家庭主妇”说明了历史偏见,该论文的作者表明,在谷歌新闻文章上训练的单词嵌入展示了事实上延续了社会中基于性别的陈规定型观念。
表示偏差稍有不同——这发生在我们定义和抽样人口以创建数据集的方式上。例如,用于训练亚马逊面部识别的数据大多基于白人面孔,导致检测深色皮肤面孔的问题。代表性偏差的另一个例子是通过智能手机应用程序收集的数据集,这最终可能会低估低收入或老年人口的代表性。
测量偏差发生在选择或收集用于预测模型的特征或标签时。容易获得的数据通常是实际特征或感兴趣标签的嘈杂代理。此外,测量过程和数据质量往往因群体而异。随着人工智能被用于越来越多的应用,如预测性警务,这种偏见可能会对人们的生活产生严重的负面影响。在 2016 年的一份报告中,ProPublica 调查了预测性警务并发现,在预测累犯(某人将再次犯罪的可能性)中使用代理测量可能会导致黑人被告比白人被告因同样的罪行获得更严厉的判决。
建模偏差
即使我们有完美的数据,我们的建模方法也会引入偏差。这有两种常见的表现方式:
评估偏差发生在模型迭代和评估期间。使用训练数据来优化模型,但是它的质量通常是根据某些基准来衡量的。当这些基准不代表总体,或者不适合模型的使用方式时,就会产生偏差。
聚合偏差在模型构建过程中出现,不同的群体被不恰当地组合在一起。在许多人工智能应用中,感兴趣的群体是异质的,单一模型不可能适合所有群体。医疗保健就是一个例子。为了诊断和监测糖尿病,模型在历史上使用血红蛋白 AIc(hba1c)的水平来进行预测。然而,2019 年的一篇论文显示,这些水平在不同种族之间以复杂的方式存在差异,适用于所有人群的单一模型必然会出现偏差。
人类评论中的偏见
即使您的模型做出了正确的预测,当人类评审员决定是接受还是忽略模型的预测时,他们也会引入自己的偏见。例如,一个人类评审员可能会基于他们自己的系统偏差推翻一个正确的模型预测,说一些大意为“我知道那个人口统计,他们从来没有表现得很好。”
什么是公平?
在许多方面,人工智能中的偏见和公平是一个硬币的两面。虽然公平没有普遍认同的定义,但我们可以广义地将公平定义为没有基于个人或群体特征的偏见或偏好。记住这一点,让我们看一个机器学习算法如何遇到公平问题的例子。
人工智能示例中的公平性
假设我们创建了一个二元分类模型,我们相信我们有非常准确的预测:
作者图片
如果这个数据实际上包括两个不同的潜在群体,一个绿色群体和一个蓝色群体,那么公平性就会受到质疑。这些组可以代表不同的种族、性别,甚至是地理或时间上的差异,比如早晚用户。
作者图片
这种公平性问题可能是聚合偏差的结果,就像前面提到的将糖尿病患者作为一个同质组进行治疗的例子一样。在这种情况下,对这两类人群使用单一阈值会导致不良的健康结果。
最佳实践
为了公平地解决这个问题,最佳实践是确保您的预测对每个组都经过了校准。如果你的模型的分数没有针对每一组进行校准,很可能你系统地高估或低估了你的一个组的结果的概率。
除了组校准之外,您可以决定为每个组创建单独的模型和决策界限。对于我们这些群体来说,这比单一门槛更公平。
作者图片
然而,创造额外的门槛会导致一个新的问题:个人公平。在下面的图表中,黑色箭头指向蓝色和绿色的个体,它们拥有非常相似的特征,但被 AI 系统完全不同地对待。正如你所看到的,在群体公平和个人公平之间经常存在一种紧张关系。
作者图片
如图所示,人工智能中的偏见和公平是一个发展中的领域,越来越多的公司,尤其是受监管行业的公司,正在加大投资,以建立治理良好的实践。在以后的帖子中,我将介绍更多关于公平的概念,包括交叉公平,并展示如何使用不同的度量来解决这些问题。
参考文献:
鲁本·宾斯。论个体公平与群体公平的表面冲突。更正,abs/1912.06883,2019。网址 http://arxiv . org/ABS/1912.06883。
乔伊.波伦维尼和蒂姆尼特.格布鲁。性别差异:商业性别分类的交叉准确性差异。在公平、问责制和透明度会议上,第 77-91 页,2018 年。
Ninareh Mehrabi、Fred Morstatter、Nripsuta Saxena、Kristina Lerman 和 Aram Galstyan。机器学习中的偏见和公平问题综述。更正,abs/1908.09635,2019。网址http://arxiv.org/abs/1908.09635。
理解偏差:神经科学&伦理人工智能的关键理论
原文:https://towardsdatascience.com/understanding-bias-neuroscience-critical-theory-for-ethical-ai-de7a31db6c05?source=collection_archive---------32-----------------------
公平和偏见
将批判理论框架应用于 AI 伦理学,同时使用神经科学来理解具有突触可塑性的无意识偏见。
照片由乔希·里默尔在 Unsplash 拍摄
一年前,当讨论面部识别中存在的种族偏见时,人工智能先驱严乐存在推特上引起了争议,“当数据有偏见时,ML 系统就会有偏见”(来源:推特)。这激起了人工智能伦理研究员 Timnit Gebru 的回应,她对这个问题过于简单的框架表示失望,这是基于她在人工智能伦理方面的专业知识的观点(来源:Twitter )。Gebru 的回答和随后的对话被主流媒体放大,虽然这确实在人工智能社区引发了更广泛的偏见讨论,但媒体的焦点是 Lecun 选择如何(错误)沟通。
抛开诚意不谈,乐存的道歉(来源)让我想起了奥德·洛德关于内疚的想法,
“太多时候,它变成了一种保护无知和事物延续现状的手段,是对永恒性的终极保护。”(洛德,1981 )。
关于被边缘化的人应该负责教育他人偏见的合理期望,Lorde 说,
“我们的精力不断流失,而这些精力本可以更好地用来重新定义我们自己,并设计出改变现在、建设未来的现实情景。”(洛德,1980 )。
我和格布鲁一样沮丧。社会偏见渗透到人工智能的每一个方面,从数据集,研究环境,甚至从业者本身。一个公平的未来取决于我们创造道德人工智能的能力;因此,我认为批判性地反思的偏见是很重要的——尽管这在情感上是多么困难,尽管没有简单的答案。此外,讨论偏见而不解决社会和结构问题是一种空洞的、最终毫无意义的努力。因此,我寻求将批判理论与神经科学相结合,以理解无意识偏见,并绘制出一条通往伦理人工智能的道路。
在一个由两部分组成的系列中,我从神经科学、遗传学、心理学、批判理论、语言学、数学和教育学等不同领域中汲取经验,阐述我的观点,即人工智能伦理学可以受益于结合各种学科的非常规方法。这第一篇文章使用神经科学来理解无意识偏见,同时与人工智能建立直接联系,所有这些都在一个关键的理论框架内。第二篇文章探索了关于神经科学的学习,并提出了一个基于关键理论的因果关系观点,允许讨论神经符号人工智能,作为一种潜在实现机器正念的方式。
在这里,我从批判理论开始,并将该领域与 STEM 学科进行对比,以表明人工智能从业者可以从交叉性的思考中受益。接下来,我将简要介绍神经科学,并强调特定子学科之间的重要差异以及它们与人工智能的关系。这直接导致了对突触可塑性的讨论,这为讨论本文的中心话题无意识偏见奠定了基础。接下来,我用批判理论解决了数据集中的偏见问题。最后,我回到我以前的语言学系列(第 1 部分 & 第 2 部分),并使用人工智能语言模型中的偏见作为一个实际例子来展示神经科学和批判理论与人工智能伦理的联系。
批判理论与人工智能伦理
很久以前,我被介绍给那些帮助我形成对世界的看法的作家:奥德·洛德、玛娅·安杰洛、贝尔·胡克、奥克塔维亚·巴特勒和安吉拉·戴维斯。我相信我姐姐的影响;与此同时,她也分享了批判理论家的作品,如弗朗兹法农,爱德华·萨义德,保罗·弗莱雷和米歇尔福柯。虽然批判理论有时被狭隘地定义为法兰克福学派,但我支持批判理论的更广泛的观点,其中学科的目的是旨在减少压迫和增加自由的社会调查。引用福柯的话来说,这需要挑战传统的权力结构,
“批判并不在于说事情不像现在这样好。它在于看清公认的做法是基于什么样的假设、熟悉的概念、既定的和未经检验的思维方式……进行批评就是使那些现在太容易的行为变得更难。”(福柯,1982 )。
STEM 学科中流行的态度要么是对批判理论的无知,要么是对批判理论的蔑视;这个领域被普遍认为在智力上不如纯科学。流行的观点包括宣称“事实胜于感觉”的优越性。考虑非经验主义主张的价值已经变得激进,数据的缺乏足以成为否定整个学科的理由。我不同意这种观点,而是选择接受批判理论有价值的激进观点,特别是在涉及到人工智能新兴领域的发展时。具体来说,创造道德人工智能的尝试将受益于对交叉性的理解(克伦肖,2017 )。偏见不仅仅是种族主义、性别不平等或宗教不容忍,它是所有形式的偏见相互作用的结果。
1989 年,金伯利·克伦肖创造了“交叉性”这个术语,试图描述社会身份相互作用的复杂方式。如今,这一含义被那些受到当前社会等级丧失威胁的人扭曲了,被嘲笑和斥为“身份政治”。然而,根据克伦肖自己的说法,
“一个透镜,一个棱镜,让我们看到各种形式的不平等是如何相互作用、相互加剧的。我们倾向于将种族不平等与基于性别、阶级、性取向或移民身份的不平等区分开来。人们经常忽略的是一些人是如何受到所有这些的影响,而这种体验不仅仅是其各个部分的总和。”(来源)。
人工智能已经在许多人生活的许多方面交织在一起;这是一个不断增长的趋势,因为人工智能的使用在各个行业都在增加。在 2018 年的一本书中,*人工智能超级大国:中国,硅谷和新的世界秩序,*人工智能先驱和风险投资家李开复将人工智能的现状描述为处于“实施时代”。在谈到人工智能的潜在危害时,李开复说,
“[b]将它们推向市场不需要人工智能研究的重大新突破,只需要日常实施的具体工作:收集数据、调整公式、在实验和不同组合中迭代算法、制作产品原型,以及对商业模式进行实验。”(李,2018 )。
李对人类与人工智能共存的愿景是基于促进彼此的爱;他建议将爱作为设计社会项目的蓝图,以对抗人工智能未来的生存威胁。虽然我同意爱情的重要性,但我认为他的观点所缺乏的是对当前对我们共同人性的生存威胁的理解,这种根深蒂固的系统性和结构性不平等正是人工智能产生的根源。
伦理人工智能需要不仅仅是确保像 GPT-3 这样的语言模型不会反刍种族主义文本,或者面部识别可以识别不同的面孔。一个鼓舞人心的例子是强有力的纪录片 《编码偏见 ,它始于 Joy Buolamwini 和 Timnit Gebru 撰写的一篇论文,题为“ 性别阴影:商业性别分类的交叉准确性差异 ”。交叉性和批判理论的影响贯穿整部电影。这一点在让所有利益相关方参与进来的努力中尤为明显,尤其是那些目前受到面部识别技术负面影响的利益相关方。重要的是,研究人员咨询了受影响的人,并将他们纳入了围绕伦理人工智能的讨论。更重要的是,这项工作正在持续进行,并朝着让研究变得可及的方向不断努力,我希望所有参与人工智能伦理的研究人员和组织都能采用这种方法。
整个人工智能行业、政府,尤其是人工智能从业者,应该提出交叉性的问题。问题如:谁研究、构建和教授 AI?谁能接触到,谁从中获利,谁的工作被 AI 服务取代?谁生产,谁拥有用于构建人工智能的数据?谁控制着 AI 所需的基础设施?。更广泛地说,谁对艾的意见被听到了?谁来决定围绕 AI 的法律,谁来执行这些法律?哪些国家有能力研究或建设人工智能,它将被部署在哪里?哪些国家的经济会因 AI 而受益或受损?。这些问题仅仅触及了表面,但目前那些有能力实施变革的人并没有讨论这些问题。
理解交叉只是朝着正确方向迈出的一步;然而,这是一个包括所有人在内的容易实现的目标。女权主义者。AI 是一个通过交叉女权主义参与进来的组织,致力于让每个人都能接触到 AI——他们的资源页面是一个开始学习的好地方。他们推荐的一些书籍包括:萨菲亚·乌莫哈·诺布尔的 压迫算法 、凯茜·奥尼尔的 数学毁灭武器 以及鲁哈·本杰明的 科技之后的种族 。当前的数据科学、机器学习和人工智能教育计划将受益于将这些材料纳入他们的课程,为学生提供人工智能伦理的交叉框架。我不自称在批判理论或交叉性方面有专长,但这些想法是帮助我批判性思考人工智能的基础。作为起点,交叉性提供了希望,随着人工智能的发展,我们不会把那些拥有最少而可能受益最多的人抛在后面。如上所述,接下来的两个部分介绍了神经科学和无意识偏见,然后在最后两个部分回到批判理论,进一步讨论人工智能的发展和伦理。
神经科学:精选分支学科概述
神经元是构成人脑结构的细胞单位,这是 Santiago Ramón y Cajal 在 19 世纪 80 年代发现的事实( Rapport,2006 )。目前认为,人类大脑包含大约 860 亿个神经元,每个神经元大约有 10,000 个突触——这些可以被认为是神经元之间的连接。这篇来自《约翰·霍普斯金医学》的有用文章提供了一个大脑解剖和功能的简单概述。为了便于理解,本文中介绍的所有神经科学概念都将有足够详细的解释,以保证没有技术复杂性的理解。
在最简单的层面上,神经科学是对神经网络如何工作的研究,与研究大脑疾病的神经学形成对比。神经科学有几种类型或子学科,这里我重点介绍与人工智能最相关的三种:系统神经科学、认知神经科学和计算神经科学。系统神经科学与系统生物学相关,后者涉及复杂生物系统的计算和数学建模。因此,系统神经科学包括在分子和细胞水平上研究大脑,然后将这种理解与认知功能(如记忆存储和语言)联系起来。这一分支学科对人工智能很有用,因为它采用了研究物理大脑的方法来理解思维,例如,大脑的物理结构如何与意识相关联。
认知神经科学采取了相反的方法,它受心理学的影响很大,并依靠理解心灵(认知)来帮助理解大脑。例如,它采用记忆的心理学分类,通过使用情景、语义和程序记忆的定义。关于人工智能,一个关键的概念是意识的神经关联,它可以被定义为与特定意识体验相关的大脑活动的特定模式。例如,考虑强化学习,决策的神经关联表明,大脑的额叶皮层通过添加情景记忆的上下文进行干预,这样决策就受到了过去事件的影响。认知神经科学也与符号人工智能领域直接相关,其中智能被设计为根据因果规则通过逻辑运算操纵符号。
除了认知神经科学,符号 AI 植根于数学的哲学;它遵循基于逻辑主义的观点,即人类的认知是通过形成内部符号表示和创建处理这些概念的规则来实现的。所以,有了符号化的 AI,机器认知就是以一种机器拥有世界知识的方式,将这些因果规则形式化的结果。作为一名哲学家和数学家,伯特兰·罗素是逻辑主义的坚定捍卫者,他认为数学可以还原为逻辑。符号逻辑的建立可以归功于罗素;1910 年,他出版了《数学原理》,提出了一个公理系统,所有的数学都可以建立在这个系统上。
二十年后,库尔特·哥德尔提出了他的不完全性定理,证明了任何原始递归算法系统都有极限。本质上,哥德尔证明了不可能使用符号逻辑来创造一套完整一致的公理来对世界进行建模。这一缺陷延伸到符号人工智能,它在 20 世纪 50 年代和 80 年代流行,但在很大程度上被放弃,转而支持神经元的连接主义观点。神经网络。从符号人工智能向神经网络的转变反映在神经科学中,认知神经科学在 1985 年被计算神经科学的新分支超越。
虽然哥德尔的不完全性定理可以作为符号 AI 对于认知不足的数学基础,但我们仍然没有正式的数学理论来解释神经网络在实践中为什么有效。因此,计算神经科学的重要性;这个领域寻求用数学模型来理解不仅仅是认知,还有大脑的结构和发展。在这个分支学科中,有兴趣开发突触可塑性现象的数学模型,这是理解无意识偏见所需的关键神经科学概念。接下来的部分涵盖了这一点,本系列的第二篇文章更详细地涵盖了计算神经科学。
突触可塑性和无意识偏向
突触可塑性,有时也被称为神经可塑性,由唐纳德·赫布于 1949 年首次提出(来源)。这个想法是神经元之间的突触连接能够改变;这种灵活性很重要,因为活动的变化决定了突触连接的强度。突触之间的现有连接可能会消失或变得沉默。此外,新的连接可以在一对神经元突触之间的新位置形成。这意味着生物神经网络的网络结构是动态的,突触之间的连接表现出时间可塑性。
有趣的是,学习是通过调整突触连接的强度来实现的,这个想法将在本系列的第二篇文章中深入探讨。这里,突出的一点是,突触可塑性可以被视为神经元在学习过程中的适应。与此相关的是,Hebb 试图通过理论化的方法来解释突触可塑性,即突触效能的增加源于突触前细胞对突触后细胞的重复和持续刺激( Choe,2014 )。更正式地说,Hebbian 学习理论是这样一种原理,即一个突触前神经元 A,如果在它本身(神经元 A)活跃时成功地重复激活一个突触后神经元 B,将逐渐变得更有效地激活神经元 B ( Hebb,1949 )。
短期突触可塑性是指在亚秒时间尺度上发生的突触强度变化,例如强度快速增加或减少,随后连接恢复正常。另一方面,长期突触可塑性可以持续几分钟到几年,并代表了大脑将信息存储为记忆的方式(来源)。在去年发布的一本神经科学书籍: Sway:解开无意识偏见 中,Pragya Agarwal 用长期突触可塑性来解释无意识偏见。在《科学美国人》 、 发表的一篇评论文章中,Agarwal 写道:
“刻板印象等社会态度和期望会改变大脑处理信息的方式,因此基于大脑的行为特征和认知技能的差异会随着时间、地点和文化的变化而变化。这意味着我们的无意识偏见并不是天生的。它们是通过我们的经验习得的,因此也可以不学。”(阿加瓦尔,2020 )。
Agrawal 使用神经成像研究来支持她关于无意识偏见的说法,具体来说,最近的fMRI研究表明,人们在对熟悉和陌生的情况进行推理时使用了大脑的不同区域。该研究指出了大脑的两个特定部分,即杏仁核和前额叶皮层,这两个部分都对刻板印象做出反应。Agrawal 解释说,当遇到一个新的人时,我们会迅速“将行为转化为带有可识别信息的神经信号,以形成对他们的印象”。当这种情况发生时,在潜意识层面,前额叶皮层同时监控来自我们所有感官的神经信息,与社会规范或个人偏好联系起来。这意味着有意识的大脑会形成不完整的解释,并且经常会包含某种偏见,也就是说,我们的社交、记忆和经历会产生无意识的偏见。
杏仁核对于理解偏见非常重要,因为它会无意识地标记传入的刺激,因此人们会迅速将他人归类为"像我和不像我"。Agrawal 声称这是偏见和歧视的根源,这意味着固型激活了大脑中与威胁和恐惧相关的部分(杏仁核)。更具体地说,fMRI 数据显示,当人们看到“与自己不同种族背景的人的面部图像时,往往比看到相同种族的人更容易激活杏仁核。”。此外,研究表明,“群体外的负面偏见甚至比群体内的同理心更加突出。”(来源)。
虽然神经成像清楚地表明无意识偏见与杏仁核和前额叶皮层都有关,但突触可塑性提供了一种解决这两个区域偏见的方法。阿格拉瓦尔强调的要点是:就像无意识偏见是后天习得的一样,它也可以是后天习得的。在本系列的第二篇文章中,我回到了这个想法,在那里我将突触可塑性与正念冥想联系起来,提出了一种可以在机器中消除无意识偏见的方法。接下来的两节提供了偏见和人工智能发展的关键理论框架。
数据集偏差和人工智能开发
Borealis AI 的产品总监凯瑟琳·休姆(Kathryn Hume)提供了一个很好的理由来批判性地思考关于人工智能发展的无意识偏见。她说
“算法就像折射人类偏见的凸面镜,但以一种相当生硬的方式进行。他们不允许像那些我们经常用来维持我们的社会的礼貌小说”(来源)。
她进一步警告说,
“我们需要小心,因为如果我们没有很好地设计这些系统,它们将会对数据进行编码,并可能放大当今社会存在的偏见。”(来源)。
当严乐存提出人工智能中的偏见源于数据中的偏见时,他暗示数据本身是客观的,一个平衡的和种族代表性的数据集将解决这个问题。如前所述,这是一个有问题的方法,因为它天真地忽视了系统和结构的偏见。尽管如此,它提供了一个机会来更深入地挖掘数据应该被视为客观的观点。在 被压迫者教育学 中,保罗·弗莱雷暗示,主体性在改变权力结构的斗争中发挥着作用。弗莱雷指出,“没有主观性,就无法想象客观性。两者都不能脱离对方而存在,也不能一分为二。”;他提出了一种“主观和客观处于不断的辩证关系中”的方法(“T10”Freire,1970 )。
数据主观性的一个令人信服的例子是由 Northpointe 创建的用于评估被告再犯风险的 COMPAS(替代制裁的矫正罪犯管理概况)软件。2016 年 ProPublica 的一项研究揭露了算法中编码的种族偏见;该软件更有可能对黑人产生 1 型错误(假阳性),对白人产生 2 型错误(假阴性)。这意味着黑人被告被错误地分配了比白人被告更高的分数,因此在预测暴力犯罪的风险时,该算法的准确率只有 20%(来源)。COMPAS 是一种专有软件,算法的工作原理被视为商业秘密,这意味着该软件相当于一个黑匣子。假设这些算法是在一个平衡的、具有种族代表性的数据集上训练的,这将强调一点,即简单地将有色人种包括在数据集中并不能解决偏见的问题。
然而,清楚的是,当累犯风险评估工具基于诸如“你的父母之一曾经被送进过监狱吗?”(来源),偏差问题延伸到数据之外。Northpointe 的创始人、前统计学教授蒂姆·布伦南(Tim Brennan)声称,很难构建一个不包括与种族相关的项目的分数,他说,“如果这些项目从你的风险评估中被忽略,准确性就会下降”(来源)。根据 Northpointe 的披露,他们的 COMPAS 数据涵盖了贫困、失业和社会边缘化(来源)。
这些社会问题与结构性和系统性种族主义密不可分;事实上,监狱作为一种制度和犯罪本身的定义,有着种族主义的历史。革命的书里,“ 监狱过时了吗? ”,安吉拉·戴维斯考察了美国奴隶制和早期监狱系统之间的历史联系。她指出,从历史上看,在美国,种族一直在构建犯罪推定中发挥着核心作用,
奴隶制废除后,前蓄奴州通过了新的立法来修改奴隶法典,以类似奴隶制时期的方式来规范自由黑人的行为。(戴维斯,2003 年)。
Brennan 和 Northpointe 忽略了历史和当前的现实,主观地选择了数据,从而产生了编码和传播社会不公的算法。因此,将数据视为客观忽略了根深蒂固的有问题的偏见。
因此,在实践中,在收集手段、框架、包容性措施、问题的适当性、质量标准以及最重要的结构性和系统性压迫的存在方面,数据应被视为主观的。为了支持这样的调查,麻省理工学院和 MILA 大学的研究人员创建了一个数据集,用来测量人工智能语言模型中的刻板印象偏见。 StereoSet 提供了一种测量语言模型对与种族、性别、宗教和职业相关的刻板印象的偏好的方法,同时确保所使用的去偏置技术不会对潜在的模型性能产生负面影响。本文的最后一节继续讨论人工智能语言模型中的偏差;然而,请注意,这种偏见存在于所有类型的人工智能中,这些模型只是一个例子。
人工智能语言模型和语言偏见
我对自然语言处理(NLP)有着浓厚的兴趣,并且我一直在与人工智能语言模型中的偏见问题进行直接斗争。这场斗争促使我在今年早些时候写了两篇文章,使用语言学理论来探索人工智能语言模型。第一篇对比了语言相对论和语言普遍性,以更好地理解指导语言模型发展的哲学。在第一篇文章的前面,我提到了谷歌如何解雇 Timnit Gebru,因为他研究人工智能语言模型的社会和环境影响。我的第二篇关注语言学的文章直接讨论了偏见的问题;作为一个实际的例子,我主要关注令人印象深刻的大型 GPT-3 模型。引用最初的 GPT-3 论文,“[ GPT-3 ]保留了它被训练的数据的偏差。…这可能导致模型产生刻板印象或偏见的内容”。
我目前的观点是,人工智能语言模型中的偏见不仅仅是数据,结构也很重要;具体来说,语言的结构很重要。通过研究经济不确定性,我偶然发现了沃尔夫社会经济学,康奈尔大学的托马斯·佩平斯基教授将其描述为,
“一个新兴的跨学科研究领域,认为语言结构解释了跨社区的信仰、价值观和观点的差异”( Pepinsky,2019 )。
当文本被用于经济分析时,经济语境中的相关性是理解语言所带来的不确定性。M. Keith Chen ( 2013 )在美国经济评论上的先前研究也表明语言对经济行为有影响。陈认为,一种语言的未来和现在的语法联系会影响一个人的储蓄习惯(陈,2013 )。经济研究的当前趋势包括采用机器学习技术;我本人写过经济学的因果 ML,这里这里和这里。更重要的是,NLP 对经济学非常有用;因此,语言结构的重要性直接关系到人工智能对经济学的有用性。
撇开经济学不谈,既然语言的结构具有相关性,那么将语言学应用于人工智能的发展是很自然的。伦斯勒理工学院认知科学系的研究人员最近出版了一本名为“*人工智能时代的语言学”*的书,该书专注于自然语言理解的语言学方法(NLU)。令人惊讶的是,作者 Marjorie McShane 和 Sergei Nirenburg 已经开源了整本书,这本书可以在麻省理工学院出版社网站上获得。作者声称,歧义是 NLU 的一个障碍,人类的方法是利用上下文来解读单词背后的意思。然而,当前的 NLP 范式是使用非常大的数据集和单词序列之间的统计关系来确定上下文,这种方法不能捕获含义。此前,在 AI 语言模型出现之前,包含词汇结构和本体的基于知识的系统用于向机器解释语言。不幸的是,这种类型的知识工程有很高的资源成本;因此,缺乏对意义的理解的替代统计方法流行起来。"修行者的行为就好像文字足以代表他们的意思,但事实并非如此.",批判麦克沙恩(来源)。
她还声称,“在其发展的这个阶段,神经科学无法为我们承担的认知模型类型和目标提供任何令人满意的(句法或结构)支持。”。也许这是 NLU 的真实情况;然而,语言结构、突触可塑性和无意识偏见之间的联系提供了关于语言在人工智能模型中偏见编码中所起作用的见解。假设语言结构包含偏见的表达,假设这种结构直接影响大脑活动(例如,储蓄习惯),那么操纵突触可塑性可以提供一种解决人工智能语言模型中编码的偏见的方法就不难了。在本系列的第二篇文章中,我从多个角度探讨了这个观点。
最后的想法
批判理论可以帮助人工智能实践者认真思考人工智能伦理,神经科学可以提供对偏见问题的神经洞察力。简单来说,系统神经科学依赖于生物学,认知神经科学依赖于心理学和符号逻辑,计算神经科学以对生物神经网络的定量理解为中心。相关地,可以说人工神经网络(AI)的目标是在设计和功能上模仿生物神经网络。为此,突触可塑性提供了一种理解生物神经网络的方法,其机制可以扩展到改进人工神经网络。
因此,在这个系列的第二部分中,我将人类学习与机器学习进行了对比,并讨论了层次结构的概念,以将批判理论与认知联系起来。然后,我将重点放在将突触可塑性与正念冥想联系起来,这让我能够探索从错误中学习是可能的这一想法。最后,我回到符号人工智能,并介绍神经符号人工智能的新领域,它是融合不同学习范式的混合方法的代表。这为从批判理论的角度讨论因果关系创造了空间,连接到用有意识的机器创造有道德的人工智能的主要目标。
如果读者对将交叉性融入人工智能伦理学的进一步材料感兴趣,我再次推荐以下书籍:萨菲亚·乌莫哈·诺布尔的 【压迫算法】;凯茜·奥尼尔的 【数学毁灭武器】 和鲁哈·本杰明的*【科技之后的种族】* 。
对本系列提到的话题感兴趣的读者可以在 Linkedin 上与我联系。我欢迎提问和反馈。
为数据科学家理解大 O 符号
原文:https://towardsdatascience.com/understanding-big-o-notation-for-data-scientists-b892bc00e1e8?source=collection_archive---------20-----------------------
包含 Python 示例和练习
伯纳德·赫曼特在 Unsplash 上的照片
由于数据科学被描述为数学、领域知识和计算机科学的交叉点,大 O 符号在计算机科学中是一个非常重要的概念。理解它将有助于我们开发更有效的算法,优化速度和内存,这在我们处理越来越多的数据时是最基本的。
在本文中,我们首先定义大 O 符号,以及它如何描述时间和空间复杂性。然后,我们研究不同的情况,并为每种情况导出大 O 符号。最后,我们建议你做一些练习来练习你的学习。
定义大 O 符号
大 O 符号是一个数学表达式,描述了当算法的自变量趋向于一个非常大的数时算法的效率。
它用于描述给定函数的时间和空间复杂度。
时间复杂度是一个描述函数运行时间的概念:函数完成任务需要多长时间。评估时间复杂度要考虑的重要因素可以是数组的长度、进行比较的次数或者必须调用递归函数的次数。
空间复杂度描述了运行函数必须分配的内存量或空间。评估空间复杂性时要考虑的重要因素还有数组的长度、声明的变量数量、数据结构的副本数量等。
大 O 符号常用来描述预期情况的最坏情况。我们很少关心最好的情况。
例如,考虑数组排序的时间复杂度。最好的情况是我们排序的每个数组都已经排序了!这样一来,数组有多大就无关紧要了。这样,时间复杂度与数组的大小无关,记为 O(1)。然而,知道这一点并不是很有用,因为如果所有的输入数组都已经排序了,我们很少需要开发排序算法。
让我们通过一个简单的例子来获得对大 O 符号的直觉。
获得大 O 符号的直觉
考虑以下情况:你住在离杂货店 5 分钟路程的地方,你把每样东西都装进了自己的袋子里。
现在,假设你有一个特别大的购物清单,并决定在一天内买下清单上的所有东西。时空复杂度是多少?
知道你住的地方离杂货店只有 5 分钟的路程,无论你买了多少东西,你都要花 5 分钟的时间去拿你的杂货。如果你买了一盒牛奶,那么你需要 5 分钟把它带回家。如果你买了 10 盒牛奶,你仍然需要 5 分钟才能把它带回家。因此,所花费的时间与你购买的商品数量无关。因此,时间复杂度表示为 O(1)。
空间复杂度呢?在这种情况下,您将每件物品打包在自己的袋子中,这意味着一个袋子只能装一件物品。因此,随着你购买的物品越来越多,你需要的袋子数量会线性增加:1 件物品需要 1 个袋子,3 件物品需要 3 个袋子,10 件物品需要 10 个袋子,以此类推。因此,空间复杂度被表示为 O(N),其中 N 是你在杂货店购买的商品数量。
可视化空间和时间复杂性
既然我们对如何得到大 O 符号有了直觉,让我们看看不同的表达式是如何相互比较的。下图显示了随着 N 的增加,一些常见的大 O 符号。
图片由作者提供。我们可以看到 O(N!)绝对是复杂度最差的场景,因为当 N 变大时,复杂度会迅速增加。另一方面,与其他情况相比,O(log(N))保持相对平坦。
看上面的图,我们可以看到我们是多么希望避免复杂度为 O(N!),因为当 N 变大时它迅速增加。
您可能还会注意到图中没有 O(1)。这是因为很难在避免错误结论的同时确定界限。原因是 O(1)不一定意味着比 O(N)或 O(log(N))好。它只是表示一条平坦的线,因此它不会随 N 增加。但是,O(1)可能比 O(N)或 O(log(N))慢。
因此,我们可以改进我们对大 O 符号的定义,并将其解释为时间和空间复杂度的增长率。
大 O 符号杂集
在进入例子和练习之前,这里有各种大 O 符号的提示、技巧和约定。
我们不关心 N 的倍数
如果我们把一个函数的复杂度评估为 O(2N),那么它等价于 O(N)。同样,O(5N)变成 O(N)。记住,大 O 符号描述了时间和空间的复杂性是如何扩展的。因此,我们可以放心地忽略 n 的任何倍数。
删除非主导术语
假设我们有 O(N + N)。从上图中,我们知道 O(N)的伸缩速度比 O(N)快得多。因此,O(N + N)等价于 O(N),因为当 N 较大时,O(N)的贡献与 O(N)相比将是最小的。
什么 O(N + log(N))?再一次,我们看上面的图,看到 O(N)是主导项,因为它比 O(log(N))增加得更快。因此,O(N + log(N))等价于 O(N)。
什么时候做加法和乘法?
当操作必须一个接一个地进行时,我们增加了复杂性。考虑下面的代码:
def some_func(a: list, b: list) -> None:
for each_a in a:
print(each_a)
for each_b in b:
print(each_b)
我们看到some_func
首先遍历数组a
,然后遍历数组b
。这样,时间复杂度为 O(A + B),其中 A 是数组a
的长度,B 是数组B
的长度。
现在,当函数必须为每个操作执行一个任务时,我们增加了复杂性。这通常发生在嵌套的 for 循环中。
def nested_some_func(a: list, b:list) -> None:
for each_a in a:
for each_b in b:
print(each_a, each_b)
这里,nested_some_func
有一个嵌套的 for 循环,为a
的每个元素打印b
的每个元素。所以时间复杂度相乘,表示为 O(A * B),其中 A 是数组a
的长度,B 是数组b
的长度。
我们什么时候看到 O(log(N))?
当问题空间在每次迭代中减半时,O(log(N))的复杂度是常见的。例如,二分搜索法的时间复杂度为 O(log(N))。
递归函数的复杂性
递归是一个概念,在这个概念中,一个问题通过一个较小问题的迭代来解决。以下列计算整数阶乘的函数为例:
def factorial(x: int):
if x < 0:
raise ValueError('Integer must be greater than or equal to 0')
elif x == 0:
return 1
elif x == 1:
return 1
else:
return (x * factorial(x-1))
假设我们想计算factorial(3)
,那么这个递归函数会做:
- 3 * 2!
- 3 * 2 * 1!
- 3 * 2 * 1 = 6
那么这里的时间复杂度是多少呢?在本例中,该函数运行了 3 次。因此,我们看到了整数和函数运行次数之间的线性关系。因此,时间复杂度为 O(N)。
我们现在准备着手做一些练习。
练习
花点时间通读每个函数,在向下滚动并查看解释之前,尝试自己找出时间复杂度的大 O 符号。
练习 1
def foo(a: list) -> None:
for each_a in a:
print(a)
for each_a in a:
print(a)
回答:我们对同一个数组迭代两次,得到 O(2N),相当于 O(N)。
练习二
def foo(a: int) -> bool:
if a > 0:
return True
else:
return False
回答:这是一个简单的 if 语句。所以它的时间复杂度不成比例,所以是 O(1)。
练习 3
def foo(a: list) -> None:
for i in a:
for j in a:
print(i, j)
答:我们在同一个数组上有一个嵌套的 for 循环。因此,它是 O(N)。您可以更精确地说 O(A),其中 A 是数组的长度a
。
练习 4
def is_prime(x: int) -> bool:
i = 2
while (i**2 <= x):
if x % i == 0:
return False
i += 1
return True
回答:我们来考虑一下例子is_prime(9)
。该函数将执行以下操作:
- 2 小于 9 和
9 % 2 != 0
。因此,我们将i
增加到 3。 - 3 是 9,所以这是最后一次检查。
9 % 3 == 0
,所以 9 是质数,函数返回True
。
那is_prime(11)
的案子呢?
- 2 小于 11 和
11 % 2 != 0
。所以我们将i
增加到 3。 - 3 小于 11 和
11 % 3 != 0
。所以我们将i
增加到 4。 - 4 大于 11。因此,11 是质数,函数返回
True
。
我们应该看到在最坏的情况下,当i
达到x
的平方根时,我们如何停止检查。因此,时间复杂度为 O(sqrt(N))。
摘要
大 O 符号是一个数学表达式,它描述了算法的效率随着其参数的增加而变化的速率。
它用来表达时间和空间的复杂性。
空间复杂度与一个功能需要分配的内存有关。时间复杂度与完成一项功能所需的时间有关。
我希望这篇短文能帮助你更好地理解大 O 符号的概念。虽然在最初的几个问题中它可能看起来模糊不清,但是随着你练习更多的问题,它会逐渐变得清晰。
干杯🍺!
来源:破解编码访谈——盖尔·拉克曼·麦克道尔
理解生物信息学——具有生物学领域知识的数据科学
原文:https://towardsdatascience.com/understanding-bioinformatics-data-science-with-biology-domain-knowledge-2bc378e89ed7?source=collection_archive---------16-----------------------
看看什么是生物信息学和生物信息学家做什么
马库斯·斯皮斯克在 Unsplash 上的照片
生物信息学是一个很大的领域,对不同的人来说似乎意味着稍微不同的东西。因此,对于局外人来说,很难确切地知道这个领域到底是什么。在这篇文章中,我想对什么是生物信息学和生物信息学家做什么做一个广泛的概述。
在关于生物信息学的对话中很少提到的一个有趣的事实是,生物信息学和数据科学之间有很多相似之处。首先,这两个领域很难全面定义。数据科学家应该具备的核心技能包括数学、计算机科学和特定领域的知识。生物信息学家应该对数学、计算机科学和生物学驾轻就熟。考虑到这一点,生物信息学对我来说是数据科学的一个领域。生物信息学家经常进入传统的数据科学角色——本质上是将生物学领域的知识换成其他东西。
从根本上说,生物信息学就是使用强大的计算机来分析大量的生物数据。生物信息学越来越受欢迎,这与生物学研究最近所处的状态有关。我们现在正在生成如此大量的数据,以至于我们需要专业的工具和人员来理解这些数据。
为了很好地理解什么是生物信息学,它有助于了解我们所说的组学在生物学研究中的意义。
什么是组学
组学是指生物学中四个研究领域的集合。这些是基因组学、转录组学、蛋白质组学和代谢组学。这四个领域的总体目标是了解它们各自的生物分子。
这四个领域是生物信息学流通的大规模数据集的来源。我们来看看每个领域都关注什么,大数据从何而来。
基因组学
基因组学可能是大多数人在考虑生物信息学时想到的东西。基因组学研究所有生命形式的 DNA。DNA 本质上只是储存细胞运转所需的信息。这可能是所有组学中最容易研究的,因为 DNA 相对来说是不变的。
基因组学的数据集是由下一代测序技术生成的。简而言之,NGS 帮助我们解读了遗传密码。NGS 输出需要特殊工具来处理和操作的大数据集。
转录组学
转录组学是关于 RNA 分子的研究。你可以认为 RNA 是 DNA 的表亲。它与 DNA 有很大的不同,因此它需要自己的研究领域。RNA 实际上来源于 DNA——它是一种短得多的分子,在生命系统中做着令人困惑的大量工作。
转录组学中使用的技术与基因组学中使用的技术基本相同——下一代测序。还有其他研究转录组学的技术,但是它们不能为生物信息学产生足够大的数据集。
蛋白基因组学
蛋白质组学就是研究蛋白质。蛋白质是活细胞的主力——它们无处不在,做着许多不同的工作。这可能是所有四个组学中最难的,因为要研究的蛋白质种类繁多。蛋白质组学中生成的数据集可以来自质谱技术。
代谢组学
这个领域主要是研究活细胞中的小分子。与蛋白质组学一样,代谢组学数据将来自质谱和核磁共振技术。
流式细胞术
流式细胞术不是真正的组学,但它属于生物信息学范畴。流式细胞术涉及测量细胞群体的特性。
生物信息学家可以参与构建和/或使用两种资源;数据库和算法。我们将看看每一个的例子,主要集中在基因组学和生物信息学上。
数据库
生物信息学中的数据库是来自给定类型数据集的数据集合。基因组学中的一个例子是序列读取存档,它是下一代测序数据的最大储存库。NCBI的生物信息学家将负责维护这些巨大的资源供研究人员使用。生物信息学家也可以利用这里的数据进行研究。
算法
一旦获得数据,您需要专业工具来正确地分析它,并从中获得有意义的见解。这就是生物信息学算法的用武之地。同样,生物信息学家可以构建或使用这些工具,或者两者兼而有之!基因组分析工具包(GATK) 为 NGS 数据的分析建立了许多工具。他们为预处理数据,寻找 DNA 样本中的突变,以及评估突变的重要性等制定程序。
我已经提到了生物信息学基因组学领域的数据库和算法,但所有四个组学和流式细胞术都有它们的等价物。
结论
从根本上说,生物信息学家使用强大的计算机来处理大的生物数据。他们通过建立和/或使用算法和数据库来做到这一点。
它有助于了解生成生物信息学数据集的四个组学。这些是基因组学、转录组学、蛋白质组学和代谢组学。基因组学和转录组学通过高通量下一代测序技术为生物信息学生成数据集。蛋白质组学和代谢组学通过质谱技术产生数据集。
最后,生物信息学可以被认为是一门具有生物学领域知识的数据科学。像生物信息学这样一个广阔的领域,总是有可能遗漏一些东西。在这里,我试图给这个领域一个广泛的概述,涵盖其中的主要子领域。
通过实现来理解:k-最近邻
原文:https://towardsdatascience.com/understanding-by-implementing-k-nearest-neighbors-469d6f84b8a9?source=collection_archive---------31-----------------------
建立你自己的模型
了解 k-最近邻分类器的工作原理并在 Python 中实现它
1-最近邻分类器的判定区域。图片由作者提供。
A 第二天,另一个经典算法:k-最近邻居。像朴素贝叶斯分类器一样,这是解决分类问题的一个相当简单的方法。该算法非常直观,并且具有无与伦比的训练时间,这使得它成为您刚刚开始机器学习生涯时学习的绝佳候选。话虽如此,但做出预测是极其缓慢的,尤其是对于大型数据集。由于维数灾难,具有许多特征的数据集的性能可能也不是压倒性的。
在本文中,您将了解到
- k 最近邻分类器的工作原理
- 为什么它被设计成这样
- 为什么它有这些严重的缺点,当然,
- 如何用 NumPy 在 Python 中实现?
因为我们将以 scikit learn-conform 的方式实现分类器,所以也值得看看我的文章构建您自己的定制 scikit-learn 回归。然而,scikit-learn 的开销很小,无论如何您都应该能够跟上。
你可以在 我的 Github 上找到代码。
理论
这个分类器的主要思想非常简单。它直接来源于分类的基本问题:
给定一个数据点 x,x 属于某类 c 的概率是多少?
在数学的语言中,我们搜索条件概率p(c|x)。虽然朴素贝叶斯分类器试图使用一些假设直接模拟这种概率,但还有另一种直观的方法来计算这种概率——概率的频率主义观点。
对概率的天真看法
好吧,但这是什么意思呢?让我们考虑下面这个简单的例子:你掷出一个六面的、可能有作弊的骰子,想要计算掷出六的概率,即 p (掷骰数 6)。如何做到这一点?嗯,你掷骰子 n 次,写下它显示 6 的频率。如果你见过数字六 k 次,你说在 k / n 左右看到六的概率是**。这里没什么新奇的东西,对吧?**
现在,假设我们想计算一个条件概率,例如
p(掷 6 号|掷一个偶数)
你不需要贝叶斯定理来解决这个问题。再掷一次骰子,忽略所有奇数的骰子。这就是条件作用:过滤结果。如果你掷骰子 n 次次,已经看到 m 个偶数并且其中的 k 个都是一个六,那么上面的概率是在k/m左右而不是 k / n 。
激励 k-最近邻居
回到我们的问题。我们要计算p(c|x),其中 x 是包含特性的向量, c 是某个类。在这个例子中,我们
- 需要大量的数据点,
- 过滤掉具有特征 x 和
- 检查这些数据点属于类别 c 的频率。
相对频率是我们对概率p(c|x)的猜测。
你看到这里的问题了吗?
**通常,我们没有很多具有相同特征的数据点。**往往只有一个,也许两个。例如,假设一个数据集有两个特征:人的身高(厘米)和体重(千克)。标签为公或母。于是, x= ( x ₁, x ₂)其中 x ₁是身高, x ₂是体重, c 可以取值男性和女性。让我们来看看一些虚假数据:
图片由作者提供。
因为这两个特征是连续的,所以具有两个数据点的概率是可以忽略的,更不用说几百个数据点了。
**另一个问题:**如果我们要对一个我们从未见过的特征的数据点进行性别预测,比如(190.1,85.2),会发生什么?这就是预测的真正含义。这就是为什么这种天真的方法不起作用。相反,k-最近邻算法所做的如下:
它试图逼近概率 p ( c | x ),不是用具有精确特征 *x、*的数据点,而是用具有接近 x 特征的数据点。
**从某种意义上来说是不太严格的。**代替等待许多身高=182.4 和体重=92.6 的人,并检查他们的性别,k-最近邻居允许考虑接近具有这些特征的人。算法中的 k 是我们考虑的人数,它是一个超参数。
这些是我们或超参数优化算法(如网格搜索)必须选择的参数。它们不是由学习算法直接优化的。
图片由作者提供。
该算法
我们现在有了描述算法所需的一切。
培训:
- 以某种方式组织训练数据。在预测时间内,该顺序应该能够为我们提供任何给定数据点 x 的 k 个最近点。
- 已经这样了!😉
预测:
- 对于新的数据点 x ,在组织好的训练数据中找到 k 最近邻。
- 聚合这些 k 邻居的标签。
- 输出标签/概率。
目前还不能实现这个,因为有很多空白要填。
- 组织是什么意思?
- 我们如何衡量接近度?
- 如何聚合?
除了 k 的值,这些都是我们可以选择的,不同的决定给了我们不同的算法。让我们简单地回答如下问题:
- 组织=按原样保存训练数据集
- 邻近度=欧几里德距离
- 合计=平均
这需要一个例子。让我们再次用人员数据检查图片。
我们可以看到 k =5 个最接近黑色的数据点有 4 个男性标签和 1 个女性标签。因此,我们可以输出属于黑点的人实际上是 4/5=80%男性,1/5=20%女性。如果我们希望一个类作为输出,我们将返回 male。没问题!
现在,让我们实施它。
履行
最难的部分是找到一个点的最近邻居。
快速入门
让我们用一个小例子来说明如何在 Python 中做到这一点。我们从
import numpy as np
features = np.array([[1, 2], [3, 4], [1, 3], [0, 2]])
labels = np.array([0, 0, 1, 1])
new_point = np.array([1, 4])
图片由作者提供。
我们已经创建了一个由四个数据点和另一个点组成的小型数据集。哪些是最近的点?新点的标签应该是 0 还是 1?让我们来找出答案。输入
distances = ((features - new_point)**2).sum(axis=1)
给我们四个值 distance =[4,4,1,5],这是从new_point
到features
中所有其他点的平方欧几里德距离。太棒了。我们可以看到三号点是最近的,其次是一号点和二号点。第四点是最远的。
如何从数组[4,4,1,5]中提取最近的点?一个distances.argsort()
帮助。结果是[2,0,1,3],它告诉我们索引为 2 的数据点最小(输出点编号为 3),然后是索引为 0 的数据点,然后是索引为 1 的数据点,最后是索引为 3 的数据点最大。
注意argsort
将distances
中的第一个 4 放在第二个 4 之前。根据排序算法,也可以反过来,但是在这篇介绍性文章中,我们不讨论这些细节。
例如,如果我们想要三个最近的邻居,我们可以通过
distances.argsort()[:3]
并且标签对应于这些最近的点
labels[distances.argsort()[:3]]
我们得到[1,0,0],其中 1 是离(1,4)最近的点的标签,零是属于下两个最近点的标签。
这就是我们所需要的,让我们开始真正的交易。
最终代码
你应该对代码很熟悉。唯一的新功能是np.bincount
,它计算标签的出现次数。注意,我首先实现了一个predict_proba
方法来计算概率。方法predict
只是调用这个方法,并使用argmax
函数返回概率最高的索引(=类)。该类等待从 0 到 C -1 的类,其中 C 是类的数量。
**免责声明:**此代码未经优化,仅用于教育目的。
import numpy as np
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.utils.validation import check_X_y, check_array, check_is_fitted
class KNNClassifier(BaseEstimator, ClassifierMixin):
def __init__(self, k=3):
self.k = k
def fit(self, X, y):
X, y = check_X_y(X, y)
self.X_ = np.copy(X)
self.y_ = np.copy(y)
self.n_classes_ = self.y_.max() + 1
return self
def predict_proba(self, X):
check_is_fitted(self)
X = check_array(X)
res = []
for x in X:
distances = ((self.X_ - x)**2).sum(axis=1)
smallest_distances = distances.argsort()[:self.k]
closest_labels = self.y_[smallest_distances]
count_labels = np.bincount(
closest_labels,
minlength=self.n_classes_
)
res.append(count_labels / count_labels.sum())
return np.array(res)
def predict(self, X):
check_is_fitted(self)
X = check_array(X)
res = self.predict_proba(X)
return res.argmax(axis=1)
就是这样!我们可以做一个小测试,看看它是否符合 scikit-learnk-最近邻分类器。
测试代码
让我们创建另一个小数据集进行测试。
from sklearn.datasets import make_blobs
import numpy as np
X, y = make_blobs(n_samples=20, centers=[(0,0), (5,5), (-5, 5)], random_state=0)
X = np.vstack([X, np.array([[2, 4], [-1, 4], [1, 6]])])
y = np.append(y, [2, 1, 0])
看起来是这样的:
图片由作者提供。
使用我们的分类器,k = 3
my_knn = KNNClassifier(k=3)
my_knn.fit(X, y)
my_knn.predict_proba([[0, 1], [0, 5], [3, 4]])
我们得到了
array([[1\. , 0\. , 0\. ],
[0.33333333, 0.33333333, 0.33333333],
[0\. , 0.66666667, 0.33333333]])
**阅读输出如下:**第一点是 100%属于类 1 第二点以 33%均等地位于每个类中,第三点是大约 67%的类 2 和 33%的类 3。
如果你想要具体的标签,尝试
my_knn.predict([[0, 1], [0, 5], [3, 4]])
它输出[0,0,1]。请注意,在平局的情况下,我们实现的模型输出较低的类,这就是点(0,5)被归类为属于类 0 的原因。
如果你检查图片,它是有意义的。但是让我们在 scikit-learn 的帮助下让自己安心吧。
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X, y)
my_knn.predict_proba([[0, 1], [0, 5], [3, 4]])
结果是:
array([[1\. , 0\. , 0\. ],
[0.33333333, 0.33333333, 0.33333333],
[0\. , 0.66666667, 0.33333333]])
唷!一切看起来都很好。让我们检查算法的决策边界,因为它很漂亮。
图片由作者提供。
再说一遍,上面的黑点不是 100%蓝色的。它是 33%的蓝色、红色和黄色,但是算法确定性地决定了最低等级,即蓝色。
我们还可以检查不同值的 k 的决策边界。
图片由作者提供。
注意蓝色区域最后变大了,因为这个类的这个优待。我们还可以看到,对于 k =1,边界是混乱的:模型是过度拟合。另一个极端是, k 与数据集的大小一样大,所有点都用于聚合步骤。因此,每个数据点得到相同的预测:多数类。在这种情况下,模型欠拟合。最佳位置介于两者之间,可以使用超参数优化技术找到。
在结束之前,我们先来看看这个算法有哪些问题。
k-最近邻的缺点
这些问题如下:
- 寻找最近的邻居需要很多时间,特别是对于我们幼稚的实现。如果我们想预测一个新数据点的类别,我们必须对照数据集中的每一个其他点来检查它,这是很慢的。使用高级数据结构组织数据有更好的方法,但问题仍然存在。
- 下面的问题 1:通常,您在更快、更强的计算机上训练模型,然后可以在较弱的计算机上部署模型。例如,想想深度学习。但是对于k-最近邻来说,训练时间比较容易,繁重的工作在预测时间内完成,这不是我们想要的。
- 如果最近的邻居一点都不近会怎么样?那它们就没有任何意义。在包含少量要素的数据集中,这种情况可能已经发生,但当要素数量增加时,遇到这种问题的几率会大大增加。这也是人们所说的维数灾难。在 Cassie Kozyrkov 的这篇文章中可以找到一个很好的形象化的例子。
尤其是因为问题 2,你不会太经常在野外看到k-最近邻分类器。这仍然是一个你应该知道的很好的算法,你也可以把它用于小数据集,这没什么错。但是,如果你有数百万个包含数千个特征的数据点,事情就变得棘手了。
结论
在本文中,我们讨论了k-最近邻分类器是如何工作的,以及为什么它的设计有意义。它试图估计数据点 x 属于类别 c 的概率,并尽可能使用最接近 x 的数据点。这是一种非常自然的方法,因此这种算法通常在机器学习课程的开始讲授。
注意,构建一个k-最近邻回归量也非常简单。不需要计算类的出现次数,只需对最近邻的标签进行平均即可获得预测。你可以自己实现它,这只是一个小小的改变!
然后,我们模仿 scikit-learn API,以一种简单的方式实现了它。这意味着您也可以在 scikit-learn 的管道和网格搜索中使用这个估计器。这是一个很大的好处,因为我们甚至有超参数 k ,你可以使用网格搜索,随机搜索,或贝叶斯优化。
然而,这种算法有一些严重的问题。它不适合大型数据集,也不能部署在较弱的机器上进行预测。加上对维数灾难的敏感性,这是一种理论上很好的算法,但只能用于较小的数据集。
我希望你今天学到了新的、有趣的、有用的东西。感谢阅读!
作为最后一点,如果你
- 想支持我多写点机器学习和
- 无论如何都要计划获得中等订阅量,
为什么不做 通过这个链接 ?这将对我帮助很大!😊
透明地说,给你的价格不变,但大约一半的订阅费直接归我。
非常感谢,如果你考虑支持我的话!
有问题就在LinkedIn上写我!
了解分类指标
原文:https://towardsdatascience.com/understanding-classification-metrics-6b585a6377de?source=collection_archive---------38-----------------------
对于一个简单的二进制分类任务,初学者经常被大量的度量标准所迷惑。在这里,我给出了敏感性(也称为回忆)、特异性和精确性的自下而上的解释。
从事分类指标工作的人经常会遇到像真阳性率、假阳性率、召回率和精确度这样的术语,深入理解它们的含义是很有用的。
实际上有很多很好的来源来解释这些术语,但是真正的理解只能来自于坐下来思考问题。此外,我们有自己思考问题的方式,所以没有放之四海而皆准的方法。在这篇笔记中,我将我对这些术语的理解具体化,以供我参考,也供任何和我想法相同的人参考。
可视化的分类问题形式https://commons.wikimedia.org/wiki/File:Precisionrecall.svg
我将采用不同的方法,而不是直接介绍所有这些术语,并让读者经历我在阅读这些术语时遇到的同样的困惑。**我将讲述一个情景和一个实验,并通过数学来解决问题。只有到最后我才会说出这些术语。**这样一来,读者就会理解这个概念,然后再为这些名字而烦恼。
让我们来看一个场景,其中有一些状态可以是真(T)或假(F)。这可以说是个人的新冠肺炎状态,或者在 Imagenet 中图像是否是猫的图像。然后,我们有一个分类器,可能是那些可以嗅出新冠肺炎阳性患者的酷狗之一,或者是你最喜欢的 CNN 分类器,可以区分猫和非猫。当它们“认为”样本为真(T)时,它们将输出正(P ),当它们“认为”样本为假(F)时,它们将输出负(N)。
现在,在这一点上,我们有一些可以考虑的自然量。
- 我们可以看看人口概率是真还是假,即 P(T)和 P(F)。请注意,它们的总和为 1。这可能是已知的(Imagenet 中的猫)或未知的(新冠肺炎病例的真实实例),在后者中我们可能有估计。
- 我们可以通过询问真实样本被发现为正 P(P|T)或负 P(N|T)的概率来查看我们的分类器执行得有多好。请注意,P(P|T) + P(N|T)=1 作为真实样本,只能以某种方式进行标记。类似地,我们可以讨论 P(P|F)和 P(N|F ),它们的和也是 1。
- 我们还可以通过询问样本被发现为阳性的概率的反问题来查看我们的分类器表现如何,实际上是真 P(T|P)和假 P(F|P)。这些加起来也必须是 1,因为标记为阳性的样本必须是真或假,即 P(T|P) + P(F|P) = 1。同理,我们可以讲 P(T|N)和 P(F|N)。
现在我要讲一下贝叶斯定理。如果你只是知道它,但没有内化它,我会建议你停下来思考一下,努力理解它。这不是很难,可以用维恩图来理解。如果你没有听说过它,那么你应该在维基百科上阅读它,然后像我建议的那样努力思考它。我不会在这里激励它,只是简单地使用它。
现在,使用贝叶斯定理,我们可以联系上述数量
很明显,我还可以写出另外三个关系式,但是请注意,其中一个是通过 T F 和 P N 从上面得到的,另外两个是通过上面第 3 点中提到的概率总和为 1 得到的。此外,从商业角度来看,上述形式通常是最有用的。差不多了!我们只需要用上面第二点提到的概率总和来稍微调整一下。
就是这样!这就是全部了。然而上面的一些术语有特殊的名称,我现在介绍一下。左边的家伙,P(T|P)叫精密。这是一个非常有用的指标,因为它量化了那些被分类为阳性的样本中有多少部分是真实的。P(P|T)被称为灵敏度或召回,它是被分类器分类为阳性的真实样本的分数。最后,P(N|F)与前面的量非常相似,不幸地不被称为对否定的回忆(这将使生活变得更简单,所以…显然不是),而被称为特异性。
通常,医学中报道的测试或分类器的度量是灵敏度和特异性。然而,人们经常提到,如果真实的人口密度是偏斜的,即 P(T) << P(F). Let’s see why that is the case. Let me massage the above expression further
Now suppose we have a super fundoo 分类器具有非常高的灵敏度 P(P|T) = 1 和非常高的特异性 P(N|F) = .99,那么人们可能会天真地认为该分类器非常好。然而,假设我们有 P(F)/P(T) ~ 1000,那么我们仍然会得到 10%的精度。
可以论证的是,从医学或商业的角度来看,精确度和召回率/敏感度通常比特异性和召回率/敏感度更有利于权衡比较。
理解分类建模中的精度、灵敏度和特异性,以及如何用混淆矩阵计算它们
原文:https://towardsdatascience.com/understanding-common-classification-metrics-titanic-style-8b8a562d3e32?source=collection_archive---------28-----------------------
直观、易于记忆的示例,用于理解常见的分类指标
照片由 Alwi Alaydrus 在 Unsplash 上拍摄
根据分类模型成功生成预测后,您会想知道预测的准确性。当涉及到分类模型时,准确性可能是一个非常微妙的概念,因为对您的模型有意义的度量标准将根据您的模型的目的而变化。例如,你是否试图预测一个病人是否患有癌症?还是想预测一个人是男是女?在评估这些模型时,您最有可能关注不同的指标,因为正如您所想象的,做出不正确的预测会产生不同的成本。
为了理解这些复杂性,让我们使用这些度量来评估一个分类模型。我们将使用的数据来自 Kaggle 著名的 泰坦尼克号——从灾难中学习的机器 分类比赛。数据集的每一行都描述了泰坦尼克号上的一名乘客。比赛的目的是利用提供的特征(如性别、年龄等。)来预测给定乘客是活着还是死了。
评估指标
在不进行任何数据清理或特征工程的情况下,我们将通过在训练数据上拟合我们的模型来生成基线逻辑回归模型,然后在同一数据集上进行预测。为简单起见,我们将使用没有任何缺失值的特性和以下指标来评估模型的准确性:
- 混淆矩阵
- 准确(性)
- 分类错误率
- 精确
- 灵敏度
- 特征
模型
我们将使用数据集中的Pclass
、Sex
、Age
、SibSp
、Parch
和Fare
列来尝试和预测Survived
,从而将逻辑回归模型拟合到我们的数据中。
符合我们的模型,现在让我们产生我们的预测。
评估我们的模型
照片由斯科特·格雷厄姆在 Unsplash 上拍摄
现在我们有了一些预测,我们可以评估模型以确定它对实际类的预测有多好。理解我们模型准确性的一个关键是混淆矩阵。为了生成一个,我们将使用caret
包中的confusionMatrix
函数。该函数要求我们将输入作为因子提供,因此我们将进行转换并显示矩阵:
在查看上面的结果时,我们可以看到我们的基线模型表现得不是很好。对角线上的值,从左上角到右下角,是模型准确预测的类。列标题表示实际类别,行标签表示预测类别。用视觉表示法来理解混淆矩阵通常更容易:
作为一个例子,如果我们看第一列(“活的”、“活的”),这是真阳性,我们看到模型正确地识别了 108 个活着的个体,但是,看左下角的(“活的”、“死的”),这是假阴性,我们看到模型预测 234 个实际活着的个体死亡。
混淆矩阵对于理解我们将用于评估该模型的指标至关重要。
准确(性)
由 Ricardo Arce 在 Unsplash 上拍摄
在我们将要讨论的所有指标中,准确性是最直接的,也是您可能最熟悉的。当涉及到分类模型时,准确性主要是一个高层次的抽查,几乎不应该是用来评估您的模型的唯一指标。可以使用混淆矩阵中的值计算准确度:
当您的响应变量中有不平衡的类时,问题就来了。例如,如果您试图检测欺诈,而 1,000 笔交易中只有 1 笔是欺诈性的,即使您预测每笔交易都没有欺诈,您仍然会有一个 99.9%准确的模型。然而,也许一个欺诈案件会造成数百万美元的损失。我们知道,对于这样的模型,预测一个欺诈性交易将是模型的重点,我们的指标应该进行调整,以帮助我们了解模型在这方面的表现。因此,在大多数分类设置中,准确性需要进一步分解,以分析模型如何预测我们关心的结果。
让我们来看看我们模型的准确性:
## [1] 0.2065095
我们的模式真的很艰难。我们只是在 21%的时间里预测实际的类。
分类错误率
在 Unsplash 上 NeONBRAND 拍摄的照片
这个度量是准确性的反义词。它向我们展示了我们的结果被错误分类的频率。其计算方法如下:
我们可以通过从 1 中减去我们的准确性度量来找到我们的模型的分类错误率。
## [1] 0.7934905
我们的模型在大约 79%的时间里预测错误的类别。
精确
照片由博夫肖在 Unsplash 上拍摄
精度是指实际阳性与预测阳性的比率。当误报的成本很高时,最常使用这种度量。例如,在一个将电子邮件分类为垃圾邮件或垃圾邮件的模型中,我们需要非常高的精确度,以便相关和重要的电子邮件不会被发送到垃圾文件夹或被阻止(误报)。这里假阳性的代价很高。精度计算如下:
对于我们的模型,我们必须稍微扩展一下这个故事,以使精度有意义。假设我们继承了一大笔钱,作为泰坦尼克号的历史爱好者,我们想给模型中确定的每个幸存者的家庭寄去 1000 美元。我们绝对不希望发送不必要的钱,所以我们真的希望我们的模型具有高精度,这意味着,我们尽可能多地向实际幸存者的家庭发送钱,并真正限制向遇难乘客的家庭发送钱的频率。
让我们看看我们模型的精度:
## [1] 0.1858864
我们模型的精确度是糟糕的。如果我们按照现在的模式发送 1,000 美元的礼物,只有大约 19%的家庭会收到礼物,其余的钱按照我们的目标都是浪费!
敏感度(回忆)
国立癌症研究所在 Unsplash 上拍摄的照片
当你关注于识别阳性结果并且假阳性的成本很低时,灵敏度或回忆是重要的——这意味着只要我们识别尽可能多的实际阳性,我们就可以拾取一些假阳性。如果我们要预测一名患者是否患有癌症,灵敏度必须高得令人难以置信,这样我们才能捕捉尽可能多的阳性病例,即使这意味着我们会引入一些实际上没有患癌症的患者。这里假阳性的成本很低。灵敏度计算如下:
让我们假设我们想给模型中确定的每个幸存者的家庭送一朵玫瑰。我们没有足够的钱给幸存者和死者的家人送花,所以我们必须做出选择。在我们内心深处,对我们来说非常重要的是,我们至少要给真正幸存者的家庭送去玫瑰。然而,我们不介意最终给遇难乘客的家庭送去一些玫瑰。我们在好市多大量购买玫瑰,所以它们相当便宜。在这种情况下,我们希望我们的敏感度非常高,以便尽可能多的幸存者家庭收到玫瑰,即使少数非幸存者家庭也收到玫瑰。
让我们计算一下我们模型的敏感度:
## [1] 0.3157895
我们模型的灵敏度真的是相当可怕。如果我们使用这个模型,只有 32%的幸存者家庭会得到一朵玫瑰!那是不能接受的!
特征
由乔希·弗雷内特在 Unsplash 上拍摄的照片
特异性是真阴性与所有阴性结果的比率。如果你担心你的否定率的准确性,并且肯定的结果有很高的成本,那么这个指标是有意义的——所以如果没有必要,你就不要吹这个口哨。例如,如果你是一名审计员,正在检查财务交易,一个肯定的结果意味着一年的调查,但是找不到一个结果只会给公司造成 50 美元的损失。特异性计算如下:
假设我们想给我们的模型所识别的死亡乘客的家人发送一封手写的邮件。自从 1912 年泰坦尼克号沉没以来,我们觉得这些家庭有时间从他们的损失中恢复过来,所以不会因为收到一张纸条而心烦意乱。然而,我们觉得给幸存者的家人发一封短信是不可思议的麻木不仁,因为他们的死亡时间会更近(最后一位泰坦尼克号幸存者于 2009 年去世,享年 97 岁),而家人仍然沉浸在悲痛之中。
让我们计算一下我们模型的特异性:
## [1] 0.1384335
我们的专一是可耻的!如果我们使用目前的模型,大约 86%的纸币接收者会记住他们最近的损失!我们不能这样!
结论
在查看我们模型的衡量标准时,有一点是清楚的:我们不应该将这种模型用于任何类型的礼物赠送。我们的模型非常不准确,只会引起恐慌。
虽然我们不会根据这个练习给泰坦尼克号幸存者写任何手写的笔记,但我们以一种令人难忘的方式学习了一些用于分类模型的最常用的度量标准。当然,还有其他重要的指标,如 F1 得分、ROC 曲线和 AUC,但是,我们将把这个讨论留到以后。
谢谢大家的支持!
感谢您阅读本文!如果你觉得有帮助,请给我一两下掌声:)
用购物篮分析理解消费者行为
原文:https://towardsdatascience.com/understanding-consumer-behavior-with-the-market-basket-analysis-3d0c017e5613?source=collection_archive---------15-----------------------
了解用于优化零售和电子商务行业销售的数据挖掘技术
塔曼娜·茹米在 Unsplash 拍摄的照片
预测客户的兴趣是许多商业模式中采用的策略。公司在各种策略上进行了大量投资,从进行客户调查到建立复杂的机器学习模型以更好地了解客户行为。
使用的一个比较突出的方法是市场篮子分析,这是一种数据挖掘技术,可以识别表现出强关系的产品。
这项研究可以识别出表面上看不出来的高相关性产品。这是一个重要的工具,因为知道哪些产品有利于购买其他产品可以使企业以更大的成功率推广和推荐商品。
在这里,我们将涵盖市场篮子分析的来龙去脉。
市场篮子分析
购物篮分析是关联规则挖掘的一种形式,它发现具有强关联或相关性的项目。
在解释购物篮分析之前,重要的是要涵盖一些关键术语。
在一个事务中购买的一组项目被称为一个项目集。
一个关联规则本质上是一个 if-then 语句,旨在建立所购买商品之间的关系。
假设你正在网上寻找一部新手机。将手机放入购物车后,您决定也要买一个手机壳。您将手机壳添加到购物车中并进行购买。
在这种情况下,项目集是{Phone,Phone Case}。
此项集的关联规则是:if ,then 。
项目集中的乘积可以分为两组:前因和后果。
前件指的是位于关联规则左侧的产品。
结果是指位于关联规则右侧的产品。
在这个例子中,先行词是电话,而结果词是手机壳。
购物篮分析需要找到表现出最强关联的项目集。
也就是说,通过识别和评估项目的所有组合来找到最显著的项目集是困难的,因为它提出了两个问题。
问题#1 :单从表面价值来看,我们无法区分最显著的项目集。
有了上面的例子,购买手机和购买手机壳有很强的相关性就说得通了。但是,如何评价表面上没有那么直接联系的物品呢?
幸运的是,有一些评估指标可以帮助定量地衡量前因和后果之间的联系。
support 度量测量项目集的频率。换句话说,它将告诉您购买项目集中的产品的频率。
支持度量的公式为:
置信度衡量的是在购买了前因的情况下,购买后果的可能性。
置信度度量的公式为:
提升指标衡量购买前因对购买后果的影响。
提升度量的公式为:
如果关联的提升为 1,那么前件和后件的购买是独立的。
如果一个关联的提升大于 1,购买前因会增加购买后果的可能性。
如果一个关联的提升值小于 1,购买前因会降低购买后果的可能性。
通过这些评估指标,我们可以筛选出不符合标准的产品组合。
问题 #2 :考虑到项目集组合的总数,我们无法处理所有的项目集。
简单来说,测试和评估每一个可能的唯一项集是不合理的。
客观地说,如果你有 1000 种不同的产品,那么在寻找最佳关联规则时,你需要考虑 499,500 种不同的两种商品的组合。任何大小组合的总数都超过了海滩上沙粒的数量。
谢天谢地,有一个简单的方法可以绕过这个问题。
apriori 算法是一种有效的替代方法,可以帮助识别频繁项集,同时过滤掉不频繁的项集。它可以不考虑项目集,而不必对它们进行评估。本文不会涉及 apriori 算法的内部工作原理,但是如果你感兴趣,你可以在这里了解更多。
缺点
尽管购物篮分析是一种非常有用的数据挖掘技术,但它绝不是对消费者行为的可靠研究。
首先,即使产品之间的关联显示出有希望的评价指标,它也不能直接证明产品之间的因果关系。毕竟,相关性不等于因果关系。
其次,像任何数据挖掘技术一样,购物篮分析容易出错。它可能会错误地忽略重要的关联或错误地包含不重要的关联。
在你进行分析的时候,记住这些缺点,以免你从你的发现中得出错误的结论。
个案研究
我们可以通过对一个存储电子商务购买的数据集(无版权保护)进行研究来演示市场购物篮分析,该数据集可以在这里访问。
这是数据集的预览。
代码输出(由作者创建)
我们只对每位顾客购买的商品感兴趣,这在“子类别”栏中有提及。让我们将这个列转换成一个列表的列表,每个列表代表一个项集。
代码输出(由作者创建)
执行市场篮分析需要计算每个项目集中关联的支持度、置信度和提升度量,如果手动执行,可能会非常耗时。谢天谢地,Python 中的 mlxtend 模块允许我们轻松地执行这样的操作。
现在我们有了项目集列表,我们必须使用 apriori 算法来删除不常用的项目集。这样做需要对数据进行一次热编码。
mlxtend 模块有自己的编码器,可以对项集进行一次性热编码。
代码输出(由作者创建)
使用 mlxtend 模块,我们可以使用 apriori 算法来识别支持值大于或等于 0.1 的项集。
代码输出(由作者创建)
因为目标是识别具有强关系的产品,所以我们将使用 association_rules 函数来查找关联类型符合要求的产品。
在这种情况下,如果一个项集中的提升值超过 1,我们将认为该关联是理想的。
代码输出(由作者创建)
根据结果,有手帕和披肩的项目集具有最高的提升值。值得探究的是,为什么购买手帕会增加购买披肩的可能性,反之亦然。
请记住,这项研究只证实了这两个项目之间的强相关性,而不是因果关系。
从这一分析中得出的一个误导是,向购买披肩的人积极推销手帕是最理想的。只有在进一步探索这两个项目之间的潜在关系后,才能得出这样的结论。
结论
照片由普拉蒂克·卡蒂亚尔在 Unsplash 拍摄
能够理解消费者的行为几乎就像是一种超能力。
这就是为什么购物篮分析作为一种技术脱颖而出,在寻找客户购买的模式和趋势时可以依赖。
这种分析本身似乎很简单,但它是产品推荐和促销系统基础的一部分,服务行业在未来许多年都将依赖这种系统。
我祝你在数据科学的努力中好运!
参考
- 罗山,B. (2019)。电子商务数据,第 2 版。于 2021 年 11 月 12 日从 https://www.kaggle.com/benroshan/ecommerce-data.取回
理解对比学习
原文:https://towardsdatascience.com/understanding-contrastive-learning-d5b19fd96607?source=collection_archive---------0-----------------------
学习如何使用自我监督学习法进行无标签学习。
拉奎尔·马丁内斯在 Unsplash 上拍摄的照片
什么是对比学习?
对比学习 是一种机器学习技术,用于通过教导模型哪些数据点相似 或不同来学习无标签数据集的**总体特征。****
让我们从一个简单的例子开始。想象你是一个新生婴儿,正在试图理解这个世界。在家里,我们假设你有两只猫和一只狗。
即使没有人告诉你他们是“猫”和“狗”,你可能仍然会意识到,与狗相比,这两只猫看起来很相似。
(左)照片由埃德加拍摄于 Unsplash |(右上)照片由拉娜·维德诺瓦拍摄于 Unsplash |(右下)图片由鲁比·施曼克拍摄于 Unsplash
仅仅通过识别我们毛茸茸的朋友之间的异同,我们的大脑就可以学习我们世界中物体的高级特征。
**例如,我们可能下意识地认为两只猫的耳朵是尖的,而狗的耳朵是下垂的。或者我们可以对比 (提示-提示)狗凸出的鼻子和猫扁平的脸。
本质上,对比学习允许我们的机器学习模型做同样的事情。它查看哪些数据点对是【相似】**【不同】,以便了解关于数据的更高层次的特征,甚至在之前的还有分类或分割等任务。**
这个为什么这么厉害?
这是因为我们可以训练模型学习大量关于我们的数据 没有任何注释或标签, 因此得名, 自我监督学习。
视网膜的眼底图像,带注释。来源:[1]
在大多数真实世界的场景中,我们没有为每张图片贴标签。以医学成像为例。为了创建标签,专业人员必须花费无数时间来查看图像,以手动分类、分段等。
通过对比学习,即使只有一小部分数据集被标记,也可以显著提高模型性能。
既然我们理解了什么是对比学习,以及它为什么有用,让我们看看对比学习是如何工作的。
对比学习是如何工作的?
在本文中,我重点关注 SimCLRv2 ,这是谷歌大脑团队最近提出的最先进的对比学习方法之一。对于其他的对比学习方法,如脸书的 MoCo,我建议回顾下面的文章。
**
幸运的是, SimCLRv2 非常直观。
整个过程可以简明地描述为三个基本步骤:
- 对于我们数据集中的每个图像,我们可以执行两个增强组合(即裁剪+调整大小+重新着色、调整大小+重新着色、裁剪+重新着色等。).我们希望模型知道这两个图像是“相似的”,因为它们本质上是同一图像的不同版本。
作者图。照片由埃德加在 Unsplash 上拍摄
- 为此,我们可以将这两幅图像输入到我们的深度学习模型(Big-CNN,如 ResNet)中,为每幅图像创建矢量表示。目标是训练模型为相似的图像输出相似的表示。
将图像表示为矢量表示。来源:Amit Chaudhary 的图解 SimCLR 框架, amitness
- 最后,我们试图通过最小化对比损失函数来最大化两个向量表示的相似性。
SimCLRv2 框架概述。作者图。照片由埃德加在 Unsplash 上拍摄
随着时间的推移,模型将了解到两个猫的图像应该具有相似的表示,并且猫的表示应该不同于狗的表示。
这意味着模型能够区分不同类型的图像,甚至不知道图像是什么!
我们可以将这种对比学习方法进一步分解为三个主要步骤:数据扩充、编码和损失最小化。
1)数据扩充
来源:Amit Chaudhary 的图解 SimCLR 框架, amitness
我们随机执行以下增强的任意组合:裁剪、调整大小、颜色失真、灰度。在我们的批处理中,我们对每个图像做两次*,以创建两个增强图像的正对*。**
2)编码
然后我们使用我们的 Big-CNN 神经网络,我们可以简单地认为它是一个函数, h = f(x), ,其中“x”是我们的一个增强图像,到将我们的两个图像编码为矢量表示。
作者图片
然后将 CNN 的输出输入到一组称为**投影头、*z =*******g(h)**的密集层,将数据转换到另一个空间。经验表明,这一额外步骤可以提高性能[2]。
如果您不熟悉潜在空间和向量表示,我强烈推荐您在继续之前阅读我的文章,这篇文章直观地解释了这个概念。
*
通过将我们的图像压缩到潜在空间表示中,模型能够学习图像的高级特征。
事实上,当我们继续训练模型以最大化相似图像之间的向量相似性时,我们可以想象模型正在学习潜在空间中相似数据点的聚类。
例如,猫的表现形式会更接近,但离狗的表现形式更远,因为这是我们训练模型学习的内容。
3)表示的损失最小化
现在我们有了两个向量, z ,我们需要一种方法来量化它们之间的相似性。
来源:Amit Chaudhary 的图解 SimCLR 框架, amitness
因为我们正在比较两个向量,自然的选择是余弦相似度,这是基于空间中两个向量之间的角。
空间中的 2D 矢量。作者图片
合乎逻辑的是,当向量在空间上越靠近(它们之间的角度越小),它们就越相似。因此,如果我们将**余弦(两个向量之间的角度)作为度量,**我们将在角度接近 0 时获得高相似性,否则获得低相似性,这正是我们想要的。
我们还需要一个可以最小化的损失函数。一种选择是 NT-Xent(归一化温度标度交叉熵损失)。
我们首先计算两幅增强图像相似的概率**。**
来源:Amit Chaudhary 的图解 SimCLR 框架,友好
注意,分母是 e^similarity( 所有对的总和,包括负对。负对通过在我们的增强图像和我们批次中的所有其他图像之间创建对来获得。
最后,我们将这个值放在一个 -log() 中,使得最小化这个损失函数对应于最大化两个增强图像相似的概率。
来源:Amit Chaudhary 的图解 SimCLR 框架, amitness
要了解更多关于 SimCLR 的细节,我推荐阅读下面的文章。
*https://amitness.com/2020/03/illustrated-simclr/
SimCLR 版本 2
值得注意的是,自最初发布 SimCLR 框架以来,作者对管道进行了以下重大改进[2]:
- 更大的 ResNet 型号用于 Big-CNN 编码器——152 层 Res-Net,3 倍宽的通道,选择性内核,注意机制。
- 更多投影头— 转换中间表示时使用三个密集层,而不是两个。
对比学习的应用
半监督学习
当我们只有很少的标签时,或者如果很难获得特定任务(即临床注释)的标签,我们希望能够使用已标记数据和未标记数据来优化我们模型的性能和学习能力。这就是半监督学习的定义。
一种在文献中日益流行的方法是无监督预训练、有监督微调、知识提炼范式【2】。
半监督学习范式综述。来源:[2]
在这种范式中,自我监督对比学习方法是一个关键的“预处理”步骤,它允许大 CNN 模型(即 ResNet-152)在试图使用有限的标记数据对图像进行分类之前,首先从未标记数据中学习一般特征。
谷歌大脑团队证明了这种半监督学习方法非常具有标签效率,并且更大的模型可以带来更大的改进,特别是对于低标签分数。
随着模型变大,模型在各种标签分数下的最高精度。来源:[2]
NLP 模拟
有趣的是,类似的自我监督方法已经在自然语言处理领域广泛使用。
例如, Word2Vec ,一种将文本转换为嵌入向量的算法,使用了类似的自我监督方法。在这种情况下,我们希望句子中彼此更接近的单词具有更相似的向量表示。
来源:克里斯·麦考密克的图, Word2Vec 教程——跳格模型
因此,我们通过在一个窗口内的单词之间创建配对来创建我们的“积极配对”。我们使用一种叫做负采样的技术来创建我们的负对。
这篇文章包含了对 Word2Vec 算法的直观和详细的解释。
http://jalammar.github.io/illustrated-word2vec/
就像 SimCLRv2 一样,Word2Vec 允许“相似”的单词在潜在空间中具有更相似的向量表示,我们可以将这些学习到的表示用于更具体的下游任务,如文本分类。
关键要点
- 对比学习是一种自我监督、独立于任务的深度学习技术,允许模型学习数据,甚至是没有标签的*。*
- 模型通过学习哪些类型的图像是相似的,哪些是不同的,来学习关于数据集的一般特征。
- SimCLRv2 是对比学习方法的一个示例,该方法学习如何表示图像,使得相似的图像具有相似的表示,从而允许模型学习如何区分图像。
- 对数据有大致了解的预训练模型可以微调用于特定任务,如图像分类当标签稀缺时显著提高标签效率,并有可能超过监督方法。
我希望这篇文章对什么是对比学习,对比学习是如何工作的,以及什么时候你可以将对比学习应用到你自己的项目中,提供一个清晰的直觉。自我监督学习真的很神奇!
参考
【1】Islam 等.利用视网膜眼底图像进行基于深度学习的糖尿病视网膜病变早期检测和分级,2018
[2]陈等.大自监督模型是强半监督学习器,2020****
理解卷积神经网络
原文:https://towardsdatascience.com/understanding-convolutional-neural-networks-316d0bb099a4?source=collection_archive---------39-----------------------
看一看引擎盖下面
图片由维基共享资源上的 Cecbur 提供
在本文中,我将训练一个深度神经网络来对图像进行分类,但我也将让您了解神经网络本身内部正在发生什么,以及卷积实际上是如何工作的。
我们将探讨以下部分。
卷积
∘ 滤波器
∘ 池化
网络
∘ 预处理
∘ 模型
∘ 训练网络
预测
神经网络“看到”了什么?
我将向你展示网络的运行,向你展示当它通过潜入它的“大脑”——网络的各层——做出决定时,它实际上“看到”了什么,我们将一起努力理解它如何决定图像的重要特征。
当你看到一只猫的图像时,你(也就是你的大脑)是如何识别出图像中有一只猫的?即使你以前没有见过具体的动物,你又如何区分猫和狗呢?
这些问题很难回答。也许我们应该从简单的开始…
你如何给计算机编程来识别图像中的猫?一只随机出现在图片中的猫。
你可以通过观察猫的不同特征来捕捉猫的本质,比如毛发的长度和颜色或者耳朵的形状。
但是这种方法有几个大问题。
首先,不同种族的猫看起来很不一样,你不可能捕捉到它们所有的特征。第二,不依赖于猫在图像中位置就能检测出猫的算法并不简单。
如果你观察像素,左边有一只猫的图像和右边有一只猫的图像看起来非常不同。
你如何独立于猫的位置和大小来检测猫?这是一个非常棘手的问题,如果不是不可能的话,通过经典编程来解决。
回旋
卷积的思想是通过以一种非常聪明的方式检测猫的特征来解决上述问题。
我们使用有监督的机器学习算法,而不是显式地对它们编程。
也就是我们拿一个有一定架构的神经网络。然后我们给它看很多带有相应标签的图像(像猫和狗,通过训练,它会学习当我们要对猫狗的图像进行分类时,哪些特征是最重要的。
然而,标准的神经网络不能立即解决上述“大小和位置”问题。
这就是回旋的用武之地。你看,卷积通过使一些像素值变大和变小来突出一些形状。因此他们改变了形象。
过滤
它的工作方式如下。我们用过滤器,这只是二维数组的数字,你应该想象我们通过图像的像素。
对于图像的每个像素值,将滤镜居中放置在该像素的“上方”,并将滤镜的每个数字乘以其正下方的像素。我们将这些新值作为像素放在新图像中。
图片由 Vincent Dumoulin,Francesco Visin 在维基共享资源上提供
这些操作的结果被传递到网络的下一层。
这类似于视觉皮层中的神经元对特定刺激的反应,因此这种架构受到生物大脑的启发。
—维基百科
更低级地说,对于每个过滤器,结果图像是输入图像的变换,其中,根据过滤器,一些特定的形状被突出显示。
联营
CNN 的第二个要素是池的概念。
共用是指通过将 n×n 个像素向下映射到 1 个像素来对图像进行缩减像素采样。同样,您应该想象一个 n×n 的数组在图像上移动,但这次不需要多次映射像素,而是将不相交的正方形映射到像素。
图片由 Andreas Maier 在维基共享资源上提供
此过程将保留重要特征,但会缩小图像大小。例如,如果我们使用一个 2×2 的数组进行池化,得到的图像将缩小 4 倍。
网络
在这一段中,我将向你展示如何处理未经预处理的图像数据!
首先要做的是获取一些数据。
在本教程中,我将从 Kaggle 下载狗和猫的图像。你可以在这里得到它们。
我已经解压了 train.zip 并将文件夹放在名为 data 的目录中。也就是说,我有路径 data/train ,所有的训练图像都在这里。
如果一个图像以“猫”开始,那么它是一只猫的图像,如果它以“狗”开始,那么它是一只狗的图像。我将使用此模式将训练数据分类为狗和猫。
预处理
现在我们需要做一些预处理。我将创建两个函数来完成这项工作。
现在只需创建一些目录,并使用适当的参数运行这些函数。
您可以通过运行以下命令进行快速检查,以确保它正常工作:
输出应该是
11250
11250
1250
1250
现在我们已经完成了预处理部分,好戏就要开始了。
模型
让我们构建将要训练的神经网络的架构,并将其保存到一个名为 model 的变量中。
现在如果我们跑
print(model.summary())
我们得到以下输出
让我们试着从这个图像中理解神经网络的架构。您应该注意的第一件事是,第一次卷积后得到的变换图像看起来是 148×148 的形状,即使我们输入的网络图像是 150×150 的形状。
原因很简单。当第一次卷积发生时,我们使用一个 3 × 3 的阵列在图像上滑动。现在,由于数组中的每个值都需要在图像中的某个像素之上,所以数组的中心不能在图像边缘的任何像素之上,因为这样一来,数组中的一些相邻数字下面就没有像素了。
因此,我们切掉边缘,留下一个 148×148 的图像。
此外,请注意,由于我们使用了一个 2×2 的数组,因此池层的输出要小 4 倍(每边的一半)。
在进入网络的第二状态之前,我们有三对卷积池层。
第二个状态是实际分类发生的地方。在展平层之后,神经网络查看卷积的提取特征,并尝试将它们分类为狗或猫。
通过查看代码,您可能会注意到最后一层仅由一个神经元组成。这个神经元的激活函数是 sigmoid 函数,它是
σ(x)= 1/(1+e^(-x)).
当 x 是一个非常大的负数时,sigmoid(x)变得接近 0 ,当 x 是一个非常大的正数时,sigmoid(x)变得接近 1 。
神经网络因此学习到根据 sigmoid 函数的这种二元行为来对猫和狗进行分类。
既然我们已经设计了模型,我们需要训练它。首先,让我们创建一些生成器。
反过来,这些发生器将把数据成批地输入神经网络。标签将从我们在预处理阶段创建的图像的文件夹名称中继承。
我们还将进行图像增强,这是确保我们的网络“看到”更多数据的一种方式。如果它没有在训练数据中以一个角度看到一只正在攀爬的猫,它可能不会在训练时将其归类为猫。在将图像传送到网络之前,通过以不同方式旋转、移动、剪切和翻转图像,我们将确保训练数据捕获尽可能多的特征。
你可能会注意到我们也在重新缩放图像。这是标准做法,被称为规范化。其思想是,重要的是像素值之间的关系,而不是像素值本身。
当然,这不仅适用于图像数据。
这个生成器很酷的一点是,实际转换的图像没有保存在磁盘上,你的训练数据保持不变。就在它们被馈送到网络进行训练之前,在 RAM 中动态地发生增强。
我们还需要将目标大小设置为 150×150,因为这是我们告诉模型的输入形状。
训练网络
让我们训练模型。
你不需要 TensorBoard 回调,但是如果你知道它是什么,请随意使用它。我将在另一篇文章中讨论这个问题。
当我运行时,我得到了大约 0.76 的验证精度,这意味着它正确地分类了大约 76%以前没有见过的图像。当然,这是在我们调整模型的超参数等等之前。
如果我们得到更多的训练数据,精确度就会提高。另一种获得更好模型的方法是使用迁移学习,在一个巨大的预先训练好的模型上建立你的网络。我将在另一篇文章中向您展示如何做到这一点。通过这种方式,你可以得到 90%以上的精确度。
预测
让我们以下面一只猫为例。
图片由维基共享资源上的 Alvesgaspar 提供
我们可以问我们新训练的神经网络这是猫还是狗。
我运行这段代码时的输出是
cat
非常好。
神经网络“看到”了什么?
让我们试着深入了解一下,试着弄清楚网络认为哪些特性是重要的。
让我们看一下训练数据中的一幅图像,看看它是如何通过网络进行转换的。以下图像是训练好的网络中卷积层的输出,让我们了解网络学习到的哪些滤波器最重要。
作者图片
作者图片
作者图片
如果你仔细观察,你会发现在第一次回旋后,猫的胡须和耳朵都亮了,这表明这些是将它归类为猫的重要特征。
如果你看第三个图像,似乎眼睛也很重要。
这表明,卷积神经网络可以识别形状,而不管形状的大小和位置,因为它通过卷积来学习哪些过滤器最重要。然后,具有 sigmoid 输出的简单神经网络通过反向传播校准其权重,以从卷积中对这些图像特征进行分类。
这篇短文展示了 TensorFlow 必须提供的一些强大的 API。希望这也能给我们一个关于卷积到底是什么的直觉。
如果您有任何问题、评论或顾虑,请在 LinkedIn 上给我发短信。
https://www.linkedin.com/in/kasper-m%C3%BCller-96ba95169/
了解卷积神经网络(CNN)
原文:https://towardsdatascience.com/understanding-convolutional-neural-networks-cnns-81dffc813a69?source=collection_archive---------17-----------------------
对最强大的深度学习工具之一及其构建模块的温和介绍
原文由安德鲁·舒尔茨在 Unsplash
本文将涵盖卷积神经网络(CNN)的所有主要方面,它们如何工作以及这项技术的主要构件。本文中使用的参考资料可以在我的 github 资源库中找到。
卷积神经网络(CNN)或简称为卷积网络是一种至少在其一层中使用卷积运算而不是矩阵乘法的神经网络。
这种类型的网络有效地用于数据元素与其相邻元素具有某种关系的应用中,如图像(由二维像素阵列表示)或时间序列或音频文件(由规则时间帧中的一维数据点样本序列表示)。
由于能够有效地提取图像特征,细胞神经网络被广泛应用于目标检测、人脸识别、语义分割、图像处理和操作等任务中。一些摄像头也有基于 CNN 的智能过滤器,自动驾驶汽车使用这些网络来导航和检测障碍物,许多其他系统都基于这种方法。
卷积运算
卷积是两个函数之间的线性数学运算。给出了函数 x(t) 和 w(a) ,分别称为输入和内核。函数 x 与 w 的卷积超过 a ,对于给定的为:
通配符运算符 (xw) 代表卷积,输出***【s(t)通常称为特征图。
该算子可以扩展到离散函数,这是在一维 CNN 上使用的情况(例如用于时间序列的情况):
而在 2D 卷积的情况下,非常用于图像处理,并且考虑到将I 作为输入图像,并且将 K 作为二维核,卷积可以表示为:**
通常核比图像小,卷积使用一个核来处理整个图像。由于简化的表示,每个卷积核(或层)需要学习少量的参数。
另一方面,由于标准 ann(人工神经网络)使用权重矩阵将给定层的神经元连接到前一层的输出,每个权重将代表一个单一的连接,因此对于相同的任务,ann 将需要学习比等效 CNN 多得多的参数。
图像卷积
正如我已经说过的,卷积广泛用于图像处理。通过改变使用的内核,有可能操纵模糊和形状,改变图像的风格或检测其边缘。下图显示了一些不同内核在基础映像上的应用。
在基础映像上使用不同的内核。内核是在它们各自的图像下表示的矩阵。图片作者。
核应用于图像的每个像素,核和图像受影响区域之间的卷积运算的结果将成为输出图像上的新像素,如下图所示。但是,内核不能应用于边界像素,因为内核的一部分会在图像之外,因此,生成的图像比原始图像稍小。
图像上的二维卷积。内核(蓝色)应用于图像(红色)。操作的结果将成为输出图像的新像素(绿色)。由于内核不能应用于真实图像之外,因此绿色区域是卷积发生的地方,从而产生一个稍小的图像。在卷积过程中,内核将滑过原始图像。图片作者。
在上图中,5x5 内核(蓝色)与 16x12 图像(红色)的卷积将产生 12x8 图像(绿色)。新的宽度和高度可以用下面的公式计算:
在 CNN 上,我们认为卷积是网络的一层,但是每层可以有一个以上的核。输出将具有与内核数量相同的特征映射。
例如,具有 4 个内核的卷积层接收尺寸为(winxhinx 1)的灰度图像,将产生尺寸为(woutxhoutx 4)的矩阵作为输出。该矩阵将不再被认为是图像,而是对应于由该层的四个内核检测的特征的一组四个特征图。
通过在构成网络结构的层上链接特征地图和内核,CNN 可以捕捉图像上存在的各种特征,这是允许这些网络学习识别物体和其他特征的过程。
多核过滤器
在多通道图像中,如 RGB 图像或由网络内层产生的特征图,卷积将在每个通道一个核的情况下发生。所有这些内核一起形成一个滤波器,每个滤波器的内核数量与输入图像的通道数量相同。
多核过滤器示例。图片作者。
每个滤波器将产生一个单一的特征图,因此我们需要通过求和或求平均值来聚集各个内核的输出,从而产生该滤波器的单一输出。
使用 n 滤镜的图层将生成 n 特征地图作为图层的输出。
填料
为了避免图像边缘像素上的内核卷积问题,我们可以在输入上应用填充。我们可以通过简单地在边框上添加更多的像素来放大它。
下图说明了三种类型的填充:零填充(a)在输入图像的周界上插入值 0;将内部像素反射到边界上的反射填充*;以及用常数值(包括 0)填充新边框的常量填充 (c)。***
填充边界的大小可以由网络的创建者决定,但通常我们选择一个值来消除输出图像上的缩减效果。我们可以用下面的公式计算新的尺寸:
联营
当网络学习最佳滤波器以仅从图像中提取相关特征时,每个滤波器也将产生噪声和与后续层不相关的信息。我们可以在卷积示例中看到,边缘检测器发现了一些不属于狗的像素。
池技术用代表像素组的值来代替像素组。下图说明了大小为 2 的MaxPool
,它将像素分组为 2x2 的正方形,并用最强像素的值替换整个组。类似地,我们可以执行AvgPool
,其中产生的像素是组的平均强度。
最大池操作。图片作者。
作为池层的直接结果,信息被压缩,只保留对后续层最重要的信息并减少干扰。输出也减少了一个因子,该因子取决于池大小(在本例中,输出的宽度和高度是输入的一半),因此每个卷积需要处理的像素更少,结果网络变得更有效。
下图说明了MaxPool
和AvgPool
在应用于狗图像的边缘检测器结果中的应用。
池技术在边缘图像上的应用。图片作者。
MaxPool
的另一个重要方面是,它使网络对输入端的小转换更加健壮。由于相邻像素被所有像素中的最高值替换,如果转换将最重要的像素保留在同一组中,结果将保持不变。
进展
我们还可以使用步长卷积来降低图像(或特征图)在各层中的维数。stride 参数表示每次迭代后内核将行走多少像素(或矩阵元素)。
在前面的例子中,我们使用了 stride = 1,这意味着内核将移动到下一个像素,当一行结束时,它将继续下一行。下图的上半部分通过对红色输入应用 5x5 内核来说明这种情况。蓝色方块代表每次迭代中内核的中心。
图片的下半部分代表步幅= 2 的情况。在这种情况下,当在行上行走时,内核将跳过一个像素,当行结束时,它也将在继续之前跳过一整行。正如我们所看到的,内核停止的像素比前一种情况少,所以生成的图像更小。
比较跨距= 1(上)和跨距= 2(下)的卷积。产生的输出大小不同。图片作者。
当我们想要恢复小于输入的输出时,维数减少是很重要的,例如编码器想要压缩图像,或者二进制分类器有一个单一的值作为输出。
我们可以为宽度( wstride )和高度( hstride )定义不同的步幅,因此可以使用下面的表达式来计算得到的尺寸。
转置卷积
在其他应用中,我们可能希望在一层之后增加输出的维度。一些生成方法通常从压缩表示(如潜在向量)开始,并通过层增加维度,直到输出生成最终图像。
实现这一点的一种方法是使用转置卷积(很多时候会被反卷积误操作),即在输入图像通过“传统”卷积之前,结合使用填充和步幅来放大输入图像,从而使输出大于输入。
下图说明了通过使用核为 3x3 且步幅= 1 的转置卷积,从 3x3 输入生成 5x5 图像的过程。
转置卷积。图片作者。
在 5x5 图像中,内核为 3x3 且步幅= 1 的“传统”卷积将生成 3x3 特征图作为输出,因此我们需要使用相同的参数执行转置卷积,以实现相反的操作。
它分两步走:
- 图像将在其原始像素(红色)之间以及边界上插入零值像素(灰色)。
- 现在,卷积将应用于放大的图像,内核为 3x3,步幅= 1。
为了计算转置卷积后的输出维数,我们可以使用以下公式:
转置卷积并不是增加图层输出维度的唯一方法。其他架构使用传统的调整大小技术,如最近邻插值,然后是传统的卷积层。
棋盘文物
转置卷积的一个缺点是,当通过图像时,内核会重叠,从而加强这些区域中像素的重要性。结果,生成的图像(或特征图)将具有周期性出现的棋盘状伪像。这种机制可以在下图中看到。
产生棋盘状伪像的机制。图片作者。
通过使用其他技术,如上面提到的调整卷积大小,我们可以避免这种影响。
结论和意见
关于卷积有很多东西要学,但第一步是理解基础知识,我希望这篇文章对很多人有帮助。
这篇课文改编自我的硕士学位论文。
特别感谢我的狗布鲁斯,他好心地让我给他拍照并用作例子。他是最好的男孩。
如果你喜欢这个帖子…
支持我一杯咖啡!
**
给我买杯咖啡!**
看看这个很棒的帖子
**</5-tips-to-start-a-career-in-data-211ad15a7ca8>
参考
奥登纳等。艾尔。反卷积和棋盘状工件
古德费勒等人。艾尔。深度学习。第九章:卷积网络
一般化和网络设计策略。技术报告 CRG-TR-89–4
Dumoulin,v .,Visin,F.: 深度学习卷积算法指南。arXiv:1603.07285 (2016 年)
拉德福德,a .,梅斯,l .,钦塔拉,S.: 深度卷积生成对抗网络的无监督表示学习。**
手动理解卷积与张量流
原文:https://towardsdatascience.com/understanding-convolutions-by-hand-vs-tensorflow-8e64053f673e?source=collection_archive---------21-----------------------
你觉得我们可以手工匹配 TensorFlow 吗?你打赌!
图片由作者提供,灵感来自来源。
1.目的
TensorFlow 和各种其他用于机器学习的开源库,如 SciPy,提供了这些用于执行卷积的内置函数。然而,尽管这些函数很好,但是打开引擎盖去发现代码背后的强大功能是值得的。在我看来,如果没有卷积层,计算机视觉就会像蝙蝠一样瞎。因此,我希望您喜欢这篇文章,因为我们将深入研究构成卷积层的卷积,并一起了解全局。
我为此制作的 Jupyter 笔记本在我的 GitHub 上。
2.背景
卷积对于计算机视觉中的深度学习任务来说并不新鲜。它们只是图像处理中使用的一种技术。在图像处理中,卷积运算是将输入图像的每个元素与其局部相邻元素相加的过程,通过内核进行加权。输出大小将取决于以下因素:
图片由作者提供,灵感来自来源。
3.输入过滤器
玉米粒有各种形状和大小。这些内核组成了滤波器,滤波器是卷积层中使用的一个参数。对于本文,我将坚持使用基于边缘检测的普通过滤器:
图片作者。
4.输入音量
为了便于对示例进行数学检查,我将使用 5x5x3 的随机输入量:
图片作者。
5.零填充
通常,零填充被添加到输入图像中。因此,在本例中,我将添加一个零填充,P=1,这将返回 7x7x3 的输入量:
图片作者。
6.进展
对于这个例子,步幅将是 S=2。
7.手算输出量
将过滤器通过左上方输入体积的局部感受野:
图片作者。
按步幅移动,S=2:
图片作者。
手动将它投入使用:
现在将过滤器通过整个输入体积:
图片由作者提供,灵感来自来源。
8.使用张量流
厉害!与我在上一节中手工做的相匹配。现在让我们试着以 S=1 的步幅传递一个图像。
图片作者。
图片作者。
使用 TensorFlow:
图片作者。
不出所料!TensorFlow 和手动定制功能产生相同的卷积图像。边缘检测过滤器现在真的更有意义了,因为你可以看到玩具驯鹿周围的线条。
这是卷积神经网络(CNN)如此伟大的原因之一。随着卷积层被训练,权重(核)被更新,并且有希望创建有意义的特征图,以使用训练过的模型来执行你的计算机视觉任务。
感谢您的阅读!我希望你已经学到了一些关于卷积的新知识,如果你还不能看到的话,我希望你能在这之后看到更大的图景。
9.参考
1.内核(图像处理)[https://en . Wikipedia . org/wiki/Kernel _(图像处理)]
2.TF . nn . conv 2d[【https://www.tensorflow.org/api_docs/python/tf/nn/conv2d】T2
3.Python。特拉维斯·奥列芬特。用于科学计算的 Python,《科学与工程中的计算》, 9,10–20(2007 年 b) K. Jarrod Millman 和 Michael Aivazis。面向科学家和工程师的 Python,科学与工程中的计算,13,9–12(2011)
4.张量流。马丁·阿巴迪、阿希什·阿加瓦尔、保罗·巴勒姆、尤金·布莱夫多、陈质枫、克雷格·西特罗、格雷格·科拉多、安迪·戴维斯、杰弗里·迪恩、马蒂厄·德文、桑杰·格玛瓦特、伊恩·古德菲勒、安德鲁·哈普、杰弗里·欧文、迈克尔·伊萨德、拉斐尔·约泽福维茨、杨青·贾、卢卡斯·凯泽、曼朱纳斯·库德鲁尔、乔希·莱文伯格、丹·曼内、迈克·舒斯特、拉杰特·蒙加、雪莉·穆尔、德里克·默里、克里斯·奥拉、黄邦贤·施伦斯、伯努瓦·施泰纳 TensorFlow:异构系统上的大规模机器学习,2015。tensorflow.org 提供的软件。
5.SciPy。保利·维尔塔宁、拉尔夫·戈默斯、特拉维斯·奥列芬特、马特·哈伯兰、泰勒·雷迪、戴维·库尔纳波、叶夫根尼·布罗夫斯基、皮鲁·彼得森、沃伦·韦克塞、乔纳森·布赖特、斯蒂芬·范德沃特、马修·布雷特、约书亚·威尔逊、贾罗德·米尔曼、尼古拉·马约罗夫、安德鲁·纳尔逊、埃里克·琼斯、罗伯特·克恩、埃里克·拉森、希杰·凯里、i̇lhan·波拉特、余峰、埃里克·摩尔、杰克·范德普拉斯、丹尼斯·拉克萨尔德、约瑟夫·佩尔(2019)SciPy 1.0-Python 中科学计算的基本算法。预印本 arXiv:1907.10121
6.NumPy。特拉维斯·奥列芬特。美国 NumPy 指南:特雷戈尔出版公司(2006 年)。(b)斯蒂芬·范德沃特、克里斯·科尔伯特和盖尔·瓦洛夸。NumPy 数组:高效数值计算的结构,科学与工程中的计算,13,22–30(2011)
7.IPython。费尔南多·佩雷斯和布莱恩·格兰杰。IPython:用于交互式科学计算的系统,科学与工程中的计算,9,21–29(2007)
8.Matplotlib。亨特,“Matplotlib:2D 图形环境”,《科学与工程中的计算》,第 9 卷,第 3 期,第 90–95 页,2007 年。
9.熊猫。韦斯·麦金尼。Python 中统计计算的数据结构,第 9 届科学中的 Python 会议录,51–56(2010)
10.sci kit-学习。法比安·佩德雷戈萨、加尔·瓦洛夸、亚历山大·格拉姆福特、文森特·米歇尔、贝特朗·蒂里翁、奥利维尔·格里塞尔、马蒂厄·布隆德尔、彼得·普雷登霍弗、罗恩·韦斯、文森特·杜伯格、杰克·范德普拉斯、亚历山大·帕索斯、戴维·库尔纳波、马蒂厄·布鲁彻、马蒂厄·佩罗特、爱德华·杜谢斯奈。sci kit-learn:Python 中的机器学习,机器学习研究杂志,12,2825–2830(2011)
11.sci kit-图像。斯蒂芬·范德沃特、约翰内斯·l·舍恩伯格、胡安·努涅斯-伊格莱西亚斯、弗朗索瓦·布洛涅、约书亚·d·华纳、尼尔·雅戈、伊曼纽尔·古亚尔特、托尼·于和 scikit-image 供稿者。sci kit-Image:Python 中的图像处理,PeerJ 2:e453 (2014)
用随机几何图形理解 DBSCAN 和 K-NN
原文:https://towardsdatascience.com/understanding-dbscan-and-k-nn-with-random-geometric-graphs-ed26cf5e5b71?source=collection_archive---------16-----------------------
作者提供的图片
实践教程
从距离矩阵到图形
在这篇文章中,我们将更详细地探索空间网络的具体属性,并使用它们来深入了解两种流行的机器学习算法,k-最近邻和 DBSCAN 。
我们从关注最简单的例子随机几何图形 (RGG)开始探索空间网络。rgg 是通过简单地将节点随机放置在某个(比如说,2D)空间中,并在某个距离 d 内的任何一对节点之间添加一条边来构建的
虽然这种结构可能看起来像是只有最纯粹的数学家才会玩的那种东西,但它是一种令人惊讶的有用的图形结构,在现实世界中具有实际应用,例如用于近距离连接无人机的自组网络。
亚马逊最近甚至有一项这类应用的专利,你可以在 USPTO 阅读更多内容,内华达大学机器人实验室的研究人员提出了一种无人机协调搜救行动的算法。
随机几何图形
事不宜迟,让我们建造我们自己的 RGG。我们首先在单位正方形中随机放置 100 个节点:
下一步是连接在一定距离 d 内的所有节点。为此,我们计算包含所有节点对之间距离的距离矩阵。
计算全距离矩阵有点浪费,因为它需要 O(N)个工作。一种更复杂的方法是使用 KDTrees 来实现线性性能,但这超出了本文的范围,因为我们只是试图熟悉这些概念,而不是开发一个实际的实现。
使用这个矩阵,我们可以很容易地计算每对节点之间的距离分布 P(d)和距离的累积分布 C(d)。
该分布遵循准钟形曲线(实际分布更有趣一点)。从累积分布可以清楚地看出,根据我们为 RGG 选择的阈值 d,我们将得到或多或少的边缘。
在 GitHub 存储库中,您可以使用一个交互式工具来查看距离矩阵和图形在您更改阈值时是如何变化的:
如果你更倾向于数学,你可以把这个阈值距离矩阵想象成图的一个加权邻接矩阵。在以后的文章中,我们会有更多关于邻接矩阵的内容,但是现在你需要知道的是,邻接矩阵只是一个矩阵,其中每个非零元素对应于两个节点之间的一条单独的边。
k-最近邻
k-最近邻算法是一个众所周知的机器学习算法家族,可用于分类或回归。这两种情况下的基本思想都相当简单。如果你想知道一个新数据点的标签或值应该是什么,你可以咨询它的 k 近邻,然后简单地采用大多数。k 的具体值是在训练模型时必须定义的超参数。
与随机几何图形的联系现在应该很清楚了。我们简单地将每个节点与其 k 个最近的节点连接起来,而不是仅仅将每个节点与某个距离 d 内的所有其他节点连接起来。
当我们玩这个游戏,并连接每个先前的节点到它的 5 个最近的邻居,我们得到:
如果你仔细检查这个矩阵,你会开始注意到一些不寻常的东西。它是不对称的!确认这一点最容易的地方是沿着主对角线,你偶尔会注意到一边有一个值,而另一边没有。这似乎是一个非常奇怪的结果。如果我们的距离度量是对称的,欧几里德距离肯定是对称的,那么网络怎么可能不是对称的呢?原因可以用一个简单的例子来说明。
想象一下,由于某种奇怪的命运转折,你发现自己完全孤独,迷失在撒哈拉沙漠中。在那个时刻,地理上离你最近的 5 个人可能在最近的城市,但是他们都有比你更近的人!你只是一个古怪的异类。验证这种直觉的一种方法是检查节点的入度分布。您会发现,与每个节点恰好有 k 条传出边的出度不同,一个节点可以有更多或更少的传入边,这取决于它与聚类外围的接近程度以及有多少离群值。
这是关于 k-NN 算法的基本观点。更中心的节点将通过许多短距离链路连接,而离群点将连接到较远且具有很少或根本没有传入边的节点。
一个形象化的观点可以让我们明白这一点。这里我们绘制了与上图中的距离矩阵相对应的有向图。如果你仔细观察靠近图中心的孤立节点,你会注意到,虽然它有 5 条长的向外的边,但由于它的外围位置,它只有一条向内的边……迷失在撒哈拉沙漠的中央。
自然,如果我们要测量这个图中的距离分布,它看起来会与我们之前看到的非常不同,因为我们严格限制了允许的距离,只保留每个节点的 k 个最短外出边。
基于密度的噪声应用空间聚类
基于密度的含噪声应用空间聚类(DBSCAN)是一种无监督聚类算法,其明确目标是以有效的方式识别任意形状的聚类。最初的 KDD 论文将算法概括为:
为了找到一个聚类,DBSCAN 从一个任意点 p 开始,并从 p wrt 中检索所有密度可达的点。Eps 和 MinPts。如果 p 是一个核心点,这个过程产生一个聚类 wrt。Eps 和 MinPts(见引理 2)。如果 p 是一个边界点,没有点是从 p 密度可达的,DBSCAN 访问数据库的下一个点。
我们可以通过将该算法转换成网络算法来更直观地表达该算法,该网络算法明确地利用了我们上面讨论的 RGG 和 k-NN 算法的特征。DBSCAN 通过连接(用有向边)距离小于一定距离的点(节点)来识别数据集中的聚类(就像在 RGG s 中一样)。外围节点和离群节点的输出少于 k(就像在中的 k-NN )。相比之下,任何在规定距离内有 k 个或更多邻居的节点称为“核心节点”。最后,数据中的聚类可以用结果图中的连接组件来唯一标识。
这种显式构建每个节点的邻域的方法计算量大,需要 O(N)存储空间,而更有效的实现(如原始论文中的实现)可以显著降低内存和计算需求。
def net_DBSCAN(X, eps=0.17, min_samples=5):
# Building the neighborhood matrix and truncate it
# at the maximum distance
matrix = distance_matrix(X, X)
matrix[matrix >= eps] = 0 # Build the directed graph using the non-zero elements of the matrix
G = nx.DiGraph()
G.add_edges_from(np.asarray(np.nonzero(matrix)).T) # Create an undirected version of the network for ease of core computation
G2 = G.to_undirected() # Find all core nodes
results = {}
results['core_sample_indices_'] = [node_i
for node_i, k in G2.degree()
if k >= min_samples-1] # Use the connected components to label each node
# as belonging to each cluster
labels = []
for label, comp in enumerate(nx.connected_components(G2)):
for node in comp:
labels.append(label) results['labels_'] = np.asarray(labels)
results['G'] = G # Identify the outlier nodes.
results['non_core'] = set(np.arange(X.shape[0])) - set(results['core_sample_indices_']) return results
当我们将上面的代码应用到 two moons 数据集时,我们得到:
其中蓝色和紫色表示数据集中的两个集群,绿色方块表示“非核心”节点。与 sklearn 实现完美匹配:
我们希望你喜欢这种看待古老的 k-NN 和 DBSCAN 算法的方式,并对它们如何工作有了新的认识。你可以在我们的伙伴 GitHub 库【https://github.com/DataForScience/Graphs4Sci找到这篇文章中分析的所有代码
当然,别忘了注册我的时事通讯,这样你就不会错过另一篇文章了。
理解深度可分卷积和移动网络的效率
原文:https://towardsdatascience.com/understanding-depthwise-separable-convolutions-and-the-efficiency-of-mobilenets-6de3d6b62503?source=collection_archive---------5-----------------------
移动网和深度可分卷积的解释
简介:
在卷积神经网络(CNN)中,2D 卷积是最常用的卷积层。MobileNet 是一种 CNN 架构,速度更快,模型更小,使用了一种新的卷积层,称为深度方向可分离卷积。由于模型的尺寸较小,这些模型被认为对于在移动和嵌入式设备上实现非常有用。因此得名 MobileNet。
关于 MobileNets 的原始论文可在此处获得— MobileNets:用于移动视觉应用的高效卷积神经网络
表 1。MobileNet 与 GoogleNet 和 VGG 16 的参数和准确性比较(来源:原始论文中的表格)
表 1 清楚地显示了即使是最深入的 MobileNet 架构也比著名的 CNN 架构具有更少的参数。较小的 MobileNets 只有 130 万个参数。此外,模型的大小明显更小。虽然 VGG16 型号可以占用高达 500 MB 的磁盘空间,但 MobileNet 只需要 16–18MB。这使得它非常适合在移动设备上加载。
图一。MobileNets 可以用于移动设备上的对象检测、分类、属性检测,甚至是地标识别(来源:图片来自原论文)
深度方向卷积;
差异 —
2D 卷积和深度卷积之间的主要区别在于,2D 卷积是在所有/多个输入通道上执行的,而在深度卷积中,每个通道保持分离。
接近 —
- 3 维输入张量被分成单独的通道
- 对于每个通道,输入与滤波器(2D)进行卷积
- 然后将每个通道的输出叠加在一起,得到整个 3D 张量的输出
图形描述 —
图二。深度方向卷积的图解说明(来源:图片由作者创建)
深度方向可分离卷积;
深度方向卷积通常与另一个步骤(深度方向可分离卷积)结合使用。这包含两个部分— 1 .过滤(所有前面的步骤)和 2。组合(根据需要,组合 3 个颜色通道以形成“n”个通道——在下面的示例中,我们将看到如何组合 3 个通道以形成 1 个通道输出)。
图 3。深度方向可分离卷积的图解说明(来源:图片由作者创建)
为什么深度可分卷积如此高效?
深度方向卷积是 -所有通道上的 1x1 卷积
假设我们有一个大小为 8x8x3 的输入张量,
并且期望的输出张量的大小是 8×8×256
在 2D 回旋——
所需的乘法次数—(8×8)x(5x5x 3)x(256)=1,228,800
在深度方向可分离卷积中
所需的乘法次数:
a.滤波 —分成单通道,所以需要 5x5x1 滤波器来代替 5x5x3,由于有三个通道,所以需要的 5x5x1 滤波器总数为 3,所以,
(8x8)x(5x5x 1)x(3)= 3800
b.合并 —所需通道总数为 256,因此,
(8x8) x (1x1x3) x (256) = 49,152
乘法总数= 3800+49152 =53952
因此,2D 卷积需要 1,228,800 次乘法运算,而深度方向可分离卷积只需要 53,952 次乘法运算即可达到相同的输出。
最后,
1,228,800/53,952 = 23 倍减去所需乘法运算
因此深度方向可分卷积的效率很高。这些是在 MobileNet 架构中实现的层,用于减少计算数量并降低功耗,以便它们可以在没有强大图形处理单元的移动/嵌入式设备上运行。
MobileNet
- 使用 深度方向可分离卷积
- 使用两个 S 收缩超参数:
a.调整通道数量的宽度乘数
表二。MobileNet 中的宽度乘数(来源:原始论文中的表格)
b.分辨率倍增器,调整特征图和输入图像的空间尺寸
表 3。MobileNet 中的分辨率乘数(来源:原始论文中的表格)
架构—MobileNet 的第一层是全卷积,而所有后续层都是深度方向可分离的卷积层。所有层之后是批量标准化和 ReLU 激活。最终分类层具有 softmax 激活。完整的架构如表 4 所示。
表 4。MobileNet 架构(来源:原始论文中的表格)
图 4。左:标准卷积层,右:MobileNet 中深度方向可分离的卷积层(来源:图片来自原论文)
图 4 显示了普通 CNN 模型和 MobileNets 在架构流程上的区别。在图像的左侧,我们看到一个 3x3 卷积层,后面是批归一化和 ReLU,而在右侧,我们看到深度方向可分离卷积层,由一个 3x3 深度方向卷积和一个批范数和 ReLU 组成,后面是一个 1x1 点方向卷积,再后面是一个批范数和 ReLU。
结论:
MobileNets 是专门为移动设备设计的非常高效的小型深度学习架构。由于尺寸较小,与较大的全卷积架构相比,精度会有所下降,但这种情况非常微小。例如,在 Stanford dogs 数据集上,Inception V3 模型的准确率为 84%,而最大的 MobileNet 的准确率为 83.3%。但是如果我们看看每个模型架构的参数数量,Inception V3 有 2320 万个参数,而 MobileNet 只有 330 万个参数。此外,仅仅通过使用宽度倍增器或分辨率倍增器,就可以制作更小更快的 MobileNet 版本。这使得 MobileNets 成为移动和嵌入式设备上非常受欢迎的深度学习模型。
接下来,我打算展示如何使用 TensorFlow 在 python 中从头开始创建 MobileNet 架构。
参考文献:
- Howard,A. G .,Zhu,m .,Chen,b .,Kalenichenko,d .,Wang,w .,Weyand,t .,Andreetto,m .和 Adam,H. (2017)。MobileNets:用于移动视觉应用的高效卷积神经网络
理解设计文档原则
原文:https://towardsdatascience.com/understanding-design-docs-principles-for-achieving-data-scientists-53e6d5ad6f7e?source=collection_archive---------26-----------------------
行业笔记《数据科学家生产力指南》
使用正确的设计文档有效运行您的数据项目
来源( Unsplash
一个好的设计文档离不开一个好的数据科学家和工程师——Vincent Tatan,Google ML 工程师
在大多数情况下,工程师花了 18 个月的时间思考和撰写如何最好地为客户服务的文档。— 尤金·严,亚马逊数据科学家
上个月,我展示了设计文档不可否认的重要性,它将设计文档解释为构建和运行机器学习系统的概念灯塔。
由于设计文档非常重要,我很乐意分享我创建设计文档的原则,以有力地执行您的数据项目。
为什么?
来源( memegen )
设计文档提供了 概念灯塔来指导您的数据项目 。
- 设计文档从概念上指导 您在每一步中理解您的目标、影响和执行,以使利益相关者受益。设计文件确保您的项目落地产生影响。
- 设计文档为您节省设计时间在执行之前突出实施和替代解决方案。
- 设计文档主持团队间的讨论,集体讨论最佳解决方案并实施数据项目。
- 设计文档是永久的人工制品为未来的合作巩固你的想法。
谁啊。
你的读者是你写设计文档的关键原因。在每篇设计文档中,你必须了解你的受众,例如:
- 你自己:确定学习旅程,集思广益,制定未来有影响力的项目。
- 团队成员:识别协作点、升级和系统特定影响。在设计文档中,您需要将您的假设与团队成员的现有知识保持一致。
- 跨部门:识别跨部门协作。你的设计文档需要传达先验知识和成功标准。
- 高管:做决策。您需要提供可靠的建议来推动高级指标(例如:用户采用率、收入和商誉)
- **外部:**培养专业声誉和网络。你需要提供可靠的外卖,避免使用术语。
为合适的空间(环境)寻找合适的设计文档类型
我想强调三种不同的环境,它们需要不同类型的设计文档。对于术语,我将强调这些环境为解决方案空间:架构空间、实现空间和想法空间。
具有各自解决方案空间的设计文档层次结构(由作者提供)
建筑空间(稳定)
设计文件特征
- 目标:记录解决复杂问题并直接影响用户的系统的高层架构。
- 主要受众:高管、技术主管
- 时间:缓慢平稳。理想情况下,除非出现中断,否则它很少发生变化。
设计文件的类型
- 架构文档:记录具有明确目标的高层系统架构,例如,project Google Loon 旨在解决可靠的互联网基础设施匮乏的问题。
- **北极星指标:**确定衡量高管沟通成败的关键指标。例如,在面向客户的应用中,衡量标准将是用户采用率,而 it 将在反滥用应用中保护用户。
实施空间(启动)
设计文档特征
- 目标:促进系统设计实施,例如数据存储、ML Ops、数据隐私访问等。该文档确保数据产品得到正确的发布、扩展和评估。
- 主要受众:技术领导、跨部门(尤其是上下游应用)
- 时间:中度变化
设计文件的类型
- 系统设计:突出系统实施流程图、上下游交互、数据存储、申诉等。
- **时间表发布文档:**强调系统发布的进度和时间表。在谷歌,我们有标准的操作程序(SOP)来确保每次发布都得到适当的维护和扩展。
- **隐私文档:**管理关于用户或其他敏感机构的机密数据。
想法空间(实验)
设计文档特征
- 目标:试验小的调整、想法头脑风暴和快速反馈收集。创意空间允许数据专业人员寻找创意,以快速产生重大影响。
- 主要受众:包括跨部门的所有人
- 时间:高度动态。每天都有一个寻呼机被起草、分析和丢弃。你的目标是迅速失败,然后继续前进。
设计文件的类型
- **一页纸:**快速移动设计文档,以促进早期的想法审查。随着想法成长为成熟的概念,一页纸将被提升为两页纸和系统设计文档。
- 学习之旅:根据过去的演示、设计文档、发布的模型来确定学习之旅。在大公司,学习之旅对于跟踪跨部门和地区合作中快速发生的变化是必要的。
- **执行前评估:**如果我们推出一个产品(例如:模型/调整),预期的影响是什么?
- 执行后评估:在过去推出的产品后有什么影响(例如:模型/调整)?
- **预分析:**当产品推出时,哪些可能会出错?
- **事后分析:**过去推出产品后有哪些出了问题?
“如果你不知道你想在你的演讲中达到什么目的,你的观众永远也不会知道。”—哈维·戴蒙德
管理设计文档的五个原则
这些是关于如何管理设计文档的简单指南。
- 从想法开始:总是在一页纸上开始你的实验(想法空间)。创建一个思想实验,并在投入更多时间之前迅速进行头脑风暴。
- **在较低层次的空间投入时间:**空间越高(想法→实现→架构),就应该投入更多的时间。最多花 1 周在一页纸上(想法空间),1 个月在实施/分析空间,1 个季度/学期在架构空间。当然这取决于范围,但你得到了要点。
- 优先考虑有前途的 One Pagers: 根据影响推广和调整你的 One Pagers。如果这个想法是为了交叉协作,花更多的时间考虑你的目标如何与高层空间(北极星度量、系统设计等)保持一致。
- **登陆北极星:**对于一般的成功指标,关注时间投入最低的想法(例如:对机器学习的小调整),对北极星指标有很大影响。这有助于你为在更高的空间着陆打下坚实的基础。
- 直接指向金块:你的设计文档需要尽可能直接地将观众指向金块。空间越高,这个金块应该越直接。
结论
一般来说,通过了解这些原则,你将创建设计文档来帮助你:
- 在所有概念空间中导航动态的、不明确的或未被很好理解的项目。
- 产生具有高影响力的项目,这些项目可以促进高管沟通。
- 优化时间投资,以获得突出北极星指标的最佳效果。
我希望这篇文章能帮助您创建设计文档,并有效地运行您的数据项目。
索利·迪奥·格洛丽亚。
关于作者
文森特用 ML @ Google 对抗网络滥用。文森特使用高级数据分析、机器学习和软件工程来保护 Chrome 和 Gmail 用户。
除了在谷歌的工作,文森特还是《走向数据科学媒体》的特约撰稿人,为全球 100 多万观众的有志 ML 和数据从业者提供指导。
在空闲时间,文森特在佐治亚理工学院攻读硕士学位,并为铁人三项/自行车旅行进行训练。
最后,请通过 LinkedIn , Medium 或 Youtube 频道 联系文森特
参考
- Eugene Yan post 如何为机器学习系统撰写设计文档
- Clement Mihailescu 谈什么是软件工程中的设计文档
理解数据科学 R 中的降维和主成分分析
原文:https://towardsdatascience.com/understanding-dimension-reduction-and-principal-component-analysis-in-r-e3fbd02b29ae?source=collection_archive---------10-----------------------
什么是降维,我们如何使用 R 中的主成分分析来确定重要的特征
当你在数据科学和分析领域工作时,处理高维数据是其中的一部分。您可能有一个包含 600 个甚至 6000 个变量的数据集,其中一些列在建模中被证明是重要的,而另一些是无关紧要的,一些是相互关联的(如体重和身高),还有一些是完全相互独立的。我们非常清楚使用数以千计的特征对于我们的模型来说既乏味又不切实际,因此我们的目标是创建一个维数减少的数据集(全部不相关),以尽可能多地解释原始数据集中的变化。从高维数据到低维数据的转换需要我们提出 a)统计解决方案和 b)数据压缩活动,一种称为 PCA(主成分分析)的技术。
图片由 @marcojodoin 在【unsplash.com】T2 上
在本文中,我们将讨论三个目标:
- 理解降维的必要性
2.执行 PCA 并分析数据变化和数据组成
3.确定在数据识别中最有用的特征
“PCA 是机器学习中的一种无监督学习技术,它通过显示数据集中的最大变化(通过关注实际区分数据的变量),将高排名矩阵的维度降低为低排名矩阵,从而捕捉原始数据的本质。”
PCA 产生主成分(等于特征的数量),这些主成分按照方差的顺序排列(PC1 显示最大方差,PC2 显示第二大方差,依此类推)。为了更详细地理解这一点,让我们使用 r 中的 prcomp()函数来处理一个样本数据集。我使用了一个在data . world**(一个开源平台)**上可用的数据集,它为您提供了几种不同品牌的披萨的营养成分。我只保留了 A、B & C 品牌的披萨。csv 使我们的分析简单易懂。
步骤 1:导入库并将数据集读入表格
确保您在当前目录中。csv 被放置(使用 getwd())或者能够使用 setdw()将其更改为当前文件。
library(dplyr)
library(data.table)
library(datasets)
library(ggplot2)data <- data.table(read.csv("Pizza.csv"))
第二步:理解数据
这些函数告诉你 a)维数,即矩阵的行 x 列 b)数据的前几行和 c)变量的数据类型。
dim(data)
head(data)
str(data)
基本初始功能(图片由作者提供)
第三步:获取主成分
我们希望让我们的目标变量为空,因为我们希望我们的分析告诉我们有不同类型的比萨饼品牌。一旦我们完成了这些并复制了数据集以保持原始值,我们将运行 prcomp()。scale = TRUE,以便在分析前将变量缩放到单位方差。
pizzas <- copy(data)
pizzas <- pizza[, brand := NULL]pca <- prcomp(pizzas, scale. = TRUE)
关于 prcomp()需要知道的重要事情是,它返回 3 样东西:
- **x 😗* 存储数据的所有主要成分,我们可以使用这些成分来绘制图表,并了解 PC 之间的相关性。
- sdev :计算标准差,了解每台电脑在数据上有多少变化
- **旋转:**确定哪个加载分数对 PCA 图有最大影响,即最大坐标(绝对值)
第四步:使用 x
尽管目前我们的数据具有两个以上的维度,但我们可以使用 x 绘制我们的图表。通常,前几个 PCs 捕获最大方差,因此 PC1 和 PC2 绘制在下面以理解数据。
pca_1_2 <- data.frame(pca$x[, 1:2])
plot(pca$x[,1], pca$x[,2])
PC1 对比 PC2 图(图片由作者提供)
该图清楚地向我们展示了前两个 PCs 如何根据定义它们的特征将数据分成三个聚类(或 B & C 比萨饼品牌)。
步骤 5:使用 sdev
这里我们使用 sdev 的平方,并计算每台电脑的变化百分比。
pca_var <- pca$sdev^2pca_var_perc <- round(pca_var/sum(pca_var) * 100, 1)barplot(pca_var_perc, main = "Variation Plot", xlab = "PCs", ylab = "Percentage Variance", ylim = c(0, 100))
百分比变化图(图片由作者提供)
这个柱状图告诉我们,PC1 显示了几乎 60%的数据变化,PC2 显示了 20 %, PC3 显示了 12%,其余的 PC 捕捉到的数据变化很少。
步骤 6:使用旋转
这一部分解释了在区分比萨饼品牌时,哪些特征最重要;旋转将权重分配给特征(技术上称为负载), PC 的“负载”数组称为特征向量。
PC1 <- pca$rotation[,1]PC1_scores <- abs(PC1)PC1_scores_ordered <- sort(PC1_scores, decreasing = TRUE)names(PC1_scores_ordered)
(图片由作者提供)
我们看到变量*‘cal’(样品中每 100 克的卡路里量)是区分品牌的最重要特征,其次是‘mois’*(样品中每 100 克的水含量),依此类推。
第七步:利用两个最重要的特征区分品牌
ggplot(data, aes(x=data$cal, y=data$mois, color = data$brand)) + geom_point() + labs(title = “Pizza brands by two variables”)
通过权重最大的柱形成聚类(图片由作者提供)
该图清楚地显示了如何代替数据集中给我们的 8 列,仅两列就足以理解我们有三种不同类型的比萨饼,从而使 PCA 成为一种成功的分析工具,将高维数据减少到较低的一列,用于建模和分析目的。
这篇文章背后的灵感来自于约翰·霍普斯金在 Coursera 上开设的数据科学专业的第三门课程和 Josh Starmer 的 StatQuest。
将离散卷积理解为多项式乘法
原文:https://towardsdatascience.com/understanding-discrete-convolution-as-polynomial-multiplication-5f94a13acd55?source=collection_archive---------17-----------------------
卷积是数字信号处理中的一种基本运算
作者插图
卷积是数字信号处理中的基本运算。它通常由以下公式定义:
DSP 书籍从这个定义开始,详细解释如何计算。我们通过傅立叶变换了解了时域卷积与频域乘法的相同之处。有限和无限脉冲响应滤波器的操作用卷积来解释。这成为所有数字滤波器设计的基础。然而,卷积本身的定义仍然有些深奥。对我来说,这个定义一直有点神奇,直到我仔细研究了多项式代数。然后,关于这个定义如何自然产生的实现发生了。从那以后,它一直伴随着我。我妹妹今天让我解释卷积运算。最初,我试图用典型的 DSP 方法来解释,但毫无效果。最后,我回到了多项式乘法的方法,这对她来说是显而易见的。所以它来了。
考虑两个简单的多项式:
计算他们的产品:
如果我们把 h(x)写成
那么我们可以将 h(x)的系数匹配为:
一种模式似乎正在形成。让我们更大胆地使用二次多项式:
这是他们的产品:
h(x)现在具有系数为 4 的度:
由以下等式给出:
是时候概括了。我们现在来看两个 J 次多项式 f(x)和 l 次多项式 g(x)。
它们的乘积是 J+1 次多项式 h(x ):
其中多项式系数由以下关系式给出:
假设 f_k 和 g_k 对于没有指定它们的索引被假设为零。即,对于负 n,f_n 和 g_n 均为零,n > J 时 f_n 为 0,n > L 时 g_n 为零,建议读者检查 h_n 的定义是否与之前 1 次和 2 次多项式相乘的结果一致。事实上,如果我们忽略无穷和的收敛问题,那么假设多项式系数分别在 f(x)和 g(x)的指数[0,J]和[0,K]之外为零,那么将该公式写成:
我们现在可以为多项式 f(x),g(x)和 h(x)的系数形成(有限)序列 f[n],g[n],h[n],并将卷积运算定义为:
其中该定义源于将序列视为相应多项式的系数。
总结:如果我们把数字序列看成多项式的系数,那么它们的卷积不过是对应多项式的乘积。
关于收敛性的一个注释:一般来说,收敛对于有限序列来说不是问题。然而,它与 IIR 滤波器相关,因为它们的脉冲响应有无限多项。从实分析可以看出,如果序列 f_n 和 g_n 是绝对可和的,则卷积和是收敛的。即,如果总和:
收敛,那么它们的卷积对每个 n 也收敛。
理解领域适应
原文:https://towardsdatascience.com/understanding-domain-adaptation-5baa723ac71f?source=collection_archive---------1-----------------------
了解如何设计深度学习框架,使他们能够适应领域
詹妮弗·罗在 Unsplash 上的照片
注意——我假设读者对神经网络及其工作有一些基本的了解。
领域适应是计算机视觉的一个领域,我们的目标是在源数据集上训练神经网络,并在与源数据集显著不同的目标数据集上确保良好的准确性。为了更好地理解领域适配及其应用,让我们先来看看它的一些用例。
- 我们有许多用于不同目的的标准数据集,如用于德国交通标志识别的 GTSRB,用于交通灯检测的 LISA 和 LARA 数据集,用于对象检测和分割的 COCO 等。然而,如果你想让神经网络很好地完成你的任务,例如印度道路上的交通标志识别,那么你必须首先收集印度道路的所有类型的图像,然后为这些图像做标记,这是一项既费力又耗时的任务。这里我们可以使用域自适应,因为我们可以在 GTSRB(源数据集)上训练模型,并在我们的印度交通标志图像(目标数据集)上测试它。
- 在许多情况下,很难收集数据集,这些数据集具有训练健壮的神经网络所需的所有变化和多样性。在这种情况下,在不同计算机视觉算法的帮助下,我们可以生成大型合成数据集,这些数据集具有我们需要的所有变化。然后在合成数据集(源数据集)上训练神经网络,在真实数据(目标数据集)上测试。
为了更好地理解,我假设我们没有可用于目标数据集/域的注释,但这并不是唯一的情况。请继续阅读进一步的解释。
因此,在领域自适应中,我们的目标是在标签或注释可用的一个数据集(源)上训练神经网络,并在标签或注释不可用的另一个数据集(目标)上确保良好的性能。
分类管道(图片由作者提供)
现在让我们看看如何实现我们的目标。考虑上述图像分类的情况。为了从一个领域适应另一个领域,我们希望我们的分类器能够很好地处理从源数据集和目标数据集中提取的特征。因为我们已经在源数据集上训练了神经网络,所以分类器必须对源数据集表现良好。然而,为了使分类器在目标数据集上表现良好,**我们希望从源数据集和目标数据集提取的特征是相似的。**因此,在训练的同时,我们实施特征提取器来提取源和目标域图像的相似特征。
成功的域名改编(图片由作者提供)
基于目标域的域适应类型
根据可从目标域获得的数据类型,域适应可分为以下几类:
- 监督的-您已经标记了来自目标域的数据,并且目标数据集的大小与源数据集相比要小得多。
- 半监督 —您既有目标域的已标记数据,也有未标记数据。
- 无监督 —你有很多目标领域的未标记样本点。
领域适应技术
主要使用三种技术来实现任何域自适应算法。以下是用于领域适应的三种技术:
- 基于散度的领域适应
- 基于对抗的领域适应
- 基于重构的域适应
现在让我们一部分一部分地来看每一种技术。
基于散度的领域适应
基于散度的域适应的工作原理是最小化源和目标分布之间的一些基于散度的标准,因此导致域不变特征。常用的基于差异的标准有对比域差异、相关比对、最大平均差异(MMD)、Wasserstein 等。为了更好地理解这个算法,我们先来看一些分歧。
在最大平均差异(MMD)中,我们试图找出给定的两个样本是否属于同一分布。我们将两个分布之间的距离定义为特征的平均嵌入之间的距离。如果我们有两个分布,比如说集合 X 上的 P 和 Q 。然后用一个特征映射 𝜑 定义 mmd:x→h,其中 h 称为再生核希尔伯特空间。MMD 的配方如下所述
为了更好地理解 MMD,请看下面的描述 — 如果两个分布的矩相似,则它们是相似的。通过应用一个核,我可以变换变量,使得所有的矩(一阶、二阶、三阶等)。)进行计算。在潜在空间中,我可以计算出矩之间的差,然后求平均值。
在相关性比对中,我们尝试使用 MMD 中的线性变换来比对源和目标域之间的相关性(二阶统计量)。
训练期间(图片由作者提供)
推理过程中(图片由作者提供)
上面的架构假设源域和目标域具有相同的类。在上述架构中,在训练期间,我们最小化两个损失,分类损失和基于散度的损失。分类损失通过更新特征提取器和分类器的权重来保证良好的分类性能。而基于散度的损失通过更新特征提取器的权重来确保源和目标域的特征是相似的。在推断时间内,我们只需从我们的神经网络传递目标域图像。
所有的发散通常是非参数的和手工制作的数学公式,其不特定于数据集或我们的问题,如分类、对象检测、分割等。因此,这种基于公式的方法对于我们的问题来说并不是非常个性化的。然而,如果可以基于数据集或问题来学习散度,那么与传统的预定义散度相比,它有望表现得更好。
基于对抗的领域适应
为了实现基于对抗的领域适应,我们使用 GANs。如果你对 GANs 不太了解,请看这里的。
这里,我们的生成器只是特征提取器,我们添加了新的鉴别器网络,它学习区分源和目标域特征。由于这是一个双人游戏,鉴别器帮助生成器生成源域和目标域不可区分的特征。由于我们有一个可学习的鉴别器网络,我们学习提取特征(特定于我们的问题和数据集),这有助于区分源域和目标域,从而帮助生成器产生更鲁棒的特征,即不容易区分的特征。
培训期间—来源(图片由作者提供)
训练期间—针对目标(图片由作者提供)
假设分类的问题,我们用的是两个损耗,分类损耗和鉴别器损耗。分类损失的目的在前面已经解释过了。鉴别器损失有助于鉴别器正确区分源和目标域特征。这里我们使用梯度反向层(GRL)来实现对抗性训练。GRL 块是一个简单的块,它在反向传播时将梯度乘以-1 或负值。在训练期间,为了更新生成器,我们有来自两个方向的梯度,第一个来自分类器,第二个来自鉴别器。由于 GRL,来自鉴别器的梯度乘以负值,从而导致训练发生器的效果与鉴别器的方向相反。例如,如果优化鉴别器损失函数的计算梯度是 2,那么我们用-2 更新生成器(假设负值是-1)。通过这种方式,我们试图以这样一种方式训练生成器,即使是鉴别器也不能区分源域和目标域的特征。GRL 层在许多关于领域适应的文献中非常常用。
基于重构的域适应
这是基于图像到图像翻译的思想。一种简单的方法是学习从目标域图像到源域图像的转换,并在源域上训练分类器。利用这个想法,我们可以引入多种方法。图像到图像转换的最简单模型可以是基于编码器-解码器的网络,并使用鉴别器来加强编码器-解码器网络,以产生与源域相似的图像。
训练期间(图片由作者提供)
测试期间(图片由作者提供)
另一种方法是我们可以使用自行车甘斯。在循环 GAN 中,我们使用两个基于编码器-解码器神经网络。一个用于将目标变换到源域,另一个用于将源变换到目标域。我们同时训练两个在两个域(源和目标)中生成图像的 gan。为了确保一致性,引入了周期一致性损失。这确保了从一个域到另一个域的变换,以及从一个域到另一个域的变换,会产生与输入大致相同的图像。因此,两个配对网络的全部损耗是两个鉴别器的 GAN 损耗和周期一致性损耗的总和。
结论
我们已经看到了三种不同的技术,它们可以帮助我们实现或实现不同的领域适应方法。它在图像分类、目标检测、分割等方面有着广泛的应用。在某些方面,我们可以说这种方法类似于人类学习视觉识别不同事物的方式。我希望这篇博客能让你对我们如何看待不同的领域适配管道有一个基本的了解。
成为 介质会员 解锁并阅读介质上的许多其他故事。关注我们的Medium,阅读更多此类博文。
理解估计偏差和偏差-方差权衡
原文:https://towardsdatascience.com/understanding-estimation-bias-and-the-bias-variance-tradeoff-79ba42ab79c?source=collection_archive---------19-----------------------
北大西洋的海面温度。图片来源: NOAA OSPO 根据使用条款
另外,如何根据偏差、方差和均方差来比较估计量
统计估计量可以根据其预测的偏差程度、其性能的一致性以及其预测的效率来评估。你的模型的预测质量取决于它所使用的估计器的质量。
在本文中,我们将详细介绍偏差的特性,并学习如何测量它。
通过一个叫做偏差-方差权衡的概念,估计者的偏差恰好与估计者预测的方差相结合,因此,我们也将学习这个概念。
最后,我们将讨论估计量的均方误差及其对回归建模的适用性,我们将展示如何使用偏差、方差及其均方误差的属性来评估总体均值的各种估计量。
什么是估计量?
估计量是用于预测或估计某个未知量的值的任何程序或公式,例如,您的航班的起飞时间,或今天的纳斯达克收盘价。
在我们的日常生活中,我们倾向于使用各种类型的估计量,甚至没有意识到这一点。以下是我们常用的一些估计类型:
基于好(或坏!)判断
你让你的股票经纪人朋友估计你最喜欢的股票一年后的价格会有多高。在这种情况下,你很可能得到价格的 区间估计 ,而不是点估计。
基于经验法则和一些计算的估计量
你使用一些评估技术,比如工作分解结构,来评估完成下一个家庭装修项目需要付出的努力。
基于轮询的估计量
你问奇数个朋友,他们认为谁会赢得下一次选举,你接受多数人的结果。
在每种情况下,你都希望估计一个你不知道的参数。
在统计建模中,均值,尤其是总体的均值,是一个经常被估计的基本参数。
让我们看一个现实生活中的数据样本。
以下是一年中特定时间东北大西洋表面温度的数据集:
东北大西洋实时海表温度数据集下载自 data.world 下 CC BY 4.0
这个数据集包含许多遗漏的读数。我们将通过将它加载到 Pandas 数据帧中并删除包含缺失温度值的所有行来清理它:
**import** pandas **as** pddf = pd.**read_csv**('NE_Atlantic_Sea_Surface_Temperatures.csv', **header**=0, **infer_datetime_format**=True, **parse_dates**=['time(UTC)'])df = df.**dropna**()**print**(df)
我们得到以下输出:
清除了所有 NaN 行的数据集(图片由作者提供)
在将近 800,000 个数据点(n=782,668)的情况下,这个数据集构成了一个非常大的数据样本。通常,你将不得不凑合使用十几个、几百个、偶尔几千个样本。
让我们打印出该示例中温度值的频率分布:
**from** matplotlib **import** pyplot **as** pltdf['sea_surface_temperature(degree_C)'].**hist**(**bins**=50)plt.**show**()
我们得到如下的情节:
东北大西洋温度值的直方图(图片由作者提供)
现在,假设我们希望估计整个东北大西洋的平均表面温度,换句话说,人口平均值。
这里有三种可能的总体均值估计量:
- 估计值#1: 我们可以取上述样本中最小和最大温度值的平均值:
y_min = df['sea_surface_temperature(degree_C)'].**min**()
y_max = df['sea_surface_temperature(degree_C)'].**max**()
**print**('**y_min**='+**str**(y_min) + ' **y_max**='+**str**(y_max))
**print**('**Estimate #1 of the population mean**='+**str**((y_max-y_min)/2))
我们得到以下输出:
y_min=0.28704015899999996 y_max=15.02521203Estimate #1 of the population mean=**7.3690859355**
- 估计值#2: 我们可以从样本中选择一个随机值,并将其指定为总体均值:
rand_temp = df.**sample**()['sea_surface_temperature(degree_C)'].**iloc**[0]
print('**Estimate #2 of the population mean**='+**str**(rand_temp))
我们得到以下输出:
Estimate #2 of the population mean=**13.5832207**
- 估计值#3: 我们可以使用下面的估计值,它平均出数据样本中的所有温度值:
人口平均值的估计值(图片由作者提供)
y_bar = df['sea_surface_temperature(degree_C)'].**mean**()
**print**('**Estimate #3 of the population mean**='+**str**(y_bar))
我们得到以下输出:
Estimate #3 of the population mean=**11.94113359335031**
我们应该使用哪个估计量?可以看出,第三个估计量——y _ bar,即 n 值的平均值——提供了总体均值的无偏估计。不过话说回来,前两个也是!
无论如何,这可能是更好地理解偏差概念的好时机。
估计偏差
假设你正在打篮球。当一些球穿过球网时,你会发现你大部分的投球都是在篮筐下的一点。在这种情况下,无论你用什么技术来估计投掷的正确角度和速度,都是低估了(未知的)角度和速度的正确值。你的估计值有负偏差。
一个有偏见的扣篮技术,似乎更多的时候,低于位于人物中心的篮子(图片由作者提供)
通过练习,你的投掷技术会提高,你也能更频繁地扣篮。从偏见的角度来看,你开始超过篮子的次数和低于篮子的次数差不多。你已经设法减少了评估技术的偏差。
一种更少偏见,更“平衡”的扣篮技术,在这种技术中,失误经常发生在图中心的篮筐两侧(图片由作者提供)
偏差-方差权衡
从上面两张图中,您可能会发现一个明显的方面,即在第一张图中,虽然偏倚很大,但遗漏镜头的“分散性”较小,导致结果的方差较低。在第二个图中,偏差无疑减少了,因为错过的镜头分布更加均匀,但这也导致了更高的分布,也就是更高的方差。
第一种技术似乎具有较大的偏差和较小的方差,第二种技术则相反。这不是巧合,很容易证明(事实上,我们将在后面证明!)在你的评估技术的偏差和方差之间有一个直接的交换。
如何计算估计量的偏差
让我们继续篮球的例子。我们可以看到篮筐的位置(两个图中间的橙色点)是保证扣篮的投掷角度和投掷速度的(未知)群体平均值的代表。失误(蓝点)代表你的技术对投掷角度和速度的总体平均值的估计。
用统计学的术语来说,每一次投掷都是一次产生结果的实验。结果的值是球(蓝点)在包含篮子的垂直平面上的位置。
如果你假设每一次投掷的结果都独立于前一次投掷(这在现实生活中几乎是不可能的,但是让我们一起玩吧!),我们可以定义 n 个独立,同分布的随机变量 y_1,y_2,y_3,…y_n 来代表你的 n 投。
让我们回忆一下我们的 n 样本平均值估计量:
人口平均值的估计值(图片由作者提供)
请注意,这意味着 y_bar 与我们的样本 n 值有关,即 n 球投掷,或 n 海洋表面温度等。转到海洋温度的例子,如果我们收集另一组 n 海洋温度值并平均它们,我们将得到样本平均值 y_bar 的第二个值。大小为 n 的第三个样本将产生第三个样本平均值,依此类推。所以,样本均值 y_bar 本身就是一个随机变量。而且就像任何随机变量一样, y_bar 有一个概率分布和一个期望值,用 E(y_bar) 表示。
我们现在可以为总体平均值定义估计量 y_bar 的偏差如下:
总体均值的估计量 y_bar 的偏差,是样本均值 y_bar 的期望值与总体均值的差值。公式如下:
总体均值估计量的偏差(图片由作者提供)
一般来说,给定一个总体参数 θ (如平均值、方差、中位数等。),以及 θ 的一个估计量 θ_cap ,则 θ_cap 的偏差为 θ_cap 的期望值与总体参数 θ 的实际(真)值之差,如下:
估计量的偏差 θ_cap 对于总体参数θ*(图片由作者提供)*
样本均值作为总体均值的无偏估计量
我们现在将展示我们之前看到的 n 个样本值的平均值估计器 y_bar ,在其预测总体平均值的能力中证明了零偏差。
使用偏差表达式, y_bar 的偏差由下式给出:
总体均值估计量的偏差(图片由作者提供)
现在,我们来计算 E(y_bar) :
样本均值 y_bar 的期望值(图片由作者提供)
随机变量 y_1,y_2,y_3,…y_n 都围绕总体均值*同分布。*因此,他们每个人都有一个期望值:
样本均值 y_bar 为零偏差(图片由作者提供)
零偏差估计器不一定是个好东西。事实上,回想一下我们也考虑过的平均表面温度的下列两个估计量:
人口平均数的另外两个估计值(图片由作者提供)
由于每个随机变量 y_i 的期望值是总体均值,估计器(1)和(2)各有一个偏差 B(。)= E(y_bar)- = - =0 。
但是常识告诉我们,估计量#(1)和#(2)明显劣于均值-of- n- 样本 - 值估计量#(3)。因此,必须有其他的性能度量,通过这些度量,我们可以评估 n- 样本值的平均值估计的适用性,并显示它优于其他估计。
其中一个度量是均方误差 (MSE)。
估计量的均方误差及其在回归建模中的适用性
对于大多数处理回归模型的人来说,均方误差是一个熟悉的性能度量。诸如用于线性模型的普通最小二乘(OLS)估计器之类的一些估计器,以及一些神经网络估计器寻求最小化训练数据和模型预测之间的均方误差。
考虑回归模型的一般方程:
具有附加残差的回归模型的一般方程(图片由作者提供)
其中,y _ OBS=【y _ 1,y_2,y_3,…y _ n】=训练数据样本, X*=回归变量矩阵,* β_ cap*=拟合*
是模型的预测。 f( X,β_cap)=y_cap 是观测值向量 y_obs 对应的拟合值向量。 所以,上面的模型方程可以简洁地写成如下:
带有附加残差的回归模型(图片由作者提供)
估计函数y _ cap***= f(.)是:*
估计函数的均方误差 f( X,β_cap) (图片由作者提供)
回归模型的估计函数通常会(但不总是)尝试最小化 MSE。
MSE 的上述等式可以用期望值的语言写成如下:
估计函数的均方误差 f( X,β_cap) (图片由作者提供)
请注意,我们还颠倒了括号中术语的顺序,只是为了保持惯例。
从下图可以看出,上述两个 MSE 方程是等价的:
以期望值表示的 MSE 公式(图片由作者提供)
从上图中我们看到,常用的均方误差公式只是简单地假设每个均方差 (y_i-y_cap_i) 出现的概率均匀分布在区间【0,n】,上导致每个概率为 1/n.
让我们回到估计量的 MSE 的一般公式:
估计函数的均方误差 f( X,β_cap) (图片由作者提供)
假设我们使用 n 个样本值的平均值估计器 y_bar 。因此, y_cap=y_bar ,因此 y_obs 现在是理论上已知的(但实际上未观察到的)总体均值。因此,样本均值 y_bar 的 MSE 可以表示如下:
样本均值 Y_bar 的均方误差(图片由作者提供)
为了计算 y_bar 的 MSE,我们将使用期望理论的以下结果:
随机变量 Y 的期望和方差之间的关系(图片由作者提供)
将上述公式应用于 MSE 表达式的 R.H.S .,我们得到以下结果:
样本均值 Y_bar 的 MSE(图片由作者提供)
让我们检查上面等式的 R.H.S。正方形下面的第一项是 E(y_bar-),我们知道,它是样本均值 y_bar 的偏差。
因为总体均值是一个常数,所以 R.H.S. 方差(y_bar- ) 的第二项就是方差(y_bar) 。因此,R.H.S 是偏差(平方)和 y_bar 的方差之和。
我们可以将这一发现归纳如下:
任何总体参数 θ 的估计量 θ_cap 的均方误差,是估计量 w.r.t. θ 的偏差 B(θ_cap) 与估计量 w.r.t. θ 的方差 Var(θ_cap) 之和:
偏差-方差权衡(图片由作者提供)
在估计任何数量时,人们常常以某个目标均方误差为目标。上述等式清楚地表明,为了实现指定的均方误差,必须在估计器的偏差和方差之间进行权衡。
**当 θ_cap=Y_bar,n 个样本值的平均值时,我们可以计算 Y_bar 的 MSE,如下所示:
样本平均值的均方误差(图片由作者提供)
我们已经证明了样本均值是总体均值的无偏估计量。所以偏置(y_bar) 为零。让我们计算样本均值的方差。
样本均值的方差(图片由作者提供)
我们现在将使用 n 个独立随机变量 y_1,y_2,y_3,…y_n 的线性组合的方差的以下性质:
n 个独立随机变量线性组合的方差(图片由作者提供)
这里,C1,C2,…,c_n 是常数。将此结果应用于 y_bar ,我们得到:
独立同分布随机变量样本均值的方差(图片由作者提供)
**y_1,y_2,y_3,…y_n 不仅是独立的随机变量,而且是同分布的,因此它们都具有相同的均值和方差,并且等于这两个参数各自的总体值。具体来说,对于所有的 i , Var(y_i) = σ。因此:
独立同分布随机变量样本均值的方差(图片由作者提供)
因此,我们已经表明n-I . I . d .随机变量的平均值估计量的方差是 σ /n.
独立同分布随机变量样本均值的方差(图片由作者提供)
这个结果也证实了我们的直觉,随着样本量的增加,样本均值的方差应该减少。
将这一结果插回到公式中用于 MSE(y_bar) ,记住 Bias(y_bar)=0 ,我们得到:
n 个独立同分布随机变量样本均值的均方误差(图片由作者提供)
现在让我们回到大西洋东北部表面温度的数据集。我们的样本量是 782,668。我们考虑了未知总体均值的以下三种估计量:
总体均值的三个候选估计值(图片由作者提供)
让我们使用偏差、方差和 MSE 的度量来比较三种估计器的性能,如下所示:
我们可以看到n 个样本值的平均值估计量(估计量#3)具有零偏差,并且在三个候选值中具有最低的方差和最低的均方误差。
摘要
- 估计量是用来预测或估计某个未知量的值的任何程序或公式。
- 给定一个总体参数 θ (如平均值、方差、中位数等。),以及 θ 的一个估计量 θ_cap , θ_cap 的偏差是 θ_cap 的期望值与总体参数 θ的实际(真)值之差。****
- 样本均值,当表示为 n 个独立同分布随机变量的平均值时,是总体均值的无偏估计量。
- n 独立同分布随机变量的样本均值方差为 σ /n ,其中 σ 为总体方差。****
- 估计量的均方误差** θ_cap 是:1)其偏差的平方和 2)其方差之和。因此,对于任何期望的均方误差,在估计器输出的偏差和方差之间总是有一个折衷。**
- 使用小偏差估计量的回归模型不一定比使用大偏差估计量的回归模型具有更高的拟合优度。还应该考虑估计量的其他属性,如 MSE、一致性和效率。
- 一些估计量,如最大似然估计量,并不寻求最小化均方误差。对于这样的估计器,人们使用拟合优度度量来测量它们的性能,例如偏差。
参考文献和版权
数据集
东北大西洋实时海表温度数据集下载自 data.world 下 CC BY 4.0
形象
北大西洋的海面温度。图片来源: NOAA OSPO 根据使用条款
本文中所有其他图片的版权归 Sachin Date 所有,版权归 CC-BY-NC-SA 所有,除非图片下方提到了不同的来源和版权。
感谢阅读!如果你喜欢这篇文章,请 关注我 获取关于回归和时间序列分析的技巧、操作和编程建议。
理解分类建模中的评估指标
原文:https://towardsdatascience.com/understanding-evaluation-metrics-in-classification-modeling-6cc197950f01?source=collection_archive---------23-----------------------
凯文·Ku 在 Unsplash 上的照片
更好地理解分类模型性能的指南
动机
分类建模成为机器学习中广泛使用的技术之一,例如欺诈检测、流失分析、疾病检测以及图像分类。为了了解分类建模中的模型性能,我们使用分类结果表,通常我们称之为混淆矩阵。
在大多数情况下,大多数人可能只是观察模型产生的精度值来确定模型的性能。但是,在某些情况下,我们不能简单地使用准确性来确定模型的性能(例如,当数据不平衡时)。在本文中,我将告诉您如何在分类建模中正确使用评估指标。
注意:在这篇文章中,我将解释二进制分类情况下的评估指标。
这个概念
首先,我们必须先了解评估指标。在机器学习中,评估指标对于帮助我们理解模型性能非常重要,从而确定我们可以从分析中给出的建议。在分类建模中,评估指标是根据真阳性(TP)、假阳性(FP)、真阴性(TN)和假阴性(FN)计算的。所有这些值都以表格形式列出(为了进一步解释,我们称之为混淆矩阵),如下图所示。
困惑矩阵(图片来自作者)
根据建模目的或使用的数据,应适当考虑将要使用的评估指标,这样结果就不会误导。在这里,我将解释分类建模中的一些评估指标,以及何时应该正确使用它们。
准确(性)
分类建模中最常见的评估指标。此指标衡量正确预测与评估的实例总数的比率。
此指标可用于大多数情况,但我建议在数据平衡时使用(即多数类和少数类的差异不太大)。
精确
精度度量用于测量从肯定类别中的全部预测模式中正确预测的肯定模式。
回忆还是敏感
灵敏度度量用于测量被正确分类的肯定模式的比例。
我建议您在少数类为阳性的数据不平衡时(例如,新冠肺炎或其他疾病数据集)使用此指标。当然,你不想错误地将一个阳性患者预测为阴性患者)。
分析不平衡数据时经常发生(图像由 Imgflip 生成)
特征
与敏感性相反,特异性度量用于测量被正确分类的阴性模式的比例。
当少数类为正类的数据不平衡时,建议使用敏感度指标;当少数类为负类的数据不平衡时,建议使用特异性指标,例如,流失数据集。
f1-分数
最后一个是 F1 成绩。该指标代表召回值和精确值之间的调和平均值
,也可以写成如下形式。
当数据集不平衡时,建议使用此指标。
例子
为了在实践中了解更多,这里我用 Kaggle 的 Pima 印度糖尿病数据库给出一个例子。分析将使用 R 编程语言进行。
皮马印度糖尿病数据库(图片来自 Kaggle
像往常一样,首先,我们需要导入库和数据。
library(car)
library(MASS)
library(tseries)
library(lmtest)
library(tidyverse)
library(imbalance)
library(mice)
library(caret)
library(caTools)
library(rsample)#Data Importing
data=read.csv("data_input/diabetes.csv")
我们按如下方式检查数据汇总。
> str(data)
'data.frame': 768 obs. of 9 variables:
$ Pregnancies : int 6 1 8 1 0 5 3 10 2 8 ...
$ Glucose : int 148 85 183 89 137 116 78 115 197 125 ...
$ BloodPressure : int 72 66 64 66 40 74 50 0 70 96 ...
$ SkinThickness : int 35 29 0 23 35 0 32 0 45 0 ...
$ Insulin : int 0 0 0 94 168 0 88 0 543 0 ...
$ BMI : num 33.6 26.6 23.3 28.1 43.1 25.6 31 35.3 30.5 0 ...
$ DiabetesPedigreeFunction: num 0.627 0.351 0.672 0.167 2.288 ...
$ Age : int 50 31 32 21 33 30 26 29 53 54 ...
$ Outcome : int 1 0 1 0 1 0 1 0 1 1 ...
然后,让我们检查数据中是否存在缺失值,如下所示。
> md.pattern(data)
/\ /\
{ `---' }
{ O O }
==> V <== No need for mice. This data set is completely observed.
\ \|/ /
`-----'Pregnancies Glucose BloodPressure SkinThickness Insulin BMI
768 1 1 1 1 1 1
0 0 0 0 0 0
DiabetesPedigreeFunction Age Outcome
768 1 1 1 0
0 0 0 0
缺失的价值分析(图片由作者提供)
没有缺失值!因此,我们好进行下一步。让我们绘制因变量(即数据中的结果)来找出数据集是否不平衡。
#Data Visualization
ggplot(data, aes(Outcome))+geom_bar()
imbalanceRatio(data,classAttr = "Outcome")
“结果”变量的数据可视化(图片由作者提供)
> imbalanceRatio(data,classAttr = "Outcome")
[1] 0.536
我们可以看到数据集是不平衡的,其中少数类是正类(标为 1)。因此,我们有兴趣了解将从模型中产生的灵敏度指标。
接下来,我们将数据分为数据训练和数据测试,如下所示。
#Data Splitting
split=initial_split(data,prop=0.7)
data.train=training(split)
data.test=testing(split)
对于本文中的例子,我将使用逻辑回归对这些数据进行建模。您可以尝试使用不同的模型和/或优化它来查看不同的结果。
> #Modeling
> model=glm(Outcome~.,data=data.train,family=binomial(link="logit"))
> summary(model)Call:
glm(formula = Outcome ~ ., family = binomial(link = "logit"),
data = data.train)Deviance Residuals:
Min 1Q Median 3Q Max
-2.4025 -0.7510 -0.4492 0.7687 2.7652Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -7.930549 0.818065 -9.694 < 2e-16 ***
Pregnancies 0.117947 0.037190 3.171 0.00152 **
Glucose 0.032608 0.004247 7.678 1.61e-14 ***
BloodPressure -0.009801 0.006241 -1.570 0.11633
SkinThickness 0.003591 0.008125 0.442 0.65849
Insulin -0.001708 0.001088 -1.569 0.11657
BMI 0.083122 0.017663 4.706 2.53e-06 ***
DiabetesPedigreeFunction 0.615187 0.340094 1.809 0.07047 .
Age 0.015894 0.010867 1.463 0.14358
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1(Dispersion parameter for binomial family taken to be 1)Null deviance: 699.94 on 537 degrees of freedom
Residual deviance: 530.59 on 529 degrees of freedom
AIC: 548.59Number of Fisher Scoring iterations: 4
通过编写如下代码,让我们来看看这个使用来自caret
库的confusionMatrix
的示例模型的性能。
> pred=predict(model,data.test,type='response')
> pred=ifelse(pred>0.5,1,0)
> confusionMatrix(table(actual=data.test$Outcome,pred),positive="1")
Confusion Matrix and Statisticspred
actual 0 1
0 136 17
1 28 49
Accuracy : 0.8043
95% CI : (0.7471, 0.8536)
No Information Rate : 0.713
P-Value [Acc > NIR] : 0.001005
Kappa : 0.5446
Mcnemar's Test P-Value : 0.136037
Sensitivity : 0.7424
Specificity : 0.8293
Pos Pred Value : 0.6364
Neg Pred Value : 0.8889
Prevalence : 0.2870
Detection Rate : 0.2130
Detection Prevalence : 0.3348
Balanced Accuracy : 0.7858
'Positive' Class : 1
乍一看,我们可能会说基于精度的模型性能良好,其中精度为 0.8043。但是,如果我们从敏感度上看,得分仅为 0.7424,这意味着预测结果仍有许多假阴性(FN),因此我们可以说该模型仍需要一些改进以增加敏感度得分,从而减少假阴性的发生。
让我们看看,如果我们从第一个模型中删除统计上最不重要的变量(即SkinThickness
变量),会看到不同的结果。
> model2=glm(Outcome~Pregnancies+Glucose+BloodPressure+Insulin+BMI+DiabetesPedigreeFunction+Age,data=data.train,family=binomial(link="logit"))
> summary(model2)Call:
glm(formula = Outcome ~ Pregnancies + Glucose + BloodPressure +
Insulin + BMI + DiabetesPedigreeFunction + Age, family = binomial(link = "logit"),
data = data.train)Deviance Residuals:
Min 1Q Median 3Q Max
-2.1998 -0.7277 -0.4219 0.7465 2.7713Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -8.1105881 0.8266014 -9.812 < 2e-16 ***
Pregnancies 0.1408917 0.0387610 3.635 0.000278 ***
Glucose 0.0356517 0.0043220 8.249 < 2e-16 ***
BloodPressure -0.0118975 0.0061181 -1.945 0.051819 .
Insulin -0.0010592 0.0009106 -1.163 0.244758
BMI 0.0793557 0.0158026 5.022 5.12e-07 ***
DiabetesPedigreeFunction 1.1127198 0.3435883 3.239 0.001201 **
Age 0.0085905 0.0114574 0.750 0.453386
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1(Dispersion parameter for binomial family taken to be 1)Null deviance: 708.97 on 537 degrees of freedom
Residual deviance: 516.31 on 530 degrees of freedom
AIC: 532.31Number of Fisher Scoring iterations: 5> pred2=predict(model2,data.test,type='response')
> pred2=ifelse(pred2>0.5,1,0)
> confusionMatrix(table(actual=data.test$Outcome,pred2),positive="1")
Confusion Matrix and Statisticspred2
actual 0 1
0 150 11
1 29 40
Accuracy : 0.8261
95% CI : (0.7708, 0.8728)
No Information Rate : 0.7783
P-Value [Acc > NIR] : 0.04490
Kappa : 0.5526
Mcnemar's Test P-Value : 0.00719
Sensitivity : 0.7843
Specificity : 0.8380
Pos Pred Value : 0.5797
Neg Pred Value : 0.9317
Prevalence : 0.2217
Detection Rate : 0.1739
Detection Prevalence : 0.3000
Balanced Accuracy : 0.8112
'Positive' Class : 1
结果好多了!我们可以看到敏感度得分增加到 0.7843,这意味着我们可以从预测结果中减少假阴性的发生(从混淆矩阵中可以看出)。
完整的代码如下。
library(car)
library(MASS)
library(tseries)
library(lmtest)
library(tidyverse)
library(imbalance)
library(mice)
library(caret)
library(caTools)
library(rsample)#Data Importing
data=read.csv("data_input/diabetes.csv")
summary(data)
str(data)
md.pattern(data)#Data Visualization
ggplot(data, aes(Outcome))+geom_bar()
imbalanceRatio(data,classAttr = "Outcome")#Data Splitting
split=initial_split(data,prop=0.7)
data.train=training(split)
data.test=testing(split)#Modeling
model=glm(Outcome~.,data=data.train,family=binomial(link="logit"))
summary(model)
pred=predict(model,data.test,type='response')
pred=ifelse(pred>0.5,1,0)
confusionMatrix(table(actual=data.test$Outcome,pred),positive="1")model2=glm(Outcome~Pregnancies+Glucose+BloodPressure+Insulin+BMI+DiabetesPedigreeFunction+Age,data=data.train,family=binomial(link="logit"))
summary(model2)
pred2=predict(model2,data.test,type='response')
pred2=ifelse(pred2>0.5,1,0)
confusionMatrix(table(actual=data.test$Outcome,pred2),positive="1")
结论
我们到了。在本文中,您将学习如何根据建模目的或分析中使用的数据来正确使用评估指标。
像往常一样,如果您有任何问题,请随时在我的联系人下面提问或讨论!下一篇文章再见,保持健康!
作者的联系人
领英:拉登·奥勒留和希卡·维亚迪努格罗霍
中:https://medium.com/@radenaurelius
参考
[1] Lever,j .,Krzywinski,m .,& Altman,N. (2016)。分类评价。性质。
[2]m . hos sin 和 m . n . Sula Iman(2015 年)。审查数据分类评估的评估指标。国际数据挖掘杂志&知识管理过程,第 5 卷,第 2 期,第 1–11 页。
https://www.kaggle.com/uciml/pima-indians-diabetes-database
了解特性的重要性以及如何在 Python 中实现它
原文:https://towardsdatascience.com/understanding-feature-importance-and-how-to-implement-it-in-python-ff0287b20285?source=collection_archive---------2-----------------------
了解最实用的数据科学概念之一
弗洛里安·施梅兹在 Unsplash 上的照片
请务必 订阅此处 千万不要错过另一篇关于数据科学指南、诀窍和技巧、生活经验等的文章!
目录
- 介绍
- 什么是特性重要性
- 为什么特性重要性如此有用?
- Python 中特性的重要性
- 具有梯度的特征重要性
介绍
有了所有可用的包和工具,构建一个机器学习模型并不困难。然而,构建一个好的机器学习模型就是另一回事了。
如果你认为机器学习只是简单地将数百列数据扔进一个笔记本,并使用 scikit-learn 建立一个模型,那么请再想想。
经常被忽视的一件大事是为这些模型选择合适的特征。无用的数据会导致偏见,从而扰乱我们机器学习的最终结果。在本文中,我们将讨论在机器学习中起关键作用的特征重要性。
在本文中,我们将介绍什么是特性重要性,为什么它如此有用,如何用 Python 代码实现特性重要性,以及如何在 Gradio 中可视化特性重要性。
什么是特征重要性?
要素重要性是指为给定模型的所有输入要素计算分数的技术-分数仅代表每个要素的“重要性”。较高的分数意味着特定特征将对用于预测某个变量的模型产生较大的影响。
为了更好的理解,让我们举一个现实生活中的例子。假设你要在工作地点附近买一套新房子。在买房时,你可能会考虑不同的因素。你做决定时最重要的因素可能是房产的位置,因此,你可能只会寻找靠近你工作地点的房子。要素重要性以类似的方式工作,它将根据要素对模型预测的影响对要素进行排序。
为什么特性重要性如此有用?
特征重要性非常有用,原因如下:
1)数据理解。
构建模型是一回事,但理解进入模型的数据是另一回事。像相关矩阵一样,特征重要性允许您理解特征和目标变量之间的关系。它还可以帮助您了解哪些功能与模型无关。
2)模型改进。
训练模型时,可以使用根据要素重要性计算的分数来降低模型的维度。较高的分数通常被保留,较低的分数被删除,因为它们对模型不重要。这不仅简化了模型,还加快了模型的工作速度,最终提高了模型的性能。
3)模型的可解释性。
特性重要性对于向其他涉众解释和交流您的模型也很有用。通过计算每个特征的得分,可以确定哪些特征对模型的预测能力贡献最大。
特征重要性背后的数学原理
有不同的方法来计算特征重要性,但本文将只关注两种方法:基尼重要性和排列特征重要性。
基尼系数
在 Scikit-learn 中,Gini 重要度用于计算节点杂质,而特征重要度基本上是节点杂质的减少量,该减少量通过从样本总数中到达该节点的样本数来加权。这就是所谓的节点概率。假设我们有一棵有两个子节点的树,我们的等式是:
这里我们有:
nij =节点 j 重要性
wj=到达节点 j 的加权样本数
Cj=节点 j 的杂质值
左(j) =节点 j 左边的子节点
右(j) =节点 j 右边的子节点
这个等式给出了节点 j 的重要性,用于计算每个决策树的特征重要性。单个特征可以用在树的不同分支中。因此,我们计算特征重要性如下。
根据树中存在的所有特征值的总和对特征进行归一化,然后用它除以随机森林中的树的总数,我们得到总体特征重要性。这样,您可以更好地理解随机森林中的特性重要性。
置换特征重要性
排列特征重要性背后的思想很简单。当我们改变一个特性的值时,通过注意误差的增加或减少来计算特性的重要性。如果置换值导致误差发生巨大变化,这意味着该特征对我们的模型很重要。这种方法最好的一点是,它可以应用于每一个机器学习模型。它的方法是模型不可知的,这给了你很大的自由。背后没有复杂的数学公式。置换特征重要性基于如下工作的算法。
- 用原始值计算均方误差
- 打乱要素的值并进行预测
- 计算混洗值的均方误差
- 比较它们之间的区别
- 按降序对差异进行排序,以获得重要性从高到低的特征
Python 中特性的重要性
如果你想自己测试代码,就去看看Saturn cloud,一个可扩展的、灵活的数据科学平台。
在本节中,我们将使用波士顿数据集创建一个随机森林模型。
首先,我们将导入所有需要的库和数据集。
import numpy as np
import pandas as pd
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.inspection import permutation_importance
from matplotlib import pyplot as plt
下一步是加载数据集,并将其分成测试集和训练集。
boston = load_boston()X = pd.DataFrame(boston.data, columns=boston.feature_names)
y = boston.targetX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
接下来,我们将创建随机森林模型。
rf = RandomForestRegressor(n_estimators=150)
rf.fit(X_train, y_train)
一旦创建了模型,我们就可以进行特征重要性分析,并将其绘制在图表上,以便于解释结果。
sort = rf.feature_importances_.argsort()plt.barh(boston.feature_names[sort], rf.feature_importances_[sort])plt.xlabel("Feature Importance")
RM 是每个住宅的平均房间数,从上面可以看出,它是预测目标变量的最重要的特征。
具有梯度的特征重要性
Gradio 是一个漂亮的包,有助于为机器学习模型创建简单的交互式界面。使用 Gradio,您可以实时评估和测试您的模型。关于 Gradio 的一个有趣的事情是,它使用单个参数计算要素重要性,我们可以与要素进行交互,以查看它如何影响要素重要性。
这里有一个例子:
首先,我们将导入所有需要的库和数据集。在这个例子中,我将使用 Seaborn 库中的 iris 数据集。
**# Importing libraries**
import numpy as np
import pandas as pd
import seaborn as sns**# Importing data**
iris=sns.load_dataset("iris")
然后,我们将拆分数据集,并将其放入模型中。
from sklearn.model_selection import train_test_splitX=iris.drop("species",axis=1)
y=iris["species"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25) from sklearn.svm import SVCmodel = SVC(probability=True)
model.fit(X_train,y_train)
我们还将创建一个将在 Gradio 界面中使用的预测函数。
def predict_flower(sepal_length, sepal_width, petal_length, petal_width):
df = pd.DataFrame.from_dict({'Sepal Length':[sepal_length],
'Sepal Width': [sepal_width],
'Petal Length': [petal_length],
'Petal Width': [petal_width]}) predict = model.predict_proba(df)[0] return {model.classes_[i]: predict[i] for i in range(3)}
最后,我们将安装 Gradio 和 Pip 并创建我们的界面。
**# Installing and importing Gradio** !pip install gradio
import gradio as grsepal_length = gr.inputs.Slider(minimum=0, maximum=10, default=5, label="sepal_length")sepal_width = gr.inputs.Slider(minimum=0, maximum=10, default=5, label="sepal_width")petal_length = gr.inputs.Slider(minimum=0, maximum=10, default=5, label="petal_length")petal_width = gr.inputs.Slider(minimum=0, maximum=10, default=5, label="petal_width")gr.Interface(predict_flower, [sepal_length, sepal_width, petal_length, petal_width], "label", live=True, interpretation="default").launch(debug=True)
gr.Interface 接受一个解释参数,该参数为我们提供了模式特征的重要性。下面是结果:
图例告诉您更改该功能将如何影响输出。所以增加花瓣长度和花瓣宽度会增加在 virginica 类的信心。只有在增加花瓣长度让你更快“更红”(更自信)的意义上,花瓣长度才更“重要”。
感谢阅读!
如果你做到了这一步,恭喜你!希望你已经彻底理解了什么是特性重要性,它为什么有用,以及你实际上如何使用它。
如果您觉得这很有用,请关注我以获取更多内容。同时,我祝你在学习上一切顺利!
感谢阅读!
务必 订阅此处 千万不要错过另一篇关于数据科学指南、诀窍和技巧、生活经验等的文章!
我希望你觉得这很有趣,很有见地。在评论里让我知道你最喜欢的 2022 年的数据可视化是什么!
不确定接下来要读什么?我为你挑选了另一篇文章:
或者您可以查看我的媒体页面:
https://terenceshin.medium.com/
特伦斯·申
- Fellow @ Saturn cloud
- 订阅我的媒体
- 跟我上媒
- 在领英上关注我
了解 Flask vs FastAPI Web 框架
原文:https://towardsdatascience.com/understanding-flask-vs-fastapi-web-framework-fe12bb58ee75?source=collection_archive---------0-----------------------
两种不同 RestAPI 框架的比较
Daria Shevtsova 拍摄于 Unsplash
简介
作为一名数据科学家并不仅仅局限于模型构建,而是朝着下一步,模型部署,努力。模型部署对于向其他人展示您的最终结果很重要*(或者可能是您的客户)*。这群人可能不懂编码,也不会通过查看您的代码来理解;他们更喜欢查看最终的应用程序,这样可以立即查看结果。一种常见的方法是将您的代码包装在 RestAPI 中,并作为微服务进行部署。
在本文中,我将介绍两种不同的可以快速搭建 web 服务器的框架: Flask 和 FastAPI 。Flask 和 FastAPI 都是用于构建小规模网站和应用程序的框架。
砂箱框架
Flask 于 2010 年发布,这是一个用 python 编写的微型 web 框架,以最少的代码支持 web 应用程序的部署。它旨在作为微服务轻松、灵活且快速地部署。Flask 构建在 WSGI (Python Web 服务器网关接口)之上,服务器将为每个请求绑定一个工作器。
下面是一个使用 Flask 进行部署的示例(这是一个使用“GET”方法获取用户输入并将值插入到 Google Big Query 中的示例——该示例部署在 Google Cloud Run 上)
使用 Flask 部署示例程序
使用 Flask 完成部署后,您可以运行 URL 并在 URL 中传递输入,将会返回一条消息。
使用 Flask 调用微服务部署
FastAPI 框架
FastAPI 比 Flask 更新,发布于 2018 年。它的工作方式类似于 Flask,后者用最少的代码支持 web 应用程序的部署。然而,FastAPI 比 Flask 更快,因为它建立在 ASGI(异步服务器网关接口)之上,从而支持并发/异步代码。这是通过用异步定义语法声明端点来实现的。
对于 FastAPI 来说,值得强调的一点是文档。在使用 FastAPI 框架进行部署时,它将生成文档并创建一个交互式 GUI (Swagger UI ),允许开发人员更方便地测试 API 端点。
下面是一个使用 FastAPI 进行部署的示例(这是一个使用“GET”方法获取用户输入并将值插入到 Google Big Query 中的示例—该示例部署在 Google Cloud Run 上)
使用 Flask 完成部署后,您可以运行 URL 并在 URL 中传递输入,将会返回一条消息,其工作方式与 Flask 类似。
使用 FastAPI 调用微服务
现在,真正让我兴奋的是 FastAPI 的附加功能,即自动生成文档(Swagger UI) 。要访问 Swagger UI,请输入 API endpoint /docs,这就是测试 API 端点的交互式 GUI。拥有一个大摇大摆的用户界面也更容易向他人解释你的程序。
FastAPI — Swagger UI
通过使用 Swagger UI,您可以轻松地测试您的 API 端点并通过接口指定参数。例如,在下图中,您可以在提供的列中轻松指定“书名”和“作者”。
从 Swagger UI 测试“获取请求”
除了 Swagger UI,FastAPI 还附带了另一个文档——“ReDoc”。该文档包含列出的所有端点,如果在同一个服务中部署了许多端点,这将非常有用。要访问文档页面,请输入 API 端点/redoc。
FastAPI — ReDoc
烧瓶和 FastAPI 的对比:
HTTP 方法:
HTTP 方法
- 在 Flask 和 FastAPI 中指定“GET”或“POST”方法是不同的。
传递参数&数据验证:
使用 Get 方法
- Flask 不提供对数据格式的验证,这意味着用户可以传递任何类型的数据,如字符串或整数等。(或者,可以将输入数据接收的验证脚本内置到脚本中,但这需要额外的工作)
- FastAPI 允许开发人员对收到的参数声明额外的标准和验证。
错误信息显示:
烧瓶& FastAPI 的错误消息
- 默认情况下,Flask 中显示的错误消息是 HTML 页面,而 FastAPI 中显示的错误消息是 JSON 格式的。
异步任务:
比较异步任务
- 正如本文前面提到的,Flask 部署在不支持异步任务的 WSGI (Python Web 服务器网关接口)上,而 FastAPI 部署在支持异步任务的 ASGI(异步服务器网关接口)上。
结论:
在研究了 Flask 和 FastAPI 之后,我会考虑将来采用 FastAPI,因为它有异步功能和自动生成的非常详细和完整的文档。此外,使用 FastAPI 进行部署所需的工作量与 Flask 相同。
如果您一直在使用 Flask,您可以考虑试用 FastAPI 并观察比较。
参考文献&链接:
[1]https://flask.palletsprojects.com/en/2.0.x/
[2]https://fastapi.tiangolo.com/
[3]https://analyticsindiamag . com/fastapi-vs-flask-comparison-guide-for-data-science-发烧友/
https://www.programmersought.com/article/60453596349/
[5]https://www . analyticsvidhya . com/blog/2020/11/fastapi-the-right-replacement-for-flask/
了解谷歌的 Switch Transformer
原文:https://towardsdatascience.com/understanding-googles-switch-transformer-904b8bf29f66?source=collection_archive---------7-----------------------
谷歌如何无成本地创建了世界上最大的语言模型
乔纳森在 Unsplash 上拍摄的照片
当 GPT-3 在 2020 年 5 月由 OpenAI 在推出时,消息不胫而走。不仅在人工智能社区,甚至在主流媒体上也有类似于“一个机器人写了这篇文章”和“你读过 GPT 3 写的东西吗?”。人们很兴奋!
在 GPT-3 之前,最大的语言模型是 2020 年 2 月发布的拥有 170 亿个参数的图灵-NLG 模型。那年晚些时候,OpenAI 用 1750 亿个参数把它炸出了公园。突然,出现了一种语言模型,它可以产生与人类通常无法区分的内容。
2021 年初,谷歌发布了一篇论文,题为“开关变压器:用简单高效的稀疏性扩展到万亿参数模型”。虽然这确实得到了一些人工智能社区之外的小媒体报道,但它并不接近 GPT-3,尽管创建了一个参数几乎十倍多的模型!
这种覆盖面的缺乏并不令人惊讶。谷歌的 1.6 万亿参数模型在性能方面不是最先进的,也没有一个整洁的 API 前端来演示人工智能的未来。然而,这并不意味着动机或结果对未来的人工智能和机器学习研究不重要。
在本文中,我们将尝试理解开关变压器背后的动机,它是如何工作的,以及为什么这些结果对机器学习研究和应用的未来如此重要。
动机
经验表明语言模型的性能随着参数数量(模型大小)、数据集大小和计算预算的增加而呈幂律增长。
然而,随着这些费用的增加,培训的财务费用也在增加。这导致开源、预先训练的语言模型越来越受欢迎,如谷歌的 BERT ,它可以在特定的下游语言任务上进行微调,如分类、问答或总结,使数据科学从业者受益于谷歌、脸书和 OpenAI 等公司掌握的大量资源。
然而,GPT-3 证明,如果这些模式继续增长,即使是大型企业和组织也可能开始陷入困境。GPT-3 花费了据称1200 万美元训练。这个包括近 5000 个模型版本的训练,使用了将近 10000 天的 GPU 时间。
同样值得注意的是,成本不仅是经济的。据估计,这次培训产生了 78,000 磅的二氧化碳排放量。类似于一个美国成年人两年生产的东西!
照片由i̇smail·埃内斯·艾汉在 Unsplash 上拍摄
OpenAI 的研究表明,用于训练人工智能模型的计算量每 3.4 个月翻一番,这在经济和环境方面产生了令人担忧的预测。
这就是 Switch Transformer 背后的动机,在不增加计算成本的情况下,创建更大的机器学习模型。
开关变压器
开关变压器是一个开关前馈神经网络(FFN)层,取代了变压器架构中的标准 FFN 层。关键区别在于,每个交换层包含多个 FFN,称为专家,而不是包含单个 FFN。
当每个令牌通过这一层时,它首先通过路由器功能,然后将令牌路由到特定的 FFN 专家。
由于每个令牌只通过一个专家 FFN,浮点运算(FLOPS)的数量保持不变,而参数的数量随着专家数量的增加而增加。
这创建了一个稀疏模型,其中不是每个参数都用于每个令牌。在这方面,开关变压器解决了上述动机,在不增加计算量的情况下增加模型参数的数量,计算量以 FLOPs 计。
在开关变压器前馈神经网络层中,每个令牌通过路由器功能将其发送到单个前馈神经网络,称为专家。由于每个令牌仅通过单个 FFN,所以计算不会增加,但是参数的数量随着专家的数量而增加。图片来自原开关变压器纸。
专家混合
使用专家来增加模型参数数量的概念对于开关变压器来说并不新奇。一篇描述专家混合层的论文于 2017 年发布,其架构与开关变压器几乎相同。
关键区别在于路由器功能会将每个令牌发送给多个 FFN 专家。作者假设路由器功能将无法学习如何路由令牌,除非它可以通过路由到 k>1 个专家来比较至少两个令牌。
另一方面,开关变压器仅使用 k=1,提供三大优势:
- 路由器的计算量减少了,因为它只路由到一个 FFN 专家。
- 每个专家的批量至少减半(即 k=1 而不是 k ≥2)。
- 降低了设备之间(即路由器到专家)的通信成本。
功率
第二个好处需要进一步分析。每个专家的批量大小也称为专家能力,即专家在给定通道中能够处理的令牌数量。
理想情况下,这将等于令牌数除以专家数,称为容量因子 1。这样,在给定的步骤中不会浪费专家的能力。
然而,这假设路由器功能在专家之间平均分配令牌。实际上,一些专家 FFN 会溢出,导致某些令牌在该步骤中没有被 FFN 专家处理。
为了避免溢出,导致令牌在该步骤中不被任何 FFN 处理,必须增加容量因子。这增加了计算和通信成本,因此辅助损耗不利于不平衡路由。图片来自原开关变压器纸。
容量因子可以增加,但是这将导致一些专家具有未使用的容量,增加计算和通信成本。
作为一种折衷,作者在总损失函数中增加了一个辅助损失,通过路由器功能来惩罚令牌的不平衡路由。他们根据经验发现,容量系数为 1.25 时性能最佳。
结果
为了衡量 Switch Transformer 的性能,他们在庞大干净的爬虫语料库()上训练了几个模型,用 T5 语言模型作为基准,对比了负 log 困惑度。
考虑到动机,为了在不增加所需计算的情况下增加参数的数量(从而增加性能),他们训练的模型与 T5 相当,即每个令牌的计算量保持相等。
他们发现了以下情况:
- 经过 100,000 步后,开关变压器模型比触发器匹配的 T5 等效模型具有更大的负损耗困惑。
- 开关变压器达到质量阈值(负。日志 perp。=-1.495)比同等的 T5 更快。在 T5 基的情况下,这个阈值从未达到过!
- 开关变压器每秒能够处理更多的样本。
缩放属性
除了分析整体性能,作者还在预训练期间查看了缩放属性。也就是说,给定一个无限的计算预算,如何缩放模型是最好的?
对三个不同的维度进行了分析,以了解模型的缩放特性:步骤、时间和针对更大的密集模型。
**步长调整:**对于固定数量的训练步长,开关变压器将优于触发器匹配的 T5 模型。增加专家数量将进一步提高性能,而不会增加失败次数。拥有 64 名专家的开关变压器模型在 60k 步中实现了与 T5 基模型在 450k 步中相同的性能,相当于 7.5 倍的加速。
T5 基极与触发器匹配的等效开关变压器模型的步进调整,专家人数不同。图片来自原开关变压器纸。
**时间缩放:**直观上,时间缩放应该等同于步长缩放。然而,跨设备的额外通信成本和路由器功能的计算意味着这需要被明确地分析。结果显示,对于固定的训练时间,开关变压器优于触发器匹配的等效 T5 基极模型。在 T5 基模型和 64 专家开关变压器模型之间观察到 7 倍的加速。
**更大的密集模型:**作者最后考虑了这样一种情况,为了匹配开关变压器的性能,使用 T5-大模型代替 T5-Base。然而,他们表明,这导致每个令牌的 FLOPS 增加了 3.5 倍,并且 FLOPS 匹配的开关变压器模型将优于此。
这些缩放结果表明,对于任何可用的计算增加,较大的开关变压器模型将优于较大的密集模型。考虑到减少语言模型的计算足迹的动机,这是一个极其重要的结果。
下游结果
为了测量下游性能,将 T5-Base(223m 参数和 124B 触发器)和 T5-Large (739M 参数和 425B 触发器)与匹配开关-Base (7.4B 参数)和开关-Large (26.3B 参数)模型的触发器进行了比较。
这些模型在 11 个不同的语言任务中进行了比较,包括分类、问题回答和总结等任务。除了电弧之外,开关变压器模型在所有任务中都优于触发器匹配的等效 T5 模型。
多语言学习
作为性能的最终测试,作者在 101 种不同语言的预训练中测量了模型的质量。在所有语言中,基于开关的模型比基于 T5 的模型具有更大的负对数困惑,并且观察到平均 5 倍的训练加速。
万亿参数模型
在文章的结尾,作者介绍了两个大型开关变压器模型 Switch-XXL 和 Switch-C 的设计和训练,它们分别具有 3950 亿和 1.571 万亿个参数。
开关-XXL 模型与 T5-XXL 模型是匹配的。但是,由于 Switch-C 模型的大小,架构大小(层大小、深度、注意力头数量等。),因此一偏,是减少了。
照片由 Unsplash 上的 Kaffeebart 拍摄
这可能是 Switch-XXL 模型的负对数困惑度大于 Switch-C 的部分原因,表明增加专家人数的收益递减,特别是以牺牲其他模型维度为代价。然而,在预训练后,两种模型都优于 T5-XXL。
这些模型也在下游任务中被测量。然而,这些结果都不是最先进的。
这也许是为什么开关变压器没有得到与 GPT-3 相同的媒体曝光率的原因。万亿参数模型虽然令人印象深刻,但也需要有令人印象深刻的性能做后盾。
然而,这并没有降低这项研究的重要性。迄今为止,增加密集语言模型的规模是生产最先进模型阻力最小的途径;但很明显,这在经济和环境上都是不可持续的。
谷歌已经表明,可以创建创新的模型架构,在不增加计算成本的情况下提高模型性能,这是数据科学和人工智能社区在不久的将来肯定会看到的事情。
五分钟了解 GPT-3
原文:https://towardsdatascience.com/understanding-gpt-3-in-5-minutes-7fe35c3a1e52?source=collection_archive---------3-----------------------
人工智能
有数百篇关于 GPT 3 号的文章。这里有一个 5 分钟的关于它的所有信息的汇编。
TT 先生在 Unsplash 上的照片
一个月前,我发表了这篇长达 35 分钟的 GPT 3 号概述。但我很看重你作为读者的时间,所以我决定写一篇超浓缩的 5 分钟文章。我总结了这篇较长文章的主要观点:GPT-3 是什么,它能做什么,以及它现在和未来对世界的影响。尽情享受吧!
GPT 3 号是什么
GPT-3 是 OpenAI 的生成式预训练模型家族的第三个版本。 GPT-1 和 GPT-2 为 GPT-3 奠定了基础,证明了两个关键假设的成功:变形金刚+无监督预训练工作正常(GPT-1)和语言模型可以多任务处理(GPT-2)。
GPT-3 是一种基于 transformer 架构的语言模型,以一种生成式、无监督的方式进行预训练,在零/一/少量多任务设置中显示出良好的性能。它的工作原理是在给定一系列标记的情况下预测下一个标记,并且可以对尚未训练过的 NLP 任务进行预测。在看过几个例子后,它在一些基准测试中达到了最先进的水平,如机器翻译、问答和完形填空任务。
GPT-3 是用巨大的互联网文本数据集训练的——总共 570GB。当它发布时,它是最大的神经网络,有 1750 亿个参数(100 倍 GPT-2)。即使在今天,它也是最大的密集神经网络,仅次于像开关变压器或悟道 2.0 这样的稀疏模型。
GPT-3 最令人印象深刻的特点是它是一个元学习者;它学会了学习。你可以用自然语言要求它执行一项新任务,它“理解”它必须做什么,就像人类一样(保持距离)。
GPT 3 号能做什么
在论文中,OpenAI 的研究人员使用标准基准将 GPT-3 与之前的模型进行了比较。它表现出比以前的类似系统更好的性能,但对于一些任务来说,受监督的系统——为特定任务而训练——要好得多。与监督系统相比,GPT-3 的主要贡献是普及了一条通往 AGI 的新的有前途的道路。
除了枯燥的基准测试,OpenAI 还提供了另一种测试 GPT 3 语言技能的方法。他们发布了测试版 API ,鼓励开发者寻找新的令人兴奋的用例。该 API 的工作原理是向基线 GPT-3 输入文本,即所谓的提示,使其专注于特定的任务。如果你输入:这个女人正在遛狗→ La mujer está paseando a su perro。孩子在公园里玩耍→ ____ ,GPT-3 会知道你在要求英语-西班牙语翻译,并将能够做到这一点。
GPT-3 的这个特殊版本将不同于任何其他用户的 GPT-3。那就是提示+元学习的力量;在不改变原始模型的情况下,用户可以让 GPT-3 成为不同任务的专家。基线 GPT-3 不知道如何执行任何任务,它知道如何学习去做,这使它更加强大和多才多艺。
这里有一个 GPT-3 能做什么的列表,还有链接(特别提到 Gwern Branwen ,他做了一个很棒的例子汇编):
- 非小说类: 对话,模仿类,杂文类,新闻类文章,剧情总结,推文类,教学类。
- 专业: 广告,邮件,文案, CV 生成,团队管理,内容营销,记笔记。
- 代码: Python , SQL , JSX , React app , Figma , javascript , CSS , HTML , LaTeX
- 创意: 小说,诗歌,歌曲,幽默,网游,桌游,迷因,烹饪菜谱,吉他标签,写出你独特的风格。
- 理性技巧: 逻辑,不确定性,常识,类比,概念交融,计数,字谜,预测。
- 哲学: 人生意义,数字 42 ,回应哲学家。
GPT 3 号现在和将来对世界的影响
疯狂炒作
GPT-3 从根本上改变了工业和学术界的人工智能格局,人们为之疯狂。一些人将人类特征归因于该系统,另一些人在此基础上建立产品和公司,它成为各地的头条新闻,一批批研究人员开始构建类似的人工智能。以下是一些炒作的例子:
- **归因:**人们说 GPT-3 是"有自我意识的,"一个"一般智力的"(或者至少是一个"无脑路径的"对它来说),并且能够"理解【和】推理"
- **杂志:**上了纽约时报,福布斯,麻省理工科技评论,连线,卫报,财富, The Verge ,科技危机,数字趋势。
- 创业公司: 可行的,寓言工作室,阿哥利亚,复制匠,纬度,他方,调试,热兹,总库,布罗卡,认为合流
- AI 后继者: 开关变压器, DALL E ,夹子, UC , LaMDA , MUM ,武道 2.0 。
潜在的危险
GPT-3 是一个令人惊叹的人工智能,但像任何其他强大的技术一样,可以被恶意使用。这是它造成伤害的许多方式中的一些:
- 偏见: OpenAI 发现 GPT-3 存在种族、性别和宗教偏见,这可能反映了训练数据中的偏见,因此该系统受到了强烈批评。OpenAI 最近发表了 PALMS ,这是一种使用小型精选数据集来减少 GPT-3 偏差的方法。
- **假新闻:**因为 GPT-3 写得太好了,它可以写出可以被当做人造的虚假文章,正如博主利亚姆·波尔和卫报所证明的那样。OpenAI 在论文中强调,人类法官只能识别 52%的 GPT-3 文章,略高于纯粹的概率。
- **环境成本:**训练 GPT 3 号产生的碳足迹与“驾驶汽车往返月球产生的碳足迹大致相同“越大越好”的趋势只有在环境没有受到威胁的情况下才会继续。
- 无用的信息:GPT 3 号不对它吐出的文字负责。这些低质量的数据在互联网上积累,用哲学家香农·瓦勒的话说,“人们越来越无法使用,甚至有害。”
- 工作损失:像 GPT-3 这样的系统威胁到基于计算机的、非常规的认知工作,甚至比机器人威胁蓝领工作更甚。目前的报告估计大约 40-50%的工作会在 15-20 年内被取代。
批评和辩论
- 在疯狂的宣传之后,人们开始寻找 GPT-3 的弱点。发现系统缺少逻辑、常识、和文本理解。加里·马库斯写了一篇对这一体系的很有说服力的评论:“[GPT-3]对世界的理解经常严重偏离,这意味着你永远不能真正相信它所说的。”
- **反批评:**格温根据一个前提对大多数批评者提出了很好的论点:“抽样可以证明知识的存在,但不能证明知识的缺失。”他发现大多数 GPT 3 号的失败是由于人们有缺陷的提示。
- **实践与哲学的争论:**实践的争论关系到 GPT-3 的局限性:我们无法确定它什么时候会正确回答,什么时候不会,这使得它不可靠。哲学辩论涉及通往 AGI 的道路:GPT-3——或任何其他基于计算机的人工智能——可能永远无法到达 AGI,除非它们“T22 长大,属于一种文化,并在世界上行动 T23。”
如果你想了解更多关于 GPT 3 号的信息,我推荐你阅读完整的概述
[## GPT-3 —全面概述
towardsdatascience.com](/gpt-3-a-complete-overview-190232eb25fd)
其他推荐阅读
</4-things-gpt-4-will-improve-from-gpt-3-2b1e7a6da49f>
跟我一起旅行到未来 了解更多关于人工智能、哲学和认知科学的内容!如有任何疑问,欢迎在评论中提问或联系LinkedIn或Twitter!:)
理解图形挖掘
原文:https://towardsdatascience.com/understanding-graph-mining-e713183a64f3?source=collection_archive---------12-----------------------
图形挖掘学习指南
你学习深度学习的第一步
来源( Unsplash )
想象一下脸书:你如何在朋友层内建立联系?
想象一下推荐系统:你怎么知道一个人的偏好与其聚类密切相关?
欢迎来到图形挖掘
理解图形分类
图形分类在大量连接的数据(例如:社交、生物和支付)中生成图形,并使用图形来识别标签(监督的)或聚类(非监督的)。
如果这听起来对你来说很难,你可以看看你的大脑,因为它是快速推断图表之间联系的大师。
例如,你的大脑知道如何从 A 点到 B 点,甚至不需要思考。想象一下你在长时间购物后的最后一次购物之旅。带着孩子去购物时,你可以浏览商品目录,并在不同类别的过道中画出多条直线来比较产品。
所有这些行动都需要整合,根据一系列子行动来推断最佳行动,以达到最终目标。尽可能以最轻松的方式完成。
一个简单的 DAG(有向无环图)流程图(来源于作者)
同样地…
图挖掘使用特征来查看一组观察结果如何与用户面临的相似性信号相关联。
图形表示基于距离公式化的实体(节点)之间的关系(边)。
有两个常见的特征:
- 来自外部来源的自然图表。例如支付网络、社交媒体和道路。
- 来自节点间相似距离度量的相似图。例如,元数据的 blob 然后通过图形表示共享 blob 结构。
根据图形的特征,我们可以将每个图形分类为
- 具有一种节点和边的简单齐次
- 复杂异构,具有多种类型的节点、多种类型的边。这些可以是有向的,也可以是无向的。
图的基本组成部分(在这种情况下是无向的)是节点和边。(来源:geeksforgeeks.org)
为什么图表很重要?
图表无处不在
图表是多用途的。您可以通过对周围的邻域进行分类来构建监督模型,通过将现有标注传播到邻域中缺失的标注来构建半监督模型,以及通过训练节点级嵌入来描述数据的结构角色来构建非监督模型
您可以使用图表完成各种各样的任务。例如,您可以根据您的用例对节点、图形和链接进行分类。
其中包括多项突破,如:谷歌 DeepMind 的超级分段图预测到达时间(ETA) 和来自 Pinterest 的PinSage。
图形计算具有关系和同一性的抽象概念
图形抽象出局部信息,从数据中提取有用的全局信息。图形结构/拓扑可以告诉我们很多关于数据的信息,比如发现数据点的聚类,或者为无形的概念提供距离度量。
图表是灵活的数据类型
图形通过嵌入和组合多种类型的特征灵活地工作,例如:文本(例如:Jaccard 相似性)、视觉(例如:图像相似性)和其他语义属性。例如,当分析师处理活动规则检测时,他们会使用几个特性,如正则表达式设置之间的相似性,并部署正则表达式来捕获这些站点。
图表是可缩放的
图形采样用于寻找感受野上的子图。这些子图可以在工人的异步分布之上公式化:获取模型参数的专用服务器。
这种可扩展性也提供了在图中使用联合学习来保护用户隐私的方法(例如基于 Android 的 ML 训练)
带有分布式警告的可伸缩性图表(来源于作者)
图形挖掘和网络入门
案例研究:GNNs 与 Cora
在这个案例研究中,我们将使用 Cora 数据,它提供了一个引用网络基准,具有 2708 个节点,5429 条边,7 个主题单词包,140 个训练,500 个验证和 1000 个测试观察。
请随意使用下面的 colab 作为你的教程。
https://colab.sandbox.google.com/drive/1d8YEErtymICvB_-YjFRH8LfUgtw-8YWW?usp=sharing
使用的库
Spektral 作为图形深度学习的开源 Python 库,基于 Keras 和 Tensorflow2。这个项目的主要目标是为创建图形神经网络(GNNs)提供一个简单而灵活的框架。
Spektral 有一个方便的功能,允许我们快速加载和预处理标准图形表示学习。它还允许函数访问特征矩阵、邻接、矩阵和掩码数组,以了解哪个节点属于训练、验证和测试集。
TF GNN 库对模型 API 是不可知的,集成了 DeepMind graphNet、Google 神经结构化学习、基于 MPNN 论文的 TF GNN API。该图还可以通过 TPU 支持的批处理/序列化在 Keras 层之间传递。
在 colab 中安装和导入这些库非常简单
!pip install numpy
!pip install tensorflow
!pip install spektral==0.6.1
import numpy as np
import tensorflow as tf
import spektral
从频谱生成形容词矩阵和特征矩阵
adj 指的是邻接矩阵,features 指的是 feature_matrix,labels 指的是论文的主题,mask sets 指的是哪个节点属于哪个数据集。
adj, features, labels, train_mask, val_mask, test_mask = spektral.datasets.citation.load_data(dataset_name=’cora’)
然后,我们替换密集特征,将特征转换为邻接矩阵,同时在 float32 中将它们设置为标准的机器学习输出格式。
features = features.todense()
adj = adj.todense() + np.eye(adj.shape[0])
features = features.astype(‘float32’)
adj = adj.astype(‘float32’)
培训和评估流程
我们按照以下步骤在 Cora 数据集上训练我们的 GNN:
- 定义 2 个 GNN 图层(输入-单位,输出-7 个主题,带 sumpooling)
- 用 Relu 激活函数实现定义层的 GNN。
- 使用 tf。GradientTape() 记录自动微分的操作。这有助于我们观察变量和梯度,以捕捉回传播错误
- 将优化器应用于渐变(Adam opt 是标准)
- 基于特征和邻接矩阵指定逻辑和精度计算
评估流程
您可以使用参数(单位、时期和学习率)进行实验,以定义验证准确性和训练/val 损失。
train_cora(features,adj,gnn,32,200,0.01)## Results ##
Epoch 0 | training loss: 1.9685615301132202 | val_accuracy: 0.20399999618530273 | test_accuracy:0.20799998939037323
Epoch 1 | training loss: 2.1238698959350586 | val_accuracy: 0.30399999022483826 | test_accuracy:0.3100000023841858
Epoch 2 | training loss: 1.6506766080856323 | val_accuracy: 0.6060000061988831 | test_accuracy:0.6150000095367432
Epoch 3 | training loss: 1.504560112953186 | val_accuracy: 0.628000020980835 | test_accuracy:0.6359999775886536
…
Epoch 129 | training loss: 0.004622798413038254 | val_accuracy: 0.7520000338554382 | test_accuracy:0.7450000047683716
正如你所看到的,似乎越多的纪元和训练步骤运行,我们可以从中获得更多的准确性。
搞定了。祝贺你的第一个图表网络!
关于作者
文森特用 ML @ Google 对抗网络滥用。文森特使用高级数据分析、机器学习和软件工程来保护 Chrome 和 Gmail 用户。
除了在谷歌的工作,Vincent 还是佐治亚理工学院计算机科学硕士校友、三项全能运动员和面向数据科学媒体的特约作家,为有抱负的 ML 和数据从业者提供指导,在全球拥有 100 多万观众。
最后,请通过 LinkedIn ,Medium或 Youtube 频道 联系文森特
索利·德奥·格洛丽亚
参考
- 谷歌图挖掘和学习
- 用 Spektral 在 TF 和 Keras 中绘制神经网络图
理解和实现图形神经网络
原文:https://towardsdatascience.com/understanding-graph-neural-network-using-pytorch-geometric-c77a7ad76459?source=collection_archive---------18-----------------------
图形数据结构介绍,如何定义自己的简单图形,以及如何建立一个简单的图形神经网络
来源:图片来自 Upsplash
图形神经网络(GNNs)在许多项目相互关联的预测任务中变得越来越流行(例如,药物发现中的分子结构、路径投影等)。然而,与其他公知的深度学习数据源(如图像、文本和/或表格)相比,图形数据结构可能更难掌握。
在这篇文章结束时,希望你已经熟悉了图形结构,以及如何使用 PyTorch Geometric (PyG) 库实现你自己的 GNNs。
目录:
- 装置
- 图表介绍
- 使用 PyG 构建简单图形
- 使用 PyG 训练和评估简单的 gnn
装置
注意:安装要求您至少安装 PyTorch 1.4.0。如果你还没有,请点击这个链接。
- 检查您是否已经有 PyTorch > 1.4.0
$ python -c "import torch; print(torch.__version__)"
>>> 1.8.0
2.找到 PyTorch 安装的 CUDA 版本:
$ python -c "import torch; print(torch.version.cuda)"
>>> 11.1
3.导出特定 torch 和 CUDA 版本的变量。
export TORCH=1.8.0
export CUDA=11.1
4.安装软件包,其中$和$是之前定义的版本。
pip install torch-scatter -f [https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html](https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html)pip install torch-sparse -f [https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html](https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html)pip install torch-cluster -f [https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html](https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html)pip install torch-spline-conv -f [https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html](https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html)pip install torch-geometric
图表介绍
图形通常具有以下基本结构,包括:
图形结构
- 节点:编号为 0、1、2 的三个圆圈
- 属性:每个节点的值( x1 )
- 边:连接不同节点的线
更复杂的图形结构(不在本文讨论范围之内)将具有额外的特性,例如:
- 邻接矩阵:定义节点如何在一个 n 乘 n 的矩阵中相互连接,其中 n 是图中节点的数量
- 边属性:边的值(例如,从 A 点到 B 点所需的米距离)
使用 PyG 构建简单图形
使用 PyG,我们可以使用简单的函数调用来重现上面的图形,如下所示:
import torch
from torch_geometric.data import Data
edge_index = torch.tensor([[0, 1, 1, 2],
[1, 0, 2, 1]], dtype=torch.long)
x = torch.tensor([[-1], [0], [1]], dtype=torch.float)
data = Data(x=x, edge_index=edge_index)
这看起来很复杂,但是让我们来分解代码:
- edge_index :是一个 2D 数组,其中第二维由 2 个子数组组成,分别表示源节点和目的节点(例如,从节点 0 到节点 1,从节点 1 到节点 0,从节点 1 到节点 2,以及从节点 2 到节点 1)
- x :三个节点的值属性
- 数据:当您提供 x 属性和 edge_index 时,构建图形数据结构
您可以找到图表的元数据详细信息,数据,,格式如下
# The number of nodes in the graph
data.num_nodes
>>> 3# The number of edges
data.num_edges
>>> 4# Number of attributes
data.num_node_features
>>> 1# If the graph contains any isolated nodes
data.contains_isolated_nodes()
>>> False
使用 PyG 训练和评估简单的 gnn
现在让我们尝试使用 PyG 实现我们自己的 GNN。让我们使用 PyG 库提供的基准数据集 Cora。
from torch_geometric.datasets import Planetoid
dataset = Planetoid(root='/tmp/Cora', name='Cora')
>>> Cora()
我们可以使用 PyG 提供的模块定义一个简单的 GNN。你可以在 PyTorch 这里了解更多关于定义 NN 网络的知识。
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = GCNConv(dataset.num_node_features, 16)
self.conv2 = GCNConv(16, dataset.num_classes)
def forward(self, data):
x, edge_index = data.x, data.edge_index
x = self.conv1(x, edge_index)
x = F.relu(x)
x = F.dropout(x, training=self.training)
x = self.conv2(x, edge_index)
return F.log_softmax(x, dim=1)
上面的代码简单地表示:初始化第一个图卷积层,然后是 ReLU 激活函数和 dropout 层,接着是第二个图卷积层,然后将输出馈送到 log_softmax 激活函数。
类似地,培训脚本可以编写如下:
model = Net()
data = dataset[0]
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
model.train()for epoch in range(200):
optimizer.zero_grad()
out = model(data)
loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])
loss.backward()
optimizer.step()
首先,我们初始化预定义的 Net()类和相应的优化器。我们将训练 200 个时期或步骤,其中我们将在调用 backward()函数进行反向传播之前应用负对数似然损失函数。
评估脚本将会是:
model.eval()_, pred = model(data).max(dim=1)
correct = int(pred[data.test_mask].eq(data.y[data.test_mask]).sum().item())acc = correct / int(data.test_mask.sum())
print('Accuracy: {:.4f}'.format(acc))>>> Accuracy: 0.8150
在这里我们调用 eval()方法来防止反向传播,并将模型设置为评估模式。此后,我们传递我们想要使用的测试数据,并计算正确答案的比例,以获得准确性分数。
就是这样!希望你能学到新东西。
结论
这篇文章简要总结了一个简单的图形结构,以及如何使用 PyG 来构造它。接下来,我们实现了一个简单的 GNN,其中我们使用了流行的 GNN 的变体,称为图形卷积网络(GCN)。我们还成功地训练和评估了我们的基准数据集。如果您想修改网络,请在 PyG 文档中找到更多详细信息。
做订阅我的邮件简讯:【https://tinyurl.com/2npw2fnz】在这里我定期用通俗易懂的语言和漂亮的可视化方式总结 AI 研究论文。
了解梯度增强树如何进行二叉分类
原文:https://towardsdatascience.com/understanding-how-a-gradient-boosted-tree-does-binary-classification-c215967600fe?source=collection_archive---------10-----------------------
使用银行券数据集,在 LightGBM 和 R 中从数据到预测的逐步重新计算
由 Eric Prouzet 在 Unsplash 上拍摄的照片
几周前,我深入研究了梯度增强模型如何工作。我提出的主要观点是,人们不必对梯度增强模型(如 XGBoost 和 LightGBM)的“黑盒”感到恐惧,理解模型正在做什么实际上是相当简单的。
在我的例子中,我使用泊松回归作为目标,现在我认为用不同的、更常用的目标:二元分类来重复这个练习会很有趣。
在这篇文章中,我们将:
- 训练二元分类模型,
- 重新计算二进制日志丢失和二进制错误度量,
- 检查预测概率和原始模型结果之间的联系,
- 根据梯度和 hessian 公式重新计算模型结果。
我们不会深入到每一个小细节,相反,我们将把重点放在二元分类目标的特殊性上。我推荐我之前关于这个话题的帖子作为起点。
环境
我们将在 LightGBM 包中工作,编程在 r 中完成。(不用说,我们讨论的所有内容都应该适用于 Python,以及其他梯度增强包,如 XGBoost。)
完整脚本请参考我的 GitHub 。
我们将要使用的数据是钞票数据集,可以在 UCI 机器学习库上免费获得。该数据包含 1372 张钞票的信息,目标是找出它们是否是伪造的。
数据
假设数据存储在data
文件夹中,为 LightGBM 准备数据的脚本:
我们有一个 LightGBM 可以使用的dtrain
对象。
训练模型
我们现在可以这样训练模型:
注意事项:
- 在现实生活中,你永远不会训练出这样的分类模型。我们有连续的特征,这意味着模型可以完美地过度拟合,除非我们用某种形式的正则化来限制它。然而,在这个项目中,我们不关心这个,我们只是想理解计算。
- 超参数应该非常简单,除了
sigmoid
。这是一个特定于二进制分类的参数,我们将很快看到它是如何在计算中使用的。
预言
我们将需要使用下面的模型预测,让我们来解决这个问题。
注意事项:
num_iteration
定义我们希望包含在预测中的树的数量。通过将它设置为 1,我们在仅一轮后就获得了模型预测的结果。rawscore = TRUE
在将原始模型结果转换为预测之前返回它们。在二元分类的情况下,这意味着返回的是对数几率而不是概率。- 来自分类模型的预测将是概率,而不是实际的标签。现在,我们将通过选择 0.5 作为阈值来进行预测,即 1 的概率超过 0.5 的每个观察值都将被预测为 1。在实际项目中,您会花很多心思来选择正确的阈值。
误差度量
我们在模型中要求两个错误度量:二进制错误和二进制日志丢失。这些指标是在模型训练期间打印出来的。我们也可以使用lgb.get.eval.result
函数来获取它们(用booster = bst
、data_name = “train”
、eval_name = “binary_logloss”
或eval_name = “binary_error”
)。
二进制错误
第一轮后的binary_error
度量是0.08454810
,第二轮后是0.07069971
。这只是数据中不正确预测的比率。例如,在第二轮中,这是实际与预测表:
predict label N
1: 0 0 734
2: 0 1 69
3: 1 0 28
4: 1 1 541
我们可以将误差计算为:
(69 + 28) / 1372 = 0.07069971
我们希望这个度量是一个低值,如果我们让模型训练更多轮次,最终,它将达到 0。(同样,这是因为我们现在没有使用任何规范化。)
binary_logloss
该指标的值在第一轮后为0.5102119
,在第二轮后为0.3966159
。binary_logloss
计算为观察值的单个二元对数损失的负平均值。观察值的二进制对数损失就是目标值为 1 的观察值的预测概率的对数,以及 1 的对数减去目标值为 0 的观察值的预测概率。
我们可以将二进制对数丢失列添加到data.table
中,就像第二轮那样:
然后像这样计算 binary_logloss:
-sum(dt[,binary_logloss_nround2])/dt[,.N] = 0.3966159
当然,第一轮结果也可以重复同样的过程。
预测的叶分数
让我们来看看叶子分数是如何变成预测的!如果我们在第一轮后打印出独特的预测(原始分数和概率),我们会得到以下结果:
predict_proba_nround1 predict_rawscore_nround1 N
1: 0.3373846 -0.9642444 679
2: 0.3702293 -0.7589048 105
3: 0.5472543 0.2708327 37
4: 0.5905585 0.5232494 551
第一列包含实际预测,即概率,第二列是原始分数。
公式
为了将原始分数转换为预测值,我们使用所谓的 sigmoid 函数:
1 / (1 + exp(-0.5232494 * 0.7)) = 0.5905585
与此相反的是 logit 函数:
log(0.5905585 / (1 - 0.5905585)) / 0.7 = 0.5232495
注意事项:
- 上面公式中的
0.7
是我们在训练模型时设置的sigmoid
参数。它在 LightGBM 参数文档中被称为“sigmoid”,但是我找不到关于这个参数的任何数学背景。如果你知道这个参数来自哪里,请给我发消息。嗯,我们知道它的用法,这很了不起!
术语摘要
我发现这里的术语有些混乱,让我快速回顾一下:
- 概率:
p
- 赔率 :
(p/(1–p))
- 对数赔率 :
log((p/(1–p)))
模型中的原始分数是对数比除以 sigmoid 参数。
在树形图中查找分数
这些都很好,但是这些价值实际上来自哪里呢?
如果我们查看lgb.model.dt.tree(bst)
表,可以很容易地通过叶子计数得到它们:这些是第一棵树中的值(tree_index = 0
)。打印出树形图表格的一部分,我们得到这个:
tree_index leaf_index leaf_value leaf_count
1: 0 0 0.5232494 551
2: 0 2 -0.7589048 105
3: 0 1 0.2708327 37
4: 0 3 -0.9642444 679
这与我们之前看到的原始分数一致。
叶分数计算
现在我们知道了指标是如何计算的,分数是从哪里来的,以及分数是如何转换成概率的。我们唯一缺少的是分数本身。
出发点
在模型甚至开始考虑分裂之前,它将计算一个基线预测,所有观察都将从该基线预测开始。
运行lgb.train
功能后,您可以在终端输出中注意到这一行:
[LightGBM] [Info] [binary:BoostFromScore]: pavg=0.444606 -> initscore=-0.317839
我们需要的线索差不多就这些了。训练数据中标签的平均值为0.444606
,因此预测将从以下位置开始:
log(0.4446064 / (1 - 0.4446064)) / 0.7 = 0.3178395
我认为这很简单:在做任何分割之前,任何一个单独的观察都有一个属于第一组的0.4446064
概率。哦,0.7
又是那个讨厌的sigmoid
参数。
第一轮目标
如果我们观察第一棵树,我们会看到它在:
variance = 0.30942
skewness = 7.60565
curtosis = -4.48625
所以在第一轮之后,我们会有四组不同的观察,每组都有不同的预测,基于上面的三个分裂。让我们试着重现这些叶子是如何得分的!
第一轮有点特殊,因为所有的观察仍然有相同的起始分数:我们在上一节看到的0.3178395
。
先说variance <= 0.30942
和skewness <= 7.60565
所在的组。该组有551
个观察值,其中512
的标签为 1,39
的标签为 0。我们还知道这组得到了一个0.5232494
的预测。这就是我们想要复制的数字。
第一轮梯度和 Hessian
我们不能再推迟了,我们必须钻研梯度和黑森计算。你可以从理论的角度试一试,但是我有点困惑。梯度和 hessian 被认为是目标函数相对于预测的一阶和二阶导数,但是我很难将sigmoid
参数放入混合中...
所以我认为最直接的方法就是看一下 LightGBM 的 源代码 。我们需要的位在GetGradients
函数中。(一要小心,label
这里跟你原来的目标不一样。对于目标为 1 的观测值,label
为 1,但对于目标为 0 的观测值,label
为-1。为了避免混淆,我将我们想要预测的值称为目标。)
在这个术语中,这个分数是当前的预测,将是我们在第一轮所有观察中的0.3178395
。梯度和 hessian 的主要构件是所谓的response
值。
- 对于目标为 1 的观测值,
response
计算如下:
-1 * 0.7 / (1 + exp(1 * 0.7 * -0.317839)) = - 0.3887755
- 对于目标为 0 的观察值,响应计算如下:
1 * 0.7 / (1 + exp(-1 * 0.7 * -0.317839)) = 0.3112245
从这些值中,我们可以很容易地计算出这个组的梯度和 hessian:我们只需将观察值的各个梯度和 hessian 相加。
根据这些值,新的叶子分数是这样计算的:
- (gradient / hessian) * 0.3 + (-0.317839) = 0.5232497
注意:
- 上面公式中的
0.3
就是learning_rate
。 512
和39
是受检组中目标值为 1 和 0 的观察次数。- 注意我们是如何将起始共享预测
-0.317839
添加到leaf_score
中的。这可能是特定于 LightGBM 的事情…本质上,总分数因此在第一轮中被滚动到叶分数中。在随后的回合中,不需要公式的这一部分。我们将为第 2 轮做一个例子来看看区别。 - 如果我们有权重,这些公式会更长。我不想让事情变得不必要的复杂,请参考源代码进行计算。请记住,这里有两个可能的权重:
label_weight
是您对正确预测目标 1 或 0 的重视程度,而weights[i]
是指您通过观察定义的权重。
第二轮目标
看看能不能把这个知识转移到第二棵树上。如果我们观察树的结构,我们可以看到,与第一个不同,这个结构是不对称的:第一次分裂的一个节点变成了一片叶子。我们会观察这个群体。通过打印variance > 0.77605
所在组中唯一的predict_rawscore_nround1
和predict_rawscore_nround2
,这就是我们得到的表格(具体如何得到表格,请参考我的 GitHub repo ):
label predict_rawscore_nround1 predict_rawscore_nround2 N
1: 0 -0.9642444 -1.4947746 575
2: 0 0.2708327 -0.2596975 8
3: 1 -0.9642444 -1.4947746 23
4: 1 0.2708327 -0.2596975 20
第一列和第二列之间的差异是一个常数,-0.5305303
,这就是我们在树形图中看到的该组的叶分数。这就是我们想要复制的数字。
第二轮渐变和 Hessian
与第一轮计算的唯一区别是,我们不再有一个共同的预测(如上表所示),因此计算时间有点长。请注意,我按组重新计算一切,以更好地展示正在发生的事情,但从技术上讲,您可以单独计算每个观察值的梯度和 hessian,然后将它们相加。
根据这些值,叶分数值计算如下:
- (gradient / hessian) * 0.3 = -0.5305302
摘要
在这篇文章中,我们重新计算了 LightGBM 在进行二进制分类时计算的指标、得分和预测。
我认为从这样的练习中得到的主要收获是对超参数如何影响模型训练的更深理解。对learning_rate
做了什么有一个大概的了解是一回事,自己重新计算这些结果是完全不同的另一回事。
我不是说像 XGBoost,LightGBM 等型号。在任何方面都很简单。我们没有触及非常重要的一点:分割点是如何确定的。这些决定是最重要的,这些车型在这方面实现的性能提升确实令人惊讶**。然而,我的观点是,一旦这些分裂点被确定,大部分的工作基本上只是一长串的算法,基于你,用户设置的超参数。**
https://matepocs.medium.com/membership
理解假设检验
原文:https://towardsdatascience.com/understanding-hypothesis-testing-65f9b3e9ab1f?source=collection_archive---------11-----------------------
假设检验
假设检验的基本原则
附身摄影在 Unsplash 上拍照
假设检验是数据科学领域中使用的一个重要的数学概念。虽然从 python 库中调用一个随机方法来为您执行测试确实很容易,但是了解幕后实际发生的事情既必要又有趣!什么是假设检验,我们为什么需要它,它有什么作用,它是如何工作的?让我们来了解一下!
什么是假设检验?
假设检验是一种统计方法,用来确定你的假设是否成立。假设可以是关于数据集中的两个变量、两个群体之间的关联或一种情况。
该方法评估两个互斥的语句(不能同时发生的两个事件),以确定哪个语句最受样本数据支持,并做出明智的决策。
假设检验的组成部分是:
- 假设—无效和替代
- 统计测试
- 概率分布
- 检验统计量
- 临界值
- 显著性水平(α)
- p 值
假说。
假设检验的过程包括两个假设——一个无效假设和一个替代假设。
- 零假设是一种假设两个变量之间没有关系、两个组之间没有关联或者当前情况没有变化的陈述,因此为“零”。它由 H0 表示。
- 替代假设与零假设相反,因为它假设两个变量之间存在某种关系,或者当前情况中存在某种变化——因此称为“替代”。用哈或 H1 来表示。
假设检验的结论是零假设是不被拒绝(所以你接受没有变化)还是被拒绝(所以你拒绝没有变化)。
我们用一个例子来理解这个。
有一个数据集包含了过去一年中住院病人的信息。该数据集中的两个特征是位置和总花费。我们相信住院期间的总花费会因一个人的居住地而有所不同——这种说法是你的替代假设,因为它假设了地点和住院花费之间的关系。
因此,无效假设将是基于一个人的居住地在医院花费的金额没有差异。
现在我们需要弄清楚我们是否应该拒绝零假设。我们如何做到这一点?
统计检验。
统计检验通过为我们提供来自样本数据的检验统计量(单个数值)来帮助我们拒绝或不拒绝我们的零假设。该检验统计量测量样本数据与原假设一致的程度——如果一致,则原假设不被拒绝,否则被拒绝。
对于不同的用例,存在多种统计测试。选择哪种统计检验来使用假设检验取决于几个因素,例如样本的分布(是否正态分布(遵循正态分布))、样本大小、方差是否已知、您拥有的数据类型以及其他一些因素。基于测试遵循的概率模型/分布,每个测试都有自己的测试统计。
比如说—
作者图片
统计检验有两种类型——单尾和双尾。
尾部的概念与概率分布相关。
概率分布是一种统计函数,其输出是实验中不同事件(可能的结果)发生的概率。
例如:
概率分布有数据和图表两种形式,但图表是理解尾部的更好方式。
作者图片
分布的尾部是分布两侧曲线/图形的末端。右端称为右尾或上尾,左端称为左尾或下尾。
一个分布没有必要在所有情况下都有两个尾部,它可以只有一个。尾巴的数量取决于你的无效假设和替代假设。
因此我们有单尾分布和双尾分布。
作者图片
因此,单尾统计检验是指其分布只有一个尾——要么是左尾(左尾检验),要么是右尾(右尾检验)。双尾统计检验是指其分布有两个尾部——左边和右边。
统计检验中尾部的目的是看得到的检验统计量是在尾部之内还是之外。尾部区域被称为拒绝的区域——这是有意义的,因为如果测试统计落在这个区域内,则零假设被拒绝。如果它落在它之外,则接受零假设。
确定尾部从哪里开始是借助于一个称为显著性水平的参数——alpha。它是当零假设为真时拒绝零假设的概率。alpha 最常见的值是 5%,即 0.05。这意味着你面临着拒绝零假设的 5%的风险,也就是说,当实际上没有差异时,你相信当前的情况有差异。
就我们的分布而言,alpha 是构成拒绝区域的分布区域,因此它是尾部。因为尾部在分布的末端,我们实际上是在说,在显著性水平下,我们的检验统计量离零假设有多远,才能真正拒绝零假设。
因此,如果我们选择一个右尾检验,我们的显著性水平是 5%,那么曲线右端分布区域的 5%将是我们的拒绝区域。利用这一点,我们计算 x 轴上的值,该值界定了剔除区域的开始位置,这就是所谓的临界值。
作者图片
在双尾检验的情况下,我们将显著性水平除以 2.5%,这将是曲线两侧每个拒绝区域的面积。那么我们将有两个临界值,拒绝区域也称为临界区域。
作者图片
单尾检验是有方向性的,因为只有一个拒绝区域。您正在寻找一个属于唯一拒绝区域的测试统计。双尾检验是无方向性的,因为有两个拒绝区域,如果检验统计量落入其中任何一个区域,则零假设被拒绝。
例如,牙医诊所患者的样本平均年龄是 18 岁,这是您的零假设(因为这是当前的情景,并且您假设没有变化)。另一位牙医加入了这一行业,你认为现在患者的样本均值将大于 18——这是你的另一种假设。由于“大于”,它是有方向性的——只有当样本均值大于 18 时,您才会拒绝零假设。如果小于 18,你的零假设不会被拒绝。
如果这是一个双尾检验,你的另一个假设就是患者的样本平均年龄不等于 18 岁。样本均值可能大于或小于 18,无论哪种情况,零假设都会被拒绝,因此它是无方向性的。
到目前为止,我们已经有了假设,一个基于概率分布的统计测试,一个我们从中获得临界值的拒绝区域的显著性水平,以及一个落在我们分布中某处的测试统计。
但是, p 值从何而来?
如前所述,测试统计与临界值进行比较。p 值与显著性水平进行比较。
p 值是您获得的检验统计数据是随机的概率,这意味着零假设实际上是正确的。如果 p 值低于显著性水平,则它在统计上是显著的,无效假设被拒绝,因为这意味着无效假设为真的概率小于 5%。如果它高于显著性水平,则不拒绝零假设。
根据概率分布的图形表示,p 值是检验统计右侧的曲线面积。
作者图片
p 值的一个很大的优点是,它不需要针对不同的显著性水平进行重新计算,因为它是直接可比的。在检验统计的情况下,必须将它们与临界值进行比较,临界值需要针对不同的显著性水平进行重新计算(如果剔除区域的面积发生变化,则区域起点的 x 轴值也将发生变化)。这就是为什么在假设检验中使用 p 值总是更好的原因。
尽管有上述优点,p 值仍然是概率性的。因此,即使无效假设是真的,也有可能被拒绝。Alpha(显著性水平)是这种情况发生的可能性。这种错误被称为I 型错误或假阳性。
与上述错误相反的是,即使无效假设不成立,也不拒绝它。这被称为类型 II 错误或假阴性。
这两个误差是反向相关的,也就是说,如果你试图减少一个,另一个就会增加。那么如何获得完美的情境呢?你不需要,你只需要决定在你的情况下哪个错误风险更小。例如,当他们实际上是阴性的时候,告诉某人他们是新冠肺炎阳性的风险较小——这是假阳性(I 型错误)。假阴性是说某人没有表现出欺诈行为,而实际上他们表现出了欺诈行为。
最后,我们对假设检验的所有构件进行了分类,因此这个过程也非常清楚。假设检验的步骤是:
- 阐明你的假设
- 选择重要程度
- 识别统计测试
- 计算测试统计量
- 计算 p 值并将其与显著性水平进行比较
- 结论——拒绝或不拒绝你的无效假设
让我们通过上面使用的关于看牙医的患者平均年龄的例子来完成这些步骤。我们知道平均年龄是 18 岁,标准差是 8。让我们假设数据服从正态分布。我们认为平均年龄不是 18 岁,但实际上比 18 岁大。
作者图片
因为我们的替代假设有方向性,我们需要一个右尾统计检验。
我们正在比较样本的平均年龄,因此我们可以使用 z 检验来确定我们的替代假设是否可能。
我们的显著性水平是 5%,我们正在进行右尾检验,因此曲线的右尾是拒绝区域。
我们的样本数据是随机抽取的 30 名患者,我们计算样本的平均年龄。
所以我们有:
作者图片
现在我们需要计算我们的测试统计量,在 z 测试的情况下是 z 得分。z 得分的公式为
作者图片
所以我们的 z 值是
作者图片
α为 0.05 的正态分布的临界值为 1.645。因此,我们已经可以看到,我们的测试统计大于我们的临界值,因此,我们可以拒绝零假设。但如前所述,p 值是确定我们是否应该拒绝零假设的最佳方法,所以我们也来计算一下。
在正态分布上得到值 2.05 的概率是 0.9798。由于 p 值是检验统计数据右侧的区域,因此可以通过从 1 中减去 0.9798 来计算。
作者图片
p 值 0.0202 小于 0.05,因此我们可以拒绝零假设,并得出结论,样本均值更有可能大于 18。
现在让我们用 python 来实现所有这些吧!
我们将使用新冠肺炎数据集。它包含 2020 年初以来的区域确诊病例和死亡病例。它还包含温度、湿度、纬度和经度。
第一步是导入所有必需的包:
import pandas as pd
import statsmodels.api as sm
我们将使用熊猫来读取我们的数据和 stasmodels 来实际执行我们的假设检验。
将数据读入数据帧:
covid = pd.read_csv(“Covid-19.csv”)
covid = covid.drop([“Unnamed: 0”], axis=1)
covid.head()
我认为温度和确诊的新冠肺炎病例数之间有关系——确诊新冠肺炎病例的地区的平均温度是否高于 12 度?
假设检验的第一步是阐明假设。我们的会是:
作者图片
由于我们的替代假设是方向性的,我们将进行单尾统计检验(右尾检验),即 z 检验。
显著性水平为 0.05,检验统计量为 z 得分,临界值为 1.645。
使用 statsmodels ztest 方法计算测试统计量和 p 值非常简单。让我们将这个功能包装在我们自己的函数中,并添加 alpha 和 p 值之间的比较。
def hyptest(data, value, alternate, alpha):
z, p = sm.stats.ztest(data, value=value, alternative=alternate)
result = 'null hypothesis rejected!' if p < alpha else 'null hypothesis not rejected'
return z, p, result
现在我们调用我们的函数—传递温度列(因为这是我们的假设中存在的变量),数字 12 作为值,因为这是我们要测试的度量,以及“更大”的替代参数,因为我们的替代假设是平均值大于值。
hyptest(covid.Temperature, 12, "larger", 0.05)**(1.0033989581188794, 0.15783420330389508, 'null hypothesis not rejected')**
结果分别是 z 得分、p 值和结论。由于 p 值大于 0.05,我们不拒绝零假设。
这就是你如何进行假设检验!
需要记住的一些关键事项是:
- 假设检验是对总体样本进行的,因此是样本数据。(如果你想确定年龄是否会影响入院的可能性,那么“人口”就是地球上的每一个人。“样本”是从这个群体中随机选择的一些人)
- 假设检验的输出是概率性的,因为它是对样本而不是总体进行的。所以你永远不能完全肯定地说零假设是真的还是假的。你干脆拒绝或者不拒绝。
- 零假设总是被写成等式=,≤或≥
- 备择假设总是写着≦,< or >
- p 值受样本大小的影响-如果样本大小增加,那么如果要拒绝零假设,p 值将会降低。
请在下面的评论中告诉我你对这篇文章的想法,或者通过林克丁联系我,我们可以联系上!
原始数据取自约翰·霍普斯金的 GitHub 库,然后经过修改得到该地区的温度。用于执行测试和创建图表的代码可以在这里找到。
理解卡夫卡,就像是你设计的一样——第二部分
原文:https://towardsdatascience.com/understanding-kafka-as-if-you-had-designed-it-part-2-33d0d24c79f1?source=collection_archive---------16-----------------------
从内向外理解阿帕奇卡夫卡式建筑
这是旨在解释卡夫卡的关键建筑元素系列的第二部分。这个想法是提供一个关于它的设计决策和内部的直觉。与消息传递语义、生产者和消费者的配置、安装、安全性等相关的细节将留到以后的文章中讨论。
还有一个重点是可读性和趣味性,所以如果你想在学习的同时获得乐趣,请继续读下去。
以前,你负责开发一个解决方案,帮助你的一个朋友将一个革命性的天气预报模型变成现实。他有了模型,但接收测量数据、存储、处理和大规模管理它们仍然是一项艰巨的任务。尽管如此,您还是推出了一款工具,它能够:
1。 接收包含任何格式的记录并无缝存储它们
2。 几乎实时地按到达顺序处理这些记录
3。 以非常高效的方式从任何特定偏移或时间查找记录
4。 以最佳方式删除记录
你甚至去度假庆祝这一壮举。然而,你朋友的一些问题仍然悬而未决,当你欣赏阿尔卑斯山倒映在湖面上的可塑性时,你几乎无法将它们从脑海中抹去:
- 如何支持多个城市?是否有必要为每个新城市准备一个基础设施?
- 如何支持多个并行读取器和写入器?
- 如何确保数据的持久性,例如在磁盘出现故障后?
- 如何在读写器全速运行的情况下备份数据?
我们回去工作吧。
继续分…
现在,您必须为多个城市提供您的解决方案,每个城市都有自己的一套测量方法。
第一个显而易见的解决方案是多次部署您的平台,每个城市一次。但是它足够可维护吗?大概不会。让每个城市给它产生的记录附上一个 id 怎么样?听起来很有趣,但是这需要截取所有记录,分配 id,然后分派修改后的记录,由于错误的 id、失败的截取等原因,这很容易出错。这个问题开始看起来很棘手。
然而,你已经学到了“分而治之”这一永恒的教训,也许这能有所帮助。如果分储呢?更确切地说,在当前状态下,所有记录都被发送到同一个目录。如果您可以创建多个目录,并决定消息应该发送到哪个目录,会怎么样?如果能够做到这一点,每个城市的名称都可以成为一个目录,这将使相同的部署服务于多个城市成为可能,并具有适当的数据隔离。
您匆忙实现了这个非常有前途的想法,但是在编码时,您意识到“目录”是一个已经使用的名称,也就是说,它在多种上下文中使用,如果有一个专门为这个工具定制的概念就好了。您也开始考虑该工具能够服务于大量用例,因此需要一个更通用的名称。你的推理是这样的:
人们或其他系统向平台发送消息,而平台则充当将消息传递给接收者的管道。这些消息与一个主题相关联,所以我可以将每个存储目录命名为 主题 。但是这个名字也在其他语境中被广泛使用。所以也许是一个相关的术语,比如话题?哎…是啊, 题目 !
从尤利卡来的!瞬间,你准备好了更多:
好吧,但是无论是谁向一个主题发送消息,都不仅仅是简单地写它,更一般地说,是产生它。同样,一个人不只是阅读信息,而是消费它。所以实际上,我们确实有 生产者 向主题发送消息和 消费者 获取它们。
您如何通过一个部署支持多个流程(图片由作者提供)
…一次又一次…
方向看起来完全正确。您刚刚创建了 3 个新概念:生产者、消费者和主题。通过允许在同一个平台上有多个主题,您还允许多个生产者和消费者共享同一个部署。然而,还有两个问题需要解决。首先还是和命名有关。第二个与可伸缩性有关。你从最简单的开始。
将整个系统称为“平台”听起来不太合适。你希望是通用的,但不要太多。平台可以是任何东西,你所拥有的是一个促进双方交流的系统。在“现实世界”中,这种类型的服务被称为经纪。那么,为什么不把保存主题的系统称为代理?问题一解决了。
第二个问题有点复杂。在大多数情况下,消费消息可能比生成消息更耗时。因此,能够横向扩展消费至关重要。
一个可能的解决方案是多线程消费者。一个线程(让我们称之为分配器)将使用来自代理的消息,并将负载分配给其他线程。但是如果单个节点不够呢?如果需要在多台机器之间分配负载,该怎么办?在这种情况下,您需要更改分发服务器以支持网络通信。然而,如果添加了足够多的节点,以至于分发服务器本身成为瓶颈,该怎么办?
避免诸如分发服务器这样的瓶颈的最直接的方法之一是允许消费者节点直接从主题消费,而不需要任何类型的中介。然而,主题中的条目是通过偏移量来处理的(这里是您开发的)。如何协调每个消费者正在处理哪些补偿?分而治之再次拯救(你开始认为这种方法是一个真正的银弹)。
您将代理划分为多个主题,每个主题都有其偏移量跟踪。如果你将主题进一步划分为子主题,并允许每个子主题都有自己的偏移量,会怎么样呢?然后,每个消费者可以从不同的子主题中获取,扩展系统就像创建更多的子主题和添加更多的消费者一样简单。另一方面,生产者将向代理查询主题的子主题,并以循环方式向每个子主题发送消息。美女!
但是,命名还是一件事。将新概念命名为副主题有点误导,因为它暗示了一个新的主题,尽管仍然与主主题相关。但是你没有一个新的主题,你只有相同主题的划分或分割。由于你有很多事情要做,你决定尽快解决它,并将子主题重命名为分区。
可以并行使用的分区主题(图片由作者提供)
最后,举一个反例来各个击破
那栋建筑看起来真的很棒,你为此感到骄傲。但是,如果一个消费者死了会怎么样呢?!因为生产者在分区之间平均分配数据,所以如果一个消费者死亡,消息的处理就变得不完整,因为整个分区都没有被处理。
你的思维习惯于分而治之,你会挣扎一会儿,直到这次决定走相反的路。如果消费者在元数据级别上分组会怎样?更具体地说,如果系统的另一个组件开始跟踪每个分区分配了哪些用户,以及最后使用了哪个偏移量,会怎么样?然后,如果一个消费者死亡,可以查询相同的组件,新的消费者可以从上一个消费者停止的地方开始。有了这个新概念,消费者不再单独工作,而是分组工作。那么,还有什么比消费者群体更好的名字呢?当然,如果一个使用者组中的使用者比主题中的分区多,一些使用者将被闲置。
现在消费者可以被无缝替换(图片由作者提供)
但是哪个组件会跟踪消费者群体呢?是否应该添加一些外部的东西,以便消费者在工作时可以接触到它?听起来不错,但是这样做也增加了新的依赖性,需要维护、监控等。但是将这种能力添加到代理本身怎么样呢?消费者已经联系了代理,所以它知道哪个消费者正在每个分区上工作。然而,经纪人不太了解消费者本身,也就是说,他们正在用他们正在消费的记录做什么。如果消费者从一个给定的偏移量读取一条记录,然后立即死亡,那该怎么办?代理可以假定记录已被处理,还是应该将相同的记录交给新的消费者来代替死去的消费者?
为了解决这个难题,您决定为消费者和代理增加一个额外的可选步骤。获取记录后,消费者可以通过发送提交消息来告诉代理消费是否成功。如果没有收到消息,代理将假设处理失败,因此,当要求新记录时,它将返回与以前相同的记录。另一种可能性是让经纪人设定提交的最后期限。如果消费者在给定的时间内没有联系,代理将认为消费是成功的,当被要求提供新的记录时,将提供与下一个补偿相关的记录。
当考虑这种机制时,你会意识到它实际上可以被设计成一种配置。在上面提到的第二种情况下,代理会自动提交。在第一种情况下,你有相反的行为。因此,您决定添加一个名为使能的配置。自动提交,可以设置真或假。
最后一次分裂
这真是太棒了。该系统现在可以平衡多个代理之间的负载,从而允许并行消费。现在,扩展系统就像添加一个新的代理一样简单。更好的是,如果一个消费者死了,一个新的可以开始,在被添加到消费者组后,它将准确地从上一个停止的地方开始。但是如果整个经纪人都死了会怎么样呢?我的意思是,从制作人的角度来看,这很容易,制作人可以从目的地列表中删除该代理,并继续向剩余的代理发送记录。但是,如果记录仍然没有被使用,会发生什么情况呢?太棒了,一个系统不能容忍数据丢失的可能性。
你首先想到的是这样一个想法:弹性通常来自冗余。如果你想承受失去某样东西,你首先需要它的复制品。在这种情况下,你希望能够失去经纪人,并保持系统的工作。然而,如果您失去了一个代理,您并没有失去一切,只是失去了一些分区。因此,如果您复制一个代理中的所有分区,该代理很容易被包含副本的分区所取代。为此,您需要做的就是决定哪个代理拥有主分区,哪个包含副本分区。一旦有了这些,生产者就可以写入主分区,另一种机制可以将记录复制到副本。前途无量!
但是,在开始编码之前,和往常一样,您需要为新概念指定合适的名称。乍一看,“主分区”和“副本分区”听起来还行。然而,副本是与其他东西相同的东西,在这种情况下,副本在某些时候可能不相同。当主分区接收到记录时,它变得不同于它的副本。没错,复制品将会跟上,但在赶上之前,它们不再是复制品。但是,嘿…这些复制品实际上是在跟随,所以把他们每个人命名为追随者听起来是对的。追随者跟随一个领导者,所以你有它。主分区,从现在开始,将被称为首领。
主题分布在分区中,分布在领导者和追随者中(图片由作者提供)
这个解决方案看起来像万灵药,但是有一个潜在的问题:如果复制过程失败了会发生什么?当然,您已经添加了消息提交的概念,但是如果您提交了书面记录,但是将记录复制到跟随者失败了,会发生什么呢?
与你已经经历的相比,这是一个更容易的问题。在这种情况下,您只需要添加一个规则,指定记录写入只能在成功复制到最小数量的跟随者之后提交。
这种设计还有一个优点。如果您将关注者添加到一个组(类似于消费者组),您可以跟踪他们中哪些人落后了。然后,如果一个领导者失败了,你可以从与前一个领导者同步的群体成员中选出新的领导者。这个组甚至可以作为系统的标尺,例如,通过指定至少一定百分比的追随者在任何时候都应该同步。这个小组的好名字是什么?好吧,这一次,既然它们是同步的,就可以认为是复制品。那么,为什么不使用同步副本集,或者简称为 ISR ?
开个玩笑,这是真正的最后一次分裂
你完成了实现,并急于向你的朋友展示新的特性,他完全被你的独创性惊呆了。你感到受宠若惊和兴奋,但当他告诉你其他城市的研究人员刚刚告诉他,今天早些时候,他们需要按街道分类的测量值时,这种感觉几乎消失了。
当前的解决方案不玩排序,你也看不到一个简单的方法来做到这一点。你的第一个想法是让每条街道上的传感器给它们产生的信息附加一个 id 和一个序列号,然后在读取时对记录进行分类。但是,这将需要大量的内存用于聚合,或者如果磁盘必须用于随机访问,则会影响性能。还有,散兵游勇怎么办?您应该保持这种状态并等待他们到达多长时间?事情开始变得过于复杂。要是你能保证同一条街上的传感器产生的记录最终能在同一个分区里就好了……但是,嘿,你不能吗?
如果记录按 id 和值划分,您可以更改生成器,强制它们将包含相同 id 的所有记录发送到同一个分区。这样,无论它们产生的顺序是什么,它们都将在同一个分区中进行排序。这样做还有更大的好处,因为通过对消息进行自然分组可以加快处理速度。在定义键没有意义的场景中,生产者只是继续做他们已经在做的事情,以循环的方式向主题分区发送消息。答对了。除了名字,一如既往。将成对的事物称为 id 和值并不常见,但是键和值完全没问题,所以就这样了。
包含相同键的记录现在被发送到相同的分区(按作者排序)
完整的画面
这就是了!将您之前开发的与您现在创建的结合起来,您将获得以下结果:
- 能够随着新硬件的增加而水平扩展的分布式平台
- 与模式无关的存储系统
- 一种通过利用页面缓存和顺序读写来支持极高吞吐量同时仍使用磁盘的机制
- 通过将主题分割成分区并创建消费者组,并行消费记录并在失败时平滑追赶的策略
- 通过在代理之间复制分区来避免数据丢失的弹性方法
- 一种通过监控同步副本来保证系统健康的机制
- 一种通过使用键来保证分区内记录顺序的方法
每一个听到这个解决方案的人都同时感到吃惊和惊讶。每一个人也询问它将被赋予的名字,而这一次你不知道。只有你,命名怪胎!
你必须承认的一点是,你创建的解决方案看起来有点超现实。它与模式无关,在使用磁盘时提供高吞吐量,在作为分布式系统时保证某种排序,允许代理无缝地来回切换,等等。
你记得你坐在阿尔卑斯山上读的一本书,关于一个人试图到达一个不可能的城堡,一个永远无法到达的遥远的愿景,正如你的设计元素。无论你如何达到它。此外,你喜欢那本书,因为它给了你一段美好的时光,那么为什么不用它来命名系统呢?但是将一个平台命名为城堡并不合适。那么作者呢?是啊,听起来绝对不错。从现在开始,当人们问起,你会告诉他们你的系统叫做卡夫卡。
参考
- 文档
2.本系列的第一部分
你给这个世界的能力
通过 Python 中的情感分析理解语言
原文:https://towardsdatascience.com/understanding-language-through-sentiment-analysis-in-python-e7bee1575cbb?source=collection_archive---------38-----------------------
使用 TextBlob 的自然语言处理能力
普里西拉·杜·普里兹在 Unsplash 上的照片
为了将数据转化为信息并发现原始数据的真正好处,开发人员、企业、机构、大学甚至犯罪分子对数据科学领域产生了浓厚的兴趣。在我们知道之前,通过代码模仿人脑功能的能力已经向我们展示了分析语言的能力是推动社会和人类进步的最重要的方法之一。由此,数据科学、机器学习和自然语言处理的发展已经被实施到消费者每天使用的工具中,如 Siri、Alexa 和 Cortana。
开源数据和数据处理的发展已经引导了稳健方法的使用,以将数据用于自然语言处理、情感分析和确定情绪。数据现在是下一个淘金热,因为我们开始了解数据需要如何提取、转换、加载,并为了充分的利益而转化为信息。理论上,和黄金一样,数据也是一种商品。
在本文中,我计划让您对利用编程工具在社交媒体网络中使用 Python 进行情感分析有一个基本的了解,以及如何利用基于文本的数据分析能力,使用基于计算机的代码来理解真实的情感。
介绍 TextBlob
作为 Python 的 NLP 库, TextBlob 已经成为开发人员的首选包之一。
TextBlob 是一个用于处理文本数据的 Python (2 和 3)库。它提供了一个简单的 API,用于处理常见的自然语言处理(NLP)任务,如词性标注、名词短语提取、情感分析、分类、翻译等。— TextBlob 的网站
使用 TextBlob 理解情感分析
[**sentiment**](https://textblob.readthedocs.io/en/dev/api_reference.html#textblob.blob.TextBlob.sentiment)
属性返回一个形式为Sentiment(polarity, subjectivity)
的命名元组。极性分数是[-1.0,1.0]范围内的浮点数。主观性是在[0.0,1.0]范围内的浮动,其中 0.0 非常客观,1.0 非常主观。— TextBlob 快速入门教程
TextBlob 返回句子的极性和主观性。
极性是介于[-1.0,1.0]范围之间的浮动值。
- -1 表示负面情绪
- 1 定义积极的情绪。
主观性介于[0.0,1.0]之间。
- 0.0 很客观,1.0 很主观。
- 如果主观性< 0.5, the sentence is more subjective than objective and vice versa.
TextBlob also provides labels for semantics which allow for the detection and analysis of emojis, tones of sentence like exclamation marks, and more.
Installing From the Python PyPI
$ pip install -U textblob
TextBlob is available as a 康达包。要使用conda
安装,请运行
$ conda install -c conda-forge textblob
Python 中的 TextBlob
首先,在你首选的笔记本编译器中导入*textblob.*
。
然后,我们需要做的就是使用TextBlob(text)
,以便利用 TextBlob 的许多不同方法。
**from** textblob **import** TextBlobblob = TextBlob(text)
一旦你创建了一个 textblob 对象,你就可以访问普通的文本处理操作。我将把 TextBlob 对象视为 Python 字符串,以展示 NLP 在情感分析等方面的强大功能。
使用 textblob 分析情感
为了使用 textblob 执行情感分析,我们必须使用如下所示的*情感()*方法;
blob = TextBlob('companies that specialize in sentiment analysis are least likely to look at for data.')
blob.sentiment
结果
Sentiment(polarity=-0.15, subjectivity=0.7)
有益的补充
拼写纠正
在我们分析大型数据集的用例中,单词的拼写错误可能会对数据产生不利影响,因此纠正单个单词的拼写非常重要。
tutorial = TextBlob("in sentimet analyss, which of the following is an implicit opinion?")print(tutorial.correct())
结果
in sentiment analysis, which of the following is an implicit opinion?
名词短语抽取
名词短语是以一个名词为中心的一组两个或多个单词(例如,“狗”、“女孩”、“男人”),包括修饰语(例如,“the”、“a”、“None of”)。例如,“男孩”不是一个名词短语,但“一个乐于助人的男孩”是一个名词短语。
通常在数据科学中,研究人员可能希望提取一个句子中的所有名词短语,而不是确定单个名词。
blob = TextBlob('I wanted to learn cryptocurrency sentiment analysis.')
blob.noun_phrases
结果
WordList(['cryptocurrency sentiment analysis'])
正如我们所看到的,只有“情感分析”是从句子中提取的,因为它是句子中唯一的名词短语。
结论
最常见的情况是,公司雇佣开发人员来分析大量数据,以获得原始数据,这些数据随后可以发现诸如消费者或客户对产品或体验的感受之类的事情。公司可以通过基于正则表达式的文本识别和抓取基本网页来识别电话号码、个人姓名、位置和其他特定实体。对语言学概念有更深入的理解,如部分词、中间词、原生词、同义词、词干、词汇化、词类、词义消歧和类似领域。
我希望这篇文章能帮助您发现自然语言处理(NLP)的强大之处,并提供一些在您自己的环境中进行测试的例子。
感谢您阅读
欢迎建设性的批评和反馈。可以在 Instagram @nirholas 、LinkedIn **、**和 Twitter @nickresendez 上联系到 nickresendez,了解新文章的更新。
理解 R 中的线性回归输出
原文:https://towardsdatascience.com/understanding-linear-regression-output-in-r-7a9cbda948b3?source=collection_archive---------0-----------------------
自信地解释您的模型与数据的吻合程度
克里斯·利维拉尼在 Unsplash 上的照片
无论是业余爱好者还是专业人士,回归都是一种非常普遍的分析形式。这是为什么呢?因为它是理解变量之间关系的最强大的工具之一。此外,它还允许我们对以前看不见的数据进行预测。大多数人都上过统计学课程,运行过简单的线性回归模型。我猜想,大多数人,给定一些模型输出,可以挑选出 y 截距和可变系数。虽然这些信息非常重要,但是我们运行模型时返回的所有其他数据呢?
还有其他我们应该考虑的事情吗?其他值告诉我们什么?
数据
照片由 Unsplash 上的 NeONBRAND 拍摄
我们将深入研究上述每个指标,目的是深入理解每个指标告诉我们关于模型的什么,而不是如何计算每个数字的具体细节。为此,我们将使用来自国家篮球协会(NBA)的数据集。该数据集包括 2017-2018 赛季每个球员的工资信息和赛季得分。我们将调查一个赛季的得分和球员工资之间的关系。我们可以通过看一个球员得了多少分来预测他的薪水吗?下面是数据集的预览:
简单线性回归输出
我们首先运行一个简单的回归模型,将薪水作为我们的因变量,将积分作为我们的自变量。该回归模型的输出如下:
现在我们有了模型和输出,让我们一步一步地浏览这个输出,这样我们可以更好地理解每个部分,以及它如何帮助我们确定模型的有效性。
打电话
call 部分向我们展示了 R 用来拟合回归模型的公式。薪水是我们的因变量,我们使用来自 NBA 数据集的点数作为预测值(自变量)。
残差
残差是实际值和预测值之间的差值。我们可以通过获取薪金的实际值并将其从模型的预测值中减去来生成这些相同的值:
summary(nba$salary - model$fitted.values)
那么我们该如何解读这一点呢?嗯,仔细想想,我们肯定希望我们的中值以零为中心,因为这将告诉我们,我们的残差在某种程度上是对称的,并且我们的模型在数据集的高端和低端都进行了均匀的预测。看看上面的输出,看起来我们的分布并不完全对称,并且稍微向右倾斜。这告诉我们,我们的模型在高工资范围的预测不如在低工资范围的预测好。我们可以用分位数-分位数图来形象化这一点。看下面的图表,你可以看到图表两端都有异常值,但是上端的异常值比下端的异常值更严重。总体而言,残差看起来具有相当正态的分布。
系数
为了理解系数是什么,我们需要回到我们在建立线性模型时实际尝试做的事情。我们希望以 y=mx+b 的形式建立一个通用模型,其中 b 是截距, m 是直线的斜率。因为我们通常没有足够的信息或数据来知道实际存在的确切方程,所以我们必须通过对斜率和截距进行估计来建立这个方程。这些估计值通常是通过普通的最小二乘法生成的,这是一种奇特的说法,即回归模型以这样一种方式找到拟合这些点的直线,即最小化每个点和直线之间的距离(最小化实际值和预测值之间的平方差总和)。
系数—估计值
我们就是从上面这条线得到系数的。直线与 y 轴相交的地方是我们的截距( b ),直线的斜率是我们的 m 。使用我们到目前为止获得的理解,以及上面输出中提供的系数估计,我们现在可以为我们的模型建立方程。我们将用点代替 m ,用*(截距)*代替 b:
y = 10,232.50 美元(x)+1,677,561.90 美元
现在我们有了这个等式,它告诉了我们什么?嗯,作为一个基线,如果一个 NBA 球员在一个赛季中得分为零,那么这个球员的平均收入是 1,677,561.90 美元。然后,他们在赛季中每获得一个额外的分数,他们将获得 10,232.50 美元。
让我们将此应用于数据集中的一个数据点。詹姆斯·哈登是我们数据集中的第一名球员,得到了 2376 分。使用我们的公式,我们得到一个估计值:
$10,232.50(2,376)+$1,677,561.90 = $25,989,981.90
詹姆斯·哈登实际上赚了 2830 万美元,但你可以看到,通过使用模型中的系数估计,我们在这里的方向是准确的。
系数—标准。错误
系数的标准误差是系数的标准偏差的估计值。实际上,它告诉我们,系数有多少不确定性。标准误差通常用于创建置信区间。例如,我们可以在斜率周围设定 95%的置信区间,点:
$10,232.50 ± 1.96($724.90) =($8,811.70,$11,653.30)
查看置信区间,我们可以说我们 95%确信实际斜率在$8,811.70 和$11,653.30 之间。
除了有助于计算置信区间和 t 值之外,它还是检查系数对模型是否重要的快速方法。如果该系数与标准误差相比很大,那么从统计上看,该系数最有可能而不是为零。
系数— t 值
t 统计量就是系数除以标准误差。一般来说,我们希望我们的系数具有较大的 t 统计量,因为这表明我们的标准误差与我们的系数相比较小。简而言之,我们说系数是远离零的 X 标准误差(在我们的示例中,点系数是远离零的 14.12 个标准误差,从统计上看,这相当远)。我们的 t 统计量越大,我们就越能确定系数是而不是零。然后使用 t 统计量来查找 p 值。
系数— Pr( > |t|)和 Signif。代码
p 值是使用 t 分布的 T 统计量计算的。p 值与 t 统计量相关联,有助于我们理解我们的系数对模型的重要性。实际上,任何低于 0.05 的 p 值通常被认为是显著的。当我们说重要时,我们的意思是什么?这意味着我们确信该系数是而不是零,这意味着该系数实际上通过帮助解释因变量内的方差而增加了模型的价值。在我们的模型中,我们可以看到 In cept和点的 p 值非常小。这让我们得出结论,有强有力的证据表明这个模型中的系数是而不是零。
系数代码为我们提供了一种快速的方式来直观地查看哪些系数对模型是重要的。在 p 值的右侧,您会看到几个星号(如果系数对模型不重要,则没有星号)。星号的数量对应于系数部分下图例中所述的系数的重要性。星号越多,意义越大。
剩余标准误差
残差标准误差是模型与数据拟合程度的度量。让我们回到上一节中显示的示例:
如果我们查看最小二乘回归线,我们会注意到该线并没有完全穿过每个点,并且在点和线之间存在“残差”(显示为蓝色线)。残差标准差告诉我们 Y 的实际值(点)与 Y 单位的预测值(线)之间的平均值。通常,我们希望残差标准差尽可能最小,因为这意味着我们模型的预测线平均起来非常接近实际值。
对于我们当前的模型,我们可以看到,平均而言,实际值与预测值(回归线)相差 630 万美元。现在,了解我们的数据集,知道最大的工资是 2830 万美元,让我们所有的预测平均相差 630 万美元不会产生一个非常准确的模型。
多重 R 平方和调整 R 平方
多重 R 平方值最常用于简单线性回归(一个预测值)。它告诉我们自变量在因变量中解释了多大比例的变化。换句话说,这是确定我们的模型与数据拟合程度的另一种方法。在上面的例子中,点数解释了我们的因变量——薪金中约 37.37%的变化。这意味着点数有助于解释工资的一些变化,但没有我们希望的那么多。最终,我们的模型并没有很好地拟合数据(我们在研究残差标准误差时看到了这一点)。
运行多元线性回归时会使用调整后的 R 平方值,从概念上来说,可以用我们描述多元 R 平方的相同方式来考虑。调整后的 R 平方值显示了所有预测因子解释的因变量中的变异百分比。这两个指标之间的差异是计算中的细微差别,我们通过添加多个变量来调整方差。
需要注意的是,R 值(倍数或调整值)并不简单,不应该仅仅根据值的计算方式来单独使用。例如,当您添加额外的预测值时,调整后的 R 平方值可能会增加,即使它们与您的因变量没有任何关系。
f 统计量和 p 值
当运行简单或多重回归模型时,假设检验正在全局模型上运行。零假设是因变量和自变量之间没有关系,另一个假设是有关系。换句话说,零假设是模型中所有变量的系数都为零。另一个假设是,它们中至少有一个是而不是零。F 统计量和总体 p 值帮助我们确定该测试的结果。根据测试中有多少变量,只看 F 统计量可能会有一点误导。如果有许多独立变量,那么 F 统计量接近于 1,但仍然产生 p 值(我们会拒绝零假设)是很常见的。然而,对于较小的模型,较大的 F-统计量通常表明应该拒绝零假设。更好的方法是利用与 F 统计量相关的 p 值。同样,在实践中,p 值低于 0.05 通常表示模型中至少有一个非零系数。
从我们的模型中可以看出,F 统计量非常大,而 p 值非常小,基本上为零。这将导致我们拒绝零假设,并得出结论,有强有力的证据表明,工资和积分之间确实存在关系。
结论
虽然在试图预测一名 NBA 球员的薪水时,在一个赛季中获得的积分是有用的信息,但我们可以得出结论,单凭这一点还不足以做出准确的预测。
已经完成了 R 中线性回归模型输出的每一部分,您现在已经准备好自信地投入到任何回归分析中。祝你好运!
谢谢大家的支持!
感谢您阅读本文!如果你觉得有帮助,请给我一两下掌声:)
参考
- 解释回归输出
- 解读线性回归输出的标准误差
- 解释 R 中的 lm 摘要
- 解释 R 中的模型输出
- 残差标准差/误差:初学者指南
理解 Python 中的列表理解
原文:https://towardsdatascience.com/understanding-list-comprehensions-in-python-6de57e26631c?source=collection_archive---------16-----------------------
本文讨论了 Python 中的列表理解,以及如何使用它们来提高代码的效率和 Python 性。
图片由克里斯里德在 Unsplash 上拍摄
列表理解帮助你用最少的代码(通常只有一行代码)执行基本的列表操作。这使得您的代码高效且 Pythonic 化。让我们看一个例子来使列表理解的概念更清楚。
让我们创建一个从 0 到 9 的整数列表,并将列表中的每个元素乘以 2。这可以通过使用 for 循环遍历列表中的每个元素并将其乘以 2 并将其追加到一个空列表中来实现。
x = list(range(10))
x
作者图片
x_doubled = []for i in x:
x_doubled.append(i * 2)
x_doubled
作者图片
让我们尝试将变量‘x’乘以 2,就像我们处理 Numpy 数组和 Pandas 系列一样。将 Numpy 数组或 Pandas 系列乘以一个数字,再将它们的每个元素乘以该数字。
x_arr = np.array(x)
list(x_arr * 2)
作者图片
如上所述,将数组乘以 2 等于将数组的每个元素乘以 2。但是列表不会发生这种情况,因为数组和序列的行为类似于向量。让我们将列表乘以 2,看看会发生什么。
x * 2
作者图片
将列表乘以 2 没有得到预期的结果。它通过将列表“x”追加到自身来扩展它。这和 x + x 是一样的。让我们用一行代码来执行这个操作。
[i * 2 for i in x]
作者图片
使用 list comprehension 已经用一行代码执行了所需的操作。让我们看看每个方法执行所花费的时间。我们可以使用“timeit”魔法命令来实现。
%%timeit
x_doubled = []for i in x:
x_doubled.append(i * 2)
作者图片
%%timeit
[i * 2 for i in x]
作者图片
%%timeit
x_arr = np.array(x)
x_doubled = list(x_arr * 2)
作者图片
我们可以看到,与其他两种方法相比,列表理解减少了代码行数和执行时间。让我们更深入地理解列表,看看一些高级操作。
在下面的例子中,我们将尝试只将偶数乘以 2 并返回它们。我们将看到如何使用 for 循环和列表理解来实现这一点。
x_even_doubled = []for i in x:
if i % 2 == 0:
x_even_doubled.append(i * 2)
x_even_doubled
使用 for 循环输出
[i * 2 for i in x if i % 2 == 0]
使用列表理解输出
让我们试着把偶数乘以 2,奇数原样返回。我们将看到如何使用 for 循环和列表理解来实现这一点。我们将在 list comprehension 中使用三元运算符来执行这个操作。
x_new = []for i in x:
if i % 2 == 0:
x_new.append(i * 2)
else:
x_new.append(i)
x_new
使用 for 循环输出
[i * 2 if i % 2 == 0 else i for i in x]
使用列表理解输出
我们试着把偶数乘以 2,奇数原样返回,去掉 0。我们将看到如何使用 for 循环和列表理解来实现这一点。
x_new = []for i in x:
if i % 2 == 0:
x_new.append(i * 2)
else:
x_new.append(i)
x_new.remove(0)x_new
使用 for 循环输出
[i * 2 if i % 2 == 0 else i for i in x if i != 0]
使用列表理解输出
让我们看看嵌套列表的理解。我们将尝试将列表中的偶数乘以 2,并保留奇数。然后,我们将偶数除以 2,得到原始列表。
[int(i / 2) if i % 2 == 0 else i for i in
[i * 2 if i % 2 == 0 else i for i in x]]
嵌套列表理解的输出
让我们试着将两个列表组合成如下所示的嵌套列表。我们将看到如何使用 for 循环、zip 函数和 list comprehension 来实现这一点。
# Method 1: Using for loop
nested_list = []for i in x:
nested_list.append([i,i])
nested_list
使用 for 循环输出
# Method 2: Using zip function
list(zip(x, x))
使用 zip 函数输出
# Method 3: List comprehension
[[i,i] for i in x]
使用列表理解输出
我们可以看到 for 循环和 list comprehension 返回的是列表的列表,而 zip 函数返回的是元组的列表。让我们尝试使用 for 循环和列表理解来创建列表元素的排列。
x = list(range(3))
x
作者图片
perm_list = []for i in x:
for j in x:
perm_list.append([i, j])
perm_list
使用 for 循环输出
[[i,j] for i in x for j in x]
使用列表理解输出
我个人在从网上搜集数据时使用列表理解。让我们尝试从网页中提取 URL 及其文本。我们将创建一个名为“html”的变量来存储一小段 html 代码,并从“HTML”变量中提取 URL 及其文本,然后将它们存储在一个以文本为键、以 URL 为值的字典中。
from bs4 import BeautifulSoup# Variable storing a small HTML code snippet
html = '''
<html>
<head>head</head>
<body>
<a href="[https://www.abc.com](https://www.abc.com)">abc.com</a>
<a href="[https://www.xyz.com](https://www.xyz.com)">xyz.com</a>
<a href="[https://www.qwerty.net](https://www.qwerty.net)">qwerty.com</a>
</body>
</html>
'''bs = BeautifulSoup(html)# Finding the 'a' tags
a = bs.find_all('a')# Using list comprehension to extract 'href'
url = [i.get('href') for i in a]# Using list comprehension to extract text
txt = [i.text for i in a]# Using dictionary comprehension to store output
{i: j for i,j in zip(txt, url)}
作者图片
这些是列表理解的一些应用。与 for 循环相比,它们效率更高,并且还减少了执行操作所需的代码行数。
聪明地理解损失函数
原文:https://towardsdatascience.com/understanding-loss-functions-the-smart-way-904266e9393?source=collection_archive---------16-----------------------
了解损失函数如何用于理解模型的性能及其在 Python 中回归和分类问题中的实现。
弗朗西斯科·卡里法诺在 Unsplash 上拍摄的照片
在这篇文章中,我们将深入探讨用于提高机器学习算法性能的不同类型的损失函数。任何经典机器学习问题的主要动机都只是这两件事:
- 提高模型的精确度以及
- 减少与此相关的损失。
我们可以说损失是你为你的模型坏预测付出的代价。
在这一系列的三篇文章中,我们将讨论什么是损失函数,以及如何使用各种类型的损失函数来优化我们模型的性能。在第 2 部分,我们将研究回归损失函数,在第 3 部分,我们将探索分类函数。
本系列充满了 Python3 中的实际操作代码块,给你一个很好的实践经验,告诉你如何用 Python 实现它们。
要跳到任何部分:
- 第 1 部分:了解损失函数。
- 第二部分:回归损失函数。
- 第三部分:分类损失函数。
什么是损失函数?
准确地说,如果你的模型预测完美,那么你的损失会很少,否则损失会很大。不管问题陈述如何,通过将 预测值 与 实际值 进行比较,总会有性能评估。这就是损失函数发挥作用的地方。
损失函数的真正应用不仅仅是它的内在 值,而是它如何被用来改善模型的性能,因此使用了成本函数。损失函数将在每个训练示例中计算,而成本函数将是损失函数的平均值。因此,在单个训练数据集中,损失函数将被计算多次,而成本函数将仅被计算一次。
我们如何利用损失函数的力量?
所以我们的最终目标是最小化成本函数。让我们用一个简单的实时例子来理解它。想象一下,在一个黑暗的夜晚,你站在一座山脉的顶峰。当你完成了一整天的徒步旅行,现在想下去,但外面很黑,你会怎么做?你肯定会试图用最少的能量下山,而你想到的第一件事就是环顾四周,试图用你的脚找到最短的路径。你不可能上山,因为你的目标是下山,所以唯一的选择是选择下山的路。所以这就是你估计的计算,如果你走下坡路,将会花费少得多的能量和努力,这正是损失函数所做的。因此,我们的目标是“找到模型的权重和偏差,使损失最小。”
在自然界中,我们看到许多遵循这种方法的例子。
不管路上遇到什么,一条河总是走最短的下坡路。
分类和回归的损失函数:
现在,既然我们知道有两种类型的监督的机器学习问题:回归(连续目标值)和分类(离散目标值),那么让我们来探究它们中的每一个,看看所有类型的损失函数用于它们中的每一个,并基于它们对于提高机器学习模型的性能的效率来比较它们。要了解更多关于您可以使用一些技术来测量性能的信息,请在完成这篇文章后访问这篇文章以了解更多信息。
回归中使用的损失函数:
回归或回归分析是一种监督 学习 技术,可以定义为统计技术,用于对因变量实数变量 y 和自变量**【Xi】之间的关系进行建模。根据不同的场景及其重要性,我们使用不同类型的回归方法。让我们来了解各种可能的损失函数,这些函数可用于改进回归分析中的性能评估。
1.均方差/L2 损耗:
这是最常用的损失函数,因为它非常容易理解和实现。它适用于几乎所有的回归问题。顾名思义,均方差就是平方误差的平均值。这里的误差是模型预测值“ y_hat 与实际值“ y_real 之差。
了解实际值和预测值之间的误差
在上图中,小圆圈是不同的 y 的 x 的实际值。这条线代表我们通过模型预测的最佳拟合**。因此,这里的虚线是误差, MSE 是所有误差的平方平均值。**
平方是为了放大大的误差,也是为了观察我们损失的方差。
均方误差/L2 损耗
Python3 中 MSE 丢失的代码实现
2.平均绝对误差/ L1 损耗:
平均绝对误差是模型预测值和实际值之间的绝对差值的平均值**。 平均绝对误差在异常值的情况下更稳健 因为不适合求差的平方,因为差太大了。**
不管误差的方向是正还是负,因为它们可能会相互抵消,从而不会产生误差,在这种情况下,我们只考虑其大小**。**
平均绝对误差/ L1 损耗
Python3 中 MAE 丢失的代码实现
3.均方根误差:
均方根误差是均方差的平方根。当我们将平方根应用于 MSE 时,RMSE 归结为与目标变量相同的单位。RMSE 的损失函数与 MSE 完全相同,我们只是将阶数从 2 降低到 1,这样就可以轻松地进行相关运算。MSE 中的相关性变得困难,因为它严重惩罚大误差。****
均方根误差
Python3 中 RMS 损耗的代码实现
4.平均偏差误差:
平均偏差误差是预测值和实际值 之间的精确差,没有应用任何数学函数,如绝对值或平方根。MBE 的主要局限是正负误差有机会 抵消*。这就是为什么这是很少使用和不太流行的损失函数。*****
平均偏差误差
Python3 中均值偏差损失的代码实现
5.胡伯损失:
正如我们已经讨论过的, MSE 和 MAE 都有缺点,所以这就是胡贝尔的损失所在。它只从 MSE 和 MAE 中提取有益的东西,并将它们纳入一个损失函数。
使用 MSE 和 MAE 的 Huber 损失
所以简而言之, Huber 损失对于小误差接近 MSE,对于异常值接近 MAE。
胡伯损失
Python3 中 Huber 丢失的代码实现
二元分类损失函数;
1.二元交叉熵损失;
顾名思义,二元分类是指将一个物体分为两类中的任何一类。例如,将电子邮件分类为垃圾邮件或非垃圾邮件。 熵基本上是不确定性的度量。 交叉熵是 两个随机变量 的不确定性之差。
所以, 如果实际类与预测概率的差异越多,那么交叉熵损失就越多。 例如,我们假设一个数据样本的实际类别为 1,,预测概率为 0.2 。这导致高损耗值*。***
二元交叉熵损失
Python3 中二值交叉熵损失的代码实现
2.铰链损耗:
铰链损耗主要用于支持向量机*。任何分类问题中的最佳可能行都会尽可能少地犯分类错误。为了通过计算来表达这一思想,铰链损失惩罚每一个不正确的分类。***
例如,假设的实际值是 1* ,而的预测值是-1 ,那么“ l(y) 就变成了 2 ,这是一个更高的损失。而如果预测值和实际值都是 1 并且匹配,那么“ l(y) 就变成了 0 也就是没有损失。***
铰链损耗
铰链损失在[-1,1]值范围内工作良好,有时甚至比二元熵损失更好。
Python3 中铰链损耗的代码实现
3.平方铰链损耗:
铰链损耗的平方就是铰链损耗的平方。I f 你想惩罚这个大错误,平方铰链损失进入画面 。除了输出将被平方之外,最大值功能将是相同的。铰链损耗的平方与误差的平方成正比。****
平方铰链损耗
Python3 中平方铰链损耗的代码实现
多项式分类损失函数;
1.分类交叉熵损失:
这是 最常用的损失函数 ,因为它非常容易理解和实现。它几乎适用于所有的分类问题。分类交叉熵损失可以认为是二元交叉熵损失的推广。 当班级数量超过 2 个 时使用。为了计算分类交叉熵损失,最佳实践是对分类进行一次性编码*。需要为每个观察的每个类别标签计算损失,并对结果 求和 。***
Python3 中分类交叉熵损失的代码实现
2.KL (Kullback-Leibler)散度:
KL 散度衡量任意两个分布之间的差异。它帮助我们理解,“ 当我们追求一个近似值 ”时,我们丢失了多少信息。
是对熵的轻微修改。除了我们的概率分布,我们还添加了一个近似分布,并计算两个分布之间的差异。
通过这种方式,我们可以追踪我们因近似而丢失的信息。
KL(库尔巴克-莱布勒)散度
Python3 中 KL 发散损失的代码实现
希望你喜欢阅读!
你可以在这里阅读更多我的文章:
***
谢谢!***
用可解释的人工智能更好地理解机器学习模型
原文:https://towardsdatascience.com/understanding-machine-learning-models-better-with-explainable-ai-bea6d28f5094?source=collection_archive---------20-----------------------
使用 ExplainerDashboard 用几行代码构建一个交互式仪表板
图片来源:作者(Canva 设计)
通过基于网络的仪表板来解读机器学习的工作是很有趣的。想象一下,访问显示模型性能、特征重要性以及假设分析信息的交互式图表。令人兴奋的是,构建这样一个信息丰富的仪表板不需要任何 web 开发专业知识,但简单的几行 python 代码就足以生成一个令人惊叹的交互式机器学习仪表板。这可以通过使用一个名为“解释器仪表板”的库来实现。
ExplainerDashboard 是一个 python 包,它生成交互式仪表板,允许用户理解并解释模型如何工作以及它如何决定结果。没有这样的工具,机器学习模型就是“黑盒模型”。因此,很难解释模型做出决策背后的原因,以及哪些因素影响了模型的决策。使用 Python 中的这个包,我们可以在 Jupyter 或 Colab 笔记本中轻松地将仪表板部署为 web 应用程序。这个 web 应用程序提供了几个交互式图表来解释它所应用的机器学习模型的工作原理。这些模型可以基于 Scikit-learn、XGBoost、CatBoost、LightGBM 和其他一些模型。仪表板通过各种交互式
图提供对模型性能的洞察,如用于理解特征相关性的 SHAP 值图、用于特征交互的
SHAP 交互图、用于选定特征影响的部分相关性图(PDP)以及通过决策树可视化决策路径等。还可以通过“假设”分析来评估改变特征值对模型性能的影响。此外,高级用户也可以使用一些额外的代码来定制这些仪表板。对于本教程,我们将只探索该包的功能,我将带您一步一步地用 Python 创建您自己的机器学习模型仪表板,只需几行代码。在教程的最后,我们将看到我们可以从这个机器学习仪表板中收集到什么样的见解。
解释器仪表板库
这个 Python 包为机器学习模型构建了一个基于 web 应用程序或内嵌笔记本的可解释仪表板。仪表板的默认组件是不言自明的,不需要额外的定义函数。这些图表或仪表板的交互组件基于另一个名为 Dash 的库,该库以网络应用和图表而闻名,使用了一个名为“Plotly”的库。最后,整个仪表板实际上是一个使用 flask server 在本地机器上运行的 web 应用程序。你可以在这里找到所有官方文档。
让我们从 ExplainerDashboard 库的 pip 安装开始本教程
pip install explainerdashboard
您可以在 Colab 或 Kaggle 笔记本中直接使用该命令。然而,如果使用在本地机器上运行的 Jupyter 笔记本,使用虚拟环境可能是一个更好的选择,以避免由于包依赖性而导致的任何冲突。
方法:
- 导入库和样本数据集
- 从数据集创建 DataFrame(本演示教程不需要数据预处理)
- 拆分数据并训练模型
- 在本地端口上部署仪表板
回归示例机器学习仪表板
对于本教程,让我们使用 sklearn 库中的样本玩具数据集“糖尿病”数据集来构建回归问题的机器学习仪表板。
导入库
#Importing Libraries & Packagesimport pandas as pd
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from explainerdashboard import RegressionExplainer, ExplainerDashboard
我们需要 Pandas 库用于数据框架,而 ExplainerDashboard 和 Dash Bootstrap 库用于构建仪表板。sklearn 库将用于获取玩具数据集,分割它并导入 RandomForestRegressor 来为这个回归示例训练模型。
导入数据集
#Import the Diabetes Dataset
from sklearn.datasets import load_diabetesdata= load_diabetes()#print the dataset
data
加载数据集
我们需要将数据集加载到 X 和 y 变量上,以创建熊猫数据框架。x 将保存要素,y 将保存目标值。
#create a DataFrame from the dataset
X=pd.DataFrame(data.data,columns=data.feature_names)#Printing first five rows of the DataFrame
X.head()
#Load target values in y
y=pd.DataFrame(data.target,columns=[“target”])
y.head()
现在我们的数据准备好了,我们可以使用 RandomForestRegressor 来训练模型。
分割数据集
让我们使用 sklearn 的 train-test split 函数将数据集按 80–20 的比例拆分。
#Splitting the Dataset
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)
print(X_train.shape,y_train.shape,X_test.shape,y_test.shape)
训练模型
我们现在可以用随机选择的估计值的 RandomForestRegressor 来训练模型。您也可以尝试使用不同的值或使用 XGBoost 来训练模型并进行比较。
#Training the model
model = RandomForestRegressor(n_estimators=50, max_depth=5)model.fit(X_train, y_train.values.ravel())
注意:在这一步中,我们使用推荐的命令“ravel()”将“y_train”转换为一维数组。这种对列向量 y 的整形将避免由 RandomForestRegressor 生成的 DataConversionWarning。
使用训练模型设置仪表板实例
explainer = RegressionExplainer(model, X_test, y_test)#Start the Dashboard
db = ExplainerDashboard(explainer,title=”Diabetes Prediction”,whatif=False)#Running the app on a local port 3050
db.run(port=3050)
该仪表板将在端口为 3050 的本地服务器上运行(如果您选择另一个端口号,比如 8080 或 3000,那么您的情况可能会有所不同)
单击该链接将在 web 浏览器的单独选项卡中打开仪表板。
您的完全交互式机器学习仪表板已经准备好了!
你可以在我的 GitHub 库上找到这个笔记本的完整代码。
按作者分类的仪表板 GIF
仪表板中的见解
有了这个仪表板,我们可以得到一些见解,比如-
- Shap 值表示每个单独的特征如何影响预测
- 置换重要性,它允许我们更深入地挖掘,以可视化模型性能如何随着特征的改变而恶化
- 在使用类似于本教程的 XGBoost 或 RandomForestRegressor 的回归模型的情况下,我们可以可视化单个决策树,而在分类器模型的情况下,我们可以获得混淆矩阵、ROC-AUC 曲线等。更好地理解模型的决策。
- 假设分析(在启动仪表板时打开的情况下)有助于了解在我们修改特征或部分数据时模型行为的变化。它还允许我们比较不同的模型。
然而,对上面的图和它们包括的参数有一些基本的理解对于理解来自这样的机器学习仪表板的洞察力也是有帮助的。对于任何寻找本教程主题的理论详细信息的人,我建议阅读克里斯托夫·莫尔纳尔的书'可解释的机器学习。
本教程到此为止。希望作为读者的你能学到一些新的有趣的东西。
直到下一篇文章,快乐阅读!
理解自然语言处理中的掩蔽语言模型(MLM)和因果语言模型(CLM)
原文:https://towardsdatascience.com/understanding-masked-language-models-mlm-and-causal-language-models-clm-in-nlp-194c15f56a5?source=collection_archive---------2-----------------------
自然语言处理中的语言模型(视觉和例子)
来自源的修改图像
大多数现代 NLP 系统都遵循一个非常标准的方法来训练各种用例的新模型,即 首先预训练,然后微调 *。*这里,预训练的目标是利用大量的未标记文本,建立一个语言理解的通用模型,然后在机器翻译、文本摘要等各种特定的 NLP 任务上进行微调。
在这篇博客中,我们将讨论两种流行的预训练方案,即掩蔽语言建模 (MLM)和因果语言建模 (CLM)。
没时间看完整个博客?然后看这个快速的< 60 秒的 YouTube 短片—
屏蔽语言模型解释
在屏蔽语言建模下,我们通常屏蔽给定句子中的某个百分比的单词,并且该模型被期望基于该句子中的其他单词来预测那些被屏蔽的单词。这样的训练方案使得这个模型在本质上是双向的,因为屏蔽单词的表示是基于出现在它左右的单词而学习的**。你也可以把这想象成 一种填空题式的问题陈述 。**
下图显示了同样的—
蒙版语言模型|作者图片
下图显示了损失计算步骤的更详细视图—
有损失的掩蔽语言模型|作者图片
这里,屏蔽词的表示可以是基于注意力的,如 BERT 及其变体,或者你也可以设计成没有注意力。基于 Alpha (注意力权重)的分布,您可以对每一个其他输入单词的表示进行加权,以学习被屏蔽单词的表示,例如—Alpha = 1 将对周围的单词给予相等的权重(这意味着每个单词在屏蔽表示中具有相等的贡献)。
因果语言模型解释
在因果语言模型下,这里的想法仍然是预测给定句子中的屏蔽标记,但与 MLM 不同,该模型被允许只考虑出现在它左边的单词来做同样的事情*(理想情况下,这可能只是左边或右边,想法是使它单向)*。这样的训练方案使得这个模型本质上是单向的。
正如您在下图中看到的,该模型预计会根据出现在句子左侧的单词来预测出现在句子中的掩码标记。并且基于模型对实际标签所做的预测,我们计算交叉熵损失并将其反向传播以训练模型参数。
因果语言模型|作者图片
下图显示了损失计算步骤的更详细视图—
带有损失的因果语言模型|作者图片
在这里,屏蔽词的表达可以是基于注意力的,就像在 GPT 和变体中一样,或者你也可以设计成没有注意力,就像我们过去在 LSTM 时代那样。基于 Alpha (见图)的分布,您可以对每隔一个输入单词的表示进行加权,以学习屏蔽单词的表示,例如—Alpha = 1 将对周围的单词给予相等的权重(意味着每个单词将对学习的屏蔽表示具有相等的贡献)。
这些系统也被称为仅解码器模型,因为在典型的编码器-解码器架构中,如在机器翻译、文本摘要等中,解码器*(文本生成器)*的工作方式类似。
什么时候用什么?
当目标是学习输入文档的良好表示时,MLM 损失是优选的,而当我们希望学习生成流畅文本的系统时,CLM 是最优选的。此外,直觉上这是有意义的,因为当学习每个单词的良好输入表示时,你会想知道它出现的单词是左还是右,而当你想学习一个生成文本的系统时,你只能看到你到目前为止生成的所有内容*(就像人类如何书写一样)*。因此,制造一个在生成文本的同时也能窥视另一面的系统会引入偏见,限制模型的创造能力。
虽然在训练包含编码器和解码器的整个架构时,您会经常发现 MLM 和 CLM 损失。两者都有各自的优点和局限性,一种叫做 XLNet 的新模式使用了一种置换技术来利用两者的优点(MLM 和 CLM)。
我希望你喜欢读这篇文章。如果你愿意支持我成为一名作家,可以考虑注册成为中的一员。每月只需 5 美元,你就可以无限制地使用 Medium
我希望你喜欢阅读这篇博客。谢谢大家!
用 6 个代码片段理解 Matplotlib
原文:https://towardsdatascience.com/understanding-matplotlib-in-6-code-snippets-63e5b8be2c8?source=collection_archive---------15-----------------------
Matplotlib 是 python 中用于数据可视化的常用库。你探索过这个库提供的所有功能了吗?如果没有,我来帮你!
在 Unsplash 上由 Adeolu Eletu 拍摄的照片
我是亚马逊的一名应用科学家。信不信由你,我不记得有哪一周我没有在工作中使用过这个图书馆。有时我们需要可视化数据以便理解,有时在演示文稿/文档中需要可视化。因此,根据需要,我们也必须担心视觉化的直觉和美化。现在,我的朋友们,matplotlib 是我所有这些任务的首选库。在这篇博客中,我们将了解如何使用 matplotlib 来绘制以下变体:
- 用一组连续数据绘制一个正态图
- 绘图分类变量
- 使用散点图绘制图形,找出两个变量之间的关系
- 用不同的格式样式绘制图形
- 创建由多个图形组成的图形—一个图形有多条曲线,或者不同的图形有不同的曲线
- 使用图形中的文本注释。
以上并不是一个详尽的列表,但是它们应该足以理解这个库。开始吧!!!
具有连续数据数组的正常图
最直接的用例之一是在训练机器学习模型时,理解随着时期/迭代的损失行为。
import matplotlib.pyplot as plt
import numpy as nploss = np.array([1, 0.95, 0.92, 0.89, 0.83, 0.76, 0.70, 0.63, 0.54, 0.48])
epochs = np.array(list(range(10)))plt.plot(loss, epochs)
plt.show()
作者图片
是的,我知道上面的图表看起来很标准。别担心,我们会在“格式样式”部分美化它。
绘制分类变量/数据
首先,什么是分类变量?这些变量占用离散和有限数量的值。例如,在分类任务中,描述类的变量是分类变量。一个具体的例子是考虑一个图像分类问题,其中我们必须分类图像是否有狗(1)或没有(0)。那么这个代表有或没有狗出现的图像数量的变量就是一个分类变量。这些变量可以用柱状图或饼状图来表示。
条形图-:
import matplotlib.pyplot as plt
import numpy as np
class_variable = ["dog", "cat", "cow", "fish"]
number_of_image = [10, 15, 8, 20]
plt.bar(class_variable, number_of_image)
plt.show()
饼状图-:
import matplotlib.pyplot as plt
import numpy as np
class_variable = ["dog", "cat", "cow", "fish"]
number_of_image = [10, 15, 8, 20]
plt.pie(number_of_image, labels = class_variable)
plt.show()
以上两个片段的可视化(图片由作者提供)
使用散点图绘制图形,找出两个变量之间的关系
正如你可能已经猜到的,散点图是用来找出两个变量之间的关系。在这里,我们设想一个变量的变化如何影响另一个变量,或者换句话说,我们试图理解两个变量之间的相关性。
import matplotlib.pyplot as plt
import numpy as np
variable_a = np.array([5,7,8,7,2,17,2,9,4,11,12,9,6])
variable_b = np.array([99,86,87,88,111,86,103,87,94,78,77,85,86])plt.scatter(variable_a, variable_b)
plt.show()
作者图片
从上图我们可以得出,当变量 _a 增加时,变量 _b 减少。
绘图的格式样式
这是其中重要的一条。在这里,我们将看到我们可以添加到一个情节的各种美化。我们将在这里看到如何添加以下内容:
- 轴标签-有助于描述 x 轴和 y 轴在图上代表的内容。
- 图例-当我们在图形中绘制多个图时非常有用。它告诉我们哪种颜色代表图中的哪种数据。
- 标题-图的标题
- 网格—在图形中添加网格有助于获得更好的推断
- 颜色-根据您的要求设置曲线的颜色。
- 虚线-设置曲线是实线还是虚线
- 标记-设置如何表示每个数据点
因此,许多新功能正在被引入。为了理解每一个的效果,我在不同的代码行上绘制了多个图,如下面的代码片段所示。
注意— 为了便于说明,我只使用了一种标记或一种颜色。您可以查看每种类型的其他可用选项。
import matplotlib.pyplot as plt
import numpy as np
loss = np.array([1, 0.95, 0.92, 0.89, 0.83, 0.76, 0.70, 0.63, 0.54, 0.48])
epochs = np.array(list(range(10)))
plt.plot(loss, epochs, label="Loss Curve 1", linestyle="dashed", marker='*', color='red')#Plot 1
plt.xlabel("Epochs")
plt.ylabel("Loss") #Plot 2
plt.title("Loss - Epoch Curve")#Plot 3
plt.grid("on") #Plot 4
plt.legend()#Plot 5
plt.show()
作者图片
为了比较,我还展示了第一个片段中的一个图(图 6)。现在,就我们的理解而言,图 6 就足够了,因为我们只需要看到损耗如何随着每个时期而变化。尽管如此,对于新手来说,Plot 5 更适合表示所有必要的信息。
创建由多个图形组成的图形
当我们需要绘制多个支线剧情时,我们可以使用下面的片段。我还添加了不同格式样式的例子,这样你就可以更清楚地理解了。
import matplotlib.pyplot as plt
import numpy as npt1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.2)plt.figure()
plt.subplot(2,2,1)
plt.plot(t1, np.sin(2*np.pi*t1), color = 'black', marker='^', linestyle='solid')
plt.title("Sin Curve")
plt.grid("on")plt.subplot(2,2,2)
plt.plot(t2, np.tan(2*np.pi*t2), color = 'blue', marker='*', linestyle='dashed')
plt.title("Tan Curve")
plt.grid("on")plt.subplot(2,2,3)
plt.plot(t1, np.cos(2*np.pi*t1), color = 'green', marker='o', linestyle='dotted')
plt.title("Cos Curve")
plt.grid("on")plt.subplot(2,2,4)
plt.plot(t2, np.exp(t2), color = 'red', marker='*', linestyle='dashdot')
plt.title("Exponential Curve")
plt.grid("on")
plt.show()
作者图片
当在同一个图中需要多条曲线时,我们可以使用下面的代码片段。
import matplotlib.pyplot as plt
import numpy as npt1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.2)plt.plot(t1, np.sin(2*np.pi*t1), color = 'black', marker='^', linestyle='solid', label = "Sin Curve")
plt.plot(t1, np.cos(2*np.pi*t1), color = 'green', marker='o', linestyle='dashed', label="Cos Curve")
plt.legend()
plt.grid("on")
plt.show()
作者图片
正如我们在这里看到的,图例有助于直观显示哪条曲线对应于哪种函数,即 sin 或 cos。
使用图形中的文本注释。
我们可以使用测试注释来指出图中的特定点,并描述该点的含义。例如,我在下面的代码中注释了正弦曲线和余弦曲线的最大值。
import matplotlib.pyplot as plt
import numpy as npt1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.2)plt.plot(t1, np.sin(2*np.pi*t1), color = 'blue', marker='^', linestyle='solid', label = "Sin Curve")
plt.plot(t1, np.cos(2*np.pi*t1), color = 'green', marker='o', linestyle='dashed', label="Cos Curve")
plt.annotate('Sin max', xy=(1.25, 1), xytext=(1.5, 1.15),
arrowprops=dict(facecolor='black', shrink=0.05),
)
plt.annotate('Cos max', xy=(2, 1), xytext=(2.25, 1.15),
arrowprops=dict(facecolor='black', shrink=0.05),
)
plt.ylim([-1.5, 1.5])
plt.legend()
plt.grid("on")
plt.show()
我在这里增加的另一件事是定义 y 轴的极限。同样,您可以更改 x 轴的限制。
结论
以上只是几个例子,我试图尽可能地涵盖更多的内容。现在,您可以使用多种工具来创建一个伟大的可视化。如果我错过了任何重要的例子,请让我知道,以便我可以在这里添加它们。
谢谢你的来访!
关注我们的 medium 了解更多此类内容。
成为 介质会员 解锁并阅读介质上的许多其他故事。
了解混合精度训练
原文:https://towardsdatascience.com/understanding-mixed-precision-training-4b246679c7c4?source=collection_archive---------5-----------------------
训练神经网络的混合精度可以在不影响模型性能的情况下减少训练时间和内存需求
帕特丽夏·塞尔纳在 Unsplash 上的照片
随着深度学习方法的发展,人们普遍认为增加神经网络的规模可以提高性能。但是,这是以内存和计算需求为代价的,这些需求也需要增加以训练模型。
这可以通过比较谷歌预先训练的语言模型 BERT 在不同架构规模下的性能来理解。在最初的论文中,谷歌的研究人员报告称,BERT-Base 的平均得分为 79.6,BERT-Large 的平均得分为 82.1。2.5 的小幅增加带来了额外的 2.3 亿个参数(110 亿对 340 亿)!
粗略计算一下,如果每个参数都以单精度存储(下面更详细),也就是 32 位信息,那么 230M 个参数相当于内存 0.92Gb。这本身看起来并不大,但是考虑到在每个训练迭代期间,这些参数每个都经过一系列矩阵运算,每个都具有额外的相关值,例如梯度。所有这些额外的价值会很快变得难以管理。
2017 年,英伟达的一组研究人员发布了一篇论文,详细介绍了如何降低训练神经网络的内存需求,使用了一种叫做混合精度训练的技术:
我们介绍了使用半精度浮点数训练深度神经网络的方法,而不会损失模型精度或必须修改超参数。这几乎将内存需求减半,并且在最新的 GPU 上加快了运算速度。
在本文中,我们将探索混合精度训练,了解它如何适应深度学习的标准算法框架,以及它如何能够在不影响模型性能的情况下减少计算需求。
浮点精度
用于以二进制格式表示浮点数的技术标准是 IEEE 754 ,由电气和电子工程协会于 1985 年制定。
如 IEEE 754 中所述,浮点精度有各种级别,从二进制 16(半精度)到二进制 256(八倍精度),其中“二进制”后的数字等于可用于表示浮点值的位数。
与整数值不同,在整数值中,位只是表示数字的二进制形式,可能只有一位保留给符号,浮点值也需要考虑指数。因此,这些数字的二进制表示形式更加微妙,会显著影响精度。
历史上,深度学习一直使用单精度(binary32,或 FP32)来表示参数。在这种格式中,1 位保留给符号,8 位保留给指数(-126 到+127),23 位保留给数字。另一方面,半精度(FP16)为符号保留 1 位,为指数(-14 到+14)保留 5 位,为数字保留 10 位。
FP16(上)和 FP32(下)浮点数格式的比较。出于说明的目的,所示的数字是每种格式可以表示的小于 1 的最大数字。作者插图。
然而,这是有代价的。每个的最小和最大正正常值如下:
除此之外,可以表示更小的非规格化数,其中所有的指数位都设置为零。对于 FP16,绝对极限是 2^(-24)然而,随着非规格化数变小,精度也会降低。
在本文中,我们不会进一步深入理解不同浮点精度的定量限制,但是 IEEE 提供了全面的文档供进一步研究。
混合精确训练
在神经网络 FP32 的标准训练期间,以增加存储器需求为代价来表示模型参数。在混合精度训练中,FP16 用于存储训练迭代期间的权重、激活和梯度。
然而,正如我们在上面看到的,这产生了一个问题,因为 FP16 可以存储的值的范围小于 FP32,并且随着数量变得非常小,精度也会降低。这样做的结果将会降低模型的准确性,与计算出的浮点值的精度一致。
为了解决这个问题,在 FP32 中存储了重量的主副本。这在每个训练迭代(一次正向传递、反向传播和权重更新)的一部分期间被转换成 FP16。在迭代结束时,权重梯度用于在优化器步骤期间更新主权重。
混合精度训练将权重转换为 FP16 并计算梯度,然后将它们转换回 FP32,再乘以学习率并在优化器中更新权重。作者插图。
在这里,我们可以看到保留权重的 FP32 副本的好处。由于学习率通常很小,当乘以权重梯度时,它们通常是很小的值。对于 FP16,幅度小于 2^(-24 的任何数字)将被视为零,因为它不能被表示(这是 FP16 的反规格化极限)。因此,通过完成 FP32 中的更新,可以保留这些更新值。
FP16 和 FP32 的使用是这种技术被称为混合-精确训练的原因。
损耗缩放
虽然混合精度训练在很大程度上解决了保持精度的问题,但实验表明,即使在乘以学习率之前,也会出现小梯度值的情况。
NVIDIA 团队表明,尽管低于 2-27 的值基本上与训练无关,但在[2-27,2^-24]范围内有一些值得保留的值,但在 FP16 的限制之外,在训练迭代期间将它们等同于零。由于精度限制,梯度等于零,这个问题称为下溢。
因此,他们建议进行损耗缩放,即在正向传递完成之后、反向传播之前,损耗值乘以一个比例因子。链规则规定所有的梯度随后被相同的因子缩放,这使得它们在 FP16 的范围内移动。
一旦计算出梯度,它们就可以除以相同的比例因子,然后用于更新 FP32 中的主权重,如前一节所述。
在损耗调整过程中,在正向传递之后,损耗会按预定义的因子进行调整,以确保它在可表示的 FP16 值范围内。由于链规则,这通过相同的因子来缩放梯度,因此实际的梯度可以在反向传播之后被检索。作者插图。
在 NVIDIA“深度学习性能”文档中,讨论了比例因子的选择。理论上,选择一个大的缩放因子没有坏处,除非它大到足以导致溢出。
当梯度乘以比例因子超过 FP16 的最大限值时,就会发生溢出。出现这种情况时,梯度变得无限大,并设置为 NaN。在神经网络训练的早期,通常会看到以下消息:
Gradient overflow. Skipping step, loss scaler 0 reducing loss scale to…
在这种情况下,该步骤被跳过,因为权重更新不能使用无限梯度来计算,并且损失比例对于未来的迭代被减小。
自动混合精度
2018 年,NVIDIA 发布了一个名为 Apex 的 PyTorch 扩展,其中包含 AMP(自动混合精度)能力。这为在 PyTorch 中使用混合精度训练提供了一个简化的解决方案。
只需几行代码,训练就可以从 FP32 转移到 GPU 上的混合精度。这给带来了两个关键的好处:
- 减少训练时间 —训练时间减少了 1.5 倍到 5.5 倍,模型性能没有显著降低。
- 减少内存需求 —这释放了内存以增加其他模型元素,如架构大小、批量大小和输入数据大小。
阿格巴洛斯在 Unsplash 上拍摄的照片
从 PyTorch 1.6 开始,NVIDIA 和脸书(PyTorch 的创造者)将这一功能转移到 PyTorch 的核心代码中,命名为 torch.cuda.amp 。这解决了围绕 Apex 包的几个痛点,例如版本兼容性和构建扩展的困难。
虽然本文不会进一步深入 AMP 的代码实现,但是可以在 PyTorch 文档中看到示例。
结论
虽然浮点精度经常被忽视,但它在深度学习模型的训练中起着关键作用,在深度学习模型中,小梯度和学习速率相乘,以创建需要更多位来精确表示的梯度更新。
然而,随着最先进的深度学习模型在任务性能方面突破界限,架构不断发展,精度必须与训练时间、内存要求和可用计算相平衡。
因此,混合精度训练在保持性能的同时基本上将内存使用减半的能力是深度学习的一个重大进步!
理解蒙特卡罗估计
原文:https://towardsdatascience.com/understanding-monte-carlo-estimation-5409d85c4c85?source=collection_archive---------13-----------------------
阿曼达·琼斯在 Unsplash 上的照片
实践教程
蒙特卡罗估计是机器学习工程师工具箱的重要组成部分。在这里,我们直观地深入研究它,以了解它的用例、性能以及一般使用时需要记住的事项。
像任何其他好的算法介绍一样,我们从一个关于我们试图解决的问题设置的故事开始。该设置是对积分的估计。
假设我给你一个函数 f ,那真的很复杂。我告诉你你可以对 f 求值,但是我对这个函数的积分感兴趣。不幸的是,你不能解析地计算这个函数的积分——也许这是不可能的,或者你的数学水平不够高。此外,函数 f 可能不会显式给出,这可能是某种模拟,您需要运行它来计算 f 的某个值。你可以做的一个选择是积分的蒙特卡罗估计。
我们正在处理估计积分的问题,因为函数 f 可能太复杂,不允许对解进行解析计算。
事实上,正如你可能从名字上怀疑的那样,这种算法起源于赌博游戏,作为一种计算预期赢款的方法,或者基于样本计算你在赌博游戏中可以赢的预期金额。显然,反复赌博以获得更多的样本来提高你的估计是不明智的,但这是计算你的预期赢(输)的有效方法。
在概率中,期望被定义为连续情况下的积分。
所以,我们来深究一下。在蒙特卡罗抽样中,我们从函数 f 的域中抽样,我们只取样本的平均值来估计函数的期望值。为什么这是一种有效的方法?TLDR;这一切都可以归结为查看估计量的前两个矩,即均值和方差。让我们来看看数学。我们可以非常粗略地将期望值的蒙特卡罗估计定义如下:
注意上面红色加粗的部分。我想让你记住,所有的样本都是从分布中抽取的,即根据密度 p(x) 来确定目标期望值。这将允许我们在推导估计量的期望值时,操纵期望值。因此,不再拖延,让我们开始推导期望值。看看下面的推导,稍微调解一下:
事实上,我们对随机变量 f(x) 的估计均值(我们用 μ-hat 来表示)具有真正的\mu 作为期望值。为什么我们会得出这个结论?因为来自分布 p(x) 的样本是独立同分布的——简称 i.i.d .剩下的就是线性的期望了。这也意味着我们对真实均值的估计是无偏的,这是一种有趣的说法,即在期望中,它渐近地收敛于真实均值。
无偏性意味着估计量收敛于真实均值
现在你可能会问这种估计量是不是“好的”,可以说你肯定会说,它是好的,因为它收敛于真实均值,而且是无偏的。还有一点你可能需要考虑的是样本数量的收敛速度。为此,我们想看看它的方差,即到其均值(二阶(中心)矩)的期望平方距离。我们得出以下结论:
最后我们得到函数 f 除以估计量的样本数 S 的方差。这是什么意思?这意味着估计器的平方误差随着因子 O(1/S) 而下降。如果我们想看看绝对误差,取该项的平方根,我们将得到 O(1/sqrt(S))。
估计π
这样收敛速度好吗?让我们来看一个例子,估算数字 π 。假设我们不知道圆周率的前 N 位,我们想估计它们。首先,我们可能注意到,单位圆的面积定义为π。如果我们看一下单位圆的四分之一面积,我们也许能够通过从单位分布中抽取一些点来估计它。
看看下图,我们看到的是包含单位圆四分之一面积的正方形。我们可以注意到,当对它们进行均匀采样(x,y 在 0 和 1 之间)时,一个点落入圆中的概率是π / 4,即圆的该部分的面积除以正方形的面积。我们可以通过采样点并根据它们是否落在圆内来标记它们来估计这一点,本质上,我们正在推断伯努利分布参数θ的值,该值应收敛到π / 4(其期望-落在圆内的概率)。
我在 JAX 编写了这个方法的简单实现,因为 JAX 很有趣,我推荐你去看看,但是等价的代码也可以用 Numpy 编写。如您所见,这在概念上非常简单,它涉及我们从均匀分布中抽取样本,标记落在圆内的样本(第 5 行),然后计算并返回π的估计值(第 6 行)。
下图说明了随着样本数量的增加,估计量的误差是怎样的。正如所料,误差大致按照我们之前推导的 S 定律 O(1/sqrt(S))的平方根倒数发展。重要的是要记住,我们已经得出了估计量的预期误差,这意味着逐点估计它可能会在预期之外波动,如图所示。
此外,如果我们以对数标度绘制前面的图,查看绝对误差,我们会注意到,当样本大小增加一个数量级时,误差会下降一个数量级。
现在我们回到这个估计量是否好的问题上来。1/sqrt(S)收敛速度对于精确计算来说不是那么好,我会告诉你为什么。以π为例。为了在数字π的第二位上大致平均精确(我说大致是因为这是基于样本的随机算法),我们需要 4 个数量级的样本(10k 个样本)。类似地,如果我们想要大致精确到第三位数,我们将需要一百万个样本。这是相当多的样本来估计只有前 3 位数的π!幸运的是,有更好的方法可以实现更快的计算速度。
外卖食品
- 蒙特卡罗算法是一种允许我们计算期望值的基于样本的估计的算法,即计算积分的估计。
- 蒙特卡洛情况下的估计误差以 O(1/sqrt(S)) 的速率下降
- 这个收敛速度没那么好。
- 但是这种算法实现起来很简单,并且在进入更好的方法之前,它可以作为估计某个量的第一次尝试。
- 不要拿它去赌博!
值得思考的事情
- 在这个算法中,我们可能只是不负责任地忽略了一个事实,即我们假设我们可以从分布 p(x) 中采样,如果我们不能从这个分布中有效地采样,会发生什么呢?
- 如果从 p(x) 取样很贵怎么办?
照片由迪伦·克利夫顿在 Unsplash 上拍摄
理解神经网络和反向传播-第一部分
原文:https://towardsdatascience.com/understanding-neural-networks-and-backpropagation-part-i-89c2c12d72cb?source=collection_archive---------41-----------------------
relu 非线性神经网络的训练
图 1:(图片由作者提供)具有四个神经元的神经网络使用反向传播来训练,以匹配具有四个斜率的参考函数。
图 2a(图片由作者提供)(左)具有初始权重和参考函数的神经网络(右)具有最终权重和参考函数的神经网络
上面图 1 中的动画显示了使用反向传播算法训练四个神经元的神经网络。参考函数是一个形状为倒 V 形的图,每边都有一个弯曲。这是一个范围为[0,4]的图,有四个斜率。图 2a(左)显示了具有初始权重的参考函数和神经网络。图 2a(右)显示了参考函数和在 7200 次反向传播迭代后收敛到参考函数的神经网络。
本文的目的是帮助读者理解神经网络和训练中使用的反向传播算法。训练神经网络在计算上非常昂贵。反向传播算法有时会给出局部而非全局最优的解决方案。因此,对于那些部署神经网络来解决他们的问题的人来说,彻底理解该算法的基础是有用的。
本文分为三个部分,涵盖以下主题:(1)概述了监督学习的基本概念和神经网络正向计算和反向传播所涉及的数学方程。(b)将这些方程转化为将重量更新描述为视觉运动的陈述。这些运动是斜率的增大或减小,或者是斜率原点的移动。(c)提出了一组使用各种神经网络的例子。这些显示了反向传播算法的操作。python 程序用于计算和生成图形和动画,直观地显示计算过程,最后,给出一个注释,解释结果图形如何与(b)中所述的规则相联系。我希望可视化和解释将帮助用户更好地理解神经网络和反向传播。
监督学习:监督学习使用一种叫做神经网络的特殊功能来模拟测试数据集中输入和输出值之间的关系。测试数据集由一系列输入和输出值组成。神经网络具有权重参数,其值最初是猜测的。训练过程使用数据集来比较由模型预测的输出值,并修改权重,使得预测值和实际值之间的误差减小。一旦这个训练过程完成,神经网络就被用来预测新输入的输出值。
神经元:神经元是将 n 个输入向量映射到单个值的函数。它是线性和非线性操作的级联,如下所示。
N(w, x) = nl(x0*w0 + x1*w1+...+xn*wn + b)
where w = {w0, w1, ..., wn} is the weight parameter of size n,
x = {x0, x1, ..., xn} is the input vector of size n ,
b is a bias
and nl is a non-linear function,
线性运算是输入向量与相同大小的权重向量加上标量偏差值的点积。非线性函数是定义在单个变量上的函数。使用的典型非线性函数是 relu,其被定义为 relu(x) = x,其中 x > 0,否则为 0。在本文中,我们使用大小为 1 的输入向量,并选择 relu 作为非线性函数。因此,神经元的方程式是
N(x) = relu(w*x+b)其中 w 是权重,b 是偏差。
如果 w > 0,那么当 x > -b/w 时,N(x) > 0。我们将把-b/w 称为神经元的起源。
*神经网络:*神经网络是由神经元组成的计算图。在输入层中具有 n 个单输入神经元并且在输出层中具有一个 n 输入神经元的神经网络由以下等式指定
NN(x)= w0 * relu(iw0 * x+B0)+w1 * relu(iw1 * x+B1)+..+wnrelu(iwnx+bn)。
在单输入的情况下,我们可以将输入权重设置为 1(以消除冗余并提高反向传播搜索效率)。因此,神经网络方程为
NN(x)= w0 * relu(x+B0)+w1 * relu(x+B1)+..+wn*relu(x+bn)
一个关键的有用观察是(a)神经元 ni (wi *relu(x+bi))仅在 x > -bi 时对总和有贡献,即,神经元仅在 x > -bi 时是活动的。B1 点被称为神经元的起点。(b)如果神经元 ni 是活动的,斜率增加 wi。需要注意的重要一点是,n 个神经元的神经网络(具有相对非线性)表示具有 n 个斜率的连续图形。当 x > bi 时,每个神经元对神经网络的斜率有贡献,其中 bi 是神经元的偏差。
例 1 ( 一个有四个斜率的神经网络):下图 3a 所示为单输入单输出神经网络。输入层有 4 个神经元,每个神经元对大小为 1 的向量进行操作。每个神经元的权重和偏差分别为{1,1,1,1}和{0,-1,-2,-3}。所建模的函数具有单个输出,因此输出层具有 4 个输入的 1 个神经元。输出图层没有非线性,权重为{2,-1,-2,-1}。图 3b 示出了由该神经网络表示的曲线。该图表示具有四个斜率{2,1,-1,-2}的连续函数,其中斜率在位置{0,1,2,3}处变化。
图 3a(图片由作者提供):宽度为 4 的神经网络。
图 3b(作者提供的图片):由输入层中具有偏置{0,-1,-2,-3}和权重{1,1,1,1}的四个神经元以及输出层中具有权重{2,-1,-2,-1}和偏置 0 的一个四个输入神经元的神经网络建模的函数。
反向传播:反向传播是用来减少测试数据和神经网络预测值之间误差的算法。该算法反复修改最初猜测的偏差和权重,直到测试数据和神经网络预测值之间的误差在可接受的范围内。参考函数 ref_f(x)和神经网络之间的差值δ(x)和误差 e(x)由下式给出
delta(x) = (ref_f(x) - Σ wi*relu(x+bi) + b)
e(x) = delta(x)**2
where n > i ≥ 0, n
is the number of neurons in the input layer.
相对于权重和偏差的梯度被表示为相对于权重和偏差的偏导数。
grad = Σ ∂e/∂wi*Δwi + ∂e/∂bi*Δbi + ∂e/∂bi*Δb where∂e/∂wi = -2 * delta(x) * relu(x+bi)∂e/∂bi = -2 * delta(x) * (x+bi > 0) ? wi : 0) and∂e/∂b = 2 * delta(x)
权重更新的公式如下
wi = wi — lr*∂e/∂wi = wi + 2*lr*delta(x) * relu(x+bi) --- equation 1bi = bi — lr*∂e/∂bi = bi + 2*lr* delta(x) *(x+bi > 0) ? wi: 0) ---- equation 2b = b — lr*∂e/∂b = bi + 2*lr* delta(x) where lr is learning rate ----- equation 3
在前向路径中的每次迭代期间,我们计算输出 NN(x)=σwi * relu(x+bi)、误差函数 e(x ),并且在反向路径中,我们更新权重和偏差。
权重更新规则是:
如果 NN(x) < ref_f(x) i.e, delta(x) >为 0(神经网络输出小于参考值)则:
For each neuron x > -bi (active neuron)
weight increases (slope increases)
if wi > 0 bias is increased, (neuron (slope) moves left ) -- rule 1
if wi < 0 bias is decreased, (neuron (slope) moves right) -- rule 2
Here the magnitude of weight increase is proportional to delta(x) and the distance x + bi from the origin -bi.
The magnitude of change in bi is proportional to delta(x) and the value of weight wi.
如果 NN(x) > ref_f(x),即δ(x)< 0, ( Neural network output is greater than the reference value) then:
For each neuron x > -bi (active neuron)
weight decreases (slope decreases)
if wi > 0 bias is decreased, (neuron (slope) moves right) -- rule 3
if wi < 0 bias is increased, (neuron (slope) moves left) -- rule 4
Here the magnitude of weight decrease is proportional to delta(x) and the distance x + bi from the origin -bi.
The magnitude of change in bi is proportional to delta(x) and the value of weight wi.
In the next section, I present a few examples to illustrate the operation of the backpropagation algorithm. A random number generator generates 400 numbers in the range [0, 4]. A reference function generates the corresponding output. The reference function used in the examples are neural networks with fixed biases and weights. A training neural network withn神经元被选择。猜测训练神经网络的初始偏差和权重。反向传播算法更新权重和偏差,使得训练神经网络和参考函数之间的误差减小。对于神经网络的训练,使用 400 个数字的数据集一次或多次,直到误差减少到期望的限度内或者我们达到运行时间的上限。训练所需的时间将取决于权重和偏差的初始值。
本节中的示例附有情节和动画。每个例子具有(I)将具有初始偏差和权重的训练神经网络与参考函数进行比较的图,(ii)将具有最终偏差和权重的训练神经网络与参考函数进行比较的图,(iii)显示随着反向传播进行的每个神经元的偏差的图,(iv)显示随着反向传播进行的每个神经元的权重的图,(v)显示随着反向传播进行的神经网络和参考函数的图的动画,以及(vi)可选地,一些例子可以具有随着反向传播更新偏差和权重的单个神经元的图的动画。
示例 2 :让我们使用由等式 ref_fn1(x) =2 * relu(x-1.0)指定的单个神经元参考函数,其中 x 被定义在区间[0,4]上。对于训练,我们将使用一个神经元的神经网络,初始偏差为 0,初始权重(斜率)为-0.6。选择 0 的偏置,使得神经元在区间[0,4]上定义的整个数据集上是活动的。神经网络和参考函数的方程是:
neural(x) = wt*relu(x+b) where wt = -0.6 and b = 0.
ref_fn1(x) = 2* relu(x-1).
这个例子将说明单个神经元神经网络对参考函数的收敛。这里,反向传播算法将神经元从 0 向右移动到 1,并将其斜率从-0.6 增加到 2。让我们看看它是如何做到的。
下面的图 4a 是显示神经网络在 800 次迭代中收敛到参考函数的动画。图 4b 示出了随着反向传播的进行,神经元的偏差和权重的变化。图 4c 示出了神经网络的初始和最终图以及参考函数。
图 4a(作者的动画) :显示在反向传播算法的 800 次迭代中一个神经元神经网络收敛到参考函数的动画图
图 4b(作者提供的图像):(左)在 800 次迭代的反向传播期间神经元的偏差更新和(右)神经元的权重更新
图 4c(图片由作者提供):(左)neural1(x)和 ref_fn1(x)标绘初始偏差(0)和权重(-0.6),(右)neural1(x)和 ref_fn1(x)在 800 次反向传播权重和偏差更新后。
上面图 4a 中动画所示的收敛有三个阶段。这些阶段是:
阶段 1:最初,神经网络输出小于参考函数(如图 4c(左)所示)。因此斜率在 4 次迭代中从-0.6 增加到 0,并且神经元向右移动(对负斜率和正δ应用规则 2)。在接下来的 12 次迭代中,斜率继续从 0 增加到 1,但是神经元现在向左移动,因为斜率是正的(对正斜率和正增量应用规则 1)。
阶段 2:在该阶段,当δ为正时,斜率增加,神经元向左移动(规则 1),当δ为负时,斜率减小,神经元向右移动(规则 3)。然而,在 300 次迭代中,移动是这样的,即总斜率从 1.0 增加到 1.84(图 4b(右)),并且总神经元从 0 向右移动*(图 4a(左))。*
阶段 3:在该阶段中,斜率继续从 1.84 上升到 2.0,并且在剩余的 500 次迭代中神经元从 0.9 向右移动到 1.0。在此阶段斜率和神经元的移动较慢,因为每次迭代中的误差较小。
结论:这个例子显示了反向传播算法更新单神经元神经网络的偏差和权重的能力,使得它收敛于参考函数。
在下一个例子中,我们使用双神经元神经网络作为参考函数。
例 3 :参考函数由定义在范围[0,4]上的等式 ref _ fn2(x)= 2 * relu(x)-4 * relu(x-2)指定。为了训练,我们使用一个在输入层有 2 个神经元的神经网络。初始偏差为{0,-0.2},初始权重为{0。, 0.08}.选择偏置使得神经元的原点尽可能接近 0。这确保了两个神经元在输入范围[0,4]上定义的大部分数据集上都是活跃的。每个神经元的初始偏置值不同。权重的更新取决于(x+bi)的值,其中 bi 是第 I 个神经元的偏差。通过选择不同的偏置,每个神经元的权重更新和偏置更新的轨迹将是不同的。从这个例子中可以看出这种差异的影响。具有初始偏差和权重的神经网络函数为
neural2(x) = wt0*relu(x -b0)+wt1*relu(x-b1) where b0=0, b1=-0.2, wt0 = 0, wt1 = 0.08
图 5a(左)示出了神经元的偏差和(右)权重的轨迹,它们被反向传播算法更新。neuron2 的偏差仅增加到 0.14,然后开始移动到-2.16,而 neuron1 的偏差增加到 1.25,然后回到 0,如图 5a 和下面的动画图 5b 所示。
让我们看看轨迹不同的原因。
图 5a(作者提供的图像):(左)图显示了随着反向传播的进行,两个神经元的偏差和(右)权重
图 5b(作者的动画)是两个神经元的图,它们的偏差和权重被反向传播算法更新
两个神经元轨迹不同的原因是:
原因 1 :偏差不同导致权重更新不同:neuron 1 初始偏差为 0,neuron2 初始偏差为-0.2。因此,neuron1 的原点为 0,neuron2 的原点为 0.2。权重更新(来自等式 1)与 neuron1 的 delta(x)*x 和 neuron2 的 delta(x) * (x-0.2)成比例。因此,当 x > 0.2 时,两个神经元的权重都增加,其中神经 1 的权重增加的量更大。
原因 2: 权重的差异导致偏差更新的差异:偏差的更新(来自等式 2)与 delta(x)和神经元的权重值成比例。由于 neuron1 的重量较大,它比 neuron2 移动得更远。此外,当 delta 为负且权重降低时,由于 neuron2 的权重较小,因此其变为负(而 neuron1 的权重仍为正)。这导致 neuron2 向右移动,而 neuron1 仍然向左移动。这是神经元 1 和神经元 2 起源分离增加的两个原因。
原因 3: 当一个神经元活动而另一个神经元不活动时,偏差和权重出现差异:随着 neuron2 进一步向右移动,其原点越过 0,则当 x < -b1 时,它不活动(其权重不更新)。这就是为什么 neuron1 的斜率增加而 neuron2 的斜率减少的原因,如上面的图 5a(右)所示。这是两个神经元的偏差和权重轨迹不同的三个原因。
下面的图 5c 显示了神经网络收敛到参考函数时的动画图。图 5d(左)示出了具有初始偏差和权重的神经网络的图,图 5d(右)示出了具有最终偏差和权重的反向传播 3601 次迭代之后的图。动画有三个阶段。在第一阶段,两个神经元都向左移动,神经元 1 以更高的斜率进一步向左移动。在第二阶段,神经元 2 开始向右移动,而神经元 1 向左移动。在最后阶段,两个神经元都移动到它们的最终位置 0 和 2,并且斜率收敛到最终值 2 和-4。
图 5c(作者的动画)显示了神经网络在 3601 次迭代中收敛到参考函数的动画图
图 5d(作者的图像)(左)具有初始偏差和权重的参考函数和神经网络的图,以及(右)具有最终偏差和权重的参考函数和神经网络的图。
结论:因此我们看到反向传播算法更新了两个神经元,使得它们遵循不同的轨迹。这允许两个神经元的神经网络在 3601 次迭代中收敛到参考函数。
接下来让我们考虑一个具有四个神经元的参考函数的例子。
例 4 :参考函数由定义在 0 ≤ x ≤4 范围内的方程 ref _ fn(x)= 2 * relu(x)-relu(x-1)-2 * relu(x-2)-relu(x-3)指定。为了训练,我们将使用四个神经元的神经网络。初始偏差为{-0.002,-0.5,-1.0,-1.5},权重为{0.001,0.04,0.07,0.1}。与前面的例子相似,我们选择了不同的偏差。
图 6a(左)显示了具有初始偏差和权重的神经网络图,以及(右)具有最终偏差和权重的神经网络图。然而,在 20000 次迭代之后,该网络不收敛于参考函数。
图 6a(作者提供的图像)具有四个神经元的神经网络图,具有初始偏差和权重(左)以及最终偏差和权重(右)
为了理解它不收敛的原因,让我们看看图 6b 中所示的四个神经元的偏差和权重的轨迹,以及图 6c 中显示四个神经元的运动的动画。
图(作者提供的图像)6b(左)四个神经元的偏差图,(右)四个神经元的权重(斜率)图
图 6c(作者的动画)显示了随着反向传播的进行,四个神经元的位置和斜率的动画。
全局最优要求四个神经元以斜率{2,-1,-2,-1}移动到位置{0,1,2,3}。相反,如图 6b 所示,四个神经元{紫色、绿色、蓝色、橙色}以斜率{1.42,0.5,-1.33,-2.1}移动到位置{0,0,1.22,2.22}。因此,neuron1 和 neuron2 都收敛于位置 0。这导致两个神经元在位置 0 合并成一个神经元,组合斜率为 1.42+0.5 = 1.92。
从图 6b 中我们可以看到,neuron1 和 neuron2 的斜率是正的并且在上升。当 delta(x) > 0 且 x > -b2 时,neuron1 和 neuron2 都向左移动。当 delta(x) < 0 and x < -b2 (i.e., neuron2 is inactive) neuron1 will move to the right and neuron2 will not be updated as it is not active when x < -b2. Overall neuron1 moves right as the movement to the right is larger, while neuron2 moves left. This is the reason for coalescing of these two neurons. Thus effectively we have a neural network of three neurons with bias {0, -1.22, -2.22} and weights {1.92, -1.33, -2.1}. This is the reason for reaching a local optimum and not a global optimum.
There are two solutions to this problem.
Solution1 :一个是改变 bias 的初始值,使神经元更向右展开。让我们选择以下初始偏差{0,-0.75,-1.5,-2.24}和权重{0,0.02,0.05,0.08}。图 7a 显示这导致 19200 次反向传播迭代的收敛。图 7b 示出了偏置和权重的轨迹。我们看到三个神经元向右移动,斜率为负。由于 neuron2 向右移动并具有负斜率,它避免了与 neuron1 合并的问题。最终偏差为{0,-1.0,-1.97,-2.93},最终权重为{1.96,-0.99,-1.82,-1.15}。图 7c 是显示神经网络在 19200 次迭代中收敛到参考函数的动画图。
图 7a(作者提供的图像)(左)具有初始位置{0,0.75,1.5,2.24}的参考函数和神经网络的图,以及(右)具有最终位置{0,1.0,1.97,2.93}的参考函数和神经网络的图
图 7b(作者提供的图像)(左)随着反向传播的进行,四个神经元的偏差图和(右)权重图。
图 7c(作者提供的图像)在 19200 次迭代中,初始神经元位置在{0,0.75,1.5,2.24}处收敛到参考函数的神经网络的动画图
第二种解决方案是使用具有五个神经元的神经网络。
解 2 :我们用一个五个神经元的神经网络,初始偏差为{0,-0.4,-0.8,-1.2,-1.6},权重为{-0.08,-0.06,-0.02,0.02,0.06}进行训练。图 8a(左)是将参考函数与具有初始偏差和权重的神经网络进行比较的图。图 8a(右)显示了在 20000 次迭代后收敛到参考函数的具有最终偏差和权重的神经网络的图。
图 8a(图片由作者提供)(左)具有初始偏差和权重的参考函数和神经网络的图,以及(右)具有最终偏差和权重的参考函数和神经网络的图。
图 8b(作者提供的图像)(左)图示出了随着反向传播的进行,五个神经元的偏差和权重(右)的轨迹。
图 8c(作者的动画)显示了在 20000 次反向传播迭代中五神经元神经网络收敛到参考函数的动画图
图 8b 示出了五个神经元的偏差和权重的轨迹。我们看到 neuron1 和 neuron2 仍然以 0 的偏差结合在一起。其他三个神经元的偏差收敛于{-1,-2,-2.89}。权重收敛到{1.24,0.72,-1.05,-1.67,-1.25}。因此,收敛性比先前的四个神经元的网络好得多。
下一个解决方案结合了解决方案 1 和解决方案 2。这里,我们使用五个神经元,它们的初始偏置如解决方案 1 中一样向右移动。
解 3 :我们用一个五个神经元的神经网络,初始偏差{0,-0.6,-1.2,-1.8,-2.4,},初始权重{-0.06,-0.04,-0.02,0.02,0.06,}。图 9a(左)示出了将具有初始偏差和权重的五个神经元的神经网络与参考函数进行比较的图,图 9a(右)示出了在 12,400 次迭代之后具有最终偏差和权重的五个神经元的神经网络进行比较的图。图 9b 示出了具有五个神经元的神经网络的偏差和权重的轨迹,而图 9c 是示出了神经网络在 12,400 次迭代中收敛到参考函数的动画。最终偏差为{0.022,-0.04,-1.08,-1.99,-2.89},最终权重为{1.43,0.54,-1.1,-1.69,-1.16}。
图 9a(作者的图像)(左)具有初始权重的参考函数和具有五个神经元的神经网络的图,(右)具有最终偏差和权重的参考函数和具有五个神经元的神经网络的图。
图 9b(作者提供的图像)(左)随着反向传播的进行,神经网络的偏差和(右)权重的轨迹图。
图 9c(作者的动画)显示了在 12,400 次迭代中五神经元神经网络向参考函数的收敛的动画图。
结论:神经网络的监督训练非常耗时。反向传播算法使用最速下降算法移动神经元并调整权重。将初始偏差分配给输入数据范围内的值非常重要。最好给每个神经元分配不同的偏置值。这是很好的传播偏见,以避免合并神经元。
理解正态分布
原文:https://towardsdatascience.com/understanding-normal-distribution-a40701efb134?source=collection_archive---------29-----------------------
在本帖中,我们将介绍正态分布的基本概念、属性和实际值。如果你想讨论什么或者发现错误,请发邮件到Lvqingchuan@gmail.com:)给我
热身
来自标准正态分布 N(0,1)的 10,000 个样本的密度
在开始之前,我想让你仔细看看上面的图表。这描绘了从标准正态分布 N(0,1)抽取的 10,000 个随机样本的密度。你在这里看到了什么?这是一个相当对称的图表,大多数数据点都以平均值 0 为中心。离平均值越远,数据点就越少。距离平均值两倍方差以内的数据点几乎覆盖了所有数据。
在这篇文章的后面,我们将会看到钟形和距离平均值的距离导致了一般的正态分布的重要性质。
侧栏
在本文中,我们将使用术语“随机变量”和“标准差”。这里有一个简短的回顾:
- 随机变量是同分布和独立分布的
- 标准差σ是方差的平方根。标准误差 s 是标准偏差除以样本大小的平方根,σ/sqrt(n)。
基本概念
数学和统计考试中经常给出正态分布的公式。我从来不喜欢背公式,但这个公式确实不难理解。对于独立同分布的变量 x,我们说 x 服从正态分布,如果概率密度函数(pdf。)的 x 可以写成:
忘记左边的第一个分数。它只是确保这个概率密度函数的积分等于 1。这是概率函数的基本属性之一。观察指数函数中的分数,你会发现它实际上是:
还是那句话,忘记左边 1/2 的分数。当你对上面的表达式求一阶导数时,它只是确保了右边部分的平方会被抵消掉(还记得吗?exp(f(x))的导数是 f’(x)exp(f(x))。我们为什么要求导?因为我们想找到局部极大值!为了确保局部/全局最大值处于总体均值,我们在分子上有(x 减去总体均值);为了确保 x 的分布曲线是钟形的(先增加,然后减少),我们在 1/2 前面有负号。此外,再想想什么是平方和相关的分布,你会发现(更多在属性部分):
1 度卡方分布和这里有什么关系?还记得卡方图(1)吗:
自由度 1 的卡方分布中 10,000 个随机样本的概率密度。
卡方(1)在这里是方便的,因为这种分布确保概率密度函数的增加/减少速率更小,因为 x 与总体均值的差异更大——再次是钟形曲线(BAM!).
性能
- 线性组合。将两个正态分布的随机变量组合在一起,您将再次得到一个正态分布的随机变量,尽管参数不同:
用一个“微妙”的概率密度函数来证明上述说法,将是一件痛苦的事情。然而,你可以用特征函数来攻击它。自己试试,然后查看维基百科页面寻找答案。一旦两个随机变量的情况清楚了,我们就可以通过归纳把它推广到多个(k 个)随机变量的情况。
- 线性变换。正态分布随机变量的线性变换仍然是正态分布随机变量:
这种说法的证明又是通过特征函数。我给出一维情形的证明如下。你可以自己升级到矩阵版本。
上述证明中唯一的技巧是让 s = at。
- 68–95–99.7 规则。这不是正态分布标准偏差的准确描述。然而,它在实际估算中工作得相当好。它说当 x~N(μ,σ):
这只是通过查看正态分布的累积函数值(z 得分)得出的近似值。这里有一个图表说明:
68–95–99.7 用标准正态分布说明的规则
实用价值
- 中心极限定理。这个著名的定理告诉您总体均值μ和方差σ为 N(μ,σ /n)的足够大样本的样本均值的分布,无论总体的分布是什么:
换句话说,当您重复抽取几乎无限多的替换样本时,每批样本的样本均值将遵循正态分布。̶i̶̶d̶o̶n̶'̶t̶̶h̶a̶v̶e̶̶a̶n̶̶i̶n̶t̶u̶i̶t̶i̶v̶e̶̶e̶x̶p̶l̶a̶n̶a̶t̶i̶o̶n̶̶a̶b̶o̶u̶t̶̶i̶t̶̶(̶n̶o̶r̶m̶a̶l̶̶d̶i̶s̶t̶r̶i̶b̶u̶t̶i̶o̶n̶̶i̶s̶̶t̶h̶e̶̶o̶n̶e̶̶m̶a̶g̶i̶c̶a̶l̶̶u̶n̶d̶e̶r̶l̶y̶i̶n̶g̶̶p̶o̶w̶e̶r̶?̶ ̶)̶、̶a̶l̶t̶h̶o̶u̶g̶h̶这个定理可以用特征函数和泰勒定理从理论上证明(参见本维基百科第页供参考)。更新 20220604 :一个直观的解释就是扔骰子。当你连续投掷两个骰子(每边 1-6)多次,并计算每次两个骰子的总和,你将得到比最大值 12 或最小值 2 多得多的 6-9。这是因为更容易得到中间值,如 1+6、2+5、3+4,然后得到极值,如 6+6。
中心极限定理有助于在足够大的样本量下满足关于正态分布的假设。两个常见的例子:
a)。t 检验和 z 检验。这些测试在假设检验和 AB 测试中非常流行。在最简单的情况下,他们根据样本统计比较两个总体均值。一个必要条件是每组样本均值的正态分布。另一个必要条件是用于计算每组标准误差的观察值的正态分布。有了这两个条件,我们将能够构造一个遵循 t 分布或标准正态分布的检验统计量。只要你有一个非常大的样本量,中心极限定理通过满足这两个条件使你的生活变得容易。
另一方面,几乎所有的 t-统计量的应用,如构造总体均值的置信区间,都需要相当大的样本量,因为中心极限定理保证了样本均值在每组中的正态分布。
b)。线性回归。根据高斯-马尔可夫定理,如果你想要方差最小的无偏系数估计量,你需要残差项服从正态分布。然而,这并不是获得无偏系数估计量的必备假设。之前写过一个帖子解释线性回归的不同假设:了解线性回归假设。
- 日志转换。如果您计划使用线性回归模型,并且您的标注是对数正态形状(右偏),您可能希望对数据应用对数变换。下面是在我的爱荷华房屋预测项目中转换前后标签的可视化:
左:原始数据;右图:对数转换数据
使用对数转换有两个目的:
a)。提高对偏斜度敏感的模型的性能,如回归随机森林和线性回归。回归随机森林使用所有树的平均输出,当标签中有异常值时,可能会相差很远。同样,线性回归确实是预测标签的条件期望。我之前写过实现随机森林和理解线性回归假设。
b)。获取此转换变量的正态分布属性,如可加性(属性部分中的线性组合)和线性(属性部分中的线性转换)。换句话说,如果您在原始尺度上增加了百分比(2%),那么转换后的数据将增加 20 美元。当原始数据的规模变化很大时,这尤其有用——100 美元的 2%增长与 100 万美元的 2%增长截然不同。通过日志转换,您可以更直观地查看数据。
您可能已经意识到,日志转换是有代价的。当你只想减少线性模型中的右偏时,你不得不承认对系数的解释从多重性(2%)变成了可加性(20 美元)。这种变化并不是在所有情况下都有意义,尤其是当您的原始数据确实在使用加法标度时。
此外,如果对因变量进行变换,假设检验中的 t 统计量和 p 值也会发生变化。这不难理解。对数变换会改变数据的标准差,从而影响 t 统计量和 p 值,但没有特定的模式(可能是膨胀或收缩)。那么,当数据进行对数转换时,我们应该使用检验统计量和 p 值吗?多半是的!只要您的目的是使数据更正常(更少偏斜),并且您的对数变换实现了这一目的,就没有理由怀疑测试统计或 p 值的有效性,尽管它们可能与您从未经变换的数据中获得的结果不同。但是,当您执行对数转换只是为了使建模结果更容易理解时,您不希望在没有检查转换数据分布的情况下搞砸假设检验。在极端情况下,当原始数据左偏时,执行对数变换将使数据更加左偏。这使得样本均值服从正态分布的 t 检验假设之一难以满足。因此,这种情况下的检验统计量和 p 值可能有偏差。
了解对象检测
原文:https://towardsdatascience.com/understanding-object-detection-1d810164b8a6?source=collection_archive---------13-----------------------
数据科学家和 ML 工程师的学习材料
利用深度学习检测图像对象(R-CNN、SSD、YOLO)
来源 Unsplash
想象一下谷歌照片:对于你所有的照片,你如何用物体来标记它们。要不要一个一个贴标签?
自动驾驶汽车怎么样?它们如何检测行人、汽车、交通灯和即将出现的障碍物?
输入物体检测算法
从图像分类到物体检测
近年来,图像分类获得了巨大的吸引力,特别是在 CNN 和破坏性应用程序(例如:自动驾驶汽车)中。2015 年,ImageNet 竞赛产生了比人类表现更好的 RESNet。
ResNet 表现优于人类(作者注释)
虽然图像分类(例如:CNN 堆栈)在对图像进行分类方面非常有效,但它在检测图像中的多个感兴趣对象以及了解它们在图像中的位置方面仍然存在局限性。
物体检测比图像分类更进了一步,画出了一个或多个感兴趣物体的边界框。
在本教程中,我们将学习使用 R-CNN 和 YOLO 快速检测物体的方法。
物体检测的一般步骤是什么?
1.对象定位
哪里的是对象?
**要定位对象,我们需要识别兴趣对象的焦点锚点。**这来自区域提案,用于定制水平/垂直细长框。每个位置都有一个锚点。
我们创建一个模型来生成标记感兴趣区域的区域提议。我们指定边界框并注释代表这些特定区域提议的图片片段。这包括多种方法,例如:滑动窗口(强力)、选择性搜索(聚类)和区域提议网络(深度学习)。
2.对象分类
图像中的是什么 ?
我们将所有视觉特征提取到包围盒中,并在区域提议上评估每个包围盒。这包括核函数和直方图函数。
对于每一个形状,我们将计算回归量,以检查锚如何偏离地面真相。我们还讨论了区域提议,它维护了由主干架构表示的兴趣对象(例如:CNN/VGG16/etc)
3.非最大抑制
我们寻找可能的包围盒,其捕获并集上的交集(IOU)内的锚。这允许我们将所有重叠的框减少到单个有代表性的边界框。
图像分类和对象检测(来源于作者)
现有的物体检测操作有哪些?
美国有线电视新闻网
R-CNN 通过提出选择性搜索从图像中提取区域(又名。区域提案)。选择搜索将 1)生成子分割以生成候选区域,2)使用贪婪算法来组合相似区域,以及 3)使用生成的区域和最终候选区域。
扭曲区域被馈送到 CNN 分类器,CNN 分类器提取特征图以馈送到支持向量机( SVM )。如果对象存在于扭曲区域内,SVM 进行分类。然后回归器将调整并设置边界框来表示区域建议。
尽管 R-CNN 在确定代表性区域方面很有效,但它仍然效率低下,因为它需要花费大量时间来训练所有 2000 个扭曲区域。选择性算法也可能导致一代又一代的不良候选人,从而减慢整个过程。
美国有线电视新闻网(来源于作者)
快速 R-CNN(双摄)
你需要有多个 CNN 分类器。在 2014 年的论文中。这使用更快的选择搜索。快速 R-CNN 也被称为双镜头,因为它直接运行地区提案和 CNN。
快速 R-CNN(来源于作者)
更快的 RCNN
由于快速 RNN 地区的建议可能是浪费,我们实际上可以运行地区的建议,使用要素地图作为输入。这更快也更直接,因为要素地图已经包含了感兴趣的对象。
更快的 R-CNN(来源于作者)
单发探测器(SSD)
SSD 通过从每个卷积层计算包围盒和图像分类来关注速度。SSD 用的是 VGG19,主干架构,想用什么架构就用什么架构。我们可以使用 RESnet,但由于它的复杂性,它违背了目的,因为它意味着速度。另一种选择是 MobileNet,用于小物体检测程序。
你可以看一下 tf2_detection_zoo 中完整的开源算法列表。
固态硬盘(来源于作者)
其他技术
- 你只看一次(YOLO) 类似于 SSD,但不是通过特征地图计算边界框,YOLO 使用暗网作为 CNN 堆栈主干,并聚合最后三层 YOLO 使用暗网作为主干。
- **基于变压器的探测器(脸书)。**也用于检测图像中的物体。
- 面具 RCNN 怎么样?蒙版是图像分割。这是目标检测的另一个应用。这显示了细分的确切含义。
练习物体探测
本教程展示了如何用图像对对象进行分类。你将获得一些实践经验,并对以下概念形成直觉:
- 使用来自 Tensorflow 对象检测库的预训练模型和 MSCoco 数据集进行开箱检测
- 通过用新的开箱即用检测之外的类修改现有的对象检测体系结构来转移学习。本培训将在急切模式下进行(TF2)
用 GPU 运行这个 colab 大概需要 1 个小时。请随意打开下面的 colab 并开始使用:)
图书馆
我们使用 TensorFlow 对象检测 API (ODAPI)库,通过 TF 后端迭代不同的对象检测配置。
- TF-Slim 是一个轻量级的库,用来定义、训练和评估 TF 模型。这个库是由谷歌人工智能大脑团队开发的,目前仍在开发中,因此使用它需要自担风险(可能会很快被弃用)。
- pycocotools 为对象检测和图像分割提供了庞大的图像数据集。 COCO 数据集
!pip install tf_slim
!pip install pycocotools
基于 COCO 数据集安装现成模型
我们将使用“MobileNet SSD”(模型动物园)来尝试我们的开箱即用模型。
使用export_inference_graph.py
工具导出的任何模型都可以通过指定模型名称和路径来加载。
model_name = ‘ssd_mobilenet_v1_coco_2017_11_17’
detection_model = load_model(model_name) # a helper function to access http://download.tensorflow.org/models/object_detection
创建推理
- 给模特打电话
- 生成带遮罩的边界框(批注的形状)
model_fn = model.signatures[‘serving_default’]
output_dict = model_fn(input_tensor)if 'detection_masks' in output_dict:# Reframe the the bbox mask to the image size.detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks(output_dict['detection_masks'], output_dict['detection_boxes'],image.shape[0], image.shape[1])
detection_masks_reframed = tf.cast(detection_masks_reframed > 0.5, tf.uint8)
output_dict['detection_masks_reframed'] = detection_masks_reframed.numpy()
使用 IPyImage display
功能显示图像:
display(IPyImage(open(anim_file, ‘rb’).read()))
注意,注释称浣熊为猫/狗/鸟/棒球手套。这意味着在 coco 数据集上训练的模型不知道如何识别浣熊。
浣熊与可可数据集(来源于作者)
训练和注释数据
我们可以使用我们准备好的训练集来训练我们的模型识别浣熊。一个简单的方法是使用object_detection.utils
中的colab_utils
工具进行注释。
使用 colab_utils 进行手动注释(来源于作者)
自我注释后的浣熊图像(来源于作者)
利用 RetinaNet 进行迁移学习
我们可以使用预先训练好的模型根据新的类别进行微调。在这种情况下,我们将使用 RetinaNet 架构,避免在实验和微调过程中浪费时间。Tensorflow 在tensor flow/models/research/object _ detection下有物体检测。
在此单元中,我们构建了一个单阶段检测架构(RetinaNet ),并恢复了除顶部分类层(将自动随机初始化)之外的所有层。
目标是加载管道配置并构建检测模型。因为我们是在一个默认情况下预测 90 个类槽的 COCO 架构下工作,所以我们在这里重写了“num_classes”字段,使其只有一个。
假设我们只注释了 10 幅图像。我们不需要创建批量输入,只需通过测试映像运行模型。
#more code in the colab.image, shapes = detection_model.preprocess(tf.zeros([1, 640, 640, 3]))
prediction_dict = detection_model.predict(image, shapes)
_ = detection_model.postprocess(prediction_dict, shapes)
print(‘Weights restored!’)optimizer = tf.keras.optimizers.SGD(learning_rate=learning_rate, momentum=0.9)
train_step_fn = get_model_train_step_function(
detection_model, optimizer, to_fine_tune)
最终结果
使用正确的模型和正确的注释进行训练。这 10 个图像应该足以将图像标记为浣熊
浣熊在 RetinaNet 迁移学习后,使用手动注释和 COCO 数据集(来源于作者)
常见问题
还有哪些工具可以帮助图像注释?
在微软 coco 中,大约有 1000 张图片和 80 个对象。但是有时我们想在不存在的物体上训练模型。
我个人认为由亚马逊工程师开源的标签是最有用的标签工具。但是如果你不想使用它,我们总是有 Tensorflow 助手函数来帮助你标记和注释。
来源于 Github
我们需要多少数据?
使用迁移学习,你不需要太多的数据,在我的教程中,你可以在 12 幅图像内运行它。但是当然这取决于用例。如果您需要在晚上运行 SSD,并使用深色图像,那么您可能也需要在上面上传许多图像。
你拥有的数据越多越好,然而随着更多数据的输入,你会发现收益递减。最重要的是拥有代表您需要的数据。这是连体网络的情况,其中具有相同参数和权重的相同配置适用于多个标签。
我们怎么知道生产哪一个?
很多时候,我们会用微服务来投放。这意味着我们将安装一台服务器,提供 API 网关来连接其他服务,并在请求到来时给出结果。对于模型的类型,这真的取决于你是优先考虑准确性(R-CNN)还是速度(SSD)。这里我提到了一篇非常酷的论文
参考资料:
博客
- R-CNN,快速 R-CNN,快速 R-CNN,YOLO
- MLSS 教程为基础代码归功于罗尼·卡尔法里西
报纸
https://arxiv.org/abs/1611.10012
关于作者
文森特用 ML @ Google 对抗网络滥用。文森特使用高级数据分析、机器学习和软件工程来保护 Chrome 和 Gmail 用户。
除了在谷歌的工作,文森特还是乔治亚理工学院计算机科学硕士校友,三项全能运动员和数据科学媒体的特约作家,该媒体在全球拥有超过 100 万的观众。
最后,请通过LinkedIn、Medium或 Youtube 频道 联系文森特
深刻的知识的理解
原文:https://towardsdatascience.com/understanding-of-and-by-deep-knowledge-aac5ede75169?source=collection_archive---------9-----------------------
思想和理论
知识结构如何将人工智能从表面相关性转化为对世界的理解
鸣谢:学习与教育——大脑功能开发理念 by Imagens Livres 授权:【https://creativecommons.org/licenses/by/2.0/】T4
哪些知识让你变得聪明?你的认知用来理解世界、解读新体验、做出深思熟虑的选择的构念是什么?定义一个框架,阐明使人类或人工智能(AI)能够理解和更高认知的各种知识,将有助于就如何有效实现这些结构进行结构化讨论,并绘制出一条通往更智能机器的道路。
允许人工智能系统组织其世界观、理解意义并展示对事件和任务的理解的知识结构将可能处于更高水平的机器智能的中心。机器认知将扩展到锚定在知识结构中的数据之外,包括描述性知识、世界动态模型和出处等维度。
学习语言时,我们区分形式和意义 : 形式是指用来表示意义的符号——表面表达。每种形式在特定的上下文中都有特定的含义,并且形式在不同的上下文中可以有不同的含义。正如 schlkopf、Bengio 等人在一篇文章中总结的那样,“当前大多数成功的机器学习可以归结为对适当收集的独立同分布(i.i.d .)数据的大规模模式识别。”系统摄取可观察的元素,如文本字符、声音信号和图像像素,并建立模式和随机相关性,同时为基于识别的任务产生出色的结果。
越来越多的人同意,算法必须超越表面相关性,进入的含义和理解,以实现更高水平的机器智能。这种明确的转变将实现所谓的系统 2 、第三波或广义/灵活人工智能。正如我在核心博客 ' 认知人工智能的崛起 *,*中概述的那样,机器智能的下一个级别需要深层的知识结构,这些知识结构可以将人工智能从表面相关性转变为对世界的理解,代表抽象、关系、学到的经验、见解、模型和其他类型的结构化信息。
DARPA 的 John Launchbury 指出人工智能的各个方面将在第三波人工智能中看到抽象(即创造新的意义)和推理(规划和决策)的转型改进。第三次浪潮本身的特点是背景适应,其中系统为现实世界的现象类别构建背景解释模型。这里提出的框架提供了一个关于知识结构如何促进这种飞跃的视角。
其中两个知识维度反映了对世界的看法——描述性 维度及其对世界的概念抽象,以及真实世界 及其现象的动态 模型。 故事 增加了人类理解和交流基于共同信仰和神话的复杂故事的能力。 上下文和源属性 以及 值和优先级 是元知识维度,其提供了有效性和关于知识的知识的基于条件的覆盖。最后, 概念引用 是结构支撑,跨维度、模态、引用绑定。总之,这六个知识维度可以带来超越事件相关性的额外深度,通过假设持久的潜在概念,可以解释和预测过去和未来的事件,允许规划和干预,并考虑反事实现实,因此使用术语“深度知识”
阐明和描述机器智能所需的各种知识结构有助于确定实现它们的最佳方式,从而实现下一级机器智能。这个博客的目标是建立被认为与下一级人工智能认知能力的发展相关的知识结构的基本类别。
支持高智能的知识维度
对于人工智能系统,实现人类理解和交流中观察到的知识结构可以为智能提供实质性的价值。当所有的知识类型都得到支持和结合时,这种价值就会大大增加。
支持高等智力的知识维度。鸣谢:Gadi Singer/英特尔实验室。
1。 描述性知识:层次、分类和属性继承
描述性知识(即概念性、命题性或陈述性知识)描述事物、事件、它们的属性以及它们彼此之间的关系。深度描述知识的概念扩展了这个定义,假设使用(适当的)类或概念的层次分层。这类知识可以包括事实和记录系统。与特定用例及环境相关的事实和信息可以作为分层知识来组织、利用和更新。
在单个 AI 系统中使用的底层本体可以用来自管理系统的任务相关类和实体来播种(例如 OpenCyc 本体或 AMR 命名实体类型)。它应该可以用神经网络/机器学习技术来扩展——新知识的获取将贡献新的实体、关系和类。
2。 世界车型
世界中的现象模型使人工智能系统能够理解情况,解释输入/事件,预测潜在的未来结果并采取行动。这些模型是抽象/概括,可以分为正式模型和近似(非正式)现实世界模型;它们允许变量的使用和在特殊情况下对实例的应用,并支持特殊实例或更一般化的类的符号操作。
形式模型的例子包括逻辑、数学/代数和物理。与正式的模型相反,现实世界的模型通常是经验的、实验的,有时是混乱的。它们既包括物理模型,也包括心理和社会学模型。程序模型(“诀窍”)包含在本课程中。
因果模型是可以帮助人工智能系统发展到下一个机器智能水平的模型类型的主要例子。在背景发生变化的情况下,如果与因果关系等知识模型相结合,并与对主导原因的背景的理解和考虑反事实的能力相结合,过去的统计数据只能有效地应用于现在来预测未来。这些模型有助于从引发情况或事件的条件和可能因素的角度来理解情况或事件。因果推理是人类思维不可或缺的组成部分,可以形式化为实现人类水平的机器智能。
3。 故事和剧本
正如历史学家尤瓦尔·赫拉利所说,故事是个人和社会的文化和世界观的重要组成部分。故事的概念是完全理解和解释人类行为和交流所必需的。故事是复杂的,可能包括多个事件和一个关联叙述中的各种信息。它们不仅仅是事实和事件的集合。相反,它们包含了关键的信息,有助于开发理解和归纳超越了提出的数据。不同于世界模型,世界模型被期望提供一个世界的可操作的表现和一个人如何与它互动,故事可以被看作是历史的,参考的或精神的。故事可以代表价值观和经验,并告知人们的信仰和行动。例子包括宗教或民族故事,神话,以及任何层次的群体分享的故事。
4。 上下文和来源归属
上下文可以定义为围绕事件或其他信息的框架,并为其适当的解释提供资源。它可以被看作是一个覆盖的知识结构,调整它所包含的知识。上下文可以是持久的,也可以是短暂的。
持续的背景可以是持久的(如从西方与东方哲学的角度获取的知识)或者它可以基于新的材料学习随时间而改变。它不会因任务而改变。
在特定的本地上下文很重要的情况下,瞬态上下文是相关的。单词在其周围的句子或段落的本地上下文中被解释。图像中的感兴趣区域通常在整个图像或视频的上下文中解释。
持久的和短暂的背景相结合可以提供完整的环境来解释和操作知识。
知识的另一个相关方面是数据起源(又名数据血统),它包括数据起源、数据发生了什么以及数据随时间移动到哪里。人工智能系统不能假设所有摄取的信息通常都是正确或可信的,特别是关于被称为后真相时代的信息。将信息与其来源联系起来可能是建立可信度、可认证性和可追溯性所必需的
5。 【价值和优先权(包括善良/威胁和道德)】
知识的所有方面(例如,对象、概念或过程)都可以在判断范围内具有相关的价值——从最大的善到最大的恶。可以假设人类智力的进化包括对回报的追求和对风险的规避(获取午餐;避免成为午餐)。这种风险/回报关联与对事物的认识紧密相连。潜在的得与失具有功利价值;对于正在考虑的实体或潜在的未来状态,也有基于伦理的价值。这可以反映出这样的伦理价值观,即赋予“善”不是基于潜在的有形回报或威胁,而是基于对什么是正确的潜在信念。
价值和优先级是元知识,反映了人工智能系统对知识、行动和结果的相关方面的主观断言。它建立了问责制的基础,应该由负责特定人工智能系统的人小心处理。当人工智能系统与人类互动并做出影响人类福祉的选择时,潜在的价值和优先化系统很重要。
6.概念引用:消歧、统一和跨模态
知识是以概念为基础的。例如,“狗”是一个抽象概念,具有多个名称(例如,在各种语言中)、一些视觉特征、声音联想等等。然而,无论其表现形式和用法如何,基本概念“狗”是独特的。它映射到英语单词“dog”,也映射到法语单词“chien”它也是属于的财产
以及狗吠声的可能来源。
概念引用(或简称 ConceptRef)是与给定概念相关的所有事物的标识符和引用集。ConceptRefs 本身实际上并不包含任何知识——知识存在于上述维度中。概念参考是多维知识库的关键;因为它们融合了这个概念的所有表象。
Wikidata 是集中存储结构化数据的知识库的一个很好的例子。在维基数据中,条目代表人类知识中的所有事物,包括主题、概念和对象。Wikidata 的条目类似于这个框架中 ConceptRef 的定义——只有一个关键区别。在 Wikidata 中,术语“项目”指的是给定的标识符以及关于它的信息。ConceptRefs 只是指向知识库的标识符。关于概念的信息填充在前面章节中描述的各种视图中(例如与概念相关的描述性或程序性知识)。
常识性知识
常识知识由隐性信息组成——人类自动应用来理解世界的一组广泛(且广泛共享)的未写假设。将常识应用于各种情况对于理解和更高层次的认知是必不可少的。在这个框架中,常识知识被认为是上述六种知识类型的子集。
理解与知识类型的关系
理解是智力的基础。即将向更高的机器智能过渡引发了一场关于“理解”的讨论。Yoshua Bengio 描述了人类水平的人工智能理解如下:捕捉因果关系和世界如何运转;理解抽象的行动以及如何使用它们来控制、推理和计划,即使是在新奇的场景中;解释发生了什么(推论,学分分配);和非分布发电。
考虑以下以知识为中心的理解的定义:创造用丰富的知识表征表达的世界观的能力;获取和解释新信息以增强世界观的能力;以及对现有知识和新信息进行有效推理、决策和解释的能力。
四个功能是这种理解观的先决条件:表示丰富的知识、获取新知识、跨实体和关系链接知识的实例以及对知识进行推理。自然,理解不是二元属性,而是因类型和程度而异。这一观点的核心是知识的本质及其表现形式——知识结构和模型的表达能力可以促进理解和推理能力的分类差异。
想象所有的人[和机器]
正如阿尔伯特·爱因斯坦所观察到的,“智慧的真正标志不是知识,而是想象力。”要真正理解,机器智能必须超越数据、事实和故事的知识。想象力对于重建、发现和发明一个可观察属性和事件背后的宇宙模型是必要的。从人工智能系统的角度来看,想象力是通过创造性推理实现的:进行归纳、演绎或溯因推理,并产生新的结果,而不是由以前的经验和输入输出的相关性严格规定的。
知识表示和推理是人工智能的一个成熟领域,致力于世界信息的表示,因此计算机系统可以解决复杂的任务。知识和推理不一定是截然不同的,而是代表了从已知到推断(可以成为新的已知)的光谱。机器理解将通过构建知识的能力来实现,辅之以高级和更新的关联推理(例如,概率和似是而非的推理、溯因推理、类比推理、默认推理等)。).
建立在深厚知识基础上的神经符号人工智能
我对更具认知性、基于知识的人工智能方法的欣赏出现在 2010 年代中期,当时我正在英特尔研究深度学习硬件和软件解决方案。加里·马库斯的优秀论文人工智能的下一个十年:迈向强大人工智能的四个步骤提供了类似的观点。
在让人工智能更有效、更负责、更高效地支持人类的过程中,目标是让人工智能系统更强大,同时也推动它们进入下一个认知和理解水平。在操纵数据、识别模式和寻找最短暂的相关性方面已经取得了长足的进步。但是,仍然有必要考虑将使人工智能系统具备建模和理解它所操作的世界的能力的知识类型。
是时候就更具认知力的人工智能所需的知识种类展开对话了。本博客中讨论的知识表示的构造类型可以以各种形式实现,最终的系统将在神经网络能力和符号知识(无论以何种表示)实现人工智能下一阶段目标的方式上有所不同。后续的博客将更详细地介绍这个框架中引入的不同知识维度。随着我们对高级认知所需的知识结构类型建立了更深入的理解,我们可以继续构建这些深层知识,使机器能够理解世界。
参考文献
查尔斯·菲尔莫。《语言中的形式和意义》。CSLI 出版物,2002 年。https://web . Stanford . edu/group/csli publications/csli publications/site/1575862867 . shtml(2021 年 5 月 4 日访问)
schlkopf,b .等人,“走向因果表征学习”。https://arxiv.org/abs/2102.11107
本吉奥。约舒厄。“从系统 1 深度学习到系统 2 深度学习”。NIPS 2019,https://slides live . com/38922304/from-system-1-deep-learning-to-system-2-deep-learning
约翰·朗什伯里。“DARPA 对人工智能的看法”。DARPA,https://www.darpa.mil/attachments/AIFull.pdf(2021 年 3 月 23 日访问)
弗朗索瓦·乔莱。“人工智能的未来是怎样的?”,https://www.youtube.com/watch?v=GpWLZUbPhr0
歌手,加迪。《认知 AI 的崛起》。走向数据科学,2021 年 4 月。https://towards data science . com/the-rise-of-cognitive-ai-a 29 D2 b 724 CCC
禁止,肯尼斯。《OpenCyc 本体简介》。https://www.qrg.northwestern.edu/nextkb/IntroOpenCycOnt.pdf(2021 年 5 月 4 日访问)
艾伦·纽维尔。“物理符号系统”,认知科学,1980 年 4 月。https://online library . Wiley . com/doi/ABS/10.1207/s 15516709 cog 0402 _ 2
珀尔朱迪亚。《为什么之书》。纽约,基础图书,2018 年 5 月。http://bayes.cs.ucla.edu/WHY/
尤瓦尔·诺亚·哈拉里。《智人,人类简史》。哈维·塞克,2014 年。
德容,汤姆和弗格森-赫斯勒,莫妮卡。“知识的类型和质量”。教育心理学,1996 年。
帕夫勒斯,约翰。“常识更接近计算机”。Quantamagazine,2020 年 4 月。https://www . quanta magazine . org/common-sense-comes-to-computers-2020 04 30/
马库斯加里。“人工智能的下一个十年:迈向强大人工智能的四个步骤”。乐百氏人工智能,2020 年 2 月,https://arxiv.org/ftp/arxiv/papers/2002/2002.06177.pdf
本文建立在之前文章中的观点的基础上:
认知 AI 的兴起
以及之前在 LinkedIn 上发表的一系列文章:
知识时代来临:
第一部分:接下来,机器变得更聪明
第二部分:效率、可扩展性和认知:绘制前沿地图
第三部分:深度知识是高等机器智能的关键
认知计算研究:从深度学习到高等机器智能
Gadi Singer 是英特尔实验室副总裁,认知计算研究总监。
了解单因素方差分析
原文:https://towardsdatascience.com/understanding-one-way-anova-df44f02922fe?source=collection_archive---------23-----------------------
由卡洛斯·穆扎在 Unsplash 上拍摄的照片
理解差异驱动因素的真正有用的工具
今天,我们将在 Excel 中进行一些数据科学研究!是的,与一些人的想法相反,在 Excel 中进行合理的分析是可能的。
Sure statsmodels 也有一个 ANOVA(方差分析)库,但我第一次在 Excel 中看到它是在很多年前,当时就想“这是什么?”。
Excel 方差分析(来源:微软)
方差分析是比较因素和分解方差的非常有用的工具。它与聚类也有很多相似之处。让我们进入我们的例子。
财务数据的方差分析示例
这里有一些标签命名的数据,你可以复制并直接粘贴到 Excel 中。它是能源股每个季度的月度回报——假设我们有一个假设,即季节性是能源股回报的一个重要决定因素。
(需要以这种方式组织,以便正确运行 ANOVA 分析。)
Spring Summer Fall Winter
2.13% 4.40% -6.20% -5.35%
4.94% -2.90% -4.45% 4.93%
1.33% 2.74% -7.73% -1.12%
-2.50% -3.80% -7.09% -2.70%
7.67% -5.41% 10.32% 4.91%
-4.62% -5.35% -0.31% -8.38%
7.44% 4.95% 2.76% -2.09%
7.36% -1.38% 0.21% -0.31%
-1.66% 1.18% 5.21% 3.84%
我们将使用 Excel 的数据分析工具对其进行方差分析(如上图所示)。请耐心听我说一会儿——我马上会解释什么是方差分析。举个例子就简单多了。
输出如下所示:
方差分析输出(来源:作者)
汇总表非常简单。它只提供基本的汇总统计数据,例如每个变量的平均值和方差。有趣的是,我们可以看到,在分析期间,能源股的平均回报率仅在春季(我定义为 3 月、4 月、5 月)为正,而能源股在秋季表现出最大的波动性。
第二个表格是 ANOVA,是行动所在的地方。SS 代表平方和。一旦你花了一些时间在统计上,你就会意识到这一切都与方差有关——测量它,解释它,分解它。在统计领域,方差是对不确定性的估计;所以统计学家和数据科学家总是试图建模和解释它。
The equation for variance is:**Sample Variance = sum(Xi - mean(X))^2/(n-1)**
分子sum(Xi — mean(X))^2
就是我们所说的离差平方和或简称平方和(SS)。它只是每个观察值和平均值之间的平方差之和。例如,要计算能源股回报的总 SS(不按季节分时段),我们将:
- 计算能源指数的月平均回报。
- 取我们刚刚计算的平均值,从能源指数的每个月收益中减去它。
- 对步骤 2 中的每个值求平方。
- 将步骤 3 中的所有值相加。
那又怎样?
因为离差平方和(在本文中我称之为 SS)是方差方程中的分子,它与方差高度相关。保持观察次数不变,SS 越高,变量的方差越高。
现在让我们回到方差分析
ANOVA 为什么叫方差分析?这是因为方差分析是一个试图将方差分解为其来源的过程。
记得我们从一个假设开始——什么季节对能源股的表现有影响。让我们想想如何测试这一点。
**如果季节很重要,我们会期望数据看起来像什么?*一旦我们按季节将数据分类成桶,我们预计每个季节桶内的回报变化将非常小,而跨季节桶的变化将非常大。换句话说,我们期望跨季节时段的高 SS 和每个季节时段内的低 SS(无意中,一些聚类算法通过最大化跨类方差同时最小化类内方差来工作)。*这在右边的图中有直观的描述。
如果季节不重要,我们还能期待什么?这将与我们刚才描述的相反。我们应该期望看到跨季节时段的低 ss(低变化)和每个时段内的高 SS(高变化)。换句话说,排序前和排序后的变化看起来差不多(左图)。
不同状态下的分布情况(来源:作者)
这听起来越来越像假设测试了。基本上,方差分析就是这样的:
方差分析是检验不同组的均值是否显著不同的一种方法。
解释我们的方差分析结果
但我喜欢 ANOVA 的是它分解变异来源的方式(解释变异基本上就是解释方差)。
变异的来源(来源:作者)
这是我之前展示的同一个 ANOVA 输出——绿色数字是各组之间的差异的统计数据(通过将各组的平均值与总体平均值进行比较来衡量,即夏季的平均值或冬季的平均值是否与总体平均值有很大差异?)而黄色数字是一个群体内变化的统计数据(仅在冬季期间能量回报就有多少变化)?总变化只是所有能量观测的总 SS,与季节无关。
So ANOVA breaks out variation as follows:Total SS = Between Groups SS + Within Groups SSWhere SS is an estimate for variation
现在我们可以检查我们上面描述的情况:
- 如果组间变异高于组内变异,那么季节一定很重要。
- 如果组间差异相对于组内差异不是很大,那么季节就无关紧要了。
我们用来定量测试我刚才描述的内容的 F 统计量是从绿色和黄色的数字中计算出来的,如下所示:
F = (SS_between/df_between) / (SS_within/df_within)
= (0.00677/3) / (0.07816/32) = 0.924The intuition around why we divide SS by df (degrees of freedom) is that we need to do so in order to normalize it. The more observations there are, the higher the SS - so in order to compare variables with unequal numbers of observations we need to normalize SS by dividing it by df.
这是我们的测试统计。如果您需要复习假设检验,我在这里介绍了一些基础知识:
但是在高水平上,F-统计量越大,我们观察到由于随机机会而观察到的情况的可能性就越小。在这种情况下,我们的零假设是均值在统计上没有差异——或者组内的差异胜过组间的差异。
在我们的例子中,要达到 5%的显著水平,我们需要看到 F 统计值为 2.90 或更高。由于我们的 F 统计量仅为 0.924,我们无法拒绝零假设。思考我们的结论的一种更直观的方式是查看 0.44 的 p 值(这是从 F 统计得出的)——0.44 的 p 值意味着有 44%的机会观察到我们由于随机机会而做的事情。那是相当高的!难怪我们没能拒绝零假设。
理解变异的来源
现在我们已经解决了技术问题,让我们稍微关注一下直觉。划分SS_between/SS_total = 0.00677/0.08493 = 8%
。这意味着只有 8%的变化是由季节引起的。因此,季节不是能源股回报的主要驱动因素。
一个很好的问题是“SS_between 相对于 SS_total(不变)有多高,均值的差异才具有统计显著性?这在解释变异时意味着什么?
要达到 2.90 的 F 统计值,SS_between 需要达到 0.0182,几乎是原来的 3 倍。在这种情况下,季节可以解释总变异的 21.4%。因此,即使发现均值在统计上不同,每个时段内仍可能存在显著差异。
结论
让我们用一个方框图来结束吧,这是我最喜欢的一种方法,可以形象化不同类别之间的差异。
能量回报的箱线图(来源:作者)
我们可以看到,虽然春季回报率较高,但所有季节的总体分布或多或少都是相互叠加的——正如我们在未能拒绝零假设时发现的那样。
方差分析是一个很好的工具,可以帮助你理解观察到的差异的驱动因素。例如,如果您试图了解是什么导致了购物者花费的差异,您可以将购物者分类,并使用 ANOVA 测试分类的质量。这就像一个反向聚类分析。在聚类中,首先进行排序,然后试图找出这些聚类的含义。通过方差分析,你假设某个分类很重要,然后你测试自己是否正确。
这可能会有点乏味,但得出的结果肯定更容易理解(也更容易向你的老板解释)。干杯!
理解机器学习中的优化算法
原文:https://towardsdatascience.com/understanding-optimization-algorithms-in-machine-learning-edfdb4df766b?source=collection_archive---------5-----------------------
机器学习中两种重要优化技术背后的数学
目录:
- 简介
- 最大值和最小值
- 梯度下降
- 学习率
- 逻辑回归中的梯度下降
- 随机梯度下降
- 结论
- 参考文献
作者图片
- 简介
优化是我们迭代地训练模型的过程,其结果是最大和最小的函数评估。获得更好的结果是机器学习中最重要的现象之一。
我们为什么要优化我们的机器学习模型?我们通过改变每一步中的超参数来比较每一次迭代的结果,直到我们达到最佳结果。我们创建了一个错误率更低的精确模型。我们可以使用不同的方法来优化模型。在本文中,我们来讨论两个重要的优化算法:梯度下降和随机梯度下降算法;它们是如何在机器学习模型中使用的,以及它们背后的数学。
2。最大值和最小值
最大值是给定范围内函数的最大值,最小值是最小值。我们将它们表示如下:
最小值和最大值(图片由作者提供)
全局最大值和最小值:分别是函数在整个定义域上的最大值和最小值
局部最大值和最小值:分别是函数在给定范围内的最大值和最小值。
只能有一个全局最小值和最大值,但是可以有多个局部最小值和最大值。
3。梯度下降
梯度下降是一种优化算法,它能找出可微函数的局部极小值。它是最小化给定函数的最小化算法。
让我们看看梯度下降的几何直观:
Y=X 的斜率(图片作者提供)
让我们举一个抛物线的例子,Y=X
这里,最小值是原点(0,0)。这里的斜率是 Tanθ。因此,当 0
点向最小值移动的斜率(图片由作者提供)
图中的一个重要观察结果是斜率在最小值时从正变到负。当我们越接近最小值,斜率越小。
那么,梯度下降算法是如何工作的呢?
目的:计算函数 Y=X 的 X*-局部最小值。
- 随机选取一个初始点 X₀
- 在 X₀.计算 X₁ = X₀-r[df/dx]r 是学习率(我们将在学习率部分讨论 r )。让我们取 r=1。这里,df/dx 只不过是梯度。
- 在 X₁.计算 X₂ = X₁-r[df/dx]
- 计算所有的分数:X₁,X₂,X₃,…。xᵢxᵢ-₁
- 计算局部最小值的一般公式:Xᵢ = (Xᵢ-₁)-r[df/dx)在 Xᵢ-₁
- 当(Xᵢ — Xᵢ-₁)很小时,即当 Xᵢ-₁、Xᵢ收敛时,我们停止迭代并宣布 X* = Xᵢ
4。学习率
学习率是一个超参数或调谐参数,它决定了在函数中向最小值移动时每次迭代的步长。比如初始步 r = 0.1,下一步就可以取 r=0.01。同样,当我们进一步迭代时,它可以按指数规律减少。在深度学习中使用更有效。
如果我们保持 r 值不变,会发生什么:
振荡问题(图片由作者提供)
在上面的例子中,我们取 r=1。当我们计算 Xᵢ,Xᵢ+₁,Xᵢ+₂,….求局部最小值 X*,我们可以看到它在 X = -0.5 和 X = 0.5 之间振荡。
当我们保持 r 不变时,我们最终会遇到一个振荡问题。因此,我们必须在每次迭代中减少“r”值。随着迭代步长的增加,减小 r 的值。
**重要提示:**超参数决定偏差-方差权衡。当 r 值较低时,可能会使模型过拟合并导致高方差。当 r 值较高时,可能会使模型欠拟合并导致高偏差。我们可以用交叉验证技术找到正确的 r 值。用不同的学习率绘制图表,检查每个值的训练损失,选择损失最小的一个。
5。逻辑回归中的梯度下降
应用 sigmoid 函数后,逻辑回归中最佳平面的公式为:
最优平面—逻辑回归(图片由作者提供)
对逻辑回归应用梯度下降算法:
逻辑回归中的梯度下降(图片由作者提供)
我们将计算 W₀、W₁、w₂……、Wᵢ-₁、Wᵢ去找 W*。当(Wᵢ-₁-Wᵢ)很小时,即当 wᵢ-₁、wᵢ收敛时,我们宣布 W* = Wᵢ
梯度下降的缺点:
当 n(数据点的数量)很大时, k 次迭代计算最佳向量所花费的时间变得非常长。
时间复杂度:O(kn)
这个问题用随机梯度下降法解决,在下一节讨论。
5。随机梯度下降(SGD)
在 SGD 中,我们不使用所有的数据点,而是使用它的一个样本来计算函数的局部最小值。随机基本上就是概率的意思。所以我们从人群中随机选择点。
- 逻辑回归中的 SGD
逻辑回归中的随机梯度下降(图片由作者提供)
这里, m 是从总体中随机选取的数据样本, n
时间复杂度:O(km)。m 远小于 n。因此,与梯度下降法相比,计算时间更短。
6。结论
在本文中,我们讨论了优化算法,如梯度下降和随机梯度下降及其在逻辑回归中的应用。SGD 是机器学习中最重要的优化算法。它主要用于逻辑回归和线性回归。它在深度学习中被扩展为 Adam,Adagrad。
7。参考文献
[1]最大值和最小值:https://en.wikipedia.org/wiki/Maxima_and_minima
[2]梯度下降:https://en.wikipedia.org/wiki/Gradient_descent
了解病人住院时间:在 R
原文:https://towardsdatascience.com/understanding-patient-hospital-stays-a-classification-and-clustering-analysis-in-r-bba200c9323?source=collection_archive---------17-----------------------
机器学习方法在病人住院记录中的应用
合著者:索菲·考特曼斯-马特尔
由卡米洛·希门尼斯在 Unsplash 上拍摄的照片
有效管理患者住院时间是现代医疗保健系统中最具挑战性也是最重要的任务之一。据目前估计,美国每年管理患者入院和住院的费用超过 3775 亿美元[1],长期住院的风险使能力和患者资源有限的医院不堪重负。研究表明,更长时间的住院会增加医院获得性疾病和感染的可能性[2],而缩短患者的住院时间(LOS)可以更有效地分配医院的资源消耗,并减少患者承担的社会和经济负担。
机器学习和数据挖掘技术已经越来越多地用于从医疗保健数据中获取洞察力,这可以帮助公共卫生机构和医院管理人力和财务资源。因此,能够将高级分析技术应用于患者医院记录具有重要价值,例如使用患者数据来预测住院时间,或者更好地了解不同患者群体对医院资源的利用情况。
目标
重症监护医疗信息集市(MIMIC) 数据库是患者数据的来源之一,它提供了全面的患者住院记录流,这些记录在过去的描述性、预测性和假设驱动的研究中被证明是有用的。该数据库由麻省理工学院计算生理学实验室开发,包含位于马萨诸塞州波士顿的哈佛大学教学医院贝丝以色列女执事医疗中心约 60,000 名重症监护病房住院患者的匿名条目。
在此分析中,我们使用从 MIMIC 数据库中提取的数据构建了两个模型,以生成关于患者住院时间的预测性和探索性洞察。我们首先建立了一个机器学习分类模型,以预测患者住院时间的分类长度,给定患者入院时的可观察特征。然后,我们使用无监督学习技术,根据各种患者-护理人员互动的数量(如程序、输入和处方药物)对患者进行聚类,这可以量化患者在住院期间使用的人力或物力资源的数量。
通过结合这些模型,我们的目标是探索患者入院时的背景和状况的固有特征,以及与患者治疗过程和资源消耗相关的属性。这些指标可用于衡量和提高医疗服务提供的有效性,实现关键医疗资源的主动分配,并可能减少不必要的住院时间。
内容
- 数据描述
- 模型构建
- 按住院时间对患者进行分类
- 通过患者-看护者互动对患者进行聚类
- 局限性
- 最终想法
注意,模型是用 R 构建的,你可以在这里 参考完整代码 。
数据描述
MIMIC III 数据库包含 2001 年 6 月至 2012 年 10 月期间记录的 50,000 多名成人患者和 8,000 名新生儿患者的住院记录。
出于分析的目的,我们利用了来自医师 Alexander Scarlat 博士编制的 MIMIC III 数据库的属性的子集。该数据集包含关于患者人口统计、入院详情、患者状况的信息,以及关于各种患者-护理人员互动的平均每日次数的信息。此外,数据还包括患者住院的总时间以及患者是否在住院期间去世。
以下是属性的子集:
查看数据
即使从 MIMIC III 数据库提取的预先准备的数据集相对干净,我们仍然发现有必要执行进一步的预处理以促进分析。同一类别的类变量(如“GI”与“胃肠”)被重新分组到同一个类中,几个高基数分类变量被重新分类以减少类的数量。我们感兴趣的关键变量——患者住院时间(LOS) —范围为 0-294 天。为了对分类任务的目标进行分类,我们将 LOS 重新分组为三类,每类中的观察值数量相当:
- 短期停留:0-5 天
- 中等停留时间:6-10 天
- 长期停留:超过 10 天
通过观察患者的各种属性,我们在下文中看到,老年患者更经常经历中等至长期住院,而年轻患者的住院时间最短。虽然患者之间存在相当大的差异,但与所有其他种族相比,白人患者总体上似乎更老。
不同种族患者按年龄划分的住院时间(LOS)。作者提供的数字。
我们还发现,大多数患者都被医疗保险或私人保险覆盖,而且大多数患者是白人。最常见的入院诊断是分娩,这可能是急诊入院人数多但死亡率低的原因。
各种患者特征的分布。作者提供的数字。
按入院诊断划分的患者入院频率。作者提供的数字。
模型结构
分类模型
在数据准备之后,我们的第一项任务是预测患者的住院时间——短期(0-5 天)、中期(6-10 天)或长期(10 天以上)。
功能选择
在排除无效预测因素(即只有在患者入院后才能观察到的变量)后,除了年龄,我们只剩下分类变量。为了进行特征选择,我们进行了卡方独立性检验,这是一种假设检验,用于确定两个分类变量之间存在显著关系。然后,对于被确定为与 LOS 显著相关的特征,我们使用 Bonferroni 调整后的事后检验进行成对比较,并确定每个显著预测因子的哪些特定类别与 LOS 显著相关。这给我们留下了以下变量,它们在分类前被虚拟化:
在排除无效预测因素(即只有在患者入院后才能观察到的变量)后,除了年龄,我们只剩下分类变量。为了进行特征选择,我们进行了卡方独立性检验,这是一种假设检验,用于确定两个分类变量之间存在显著关系。然后,对于被确定为与 LOS 显著相关的特征,我们使用 Bonferroni 调整后的事后检验进行成对比较,并确定每个显著预测因子的哪些特定类别与 LOS 显著相关。这给我们留下了以下变量,它们在分类前被虚拟化:
为分类选择的要素和类的列表。
模特培训
为了预测患者的住院时间,我们决定探索以下 3 种不同的分类模型,并比较它们的相对性能:
- 多项式逻辑回归
- 随机森林
- 梯度推进机
简而言之,我们测试的模型通过计算患者记录属于每个 LOS 类别(短/中/长)的概率来生成 LOS 预测,并根据最高预测概率为患者分配一个 LOS 类别。
MLR 通过使用最大似然估计来定义似然函数,以计算在假设的概率分布下观察给定结果的条件概率。然后,它“搜索”实现该函数最大似然性的函数的最佳系数。另一方面,RF 和 GBM 是集成学习方法,它们构造多个决策树并输出对应于每个单独树的平均预测的 LOS 类。RF 和 GBM 之间的关键区别在于,RF 并行构建几个完整的树,从而产生个体偏差(误差)较低但树之间的预测方差可能较高的完全生长的树,而 GBM 顺序生长几个小树。由 GBM 产生的这些小树中的每一个都具有高偏差,但是从先前的树中学习并校正由先前的树产生的错误,因此减少了预测之间的总体方差。
K 均值聚类模型
为了完成分类任务,我们还决定探索无监督的方法,通过各种患者-护理人员互动的平均每日次数对患者进行聚类,作为对患者住院期间利用的人力或物力资源量的测量。为了简化流程,我们将 1349 例“急诊”住院患者作为优先考虑的对象,这些患者属于以下五种最常见的住院诊断:胃肠道出血、冠状动脉疾病、肺炎、败血症和充血性心力衰竭。
随后,我们选择了八个定量变量来对患者进行分组,这些变量以平均每日规模进行测量:
K-均值聚类模型的特征选择。
由于每个变量的范围不同,在应用 K-Means 聚类方法之前,我们首先使用最小-最大归一化来缩放变量。在将每个患者分配到一个聚类之后,将主成分分析应用于数据集以执行降维,从而通过前两个主成分可视化聚类。
根据住院时间长短对患者进行分类
从我们的分类模型中,我们可以看到梯度推进机器略微优于其他两个测试模型。由于 GBM 使用集成方法来连续生成分类树,每棵树都使用从以前的树中获得的知识来提高聚合性能,因此它通常比简单的逻辑回归或随机森林执行得更好。但是,我们在这里仍然看到,模型的整体性能较差;事实上,我们无法获得比随机猜测高得多的准确度。
用于预测患者住院时间(LOS)的模型的准确性。
这些结果表明,仅根据患者特征、诊断和入院情况,很难预测住院时间的长短。这并不奇怪,因为住院时间的长短可能是由患者的许多外源性因素决定的,如医生的可用性、专业设备和管理患者病例的有效性,或者对初始疾病的治疗是否会导致发现需要治疗的其他疾病。
我们还生成了混淆矩阵来进一步分解我们的结果,并检查模型的精确度和召回率。
作为快速复习:回忆是分类器完整性的度量;模型在该类别的所有真实现有观察值中正确识别短期、中期或长期停留的能力,同时 Precision 计算每个服务水平类别中正确识别的观察值数量与预测为短期、中期或长期停留的观察值总数的比率。
MLR、RF 和 GBM 模型的混淆矩阵比较。
混淆矩阵显示,所有模型在识别短期停留方面表现最佳。然而,这可能是由于模型倾向于压倒性地预测任何其他类别的短期停留,因为模型不太可能在中期和长期停留发生时识别它们。在这种模式下,医院很可能会低估患者的住院时间,这可能会导致床位、工作人员和资源准备不足,无法满足实际的能力需求。考虑到医疗资源分配中误导信息的高后果风险,我们可以推断,医院没有足够的信息来仅根据患者的入院特征做出任何与 LOS 相关的决定。
通过患者-看护者互动对患者进行聚类
接下来,让我们看看聚类模型的结果。对于三个聚类,我们发现总的方差和(计算为聚类之间相对于总方差的方差)为 64.5%,代表了可以由三个聚类解释的患者的总方差。前两个主成分的聚类图显示,聚类 3 代表了绝大多数患者,他们经历了相对较低的患者-护理者交互的平均每日次数,并且具有相对较低的变化程度。被分配到组 2 的患者在患者-护理者相互作用中表现出更高的变化,而组 1 代表在患者-护理者相互作用中具有最高总体数量和变化的患者。
前两个主成分绘制的患者-护理者相互作用的 K 均值聚类结果。作者提供的数字。
现在,让我们通过查看每个聚类中患者特征的相对频率来细分每个聚类,在这里,我们看到聚类 1 中的患者最有可能被诊断为败血症,住院时间最短,死亡频率最高。这一观察结果是合理的,因为脓毒症被归类为一种医学急症,它可以迅速发展为脓毒性休克,引发组织损伤、器官衰竭,并且常常是致命的[3]。虽然我们不能假设因果关系,但有可能该集群中患者-护理者相互作用的高度变化是由高致死率条件的优势驱动的,即患者要么在治疗前死亡,要么在治疗中死亡。
通过患者-看护者互动聚集的患者特征的相对频率。作者提供的数字。
我们发现集群 2 和集群 3 中的大多数患者的患者-护理人员互动次数更少,变化更小,住院时间更长。与聚类 1 相比,可能的情况是,相互作用的数量在入院后最初可能很高,但一旦患者稳定下来,最终会趋于平稳。这些组中的患者也不太可能死亡,更有可能被诊断出患有胃肠出血、冠状动脉疾病和充血性心力衰竭等疾病。这些情况有不同的严重程度,但不太可能立即危及生命。
总的来说,我们能够确定一些与患者-护理者互动次数相关的关键特征,这些特征主要涉及患者的状况,而不是他们的人口统计学特征。聚类的分布表明,很少有患者可能平均每天需要更多的资源,但是大多数患者利用了类似数量的资源。然而,聚类中的重叠仍然表明,患者-护理人员的相互作用可能会受到本分析范围之外的因素的影响,如患者病史和病情严重程度,并且在个案基础上有很大差异。
限制
模型解释和患者成本量化
将预测分析应用于医疗保健环境可能非常具有挑战性,因为患者结果的建模必须考虑模型的可推广性以及治疗成本和结果的显著差异,即使在相似的患者群体中也是如此。患者入院时的病情需要不同的治疗程序,并进入不同的单位,具有不同的能力和资源。由于目前的数据也是在 11 年期间收集的,医院项目、单位和部门的重组也可能随着时间的推移而发生。因此,为了量化患者 LOS 的成本,按照诊断、入院地点以及时间段对患者进行分类可能是有用的。
虽然我们试图通过患者-护理人员的互动对患者进行分组,以衡量患者的资源消耗,但同样重要的是要记住,像获取患者生命体征这样的互动比进行外科手术的成本低得多,因此很难仅根据这些结果来量化每个患者组的成本。
样本偏差
重要的是要认识到,用于分析的数据只包括一家医院的入院人数。这些患者也主要是白人,由私人保险或医疗保险(65 岁及以上患者的联邦健康保险)覆盖,平均年龄为 59 岁。有趣的是,我们发现 70%的患者被归类为急诊室入院,超过 10%的入院患者最终死亡,相比之下,美国平均每 1,000 名急诊室入院患者中有 0.77-1.48 人死亡[4]。由于 MIMIC III 数据集的患者资料不是美国患者人口构成的代表性样本,因此需要注意不要将结果外推至更广泛的美国人群。
功能有效性
我们的分类模型的主要限制之一是缺乏全面和定量的措施。事实上,我们只能使用六个分类预测因子(入院类型、地点和诊断、宗教、婚姻状况、种族)、一个二元预测因子(性别)和一个连续预测因子(年龄)。纳入入院时记录的其他关键指标,如体重指数(身体质量指数)、心率、体温、神经反射,以及疼痛程度和既往医疗状况等一般指标,可能会提高分类模型的预测能力。
最终想法
这项分析的中心目标之一是使用机器学习模型来更好地了解患者住院和随后住院时间(LOS)的潜在模式。虽然模型的结果表明,仅根据入院特征预测患者的 LOS 可能是困难的,但我们能够通过患者-护理者的互动对患者进行聚类,以根据医院资源利用情况成功识别三组患者,并了解与此相关的特征、诊断和死亡率模式。
医疗保健分析在促进医疗保健资源管理、预后和诊断分析,甚至疾病和残疾的早期检测方面显示出巨大的潜力。然而,为了将预测模型用于此类任务,数据收集、算法调整和模型解释必须以最终促进它们所服务的个人、社区和人群的利益的方式进行。这些模型可能有很大的好处,但当人类的生命处于危险之中时,必须小心处理。
项目代码:
github:【https://github.com/duncan-wang/LOS-prediction
参考资料:
[1] Health Catalyst (2016),“以患者为中心的 los 减少计划改善了结果,节省了成本”。
[2] Hassan M .,David K. (2006),"住院时间和获得感染的概率,"国际医药和保健营销杂志,第 4 卷,第 4 期,第 324-338 页。
[3]美国卫生与疾病中心(CDC) (2020),什么是脓毒症?”。
[4] Shmerling,R. (2018),“人死在哪里”哈佛健康博客。
MIMIC III 数据库:
MIMIC-III,一个免费的重症监护数据库。Johnson AEW,Pollard TJ,Shen L,Lehman LH,Feng M,Ghassemi M,Moody B,Szolovits P,LA 和 Mark RG。科学数据(2016)。DOI: 10.1038/sdata.2016.35。可在:【http://www.nature.com/articles/sdata201635获得
如果您想分享任何想法,请随时在 LinkedIn 上联系我们。
https://www.linkedin.com/in/duncan-w/ https://www.linkedin.com/in/sophie-courtemanche-martel/?originalSubdomain=ca
了解 PCA
原文:https://towardsdatascience.com/understanding-pca-90f7b1961fa4?source=collection_archive---------14-----------------------
插图:寻找主成分。所有图片均由作者提供。
主成分分析的深入解释
用眼睛看数据的能力是机器学习中最不受重视的事情之一。在进行任何机器学习之前,可视化数据可以揭示许多模式。探索它们可以在以后获得巨大的回报,因为我们可以获得关于使用什么算法、忽略什么特性等的良好直觉。
然而,有一个大问题:人类无法看到大于三维的空间。因此,对于现实生活中的数据集,我们必须执行某些技巧,以受益于可视化可以提供的洞察力。
主成分分析(PCA)是实现这一目的的最基本和最有用的方法之一。主成分分析将数据线性转换到一个空间,突出每个新特征的重要性,从而使我们能够修剪那些没有揭示太多的特征。
首先,我们将对 PCA 有一个直观的了解,然后我们进行更详细的数学处理。
PCA 背后的主要思想
为了更好地理解 PCA 的作用,我们将看看它在一个简单数据集上的表现。
假设我们的数据存储在矩阵中
其中 n 代表特征, d 代表样本数。为了简单起见,我们假设 n = 2 ,这样我们就可以想象正在发生什么。然而,所有这些都适用于一般情况。
简单的数据集。
我们可以立即观察到的是,x₁的特征和 x₂的特征可能不是我们数据的最佳描述符。这种分布似乎在两个变量之间延伸,尽管形状表明数据可以从特定的角度简化。这些特征似乎是相互关联的:如果 x₁小,那么 x₂大。如果 x₁大,x₂小。这意味着变量包含冗余信息。当我们有数百个特性时,冗余是次优的。如果我们能够将数据重塑为变量不相关并根据重要性排序的形式,我们就能够丢弃那些不太有表现力的变量。**
我们可以用线性代数的语言来描述这个过程。为了使数据去相关,我们希望对角化X 的协方差矩阵。因为经验协方差矩阵
是对称的,频谱分解定理保证作为正交矩阵 U 使得
(注意,在不失一般性的情况下,我们可以假设对角线中的元素是递减的。)
所以,我们有
如果我们定义变换
Y 表示具有不相关特征的数据视图。这就是主成分分析的精髓。 Y 的每个特征都是 X 特征的线性组合。 Y 称为 X 的主成分向量,而其特征称为主成分。
应用到我们的简单数据集,这是结果。
简单玩具数据集的 PCA 变换。
主成分使方差最大化
除了不相关的性质 Y 之外,还有一点使其特征独一无二:每个主成分在投影到数据上时都使数据的方差最大化。
寻找一个方向,使投射到它上面的数据的方差最大化。
PCA 可以被认为是寻找投影数据的方差最大的方向的迭代过程。
一般来说,第 k 个主分量可以通过寻找与第一个 k-1 个主分量正交的单位向量,并使投影到其上的数据的方差最大化来获得。
主成分分析降维
既然我们已经了解了 PCA 是如何工作的,我们应该研究它在真实数据集上是如何工作的。除了消除特征中的冗余,它还可以用来修剪那些没有传达很多信息的特征。回想一下,协方差矩阵
是对角线,特征的方差按降序排列:
解释了方差对的比值定义
可以认为是数据中“所有方差”的百分比。因为方差在减小,所以最有意义的特征出现在最前面。这意味着如果累计解释方差
对于一些 k 来说足够大,比如说在 95% 左右,在 k 之后的主分量可以被丢弃,而没有显著的信息损失。
为了了解它在真实数据上的表现,我们将看看 PCA 在著名的 Iris 数据集上的表现!该数据集由来自三种不同种类鸢尾的四个特征(萼片长度、萼片宽度、花瓣长度、花瓣宽度)组成。这是数据集的外观。
虹膜数据集。
通过检查,我们可以看到一些特性的组合很好地分离了数据,一些则没有。他们的顺序绝对不意味着他们的重要性。通过计算协方差矩阵,我们还可以注意到它们似乎是相关的:
**[[ 0.68112222 -0.04215111 1.26582 0.51282889]
[-0.04215111 0.18871289 -0.32745867 -0.12082844]
[ 1.26582 -0.32745867 3.09550267 1.286972 ]
[ 0.51282889 -0.12082844 1.286972 0.57713289]]**
让我们应用 PCA 来看看它对我们的数据集做了什么!
虹膜数据集的 PCA 变换。
前两个主成分几乎完全描述了数据集,而第三个和第四个主成分可以省略而不会明显丢失信息。协方差矩阵看起来也更好。它本质上是对角的,所以特征彼此不相关。
**[[ 1.57502004e+02 -3.33667355e-15 2.52281147e-15 5.42949940e-16]
[-3.33667355e-15 9.03948536e+00 1.46458764e-15 1.37986097e-16]
[ 2.52281147e-15 1.46458764e-15 2.91330388e+00 1.97218052e-17]
[ 5.42949940e-16 1.37986097e-16 1.97218052e-17 8.87857213e-01]]**
PCA 不做的是
尽管 PCA 经常用于特征工程,但它的功能是有限的。例如,如果数据集被拉伸得很薄,并且它们之间的分隔边距很小(如下例所示),则 PCA 不会提供类之间差异较大的表示。
原因是正交变换给出主分量向量,并且正交变换保持距离。因此,这不会沿任何特征拉伸空间。这是优点,同时也是缺点。在二维空间中,正交变换只是旋转和反射的组合。
如果你喜欢把机器学习概念拆开,理解是什么让它们运转,我们有很多共同点。看看我的博客,我经常在那里发表这样的技术文章!
理解自动驾驶的感知和运动规划(2021)
原文:https://towardsdatascience.com/understanding-perception-and-motion-planning-for-autonomous-driving-2021-e9241e067db7?source=collection_archive---------21-----------------------
深入研究当前的 SOTA 方法,共同预测汽车周围的环境及其行为
自动驾驶是移动的未来。图片由 @ed259 提供。
解释广告最新趋势的三篇论文
尊敬的 CVPR 2021 会议自动驾驶研讨会(WAD),我想与您分享三种最先进的自动驾驶感知和运动规划方法。我选择了最近在当前基准中取得突出成绩的论文,其作者被选为 CVPR 2021 的主题演讲人。
为了更广泛地探索这个主题,这三篇论文涵盖了不同的方法: Wayve (英国初创公司)论文使用相机图像作为监督学习的输入,丰田高级发展研究所(TRI-AD) 使用非监督学习, Waabi (多伦多初创公司)使用激光雷达和高清地图作为输入的监督方法。
本文中介绍的论文的比较。图片由作者提供。
- "**:来自周围单目摄像机的鸟瞰图中的未来实例预测。",安东尼·胡、扎克·穆雷兹、尼基尔·莫汉、索菲娅·杜达斯、杰弗里·霍克、vijay·巴德里纳拉亚南、罗伯托·奇波拉和亚历克斯·肯德尔,2021。[1]
- 打包 :用于自监督单目深度估计的 3D 打包。(CVPR 2020 口述)、熊伟·吉齐利尼、拉雷斯·安布鲁斯、苏迪普·皮莱、艾伦·拉文托斯和阿德里安·盖登。[2]
- 感知、预测、规划 :通过可解释的语义表示进行安全运动规划。ECCV (2020 年)。萨达特、卡萨斯、、任、吴、普拉纳布·达万和乌尔塔松。[3]
为什么感知和动作规划在一起:
自主车辆(AVs)感知的目标是从多个传感器中提取语义表示,并将结果表示融合到 ego-car 的单个“鸟瞰图”(BEV)坐标框架中,用于下一个下游任务:运动规划。
从六个摄像机(左图)转换到一个 ego-car 鸟瞰图(右图)的示例。我们可以看到汽车用蓝色标记,它们的运动由模型预测,用线表示。图片来自 NVIDIA paper Lift,Splat,Shoot [4]。
在最近的论文中,语义预测和鸟瞰图(BEV)是联合计算的(感知)。然后,时间状态能够联合预测周围代理的行为和本车运动(运动规划)。
端到端才是王道
近年来,端到端多任务网络的表现优于顺序训练网络。目前,输入只是原始传感器测量值,输出是方向盘命令。为了避免“黑箱”效应,为了优化目的(每个块可能有其中间损失函数)和结果的可解释性(特别是当结果不好时),有必要创建中间块。因此,我们可以在中间层块之间访问可解释的中间表示,如语义图、深度图、周围代理的概率行为(见下图)。
学习使用端到端 DL 和 CV 驾驶。图片来自亚历克斯·肯德尔(Wayve) CVPR 主题演讲[5]
这篇文章深入探讨了 AD 当前分裂的两个主要部分:
- 第一部分:仅使用摄像机作为输入的模型: ▹监督// ▹无监督
- 第二部分:使用激光雷达(laser)和高清地图作为输入的模型 ▹监督*。***
第 1)节仅使用摄像机
仅限摄像头。图片来自 @jstepphoto 。
监督
我们将乘坐一辆最新型号(CVPR 2021)" T8 " FIERY"[1],由一家名为 Wayve (Alex Kendall CEO)的初创公司的研发人员制造。他们的目标是从单目相机中学习 3D 几何和时间推理的表示。
对于 AV 上只有单目摄像机的团队来说,第一个挑战是学习深度。这是创建鸟瞰图参考框架的重要步骤,在该参考框架中可以识别实例并规划运动。由于每个摄像机最初在其自己的参考坐标中输出其自己的推断,因此该任务更加困难。
该过程的一个重要步骤是从 2D 图像生成 3D 图像,因此我将首先解释将 2D 图像从相机装备“提升”到所有相机共享的世界的 3D 表示的最新方法。NVIDIA CVPR 2020 年发表的论文“ Lift,Splat,Shoot:通过隐式取消投影到 3D 来编码来自任意相机装备的图像”[4]中的这种方法也用于 FIERY。
- 使用“提升-拍打-拍摄”将 2D 编码为 3D
此处提供纸张和代码。
在 2D 图像上创建第三个维度。这张图片展示了“抬起、拍打、拍摄”纸张的“抬起”步骤[4]。
1。提升:将本地 2D 坐标系转换为所有摄像机共享的 3D 坐标系。它们为每个像素生成所有可能(离散化)深度的表示。深度概率充当自我注意权重。
该模型通过将来自 2D 图像的每个像素与离散深度 d 的列表相关联来人工创建大的点云。对于具有(r,g,b,a)值的每个像素 p,网络预测上下文向量c和**深度分布a*。上下文向量 c 然后乘以来自分布 d 的每个权重 a。作为矩阵的结果是 a 和 c 的外积。该操作使得能够对特定深度给予更多关注。如果深度分布 a 全为 0,但一个元素为 1,则该网络充当伪激光雷达。每个图像的点云张量馈入在图像网上预先训练的有效网骨干网。EfficientNet 模型将输出上述由要提升的特征 c 和一组离散深度概率 a 构成的外积。***
2。Splat :外部和内部相机参数用于将 3D 表示法 Splat 到鸟瞰视图平面上。
他们使用最初用于激光雷达点云中物体检测的点柱技术。Pointpillar 将点云转换为伪图像,以便能够应用 2D 卷积架构。
点云被离散化为 x-y 平面中的网格,这创建了一组柱子 p。云中的每个点被转换为 D 维(D=9)向量,其中我们添加( Xc,Yc,Zc )到柱子中所有点的算术平均值的距离和(Xp,Yp)从 x-y 坐标系中的柱子中心到原始点(x,y,z,反射率)的距离。从这个稀疏的支柱网格,他们创建了一个大小为(D,P,N)的密集张量,其中 P 是非空支柱的数量(可能用 0 填充),N 是每个支柱的点数(如果一个支柱中有太多的点,则可能进行采样)。这个稠密张量馈入一个点网网络以生成一个(C,P,N)张量,随后是一个 max 运算以创建一个(C,P)张量。最后,我们使用 P 将特征散射回原始的柱子位置,以创建大小为(C,H,W)的伪图像。
在“提升,拍打,射击”中,作者在 D 轴上使用总和池而不是最大池来创建 C x H x W 张量。他们将这个张量输入由 ResNet 块组成的第二个主干网络,将点云转换为鸟瞰图像。
3.拍摄:他们为 BEV 中的每个实例“拍摄”不同的轨迹,计算它们的代价和代价最小的轨迹。
对于轨迹规划,让我们看看“火热的”而不是 NVIDIA 论文的拍摄部分。
2。用于运动规划的 FIERY:
代码可用此处。
FIERY 的整体架构分六步走。图片来自原纸[1]。
学习时间表征:
让我们考虑我们已经获得了连续帧中的 BEV 特征 X=(x_1,..,x_t) 从上面呈现的**Lift-Splat-Shoot*的提升步骤。*作者用空间变换模块 s 将 x 中所有这些过去的特征 x_i 扭曲到当前参考系 t,例如 x_i^t =S(x_i,a_ a_..a_i),使用a_i 时的平移/旋转矩阵 I
然后,这些特征被串联起来 (x_1t,…,x_tt) 并馈入 3D 卷积网络,以创建时空状态 s_t 。
*他们用这个状态 s_t 来参数化两个概率分布:现在的 P 和未来的分布 F 。当前分布以当前状态 *s_t,为条件,未来分布以当前状态 s_t 以及观察到的未来标记 (y_{t+1},…,y_{t+H}) 为条件,其中 H 为未来预测范围。
FIERY 型号的输入(a)和标签(b-f)。图片来自论文[1]。
我们可以想象上图中不同的标签。标签包含实例的未来中心度(=在该位置找到实例中心的概率)(b)、偏移量(=指向用于创建分段图的实例中心的向量(c)) (d)以及该实例的流量(=位移矢量场)(e)。
最终的聚合实例分段图如(f)所示。
这两种概率分布是对角高斯分布。因为来自当前分布的任何样本都应该编码可能的未来状态,所以当前分布被推动以覆盖具有 KL 散度损失的观察到的未来。
未来分布 F 是卷积门控递归单元网络,其将当前状态 s_t 和来自 F 的样本(在训练期间)或来自 P 的样本(在推断期间)作为输入,并且递归地生成未来状态。
通过 top-k 交叉熵来评估语义分割(仅 top-k 是因为大多数像素属于背景而没有任何相关信息)。
指标:
他们用未来视频全景质量评估他们的模型,用于评估分割实例度量的一致性和准确性,以及用于评估模型预测多模态未来的能力的广义能量距离。
它们在语义分割任务中优于其他最先进的方法(包括 Lift-Splat ),并且在未来实例预测中也优于基线模型。
结论:
这一切都是为了摄像机系统的一种最先进的监控方法。要记住的关键是感知和计划是一起完成的,主要依赖于时间状态和多模态。
无人监督的
代码可用此处。
单幅 RGB 图像的深度估计。图片来自 TRI-AD 博客[7]
来自 TRI-AD 的 Adrien Gaidon 认为监督学习不会扩展、推广和持续。这就是为什么他在寻找一种高效的规模化监管方式…而不用贴标签!他们找到了方法:他们使用自我监督。
在没有任何监督标签的情况下,他的 TRI-AD 人工智能团队可以从单目图像中重建 3D 点云。
怎么可能呢?他们使用射影几何的先验知识通过他们的新模型 PackNet 产生期望的输出。他们取得了非常好的结果,他们的自我监督模型优于监督模型。
自我监督训练不需要任何深度数据。而是训练它合成深度作为中间体。
他们的方法解决了由于输入图像在通过传统的 conv 网(由于汇集)后分辨率损失而存在的瓶颈。因此,他们将卷积网络架构应用于深度估计任务。由于张量操作和 3D 卷积,他们的压缩模型具有保持目标图像分辨率的优势。
给定一张图片作为测试时间,他们的目标是学习:
- 将图像映射到每像素深度的函数 f_d ,
- 单目自我运动估计器 f_x 包含源图像到目标图像的旋转/平移。
我们将关注第一个学习目标:深度预测。
深度估计问题是一个训练过程中的图像重建问题,类似于传统的计算机视觉中的运动重建问题。
传统计算机视觉中的运动结构。图片来自洪堡州立大学。
PackNet 模型正在使用带有两个主要模块的单个摄像机学习这种 SfM。
图片来自原纸[2]。
- 打包块:用可逆的 Space2Depth 技术【6】对输入的 RGB 图像张量进行缩减,然后网络学习压缩,学习用 3D conv 层进行扩展。结果通过整形变平,并馈送到 2D 卷积层。
- 解包块学习解压缩和展开打包的卷积特征回到更高的分辨率。它再次使用 2D,然后三维层,然后通过深度 2 空间技术[6]重塑和扩展。
在训练期间,网络通过从源图像中采样像素来学习生成图像t*。*
损失
它们的深度映射损失分为两个部分:
深度映射的损失。图片由作者提供。
外观匹配损失 L_p :使用结构相似度项和 L1 损失项评估目标图像 I_t 和合成图像 t 之间的像素相似度
深度正则化损失 L_s :他们鼓励估计的深度图在梯度上用 L1 罚函数进行局部平滑。因为在对象边缘上存在深度不连续,为了避免丢失无纹理的低梯度区域,当图像梯度高时,该平滑被加权为较低。
我们在这里不涉及这一点,但它们的损失利用相机速度来解决单目视觉固有的比例模糊。
结果:
图像重建与传统流水线(b)和提出的方法(c)的比较。所提出的方法保留了细节。图片来自原纸[2]。
在著名的 KITTI 基准测试中,他们的模型优于 self、semi 和 fully supervised 方法。
2021 年更新:
*他们最近通过他们的新 2021 型号扩展到了 360 度摄像机配置:*来自多个摄像机的全环绕单深度,熊伟·圭齐利尼等人。
为了做到这一点,他们非常狡猾地利用时空信息。他们使用的六个摄像头重叠太少,无法在另一个摄像头(摄像头 B)的帧中重建一个摄像头(摄像头 A)的图像。为了解决这个问题,他们实际上使用来自摄像机 A 的过去帧的图像来投影到摄像机 b 的当前帧。
FSM 模型从 6 个相机装备配置(如左图所示)预测点云(右图)。图片来自原始纸张[2]
半监督 =自我监督+稀疏数据。
今年,TRI-AD 还提出了一个半监督推理网络:“用于统一单目深度预测和完成的稀疏辅助网络(SANs),熊伟·圭齐利尼等人,这些 SANs 可以根据推理时只有 RGB 图像还是稀疏点云来执行深度预测和完成。
第 2)节使用激光雷达和高清地图
自动驾驶汽车最初使用激光雷达、激光传感器和高清地图来预测和规划它们的运动。近年来,多任务深度学习的使用创造了利用激光雷达技术导航的端到端模型。
***为什么使用高清地图?*高清地图包含关于语义场景的信息(车道、位置停车标志等)。
《感知、预测、规划》一文中提出的整体架构。图片来自论文[3]。
我来呈上优步·ATG 在《ECCV 2020》上发表的一篇论文:“ 【感知、预测、规划】【3】。这篇论文是由作者之一拉奎尔·乌尔萨顿提交的,她今年资助了自己的广告初创公司,名为 Waadi 。
她的论文提出了一个端到端的模型,它联合感知、预测和规划汽车的运动。他们创建了一个新的中间表示来学习他们的目标函数:一个语义占用网格来评估运动规划过程中每个轨迹的成本。这个语义层也被用作中间的和可解释的结果。这种网格使得广告比传统方法更安全,因为它不依赖于阈值来检测对象,并且可以检测任何形状
他们的模型被分成三块。
- 感知块
端到端感知和循环占用模型。||是串联、+元素式求和以及用于缩减的增量双线性插值。图片来自论文[3]。
感知模型首先从激光雷达测量和高清地图中独立提取特征。为此,他们将激光雷达的 10 次连续扫描体素化为 T=10 帧,并将其转换为 BEV(鸟瞰图)中的当前汽车帧。这将创建一个 3D 离散格网,每个像元都有一个二进制值:被占用或为空。
它们在 Z 轴上连接时间轴以获得(HxWxZT)张量。第三轴上的级联允许以后使用 2D 卷积骨干网。
地图的信息存储在 M 通道张量中。每个通道都包含不同的地图元素(道路、车道、停车标志等)。那么最后的输入张量就是 HxWx(ZT+M) 。实际上,ZT+M=17 个二进制通道。
然后,输入张量被送入由两个流组成的主干网络。一个流分别用于激光雷达和地图要素。这些流仅在使用的要素数量上有所不同(激光雷达流的要素越多)。输出被连接并馈入卷积层的最后一个块,以输出 256 维特征。
2。预测块
用于预测的语义类被组织成分层的组。每组都有不同的计划成本(停放的车辆没有移动的车辆重要)。这些组中的每一组都被表示为空间和时间上的分类随机变量的集合(对于 x,y 网格为 0.4m/像素,时间为 0.5s(因此 10 次扫描产生 5s 窗口)。简而言之,预测的目标是回答这个问题:谁(哪个类的哪个实例)将移动到哪里?
他们再次使用 2D 卷积块,主要是两个具有不同膨胀率的平行流。一个具有细粒度特征的流针对最近未来的预测。另一个流使用具有膨胀卷积的更粗糙的特征用于长期预测。使用先前的输出和连接的要素以循环方式更新输出。
3。运动规划模块
他们从自我车的各种轨迹中取样,并选择一个最小化学习成本函数的轨迹。该成本函数是主要考虑语义占用预测的成本函数: fo 和与舒适安全和交通规则相关的 fr 的总和。
fo 由两项组成:第一项惩罚与高概率区域相交的轨迹,第二项惩罚在不确定占有区域中的高速运动。
**
f 是成本函数,τ是轨迹,x 是输入数据,o 是占用预测,w 是可学习的参数。[3]
t 是时间步长,c 是占据网格的单元,τ是轨迹,λ是添加到周围物体以避免碰撞的余量参数,v 是速度。[3]
这些成本函数用于最终的多任务目标函数:
语义占用损失和规划损失之和。[3]
语义占据损失 L_s 是语义占据随机变量的地面分布 p 和预测分布 q 之间的交叉熵损失。
规划损失 L_M 是一种最大边际损失,鼓励人类驾驶轨迹(地面实况)比其他轨迹具有更小的成本。
结果
导致 5s 帧。图片来自报纸[3]
因此,在碰撞数量方面,将占用网格表示添加到模型优于最先进的方法。对整个管道进行端到端(而不是一个接一个)的训练提高了安全性(10%)和人类模仿性(5%)。
结论
我简要地探讨了广告的最新趋势,概述了最近发表的三篇最先进的论文。
2021 年感知和运动规划的趋势是:
- 端到端模型优于顺序模型,
- 相机 VS 激光雷达,
- 学习深度如果你只依靠相机,
- 多智能体与自我车的纠缠互动。
许多生产级自动驾驶公司发布了他们最近进展的详细研究论文。此外,我们应该利用他们有时将代码作为开源库发布的优势。
感谢您的阅读!
中上关注我 推特 !😃
参考资料:
[1] 火热:从环绕单目摄像机鸟瞰视角预测未来实例, Anthony Hu 等
[2]“打包:3 用于自监督单目深度估计的 3d 打包。(CVPR 2020),熊伟·吉齐利尼,拉雷斯·安布鲁斯,苏迪普·皮莱,艾伦·拉文托斯,阿德里安·盖登。https://arxiv.org/abs/1905.02693
[3] " 感知、预测和规划:通过可解释的语义表示进行安全运动规划"ECCV 2020。萨达特、卡萨斯、任、吴、普拉纳布·达万和 r .乌尔塔松、和
[4] " 举起、拍打、拍摄:通过隐式反投影将来自任意相机装备的图像编码为 3D, ECCV 2020,乔纳·菲利翁,桑亚·菲德勒,https://arxiv.org/abs/2008.05711**
[5]https://youtu.be/eOL_rCK59ZICVPR 2021 年自动驾驶研讨会
[6] " 利用高效的亚像素卷积神经网络实现单幅图像和视频的实时超分辨率",2016,施,何塞·卡瓦列罗,费伦茨·胡斯萨尔,约翰内斯·托茨,安德鲁·p·艾特肯,罗布·毕晓普,丹尼尔·吕克尔特,,,。
[7]https://medium . com/Toyota research/self-supervised-learning-in-depth-part-1-of-2-74825 baaaa 04
理解点流程模型—第 1 部分
原文:https://towardsdatascience.com/understanding-point-process-model-with-r-983553ca2a86?source=collection_archive---------30-----------------------
实践教程
用 R 对点过程模型的实际介绍
我最近一直在将空间数据作为一种学习练习,我对点模式分析特别感兴趣,这种分析通常用于流行病学,并在生态学中得到发展。虽然一些软件包已经有了这方面的固定功能(参见优秀的inlabru
或众所周知的spatstat
),但我不喜欢依赖它们。因为我想提高我对点模式模型的理解,并决定在我需要从头开始编写模型代码的地方使用rstan
。Stan,这是一种概率编程语言,使用哈密尔顿蒙特卡罗算法获得贝叶斯推断。
点模式和点过程
有许多资源介绍了点模式和点过程的概念,但是我将在这里快速解释这两个概念。
点模式
点模式代表一组点在时间、空间或更高维度中的分布。例如,森林中树木的位置可以被认为是一个点模式。犯罪地点是点模式的另一个例子。有三种通用模式:
- 随机:任意点在任意位置出现的概率相等,并且一个点的位置不受其他点位置的影响。例如,如果我把一袋大理石扔在地板上,图案很可能是随机的。
- 均匀:每个点都离它的邻居尽可能远。例如,我们可以想到一个人造森林,在那里树木被有规律地放置。
- 群集:许多点集中在一起,可能是由于协变量。我们可以以蜜蜂在田野中的位置为例,这些位置很可能聚集在花的周围。我们在这篇文章中模拟点模式代表了一个聚集的点模式。
点过程
空间点过程是点模式的描述。我们可以把它看作是生成点模式的模型。这些点来自随机过程,由局部强度λ(s)描述,局部强度测量空间中给定位置 s 处的点的预期密度。如果点独立且随机出现,则局部强度可由齐次泊松分布描述,并被称为泊松点过程。如果事件位置是独立的,但强度在空间上是变化的,则分布是由非均匀点过程产生的(即λ(s)变化)。后者也称为非齐次泊松过程。
我们可以将非均匀点过程的强度建模为协变量的函数。我们将这种类型模型描述如下:
λ(s)= exp(α+β÷X(u))
其中 X(u)是空间协变量,α和β是待估计的参数。Z(u)可以代表例如土壤的 pH 值或空气中的温度。
r 库
要复制本教程,您需要加载以下库:
library(spatstat)
library(sf)
library(sp)
library(maptools)
library(raster)
library(rstan)
library(tidyverse)
library(cowplot)
模拟点模式
首先,我需要模拟一个点模式。在我看来,模拟数据有无数的好处,尤其有助于理解生成过程(即数据是如何创建的)。从实用的角度来看,当生成数据时,我们可以完全控制参数,并且很容易看出我们在拟合模型时是否犯了错误。
这是一个函数,它根据我们的α、β值和研究区域的尺寸在内部生成一个点模式。注意dim[1]
和dim[2]
必须相等。
该函数返回 3 个对象的列表:
- 每个网格单元中的点数。在 stan 中拟合模型时,这将非常有用。
- 一个 ppp 对象,它是一个 spatstat 对象。这将有助于用 spatstat 拟合模型
- 协变量,它是一个数值网格
genDat_pp <- function(b1, b2, dim, plotdat = TRUE){
# Define the window of interest
win <- owin(c(0,dim[1]), c(0,dim[2]))
# set number of pixels to simulate an environmental covariate
spatstat.options(npixel=c(dim[1],dim[2]))
y0 <- seq(win$yrange[1], win$yrange[2],
length=spatstat.options()$npixel[2])
x0 <- seq(win$xrange[1], win$xrange[2],
length=spatstat.options()$npixel[1])
multiplier <- 1/dim[2]
# Simulate the environmental covariate
gridcov <- outer(x0,y0, function (x,y) multiplier*y + 0*x)# Set the coefficients
beta0 <- b1
beta1 <- b2
# Simulate the point pattern
pp <- rpoispp(im(exp(beta0 + beta1*gridcov), xcol=x0, yrow=y0))
# We count the number of points in each grid cell, plot it and make a vector out of it
qcounts <- quadratcount(pp, ny=dim[1], nx=dim[2])
dens <- density(pp)
Lambda <- as.vector(t(qcounts)) # We have to use t() as we need to # construct the vector with the column first
if(plotdat == TRUE){
par(mfrow=c(1,2), mar=c(2,2,1,1), mgp=c(1,0.5,0))
plot(im(gridcov), main = 'Covariate')
plot(dens, main = 'Intensity')
}
# Return a list with which I can play with
return(list(Lambda = Lambda, pp = pp, gridcov = gridcov))
}
我为要复制的结果设置了一个种子,并为模拟选择了参数:
set.seed(123)
b1 <- 2
b2 <- 3
dim <- c(20,20)
最终生成我的点模式。该函数生成了两个图,第一个是模拟的协变量,第二个是点模式的模拟强度。
pp <- genDat_pp(b1, b2, dim)
瞧啊。我们现在有可以利用的数据了!
用 spatstat 拟合点过程模型
作为一个基本的检查,我用包spatstat
中的函数ppm()
来拟合模型,以确保我能够恢复我之前指定的参数。spatstat
无疑是空间分析方面最成功的软件包,它具有大量用于拟合点过程模型和描述点模式的良好功能。查看网站!
cov <- im(pp$gridcov)
fit <- ppm(pp$pp ~ 1 + cov)
fit$coef## (Intercept) cov
## 2.187846 2.788411
模型的系数与我指定的系数是一致的。
在 stan 中拟合点过程模型
我在 stan 中为点流程模型编写的代码如下:
ppm_stan <- '
data{
int<lower = 1> n;
vector[n] x;
int<lower = 0> y[n];
}
parameters{
real beta0;
real beta1;
}
transformed parameters{
}
model{
//priors
target += normal_lpdf(beta0 | 0,5);
target += normal_lpdf(beta1 | 0,10);// likelihood
target += poisson_log_lpmf(y | beta0 + beta1 * x);
}
generated quantities{
vector[n] lambda_rep;
lambda_rep = exp(beta0 + beta1 * x);
}'
我们接下来拟合这个模型:
stan_data = list(n = length(pp$Lambda),
x = as.vector(t(pp$gridcov)), y = pp$Lambda)
fit_stan <- stan(model_code = ppm_stan, data = stan_data,
warmup = 500, iter = 2000, chains = 3)
检查系数是否与我指定的一致:
print(fit_stan, pars = c('beta0', 'beta1'))## Inference for Stan model: 200e1419a3bfac13c3097743f3003142.
## 3 chains, each with iter=2000; warmup=500; thin=1;
## post-warmup draws per chain=1500, total post-warmup draws=4500.
##
## mean se_mean sd 2.5% 25% 50% 75% 97.5% n_eff Rhat
## beta0 2.12 0 0.02 2.08 2.11 2.12 2.14 2.17 1003 1
## beta1 2.97 0 0.03 2.91 2.95 2.97 2.99 3.02 1029 1
##
## Samples were drawn using NUTS(diag_e) at Wed Dec 02 10:20:18 2020.
## For each parameter, n_eff is a crude measure of effective sample size,
## and Rhat is the potential scale reduction factor on split chains (at
## convergence, Rhat=1).
这也是连贯的。我们注意到 Stan return 的系数比ppm()
给我们的要高一点。
比较 spatstat 和 rstan 输出
我们能做的第一件事是检查预测是否正确。这可以帮助我们发展关于哪个软件性能更好的直觉,并帮助我们再次检查模型是否正确。
对ppm()
对象进行预测比对 stan 对象进行预测更简单,但仍然相对简单:
# spatstat predictions
pred <- predict(fit)# Stan predictions
lambda_rep <- as.data.frame(rstan::extract(fit_stan)['lambda_rep'])
mean_lambda_rep <- apply(lambda_rep, 2, 'mean')
然后我们创建一个网格,在其中我们将收集所有的预测
pointp <- pp$pp
pp_sp <- as.SpatialPoints.ppp(pointp)
pp_sf <- st_as_sf(pp_sp)grid <- st_make_grid(pp_sf, n = dim, what = 'polygons') %>% st_as_sf()
grid$pred_stan <- mean_lambda_rep
grid$pred_spatstat <- as.vector(t(pred$v))
grid$intensity <- pp$Lambda
绘制预测图
plot(grid)
不知何故,spatstat 不能预测某些细胞。
我们还可以绘制系数,这将有助于我们可视化与参数值相关的误差。
从图中我们可以看到 stan 比ppm()
函数执行得更好。我们可以通过计算均方根误差的总和来形式化这种直觉。
我们定义我们的助手函数rmse
:
rmse <- function(true, observed){sqrt((true - observed)^2)}
我们计算。首先注意,我们去掉了 NAs 值,因为 spatstat 在某些网格单元中没有预测。
grid_no_na <- grid %>% filter(!is.na(pred_spatstat))
sum(rmse(grid_no_na$intensity, grid_no_na$pred_stan))## [1] 1993.056sum(rmse(grid_no_na$intensity, grid_no_na$pred_spatstat))## [1] 2551.068
stan 拟合的点过程模型的和 rmse 不如 spatstat 拟合的和 RMSE,这使我们得出结论,在这种情况下 stan 表现更好。
最后
在本文中,我介绍了点模式和点过程模型的概念。在处理空间数据分析中经常遇到的点模式时,ppm 是一类非常强大的模型。正如我提到的,理解你正在拟合的模型是很重要的,虽然 Stan 可能不是 ppm 的最佳选择( INLA 更有效),从头开始编写你的模型会让你更好地理解你的模型在做什么,以及如何解释它的结果。
在第 2 部分中,我们将进一步研究点过程的情况,我们将了解如何模拟和拟合考克斯过程——它是一个具有随机强度函数的非齐次泊松过程。我们还将以对数高斯考克斯过程为例,其中考克斯过程的对数强度是高斯过程!
了解变压器中的位置编码
原文:https://towardsdatascience.com/understanding-positional-encoding-in-transformers-dc6bafc021ab?source=collection_archive---------18-----------------------
理解 ML
变压器模型位置编码方法的可视化。
什么是位置编码?
正如我在“注意力机制介绍”中解释的,注意力并不关心输入的位置。为了解决这个问题,我们必须引入一种叫做的位置编码。这种编码在最初的“注意力是你所需要的全部”论文中有所涉及,它被添加到每个输入中(不是连接而是添加)。
图 1:原变压器架构,来源 《注意力就是你需要的一切》,2017
这篇论文只考虑了固定的(不可训练的)位置编码,这就是我要解释的。现在编码是和模型一起训练的,但是这需要另一篇文章。为了计算位置编码的值,我们必须转到本文的第 3.5 节。作者使用 sin 和 cos 函数来计算每个输入向量的值。
如你所见,这些值取决于 d_ (输入尺寸)和 i i (位置向量的索引)。原始论文对 512 维向量进行操作,但为了简单起见,我将使用 d_ = 50 或 d_ = 20 。作者还附上了他们为什么选择这种函数的注释:
我们选择这个函数,因为我们假设它将允许模型容易地学习通过相对位置来参与,因为对于任何固定的偏移 k,PE_{pos+k}可以表示为 PE_ 的线性函数。
位置编码可视化
图 2:位置编码可视化,设计基于“注意力是你所需要的全部”,NeurIPS 2017 论文
注意
这只是原图中的一个屏幕,不幸的是我不能在介质上包含部分应用程序。如果你想玩,请直接进入https://erdem . pl/2021/05/understanding-positional-encoding-in-transformers # positional-encoding-visualization
价值观念
我们使用给定指数的公式计算每个指数的值。值得注意的是, cos 函数中的 2 i 值是一个偶数,因此为了计算第 0 个和第 1 个索引的值,我们将使用:
这就是为什么第 0 个和第 1 个索引的值只取决于位置的值,而不是同时取决于位置和 d_ dmodel 的值。这从第二个指数向前改变,因为被除数不再等于 0,所以整个除数大于 1。
维度依赖性
如果切换到第二步,那么可以比较一下 PE 值是如何根据 d_ 变化的。
图 3:不同维度 PE 值对比(d),来源: 位置编码可视化
前两个指标的周期不随 d_ 的变化而变化,但随 d_ 的减小,后续指标(第 2 个及以上)的周期变宽。这可能是显而易见的,但仍然很好地看到了差异。
功能周期
当我们绘制前 20 个位置向量的 PE 值时,我们得到如下结果:
图 4:前 20 位的位置编码值,使用 Tensorflow —位置编码 代码生成
这个图是从 Tensorflow 的教程之一生成的,你可以在谷歌的帮助下直接从他们的网站上运行它。如你所见,位置向量的较低维度具有非常短的波长(相同点之间的距离)。指数 i = 6 的函数的波长具有大约 19 (2 * 10^{12/25}).)的波长
我们知道周期是随着 i 的增加而增加的。当 i 到达 d_ 边时,你需要大量的 pos 向量来覆盖整个函数周期。
图 5:进一步索引的函数值,来源: 位置编码可视化
较高索引的前 20 个位置的值几乎是恒定的。你可以在图 4 中看到同样的事情,其中 30-50 列的颜色几乎没有变化。为了看到这种变化,我们必须绘制成千上万个位置的值:
图 6:使用 Tensorflow —位置编码 代码生成的进一步索引的位置编码周期
警告 这个图有一个内置的错觉,它实际上不是错觉,但因为它试图在 670px(高度)上打印 40k+值,所以它不能显示任何波长小于 1px 的值。这就是为什么第 24 列之前的任何内容在视觉上都是不正确的,即使使用了正确的值来生成该图。
结论
位置嵌入为转换器提供了关于输入向量位置的知识。它们被添加(而不是连接)到相应的输入向量。编码取决于三个值:
- 位置 —矢量的位置
- i —向量内的索引
- d_ —输入的维度
在周期函数(和)的帮助下交替计算值,这些函数的波长随着输入向量维数的增加而增加。当更远的索引需要很多位置来改变一个值(大周期)时,更靠近向量顶部的索引值(较低的索引)变化很快。
这只是进行位置编码的一种方式。当前的 SOTA 模型具有与模型一起训练的编码器,而不是使用预定义的函数。作者甚至在论文中提到了这个选项,但没有注意到结果的不同:
我们还尝试使用习得的位置嵌入,发现两个版本产生了几乎相同的结果(见表 3 行(E))。我们选择正弦版本,因为它可以允许模型外推至比训练期间遇到的序列长度更长的序列长度。
参考资料:
- 阿希什·瓦斯瓦尼等人,“注意力是你所需要的一切”,neur IPS 2017https://arxiv.org/abs/1706.03762
原载于https://erdem . pl。**
理解概率模型和公理
原文:https://towardsdatascience.com/understanding-probability-models-and-axioms-c0f498972b80?source=collection_archive---------8-----------------------
基本原则
为什么还要关心样本空间、事件和概率度量?
孙富在 Unsplash 上的照片
你必须把基础的东西做好,因为否则那些花哨的东西是不会起作用的。—兰迪·波许,美国教育家,计算机科学教授
概率论是这些基础之一,为了在机器学习或人工智能领域取得成功,人们应该认真学习。
作为数学中有关不确定性概念的一个分支,概率论为我们提供了一个一致推理以及做出预测和决策的框架。它在机器学习中起着核心作用,处理非确定性问题。
概率论和相互作用[图片由作者提供]
在下面的章节中,我们将处理概率论的基本概念,慢慢地在机器学习的主要支柱之一中建立我们的基础。
声明:我不是数学专家。请把这篇文章仅仅作为一个指南,希望能为概率论的基础提供一些基本的直觉。
概率空间
不严格地说,概率是关于不确定性的研究。
当我们谈论概率时,我们最有可能指的是不确定事件发生的几率。因此,概率可以被看作是一个事件发生的次数,或者是对一个事件的信任程度。例如,在一次投掷中硬币正面朝上的概率。
概率空间的构造提供了所需的数学结构,不仅可以正式讨论概率论,还可以描述实验的随机结果。
形式上,概率空间是由三元组(ω,F,ρ)定义的*:样本空间(ω)、事件空间和概率测度。*
样本空间
样本空间通常表示为ω,描述了所有可能结果的集合。
假设我们连续掷两次硬币。所有可能结果的集合将被定义如下:{HH, HT, TH, TT} | H=Heads; T=Tails.
两次投掷硬币的样本空间[图片由作者提供]
知道了样本空间是什么,再来说说里面的元素及其性质。
当我们掷一枚硬币时,结果不是正面就是反面,而不是两个都是。这是因为所有的元素都是相互排斥的,也就是说一次只能有一个结果。
此外,元素是*集体穷举。*如果我们再掷一次硬币,至少会有一种结果。无论是正面还是反面的结果,都涵盖了整个样本空间内的所有可能性。
元素需要有“正确的”粒度。这仅仅意味着,样本空间中的元素需要与我们的实验相关。回到我们的单次抛硬币的例子,让我们扩大我们的样本空间,包括关于天气的元素{HR, TR, HNR, TNR} | H=Heads; T=Tails; R=Raining; NR=Not raining.
虽然在抛硬币时记录这种信息可能很有趣,但它很可能与我们的实验结果无关。因此,新的样本空间没有合适的粒度。
事件空间
事件空间 F 描述了实验的一组潜在结果,因此是样本空间的子集。例如,一个 toin coss 的一组潜在结果将是{H}
——硬币正面朝上。
事件空间的欧拉图。b 是样本空间,A 是事件。[图片由作者提供]
概率测度
当我们投掷一枚硬币,想要表达硬币出现反面的概率时,我们需要某种函数将事件转换成一个实数值。
这就是概率测度(或概率分布)ρ的作用。它将事件 E ∈ F 映射到 0 和 1 之间的一个实数值。或者,换句话说,ρ可以被认为是将事件 E 转换为 0 到 1 范围内的实数值的函数,即事件空间 F 的元素。
在我们的例子中,表示事件通过一次抛硬币得到反面的概率是P(T) = 0.5
既然已经定义了概率空间,那么就可以谈谈某些规则或者说概率公理了。
概率公理
由安德雷·柯尔莫哥洛夫在 1933 年提出的三个概率公理仍然是概率论的核心和基础。
第一公理:
事件发生的概率是一个非负实数。
第一个公理,非负实数
上式告诉我们,事件空间 *F,*内事件 *E,*发生的概率 P 大于或等于零。概率也是实数值。
尽管方程看起来很复杂,但第一个公理应该是直观的。如果我们考虑扔硬币——硬币正面朝上的负概率没有任何意义,要么是正面,要么不是正面。
第二条公理:
第二个公理描述了琐碎事件,即至少一个基本事件至少出现一次。
第二个公理,琐碎事件
这将是我们的硬币,至少出现正面或反面。
第三条公理:
两个(或任何可数序列的)不相交集合的概率可以通过每个集合的单独概率的总和来计算。
第三个公理,有限可加性的一个例子
简单地说,如果 A 和 B 是不相交的,这意味着它们的交集等于一个空集,那么 A 和 B 的并集的概率等于各自概率的总和。
在我们的例子中,事件 A 是正面,事件 B 是反面。这两个事件是不相交的,因此正面或反面发生的概率是P(A) + P(B) = 0.5 + 0.5 = 1
这个等式可以进一步推广。
第三个公理,广义可加性
概率计算:示例
说完了理论背景,让我们通过看一些例子来获得更多的直觉。
离散/有限示例
想象一下连续滚动两个四面体(四边)骰子。样本空间将是覆盖所有可能结果的 4x4 网格。
两卷四面体骰子[图片由作者提供]
在我们的样本空间中,总共有 16 个(4x4)元素。每种结局发生的概率是 1/16。第一个骰子作为一个出现的概率是多少?
第一个骰子是一的概率
如上图所示,我们必须考虑四种可能的结果{(1,1), (1,2), (1,3), (1,4)}
,因此任何一种结果发生的概率是 1/4。
本例中的基本原理是离散统一定律或分布。不严格地说,这意味着样本空间由 n 个同样可能的元素(1/16)组成,事件空间包含多个 k 个元素(4)。
连续例子
让我们假设我们向一个单位正方形投掷飞镖,无论如何,我们总是击中。这可以用 0 ≤ x,y ≤ 1 来描述。
向单位正方形投掷飞镖[图片由作者提供]
以下事件的概率是多少?
或者换句话说,投飞镖的概率是多少,击中 x + y ≤ 1/2 定义的区域,基本就是上图所示的三角形。如果我们用 1/2 底高来计算面积,我们得到
接下来,击中特定点(0.5, 0.7)
的概率是多少?
为了计算该事件的概率,我们必须计算单点的面积,该面积为零。
结论
我们讲了概率空间,定义它的三元组*(样本空间,事件空间,概率测度)*,了解了三个概率公理及其含义。
尽管是基本概念,但重要的是获得直觉,为简单的原则打下坚实的基础。最终,我们的*【花式模型】*将建立在这个基础上。
感谢您的阅读!确保保持联系&在 Medium 、 Kaggle 上关注我,或者在 LinkedIn 上说声“嗨”
喜欢这篇文章吗?成为 中级会员 继续无限学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
https://medium.com/@marvinlanhenke/membership
参考资料/更多资料:
[1] [2]戴森罗斯,议员,费萨尔,A. A .,Ong,C. S. (2020)。机器学习的数学(第 152 页)。剑桥大学出版社。
视频讲座:麻省理工学院 2012 年春季课程概率导论
了解 Python 导入,init。py 和 pythonpath —一劳永逸
原文:https://towardsdatascience.com/understanding-python-imports-init-py-and-pythonpath-once-and-for-all-4c5249ab6355?source=collection_archive---------0-----------------------
PYTHON 基础
了解如何导入包和模块(以及两者之间的区别)
在本教程结束时,这是您可以轻松使用的目录结构(针对Medium_Imports_Tutorial
项目)——从一个子目录导入任何脚本到另一个子目录(蓝色箭头)。
注:如果你愿意合作,这里有Github回购。
学习 Python 导入的目录结构
在我们开始之前,让我们了解一下包和模块之间的区别,因为我们将在整篇文章中多次提到它们。
模块:一个 python 脚本。
包:模块的集合。
我们开始吧...
上图中的目录结构看起来有点复杂,我不会要求你一次创建它。
为了简单起见,让我们首先在项目目录中创建一个目录scripts
,并向其中添加两个模块——example1.py
和example2.py
。
这个想法是让在example1.py
中定义的任何函数/变量/类都可以在example2.py
中访问。该模块的内容如下:
***#example1.py***MY_EX1_STRING = 'Welcome to Example1 module!'def yolo(*x*: int):
print("You only LIve", *x*, "times.")
要在example2.py
内导入这些项目:
***#example2.py***import example1*# imported string*
print("The imported string is: ", example1.MY_EX1_STRING)*# imported function*
example1.yolo(10)
运行 example2.py 的输出
只是重复一下显而易见的内容,可以使用点符号来访问导入模块中的项目——例如,example1.yolo()
或example1.MY_EX1_STRING
。如果你觉得每次都写example1.XXX
似乎有点太长,我们可以使用别名as
并重写example2.py
如下。正如您正确猜测的那样,输出仍然保持不变。
***#example2.py***import example1 **as e1***# imported string*
print("The imported string is: ", **e1**.MY_EX1_STRING)*# imported function*
**e1**.yolo(10)
当我们写一个' import '语句时,到底发生了什么?
python 解释器试图寻找包含我们试图在sys.path
中导入的模块的目录*。这是一个目录列表,Python 会在查看完缓存模块和 Python 标准库模块后搜索这些目录。*
让我们看看此时我们的系统路径包含了什么(通过注释掉example2.py
中的前几行代码)。
**#example2.py***# import example1
# print("The imported string is: ", example1.MY_EX1_STRING)
# example1.yolo(10)*import sys
print(sys.path)
sys.path 的输出
正如你所看到的,由sys.path
返回的列表中的第一个元素指向Medium_Imports_Tutorial/scripts
目录,这是我们导入的模块即example1.py
所在的位置。请注意,这个目录神奇地出现在sys.path
中并不是巧合。
来自
sys.path
的输出将总是包含索引为 0 的当前目录!当前目录是正在运行的脚本所在的目录。
这就是当调用者和被调用者模块位于同一个目录中时,导入相当简单的原因。
如果我只想从导入的模块中导入某些项目,而不是全部,该怎么办?
在我们的例子中,我们只有一个字符串和一个在example1.py
模块中定义的函数。需要记住的一件重要事情是,每当执行一个 import 语句时,整个模块都将运行。为了证明这一点,让我们稍微修改一下example1.py
:
***#example1.py*****print("Thanks for importing Example1 module.")**MY_EX1_STRING = 'Welcome to Example1 module!'def yolo(*x*: int):
print("You only LIve", *x*, "times.")**yolo(10000)**
现在试着运行example2.py
。您将看到打印语句以及yolo(10000)
的输出也将被打印出来(除了之前的输出)。
注意:有一个解决方法,我们可以控制语句在导入时是否运行。例如,请参见下面的代码片段。
***#example1.py***print("Thanks for importing Example1 module.")MY_EX1_STRING = 'Welcome to Example1 module!'def yolo(*x*: int):
print("You only LIve", *x*, "times.")**if __name__ == '__main__':
yolo(10000)**
在 *if__name__ == '__main__'*
语句里面的代码 在导入 的时候不会运行,但是在外面定义的 *yolo()*
和 *MY_EX1_STRING*
可以通过导入使用。话虽如此,如果我们将 example1.py
作为独立模块运行,那么if
语句中的代码将被执行。
运行 example1.py 的输出
总之,既然我已经证明了导入一个模块可以运行它的所有内容(如果不使用if __name__ == “__main__"
),那么为什么只导入感兴趣的项目是有意义的就相当直观了。让我们看看如何在example2.py
中通过从example1.py
导入yolo
函数来实现这一点。这也有助于我们摆脱点符号,我们可以简单地使用yolo
功能。
**#example2.py****from example1 import yolo**
yolo(10)
类似地,我们可以通过from example1 import yolo, MY_EX1_STRING
从example1.py
导入两个对象。
注意:通常,存在包含进口陈述的代码,例如 *from example1 import **
。这实质上意味着导入所有内容,但是,这被认为是一种不好的做法,因为它会对代码的可读性产生负面影响。
PYTHONPATH 有什么用?
如果您注意到 Github 上项目的目录结构,通常会有一个utils
目录,其中包含一些用于预处理、数据清理等常见任务的实用程序脚本。这些脚本与主脚本分开保存,旨在重用。
让我们继续为我们的项目创建一个。utils
包将包含三个模块— length.py
、lower.py
和upper.py
,分别用于返回字符串输入的长度、小写和大写。
我们还将在项目根目录下创建example3_outer.py
模块。这是我们将导入util
包中的模块的地方。
三个模块的内容如下:
**#utils/length.py**def get_length(*name*: str):
return len(*name*)**#utils/lower.py**def to_lower(*name*: str):
return *name*.lower()**#utils/upper.py**def to_upper(*name*: str):
return *name*.upper()
现在,如果我们必须在example3_outer.py
中导入length.py
模块,这是我们通常的做法。
**#example3_outer.py**import utils.lengthres = utils.length.get_length("Hello")
print("The length of the string is: ",res)
需要注意的是,如果你要做的是import length
而不是import utils.length
,你会得到ModuleNotFoundError: No module named ‘length’
。这是因为sys.path
列表不包含../Medium_Imports_Tutorial/utils
目录(但),该目录是它找到length.py
模块所需要的。让我们看看如何将它添加到sys.path
列表中。
有两种方法可以做到这一点:
方法 1 :使用sys.path.append
**#example3_outer.py**import os
import sysfpath = os.path.join(os.path.dirname(__file__), 'utils')
**sys.path.append**(fpath)
print(sys.path)import length
txt = "Hello"
res_len = length.get_length(txt)
print("The length of the string is: ",res_len)
需要考虑的事情很少:
imports
的顺序很重要——只有使用sys.path.append
将路径附加到utils
目录后,才能执行import length
语句。简而言之,不要为了整洁而将imports os
、import sys
和import length
都放在脚本的顶部!os.path.dirname(__file__)
返回当前工作目录的绝对路径。我们使用os.path.join
将utils
目录添加到这个路径中。- 与往常一样,使用点符号(即
length.get_length()
)可以方便地访问导入模块中定义的函数。
方法二:使用PYTHONPATH
环境变量
我经常发现修改 pythonpath 变量比使用方法 1 添加目录更容易。
PYTHONPATH 是一个环境变量,您可以设置它来添加额外的目录,python 将在这些目录中查找模块和包。[ 来源
在我们修改它之前,让我们在终端中使用echo $PYTHONPATH
检查它的内容(以确保我们没有覆盖它):
看起来它现在是空的,但是如果不是空的,我们总是建议修改 pythonpath,以一种追加到它而不是覆盖它的方式。更具体地说,您必须将新目录添加到PYTHONPATH
,用冒号(:
)将其与现有内容隔开。
有了 pythonpath 变量集,我们不再需要在example3_outer.py
中追加到sys.path
(为了清晰起见,我在下面的代码片段中把它们注释掉了)。
**#example3_outer.py****#import os
#import sys****#fpath = os.path.join(os.path.dirname(__file__), 'utils')
#sys.path.append(fpath)
#print(sys.path)**import length
txt = "Hello"
res_len = length.get_length(txt)
print("The length of the string is: ",res_len)
注意:一旦关闭 python,列表将恢复到以前的默认值。如果您想将一个目录永久添加到 *PYTHONPATH*
,请将导出命令( export PYTHONPATH=$PYTHONPATH:$(pwd)/utils
) 添加到您的 *~/.bashrc*
。(参见本stack overflow讨论)。
最后,定义了两个方法之后,让我们选择一个(基于您的偏好/用例)来导入剩余的两个模块—example3_outer.py
中的upper.py
和lower.py
。
(注:我用方法 1 只是为了好玩。)
**#example3_outer.py**import os
import sysfpath = os.path.join(os.path.dirname(__file__), 'utils')
sys.path.append(fpath)import length
**import upper
import lower**txt = "Hello"res_len = length.get_length(txt)
print("The length of the string is: ",res_len)**res_up = upper.to_upper(txt)
print("Uppercase txt: ", res_up)****res_low = lower.to_lower(txt)
print("Uppercase txt: ", res_low)**
超级!这看起来真棒。然而,如果我们可以只做import utils
而不是单独导入其中的所有模块,那不是很好吗?毕竟,我们的用例表明我们确实需要所有这三个功能。那么我们该怎么做呢?
我们什么时候需要 init。py?
首先,让我们尝试在example3_outer.py
中导入utils
目录(在注释掉所有现有代码之后):
**#example3_outer.py**import utils
运行这个脚本不会导致任何错误,这是理所当然的——解释器会查看sys.path
内部,并在索引 0 处找到当前目录../Medium_Imports_Tutorial
。这就是找到utils
目录所需的全部内容。
现在让我们尝试从utils
访问length.py
模块:
**#****example3_outer.py**import utilstxt = "Hello"
res = utils.length.get_length(txt)
当您尝试运行这个脚本时,您会看到一个AttributeError: module ‘utils’ has no attribute ‘length’
。通俗地说,这意味着我们将无法访问utils
中的任何 python 脚本,因为解释器还不知道这是一个包!
我们可以通过在utils
文件夹中引入__init__.py
文件将这个目录变成一个包。
在__init__.py
中,我们导入所有我们认为对我们的项目必要的模块。
***# utils/__init__.py*** *(incorrect way of importing)*from length import get_length
from lower import to_lower
from upper import to_upper
我们称之为example3_outer.py
import utilstxt = "Hello"
res_low = utils.to_lower(txt)
print(res_low)
等一下! 为什么运行 *example3_outer.py*
时会出现错误?
答:我们在上面的__init__.py
中导入模块的方式对你来说似乎是合理的——毕竟__init__.py
和length.py
(或lower.py
、upper.py
)在同一级别,所以没有理由from lower import to_lower
不工作。事实上,如果您单独运行这个init
文件,它将完美地执行(它不会给出任何输出,但仍然会成功执行)。
话虽如此,我们不能使用上述导入方式,因为即使length.py
和lower.py
与__init__.py
处于同一级别,这也不是调用init
的级别。实际上,我们从example3_outer.py
发出调用,因此sys.path
将只有example3_outer.py
的当前目录,即../Medium_Imports_Tutorial
来搜索中的任何导入。因此,当解释器在example3_outer.py
中遇到import utils
命令时,即使它移动到utils
目录中的__init__.py
,也不会自动更新sys.path
,解释器也无法知道在哪里可以找到名为length
的模块。我们必须以某种方式指向目录的位置。为此,我们可以在__init__.py
中使用相对或绝对导入(或如上所述设置PYTHONPATH
变量)。
相对导入(不推荐):指定相对于调用脚本路径的路径。
**# utils/__init__.py**from .lower import to_lower
from .upper import to_upper
from .length import get_length
我们使用点符号(.
或..
)来指定相对进口。lower 前面的单个点指的是调用导入时所在的目录。这可以看作是从./lower.py
导入to_lower()
。类似地,模块名前的双点意味着从当前级别向上移动两级。
绝对导入(更好的选择):指定从项目根目录(或 sys.path 可以访问的任何其他目录)导入的模块的绝对路径。
**# utils/__init__.py**from utils.lower import to_lower
from utils.upper import to_upper
from utils.length import get_length
现在,与相对进口相比,它包含了更多的信息,而且不容易被破解。此外,如上所述,sys.path
可以访问项目根目录,即../Medium_Imports_Tutorial
,从那里可以轻松搜索utils
目录。(为什么?因为它是项目根目录的直接子目录)。
当我们导入一个定义了 **__init__.py**
**的包时会发生什么?**这是一个初始化步骤,是我们导入包时执行的第一个文件。考虑到我们在这里做了所有必要的导入,调用脚本中的代码要干净得多。例如:
**#example3_outer.py****import utils**txt = "Hello"
res_len = **utils.get_length**(txt)
print(res_len)res_up = **utils.to_upper**(txt)
print(res_up)res_low = **utils.to_lower**(txt)
print(res_low)
厉害!现在我们已经将我们的utils
目录转换成了一个包。这个包的美妙之处在于,它可以被导入到任何地方,并且几乎可以立即使用。让我们看看如何在scripts
目录中使用这个包。让我们在scripts
中创建一个名为example3.py
的新文件。
**# scripts/example3.py**import os
import sysPROJECT_ROOT = os.path.abspath(os.path.join(
os.path.dirname(__file__),
os.pardir)
)
sys.path.append(PROJECT_ROOT) import utils
print(utils.get_length("Hello"))************** OUTPUT *********
5
需要考虑的事情很少:
- 在导入
utils
包之前,我们必须确保utils
的父目录,即项目根目录可以被 Python 解释器访问。假设它会默认发生是不明智的,主要是因为我们现在在项目根目录中的一个级别(我们从scripts/example3.py
运行脚本),sys.path
将在索引 0 处有../Medium/Imports_Tutorial/scripts
。 os.path.dirname(__file__)
将给出当前脚本的目录名,而os.pardir
将使用点符号给出父目录的路径,即..
。总而言之,os.path.abspath
将提供项目根的绝对路径。
额外好处:我们甚至可以将其他目录中的模块添加到我们的__init__.py
中。例如,让我们引入在scripts/example1.py
中定义的yolo()
。
**# utils/__init__.py**from utils.lower import to_lower
from utils.upper import to_upper
from utils.length import get_length**from scripts.example1 import yolo**
在example3.py
中调用该函数
**# scripts/example3.py**import os
import sysPROJECT_ROOT = os.path.abspath(os.path.join(
os.path.dirname(__file__),
os.pardir)
)
sys.path.append(PROJECT_ROOT)import utils
print(utils.get_length("Hello"))
**utils.yolo(2)**************** OUTPUT *********
5
**You only LIve 2 times.**
结论
老实说,导入错误在开始的时候真的让我很害怕,因为这是我从来不需要担心的一个方面。多年来,我已经学会了一个有用的技巧——对于你试图使用import XYZ
导入的任何包/模块,确保 Python 解释器可以访问它。如果没有,更新sys.path
或者更好地将相关目录附加到PYTHONPATH
变量,避免在脚本中处理它。
一如既往,如果有更简单的方法来做/解释本文中提到的一些事情,一定要让我知道。一般来说,避免不请自来的破坏性/垃圾/敌意评论!
直到下一次✨
我喜欢写循序渐进的初学者指南、操作指南、面试问题、ML/AI 中使用的解码术语等。如果你想完全访问我的所有文章(以及其他作家在媒体上的文章),那么你可以使用 我的链接这里 注册。
* https://varshitasher.medium.com/six-reasons-to-switch-to-this-podcast-app-today-3a396ada0a2b *
理解 PyTorch 激活函数:数学和算法(第一部分)
原文:https://towardsdatascience.com/understanding-pytorch-activation-functions-the-maths-and-algorithms-part-1-7d8ade494cee?source=collection_archive---------26-----------------------
PyTorch 中激活函数的数学定义、算法和实现的分步指南
你可以在这里找到第二部。
由比尔·麦基在 Unsplash 上拍摄的照片
介绍
在 ML 的世界中,激活函数帮助网络学习输入数据中的复杂模式(或嵌入)。与我们的大脑相比,激活功能类似于神经元的末端,在给定一组复杂输入的情况下,决定将什么信息包传播到后续神经元。
在这篇文章中,我们将从数学上形式化并实现 PyTorch 中一些更流行的激活函数。它将根据您正在查看的输出类型进行划分,即:
- (轻微)正 : ReLU 和漏 ReLU
- 在 0 和 1 之间 : Sigmoid,Softmax
- 介于-1 和 1 之间 : Tanh
1.(稍微)积极
如果您希望修改输入并只取其正值,那么整流线性单元(ReLU)或泄漏 ReLU 是合适的
a.整流线性单元
ReLU 数学定义
给定输入 x, ReLU 将取 0 和 x 之间的最大值。
图形表示
在 python 中实现 ReLU 函数的方法如下:
import numpy as nparr_before = np.array([-1, 1, 2])def relu(x):
x = np.maximum(0,x)
return xarr_after = relu(arr_before)arr_after
#array([0, 1, 2])
并且在 PyTorch 中,可以很容易地调用 ReLU 激活函数。
import torch.nnrelu = nn.ReLU()
input = torch.randn(2)
output = relu(input)
b.泄漏整流线性单元(ReLU)
泄漏 ReLU 数学定义
week ReLU 和 Leaky ReLU 略有区别。给定输入 *x,*如果值为正,Leaky ReLU 将取 0 和 x 之间的最大值,否则它将 x 乘以提供的负斜率。从图形上看,ReLU 有以下转化行为。
泄漏 ReLU 图形表示
在 python 中实现泄漏 ReLU 激活函数可以按如下方式完成:
import numpy as nparr_before = np.array([-1, 1, 2])# If x>0 returns x, else returns x*negative_slope
def leaky_relu(x, neg_slope=0.01):
x = np.where(x>0, x, x*neg_slope)
return xarr_after = leaky_relu(arr_before)arr_after
#array([-0.01, 1., 2.])
并且在 PyTorch 中,可以很容易地调用泄漏的 ReLU 激活函数。
import torch.nnneg_slope=0.01
leaky_relu = nn.LeakyReLU(neg_slope) #Pass in negative slope value
input = torch.randn(2)
output = leaky_relu(input)
2.介于 0 和 1 之间
如果您希望输出介于 0 和 1 之间的值(对于概率分类类型的问题非常有用),那么 Sigmoid 或 Softmax 激活函数都是合适的,具体取决于下面讨论的一些注意事项。
a.乙状结肠的
Sigmoid 数学定义
从图形上看,Sigmoid 具有以下转换行为,将输出限制为[0,1]。
Sigmoid 图形表示
在 python 中实现 Sigmoid 函数的方法如下:
import numpy as nparr_before = np.array([-1, 1, 2])def sigmoid(x):
x = 1 / (1 + np.exp(-x))
return xarr_after = sigmoid(arr_before)arr_after
#array([0.26894142, 0.73105858, 0.88079708])
在 PyTorch 中,您可以轻松地调用 Sigmoid 激活函数。
import torch.nnsigmoid = nn.Sigmoid()
input = torch.randn(2)
output = sigmoid(input)
b.Softmax
Softmax 类似于 sigmoid 激活函数,因为每个元素的输出位于 0 和 1 之间的范围内(即[0,1]).不同之处在于 softmax 对指数项进行了归一化,使得分量之和等于 1。因此,softmax 通常用于多类分类问题,其中已知类的总概率总和通常为 1。
Softmax 数学定义
在 python 中实现 Softmax 函数的方法如下:
import numpy as nparr_before = np.array([-1, 1, 2])def softmax(x):
numerator = np.exp(x)
denominator = np.sum(np.exp(x))
x = numerator / denominator
return xarr_after = softmax(arr_before)arr_after
#array([0.03511903, 0.25949646, 0.70538451]) #Sums up to 1
在 PyTorch 中,您可以轻松调用 Softmax 激活函数。
import torch.nnsoftmax = nn.Softmax(dim=1)
input = torch.randn(2, 3)
output = softmax(input)
3.介于-1 和 1 之间
如果您希望将值转换到-1 和 1 之间,那么 Tanh 可能是一个合适的激活函数。
a.双曲正切
Tanh 数学定义
从图形上看,Tanh 具有以下激活行为,将输出限制在[-1,1]之间。
Tanh 图形表示
在 python 中实现 Tanh 函数的方法如下:
import numpy as nparr_before = np.array([-1, 1, 2])def tanh(x):
x = (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))
return xarr_after = tanh(arr_before)arr_after
#array([-0.76159416, 0.76159416, 0.96402758])
在 PyTorch 中,您可以轻松地调用 Tanh 激活函数。
import torch.nntanh = nn.Tanh()
input = torch.randn(2)
output = tanh(input)
结论
这篇文章介绍了 PyTorch 中一些更常见的激活函数的数学定义、图形表示和实际实现。下一篇文章将讨论一些更高级的激活功能,它们可能对不同的用例有用。敬请期待!
做订阅我的邮件简讯:【https://tinyurl.com/2npw2fnz】在这里我定期用通俗易懂的语言和漂亮的可视化总结 AI 研究论文。
理解 PyTorch 激活函数:数学和算法(第二部分)
原文:https://towardsdatascience.com/understanding-pytorch-activation-functions-the-maths-and-algorithms-part-2-1f8bce111a7b?source=collection_archive---------38-----------------------
PyTorch 中激活函数的数学定义、算法和实现的分步指南
第 1 部分可以在这里找到。
由比尔·麦基在 Unsplash 上拍摄的照片
介绍
在 ML 的世界中,激活函数帮助网络学习输入数据中复杂的非线性模式(或嵌入)。
在这篇文章中,我们将从数学上形式化并实现 PyTorch 中一些更健壮但不太流行的激活函数。要了解更多关于更流行的激活功能,请在第 1 部分中找到它们。它将根据您正在查看的输出类型进行划分,即:
- (轻微)阳性 : ReLU6,随机泄漏
- 在 0 和 1 之间 : Softmin
- 小于 0 : LogSoftmax,LogSigmoid
1.(稍微)积极
之前的帖子强调了 ReLU 和 LeakyReLU 的用法。
如果您希望修改输入,并且只取它们的正值(在一定程度上取它们的负值),那么 ReLU6 和随机化泄漏(RRELU)是合适的。
a.整流线性单元 6 (ReLU6)
ReLU6 数学定义
给定输入 x, ReLU6 将取 0 和 x 之间的最大值,然后取初始输出和 6 之间的最小值。为什么将最大正值设置为 6?根据论文,在低精度足够的情况下,6 的大小增加了计算的鲁棒性和稳定性。从图形上看,ReLU6 具有以下转变行为:
在 python 中实现 ReLU6 函数的方法如下:
import numpy as nparr_before = np.array([-1, 1, 7])def relu6(x):
x = np.minimum(np.maximum(0,x), 6)
return xarr_after = relu6(arr_before)arr_after
#array([0, 1, 6])
并且在 PyTorch 中,可以很容易地调用 ReLU6 激活函数。
import torch.nnrelu6 = nn.ReLU6()
input = torch.randn(2)
output = relu6(input)
b.随机化泄漏率
RReLU 数学定义
在 RRELU 中,当输入值为正值时,转换将输出给定的正值。但是,如果是负的,那么输入将乘以 a ,其中 a 是从均匀分布 N (下,上)中随机抽取的。
在 python 中实现 RReLU 激活函数的方法如下:
import numpy as nparr_before = np.array([-1, 1, 2])# If x>0 returns x, else returns x*sampled_a
def rrelu(x, lower=0.125, upper=0.333):
sampled_a = np.random.uniform(lower, upper)
x = np.where(x>0, x, x*sampled_a)
return xarr_after = rrelu(arr_before)arr_after
#array([-0.225, 1., 2.])
在 PyTorch 中,您可以轻松地调用 RReLU 激活函数。
import torch.nnneg_slope=0.01
rrelu = nn.RReLU(0.125, 0.333) #Pass in the lower and upper values
input = torch.randn(2)
output = rrelu(input)
2.介于 0 和 1 之间
如果您希望输出介于 0 和 1 之间的值(对于问题的概率分类类型很有用),那么 Softmin 激活函数将是合适的,这取决于下面讨论的一些注意事项。
a.Softmin
Softmin 类似于 softmax 激活函数,因为每个元素的输出位于 0 和 1 之间的范围内(即[0,1]).区别在于 softmin 将输入元素与负的 1 相乘,如下所示:
软最小数学定义
与 Softmax 相比,您何时使用 Softmin?这是您希望检测到更多负值的时候。例如,如果您有一个在一组图像中识别非狗的分类任务,模型在识别狗方面的置信度越低,您的分类性能就越好。
在 python 中实现 Softmin 函数的方法如下:
import numpy as nparr_before = np.array([-1, 1, 2])def softmin(x):
numerator = np.exp(-x)
denominator = np.sum(np.exp(-x))
x = numerator / denominator
return xarr_after = softmin(arr_before)arr_after
#array([0.84379473, 0.1141952 , 0.04201007]) #Sums up to 1
在 PyTorch 中,您可以轻松调用 Softmin 激活函数。
import torch.nnsoftmin = nn.Softmin()
input = torch.randn(2, 3)
output = softmin(input)
3.小于 0
如果您希望将值转换为小于 0 的值,那么 LogSoftmax 和 LogSigmoid 可能是合适的激活函数。
a.LogSoftmax
LogSoftmax 数学定义
与 Softmax 类似,LogSoftmax 将日志操作应用于 Softmax 函数。除了数值稳定性之外,还有一个重要的优点:与 Softmax 相比,这个激活函数严重惩罚了错误的分类预测。
在 python 中实现 LogSoftmax 函数的方法如下:
import numpy as nparr_before = np.array([-1, 1, 2])def logsoftmax(x):
numerator = np.exp(x)
denominator = np.sum(np.exp(x))
x = numerator / denominator log_x = np.log(x)
return log_xarr_after = logsoftmax(arr_before)arr_after
#array([-3.34901222, -1.34901222, -0.34901222])
并且在 PyTorch 中,可以很容易地调用 LogSoftmax 激活函数。
import torch.nnlogsoftmax = nn.LogSoftmax()
input = torch.randn(2)
output = logsoftmax(input)
b.对数乙状结肠
对数数学定义
类似于 LogSoftmax 对 Softmax,LogSigmoid 将 log 运算符应用于 Sigmoid 函数。从图形上看,LogSigmoid 具有以下转换行为,将输出限制为(-inf,0)。
对数图形表示
在 python 中实现 LogSigmoid 函数的方法如下:
import numpy as nparr_before = np.array([-1, 1, 2])def logsigmoid(x):
x = 1 / (1 + np.exp(-x))
return np.log(x)arr_after = logsigmoid(arr_before)arr_after
#array([-1.31326169, -0.31326169, -0.12692801])
并且在 PyTorch 中,可以很容易地调用 LogSigmoid 激活函数。
import torch.nnlogsigmoid = nn.LogSigmoid()
input = torch.randn(2)
output = logsigmoid(input)
结论
这篇文章继续讨论 PyTorch 中一些更健壮但不常用的激活函数的数学定义、图形表示和实际实现。如果你受益匪浅,请分享并为这篇文章鼓掌!
做订阅我的邮件简讯:【https://tinyurl.com/2npw2fnz】在这里我定期用通俗易懂的英语和漂亮的可视化总结 AI 研究论文。
理解 PyTorch 损失函数:数学和算法(上)
原文:https://towardsdatascience.com/understanding-pytorch-loss-functions-the-maths-and-algorithms-part-1-6e439b27117e?source=collection_archive---------33-----------------------
PyTorch 中损失函数的数学定义、算法和实现的分步指南
你可以在这里找到第二部。
由杰斯温·托马斯在 Unsplash 上拍摄的照片
就像人类一样,机器从过去的错误中学习。这些“错误”被正式称为损失,并由函数(即。损失函数)。如果机器学习算法的预测离地面真相更远,那么损失函数就会显得很大,反之亦然。因此,任何学习过程的目标都将是最小化这种损失,使得最终的输出将紧密匹配真实世界的标签。这篇文章将介绍一些更流行的损失函数的数学定义和算法,以及它们在 PyTorch 中的实现。
介绍
选择最佳损失函数是一项设计决策,取决于我们的计算约束(如速度和空间)、数据集中是否存在显著异常值以及我们拥有的输入/输出类型。
尽管如此,在选择不同的损失函数时,我们需要问的第一个问题是我们面前的数据类型。一般来说,损失函数可以根据我们正在处理的特定任务进行灵活的分组:或者是一个回归或者是分类问题。回归处理连续的数据集,例如在给定一个国家的人口增长率、城市化、历史 GDP 趋势等的情况下预测其人均 GDP。另一方面,分类问题涉及有限的离散类别,例如预测卫星图像是否正在经历任何降雨事件。
回归损失函数
平均绝对误差(L1 损耗)
平均绝对误差损失函数
平均绝对误差(MAE)是真实值(y_i)与其对应的预测值(y_hat_i)之间的绝对差值除以此类对的总数。
算法:MAE
import numpy as npy_pred = np.array([0.000, 0.100, 0.200])
y_true = np.array([0.000, 0.200, 0.250])# Defining Mean Absolute Error loss function
def mae(pred, true):
# Get absolute difference
differences = pred - true
absolute_differences = np.absolute(differences) # Get the mean
mean_absolute_error = absolute_differences.mean()
return mean_absolute_errormae_value = mae(y_pred, y_true)
print ("MAE error is: " + str(mae_value))
PyTorch 实现:MAE
import torchmae_loss = torch.nn.L1Loss()input = torch.randn(2, 3, requires_grad=True)
target = torch.randn(2, 3)
output = mae_loss(input, target)
output.backward()input
#tensor([[-0.5855, 0.4962, -0.7684],
[ 0.0587, 0.5546, 0.9823]], requires_grad=True)target
#tensor([[ 0.7184, -1.3773, 0.9070],
[-0.1963, -3.2091, -0.8386]])output
#tensor(1.7821, grad_fn=<L1LossBackward>)
均方误差(L2 损耗)
均方误差损失函数
与 MAE 类似,均方误差(MSE)是真实值(y_i)和预测值(y_hat_i)之间的平方(成对)差的总和,除以这种对的数量。MSE 通常通过应用平方算子来惩罚远离事实的预测,但是对异常值不太稳健,因为它倾向于夸大这种观察。
算法:MSE
import numpy as npy_pred = np.array([0.000, 0.100, 0.200])
y_true = np.array([0.000, 0.200, 0.250])# Defining Mean Squared Error loss function
def mse(pred, true):
# Get squared difference
differences = pred - true
squared_differences = differences ** 2 # Get the mean
mean_squared_error = squared_differences.mean()
return mean_squared_errormse_value = mse(y_pred, y_true)
print ("MSE error is: " + str(mse_value))
py torch 实现:MSE
import torchmse_loss = torch.nn.MSELoss()input = torch.randn(2, 3, requires_grad=True)
target = torch.randn(2, 3)
output = mse_loss(input, target)
output.backward()input
#tensor([[-0.4867, -0.4977, -0.6090],
[-1.2539, -0.0048, -0.6077]], requires_grad=True)target
#tensor([[ 2.0417, -1.5456, -1.1467],
[ 0.7593, -0.5154, -1.3713]])output
#tensor(2.1129, grad_fn=<MseLossBackward>)
分类损失函数
二元交叉熵
二元交叉熵损失函数
如果你只有两个标签(如真或假,猫或狗,等),那么二元交叉熵(BCE)是最合适的损失函数。请注意,在上面的数学定义中,当实际标签为 1 (y(i) = 1)时,函数的后半部分会消失。在实际标签为 0 (y(i) = 0)的情况下,等式的前半部分被丢弃。简而言之,我们只是将实际预测概率的对数乘以地面真实类。当我们在分类交叉熵(在上一节中讨论)中推广 BCE 来处理 2 个以上的类时,这个想法是有用的。
算法:BCE
import numpy as npy_pred = np.array([0.1880, 0.4137, 0.2285])
y_true = np.array([0.0, 1.0, 0.0]) #2 labels: (0,1)def BCE(y_pred, y_true):
total_bce_loss = np.sum(-y_true * np.log(y_pred) - (1 - y_true) * np.log(1 - y_pred)) # Get the mean BCE loss
num_of_samples = y_pred.shape[0]
mean_bce_loss = total_bce_loss / num_of_samples
return mean_bce_loss
bce_value = BCE(y_pred, y_true)
print ("BCE error is: " + str(bce_value))
PyTorch 实现:BCE
import torchbce_loss = torch.nn.BCELoss()
sigmoid = torch.nn.Sigmoid() # Ensuring inputs are between 0 and 1input = torch.randn(3, requires_grad=True)
target = torch.empty(3).random_(2)
output = bce_loss(sigmoid(input), target)
output.backward()sigmoid(input)
#tensor([0.1880, 0.4137, 0.2285], grad_fn=<SigmoidBackward>)target
#tensor([0., 1., 0.])output
#tensor(0.4501, grad_fn=<BinaryCrossEntropyBackward>)
范畴交叉熵(即。负对数-可能性+对数软最大值)
分类交叉熵损失函数
类别交叉熵(CCE)损失函数可以用于具有两个以上类别的任务,例如狗、猫、虎、等之间的分类。上面的公式看起来令人望而生畏,但 CCE 本质上是 BCE 的推广,在所有类上增加了求和项。
算法:CCE
import numpy as npy_pred = np.array([0.1880, 0.4137, 0.2285])
y_true = np.array([0.0, 1.0, 0.0])def CCE(y_pred, y_true):
total_cce_loss = np.sum(-y_true * np.log(y_pred) - (1 - y_true) * np.log(1 - y_pred)) # Get the mean CCE loss
num_of_samples = y_pred.shape[0]
mean_cce_loss = total_cce_loss / num_of_samples
return mean_cce_losscce_value = CCE(y_pred, y_true)
print ("CCE error is: " + str(cce_value))
PyTorch 实现:CCE
import torchcce_loss = torch.nn.CrossEntropyLoss()input = torch.randn(2,3, requires_grad=True)
target = torch.empty(2).random_(3) #3 different classes
output = cce_loss(input, target)
output.backward()input
#tensor([[-0.1069, -1.0915, 0.6950],
[-0.4095, 1.0890, -1.4179]], requires_grad=True)target
#tensor([1, 1])output
#tensor(1.2663, grad_fn=<NllLossBackward>)
结论
这就是我们对 PyTorch 更流行的损失函数、它们的数学定义、算法实现和 PyTorch 的 API 实践的介绍。本系列的下一部分将更多地讨论其他不太流行但有用的损失函数。
做订阅我的邮件简讯:https://tinyurl.com/2npw2fnz在那里我定期用通俗易懂的英语和漂亮的可视化总结 AI 研究论文。
理解 PyTorch 损失函数:数学和算法(下)
原文:https://towardsdatascience.com/understanding-pytorch-loss-functions-the-maths-and-algorithms-part-2-104f19346425?source=collection_archive---------21-----------------------
PyTorch 中损失函数的数学定义、算法和实现的分步指南
Part 1 可以在这里找到。
照片由 Antoine Dautry 在 Unsplash 上拍摄
这是第 1 部分的延续,你可以在这里找到。在这篇文章中,我们将通过定义数学公式,编码算法并在 PyTorch 中实现,来深入挖掘 PyTorch 中鲜为人知但有用的损失函数。
介绍
选择最佳损失函数是一项设计决策,取决于我们的计算约束(如速度和空间)、数据集中是否存在显著异常值以及我们拥有的输入/输出类型。
尽管如此,在选择不同的损失函数时,我们需要问的第一个问题是我们面前的数据类型。一般来说,损失函数可以根据我们正在处理的特定任务进行灵活的分组:或者是一个回归或者是分类问题。回归处理连续的数据集,例如在给定一个国家的人口增长率、城市化、历史 GDP 趋势等的情况下预测其人均 GDP。另一方面,分类问题涉及有限的离散类别,例如预测卫星图像是否正在经历任何降雨事件。
回归损失函数
平均绝对误差(L1 损耗)—但更好……(平滑损耗)
这个损失函数类似于 MAE,但是更好更稳定:例如,防止爆炸梯度。
平滑 1 损耗
那看起来…令人畏惧!让我们慢慢分解这些。
第一行概括了损失函数的数学定义。给定一组预测, x 和它们的基本事实, y ,我们平均出一个损失指标, z.
那么什么是 z 呢?它是一个基于情况的损失函数: 如果 预测值和地面实况值之间的绝对差值低于一个β值(这是一个由用户预先确定的先验值),我们将该差值的平方乘以 0.5 并除以β; 否则 从预测值和实际值的绝对差值中减去一半β。
在 Python 中,这可以写成:
算法:smooth 1 loss
import numpy as npy_pred = np.array([0.000, 0.100, 0.200])
y_true = np.array([0.000, 0.200, 0.250])# Defining z function
def calculate_z(diff, beta=0.5):
if (diff < beta).all():
return 0.5 * np.power(diff, 2) / beta
else:
return diff - 0.5 * beta# Defining Smooth L1 Loss function (with beta defined to be 0.5)
def smoothl1_loss(pred, true):
# Get absolute difference
differences = pred - true
abs = np.absolute(differences) # Get the intermediate z values
z_values = np.apply_along_axis(calculate_z, 0, abs) # Get the mean
smoothl1loss = z_values.mean()
return smoothl1losssmoothl1loss_value = smoothl1_loss(y_pred, y_true)
print ("SmoothL1Loss error is: " + str(smoothl1loss_value))
在 PyTorch 中,它只是一个简单的函数调用…
PyTorch 实现:smoothl loss
import torchsmoothl1_loss = torch.nn.SmoothL1Loss(beta=0.5)input = torch.randn(2, 3, requires_grad=True)
target = torch.randn(2, 3)
output = smoothl1_loss(input, target)input
#tensor([[ 0.6051, 1.8739, 0.8015],
[ 0.6713, -0.2191, -1.6360]], requires_grad=True)target
#tensor([[ 0.5638, -0.0400, 1.0652],
[-0.7935, 1.6107, -0.3567]])output
tensor(0.9265, grad_fn=<SmoothL1LossBackward>)
分类损失函数
还记得我们的第一部分对二元交叉熵的研究吗?我们将对它稍加改进以获得更大的数值稳定性(即性能更好)。
二元交叉熵—但更好… (BCE With Logits)
这个损失函数是 BCE 更稳定的版本(即。你可以阅读更多关于 log-sum-exp 数值稳定性的技巧),它在计算 BCELoss 之前结合了一个 Sigmoid 层。
二元交叉熵损失函数
简单重述一下 BCE:如果你只有两个标签(例如真或假,猫或狗,等),那么二元交叉熵(BCE)是最合适的损失函数。请注意,在上面的数学定义中,当实际标签为 1 (y(i) = 1)时,函数的后半部分会消失。在实际标签为 0 (y(i) = 0)的情况下,等式的前半部分被丢弃。简而言之,我们只是将实际预测概率的对数乘以地面真实类。
现在的区别在于在两个地方应用了一个 Sigmoid 函数:
- log( sigmoid (y_hat))和
- log(s 形 (1 — y_hat))
在 Python 中,这可以写成…
算法:BCEWithLogits
import numpy as npy_pred = np.array([0.1880, 0.4137, 0.2285])
y_true = np.array([0.0, 1.0, 0.0]) #2 labels: (0,1)def sigmoid(x):
return 1 / (1 + np.exp(-x))def BCEWithLogits(y_pred, y_true):
total_bcelogits_loss = np.sum(-y_true * np.log(sigmoid(y_pred)) - (1 - y_true) * np.log(sigmoid(1 - y_pred))) # Get the mean BCEWithLogits loss
num_of_samples = y_pred.shape[0]
mean_bcelogits_loss = total_bcelogits_loss / num_of_samples
return mean_bcelogits_lossbcelogits_value = BCEWithLogits(y_pred, y_true)
print ("BCEWithLogits error is: " + str(bcelogits_value))
它的 PyTorch 实现也很简单。
PyTorch 实现:BCEWithLogits
import torchbcelogits_loss = torch.nn.BCEWithLogitsLoss()input = torch.randn(3, requires_grad=True)
target = torch.empty(3).random_(2)
output = bcelogits_loss(input, target)input
#tensor([-0.7844, -1.8377, 0.1435], requires_grad=True)target
#tensor([1., 0., 1.])output
#tensor(0.6440, grad_fn=<BinaryCrossEntropyWithLogitsBackward>)
结论
这就是我们对 PyTorch 的不太流行但更好(在数值上更稳定等)的损失函数、它们的数学定义、算法实现和 PyTorch 的 API 实践的中间接触。
【https://tinyurl.com/2npw2fnz】订阅我的电子邮件简讯:https://tinyurl.com/2npw2fnz我定期在那里用通俗易懂的英语和漂亮的可视化总结 AI 研究论文。
用图像理解随机森林的超参数
原文:https://towardsdatascience.com/understanding-random-forests-hyperparameters-with-images-9b53fce32cb3?source=collection_archive---------20-----------------------
理解随机森林 ML 模型中超参数的影响
由 Geran de Klerk 在 Unsplash 拍摄的照片
关于随机森林
决策树是一种解决问题的分布式算法。它试图通过将决策的每一步二进制化来模拟人类的思维过程。所以,在每一步,算法都在真或假之间选择前进。
该算法简单,但非常强大,因此广泛应用于机器学习模型中。然而,决策树的一个问题是它很难概括一个问题。该算法学习如何决定一个给定的数据集,以至于当我们想用它来处理新数据时,它无法给我们最好的答案。
为了解决这个问题,创建了一种新型的决策树算法,通过收集在同一数据集的各种变化上训练的许多树,并使用投票或平均系统来组合它们,并为每个数据点确定最佳结果。这就是随机森林的概念。
随机森林是由树结构分类器(…)独立同分布随机向量的集合组成的分类器,并且每棵树为输入 x 处最流行的类别投一个单位票。
创建简单的模型
创建模型相当简单。正如你们中的许多人可能知道的,实际的模型实例、拟合和预测只需要几行代码就可以完成。然而,困难的部分通常是准备数据和调整模型。
要调整模型,我们必须将超参数从默认值更改为能给我们带来最佳结果的值。我们的目标是更好地理解随机森林中每个超参数的作用,以便在需要时更好地修改它们。
以下是我将在本例中使用的导入和数据集:来自sklearn
的 wines 数据集。
# Data
import pandas as pd
from sklearn.datasets import load_wine# Data split
from sklearn.model_selection import train_test_split# Model
from sklearn.ensemble import RandomForestClassifier# Visualize Tree
from sklearn.tree import export_graphviz# Load dataset
df = load_wine()# variables
X = pd.DataFrame(df.data, columns=df.feature_names)
# target
y = df.target# Split train and test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=12)
以下是具有默认值的模型:
# Instantiate class. Using random_state=2 for you to be able to reproduce the same resultrf = RandomForestClassifier(*n_estimators=100*, *criterion='gini'*, *max_depth=None*, *min_samples_split=2*, *min_samples_leaf=1*, *min_weight_fraction_leaf=0.0*, *max_features='auto'*, *max_leaf_nodes=None*, *min_impurity_decrease=0.0*, *bootstrap=True*, *oob_score=False*, *n_jobs=None*, ***random_state=2***, *verbose=0*, *warm_start=False*, *class_weight=None*, *ccp_alpha=0.0*, *max_samples=None*)
我们来训练一下,生成一张图。
# Fit the model
rf.fit(X_train,y_train)# Extract one of the trees from the model
tree = rf.estimators_[99]# Export as dot file
export_graphviz(tree, out_file='tree.dot',
feature_names = df.feature_names, class_names = df.target_names, rounded = True, proportion = False, precision = 2, filled = True)# Convert to png using system command (requires Graphviz)
from subprocess import call
call(['dot', '-Tpng', 'tree.dot', '-o', 'tree.png', '-Gdpi=90'])# Display in jupyter notebook
from IPython.display import Image
Image(filename = 'tree.png')
图 1:具有所有默认值的随机森林模型。图片由作者提供。
好的,很好。现在,在继续之前,让我们排列我们正在使用的名称。
- 节点是我们有分裂的时候。
- 分支是一个决策路径【例如酒精=真>色调=真>结束(叶子)】
- 叶子是树枝的最后一格。
也就是说,在图 1 中注意到的第一个有趣的事情是,当“基尼”指标值为 0.0 时,树枝才到达叶子。该指标是一个衡量分割质量的函数。sklearn
支持信息增益的“基尼”或“熵”。当数字达到 0 时,我们不能获得更多的信息,因为叶子现在是纯的。当你查看值【类 0 数量,类 1 数量,类 2 数量】时,一个纯叶节点被确认。如果预测的类中的数是唯一大于 0 的数,则该叶是纯的*(例如[0,1,0]和 class_1 =纯节点)*。
我们的目标是更好地理解改变超参数如何改变叶子、节点和分支的数量。因此,我将一次改变一个主要的超参数,并绘制结果。
最大功能
寻找最佳分割时要考虑的特征数量。默认值为“auto”,使用“sqrt”,但它有其他选项,如“log2”或一个有趣的可能性,即输入一个介于 0 和 1 之间的浮点数,这将是每次分割时使用的功能的百分比。如果你有 10 个特性,使用max_feature=0.2
,它会考虑 20%的特性,也就是 2。
通常不是所有的特征都那么重要,所以这是一个很好的在GridSearchCV
中测试的超参数,你可以试着从 0.3,0.4 这样的值开始。这里的数字越小,方差越小,但偏差越大。对于较高的数字,您有更多的机会将最佳特征用于分割,因此您将减少偏差,但增加方差。
图二:max_features 对比。作者图片
最大深度
这个超参数将限制树可以向下生长的最大分裂数量。
# Instantiate class
rf = RandomForestClassifier(max_depth = 2)
图 3:最大深度=2 的 RF 模型
因此,正如我们选择了max_depth=2
,这意味着它只能分裂两次,使第三行的结果方块成为树叶。请注意,基尼系数指标仅适用于一个方块。事实上,它对结果没有太大的影响,因为在这个模型中有 100 个不同的树(估计量)。即使深度限制为 1,它仍然预测了三个类。它必须与其他超参数一起使用。
分割的最小样本数
给定节点中能够拆分的最小样本数。
再看图 3。看到左侧有 42 个样本。让我们把min_samples_split
设为 50,看看会发生什么。
rf = RandomForestClassifier(min_samples_split=50, random_state=2)
作者图片
不出所料,左边的树枝没有生长。因此,这是修剪树并迫使它在达到节点纯度之前给出分类的另一种方式。
最大叶节点数
它决定了你的树的最大叶子数。
rf = RandomForestClassifier(max_leaf_nodes=3, random_state=2)
图 4: max_leaf_nodes=3。图片由作者提供。
这里,我们看到分类器为每个可预测的类(类 0、1 或 2)创建了一个叶子。
每片叶子的最小样本数
叶子需要的样本数。这意味着,如果叶片上的样本数在另一次分割后低于该数量,则不会进行处理。
rf = RandomForestClassifier(min_samples_leaf=20, random_state=2)
图 5: main_samples_leaf=20。图片由作者提供。
在图 5 中可以看到,每片叶子中的样本数高于 20。当我们的模型过度拟合时,我们可以尝试调整这个超参数,无论是否与max_depth
结合,并强制做出更早的决定,这可能有助于推广预测。
复杂性成本修剪
另一种修剪树的方法是使用ccp_alpha
超参数,它是复杂性成本参数。该算法将通过计算复杂度成本在树之间进行选择,具有较小值的数量被认为较弱,因此它们被修剪。一旦复杂性成本的最小值高于ccp_alpha
,修剪就停止。ccp_alpha
的值越大,修剪的节点数越多。
图 6:CCP 阿尔法数的差异。图片由作者提供。
在你走之前
本材料的目的是让您直观地了解改变随机森林模型中的每个超参数将如何影响您的结果。
n_estimators
:估计数。你拥有的越多,你应该有一个更准确的结果,但它在计算能力方面更昂贵。criterion
: 在基尼或熵之间选择。两者将寻求相同的结果,即节点纯度。- 树越大,越有可能过度拟合。RF 模型通常会尽量减少这种情况,但如果您的模型过度拟合,这个超参数可能会是一个有趣的玩法。
- 这个和上面那个一起工作。这是分裂到另一个分支所需的最小样本。
max_leaf_nodes
:可以强制树少叶子。ccp_alpha
:另一种修剪树的方法,基于复杂性成本的计算。- 参见 GitHub 中的代码,这里是。
跟我来
如果你对这些内容感兴趣,请点击那个按钮告诉我应该写些什么,并关注我。
https://medium.com/gustavorsantos
参考
https://www.stat.berkeley.edu/~breiman/randomforest2001.pdf
https://scikit-learn.org/stable/modules/tree.html#minimal-cost-complexity-pruning
https://sci kit-learn . org/stable/modules/tree . html #最小成本复杂性修剪
随机森林文档
理解规范化
原文:https://towardsdatascience.com/understanding-regularisation-7576f36942f5?source=collection_archive---------28-----------------------
正则化是一个强大的工具,可以帮助调整模型
卢卡斯·本杰明在 Unsplash 上的照片
今年年初,我对正规化的理解非常有限。对我来说,它只是一个在过度合身时使用的工具。如果模型的验证损失高于列车损失,添加 L1 或 L2 正则化可能能够解决这个问题。事实是,有许多不同的方法来看待正则化,它是一个强大的工具,可以帮助调整行为不同的模型。
过度拟合——它是什么,为什么会发生?
在理解解决方案(正则化)之前,我们必须首先理解过度拟合的问题。
让我们从我们都熟悉的过拟合诊断开始:当验证/测试损失高于训练损失时。这表明该模型符合训练集中的某些模式,而这些模式可能不存在于测试集中。
这个方差是指预测的方差,而不是基础数据的方差。如果我将数据集分割成 5 个相等的大小,并通过决策树等高方差模型,与支持向量机等低方差模型相比,它可能会给出非常不同的输出。高方差模型比低方差模型更容易过度拟合。
观察过度拟合的另一种方法是查看模型本身的预测。我非常肯定,你们中的许多人以前见过这张图,它显示了回归问题中过度拟合的预测。
当然,对于简单的问题,我们可以很容易地看到解决方案。但是当处理像图像或文本这样的非结构化数据时,这可能不明显,这就是为什么使用验证损失。
不仅仅是诊断,我们首先要明白为什么这个问题会存在。
- 真实世界的数据是有噪声的
数据中总是存在异常和不同的交互和行为。这样做的问题是,所有这些随机噪声都将被模型作为信息捕获。该模型将数据中的噪声误认为它可以使用的模式,这导致过度拟合。 - 高维度
高维度恶化了噪声和方差导致的问题。随着维数的增加,随机特征与目标相关的概率只是偶然地增加。噪声越多,模型从噪声中学习的就越多。 - 小数据集 与高维度类似,小数据集会导致噪声对模型性能产生更大的恶化作用。通过拥有更多数据点来减少方差,小数据集将经历极高的方差
除了减少过度拟合,正则化还可以应用于无监督的实例。在这种情况下,正则化用于推动模型以某种方式运行,而不是最小化验证损失。
什么是正规化?
数学定义
正规化是对损失增加惩罚的过程。
数学定义是我们都熟悉的东西。通过在损失函数中添加额外的惩罚,我们引入了模型必须优化的额外目标。然后,模型的最终收敛将平衡这些目标中的一部分,以获得性能最佳的解决方案。
现在让我们从不同的角度来看待正规化。
看待正规化的另一种方式更直观一些。我们可以从名字本身来看待正则化:让事情更有规律。虽然这个定义可能相当模糊,但通过这个“正则化透镜”来观察许多方法可能非常有用。让我们看看 L1 正则化(套索回归)在这个镜头下是什么样子的。
L1 正规化公式
这里发生的是,我们基于权重的绝对值来惩罚模型。在拟合模型之后,我们看到许多预测器的权重将被设置为 0。我们这样做是因为不可能每一个特征都与目标相关联。
本质上,我们说的是“低权重值是 不规则的”。假设首先对预测值进行缩放,则具有低权重值的要素可能与目标没有关系,只是模型过度适应随机噪声。这些低权重被认为是“不规则的”,并使用该附加损失函数来移除。我们将权重设置为 0 的阈值将取决于λ的值。
我更喜欢这个定义的原因是,它更容易看到其他机器学习技术如何能够归入正则化。除了 L1 和 L2 等著名的正则化方法,其他常用的机器学习方法也可以从正则化的角度来看。
例如,放弃和提前停止都是用于防止神经网络过度拟合的方法,这可以被视为正则化
这种看待正规化的方式也有一个很好的贝叶斯视角。在这种范式下,我们所认为的“常规”代表了我们先前对数据的信念。规范化只是将模型推向我们先前的信念。如果先验信念模拟现实世界的过程,正则化将有助于模型更好地概括,并在最终应用中产生更多价值。
现在我们来看一些例子!其中一些例子是从我在学校学的优化模块中借来的,显示了在特殊情况下的规律性。
基本正规化
L1 向我们展示了正则化是如何让一个模型更好地泛化的,但是在某些情况下,没有正则化的模型是完全无用的!
观察到的泊松过程散点图-图片由作者提供
我们这里有一个时间序列图,其中的数据点是根据泊松分布生成的。蓝色曲线是决定λ的函数。这可以代表任何罕见的事件,如某一天检测到的产品缺陷数量或提交的保险索赔数量。我们想要恢复的是速率参数λ 的估计值,并观察它如何随时间变化。
我们可以发现的一个方法是使用最大似然估计(MLE) 。对于每个数据点,我们预测使该数据点的可能性最大化的速率参数。但是在我们的情况下,这可能会造成严重的问题!
泊松分布最大似然估计的推导
从上面的计算中我们看到,给出最大可能性的 rate 参数是当前数据点本身的值!这给了我们上图,它与基本分布相差甚远,并没有真正给出任何有用的见解。虽然这组预测的可能性分数是全局最优,但我们知道这种情况不太可能发生。
使用 MLE 的λ参数预测—作者图片
根据我们之前的信念,我们知道像这样的过程不应该让 lambda 参数移动太多。函数可能会更平滑,我们可以通过执行正则化来调整这种不规则的行为。我们在这里可以做的是推动模型生成遵循更平滑形状的预测。这可以使用损失函数来完成,该损失函数惩罚预测与前一时间步的差异。
正则化损失函数的对数似然和梯度
我们求解新损失函数的梯度,并使用梯度下降来优化它。因为 was 可以计算损失函数的梯度,所以我们可以执行简单的梯度下降算法来优化该损失函数。
正则化最大似然估计
在对这个新的损失函数进行优化之后,我们看到所产生的预测更好地适合基础函数。
正则化后的预测—作者图片
该函数现在对突然增加不太敏感,并且可以更好地洞察潜在的过程。实际上,我们永远不会知道这个底层函数,但是通过使用测试数据,我们可以看到我们的函数在现实世界中更有用!
图像正则化
由 Ravi Sharma 在 Unsplash 上拍摄的照片
正则化也适用于图像问题。这个例子显示了正则化如何应用于图像去噪问题。这个问题更多的是一个优化问题,而不是一个机器学习问题,将只有一个数据点,我们将尝试只基于这个例子进行优化。
对于这个例子,我们将使用添加随机噪声到上面的图像。我们随机设置一些像素为白色,并尝试设计一个程序来恢复原始图像。
原始图像与噪声图像 Ravi Sharma 在 Unsplash 上拍摄的原始照片
让我们从损失函数开始。在这种情况下,我们将使用 L2 损失函数,以便输出将类似于输入图像。然后,正则化通过严重惩罚“噪声”点来防止和精确复制输入。
全变差正则化损失函数
如果你注意到,正则化损失类似于第一个例子。这被称为全变差正则化(TVR ),可以根据维数进行推广。总变差正则化不是一维变差,而是惩罚 x 平面和 e 平面的变差。这是基于一个潜在的假设,即在图像中,像素值在大部分时间内不会发生很大变化,这种规律性的损失确保了这种行为。
现在进行优化!我们将使用 PyTorch,它帮助我们执行反向传播步骤并计算梯度。我们所要做的就是提供损失函数,并使用loss.backward()
和img_pred.grad
来获得梯度下降的梯度。
使用 PyTorch 的梯度下降
理想情况下,这将大大平滑图像,去除大部分随机噪声,同时保留大部分图像内容!
原始图像(左)、噪声图像(中)、清洁图像(右)
还不错!斑点肯定仍然很明显,但与嘈杂的图像相比要好得多。除了我们看到的去噪应用,TVR 还用于许多基于图像的生成模型,如风格转移和深度梦境,以平滑模型产生的最终图像。
生成建模中的正则化
马修·科莫伊在 Unsplash 上的照片
现在让我们转到更有趣的东西,自动编码器和生成建模!
VAE 输出-作者图片
自动编码器本质上是一种降维工具,它将高维数据点压缩成低维表示。这个想法很简单,我们训练一个模型将数据压缩到一个更小的维度,然后从压缩的表示中创建原始点。该模型然后基于。通过足够的训练,压缩的表示包含数据点的所有信息,但是在压缩包中。
就其本身而言,自动编码器是非常有用的算法,但通过添加正则化,你会得到非常特别的东西!自动编码器现在变成了一个变型自动编码器(VAE),一个可以创建新的合成数据点的生成模型。
以前,对潜在表示没有限制,但现在我们增加了一个额外的正则化损失函数。这个损失函数不利于模型偏离标准的多元正态分布。为此,我们使用 KL-散度损失函数来计算概率分布之间的差异。
由重建损失(蓝色)和正则化 KL-散度损失(橙色)组成的 VAE 损失函数
在用这个新的损失函数训练后,隐藏变量变得更加正态分布。这个潜在空间中的采样点,并可能产生看起来像训练集的全新数据点。通过正则化,以前的降维技术可用于生成式建模,并创建在训练集中找不到的完全唯一的数据点。这种正则化方法的有趣之处在于,即使我们没有太多的先验信息,我们也可以生成有用的结果。我们并不真正知道是什么隐藏变量决定了数据是如何创建的,但是使用这种正则化方法确实会产生有趣且有用的结果。
如果你想知道更多关于 VAEs 的信息,我写了 4 部分的系列文章,你可以在这里找到:
正则化是一种非常强大的技术,嵌入在许多不同的常用算法中。除了 L1 和 L2 正则化,还有许多其他正则化方法,我们可以用来优化我们的模型。它给了我们数据科学家额外的旋钮来调整我们的模型并获得更好的结果。
如果你喜欢这篇文章,请在 Medium 上关注我!
查看代码:https://github.com/reoneo97/understanding-regularisation在 LinkedIn 上连接:https://www.linkedin.com/in/reo-neo/
直观地理解剩余网络
原文:https://towardsdatascience.com/understanding-residual-networks-resnets-intuitively-5afef9f089ea?source=collection_archive---------36-----------------------
资源网是许多计算机视觉应用的支柱
照片由像素的皮克斯拜拍摄
ResNets 或残差网络是我们最终能够深入神经网络的原因。每个人都需要知道它们为什么工作,这样,他们就可以做出更好的决定,并理解神经网络为什么工作。**人工智能不是黑匣子。**在 ResNets 出现之前,层数多的神经网络一直比层数少的神经网络表现差(退化问题)。
雷斯网纸业(https://arxiv.org/pdf/1512.03385.pdf)
上图显示,普通 20 层网络的误差(越小越好)总是优于普通 56 层网络。
出了什么问题?
让我们从单个神经元开始。
来源:作者
单个神经元有权重和偏差。偏向是让它活着,以免当 x = 0 时它死了。权重实际上决定了输入的重要性。权重越低,输入就越不重要。
警告是权重和偏差的值都在 0 和 1 之间。
x 是输入。在 ResNets 的情况下,x 将是一个图像。在给 ResNet 之前,让我们看看图像是什么样的。
来源:作者
图像由像素组成,每个像素取 0 到 255 之间的值。神经网络以这些数字的形式接收图像。上图是数字 0 被神经网络转换成数字后的图像。
但是,在网络喝这种数字汤之前,我们需要做更多的事情。
你愿意在更短的时间内跑完 255 英里还是 1 英里?
来源:作者
神经网络也运行到解决方案,这是更容易的,如果他们必须运行更少。所有值都除以 255(最大值)。我们称之为重新缩放,但它实际上是将代表图像的数字从圆圈 A 移至圆圈 b。因此,它减少了神经网络部分的工作。
因此,进入网络的内容在 0 到 1 的范围内。让我们看看这个值经过单个神经元时会发生什么。w 和 b 都在 0 和 1 之间的范围内。因此,y 在 0 到 0.1 的范围内。
如果我们把这个过程想象成数据通过网络,我们会看到值不断变小。
来源:作者
我们最终会遇到非常小的值(0.00001)。如果我们的值如此之小,我们将学到的(反向传播误差)也将更少,从而导致大网络给出的高训练误差。
解决方案
以上我们了解到价值观开始消亡。当一个人的心开始死亡时,我们该怎么办?心肺复苏术。
现在,当你为一个神经网络做心肺复苏时,它看起来像这样:
来源:作者
恢复权重的绿线是剩余连接,这就是 ResNets 的名称。
这就是如何在一行中描述 ResNets 中的剩余连接:
用于神经网络的 CPR
因此,有了剩余连接,这些值就不再消亡,我们最终得到的是一些重要的值,这些值导致神经网络中的一些重要学习。
这就是 ResNets 能够非常非常深入,同时仍能提供出色结果的方式和原因。
使用 Python 理解 ROC 曲线
原文:https://towardsdatascience.com/understanding-roc-curves-c7f0b52e931e?source=collection_archive---------7-----------------------
艾萨克·史密斯在 Unsplash 上拍摄的照片
用 Python 构建接收机工作特性曲线的基本直觉
如果你谷歌:“ROC 曲线机器学习”,你会得到这样一个维基百科的答案:
受试者操作特征曲线,或 ROC 曲线,是一种图示,说明了二元分类器系统在其辨别阈值变化时的诊断能力
另一个常见的描述是 ROC 曲线反映了跨不同分类阈值的模型的敏感性。当我开始研究机器学习时,这些定义总是让我感到困惑。
在这篇文章中,我将分享我是如何学会理清自己“初学者般”的困惑,并对 ROC 曲线形成足够好的直觉的。
ROC 曲线到底是什么?
理解 ROC 曲线的一种方式是 它描述了模型的灵敏度(真阳性率或 TPR)与其特异性(关于假阳性率描述:1-FPR) 。
现在,让我们理清这里的每个概念。
TPR 被称为模型的敏感度,是“阳性”类的正确分类除以数据集中所有可用阳性类的比率,数学上:
作者图片
虽然 FPR 是假阳性(误分类为阳性的预测数)与所有可用阴性类别之间的比率,但在数学上:
作者图片
将问题与阈值分数分离
一开始,暗示我的直觉是要把握门槛分数的作用。一个很好的起点是建立一个心理图景:
通过这种经典的可视化,人们可以了解到第一直觉,即 理想的模型是具有尽可能高的真阳性率同时保持尽可能低的假阳性率的模型。
阈值对应于某个值 T(例如 0 和 1 之间的值),该值用作分类器的决策边界,并且它影响 TPR 和 FPR 之间的折衷。
让我们写一些代码来获得所有这些组件的可视化。
可视化 ROC 曲线
实现这一点的步骤如下:
- 导入我们的依赖关系
- 用
**drawdata**
包给 Jupyter 笔记本画一些假数据 - 导入假数据到熊猫数据框
- 对数据拟合逻辑回归模型
- 以概率值的形式获得逻辑回归模型的预测
- 设置不同的阈值分数
- 可视化 roc 曲线图
- 得出一些最终结论
1.导入我们的依赖性
from drawdata import draw_scatter
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_recall_curve,precision_score, plot_roc_curve
2.用 Jupyter 笔记本的drawdata
包画一些假数据
draw_scatter()
输出:
3。将假数据导入熊猫数据框
df = pd.read_csv("./data.csv")
4.根据数据拟合逻辑回归模型
def get_fp_tp(y, proba, threshold):
"""Return the number of false positives and true positives."""
# source: https://towardsdatascience.com/roc-curve-explained-50acab4f7bd8
# Classify into classes
pred = pd.Series(np.where(proba>=threshold, 1, 0),
dtype='category')
pred.cat.set_categories([0,1], inplace=True)
# Create confusion matrix
confusion_matrix = pred.groupby([y, pred]).size().unstack()\
.rename(columns={0: 'pred_0',
1: 'pred_1'},
index={0: 'actual_0',
1: 'actual_1'})
false_positives = confusion_matrix.loc['actual_0', 'pred_1']
true_positives = confusion_matrix.loc['actual_1', 'pred_1']
return false_positives, true_positives
# train test split on the fake generated dataset
X = df[["x", "y"]].values
Y = df["z"].values
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=42)
y_test = np.array([1 if p=="a" else 0 for p in y_test])
y_train = np.array([1 if p=="a" else 0 for p in y_train])
# create the model
lgr = LogisticRegression()
lgr.fit(X_train, y_train)
5.以概率值的形式获得逻辑回归模型的预测
y_hat = lgr.predict_proba(X_test)[:,1]
6.设置不同的阈值分数
thresholds = np.linspace(0,1,100)
7.可视化 roc 曲线图
# defining fpr and tpr
tpr = []
fpr = []
# defining positives and negatives
positives = np.sum(y_test==1)
negatives = np.sum(y_test==0)
# looping over threshold scores and getting the number of false positives and true positives
for th in thresholds:
fp,tp = get_fp_tp(y_test, y_hat, th)
tpr.append(tp/positives)
fpr.append(fp/negatives)
plt.plot([0, 1], [0, 1], linestyle='--', lw=2, color='r',label='Random', alpha=.8)
plt.plot(fpr,tpr, label="ROC Curve",color="blue")
plt.text(0.5, 0.5, "varying threshold scores (0-1)", rotation=0, size=12,ha="center", va="center",bbox=dict(boxstyle="rarrow"))
plt.xlabel("False Positve Rate")
plt.ylabel("True Positive Rate")
plt.legend()
plt.show()
8.得出一些最终结论
通过改变阈值分数,我们可以得到增加的真阳性率和假阳性率。 一个好的模型是阈值分数使真阳性率尽可能接近 1,同时使假阳性率尽可能低。
但是,我们如何选择最佳的分类阈值呢?
一个简单的方法是取真阳性率和假阴性率之和最大的一个(1- FPR)。
另一个标准可以是简单地**选择离你的 ROC 空间左上角最近的点。**然而,这意味着真阳性率和真阴性率具有相同的权重(来源(https://stats.stackexchange.com/questions/123124/how-to-determine-the-optimal-threshold-for-a-classifier-and-generate-roc-curve#:~:text=A simple method is to,thresholds like financial costs, etc.&text=Choose the point closest to,corner of your ROC space.)),这在癌症分类等情况下不一定成立,因为假阳性的负面影响大于真阳性的影响。
关于 ROC 曲线的最后思考
我认为,从长远来看,花一些时间来消化评估指标对您的机器学习之旅非常有益。在本文中,您了解了:
- 关于 ROC 曲线如何工作的基本直觉
- 分类阈值如何影响模型的敏感性和特异性之间的关系
- 关于如何使用 ROC 曲线设置最佳分类阈值的直觉
如果您想了解更多关于 Python 的机器学习知识,请查看以下课程:
这些是附属链接,如果你使用它们,我会得到一小笔佣金,干杯!:)
- 机器学习 A-Z:动手 Python & R 在数据科学
- 用于数据科学和机器学习的 Python 训练营
如果你喜欢这篇文章,请在 Medium 、上关注我,订阅我的简讯,在 Twitter 、 LinkedIn 、 Instagram 或 join Medium 上与我联系!谢谢,下次再见!:)
参考
- ROC 曲线超赞教程
- 在 ROC 曲线上堆叠交换螺纹
- 维基百科页面上的 ROC 曲线
- 工整文章由 Zolzaya Luvsandorj 讲述巨蟒的巨鸟曲线
什么是流处理?
原文:https://towardsdatascience.com/understanding-stream-processing-2ebebefa523e?source=collection_archive---------15-----------------------
流处理与批处理
从德国公司大数据领域的各种项目中,我意识到许多公司都面临着类似的问题。他们有旧的遗留系统,非常适合当时的设计和建造。今天,新技术出现,新事物成为可能。人们在谈论流处理和实时数据处理。每个人都想采用新技术来投资未来。尽管我个人认为这是一个合理的想法,但我也相信人们必须首先了解这些技术以及它们的用途。当我与各种客户一起工作时,我意识到以一种清晰的方式定义什么是流处理以及我们可以利用它的用例并不太容易。因此,在这一系列文章中,我将分享我的一些想法,我们将阐述这两种方法,以更好地理解它们是什么。在这第一篇文章中,我将试图明确区分众所周知的批处理和流处理。
关系数据库模型可能是最成熟和被采用的数据库形式。我想几乎所有公司都将 it 作为实施运营业务的核心组件。通常,这个中央数据存储的副本存在,用于分析用例。然而,复制和分析查询通常作为所谓的批处理作业运行。尽管我们中的大多数人可能对关系数据库有广泛的了解,但我还是想在文章开始时对批处理作业的特征有一个清晰的定义。
什么是批处理?
批处理作业通常按如下方式执行:
- 读取所有输入数据,
- 执行转换/逻辑,
- 将结果写入接收器。
关键的部分是,在开始处理之前,我们首先读取我们希望用查询处理的整个输入。因此,我们是在“事后”查看我们的数据。也就是说,我们想要查看的所有数据都必须已经存在。然而,当我们处理运营数据时,这些数据是不断变化的。我们正在分析由我们的核心业务案例产生的数据,因此它将继续变化,直到我们退出我们的业务。因此,为了能够执行批处理作业(并在事后查看数据),在某个时间点,我们必须获取底层数据的快照,并在“还存在什么”上运行我们的逻辑。这人为地将我们不断变化的数据集分成特定大小的批次。通常,批量大小由我们想要处理新事件的某个时间间隔指定(例如,一天一次、一天两次、一小时一次)。
作者图片
批处理的局限性是什么?
自然地,这种将我们的输入数据集人为划分成固定时间间隔的批次的做法导致了我们的处理结果的有限流通性。我们的结果数据集的有限流通性反过来限制了我们能够在其上构建的洞察力和用例。例如,如果我们一天只处理一次数据,那么昨天的结果今天才可用。
什么是流处理?
为了克服批处理的这一缺点,我们可以继续减少批处理的大小,直到我们在特定用例中得到我们期望的结果。我们可以一小时、一分钟或一秒钟处理一次。如果我们继续减少批处理时间间隔,我们最终将处理每个立即到来的事件。然而,每隔几毫秒查询数据库中的新事件会带来相当大的开销。此外,单个记录查询的价值甚至比每天只提供一次的结果更有限。由于批处理查询被设计为在开始处理之前读取所有记录,因此我们无法从单个记录批处理中获得太多信息。
假设我们想通过一些特定的关键字对数据集进行排序。如果我们查看一天的一批数据,我们得到的结果将和预期的一样:当天事件的有序列表。然而,对单记录数据集进行排序是没有意义的,因此我们的查询实际上是没有价值的。因此,有一种不同的方法来处理事件。这通常被称为流处理。
流处理是一种特殊类型的输入数据的特殊处理模式,它在许多方面不同于批处理。流处理的基本特征是:
- 处理未绑定的数据集:我们处理一个不断接收更新的数据集。只要我们还在这一行,总会有新的记录。
- 立即处理记录:我们希望在每条记录被添加到数据集中时对其进行处理。我们希望以低延迟处理它(无论这在数字上意味着什么)。
- 记录总是一个事件:流中的每个数据记录都是一个事件。
事件是一个
- 小,
- 自带,
- 不可变的对象
- 描述发生了什么事情
- 在某个时间点。
本质上,流处理是对不断增长的数据集的处理,该数据集由不可变记录的事件组成。由于事件不可更改,更新数据集的唯一方法是创建新记录。因此,我们正在处理一个只追加的数据集,并希望在每个事件到达时都进行处理。
让我们看看如何使用流处理来执行前面的示例,即按照某个数字对数据集进行排序。通常,每当我们需要一个流内数据的全局视图时,流处理器需要维护一个状态。在我们的例子中,这个状态就是所谓的物化视图。这个实例化视图随着每个新事件的到来而更新。就像这样,我们基本上是随着每个新事件的到来来更新我们的结果。每个时间点的当前状态可以通过从头重放整个流并对事件应用相同的逻辑来再现。
作者图片
结论
尽管每个人都在谈论流处理这个术语,并且它似乎可以应用于每个用例,但我们已经看到,它更多的是一种针对具有特殊特征的数据集的特殊处理模式。流处理意味着通过处理每条记录来处理一个未绑定且不断增长的数据集。这个数据集由事件组成,这些事件是小型的、自包含的和不可变的对象,描述在某个时间点发生的事情。流的关键属性是所有记录都是不可变的,因此我们处理的是只附加的数据集。每当我们处理这样的事件流时,我们都需要跨事件维护一个状态,以便对数据有一个全局的看法。为了处理新到达的输入事件,我们简单地将它与我们的逻辑一起应用于当前状态。只要我们保留了事件流的历史,我们就能够从任何时间点重现这种状态。每当我们的用例不满足这些需求时,它很可能不太适合作为流应用程序来实现。
在下一篇文章中,我们将详细阐述事件流和关系数据库中表的概念之间的联系。
了解代理模型及其在数据科学中的优势
原文:https://towardsdatascience.com/understanding-surrogate-models-and-their-benefits-in-data-science-5cdc81a0509a?source=collection_archive---------20-----------------------
R&D 使用的一些模型继承自基础理论,可能很难操作或转移。这个现实生活中的例子(带有代码)解释了为什么代理模型提供了一个有趣的替代方案。
阿诺·塞纳尔在 Unsplash 拍摄的照片
理论方法与替代方法
首先,区分我们将在本文中讨论的两种模型之间的主要区别是很重要的:
- 理论模型应该被认为是“现象学的”模型,继承自科学知识并以方程的形式表达,就像(很简单!)下面一个:
理论压力公式
图片作者
- 替代模型基于经验和/或模拟数据。它们只是理论模型的一种“接近的表示”,并且,通过延伸,是地面真相的一种“接近的表示”。它们通常不太准确,但也不太复杂。机器学习模型属于第二类,因为它们几乎总是只依赖于观察。
通过测量 100 种不同的力和面积组合
下的压力
推导出的替代公式图片由作者提供
那么,当我们已经有了理论模型,为什么还要对使用代理模型感兴趣呢?
想象一个研发部门正在设计一个新的流程。他们想要模拟每个分子的行为方式,或者至少,以最精确的方式模拟这个过程。
为了达到这样的精度,他们将使用模拟解决方案,其中嵌入了对过程及其相应的机械方程式的详细描述,如下图所示:
gPROMS 的屏幕截图—包含在 Process Systems Enterprise 的 kind 授权中
这一步完成后,工程部门的同事们准备开始在新车间中集成该设备,他们渴望从 R&D 的准备工作中受益…但他们面临一些限制:
- 软件:模拟工具可能很贵,而且由于他们的公司想要限制可用许可证的数量,他们无法使用这些工具。此外,理论模型的格式不能用它们自己的工具来解释。
- 计算:模拟的计算量可能很大,即使工程部门可以访问理论模型,他们也无法在更大的范围内将所有局部和复杂的模型结合起来,以模拟整个车间或工厂的行为。这就像试图通过整合每个引擎的工作方式来描述道路交通的变化……而每辆车的速度就足够了。
- 保密 : R & D 确实同意在内部分享其工作成果,但也将这一新流程视为公司知识产权的一部分。由于工程部门可能会分包他们的一些研究,R & D 不愿意完全透露这个过程是如何设计的。他们宁愿把它表达成一个“黑匣子”,只有动态的输入和输出,对周围的环境作出反应。
出于上述所有原因,代理模型可以代表一种有趣的替代方案,以降低所需的计算能力,同时允许与标准工具更好的兼容性,并且不会泄露公司的知识产权。
如下所述,同样的过程动力学可以从纯理论的观点或从“接近”的观点来表达:
理论模型 Vs 代理模型(图片由作者提供—图标来源:flaticon.com)
现实生活中的应用呢?
之后描述的工作是我和我的 R&D 同事 Baptiste Boit 进行的第一个实验的净化版本,他一直在推动我(几个月来!)来开发代理模型…直到我明白这个概念有多关键!
完整的源代码——代码和模拟数据——可以在 GitHub(本文末尾的链接)上找到。
我们的目标是从具有以下特征的流程中创建一个代理模型:
两个初始条件(X)定义了 100 个周期(时间)期间动态批处理的行为,通过 2 个输入变量和 3 个输出变量(Y)表示:
描述过程的“笨拙”公式=作者图片
Baptiste 模拟了 200 个不同的批次(“样本指数”从 0 到 199),每个批次都以不同的起始条件(“Init_Cond_1”和“Init_Cond_2”)开始,就像一个标准的“实验设计”。
为了让它更容易理解,我将动态变量的数量从 5 个减少到了 3 个。这些动态变量(Dyn_Input_1、Dyn_Input_2 和 Dyn_Output_1)的值在每个批次的每个周期都会被记录,并已被归一化(MinMaxScaler()):
作者第一批
模拟图像的前 20 行
探索模拟数据
我们首先绘制初始条件的分布,正如人们所预料的那样,它们在两个范围内以类似 DoE 的方式均匀随机分布:
传播的初始条件
图片作者
为了便于进一步研究,让我们将这些数据整合到一个 200 行的数据框架中,该数据框架为每批数据编译三个动态变量的序列(100 个数据点):
综合数据框
图片作者
让我们随机选择 20 个批次,显示变量的动态,看看它们的轮廓是什么样的(每种颜色对应一个批次):
20 个不同批次的动态变量样本
作者图片
从动态变量中提取功能特征
我们可以观察到“ Dyn_Input_1 ”具有线性轮廓。
作者提供的 20 个不同批次
图像的“Dyn_Input_1”样本
现在的问题是:“这些配置文件中的每一个与初始条件有什么关系?
由于我们不能直接比较初始条件(2 个值)和“Dyn_Input_1”行为(100 个连续事件),我们需要找到一个代理!
在这种情况下,我们可以对每一批应用线性回归,并提取相应的系数。由于所有事件都从(0,0)坐标开始,因此只有斜率(a1,a2,…)会带来相关信息。
动态变量的行为及其对应的线性方程
作者图片
作者使用 Dyn_Input_1 系列、系数和分数的合并数据框架
图片
一旦提取了这两个特征(线性回归系数和相应的分数;上面最后两列),我们高兴地看到系数和初始条件#2 之间的相关性非常强: 0.996 :
这意味着,如果我们知道初始条件#2 的值,我们就能够推断出动态输入#1 的相应斜率(=系数),并最终推断出 100 个连续事件的值。
到目前为止,一切顺利😀
动态输入#2 有一个稍微复杂一点的轮廓:第 n 根。
作者提供的 20 个不同批次
图像的“Dyn_Input_2”样本
与动态输入#1 一样,我们需要找到一个比 100 个数据点序列更简单的代理来表达每一批的行为。
我们仍然可以依赖线性回归,但是首先,需要对序列进行转换:我的方法是对时间=0 到值达到预定义阈值 0.00003 之间的部分进行“根转换”,如下例所示:
n 次根变换对原始 Dyn_Input_2 变量(双标度)的影响
作者提供的图像
为了定义这个阈值,我查看了 200 条曲线,并确定了大多数曲线(如果不是全部的话!)开始渐近。该“根部截面极限”范围在 7(最小值)、14(中值)和 43(最大值)之间:
根节限上 200 批次
图片作者
应用变换后,我们提取每个模拟的回归系数和截距,并检查这些特征和初始条件之间是否存在相关性:
作者使用 Dyn_Input_2 系列、系数和分数
图像合并数据框架
我们可以观察到,动态输入#2 的斜率也与初始条件#2 高度相关( 0.995 ),并且其截距与初始条件#1 相关( 0.84 )。至于动态输入#1,我们现在可以从唯一的初始条件值中推导出动态输入#2 的行为。
动态输出#1 具有第三种类型的曲线:在时间=0 和时间=0.1001 之间急剧增加之后,它是具有小负斜率的线性曲线:
20 个不同批次的“Dyn_Output_1”样本
作者提供的图片
我们可以用同样的方法提取 3 个相关特征:
- 初始值(时间=0 时)
- 系数和截距的线性行为从时间=0.1001
作者使用 Dyn_Input_1 系列、系数和分数
图像合并数据框架
同样,我们可以观察到初始条件#2 和第三个动态变量之间的强相关性。
动态变量与初始条件和模型建立的总体相关性
既然提取了每个动态变量的特征,并且建立了与初始条件的相关性,我们可以为每个动态变量创建一个线性模型:
为了使这些代理模型更容易访问,我们可以创建一个“SurrogatePrediction”类,它有 3 种不同的方法,可以根据我们提供的初始条件生成预测的时间序列。
让我们选择两个随机初始条件,直观地比较替代模型预测和地面真实情况:
Dyn_Input_1(预测与真实) —作者图片
Dyn_Input_2(预测与真实) —作者图片
Dyn_Output_1(预测与真实) —作者图片
结论
我们现在拥有三个代理函数,它们只能通过它们的系数/截距来表达,并且可以模拟原始进程的行为方式,而不会暴露其核心设计。
它们是用 Python 开发的,但可以很容易地转换成其他格式,因为它们只是简单数学方程的组合!
任务完成!😀
注意:有人可能会说,这种模型可以更容易地用随机森林或梯度增强树这样的算法来实现。这是真的,我自己测试过(包含在 GitHub 库中)。由于训练集和测试集之间良好的同质性,验证分数超过 99%。然而,缺点是像系综树这样的“复杂”模型很难用另一种语言或仅通过方程来移植。
再次感谢巴蒂斯特·博伊特🙏早在我之前就理解了这种方法对于制造/加工行业以及其他行业来说是一个至关重要的话题!
相应的代码存储在这里:
https://github.com/pierrelouisbescond/surrogate_model_demo
请不要犹豫,浏览我在 Medium 上的其他文章:
https://pl-bescond.medium.com/pierre-louis-besconds-articles-on-medium-f6632a6895ad
通过实施了解 t-SNE
原文:https://towardsdatascience.com/understanding-t-sne-by-implementing-2baf3a987ab3?source=collection_archive---------18-----------------------
t-SNE 是如何工作的以及如何实施的
图片作者。
在这篇博文中,我们将探究 t-SNE 算法的内部工作原理,清楚地理解它是如何工作的,它可以用来做什么,以及它的局限性是什么。我将采用自上而下的方法,首先在更高的层次上更一般地解释算法是如何工作的,然后更深入地探究它背后的数学。这篇文章在大部分有等式或计算的地方都包含代码块,因为有些人通过代码理解概念比数学更容易。整篇帖子也是笔记本,可以下载。
介绍
t-SNE 是一种用于可视化高维数据的算法。因为我们无法想象任何超过二维——也许是三维——的东西,所以 t-SNE 通过减少数据中的维数来做到这一点。这样做的同时尽可能地保留数据的结构。如果我们比较 SNE 霸王龙和主成分分析,我们会发现主成分分析试图保留数据中的信息,而 SNE 霸王龙则试图保留数据中的相对距离和聚类结构,因此较少考虑保留的总信息。
一般程序
因为我们的目标是降低数据的维度,所以让我们从一个简单的例子开始,看看将二维数据降低到一维会是什么样子。
从 2D 到 1D 的 SNE 投影。图片作者。
如您所见,该算法的输出不仅仅是到 x 轴的投影,它还会转换维度,以便尽可能保持相似和不相似数据之间的相关性。
如果你看一下下面的 GIF,你就能明白这个过程是如何发生的。在算法的每次迭代中,相似的数据点被拉到一起,而不相似的点被推开。这意味着,通过足够的迭代,算法应该以与点的自然结构相似的方式对点进行聚类。
t-SNE 迭代过程的结果。图片作者。
数学
现在让我们看看算法实际上是如何工作的,以及它背后的数学原理。首先,我们需要能够确定一对数据点是否相似。为此,我们首先计算每一对点之间的欧几里德距离。
然后,我们通过下面的过程来计算相似性:对于每个数据点,我们将它放在高斯曲线的中间,其余的数据根据它们的距离沿着曲线的其余部分。这意味着更靠近中间的点与选择的点相似,而边缘的点则非常不同。
这反映在下面的公式中,该公式基本上是归一化的高斯分布;
你可能想知道,我们如何选择标准差(sigma)?这不是我们直接选择的,而是通过设置一个叫做困惑的东西;其定义为,
基本上,困惑反映了我们对数据密度的看法。困惑的最佳值实际上无法通过分析来计算。因此,我们通常需要尝试不同的值,并试图找到提供最佳结果的值。困惑的最佳值通常在 5 到 50 之间。
通过我们设置的困惑,算法通过做二分搜索法来选择与之对应的 sigmas。
既然我们现在知道如何找到原始高维状态数据之间的相似性,我们需要对其低维表示做同样的事情。这样,我们将能够确保在原始结构中靠得很近的数据在投影中也靠得很近。
这是一个与前一个非常相似的过程,唯一的不同是,我们将使用一个学生的 t 分布,其中有一个自由度,而不是使用高斯分布。
这种分布非常类似于高斯分布。只是边缘高一点,中间低一点。
t-Student(蓝色)和高斯(灰色)分布。图片作者。
我们现在知道如何计算高维和低维空间的相似性。接下来,我们将进行迭代过程。这将通过使用梯度下降步进并选取数据的越来越好的表示来完成。
但为了能够计算梯度,我们需要一个成本函数——这意味着一种检查低维数据结构是否准确代表高维状态的方法。因为我们基本上将比较两个分布,所以我们使用 Kullback-Leibler 散度来进行比较。
我不会在这里展示获得梯度的导数。如果你感兴趣的话,我建议你查看一下原始论文中关于这个算法的附录。如果你经历这个过程,得到的梯度如下:
至此,梯度下降程序基本上和往常一样。然而,我们将在这里使用动量,以使开始时的学习快一点。这只是一个简单的阶跃函数。
只剩下一件事我还没告诉你。也就是所谓的拥挤问题。这个问题的要点是,因为我们减少了维度的数量,我们能够在这些维度中表现的东西也减少了。为了理解这一点,想象一个正方形,它的每条边都是一个数据点。现在试着在一维空间中表示这四个点。你应该会看到你将会得到几个结果的组合,但是没有一个感觉是正确的,因为你不能代表它们到另外两个点的距离都是相等的。这基本上就是拥挤问题。为了解决这个问题,我们设定
现在我们知道了实现 t-SNE 算法的一切。
结果
我们可以在MNIST 数字数据集上快速运行它,并看到它确实将不同的数字聚集在不同的簇中,这正是我们希望看到的。
MNIST 的 t-SNE。图片作者。
但是现在让我们生成一些数据来检查它如何在不同的结构上工作。我将只生成二维数据,并在 t-SNE 上运行,以获得二维表示。虽然这实际上没有意义,但我在这里这样做了,这样我们就能够可视化结果,并且更容易检查它们。
第一,距离不同。如果您查看下面的结果,您会发现并非所有结果都保留了聚类之间的距离。这表明选择正确的困惑以尽可能保持原始结构的重要性。
不同班级之间的距离不同。图片作者。
接下来,我们尝试不同密度的集群。这里,我们看到 SNE 霸王龙创造的星系团的密度变得差不多了。这样做的原因是,当我们计算相似性时,我们将结果归一化。这导致簇具有相似的大小,尽管它不是原始数据的样子。
不同密度的数据。图片作者。
我们还可以看到,该算法可以区分一个集群内的密集区域作为不同的集群,这是非常令人印象深刻的。但是,请注意,困惑集将改变结果,因此我们需要通过困惑来表示我们对数据的了解,或者尝试不同的值来比较结果。
不同密度的数据。图片作者。
最后,再举一个例子,主要是因为视觉上看起来很酷。尽管如此,如果您查看由 50 个困惑获得的结果,您可以看到,与其余的数据点相比,聚类的中间部分被推出更多。这是由于这些区域更加密集,因此推拉效应变得更大。
如果你有兴趣看更多 t-SNE 在不同数据结构及其限制上的结果,我建议查看distilt . pub。
图片作者。
最后,我们可以比较 SNE 霸王龙和主成分分析的结果,清楚地看到 SNE 霸王龙的目标是对数据进行聚类,因此在尝试对数据进行聚类时,可视化更加有用。
主成分分析和 t-SNE 的比较。图片作者。
结论
我们通过代码看到了 SNE 霸王龙是如何工作的。如果你想把这篇文章作为笔记本下载,你可以在这里得到它。我们还看到 t-SNE 比 PCA 有不同的用途。虽然它们都降低了数据的维度,但它们的方式非常不同。因此,在使用 SNE 霸王龙之前,我们应该仔细考虑它的缺点。
通过多标签分类+ VGG-19、Inceptionv3、AlexNet 和迁移学习了解亚马逊雨林
原文:https://towardsdatascience.com/understanding-the-amazon-rainforest-with-multi-label-classification-vgg-19-inceptionv3-5084544fb655?source=collection_archive---------21-----------------------
法比奥·菲斯塔罗尔在 Unsplash 上的照片。
人工智能对生态系统保护的力量
目录
一.导言
- 亚马逊生态系统的现状
- 人工智能的潜力
二。了解数据集
三。计算机视觉;Conv 网络架构
- 多标签分类
- VGG-19
- AlexNet
- Inceptionv3
- 迁移学习
四。亚马逊卫星芯片图像 ML 分类模型
- 数据可视化/探索性分析
- 预处理
- 模型
- 模型性能比较
动词 (verb 的缩写)结束语
亚马逊雨林:郁郁葱葱的绿色植物和生物多样性孕育了地球上丰富的动植物。密集而充满生命,亚马逊的功能不仅仅局限于成为一个迷人的生物群落。亚马逊是一个重要的碳汇;从空气中吸收超过 20 亿吨或 5%的年度碳排放量。
亚马逊还提供了一个自然资源的宝库,包括运输和流经亚马逊河的淡水、有价值的矿物质、全球粮食供应、具有特殊性能的可用于治疗疾病的药用植物。为了量化亚马逊植物群对医学的影响:今天使用的所有药物中有 25% 来自亚马逊,巴西亚马逊地区的 41 种植物可用于治疗疟疾,在亚马逊雨林中发现了 70%具有抗癌特性的植物。大自然的药房位于亚马逊雨林中。
亚马逊是设计出来的,注定要被人类的贪婪所毁灭。
在农业、牧场、城市发展、伐木和采矿的包围下,亚马逊的效用正在被耗尽。所有的雨林资源、美景和奇迹都被从 550 万公里的丰富生命中榨干了,所有依赖亚马逊的人都被晾在一边。更令人不安的是,对亚马逊的破坏正在将更多吨的碳送入迫在眉睫的气候变化之口,并加剧了一个积极的反馈循环:森林砍伐增加了亚马逊的温度,干燥了植被,随后培育和促进了更多的森林火灾。
为了减轻对亚马逊的进一步破坏,关键是:
- 加强监管,完善或起草符合生态系统最佳利益的政策。
- 自动监控人员活动和操作。(人工智能进入了等式。)
- 了解根本原因和问题。所有的解决方案都是从理解问题开始的。揭开亚马逊雨林土地使用背后的秘密是一个很好的起点,标志着解决雨林破坏的整体问题。
利用人工智能的力量,我们可以通过卫星图像和计算机视觉应用程序更好地了解亚马逊地区的人类活动,并相应地加强监管。
了解数据集
数据集由 P lanet 提供,并提出了一个多标签分类问题,其中卫星图像芯片必须根据其大气条件和土地使用情况进行标记。
数据集包括一个 train_csv 文件,标签位于该文件中,图像芯片位于 train/test-jpg 下。
图像芯片来自太阳同步轨道和国际空间站轨道上的 4 波段卫星。
这些标签并不相互排斥,可以分为:人工采矿、常规采矿、半多云、居住、裸地、开花、选择性伐木、道路、耕作、水、农业、霾、初级、排污、多云、清洁和/或刀耕火种。
该数据集可在以下位置找到:
https://www.kaggle.com/c/planet-understanding-the-amazon-from-space/overview
计算机视觉;Conv 网络架构
计算机视觉是机器学习的一个子集,属于人工智能的广阔领域,允许计算机看到并学习对图像的高级理解。
“在抽象层面上,计算机视觉问题的目标是使用观察到的图像数据来推断关于世界的一些事情。”
— 计算机视觉:模型、学习和推理,2012 年。
计算机视觉的过程模仿人类视觉系统;该领域旨在教会计算机接受视觉输入数据、处理数据和输出结果的复杂性。作为人类,我们不需要太多的思考或努力就可以在飞行中完成这项任务,但当试图将这种能力赋予机器时,这就变成了一项复杂得多的任务。
近年来,卷积神经网络改变了这个领域:卷积神经网络是一类专门为视觉图像应用而设计的神经网络。
卷积神经网络由两个主要部分组成:
- 特征提取
这是网络的一部分,其中模型对图像数据应用一系列操作,主要目标是从图像中获取特征*。
协作执行这些操作并提取特征的卷积神经网络的层是:
- 卷积→特征提取的第一层。卷积层将滤波器应用于输入图像,以便学习图像特征。
- 池化→然后将对卷积图层的要素地图输出进行缩减采样。因此,池层的主要功能是空间维度减少。这里,应用了汇集操作,以便在特征图中仅突出显示最显著的特征。
- 展平→全连接图层之前的图层,将汇集的要素地图输入展平为一维数组;然后,该输出将被传递到全连接层。
*让我们能够识别的图案、线条和物体特征。
2.分类
卷积神经网络的这一部分负责将图像分类成一个或多个预定类别。这因任务而异:常规图像多分类意味着将整个图像分类到其中一个类别中,语义分割在更细粒度的级别上工作,将图像中的所有像素分类到一个类别中,这同样取决于数据。
这里使用的卷积神经网络的层:
- 全连接层→卷积神经网络中的最后一层。全连接层基于每个类别的概率生成输入图像的最终预测。
如前所述,数据集是一个多标签分类问题。与将图像分组在多个类别的之一下的多分类不同,在多标签分类中,一些图像可能只属于一个目标值,而其他图像可能占两个、三个、四个甚至全部十七个目标值。
完全披露:在此之前,我从未处理过卫星图像数据。出于对哪些卷积神经网络架构最适合卫星图像的好奇,我决定试验一些常见的卷积神经网络架构,并比较每个模型的性能。
使用的卷积神经网络架构:
- VGG-19
VGG-19 是视觉几何组开发的卷积神经网络架构;在被评为 2014 年 ILSVRC 分类任务的亚军后,它在计算机视觉社区中变得更加精通。它经常与 VGG-16 联系在一起,不同之处在于 VGG-19 有 19 层可训练重量,而不是 16 层,因此得名。
VGG-19 建筑的亮点:
“使用具有非常小(3 × 3)卷积滤波器的架构,这表明通过将深度推至 16–19 个重量层,可以实现对现有技术配置的显著改进。”—用于大规模图像识别的超深度卷积网络
最初的作者在他们最初的研究论文中对架构的配置进行了更深入的研究。
- AlexNet
AlexNetGeoffrey E. Hinton 的作者是 Alex Krizhevsky、Ilya Sutskever,他以巨大的误差赢得了 ILSVRC 2012 竞赛,并被认为刺激了卷积神经网络的普及。
该架构的特征包括:
- 架构层包括 5 个卷积层和 3 个最大池层。
- 使用的激活函数是 Relu 而不是 Tanh,这引入了非线性并提高了训练速度。
- 重叠最大池用于降低错误率。
- 该架构还在完全连接的层之后利用了丢弃层,以避免过度拟合的问题。
3.开始 v3
Inceptionv3,顾名思义,是 Inception 卷积神经网络的第三个变体。Inceptionv3 建立在其前身 Inception 和 Inceptionv2 的基础上。
这是盗梦空间模型及其论文的时间表:
Inception→Inception 的设计突出了在不牺牲计算资源的情况下增加网络的宽度和深度。
在这里看论文。
Inceptionv2 →在《重新思考计算机视觉的盗梦架构》中引入的第二个盗梦变体。
“我们正在探索扩大网络规模的方法,目的是通过适当的分解卷积和积极的正则化,尽可能有效地利用增加的计算。”—重新思考计算机视觉的初始架构
在这里看论文。
Inceptionv3 层:
- 盘旋
- 平均池
- 最大池
- 拒绝传统社会的人
- 全连接的
与 Inceptionv2 相同的论文。
迁移学习的概念
迁移学习是机器学习中使用的一种方法,来自一个预先训练好的模型的知识(可学习的参数,如权重和偏差)可以在另一个模型中利用,其好处是:
- 更快的训练时间
- 在数据有限的应用中提高性能。
- 更好的泛化;防止过度拟合。
简而言之,这是使用一个已经在特定数据集上训练过的模型,现在可以应用于另一个问题。
一般来说,迁移学习最适合在您拥有的数据有限且数量稀少,或者问题出在模型先前训练的数据领域时使用。
Keras 提供深度学习图像分类模型,其权重经过预先训练,可用于迁移学习。可以使用流行的卷积神经网络架构,如 Xception、VGG16、VGG19、ResNet50、Inceptionv3、DenseNet121、EfficientNetB7 等。
亚马逊雨林卫星图像多标签模型
数据可视化总是一个好的起点。如果执行正确,探索性数据分析可以提取关键见解,然后用于设计与数据一致的模型。比如:数据有限吗?那么迁移学习可能是个好主意。缺失了很多价值观?特征工程可能会有所帮助。这一阶段的过程是为了更好地理解机器学习的关键:数据。
**image_name tags**0 train_0 haze primary
1 train_1 agriculture clear primary water
2 train_2 clear primary
3 train_3 clear primary
4 train_4 agriculture clear habitation primary road
5 train_5 haze primary water
6 train_6 agriculture clear cultivation primary water
7 train_7 haze primary
8 train_8 agriculture clear cultivation primary
9 train_9 agriculture clear cultivation primary road(40479, 2){'habitation', 'clear', 'cultivation', 'slash_burn', 'bare_ground', 'artisinal_mine', 'road', 'primary', 'selective_logging', 'conventional_mine', 'partly_cloudy', 'agriculture', 'water',
'cloudy', 'blow_down', 'haze', 'blooming'}
训练 csv 文件中有 40479 个值,打印了 17 个标签。
# values with one label
cloudy
cloudy
cloudy
cloudy
cloudy
cloudy
cloudy
[...]# values with six labels
agriculture clear habitation primary road water
blooming clear cultivation habitation primary slash_burn
agriculture clear habitation primary road water
agriculture bare_ground clear habitation primary road
agriculture clear cultivation habitation primary road
agriculture clear cultivation habitation primary road
[...]# values with nine labels
agriculture clear cultivation cultivation habitation primary road slash_burn water
agriculture artisinal_mine clear conventional_mine cultivation habitation primary road water
[...]
注意:该数据集不包含任何标签数超过 9 的图像。
现在有了每个标签的值的数量,我们可以绘制分布图来检查类别不平衡。
根据分布图,大多数图像有 2、3 或 4 个标签。
将图像可视化也是一个好主意,这样可以了解模型预测的中心内容。
数据预处理
要对数据进行预处理,首先要读入图像。数据集提供 40479 个值,但是为了加速训练;我读入了 20,000 个值,将 16,000–4000 个值用于培训和验证。
图像被加载到规范化的 NumPy 数组中。现在加载目标值或 y 值。同样,这是一个多标签分类问题,因此对于一些图像会有不止一个标签。如前所述,我将数据分成 16,000-4,000 份进行训练验证。
array([[0, 0, 0, ..., 0, 0, 0],
[1, 0, 0, ..., 0, 1, 0],
[0, 0, 0, ..., 0, 1, 0],
...,
[1, 0, 0, ..., 0, 1, 0],
[0, 0, 0, ..., 0, 1, 0],
[0, 0, 0, ..., 0, 1, 0]])
模型
VGG-19 —使用顺序 API
AlexNet —使用顺序 API
Inceptionv3 +迁移学习—功能 API
模型性能比较
图片作者。
这里需要注意的是,我调整了模型的大小,并根据 VGG 的图像尺寸进行了训练——从 19 到 32 乘 32,而不是 128 乘 128。VGG-19 的预计到达时间大约是 4 个小时,我想加快训练的速度。
值得注意的是,训练精度都在接近的范围内,但是验证精度存在差异。
看一看图表,很难确定谁是赢家;然而,Inceptionv3 +迁移学习模型有进一步提高验证准确性的潜力。名义上,我将宣布 Inceptionv3 +迁移学习在使用整体观点(培训 acc、验证 acc 和培训速度)的三者中表现最好。
结束语
好吧,我承认,我以“使用这个数据集很有趣”结束了这些机器学习项目中的每一个,但这一个尤其开启了对人工智能的更深层次的欣赏。
我开始这个项目是出于好奇,想了解更多关于土地使用的知识,但最终也了解了雨林的所有不同功能。这就是处理不熟悉的数据的美妙之处,你最终会增加一些你自己的个人知识。
人工智能的现实应用总是最令人兴奋和敬畏的。提高地球上的生活质量应该是我们建设、发明和创造的首要原因;否则,这些任务很快就变得毫无意义。我会在未来寻找更多真实世界的影响数据集;如果你有,请在评论中链接它们!我很想探索它们。
查看我的其他作品,并在 LinkedIn 上与我联系:
月球岩石地貌分割用 U -Net
用 LeNet-5 进行星系多类影像分类
利用 K-Means 对鸢尾花类型进行分类
*参考文献已被超链接!
从 Scikit learn 了解混淆矩阵
原文:https://towardsdatascience.com/understanding-the-confusion-matrix-from-scikit-learn-c51d88929c79?source=collection_archive---------5-----------------------
混淆矩阵输出的清晰表示
sklearn 的混淆 _ 矩阵默认输出是什么?作者图片
介绍
在我最近的一个项目中——一个交易监控系统生成了许多误报警报(这些警报随后由调查团队进行人工调查)。我们被要求使用机器学习来自动关闭那些错误的警报。机器学习模型的评估标准是一个度量标准负预测值,这意味着在该模型的所有负预测中,它已经正确识别了多少个案例。
NPV =真负值/(真负值+假负值)
假阴性的成本非常高,因为在这些情况下,我们的模型说它们不是欺诈性的,但实际上,它们是欺诈性的交易。
为了付诸行动,我会快速显示混淆矩阵,下面是 jupyter 笔记本的输出。我的二元分类模型是用 target = 1(欺诈交易)构建的,所以 target= 0(非欺诈交易)。
cm = confusion_matrix(y_test_actual, y_test_pred)
print(cm)----- Output -----
[[230, 33]
[24, 74]
根据你如何解释混淆矩阵,你可以得到 90%或 76%的净现值。因为—
TN = cm[0][0]或 cm[1][1] ie。230 或 74
FN = cm[1][0] ie。24
维基百科表示法
我参考了维基百科上的混淆矩阵表示法。
来自维基百科的混淆矩阵
这张来自维基百科的图片显示,预测的标签在水平方向,而实际的标签在垂直方向。这意味着,
TN = cm[1][1] ie。76
FN = cm[1][0] ie。24
净现值= 76%
Sklearn 表示
Scikit learn 文档称 —维基百科和其他参考资料可能使用不同的轴约定。
哦等等!文档没有提到任何明确的东西,不是吗?他们说维基百科和其他参考资料 可能 对坐标轴使用不同的约定。
**您所说的“可能对轴使用不同的约定”是什么意思?**我们已经看到,如果您对轴使用错误的约定,您的模型评估指标可能会完全偏离轨道。
如果你通读文档,并接近底部,你会发现这个例子
tn, fp, fn, tp = confusion_matrix([0, 1, 0, 1], [1, 1, 1, 0]).ravel()
在这里,他们拉平了矩阵输出。在我们的例子中,这意味着,
TN = cm[0][0] ie。230
FN = cm[1][0] ie。24
净现值= 90%
理解混淆矩阵的结构
清楚地理解混淆矩阵的结构是最重要的。尽管您可以直接使用该公式来衡量大多数标准指标,如准确度、精确度、召回率等。很多时候,您需要计算阴性预测值、假阳性率、假阴性率等指标,这些指标在开箱即用的软件包中是不可用的。
现在,如果我让你为混淆矩阵选择正确的选项,这是混淆矩阵的输出。你会选哪一个?
混淆矩阵上的混淆。作者图片
你的答案是“ A ”因为维基百科是这么说的,还是“ C ”因为 sklearn 文档是这么说的?
让我们找出答案
考虑这些是您的 y_true 和 y_pred 值。
y_true = [0, 1, 0, 1, 0, 1, 0]
y_pred = [1, 1, 1, 0, 1, 0, 1]
通过查看给定的列表,我们可以计算出以下内容:
TP(真正)= 1
FP(假阳性)= 4
TN(真负值)= 0
FN(假阴性)= 2
对于用于二进制分类的经典机器学习模型,您通常会运行以下代码来获得混淆矩阵。
**from** **sklearn.metrics** **import** confusion_matrixconfusion_matrix(y_true, y_pred)
混淆矩阵的输出
如果我们把它填充回混淆矩阵,我们得到混淆矩阵如下
因此正确答案是“D”
cm = confusion_matrix(y_true, y_pred)
print (cm)--- Output ---
[[0,4]
[2,1]]which translates to this: predicted
0 1
----- -----
0| 0 | 4
actual ----- -----
1| 2 | 1
TN(真负值)= cm[0][0] = 0
FN(假阴性)= cm[1][0] = 2
TP(真正)= cm[1][1] = 1
FP(假阳性)= cm[0][1] = 4
参考原始图像。选项 D 是默认输出。作者图片
然而,如果你要添加一个简单的参数“标签”。
cm = confusion_matrix(y_true, y_pred, labels=[1,0])
print (cm)--- Output ---
[[1,2]
[4,0]]which translates to this: predicted
1 0
----- -----
1| 1 | 2
actual ----- -----
0| 4 | 0
TP(真正)= cm[0][0] = 1
FP(假阳性)= cm[1][0] = 4
TN(真负值)= cm[1][1] = 0
FN(假阴性)= cm[0][1] = 2
参考原始图像。选项 C 是可以通过参数“label”得到的
结论:
来自 sklearn 的混淆矩阵的默认输出的正确表示如下。水平轴上的实际标签和垂直轴上的预测标签。
- 默认输出
#1\. Default output
confusion_matrix(y_true, y_pred)
2.通过添加 labels 参数,您可以获得以下输出
#2\. Using labels parameter
confusion_matrix(y_true, y_pred, labels=[1,0])
感谢阅读!
- 如果你喜欢这个,请在 medium 上关注我。
- 你们的掌声对写更多、写得更好是一个巨大的鼓励和帮助。
- 有兴趣合作吗?我们在 Linkedin 上连线吧。
- 请随意写下您的想法/建议/反馈。
- Github 链接
了解协方差矩阵
原文:https://towardsdatascience.com/understanding-the-covariance-matrix-92076554ea44?source=collection_archive---------1-----------------------
基本原则
关于方差、标准差、相关性和协方差,你需要知道的就是
艾莉娜·格鲁布尼亚克在 Unsplash 上的照片
L 线性代数是机器学习的基础之一,被认为是*‘数据的数学’*。虽然我个人喜欢线性代数的许多方面,但有些概念一开始并不容易掌握。我经常努力想象一些概念的实际应用或实际好处。
然而,协方差矩阵却讲述了一个完全不同的故事。
协方差和相关性的概念使线性代数的某些方面变得生动。像 PCA 这样的算法在很大程度上依赖于协方差矩阵的计算,协方差矩阵在获取主成分中起着至关重要的作用。
在接下来的部分,我们将学习协方差矩阵,如何计算和解释它。但首先,我们需要了解相关的概念,基础知识,让我们有更深入的了解。
什么是相关性,它告诉我们什么?
相关性分析旨在识别变量之间的共性。
让我们想象一下,我们从一个随机的人群中测量变量*【身高】和【体重】*。一般来说,我们会认为高个子比矮个子重。这种关系的散点图可能如下所示:
身高和体重变量的散点图[图片来自作者]
通过观察上面的图,我们可以清楚地看出这两个变量是相关的。相关性,或者更确切地说是相关系数,为我们提供了一种统计方法来量化这种关系。
该系数的范围从负 1 到正 1,可以解释如下:
- 正相关 — 告诉我们两个变量的移动方向相同,例如两个值同时增加。
- 负相关 — 描述负相关变量。也就是说,如果一个变量增加,另一个就减少,反之亦然。
- 相关系数为零表示完全没有关系。
注:相关系数仅限于线性,因此不会量化任何非线性关系。为了测量非线性关系,可以使用其他方法,如互信息或转换变量。
那么我们为什么还要关心相关性呢?
原来,相关系数和协方差基本上是相同的概念,因此密切相关。相关系数只是限定在范围[-1,1]内的协方差的归一化版本。
这两个概念依赖于相同的基础:方差和标准差。
引入方差和标准差
方差作为离差的一种度量,告诉我们数据值有多么不同或多么分散。
我们可以通过取每个数据值和平均值之间的平方差的平均值来计算方差,从广义上讲,平均值就是每个数据点到中心的距离。
通过观察这个等式,我们已经可以知道,当所有数据值都接近平均值时,方差将会很小。如果数据点远离中心,方差会很大。
让我们来看两个例子,让事情变得更具体一些。
小方差与大方差数据的例子[图片由作者提供]
一旦我们知道了方差,我们也就知道了标准差。它就是方差的平方根。
现在我们知道了基本的概念,我们可以在下一节中把事情联系起来。
协方差和协方差矩阵
假设我们有一个包含两个要素的数据集,我们想要描述数据中的不同关系。协方差的概念为我们提供了这样做的工具,允许我们测量两个变量之间的方差。
我们可以通过稍微修改之前的方程来计算协方差,基本上是计算两个变量之间的方差。
如果我们之前的意思是将我们的数据居中,我们可以将等式简化为如下:
简化后,我们可以看到协方差的计算实际上非常简单。它只是包含数据的两个向量的点积。
现在想象一下,一个数据集有三个特征 x、y 和 z。计算协方差矩阵将得到一个 3x 3 的矩阵。该矩阵包含每个特征与所有其他特征及其自身的协方差。我们可以这样想象协方差矩阵:
基于从头开始实施 PCA 的示例
协方差矩阵是对称的,并且逐个特征地成形。对角线包含单个要素的方差,而非对角线条目包含协方差。
我们已经知道如何计算协方差矩阵,我们只需要将上面等式中的向量与以平均值为中心的数据矩阵进行交换。
一旦计算出来,我们就可以用前面我们学习相关系数时描述的相同方式来解释协方差矩阵。
运用我们的知识
既然我们已经完成了基础工作,让我们应用我们的知识。
出于测试目的,我们将使用 iris 数据集。数据集由 150 个样本组成,具有 4 个不同的特征(萼片长度、萼片宽度、花瓣长度、花瓣宽度)
让我们通过在散点图中绘制前两个特征来看一看数据。
通过绘制前两个特征对虹膜数据集进行概述[图片由作者提供]
我们的目标是*‘手动’*计算协方差矩阵。因此,我们需要先对我们的数据进行均值居中。为此,我们定义并应用以下函数:
注:我们通过减去平均值并除以标准差来标准化数据。
运行上面的代码,标准化我们的数据,我们得到了预期的平均值 0 和标准差 1。
接下来,我们可以计算协方差矩阵。
**注:**同样的计算可以用 NumPy 的内置函数 numpy.cov(x)来实现。
我们的协方差矩阵是一个 4x 4 的矩阵,逐个特征地成形。我们可以通过如下方式绘制矩阵和协方差:
协方差矩阵绘制成热点图[图片由作者提供]
通过获得高协方差或相关系数,我们可以清楚地看到不同特征之间的大量相关性。例如,花瓣长度似乎与花瓣宽度高度正相关,这在直觉上是有意义的——如果花瓣更长,它可能也更宽。
结论
在本文中,我们学习了如何计算和解释协方差矩阵。我们还讲述了一些相关的概念,如方差、标准差、协方差和相关性。
协方差矩阵在主成分分析中起着核心作用。用更人工的方法实现或计算它将许多重要的部分联系在一起,并为一些线性代数概念注入了活力。
感谢您的阅读!确保保持联系&在 Medium 、 Kaggle 上关注我,或者在 LinkedIn 上说声“嗨”
马文·兰亨克
# 30 日
View list30 stories
喜欢这篇文章吗?成为 中等会员 继续无限学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
https://medium.com/@marvinlanhenke/membership
参考资料/更多资料:
- 从零开始实施 PCA
- 迈克·科恩博士。线性代数:理论,直觉,代码。
理解神经网络的表达能力
原文:https://towardsdatascience.com/understanding-the-expressive-power-of-neural-networks-d4918c9e98da?source=collection_archive---------21-----------------------
实践教程
我一直对神经网络似乎可以学习任何东西的能力感到惊讶。AlphaGo、谷歌翻译和特斯拉 Autopilot 都使用神经网络,但用于完全不同的任务。这怎么可能呢?事实证明,有一种叫做通用逼近定理的东西证明,在一定条件下,神经网络可以以任意精度逼近任何函数。这个定理的完整陈述和证明需要一些高等数学来理解,但是我们来看一个更简单的版本,建立一些直觉。首先,我们将使用一个通用的激活函数来构建任意函数。然后,我们将演示如何用神经网络来表示我们构建的任何函数。
第一部分:从激活函数到任意函数
通用逼近定理的完整陈述涉及向量值函数。为了简化,我们将考虑标量函数。我们的目标是逼近任意函数 y = f(x),其中 x 和 y 是实数。回想一下高中微积分,任何这样的函数都可以用矩形来近似,如下所示。
y = x 的矩形近似。
矩形越窄、越多,近似值就越好:
更多的矩形,更好的近似。图片作者。
因此,如果我们能创建任意宽度和高度的矩形,并把它们放在我们想要的任何地方,我们就能逼近任何函数 y = f(x)。现在我们应该怎么做呢?
我们的第一个提示来自神经网络中常用的激活函数,tanh 函数。k = 1 的函数 y = tanh(kx)如下所示:
y = tanh(x)。图片作者。
随着 k 的增加,请注意图形的对角线部分变得越来越垂直。这里是 y = tanh(10x):
y = tanh(10x)。图片作者。
这里是 y = tanh(1000x):
y = tanh(1000x)。图片作者。
我们现在有一个矩形的左边缘。但是仍然有一些问题:我们希望图的水平部分是 0,而不是-1 和 1,而且我们还没有构造右边。幸运的是,有一种方法可以同时解决这些问题。请注意,如果我们反转(取负值)双曲正切函数并向右移动 1,我们会得到这个函数:
y = -tanh(1000(x-1))。图片作者。
现在,如果我们将这两个函数相加,我们得到:
y = tanh(1000 x)-tanh(1000(x-1))。图片作者。
我们已经实现了制作矩形的目标!现在让我们花一些时间来观察矩形函数的属性。
- 首先,除了矩形所在的地方(这里是区间(0,1)),矩形函数在任何地方都是 0。这意味着我们可以添加任意多的其他矩形函数,只要没有矩形相互重叠。
- 第二,我们可以任意调整矩形的宽度。例如,如果我们希望宽度为 2,我们的函数将是 y = tanh(1000 x)-tanh(1000(x-2))。
- 第三,我们可以任意调整矩形的高度。如果我们想要高度为 3,我们的函数将是 y =(3/2)tanh(1000 x)—(3/2)tanh(1000(x-1))。
- 最后,我们可以调整矩形在 x 轴上的位置。如果我们想要一个从 x = -1 而不是 x = 0 开始的矩形,我们的函数应该是 y = tanh(1000(x+1)) — tanh(1000x)。
我们可以用下面的规则来概括这些观察结果。如果我们想要一个矩形,其左侧为 x = s,高度为 h,宽度为 w,近似精度为 k(k 越高越精确),我们的等式为:
y =(h/2)tanh(k(x-s))—(h/2)tanh(k(x-s-w))
例如,对于一个左侧为 x = -2,高度为 2,宽度为 3,精度为 1000 的矩形,一旦您插入数字,等式就是 y =-tanh(1000(x+2))+tanh(1000(x-1))。见下文:
y =-tanh(1000(x+2))+tanh(1000(x-1))。图片作者。
现在我们有了逼近任何函数所需的工具。例如,我们可以使用三个矩形来粗略地逼近从 0 到 3 的恒等函数:
y =[(1/2)tanh(1000 x)—(1/2)tanh(1000(x-1))]+[tanh(1000(x-1))—tanh(1000(x-2))]+[(3/2)tanh(1000(x-2))—(3/2)tanh(1000(x-3))]。图片作者。
如果我们想做得更好,我们可以使用更多的矩形:
y =[(0.5/2)tanh(1000 x)—(0.5/2)tanh(1000(x-0.5))]+[(1/2)tanh(1000(x-0.5))—(1/2)tanh(1000(x-1))]+[(1.5/2)tanh(1000(x-1))—(1.5/2)tanh(1000(x-1))]+图片作者。
第二部分:从任意矩形到神经网络
下一步是找到一种方法,通过神经网络来表示我们的矩形。这被证明是非常简单的。让我们再来看看我们为任意矩形找到的公式:y =(h/2)tanh(k(x-s))—(h/2)tanh(k(x-s-w))。使用具有一个隐藏层的网络,我们可以表示这个函数:
图片作者。
该网络接收一个输入 x,并有一个针对输入层的偏置项(用正方形表示)。隐藏层有两个节点,都有 tanh 激活,没有偏置项。单输出节点没有激活功能。整个网络的权重如图所示。您可以自己验证所有的权重相加,输出确实是我们的矩形函数。
最后一个问题——如果我们想要不止一个矩形呢?解决方案很简单:对于每个额外的矩形,我们向隐藏层添加两个节点,并向输入和输出层添加适当的权重/连接。这意味着每个矩形需要两个隐藏节点来代表我们的网络。例如,我们上面看到的身份函数的六个矩形近似将有十二个隐藏节点。
把所有的东西放在一起,我们现在有一种方法,用神经网络来表示任何函数 y = f(x)和 x,y 实数。这样做的方法是将函数分解成一些矩形(矩形越多,逼近越好),并为每个矩形找到将在我们的广义矩形公式中使用的参数 h、k、s 和 w。然后,我们可以使用如上所示的找到的参数构建神经网络,对每个矩形/参数集使用两个隐藏节点。
限制
在这一点上,你可能会问——那么是什么阻碍了呢?如果任何功能都可以用神经网络来表示,为什么我们没有完美的自动驾驶汽车?为什么人工智能不跑来跑去解决世界上所有的问题?简而言之,问题在于神经网络很难训练。仅仅因为您知道应该有一组参数很好地逼近您给定网络架构的功能,并不意味着有任何好的方法来找到这些参数。训练神经网络最常用的方法是梯度下降法,这种方法在实际中对于某些任务(例如图像分类)非常有效,但是不能保证梯度下降法能够为任意函数找到正确的参数。这是一个棘手的问题,在未来我会写一些关于它。
请随时留下您的任何问题/意见!让我知道你还想看什么机器学习话题。
理解 Git 的基础知识
原文:https://towardsdatascience.com/understanding-the-fundamentals-of-git-25b5b7ded3c4?source=collection_archive---------12-----------------------
由 Roman Synkevych 在 Unsplash 上拍摄
理解在幕后操作的各种 Git 对象
Git 是一个强大的工具,但是它可能会让人不知所措,尤其是对于新手来说。即使对于有经验的开发人员来说,陷入合并或重定基础冲突也是很常见的。即使有大量的博客可用,有时也很难确定原因,最终会浪费我们的生产时间。
已经有太多的教程了,但是大部分只是简单地谈论高级用户命令、语法以及如何使用它们,抽象出了大部分内部细节。
本文试图揭示 Git 是如何工作的。但是我们为什么要为此烦恼呢?从头开始了解它是如何工作的对使用命令有很大帮助。因为它不是关于学习命令,而是关于学习概念模型。因此,我们将尝试理解命令是如何工作的,而不是学习一堆命令。一旦我们开始理解它,我们在使用命令时会越来越舒服和自信,最终,我们会开始喜欢它。此外,了解内部情况总有一种极客的快感。有了这些,我们来揭开 git 的神秘面纱。
git——一个愚蠢的内容跟踪器(如 man git 中所述)
在其核心,git 是一个简单的键值存储,一个将键映射到值的简单结构,这个结构是持久的,即它存储在我们的磁盘中。这些值只是字节序列。它可以是任何类型的内容,可以是文本文件或二进制文件等。我们可以向 git 提供一个值,git 将为它计算一个惟一的键,稍后可以使用这个键来检索内容。
作为演示,我们将使用hash-object
命令,该命令获取一些数据并返回唯一的密钥。由于hash-object
不直接操作字符串数据,我们必须通过管道输入并传递— stdin
标志让hash-object
知道。(hash-object
是管道命令之一,如果你以前没用过完全没问题)
**$** **echo** "Hello Sarah" **| git hash-object** --stdin
0e170dcd3efae4d183c78dced6c5b9c7e13f70c5
上面生成的散列将被用作存储该内容的密钥。它是使用 SHA1 算法生成的。要深入了解 SHA1,可以参考这里的。需要注意的重要一点是,对于相同的字节序列,我们每次在每个操作系统上都将得到相同的散列。对于两个不同的内容,我们几乎不可能得到相同的散列。
因此,git 存储库中的每一部分内容都有自己的散列。现在,让我们尝试将这些内容存储在 git 中,看看它是如何工作的。首先,我们必须初始化一个新的 Git 存储库:
**$** **git** **init** test
Initialized empty Git repository in /workdir/test/.git/
**$** **cd** test
**$** **ls** **-a**
**.**/ **..**/ **.git**/**$** **ls** .git/objects
**info**/ **pack**/
现在,我们有一个.git
目录来保存我们的内容。如果我们检查一下.git
目录,它有一个叫做objects
的子目录,叫做对象数据库。git 在这里保存所有用于保存内容、文件、目录等的对象。
目前,除了作为初始化的一部分创建的pack
和info
子目录之外,没有其他对象。再次使用hash-object
和-w
标志不仅会返回密钥,还会将该对象写入.git
存储。
**$** **echo** "Hello Sarah" | **git** **hash-object** **-w --stdin**
0e170dcd3efae4d183c78dced6c5b9c7e13f70c5**$** **ls** .git/objects/
**0e/ info/ pack/****$** **find** .git/objects **-type** f
.git/objects/0e/170dcd3efae4d183c78dced6c5b9c7e13f70c5
我们可以看到,git 已经存储了我们的数据。目录由哈希的前两个十六进制数字(0e
)创建。其中存在一个文件,该文件包含哈希的剩余字符。这是 git 遵循的命名方案。我们原始数据存在于该文件中。这个文件被称为 blob 数据。
blob 是一段普通的内容。Git 添加了一个小标题,并压缩了这个 blob 中的原始内容。我们可以用git cat-file
命令检查内容。传递-t
将告诉我们内容的类型,而-p
标志将打印该对象的内容。
**$** **git cat-file** 0e170dcd3efae4d183c78dced6c5b9c7e13f70c5 **-t**
blob
**$** **git cat-file** 0e170dcd3efae4d183c78dced6c5b9c7e13f70c5 **-p**
Hello Sarah
因此,git 可以获取任何内容,为其生成一个如散列中所示的键,然后将内容作为 blob 保存在存储库中。
通过进行第一次提交来了解对象数据库
我们现在将稍微深入一下对象数据库。我们将探索 git 存储的各种类型的对象是什么以及如何存储的。
git 存储的对象主要有 3 种类型:
- Blob :我们上面看到的这个对象存储了原始内容。
- 树:这个对象用于存储我们项目中的目录。
- 提交(Commit):这个对象在每次提交时被创建,并提取这个特定提交的所有信息。
让我们创建一个示例项目来深入理解每一个。一个app
项目。在它的根目录下,我们将有一个README.md
文件和一个src
目录。在src
目录中,我们有一个textfile
和hello_world.py
源文件。
**$ git init** app
**$ cd** app
**$ echo** "To demonstrate GIT objects" **>** README.md
**$ mkdir** src
**$ cd** src
**$** **echo** "To demonstrate GIT objects" **>** textfile
**$** **echo** "print('hello world')" **>** hello_world.py**$** **tree** .
.├── README.md
└── **src** ├── hello_world.py
└── textfile
1 directory, 3 files
目前,我们的 git 存储库没有提交任何东西,所以让我们进行添加这些文件和目录的初始提交。提交完成后,我们将检查objects
目录,查看创建的各种对象。
**$** **ls** **-a** .git/objects
**./** **../** **info/** **pack/****$ git add .****$ git status** On branch masterNo commits yetChanges to be committed:
(use "git rm --cached <file>..." to unstage)new file: README.md
new file: src/hello_world.py
new file: src/textfile**$ git commit -m "**inital commit, adding README and src dir**"****$ git status** On branch master
nothing to commit, working tree clean**$ git log** commit 67e94955f7d3fffd307d0f070e17d652800b503e (**HEAD -> master**)
inital commit, adding README and src dir**$** **ls** **-a** .git/objects
**.**/ **..**/ **17**/ **63**/ **67**/ **75**/ **b9**/ **info**/ **pack**/**$** **find** .git/objects/ **-type** f
.git/objects/67/e94955f7d3fffd307d0f070e17d652800b503e
.git/objects/17/14900a9b496867b319101942b690af9e4d399e
.git/objects/75/d9766db981cf4e8c59be50ff01e574581d43fc
.git/objects/63/03057f97f1cb0222d3e916c3ab471e3c06b9b2
.git/objects/b9/941014e9cc4cb12e3b1283de8846127f96e6d7
我们在提交历史中看到一个提交,但是在objects
目录中,我们看到正在创建各种对象。让我们使用git cat-file
命令逐个检查它们,从log
命令中查看的提交开始。
**$ git cat-file** 67e949 **-t** commit **$** **git cat-file** 67e949 -p
tree 1714900a9b496867b319101942b690af9e4d399e
author RachitTayal <rachit.tayal@gmail.com> 1624011001 +0530
committer RachitTayal <rachit.tayal@gmail.com> 1624011001 +0530inital commit, adding README and src dir
正如我们在上面看到的,提交对象包含一段简单而简短的文本。每当进行一次提交(使用git commit
),git 就会生成这个文本,生成它的散列,然后像存储 blob 一样存储它。提交文本包含关于提交的所有元数据。除了作者、提交者、提交日期之外,它还有树对象的散列。这个提交(171490
)指向项目的根目录。让我们获取这个树对象的内容来进一步理解它。
**$ git cat-file** 171490 **-t**
tree
**$ git cat-file** 171490 **-p**
100644 **blob** 6303057f97f1cb0222d3e916c3ab471e3c06b9b2 README.md
040000 **tree** b9941014e9cc4cb12e3b1283de8846127f96e6d7 src
就像提交对象一样,树对象也是一段文本。它包含目录中的内容列表(由哈希表示)。在这种情况下,我们有一个 blob 和另一棵树以及它们相应的名称。blob 是根目录中的README.md
文件,而树是根目录中的src
目录。
让我们再次使用git cat-file
来获取 blob 的内容。
**$ git cat-file** 630305 **-t**
blob
**$ git cat-file** 630305 **-p**
To demonstrate GIT objects
因此,blob 的内容与我们的README.md
文件中的内容相同。
总而言之,提交指向一棵树(表示根),而这棵树指向一个 blob ( README.md
文件)和另一棵树(src
目录)。blob 只是存在于README.md
文件中的一段内容。让我们快速检查另一棵树。
**$ git cat-file** b99410 **-t**
tree
**$ git cat-file** b99410 **-p**
100644 blob 75d9766db981cf4e8c59be50ff01e574581d43fc hello_world.py
100644 blob 6303057f97f1cb0222d3e916c3ab471e3c06b9b2 textfile
它有两个斑点。其中一个 blobs 存储了hello_world.py
文件的内容。而另一个 blob 存储textfile
的内容。需要注意的重要一点是textfile
和README.md
的 blob 具有相同的散列,因为两个文件的内容完全相同。因此,git 将存储一个 blob,而不是为同一个 blob 创建两个单独的副本。
整个对象数据库可以描述如下:
提交后对象的快照
第二次提交
现在,让我们在README.md
文件中做一些更改,并进行第二次提交。
**$ echo** "Added some change" **>>** README.md
**$ git add** README.md
**$ git status**
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)**modified: README.md**
**$ git commit -m** "updated README"
**$ git log**
commit 5abd2e3d6903385c2d7f646811f84decd41bcdc7 (**HEAD -> master**)
...
commit 67e94955f7d3fffd307d0f070e17d652800b503e
让我们再次使用cat-file
命令来查看第二次提交的内部。
$ **git cat-file** 5abd2e -t
commit
$ **git cat-file** 5abd2e -p
**tree** 62da8c3c87d1b7725dbcc4450d5ec25384a7614e
**parent** 67e94955f7d3fffd307d0f070e17d652800b503e
author RachitTayal <rachit.tayal@gmail.com> 1624019462 +0530
committer RachitTayal <rachit.tayal@gmail.com> 1624019462 +0530updated README
除了显而易见的字段之外,它还有一个父提交,指向前一个散列的提交。提交以这种方式链接。大多数提交都有一个父级。(异常是第一次提交)。这个提交中存在的树的散列(62da8c
)不同于第一个提交所指向的,这意味着它指向一个新的树。
检查新树的内容将得到:
$ **git cat-file** 62da8c -p
100644 blob 5ca3f4ffb43baf06df6e3fcb0a056cc6263cf32f README.md
040000 tree b9941014e9cc4cb12e3b1283de8846127f96e6d7 src
我们可以看到,它有另一棵树(src
目录)和一个 blob ( README.md
)文件。blob 不具有与前一次提交相同的散列,因为我们已经对README.md
文件添加了更改。因此创建了新的斑点。
然而,树对象与前一次提交具有相同的散列,因为没有进行任何更改,git 将重用前一个树对象。第二次提交后,对象数据库的文件结构如下所示:
第二次提交后对象目录的文件结构
至此,我们大致了解了 git 对象模型的工作原理。一旦理解了这一点,理解进一步的复杂操作,如合并、重定基础和分支策略就变得非常直观了。(我们将在下一篇文章中讨论)。
总结:
我们已经看到 git 是如何基于键值结构进行内容跟踪的。密钥基于 SHA1 算法生成的哈希。我们已经看到了各种管道命令,如git hash-object
和git cat-file
来分别生成散列和查看目标文件的内容。
接下来,我们看到了每当我们提交项目时,git 对象数据库的幕后发生了什么。它强调了整个 git 对象模型、存储在 git 中的各种类型的对象(blobs、tree、commits)以及对象在进一步提交时是如何交织在一起的。这为理解分支和合并相关操作以及各种其他高级概念奠定了基础,我们将在下一篇文章中对此进行讨论。在那之前继续探索。
用计算机视觉理解新冠肺炎对交通的影响
原文:https://towardsdatascience.com/understanding-the-impact-of-covid-on-traffic-in-singapore-with-computer-vision-852d2a94882f?source=collection_archive---------41-----------------------
实践教程
用 Python 和 OpenCV 分析新加坡的交通
照片由来自佩克斯的阿拉明·阿-达伊拍摄
ovid-19 深刻影响了我们生活的方方面面,从全球供应链到我们的工作方式。在疫情期间,大多数国家都在不同程度的限制下实施了某种形式的封锁。这些封锁的一个有趣的方面是对世界不同地区日常生活的影响,最常见的预防措施之一是留在家中的命令。新加坡作为一个人口密集的城市国家和岛屿,为观察这些影响提供了一个有趣的测试案例。这两个因素,加上强有力的政府干预,应该为这些影响提供了充分的证据。通过使用政府的交通摄像头数据库和计算机视觉,我们将试图了解城市中心附近的交通如何受到并仍然受到整个疫情的影响。
这篇文章的重点是回答以下问题:
新冠肺炎对新加坡的交通有影响吗?如果是,影响是什么,是什么造成的?
本文中的代码是用于解释目的的补充工具,已经从原始代码中进行了缩写和略微修改;这不是一次演练,而是如何解决问题的一个可能的脚手架。如果您只是对数据感兴趣,请随意跳到结果部分。
数据收集
ingapore 拥有一个令人难以置信的公共数据库,涵盖了城市及其功能的方方面面。你可以去参观:https://data.gov.sg/。该项目利用由陆路运输管理局管理的交通摄像头部分。该 API 允许用户指定时间戳,并返回城市中每个摄像机的所有数据。我们可以使用 python 中的请求库来指定时间戳,并接收一个 JSON 对象,该对象包含所有摄像机的位置和视频帧。
返回的 JSON 对象是每台摄像机和各种数据的列表,包括位置、视频帧的链接和一些关于图像的元数据。我们对三个方面最感兴趣:
- camera_id —嵌套在相机键内的相机数组中
- image:一个 URL,包含摄像机当时看到的图像
- 位置:相机的 GPS 线,嵌套在相机对象中
为此,需要对 JSON 响应进行规范化和解析。这可以通过熊猫图书馆来完成,它将用于管理我们的数据。
这将给我们留下一个 87 行 8 列的熊猫数据帧。
前十行
这个数据帧是对于给定的时间戳,城市周围的所有 摄像机的 。为了减少收集的数据量并控制范围,我们将把摄像机的数量限制为 1702 和 1711。它们位于璧山区和实龙岗区之间的 CTE 高速公路上。在主干道上,交通的任何显著变化都应该很容易被发现。下面是每个摄像机看到的一个例子。
照相机 1702 例子
照相机 1711 的例子
下一步是建立一个测量流量模式的时间框架。选择了 2019、2020 和 2021 年从 3 月 1 日到 5 月 1 日的两个月时间,以每三分钟为增量。选择这一点有三个主要原因:
- 包含三年的时间框架可以实现 COVID 之前、之中和之后的评估,其中 2019 年作为正常流量模式的示例。
- 这个时间框架在封锁方面也很重要-因为最严格的措施是在 2020 年 4 月推出的,限制将在 2021 年取消。
- 将时间范围限制为每三分钟,可以更好地管理要标记的图像数据集。
使用 pandas,可以建立批量请求的框架。首先,用 date_range 函数制作时间戳的数据帧:
其次,将时间戳格式化成可以传递给 API 的格式。
现在我们有了要循环的日期,我们可以利用并发库使用 futures 函数进行并发请求。未来的库通过创建不同的工人,使批量请求数据变得容易得多,这些工人可以彼此并行地进行请求。关于如何使用期货的一个很好的指南可以在这里找到。
下面是将要使用的功能的基本概要。Fair wairing:每个电话仍然需要大约 2 个小时才能完成。
这将产生一个包含所有响应的庞大列表。下一步是按 camera_id 列对响应进行排序,并将它们保存为各自的. csv 文件。我还建议将原始列表保存为 DataFrame,以便以后需要时可以引用。(因此,如果我们想在未来研究其他相机,我们不必重复 2019 年的 API 调用。)
2020 年和 2021 年重复这些步骤,总共留下 6 个单独的文件,每个相机 3 个。请求部分的总运行时间约为 6 小时。我们现在有了图像的链接,可以继续从数据库中抓取图像了。为了获取图像,我们将使用与之前相同的结构来进行并发调用,但是首先,加载上一步中创建的数据帧。
加载数据帧后,我们可以编写新的请求函数和并发请求框架。
关于上面的代码块及其输出,有几点需要注意。首先,我们正在抓取大量图像;所以要确保有足够的空间来存放它们。第二,每个呼叫大约需要 1.5 到 2 个小时,具体取决于定义的工作人员数量。
收集完图像后,我们就可以开始生成数据了。我们将使用 OpenCV 并利用 google 提供给 Colab 用户的 GPU 能力。为了做到这一点,我建议按照这个教程来设置 OpenCV,以便在 colab 环境中使用 GPU 来加速图像的标记。
设置完成后,多亏了 OpenCV,标记图像变得相当简单。
OpenCV_example.py 的输出
关于如何设置 detect_common_objects 函数,有一些重要的注意事项:
- 你可能已经注意到,它既没有标记图像前面的模糊汽车,也没有标记旁边的汽车。这是因为默认过滤级别为 0.5。置信度值低于 0.5 的任何对象都不会被认为可以防止误报。通过在函数调用中定义 nms_thershold,可以将该级别调整为所需的任何级别。更多信息可以在这里找到。
- 您可以使用 model 关键字修改在其中对模型进行训练的标记数据集。然而,YOLOv4 非常适合这项任务。如果你有兴趣了解更多,这里有一个 YOLOv4 结构和设计的链接。
我们的基本工作流现在已经设置好了,我们可以编写函数来处理 2019 年数据集中的所有图像,并建立一种方法来跟踪标签并将它们添加回数据帧。
接下来,我们可以使用该函数遍历收集的所有数据,并生成可用于分析的标签数据帧。下面是摄像头 1702 的 2019 年图像的通话情况。
然后,我们对每一年和每一台相机重复这一步。最后,我们准备开始做一些分析!如果您已经完成了数据采集过程,我想澄清几个可能出现的问题。
- 数据集仅限于调用 api_imageRequest 函数返回的内容。我使用了一个 try-expect 块,这样即使调用失败,它也不会抛出错误,并且不是所有的时间戳都有有效的图像可以提取。因此,您的数据集可能与我生成的数据集有所不同,但流量数据的总体趋势应该仍然相对相似。此外,抓取 2021 年的图像导致图像减少了约 35%,这很可能是在数据库方面。
- 为什么我们没有在 get_label_count 块中定义要计数的标签?我们想跟踪摩托车、卡车和任何可能在路上行驶的车辆。虽然人或其他物体有可能被计算在内,但由于每个数据集包含数以千计的图像,因此它对流量的整体趋势只会产生极小的影响。
- 下载图片时,3 月 17 日和 18 日 1711 相机的 2019 都不完整。严重缺乏白天的图像导致那些日子的数据不准确。经过调查,在此期间进行了定期维护,这可以解释异常现象。我们通过替换在数据分析部分对此进行了说明。
数据分析
在进行探索性数据分析时,记住我们在项目开始时提出的“全局”问题并使用这些问题来指导过程是很重要的。
【COVID 对新加坡的交通有影响吗?如果是,影响是什么,是什么造成的?
第一步是加载所有以前收集的数据,并开始将其聚合成我们可以使用的东西。
关于编码示例的注意事项:我们将查看相机 1711,因为它提供了一些有趣的挑战(如上所述),然而,相同的步骤应用于相机 1702 以生成本文中的图形。
在数据被加载之后,我们可以通过添加一个名为“num_cars”的新列来将标签 DataFrame 与原始数据合并,该列表示生成的标签。
我们还可以继续修改“时间戳”列,这对以后的重采样很重要。
通过运行。在我们的每个数据帧上描述(),我们可以了解我们正在处理的数据。
从该输出中得出的最重要的细节之一是 2020 年到 2021 年的计数差异。虽然大约 13k 的数据点仍然为这种分析提供了典型的流量模式,但实际上不可能比较总计数。
下一步是了解我们数据的形状,我们可以通过观察标签的频率来做到这一点。这使我们对交通模式的分布有了一个大致的了解。我们将使用 pandas 的 count_values()函数来生成这些数据。
我们使用 normalized 关键字来获得标签的比例,而不是精确的计数,然后将它们四舍五入到最接近的百分之一,以使绘制它们更容易!
一定数量汽车的车架比例
我们可以从图表中看到,2020 年和 2021 年,较大流量急剧下降,空帧或稀疏帧大幅增加。这些图表提供了一个很好的概览,并显示了很大的差异。然而,为了得出有意义的结论,处理当前数据集的一些问题是很重要的。
每年之间数据点数量的差异和偏斜分布使得很难知道到底发生了什么。我们可以对数据进行重新采样,以更好地了解整个人口,并进行时间序列分析。由于我们的数据是有时间戳的,panda 内置的重采样工具是获取时间序列的有效方法。为了处理年份之间的计数差异,我们将避免任何依赖于总计数的度量,而是使用描述数据的度量,如平均值、最大值和中值。
如上所述,2019 年的数据集存在问题。3 月 17 日和 18 日显示异常低值。我们可以使用列索引将其与数据集中的其他日期进行比较。
确定异常值是否是真实数据点的一个重要部分是查看生成它们的元素——在这种情况下,是图像。在对图像进行了一些检查之后,很明显,在那些日子里,大量的图像丢失了,而 serval 实际上是维护消息。
从数据库返回的维护消息
因为我们已经确定这两个数据点很可能不具有代表性,所以可以用几种不同的方法来解决这个缺失的数据。一种方法是尝试只在那几天再次请求映像,但是如果维护是他们捣乱的原因,这将不起作用。另一种方法是使用数据集中的其他星期日和星期一来生成值。这种方法将给出一个合适的近似值来代替缺失的数据,并且可以通过将这些天的平均值作为每个测量值的替代来实现。
准备好数据集后,下一步是可视化数据。如上所述,我们应该对数据的形状有一个概念,因为它将指导未来的步骤和统计测试。我们将使用箱线图来理解数据的形状,并使用 pyplot 的 subplot 函数来为两台摄像机生成信息丰富的紧凑视图。生成可视化后,将上下文应用到数据中以真正理解每个图表所表达的内容是很重要的。
- 中位数——这是一个很好的指标,可以衡量在任何给定的时间你在路上会看到多少辆车。
- 均值-也是在任何给定时间你期望在路上看到的东西的度量,但它更容易受到异常值的影响。
- max——当天一帧中的最大汽车数量,这是衡量交通高峰的一个很好的指标。
我们可以收集到一些东西(新冠肺炎)在 2020 年引起了巨大的变化,展开数据:每个指标都有总体下降的趋势。平均值的线形图可用于观察这一趋势。
理解数据
很明显,这两个地点在 4 月 7 日左右显示出 2020 年的急剧下降,这与总理的“电路中断”相吻合,该中断大大限制了旅行,并呼吁所有个人限制在公共场所聚集。每个摄像头都显示,除了 4 月 27 日星期一之外,本月剩余时间的平均流量大幅减少了 50%。虽然当天没有重大新闻或事件,但数据与其他周一一致。这一减少证明了疫情及其相关政策极大地减少了交通流量。
交通流量似乎还没有恢复到 2021 年疫情之前的水平。这个假设可以用单侧韦尔奇 T 检验来检验。这个统计测试将有助于了解每年的流量水平是否实际上在变化,并且不在变化范围内。我们将测试数据集的平均值(道路上汽车的平均数量)和最大值(高峰业务),以了解全貌。Scipy 库的。ttest_ind() 函数提供了一种简洁的方法。
运行 T-test 函数会给出两个输出:T-stat 和 P-value。T-stat 表示两个样本组差异的方向和水平,P 值表示确定性水平。在这种背景下,负 T-stat 意味着 2021 组小于 2019 组。确定性是 P 值减 1,或我们确定存在差异的程度。确定性值> 95%被认为是显著的。将所有这些放在一起,对于每个测量,两组在每帧的平均汽车数量以及最大数量方面显示出统计上的显著差异。
在该项目中,两个交通摄像头与 OpenCV 结合使用,以了解新冠肺炎疫情对新加坡交通的影响,包括 2020 年 4 月交通流量减少 50%,以及统计测试,以提供新加坡交通仍未恢复到疫情之前水平的证据。虽然不可能把一切都归咎于疫情,但有强有力的证据表明,疫情周围的政策和公众反应已经改变了新加坡最繁忙道路之一的交通状况。
提及和最终注释
这个项目的灵感来自于一个探索更有限的日期和时间范围的高级编码项目。这些项目是有指导的,但不会给用户任何代码,这使得它成为一种很好的实践方式,同时仍然提供了一个体面的挑战。我还想说,如果你自己做这个项目,你的数据集将很可能与我的不同,只是由于调用的数量和最终用户与数据库之间的通信。也就是说,数据的总体趋势和分布应该是相似的,因为我试图摆脱依赖于计数的测量。另外,对于那些对使用新加坡数据库感兴趣的人,你可以在这里找到条款和服务的链接!最后,感谢您花时间阅读这篇文章,我希望它能激励其他人。
理解面试官的心态
原文:https://towardsdatascience.com/understanding-the-interviewers-mindset-aacb39be64b2?source=collection_archive---------15-----------------------
如何进入面试官的思维并在数据科学工作面试中表现得更好
作者在 Canva 上创建的图片
对于求职者来说,工作面试可能看起来像是单方面的相遇。他们问,我答。我说,他们听。他们很强大,我无能为力。他们有选择,我没有。
嗯,那通常是真的。采访者处于有利地位。他们隐藏在组织的背后,你自己去面对他们。除了你的知识,你的经验,你的个性,你一无所有。你只有你自己。他们有工作。你不知道。犯一点小错误,你的命运就掌握在他们的手中。
虽然在某种程度上这是对的,但也不完全对。尽管他们通常比你占优势,但这并不是说你完全无能为力。当他们试图理解你是如何做的时候,没有人说你不被允许去理解是什么让他们做的。
一旦你明白了这一点,你会发现你可以很容易地扭转局面。你就能把面试变成双方平等的对话。这样双方都可以得到他们想要的,而没有他们不得不翻身的感觉。那比妥协好多了。毕竟,妥协被定义为让双方都不开心的解决方案。
为了避免这种情况,我在这里来看看一些让面试官更人性化的事情。在理解了他们的不安全感之后,我会深入了解他们在面试中想要什么。最后,我会给你一些关于如何准备这种数据科学面试的建议。
是什么让面试官更有人情味?
这里有一个简短的汇总表,让你有个感觉。一会儿我会详细阐述这四点。
作者创造的形象
面试官也不喜欢面试。
在那里,你们至少有一个共同点。事实是,面试官和你一样讨厌面试。因为一些其他的原因,但尽管如此,感觉是一样的。
他们不喜欢面试,因为面试会让他们脱离工作。
然而,他们知道他们不应该让他们的时间表超过他们的专业水平。你应该能理解。你压力太大,没有工作,或者离开办公室去参加面试。如果你尊重面试官的时间,你可以让他们不那么讨厌这段经历。准时参加面试。做好准备,这样你对你的工作经历、公司等的回答。,更切题,也更省时。遵循面试结构,坚持面试官引导你进入的话题。这是你应该做的。但是如果面试官忽略了这三点,那么这三点也可能成为你的危险信号。
采访者通常也没有接受过进行采访的培训。他们中的大多数人在见到你之前,只会凭借他们的经验和纯粹的责任心去谷歌“如何进行面试”。就像你会利用你以前面试的经验和阅读大量关于如何在面试中表现出色的文章一样。甚至可能是一篇关于理解面试官心态的文章。
他们和你一样,害怕自己出丑。
他们不是在寻找最优秀的人。
我的意思是,他们试图找到理想的候选人。但是现实是理想最大的敌人。事实是,在给定的环境和限制条件下,他们试图找到最佳候选人。基本上,考虑到招聘的时间和预算,他们会寻找相当优秀的人。他们会将候选人的素质与获得他们所需的时间和金钱进行比较。如果他们有一个几乎拥有他们需要的一切的人,和一个稍微好一点但需要多几倍时间和金钱投入的人,公司可能会满足于第一个候选人。
当你认为你的经验、教育和知识不够时,你应该意识到这一点。你唯一应该做的就是突出你作为候选人的所有优点。你不需要完美,只要够好就行。完美是好的敌人。
他们不知道自己想要什么。
这些公司通常不知道他们在寻找什么,确切地说他们需要什么资格等等。
例如,公司可能认为他们需要擅长数据分析的人。但并不能保证他们知道自己需要哪些技能,数据分析会用到哪些工具等等。你知道当他们问你“你认为自己五年后会怎样”时,你有多纠结吗?对他们想要的候选人没有明确的想法表明他们也在这个问题上挣扎。
当你明白这一点时,你就更容易与面试官进行双向对话。他们没有必要试图在你的知识中寻找漏洞。不,他们通常想以专家的身份和你谈谈,看看你对你申请的工作理解如何。他们希望你帮助他们更清楚地了解他们需要什么,他们需要谁。例如,他们可能会询问您使用 PostgreSQL 的体验。也许他们会问这个问题,因为他们正在考虑过渡到这个数据库。在与他们的交谈中,您可以问一些关于数据量、他们想用这些数据做什么、数据库现在看起来如何的问题。从这一点出发,你可以谈论为什么 PostgreSQL 是一个好的选择。或者为什么其他数据库可能更适合他们的需求。也许是您更熟悉的 SQL Server。在这里,你是在帮助他们创造需求,而不是回应他们的需求。你在帮助他们找到最好的候选人:希望是你自己。
找到一个好员工并不容易。
不要以为你申请的所有工作都有比你优秀的候选人。不一定是这样。公司经常很难找到一名好员工,尤其是当他们经常与一些大型科技公司争夺候选人时。这意味着你并不像你想象的那样可以随意处置。当然,你不应该在面试时大喊,“你需要我,我知道你需要我!你,现在就雇用我!”。但重要的是要记住,很有可能公司需要你,就像你需要他们一样。
在某种程度上,所有这四点都显示了一些面试官和公司的不安全感了解某人的不安全感会让他们更有人情味。这让他们更像你。
现在你知道面试官(可能)的不安全感,他们不喜欢什么,不知道什么。我想我们该谈谈他们知道些什么的话题了。因为可以肯定的是,大多数面试官都在他们的候选人身上寻找一些特质。
面试官想要什么?
图片来自 Canva
无风险雇佣
理想情况下,他们寻找的是没有风险的人。当然,没有这样的候选人。但可以肯定的是,面试官的工作是雇佣风险尽可能低的人。
无风险雇佣意味着找到一个有值得尊敬的相关经验的人。面试官希望这种经历尽可能贴近公司的需求。如果他们找到了这样的候选人,很有可能这个候选人在新工作上的过渡会很顺利。这是合乎逻辑的;如果你正在处理你以前已经处理过的情况,机会是你学到了一些东西,你知道如何处理这些情况(更好)。再说一遍,如果有时间和金钱,无风险的候选人是他们能得到的最好人选。
他们也在寻找对工作环境有积极贡献的人。愉快共事的人。那些不把别人的成就归功于自己的人,那些在压力下不崩溃的人,那些在离开时不推卸责任的人变得强硬起来。
当然,他们在寻找一个对公司满意的人。一个会尽可能长时间贡献的人。如果他们发现你对和他们呆在一起不感兴趣,他们会犹豫是否在你身上投资时间和金钱。
即时贡献
说到贡献,这些公司真的希望找到一个能立即做出贡献的人。即插即用型员工。这通常发生在急需雇人的情况下。对于这种情况,找到一个可以立即做出贡献的人是一个理想的解决方案。
然而,有时不可能找到这样的候选人。或者公司有意雇用某人是因为他或她的潜力,而不是当前的知识或以前的经验。毕竟,即使是即插即用的员工也需要花一些时间来适应新的环境。也许学习使用一个新的核心系统,理解数据结构,业务的一些细节,或者公司本身。当然,如果你有经验,花的时间会少一些。但有时,公司希望建立在一个长期的时间尺度上,开发员工未来利益的潜力,并在某种程度上,从零开始按照员工的需求塑造他们。他们寻找的是学习的能力,而不是当前的知识。毕竟,大多数工作并没有那么复杂,因此,一些相当聪明的人,或者可能受过相关教育的人,无法学到所需的技能。当然,其中一些需要很多时间,但是公司有时愿意投资这些时间。
进步和良好的品牌
你如何选择你想去的公司?我相信你在考虑公司的形象和其他事情。同等条件下,在一家拥有某种声望和形象的公司工作总是更好。
求职者也是如此。面试官希望让他们的公司变得更好。在实践中以及在他人眼中也是如此。要做到这一点,他们会关注你曾经就读的学校和/或学院。通常,最受重视的大学是有原因的。在某种程度上,大学为他们做了最初的选择。虽然名牌大学不能保证一个好员工,但它至少(在某种程度上)保证了某人的知识和学习能力。
但是,总有但是!大学一般只有在你没有任何(或很少)经验的情况下才重要。在比较这样的候选人时,面试官必须根据你上的大学和你的成绩来评估你。在几乎所有其他情况下,经验胜过任何教育。雇主看的是你在实践中的能力。如果你以前在一些知名公司工作过,这看起来会稍微好一点。同样,和名牌大学一样,如果你不够优秀,你就不可能为这样的大公司工作。
不仅如此,它可能会给他们的公司带来一个有价值和有知识的员工。当公司可以吹嘘他们的数据科学团队如何如何时,这看起来也不错,比如说,FAANG 背景。
除了良好的品牌效应,雇主还希望在你的简历或数据科学求职信中看到一些进展。它可以是同一家公司内部的层级结构,也可以是更换公司。也有可能是你没有往上爬,但是隔几年就去了一家技术更先进、更有挑战性的公司。所有这些都表明你没有停滞不前。你表现出了变得更好和承担更多责任的意愿。这肯定是你的面试官会喜欢的。
匹配文化
已经有很多关于公司文化的文章。每个公司都认为自己是独一无二的,与其他公司相比,有着完全不同的公司文化。老实说,当谈到公司文化时,我们更多的时候是在谈论一些模糊的、通用的概念,这些概念是公司试图呈现给他们的独特概念。
他们不是。就像你对面试官说这样的话,你不会是独一无二的:
“我是一个优秀的团队合作者,但也非常独立。”
每个人都这么说。他们这样说是因为他们不知道面试官想听什么,所以他们试图涵盖一切。
如果你真的想引起面试官的共鸣并脱颖而出,你必须冒一点风险。不是某种盲目的冒险。如果你为面试做好了准备,并倾听面试官的暗示,你就能了解面试官在寻找什么样的合群。如我所说,没有那么多变化。所以,举例来说,如果你在面试过程中发现团队合作是至关重要的,那就专注于此。不要说你如何擅长团队合作,但也很独立。不,只关注团队合作。告诉他们你是一个优秀团队成员的故事。没有人会认为,由于你出色的团队合作,你完全依赖他人,而自己什么也做不成。
反过来也一样。如果公司刚刚起步,你必须自己解决很多问题,那么重点给出几个例子,让你看起来像一个高度独立的专业人士。这也并不意味着你是一个不想和任何人在一起并吓跑同事的隐士。
简单的语言
我知道这很诱人。你如此渴望向面试官展示你有多优秀,以至于尽可能地使用行话、流行语和性感的缩写。通常情况下,你无法完全避免。使用某些特定工作和/或行业的术语是很自然的。
然而,面试官通常不喜欢这样,因为这听起来像是在吹牛。甚至可能就像你在用时髦的词语来掩盖对这个话题缺乏实质性的了解。即使你不是因为这个原因才这么做的,也不要给面试官怀疑的理由。
能够用简单的语言解释你的工作和你所做的事情通常是一个人真正理解他们在谈论什么的标志。这不仅显示了他们透彻的理解,也显示了他们能够想出自己的解释,而不仅仅是使用其他人都使用的普通短语。
面试官喜欢听到简单的语言还有一个重要的原因。如今,对于数据科学家和所有其他从事数据工作的人来说,与背景、经历和知识大相径庭的各种股东交流变得越来越重要。跨部门协作是你无法避免的事情,而且越来越需要。这意味着你必须能够用一种不太专业的方式向那些甚至不熟悉你的基本工作的人解释一些事情。让他们加入的唯一方法是让他们理解你。如果你知道自己在做什么,如果你能解释清楚,他们就能做到——没有比求职面试更好的地方来展示这些特质了。毫不奇怪,面试官会问你类似的问题:“你会如何向一个 6 岁的孩子解释云技术?”。
如何准备这些面试
图片来自 Canva
研究你的雇主和面试官
你应该为面试做好准备。你不能总是为你会被问到的问题做好准备。但你必须做的是研究你的雇主。了解他们的产品、历史、行业、组织结构等等。
对你的面试官也这样做。如果你知道他或她的名字,试着对他们做一点研究。找到关于他们背景的信息:他们在哪里上学/大学,他们在哪里工作,他们的专业领域是什么。
这会显示出你对这家公司的兴趣,而且一旦你了解了这家公司的基本情况,谈论你未来的工作会更容易。熟悉面试官也有助于和他们建立联系,尤其是如果你们有共同点的话。
了解公司文化
这是你只有在他们的网站上阅读文化才能大致理解的事情。正如我所说的,这通常包括可能意味着任何事情和没有任何事情的一般性陈述。更重要(也更难)的是,试着从你参加面试时看到的和从面试官那里学到的东西中“感受”公司文化。你没有太多时间去做那件事,但是你可以得到一些线索。办公室看起来是空的还是挤满了人?人们是独立工作还是团队工作;有时,这是可能的,尤其是如果它是一个开放空间的办公室。办公室是不是显得很安静,还是充满了人们的喋喋不休?交流是显得冷淡专业,还是很轻松?
这些只是一些建议。但是最重要的一点是,当你参加面试的时候,要睁大你的眼睛,竖起你的耳朵,倾听你所听到的和看到的。尤其是面试官发出了什么样的信号。适应他们。
了解工作类型
这是你事先只能部分知道的事情。你可以试着从职位描述、做互联网调研等方面去了解工作类型。但你不可能什么都懂。这就是为什么为面试准备一些关于工作类型的问题是很重要的。例如,我是在团队中工作还是独自工作?这-和-这必须从头开始设置还是仅仅改进?你使用什么技术?你打算使用什么技术?
作为一名数据科学家,了解你在工作中必须做的工作类型的最佳方式是通过我们为你准备的一些非编码和编码问题。
当然,在面试过程中你会想到一些其他的问题。这些问题的意义不仅仅在于表明你有问题要问。这是为了更清楚地表明对你的期望。作为一个(非常令人向往的)副作用,你会表现出你理解这份工作和这个行业(可能)存在的问题。此外,有了这些问题,你就有了一个框架,来回答那些你无法准备、只能在与面试官交谈时提出的问题。
准备好个人故事
不,我不是说你第一次看《小王子》的时候是怎么哭的。尽管这也不应该被排除在外。尤其是如果面试官问你最喜欢的书是什么。
我想更多的是展示面试官想要的技能的个人故事。也许是一个关于你如何在项目中途被任命为项目负责人以及你如何处理此事的故事?或者,即使你是一名经济学家,你是如何从事数据科学的?或者你是如何成为某个初创公司的第一名员工的,当时的 job 和现在公司雇佣 30 人的 job 有什么区别?
看,这些故事都很有用。它们会告诉你很多关于你的事情。只有一个这样的故事可以概括你的个性,你如何处理逆境,你的数据科学技术技能,软技能,你的沉着,机智,幽默,口才,甚至对生活的整体看法。通过讲述个人故事,你会以一种非直接的方式做到这一切,而不是吹嘘和无聊地提供你擅长的事情的清单。讲一个故事,让面试官总结他们是否喜欢听到的内容。
在面试之前,想出 4-5 个有趣的故事,突出你做得好的事情。
做你自己
我承认,对此毫无准备。你要么是你自己,要么不是。即使你不是你自己,那也是你自己。但是我们不要太哲学化了。我想说的是:要真实。是的,做好准备。试着读懂面试官的暗示。但是不要刻意去让他们喜欢你。不管你怎么想,人们通常会看穿这一点。很有可能,你会完全弄错。即使你在面试中骗过了他们,当你开始工作的时候,你会被发现,很快,你就会失业。
那没有意义。做你自己总是更好,诚实地回答,用你的方式说话,用你的方式思考。你应该努力展现自己最好的一面。不是别人的最佳版本。
摘要
理解面试官想法的第一步是接受面试官也是人。他们比你想象的更像你。他们不喜欢面试;他们可能缺乏安全感,不确定自己在寻找什么。当然,他们不是在寻找一个完美的员工。通过理解这一点,你将帮助自己打破带着恐惧或某种理想化接近面试官的习惯。一旦你意识到他们并不完美,就更容易与他们建立双向的融洽关系。
其次,你需要明白他们在找什么。他们正在寻找一个风险尽可能低的人。他们也希望有人能立即做出贡献。或者,如果没有,愿意学习的人。最重要的是,他们想要一个能与其他人和谐相处的人,一个能让工作场所尽可能愉快的人。最后,拥有令人尊敬的教育和/或工作背景对公司形象总是有好处的。
最后,明白这一点后,你需要有一定的策略来引起面试官的共鸣。这基本上可以归结为面试时的准备和警觉。你应该研究公司和面试官。确保研究公司的文化,并就地吸收。对某一类型的工作做研究,准备一些问题,并准备好在面试中根据你对这份工作的了解来提问。准备几个展示你的技术和软技能的故事。一旦你做好了所有的准备,放松,做你自己。如果做自己就是不放松,那也没关系。
最初发表于【https://www.stratascratch.com】。
了解 n_jobs 参数以加速 scikit-learn 分类
原文:https://towardsdatascience.com/understanding-the-n-jobs-parameter-to-speedup-scikit-learn-classification-26e3d1220c28?source=collection_archive---------9-----------------------
数据分析
一个现成的代码,演示了如何使用 n_jobs 参数来减少训练时间
作者图片
在本教程中,我说明了由scikit-learn
库的一些类提供的n_jobs
参数的重要性。根据官方的scikit-learn
库,n_jobs
参数描述如下:
为邻居搜索运行的并行作业的数量。除非在 joblib.parallel_backend 上下文中,否则 None 表示 1。-1 表示使用所有处理器。
这意味着n_jobs
参数可以用来分配和利用本地计算机中所有可用的 CPU。
在本教程中,我通过将n_jobs
参数从 1 变化到 CPU 的最大数量,来评估适应 scikit-learn 库提供的所有默认分类数据集所需的时间。作为例子,我将尝试一个带有交叉验证的网格搜索的 K-Neighbors 分类器。
定义辅助变量
首先,我定义了所有分类数据集名称的列表,包含在 sklearn.datasets 包中。
datasets_list = ['iris', 'digits', 'wine', 'breast_cancer','diabetes']
然后,我计算系统中可用的 CPU 数量。我利用了os
包提供的cpu_count()
函数。
import os
n_cpu = os.cpu_count()
print("Number of CPUs in the system:", n_cpu)
就我而言。CPU 的数量是 4 ( 一台相当旧的电脑,唉…我应该决定造一台更新的… )
我还定义了网格搜索的所有参数。
import numpy as np
parameters = { 'n_neighbors' : np.arange(2, 25),
'weights' : ['uniform', 'distance'],
'metric' : ['euclidean', 'manhattan',
'chebyshev', 'minkowski'],
'algorithm' : ['ball_tree', 'kd_tree']
}
定义主要功能
现在,我准备定义 main 函数,它将用于测试训练所用的时间。我导入所有需要的函数和类:
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import *
import time
我定义了load_and_train()
函数,它接收数据集名称作为输入。为了加载相应的 dataaset,我利用了globals()
函数,它包含一个包含所有导入函数的表。因为我已经导入了 scikit-learn 提供的所有数据集,所以我可以将函数名传递给globals()
函数。语法是:globals()[<function_name>]()
。
def load_and_train(name):
dataset = globals()['load_' + name]()
X = dataset.data
y = dataset.target
一旦加载了数据集,我就可以构建一个循环,通过改变 CPU 的数量来遍历 CPU 的数量并计算训练所用的时间。我构建了一个包含所有运行时间的列表,最终由函数返回。
tdelta_list = []
for i in range(1, n_cpu+1):
s = time.time()
model = KNeighborsClassifier(n_jobs=i)
clf = GridSearchCV(model, parameters, cv = 10)
model.fit(X_train, y_train)
e = time.time()
tdelta = e - s
tdelta_list.append({'time' : tdelta, 'bin' : i})
return tdelta_list
绘图结果
最后,我为所有数据集名称调用load_and_train()
函数,并绘制结果。
import matplotlib.pyplot as plt
import pandas as pdfor d in datasets_list:
tdelta_list = load_and_train(d)
df = pd.DataFrame(tdelta_list)
plt.plot(df['bin'], df['time'], label=d)
plt.grid()
plt.legend()
plt.xlabel('N Jobs')
plt.ylabel('Time for fit (sec.)')
plt.title('Time for fit VS number of CPUs')
plt.show()
作者图片
对于所有数据集,通过增加作业数量来减少对 K 近邻分类器执行具有交叉验证的网格搜索所花费的时间。为此,我强烈建议您使用n_jobs
参数。
具体来说,我建议设置n_jobs=n_cpus-1
,以免机器卡死。
摘要
在本教程中,我演示了如何使用n_jobs
参数来加速训练过程。
本教程的完整代码可以从我的 Github 库下载。
现在 Medium 提供了一个新特性,即它允许构建列表。如果您喜欢这篇文章,您可以将其添加到您的收藏列表,只需点击按钮,放在文章右上角的按钮:
作者图片
如果你想了解我的研究和其他活动的最新情况,你可以在 Twitter 、 Youtube 和 Github 上关注我。
相关文章
透过数据的镜头理解疫情
原文:https://towardsdatascience.com/understanding-the-pandemic-through-the-lens-of-data-44809b771e5b?source=collection_archive---------49-----------------------
多伦多当前新冠肺炎病例的探索性数据分析
疾控中心在 Unsplash 拍摄的照片
介绍
2019 年 12 月,中国武汉发现首例新型病毒。世卫组织和中国当局确认了人际传播。不久之后,它被宣布为全球疫情。这当然是新冠肺炎,一种由新型冠状病毒引起的高传染性疾病。自那以来,我们已经取得了长足的进步,目前已有超过 1 . 05 亿人受到感染(截至 2021 年 2 月)。全球病例仍在增加,一些国家采取了一些限制措施。
为了更好地了解正在进行的疫情,一些研究人员开始分析现有的数据,以提取有价值的见解。在这篇文章中,我将分析多伦多 Covid 病例的公开数据。目标是结合新闻报道来理解这些数据所提供的信息。
数据源
多伦多市的开放数据门户是一个伟大的倡议,它提供了大量的数据集来探索和了解多伦多市是如何工作的。特别是在这个项目中,我接手了新冠肺炎病例,它包含了向多伦多公共卫生部门报告的所有病例的人口统计和地理信息。该数据每周更新,当前分析包含截至 2021 年 2 月 1 日的数据。
探索性分析
数据集由 83474 个点和 18 个要素组成,其示例如下所示。截至 2021 年 2 月 1 日,我们有 80,775 例确诊病例和 2699 例疑似病例。
前五点来自于数据中的一些特征
自 2020 年 1 月起每月报告的病例数
自 2020 年 1 月起每月报告的死亡病例数
上图显示了自疫情开始以来每月报告的病例总数和死亡病例数。我们可以清楚地看到两波,第二波仍在进行中。8 月份结束的第一波高潮出现在 4 月份。第二波似乎感染了更多的人群,但导致死亡病例减少。这表明,从第一波开始,我们已经学会更好地应对疫情。自疫情开始以来的每日案例如下所示。
自疫情开始以来的每日病例
现在让我们了解一下各年龄组的病例分布情况。
:考虑的年龄组有 0-19 岁、20-29 岁、30-39 岁、40-49 岁、50-59 岁、60-69 岁、70-79 岁、80-89 岁、≥90 岁。
不同年龄组的新冠肺炎病例
以上显示了不同年龄组的 Covid 病例(以千计)。我们可以看到,年轻一代的病例数要高得多,这可能仅仅是因为多伦多的青年人口较多。因此,了解每个年龄组的人口统计是很重要的。这些人口统计数据来自 StatCan 。这是 2016 年的人口普查数据,我假设到 2021 年增长 5%,略高于 2011 年到 2016 年的增长(4.3%)。
多伦多人口和 Covid 病例与年龄组
正如预期的那样,由于人口较多,较年轻年龄组的病例数明显较高。从绝对数字来看,20 至 29 岁年龄组的病例数量最多。这是有道理的,因为 20 至 29 岁年龄段的人往往相互接触最多,流动性也很高。就感染人数而言,这是受影响最严重的年龄组吗?为了找出答案,让我们画出不同年龄组的病例数与人口数的比率。
每个人口的病例数
令人惊讶的是,竟然是 90 岁以上的年龄段!病例与人口的比率(~10)明显高于其他年龄组(~3)。虽然 90 岁以上年龄组的人口是最小的,但他们中的许多人居住在观察到严重疫情的长期护理院。稍后将详细介绍。现在,让我们看看这些确诊病例的结果。
结果 :活动(仍在进行中的病例)、已解决(患者已康复的病例)、致命(导致死亡的病例)
在多伦多的所有病例中,约 70000 例已得到解决,约 3%的病例(2265 例)是致命的。
基于结果的病例计数
不同年龄组的病例结果
上表显示了不同年龄组的结果。我们可以看到死亡率随着年龄的增长而增加。
各年龄组的死亡率和病例数
这个情节很恐怖!我们可以看到,随着年龄的增长,感染人数明显减少,而致命病例却急剧增加。各年龄组的死亡率百分比如下所示。
各年龄组的死亡率百分比
随着年龄的增长,死亡率急剧增加,90 岁及以上的约占 30%。我们的中和抗体越多,我们对 Covid 的免疫力就越好。不幸的是,这些抗体随着时间的推移而减少,因此老年人群更容易因 Covid 而死亡。更多关于这个的讨论可以在这里找到。
传染源:
旅行(安大略省外旅行)密切接触(与确诊或疑似病例有密切接触)机构(长期护理院、特殊护理医院、急症护理医院等。)、医疗保健(家庭医生、牙医等。)、社区(杂货店、健身房等。)、不明(感染源不明)、暴发(与长期护理、无家可归者收容所等暴发有关的病例。)
病例与传染源
大多数病例的传染源不明,这有点令人担忧,甚至令人害怕。由此可见接触者追踪有多难。我建议人们开始使用 Covid Alert app 来帮助追踪联系人的来源。
密切接触、暴发和社区是下一个最常见的传染源。
年龄组较年轻一侧的大多数病例对应于密切接触和社区传播。而与疾病爆发相关的感染是 80 岁及以上人群的主要感染源。这与自疫情开始以来我们一直在新闻中听到的长期护理单位爆发疫情相一致,这令人深感沮丧。
与死亡病例相对应的传染源
特别是在长期护理单位中的爆发可被视为死亡病例的主要原因。如果安大略省更好地处理长期护理单位,死亡人数本来可以大大减少!对加拿大养老院危机的详细分析可以在这里找到。
最后,让我们看看案件在多伦多各地区的分布情况。这个城市被分为 96 个前分拣区(FSA)。每个 FSA 对应一个以字母 m 开头的唯一的 3 位邮政编码。
多伦多地图,显示每个 FSA 的死亡病例数
多伦多地图,显示每个 FSA 中的活动案例数
在多伦多推广疫苗时,最好针对上面显示的活跃病例数量最多的地方。这对应的是怡陶碧谷(M9V),北约克(M3N,M2R),斯卡伯勒(M1B),约克(M6M)。理想的情况是开始给长期护理院的人接种疫苗,同时在上述地点进行大规模接种。
结论
- 与第一波相比,8 月开始的第二波感染人数明显更多,但导致的死亡病例相对较少。这表明,做好应对疫情的准备有助于拯救许多生命,这是一个特别重要的教训,值得在未来发扬光大。
- 由于流动性大和相互接触,20 至 29 岁年龄组的感染人数最多。另一方面,大多数死亡病例发生在 80 岁及以上。这是由于中和抗体随着时间的推移而减少。
- 在超过 40%的病例中,感染传播的来源不明,这表明追踪接触者的困难。在已知病例中,密切接触是头号传染源。这也是安大略省总理实施严格的居家隔离令的原因。
- 在多伦多的所有新冠肺炎病例中,最致命的病例是由于爆发引起的,特别是在长期护理院和养老院。正如在此所讨论的,这些护理院的条件必须得到显著改善,这些护理院过度拥挤的问题必须得到解决,并且应该雇用更多合格的工作人员。
- 多伦多没有疫苗接种的时间表,但根据现有的数据,理想的策略是尽快为长期护理院和养老院的人接种疫苗,并在受影响最严重的地区开始大规模接种疫苗。
- 50 岁及以下年龄组的死亡率几乎为零,20 至 29 岁年龄组的感染人数最多。在给 50 岁以上的人和所有年龄组的脆弱人群接种疫苗后,给 20 至 29 岁年龄组的人接种疫苗似乎可以遏制病毒的传播。
通过数据我们可以看出,感染传播的主要原因是密切接触。隔离和留在家中是遏制病毒传播的有效策略。我明白并不是很多人有我这样的特权,与世隔绝,呆在家里。但是我强烈要求你尽可能地遵守这些命令。虽然不是强制性的,但我也强烈建议您接种疫苗,建立群体免疫,共同抗击疫情病毒!
所有的分析都是用 Python 完成的,相关代码可以在我的 GitHub repo 中找到。请在这里分享你的想法,或者在 LinkedIn 上与我联系。
感谢阅读!
**编者注:towardsdatascience.com是一家以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
参考
- https://open.toronto.ca/dataset/covid-19-cases-in-toronto/
- https://www12 . stat can . GC . ca
- https://www . the lancet . com/journals/lancet/article/piis 0140-6736(21)00083-0/full text
- https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7288963/
了解为真实世界场景构建机器学习模型的过程
原文:https://towardsdatascience.com/understanding-the-process-of-building-a-machine-learning-model-for-a-real-world-scenario-30a50fc12f7f?source=collection_archive---------31-----------------------
构建线性回归模型以根据天气历史数据预测表观温度的实用分步指南
由卡洛斯·穆扎在 Unsplash 上拍摄的照片
本文的重点是找出特定要素之间的关系,并在经历了所有必要的步骤后使用天气历史数据集进行预测,
- 数据清理
- 数据转换
- 特征编码
- 特征缩放
- 特征离散化
- 降维
- 线性回归模型
- 模型评估
这里的目标是发现,湿度和温度之间是否存在关系,湿度和表观温度之间是否存在关系?并且还发现在给定的湿度下是否可以预测表观温度。****
这里使用的数据集是 Kaggle 的天气历史数据集。点击这里可以找到。
首先,导入所需的 python 库。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
import seaborn as sns
from sklearn import preprocessing
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import KBinsDiscretizer
from sklearn import linear_model
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from math import sqrt
from sklearn.model_selection import cross_val_score, cross_val_predict
from sklearn import metrics
然后将数据集导入 Colab 并读取。
from google.colab import drive
drive.mount("/content/gdrive")data_set = pd.read_csv('/content/gdrive/My Drive /data /weatherHistory.csv')
data_set.tail(10)
数据集中的最后 10 行可以用下面的*data_set.tail(10)*
进行检查。
输出:
资料组
那么原始数据集的副本被创建为 x。
X = data_set.copy()
1.数据清理—处理缺失值、异常值和异常值
应该检查数据集是否有缺失值,下面的代码将返回 True 如果有任何缺失值,否则返回 False 。
X.isnull().values.any()
上面的代码输出 True ,表示数据集中有缺失的值。因此需要识别出缺少值的列。
X.isnull().any()
输出:
这意味着,只有 Precip 类型列有缺失值,所有其他列没有任何缺失值。
缺失值的百分比可按如下方式检查。
print(X.isnull().sum() * 100 / len(X))
输出:
我们可以看到百分比非常低,所以我们可以用下面的代码删除数据集中所有缺失的值。
X = X.dropna()
既然缺失值问题已经解决,接下来,我们应该检查异常值或异常值。
X.boxplot(figsize=(18,8))
输出:
所有特征的箱线图
我们可以看到压力特征的数据分布是异常的,因为压力已经为 0。我们可以检查有多少数据显示异常。
X[X['Pressure (millibars)'] == 0].shape[0]
产量:1288
所以这些都不是离群值。这些值可能是一些人为错误或系统故障的结果。因此,我们不能简单地接受它们,也不能放弃它们,因为那样我们会错过其他功能数据。所以我们可以利用 IQR。
IQR 或四分位数范围是基于将数据集划分为不同分位数的变异性度量。
我们可以用分位数来计算下限和上限。然后我们用下限代替小于下限的值,用上限代替大于上限的值。这也适用于左偏或右偏的数据。
fig, axes = plt.subplots(1,2)
plt.tight_layout(0.2)
print("Previous Shape With Outlier: ",X.shape)
sns.boxplot(X['Pressure (millibars)'],orient='v',ax=axes[0])
axes[0].title.set_text("Before")Q1 = X["Pressure (millibars)"].quantile(0.25)
Q3 = X["Pressure (millibars)"].quantile(0.75)print(Q1,Q3)
IQR = Q3-Q1
print(IQR)lower_limit = Q1 - 1.5*IQR
upper_limit = Q3 + 1.5*IQR
print(lower_limit,upper_limit)X2 = XX2['Pressure (millibars)'] = np.where(X2['Pressure (millibars)']>upper_limit,upper_limit,X2['Pressure (millibars)'])X2['Pressure (millibars)'] = np.where(X2['Pressure (millibars)'] <lower_limit,lower_limit,X2['Pressure (millibars)'])print("Shape After Removing Outliers:", X2.shape)
sns.boxplot(X2['Pressure (millibars)'],orient='v',ax=axes[1])
axes[1].title.set_text("After")
plt.show()
输出:
施加 IQR 压力前后的箱线图
然后,我们需要通过绘制箱线图来检查湿度中的异常值或异常值。
humidity_df = pd.DataFrame(X2["Humidity"])
humidity_df.boxplot()
输出:
湿度箱线图
我们可以看到湿度为 0.0。所以我们要检查有多少数据值是 0.0。
X2[X2['Humidity'] == 0].shape[0]
产量:22
鉴于地球的气候和天气条件,湿度不可能为零。出现这种异常的数据点数量也非常少,因此我们可以简单地删除它们。
X2 = X2.drop(X2[X2['Humidity'] == 0].index)
现在,我们完成了数据清理。
通常,在数据清理之后,您可以继续进行数据转换。但在这里,我在分割数据之前进行了特征编码,因为这将消除为训练和测试数据单独进行特征编码的需要。稍后将解释在应用任何变换之前拆分数据集的原因。
2.特征编码-处理分类特征
分类特征是可以分组到类别中的数据。举个例子,我们可以拿性别、肤色等。我们需要将那些非数值转换成数值,以便训练机器学习模型。有两种处理分类数据的传统技术。
- 一键编码
- 标签(整数)编码
我将用天气历史数据集中的例子来解释这两点。我们的数据集中有两个分类列,Precip Type 和 Summary。让我们以“Precip 类型”为例。
X2['Precip Type'].value_counts()
输出:
我们可以看到‘Precip Type’中的数据值不是雨就是雪。所以 Precip 类型’是一个分类特征。
一键编码
在这种方法中,分类特征被值为 0 或 1 的新特征所取代。Precip 类型被新的特征雨和雪所取代,如下图所示。
标签编码
在这种技术中,每个分类值都被转换成一个数值。如下图所示。
对于线性模型,一键编码更合适。如果我们对这种情况应用标签编码,那么模型将试图识别顺序,因为特征值类似于 0、1、2、3 等。但是如果是二进制类别,我们可以使用标签编码。
这里,因为 Precip 类型只有 2 个值,所以我可以使用标签编码。
X2['Precip Type']=X2['Precip Type'].astype('category')
X2['Precip Type']=X2['Precip Type'].cat.codes
但是如下图所示,summary 有许多类别。
final['Summary'].value_counts()
输出:
所以我们需要对汇总列进行一次性编码。*pd.get_dummies*
将根据每个类别创建新的特性列,然后我们需要合并新的特性列并删除摘要列,如下面的代码所示。
dummies_summary = pd.get_dummies(X2['Summary'])
merged_summary = pd.concat([X2,dummies_summary],axis='columns')
X2 = merged_summary.drop(['Summary'], axis='columns')
X2
输出:
应用要素编码后的数据集
3.分割数据集
数据泄漏是指机器学习模型的创建者犯下的错误,其中他们意外地在测试和训练数据集之间共享信息。
当我们对训练和测试数据集一起(对整个数据集)应用变换、离散化和缩放等时,可能会导致数据泄漏。为了缓解这个问题,我在转换之前分割数据集,以避免模型过度拟合。
表观温度是目标特征。因此,我们需要将其从要素数据集中分离并移除。这里,数据集分为 80%用于训练,20%用于测试。
target_column = pd.DataFrame(final_summary['Apparent Temperature (C)'])final_summary = final_summary.drop(['Apparent Temperature (C)'], axis='columns')X_train, X_test, y_train, y_test = train_test_split(final_summary, target_column, test_size=0.2)
拆分数据集后,需要重置索引。
X_train=X_train.reset_index(drop=True)
X_test=X_test.reset_index(drop=True)
y_train=y_train.reset_index(drop=True)
y_test=y_test.reset_index(drop=True)
现在,我们可以分别对训练和测试数据集应用转换。
4.数据转换
真实数据集中的变量将遵循更偏态的分布。但是如果数据来自正态分布,那么机器学习模型可以学习得很好。因此,我们应该使用直方图和 Q-Q 图来检查这些变量是如何分布的。这里我只解释训练数据集的转换。同样的过程也应该应用于测试数据集。
X3 = X_train.copy() #copy of the training dataset
Y3 = X_test.copy() #copy of the testing dataset stats.probplot(X3["Temperature (C)"], dist="norm", plot=plt)plt.show()
输出:
温度的 Q-Q 图
同样,对于所有特性,我们可以使用 Q-Q 图分析数据分布,以查看数据是否偏离了预期分布(红线)。这里我们可以看到温度呈正态分布。
但是当我们看到风速的 Q-Q 图时,我们可以看到数据是倾斜的。
风速的 Q-Q 图
然后我们也可以绘制直方图。
X3.hist(figsize=(15,10))
输出:
训练数据的直方图
我们可以看到湿度是左偏的,风速是右偏的。可见性也显示了一些左偏,但是在应用变换之后,它没有显示正态分布。所以我没有应用可见性的转换。
对于右偏的数据,我们应用对数变换,对于左偏的数据,我们可以应用指数变换。
logarithm_transformer = FunctionTransformer(np.log1p)
data_new1 = logarithm_transformer.transform(X3['Wind Speed (km/h)'])
X3['Wind Speed (km/h)']=data_new1
X3['Wind Speed (km/h)'].hist()
这里我使用了*np.log1p*
,因为风速值为 0.0,而 np.log 仅用于正数。
输出:
应用对数变换后的风速直方图
现在我们可以看到风速呈正态分布。
由于湿度是左偏的,我们应用指数变换。
exp_transformer = FunctionTransformer(np.exp)
data_new2 = exp_transformer.transform(X3['Humidity'])
X3['Humidity']=data_new2
X3['Humidity'].hist()
输出:
应用指数变换后的湿度直方图
在这里,我展示了直方图在转换后是如何变化的。
风速:
湿度:
我们可以从 Q-Q 图和直方图中看到,大声覆盖始终为 0.0。因此,由于它没有影响,我们需要在训练和测试数据中消除噪声。
X3 = X3.drop(['Loud Cover'], axis='columns')
Y3 = Y3.drop(['Loud Cover'], axis='columns')
由于格式化日期是一个唯一的值,而每日摘要不是一个数值,它有如此多的不同值,我们可以将它们都删除。
X3 = X3.drop(columns=['Daily Summary','Formatted Date'])
Y3 = Y3.drop(columns=['Daily Summary','Formatted Date'])
5.特征缩放—标准化
特征缩放指的是用于归一化独立变量的值的范围的方法。
这里我使用了标准化来进行缩放。标准化将数据转换为平均值 0 和单位标准差。这一步至关重要,因为它避免了模型受到大幅度变量显著影响的机会。
标准化不适用于分类变量。因此,在对数字特征进行标准化之前,应该将它们放在一边。标准化也应该分别应用于训练和测试数据。
这里,请注意,我仅将*scaler.fit()*
用于训练数据,因为我们需要将用于训练数据集的相同参数(平均值和标准偏差)应用于训练数据集。
X4 = X3.copy()
Y4 = Y3.copy()to_std_train = X4[['Temperature (C)', 'Humidity','Wind Speed (km/h)', 'Wind Bearing (degrees)', 'Visibility (km)','Pressure (millibars)']].copy()
to_std_test = Y4[['Temperature (C)', 'Humidity','Wind Speed (km/h)', 'Wind Bearing (degrees)', 'Visibility (km)','Pressure (millibars)']].copy()scaler = StandardScaler()
scaler.fit(to_std_train)train_scaled = scaler.transform(to_std_train)
test_scaled = scaler.transform(to_std_test)std_df_train = pd.DataFrame(train_scaled, columns = to_std_train.columns)
std_df_test = pd.DataFrame(test_scaled, columns = to_std_test.columns)X4[['Temperature (C)', 'Humidity','Wind Speed (km/h)','Wind Bearing (degrees)','Visibility (km)','Pressure (millibars)']]=std_df_train
Y4[['Temperature (C)', 'Humidity','Wind Speed (km/h)','Wind Bearing (degrees)','Visibility (km)','Pressure (millibars)']]=std_df_test
标准化数据后,我们可以使用相关矩阵进行相关分析。
sns.heatmap(std_df_train.corr(),annot=True);
相关矩阵
我们可以知道湿度和温度之间有负相关关系。所以要回答这个问题湿度和温度之间有和的关系吗?是的。湿度和温度呈负相关。
6.[数]离散化
离散化用于将连续变量转换为离散变量。这里我们可以看到,当绘制风向直方图时,它不符合正态分布。当具有非标准概率分布的数值变量被离散化时,机器学习模型可以表现得更好。我已经用 K-means 离散化了风向。
X5 = X4.copy()
Y5 = Y4.copy()data1 = pd.DataFrame(X5, columns=['Wind Bearing (degrees)'])
data1 = data1.dropna()
data2 = pd.DataFrame(Y5, columns=['Wind Bearing (degrees)'])
data2 = data2.dropna()discretizer = KBinsDiscretizer(n_bins=8, encode='ordinal', strategy='uniform')discretizer.fit(data1)
_discretize1 = discretizer.transform(data1)
_discretize2 = discretizer.transform(data2)
X_dis = pd.DataFrame(_discretize1)
Y_dis = pd.DataFrame(_discretize2)
X_dis.hist()
输出:
离散化后的风向直方图
我们可以绘制一个相关矩阵,以确定目标列(表观温度)的特征的重要性。
相关性是一种统计度量,表示两个或多个变量一起波动的程度。
X5['Wind Bearing (degrees)'] = X_disd_data = X5[['Temperature (C)', 'Humidity','Wind Speed (km/h)','Wind Bearing (degrees)','Visibility (km)','Pressure (millibars)']].copy()d_data['Apparent Temperature (C)'] = y_train
d_data.head(10)
print(d_data.corr())
sns.heatmap(d_data.corr(),annot=True)
相关矩阵
我们可以看到,湿度和目标变量表观温度有着显著的高度相关性。所以回答问题湿度和表观温度之间有 关系吗?是的。湿度和表观温度呈负相关。
7.降维—主成分分析
降维的重要性在于,我们可以通过去除冗余,只保留有用的信息来压缩数据集。太多的输入变量可能会导致维数灾难,然后模型将无法很好地执行,因为模型还会从训练数据集中的噪声中学习并过度拟合。
主成分分析是一种用于降维的强大技术,增加了可解释性,但同时最小化了信息损失。
pca = PCA(n_components=12)
pca.fit(X5)
X_train_pca = pca.transform(X5)
X_test_pca = pca.transform(Y5)
principalDf = pd.DataFrame(data = X_train_pca)
principalDf.head(20)
输出:
参数*n_components*
的值通过分析下面的*explained_component_ratio_*
来决定。
pca.explained_variance_ratio_
输出:
PCA 解释的方差比
当决定使用主成分的数量时,我们应该考虑上述值。数组的第一个元素是高方差维数,我们应该认为高方差维数的总和约为 0.95。这里我用了 12 个主要成分。
8.线性回归模型
完成所有上述步骤后,将线性回归模型应用于数据集。
lm = linear_model.LinearRegression()
model = lm.fit(X_train_pca,y_train)
9.模型评估
当我们评估我们的模型时,可以看到精度为 0.990223。
accuracy = model.score(X_test_pca, y_test)
print("Accuracy:", accuracy)
输出:
为了进一步评估模型,我们使用均方差(MSE)。
predictions = lm.predict(X_test_pca)
y_hat = pd.DataFrame(predictions, columns=["predicted"])
mse = mean_squared_error(y_test, y_hat)
print('Test MSE: %.3f' % mse)
输出:
我们也使用了计算的均方根误差(RMSE)。
rmse = sqrt(mean_squared_error(y_test, y_hat))
print('Test RMSE: %.3f' % rmse)
输出:
我们可以进行 6 重交叉验证。
scores = cross_val_score(model, X_test_pca, y_test, cv=6)
print("Cross-validated scores:", scores)
输出:
用下面的代码,我计算了交叉预测的准确性。
predictions = cross_val_predict(model, X_test_pca, y_test, cv=6)
accuracy = metrics.r2_score(y_test, predictions)
print("Cross-Predicted Accuracy:", accuracy)
模型的精度是好的。但是检查重量参数也很重要。
权重参数是模型在新数据下表现良好的一个重要指标。如果权重参数较小,则意味着您的模型非常好,在没有数据的情况下会表现得更好。
#W parameters of the model
print(lm.coef_)
输出:
在这里,权重参数不是很低。但是我们可以通过识别和改变我们在预处理、转换等过程中所做的一些步骤来进一步减少它们。
我们可以将模型的预测可视化如下。这里我只绘制了 100 个数据点的图表。
plt.figure(figsize=(15, 7))
plt.plot(y_hat[:100], label = "Predicted")
plt.plot(y_test[:100], label = "Actual")
plt.title('Predictions Vs Actual')
plt.legend()
plt.show()
输出:
预测与实际数据图
10.结论
在本文中,我向您提供了如何通过应用数据清理、数据转换、特征编码、特征缩放、离散化、维度缩减来构建机器学习模型的分步指南,并且我还评估了线性回归模型。
我希望这篇文章能帮助你很好地理解我们应该遵循的重要步骤以及它们背后的主要概念,以建立一个好的机器学习模型。
编码快乐!
11.Colab 代码
https://colab.research.google.com/drive/1C4GlUeLKhiC-1aX0D63M88_Rw-K7nCTc?usp=sharing
理解数据库管理系统(RDBMS)的关系模型
原文:https://towardsdatascience.com/understanding-the-relational-model-of-database-management-systems-56f17db99f56?source=collection_archive---------19-----------------------
以及为什么它在整个行业如此受欢迎
在流行媒体对机器学习的大肆宣传和荣耀背后,一个有点被忽视的极其重要的组件是数据库管理系统(DBMS)的作用。当然,并不是每个人都需要知道数据库管理的细节。但是,如果你以任何身份使用机器学习,在你的职业生涯中,很大程度上,理解一定程度的机器学习可能会有所帮助。
照片由玛格丽特·韦尔在 Unsplash 拍摄
大约在 60 年代,开发人员仍然使用硬编码软件来管理数据。每当这些数据不适合非常严格的预定义架构时,软件每次都需要进行重构,以适应存储的数据类型和用于检索和操作数据的方法类型。如果开发人员使用哈希表来定义数据结构,随着数据库的增长和需求的发展,系统将需要重新编写。这是一个重复发生的事件。
在 IBM 工作的一位名叫 Edgar F. Codd 的数学家看到了这种对通用架构的需求,这种架构可以真正绕过硬编码的僵化,以适应不断发展的需求。进入关系数据库管理系统(RDBMS)。1970 年,他发表了一篇描述这种架构的论文,其中系统本身可以找出存储、检索和操作数据的最佳可能表示和过程。
大型共享数据库的数据关系模型。美国计算机学会通讯26.1(1983):64–69。ACM 的通信。Web 。
Codd 建议我们使用简单、原始的数据结构,如标量、整数、浮点和字符串来存储数据。数据会以元组的形式形成关系。也许用更简单和更容易理解的术语;想象一个数据表(也称为关系),其中每个单元格都是简单的标量数据类型之一,在每一行中作为元组连接起来,形成它们自己的关系。每个实体(或行)都有一个唯一的 ID,称为主键。表也可以通过这些键相互对话,这些键现在被称为外键,使用七个基本操作形成自定义关系。下面列出了基本操作及其相应的标准 SQL 语法:
i) Select: 选择并返回一个新的关系,它是满足某些条件谓词的元组的子集:SELECT * FROM Shop_A 其中 author _ id = 102
**ii)投影:**返回只包含指定属性的元组的新关系,可以重新排列属性顺序,可以操作值:SELECT author_id-100,book _ id FROM Shop _ A WHERE author _ id>102;
iii) Union: 将两个输入关系中的所有元组作为一个新关系返回,但仅当两者中的输入数据类型和属性相同时才有效:(SELECT * FROM Shop _ A)Union ALL(SELECT * FROM Shop _ B);
iv) Intersection: 返回两个输入关系中的元组的新关系,但仅当两者中的输入数据类型和属性相同时才有效:(SELECT * FROM Shop _ A)INTERSECT(SELECT * FROM Shop _ B);
v) Difference: 返回元组在第一个输入中但不在第二个输入中的新关系,但仅当两者的输入数据类型和属性相同时才有效:(SELECT * FROM Shop _ A)EXCEPT(SELECT * FROM Shop _ B);
vi) Product: 返回一个新的关系,即两个输入的点积,aka。所有可能的组合,一般用于测试:SELECT * FROM Shop _ A CROSS JOIN Shop _ B;或者,选择* FROM Shop_A,Shop _ B;
vii) Join: 返回两个输入关系中都有的元组的新关系,但与 Union 不同,数据和属性类型不需要相同,只要元组内至少有一个匹配即可:SELECT * FROM Shop _ A NATURAL Join Shop _ B;
此后,又增加了更多高级操作,如除法、聚合、排序等等。
这些较低级的操作被用来用一种叫做关系代数的技术来评估关系。RDBMS 使用这些原始的关系代数表达式来确定最有效的如何这就是关系演算。系统中一个非常复杂的组件叫做查询优化器 来完成这项工作。
假设您想在表 A 和表 B 之间创建一个新的关系,每个表都包含 50 亿行,您希望所有主键小于 500 的元组都同时出现在表 A 和表 B 中,并且具有相同的属性。一种方法是首先自然连接所有 100 亿行,然后过滤少于 500 的选择键。另一个过程可以是首先从 A 和 B 中过滤选择少于 500 个键,然后自然连接 1000 个(最多)条目。根据数据库的实际大小,第二个过程的性能因素将比第一个过程有效得多。
这就是关系模型的优势所在。用户只需要说出他们想要做什么,RDBMS 就会计算出 T2 如何以最有效的方式做这件事。这就是像 SQL 这样的查询语言被称为“非过程化”的原因。系统内置了明确的步骤(或程序)。与 Python 或 C/C++等编程语言不同,在这些语言中,用户需要显式声明对数据进行多次迭代,寻找这一特性,如果 n 大于某个数字,请选择另一种方法,yada yada,SQL 只需被告知所需的最终结果。
RDBMS 主要基于三大支柱:
**i)结构(模式):**关系及其内容,如属性、类型、数据内和数据间的关系。
**ii)完整性:**确保数据库的内容满足约束条件(也就是一些预定义的本地结构,比如内存分配),以在给定这些约束条件的情况下验证数据库的实例,没有冗余。
**iii)操作:**如何通过运行查询来访问或修改数据。
因为该系统可以随着不断发展的数据和需求而发展,所以它非常通用,适合大多数数据库的业务需求。RDBMS 由于其智能化设计,可以说是数据库管理系统的人工智能。
💔-reasons-why-your-machine-learning-model-is-garbage-d643e6f0661> </5-stages-of-learning-data-science-40bca61f11b1>
参考文献:
- 帕夫洛 A,2019,数据库系统介绍,讲义,15-445/645,卡内基梅隆大学
- 大型共享数据库的数据关系模型。美国计算机学会 26.1 (1983 年)通讯:64-69。ACM 的通信。网络。
附言:要获得更多关于数据科学、编程以及生物学家如何在数据革命中导航的简明扼要的文章,可以考虑关注我的博客。
由于每分钟都有成千上万的视频被上传,所以过滤掉它们是很重要的,这样你就可以只使用高质量的数据。我亲自挑选的,我会把你感兴趣的主题的教育视频发邮件给你。报名这里。
感谢您的阅读!
了解萨里玛模型的季节顺序
原文:https://towardsdatascience.com/understanding-the-seasonal-order-of-the-sarima-model-ebef613e40fa?source=collection_archive---------2-----------------------
了解 Python statsmodels 库的 SARIMA 模型的(D,P,Q,M)季节顺序的快速概述和现成代码。
图片来自 Pixabay 的romnyepez
几个月前,我写了一篇文章,描述了为时间序列预测构建 SARIMA 模型的全过程。在那篇文章中,我解释了如何调整 SARIMA 模型的 p、d 和 q 阶,并根据 NRMSE 评估了训练模型的性能。
关于文章的一个评论是,提议的模型基本上是 ARIMA 模型,因为没有考虑季节顺序。我感谢评论的作者,我调查了这方面。
现在我在这里向你们解释我发现的一个有趣的方面,不幸的是,我在网上找到的文章中没有很好地解释它。
萨里玛模型订单
SARIMA 模型可通过两种订单进行调整:
- (p,d,q)顺序,是指时间序列的顺序。这个顺序也用于 ARIMA 模型(不考虑季节性);
- (P,D,Q,M)季节顺序,是指时间序列的季节成分的顺序。
在本文中,我将重点介绍季节性订单的重要性。
加载数据集
首先,我导入了 1990 年至 2019 年意大利入境游客的相关数据集作为一个pandas
数据框架。数据摘自欧洲统计:旅游业年度数据。
import pandas as pddf = pd.read_csv('source/tourist_arrivals.csv')
df.head()
作者图片
现在我把数据集转换成时间序列。这可以分三步完成:
- 我将
date
列转换为日期时间类型 - 我将
date
列设置为数据帧的索引 - 我将数据帧的
value
列赋给一个新变量,名为ts
。
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)
ts = df['value']
我通过绘制时间序列来探索它。我开发了matplotlib
库。
from matplotlib import pyplot as pltplt.plot(ts, label='prediction seasonal')
plt.grid()
plt.xticks(rotation=90)
plt.show()
作者图片
我注意到时间序列呈现季节性,因此 SARIMA 模型是合适的。此外,时间序列也呈现增长趋势。
(p,d,q)顺序
现在我将时间序列分成两部分:训练集和测试集。训练集将用于拟合模型,而测试集将用于评估模型。
ts_train = ts[:'2019-03-01']
ts_test = ts['2019-04-01':]
在另一个笔记本中,我已经解释了如何计算 SARIMA 模型的(p,d,q)阶,因此我将其手动设置为发现的值:
d = 1
p = 10
q = 7
(P,D,Q,M)顺序
(P,D,Q,M)阶是指自回归参数、差异、移动平均参数和周期的模型的季节性组件:
- d 表示季节性过程的积分顺序(使时间序列稳定所需的转换次数)
- p 表示季节成分的自回归顺序
- q 表示季节性成分的移动平均顺序
- m 表示周期性,即一个季节中的周期数,例如每月数据为 12。
为了评估季节顺序,我们必须从时间序列中提取季节成分。出于这个原因,我们利用了由statsmodels
库提供的seasonal_decompose()
函数。在输入参数中,我们可以指定分解模型(加法或乘法)以及我们是否想要推断趋势。该函数返回趋势、季节和剩余部分。
from statsmodels.tsa.seasonal import seasonal_decomposeresult = seasonal_decompose(ts, model='additive',extrapolate_trend='freq')
result.plot()
plt.show()
作者图片
订单
为了提取 D,我们必须检查季节成分是否是平稳的。我们定义一个函数,利用 Adfuller 测试来检查平稳性。
from statsmodels.tsa.stattools import adfuller
import numpy as npdef check_stationarity(ts):
dftest = adfuller(ts)
adf = dftest[0]
pvalue = dftest[1]
critical_value = dftest[4]['5%']
if (pvalue < 0.05) and (adf < critical_value):
print('The series is stationary')
else:
print('The series is NOT stationary')
然后,我们对时间序列的季节性部分调用check_stationarity()
函数:
seasonal = result.seasonal
check_stationarity(seasonal)
级数是平稳的,因此我们不需要任何额外的变换来使它平稳。我们可以设置 D = 0。
采购订单
P 的值可以通过查看季节分量的偏自相关(PACF)图来提取。在排除中间滞后的贡献后,PACF 可以被想象为序列和它的滞后之间的相关性。
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
plot_pacf(seasonal, lags =12)
plt.show()
作者图片
在 PACF 图中,值超出置信区间(浅蓝色)的最大滞后是 12,因此我们可以设置 P = 12。
q 顺序
Q 阶可以通过自相关(ACF)图计算。自相关是单个时间序列与其自身滞后副本的相关性。
plot_acf(seasonal, lags =12)
plt.show()
作者图片
从上图中,我们注意到,值超出置信区间的最大滞后是 8,因此 Q = 8。
火车模型
为了显示调整和不调整(P,D,Q,M)顺序的 SARIMA 模型之间的差异,我们拟合了两个模型,第一个模型没有季节性顺序,第二个模型有季节性顺序。
不按(P,D,Q,M)顺序拟合
我们利用了statsmodels
包的SARIMAX()
类,并将其配置为只处理(p,d,q)顺序。
from statsmodels.tools.eval_measures import rmse
nrmse = rmse(ts_pred, ts_test)/(np.max(ts_test)-np.min(ts_test))
nrmse
它给出了以下输出:
0.0602505102281063
符合(P,D,Q,M)顺序
我们通过传递seasonal_order
参数来拟合模型。此操作比上一个操作要求更多。
model_seasonal = SARIMAX(ts_train, order=(p,d,q), seasonal_order=(P,D,Q,12))
model_fit_seasonal = model_seasonal.fit()
我们计算预测和 NRMSE:
ts_pred_seasonal = model_fit_seasonal.forecast(steps=n_test)
nrmse_seasonal = rmse(ts_pred_seasonal, ts_test)/(np.max(ts_test)-np.min(ts_test))
nrmse_seasonal
它给出了以下输出:
0.08154124683514104
考虑
我们注意到,就 NRMSE 而言,没有季节性订单的模型优于另一个模型。
(P,D,Q,M)顺序没用吗?的确不是。对于短期预测,这两个模型的行为方式几乎相同。然而,对于长期预测,具有(P,D,Q,M)阶的模型更现实,因为它反映了增长趋势。
为了解释这个概念,我们可以在两种情况下计算一个长期预测:
N = 300
ts_pred = model_fit.forecast(steps=n_test+N)
ts_pred_seasonal = model_fit_seasonal.forecast(steps=n_test+N)
我们可以画出结果。我们注意到这两个模型之间有很大的不同。虽然没有(P,D,Q,M)阶的模型倾向于随时间减少,但是另一个模型反映了增加的趋势。
plt.figure(figsize=(10,5))
plt.plot(ts_pred_seasonal, label='prediction with P,D,Q')
plt.plot(ts_pred, label='prediction without P,D,Q')
#plt.plot(ts_test, label='actual')
plt.title('Multi-step Forecasting (manual parameters)')
plt.legend()
plt.grid()
plt.xticks(rotation=90)
plt.show()
作者图片
摘要
在本教程中,我解释了 SARIMA 模型中季节顺序对于长期预测的重要性。
本文解释的所有代码都可以作为 Jupyter 笔记本从我的 Github 库下载。
如果你想了解我的研究和其他活动的最新情况,你可以在 Twitter 、 Youtube 和 Github 上关注我。
相关文章
</4-different-approaches-for-time-series-analysis-7e2364fadcb9> [## 4 种不同的时间序列分析方法
towardsdatascience.com](/4-different-approaches-for-time-series-analysis-7e2364fadcb9) https://alod83.medium.com/june-articles-a-summary-of-my-june-articles-in-case-you-have-missed-them-8bc370375419
理解计算机视觉中的转换;
原文:https://towardsdatascience.com/understanding-transformations-in-computer-vision-b001f49a9e61?source=collection_archive---------3-----------------------
克里斯多夫·伯恩斯在 Unsplash 上拍摄的照片
入门指南
仿射变换和单应性概述
内容
- 仿射变换
- 单应性
—齐次坐标
—针丨孔丨摄像机型号
—单应性方程
- 参考
变换是计算机视觉的重要组成部分,理解它们如何工作为更高级的技术奠定了基础。
在这里,我将主要介绍仿射变换和单应性。
仿射变换:
仿射变换是最简单的变换形式。这些变换在满足以下特性的意义上也是线性的:
- 线条映射到线条
- 点映射到点
- 平行线保持平行
仿射变换的一些常见例子是平移、扩展、旋转、剪切和反射。此外,这些变换的任何组合(如膨胀后的旋转)都是另一种仿射变换。
基本仿射变换的示例(图片由作者提供)
与其将仿射变换分解成不同的情况,不如有一个统一的定义。因此,我们转向使用矩阵作为线性变换来定义仿射变换。如果你不熟悉将矩阵解释为空间的线性变换,3Blue1Brown 有一个关于这个主题的精彩视频:
为了将矩阵理解为线性变换
本质上,我们可以把仿射变换看作是首先用矩阵进行某种线性变换,然后用某种平移进行组合。
在 2D 的情况下,仿射变换的等式由下式给出:
2D 仿射变换的方程式(图片由作者提供)
这里,矩阵用条目( x 1 和 x 2)表示向量上的一些线性变换,例如反射、剪切、旋转、膨胀或所有四者的组合。需要注意的是,由于变换是线性的,所以它也一定是可逆的,所以矩阵的行列式是非零的。转换的最后一步是向量[ t 1, t 2]的平移,完成到向量[ y 1, y 2]的转换。
2D 仿射变换的例子(图片由作者提供)
仿射变换也可以用下面的等式推广到 n 维的维:
n 维仿射变换方程
这个变换通过应用线性变换 A (其中 A 是一个 *n×n,*可逆矩阵),然后应用向量 b ( b 具有维度 n ×1)的平移,将向量 x 映射到向量 y 。
总之,仿射变换可以表示为由一些平移组成的线性变换,并且它们在为计算机视觉修改图像方面极其有效。事实上,图像预处理很大程度上依赖于仿射变换来进行缩放、旋转、移位等。
单应性:
单应是一种投影变换,因为我们利用投影来关联两个图像。同形异义词最初被引入来研究视角的变化,它们使人们能够更好地理解当我们从不同的角度看图像时,图像是如何变化的。
使用单应变换视角(鸣谢:马里兰大学
单应性的研究是通过检查相机根据其位置和方向拾取不同图像的事实来进行的。本质上,单应是同一场景的两个图像之间的变换,但是从不同的角度。只有两种情况适用单应性(这两种情况都假设世界视图可以用平面来建模):
- 图像是由同一个相机从不同的角度拍摄的(世界现在基本上是一个平面)
- 两台摄像机从不同的位置观察同一平面
鸟瞰单应性的两个案例(图片由作者提供)
然而,为了使用单应性,我们必须首先设计工具来描述一幅图像在相机上的表现。更具体地说,如果给我们一个摄像机和一个图像平面(图像出现的地方,也是摄像机的属性),我们必须找到世界上的一个点(称为世界点)出现在图像平面上的位置。
找到图像上的点的坐标是单应性的关键
因为光是直线传播的,所以我们知道在图像平面上出现了一个笛卡尔坐标的世界点( X,Y,Z ),它位于图像平面与经过相机中心和世界点的直线(这条线就是光到达相机的路径)的交点处。
然而,为了正确地定义这个公式,我们必须绕道到射影几何中一个叫做齐次坐标的概念。
齐次坐标:
齐次坐标(或射影坐标)是另一种坐标系,其优点是齐次坐标的公式往往比笛卡尔坐标(x-y 平面上的点)中的公式简单得多。相比之下,齐次坐标使用 3 个坐标( x ', y ', z ')来表示空间中的点(一般来说,它们比笛卡尔坐标多使用一个坐标)。另外,将齐次坐标转换为笛卡尔坐标相对简单:
将齐次坐标转换为笛卡尔坐标
注意,当 z' =1 时,齐次坐标很好地映射到笛卡尔坐标。再者,当z’= 0 时,我们把对应的笛卡尔坐标解释为无穷远处的一点。记住这一点,让我们研究齐次坐标的一些应用。
首先,齐次坐标中的直线,只用 3 个点就可以表示出来。具体来说,你可以把一条线 l 在齐次坐标下表示为( l 1, l 2, l 3)。那么,这条线就是所有点的集合 p= ( x , y , z ),使得 l 与 p 的点积为 0。
用齐次坐标表示的线(图片由作者提供)
注意的第二个性质是,给定两点 p 1=( a , b , c )和 p 2 = ( d , e , f ),直线 l 经过 p 1 和p
齐次坐标中两点之间的线(图片由作者提供)
注意的最后一个性质是:两条直线 l 1 和 l 2 的交点(齐次坐标中)是两条直线的叉积给出的点 p 。
齐次坐标中两条线的交点(图片由作者提供)
有了这些性质,我们现在就能很好地理解单应性背后的公式。
针丨孔丨摄像机型号:
我们现在回到我们的问题,在给定所述摄像机的位置和方向的情况下,找到一个世界点 ( X 、 Y 、Z)——这是在笛卡尔坐标中——位于所述摄像机的图像平面的位置。
特别地,我们发现世界点( X , Y , Z ,1)位于图像平面的点(X’,Y’,Z’)上,其中两个点在齐次坐标中,并且通过以下等式相关( f 是描述相机焦距的常数):
世界点齐次坐标与像平面齐次坐标的关系方程
从这里我们可以把( x ', y ', z ')转换成前面所说的图像平面上的笛卡尔坐标( x , y )。
事实证明,将世界点转换为图像平面上的点的矩阵可以很好地分解,为我们提供了一种直观的方式来理解矩阵的作用:
矩阵可以理解为两个动作:(1)缩放,(2)压缩到更低维度
但是,由于图像上的坐标系不同于笛卡尔坐标系(左上角是像素坐标中的(0,0)),我们必须执行一次最终转换,以从同质图像平面坐标(x’、y’、z’)转换为同质像素坐标(u’、v’、w’)。
像素坐标的表示(图片由作者提供)
因此,我们首先通过除以像素的大小来缩放我们的图像平面坐标(以便将它们转换成像素),像素的大小在 u 方向上是 ρu 并且在 v 方向上是 ρv 。你可以认为这是把米这样的单位转换成像素。接下来,我们必须通过一些 u 0 和 v 0 来平移坐标,这样像素坐标的原点就在适当的位置。把这两个变换放在一起,我们得到下面的公式:
将图像平面坐标转换成像素坐标。
最后,将所有东西放在一起,我们可以通过将世界点( X , Y , Z ,1)转换为像素坐标(u’,v’,w’),来完成我们的相机模型,其中两者都以齐次坐标给出:
相机模型的方程式
外部参数可以被认为是一个术语,它为我们提供了关于摄像机的方向(存储在旋转矩阵 R 中)和位置(存储在向量 t 中)的信息。
在实际中,我们并不经常知道所有的参数,所以我们可以近似相机矩阵来代替,它只是一些 3×4 的矩阵(通过矩阵乘法性质);这是通过校准摄像机来实现的。
此外,相机矩阵的一个重要属性是缩放 C 的条目给出了描述同一相机的新相机矩阵。这是因为如果我们将 C 乘以某个常数 λ ,那么同质像素坐标的所有条目也会被 λ 缩放。然而,当我们从齐次坐标转换到笛卡尔坐标时(如前所示), λ 被抵消,留下与缩放前相同的笛卡尔坐标。因此,因为比例因子是任意的,所以让相机矩阵的右下角的条目为 1 已经成为惯例。
相机矩阵的标准形式
有了这些定义的方程,我们就非常接近获得单应性的公式。
单应方程;
让我们再一次检查针丨孔丨摄像机的设置。在这个设置中,我们的摄像机将拍摄位于一个平面上的点 P =( X , Y , Z ),其中点 P 在图像平面上的同质像素坐标中显示为(u’,v’,w’)。现在,我们可以用一个聪明的技巧来选择坐标系。也就是说,我们让 X 和 Y 轴位于平面内,使得 Z 轴指向平面外。因此,平面上所有点的 Z 坐标为 0,意味着 P 的形式为 P =( X , Y ,0)。
方便选择坐标系(坐标显示为 齐次)(图片由作者提供)
现在,将其代入我们的相机方程,并使用 Z =0,我们得到以下简化:
利用照相机等式中的 Z=0
这个新的相机矩阵被称为单应矩阵 矩阵 H ,有 8 个未知条目(因为右下角的 1 是固定的)。通常,平面单应矩阵的条目用 H 而不是 C 表示,如下所示:
平面单应性方程
我们现在最后的任务是估计 H 的条目。由于单应矩阵中有 8 个未知数,并且平面上的每个世界点有 2 个坐标,我们将需要在 4 个世界点上校准摄像机,以便估计 H 的所有条目。
概括地说,单应性是一种变换,当两个图像是同一平面的图片,但从不同的角度看,我们可以使用它将一个图像转换为另一个图像。在数学上,这种变换由单应矩阵执行,该单应矩阵是具有 8 个未知数的 3×3 矩阵,并且可以通过用 4 个对应点校准图像来估计(使用更多点获得更好的近似,但是 4 是所需的最小值)。
带有黄色校准点的单应性示例(图片由作者提供)
总而言之,homgraphies 是一个强大的工具,可应用于像增强现实(将某些图像投影到环境中)和图像拼接(将多幅图像组合起来创建一个更大的全景图)等领域。
参考
*【https://en.wikipedia.org/wiki/Homogeneous_coordinates *
http://www . cs . UMD . edu/class/fall 2019/cmsc 426-0201/files/16 _ homo graphy-estimation-and-decomposition . pdf
https://medium . com/swlh/image-processing-with-python-image-warping-using-单应矩阵-22096734f09a
https://www.youtube.com/watch?v=l_qjO4cM74o
https://www.youtube.com/watch?v=fVJeJMWZcq8
使用 Doccano 了解文本数据
原文:https://towardsdatascience.com/understanding-your-textual-data-using-doccano-70e51656c2d2?source=collection_archive---------15-----------------------
文本标注工具不仅仅用于创建数据集。
图 1: Doccano
每个研究人员应该做的第一件事就是了解他们的数据和领域。有许多方法可以做到这一点,从手动检查列和行,打印统计数据,使用 pandas_summary,使用特征选择方法,使用通气管,可视化数据,解释您的模型等。
我认为当你遇到新数据需要被标记成几个类的时候,你需要做的第一件事就是自己注释它。
坐在房间里,在屏幕前,对你的数据做几个小时的注释,可以让你深入理解它。设置完成后,大多数注释工具允许您进入工厂思维模式,您可以在每个屏幕上获得一个注释,通过使用快捷键,您可以简化并适应快速标记程序。
问题是
然而,您可能需要考虑另一个场景,想象一个专家团队,每个人对所讨论的领域都有自己的观点。
你认为每个人都同意他们的同事吗?
你觉得大家都一致吗?
当然不是!
7 个注释神话
这些神话是人们不能就任何事情达成一致的一些最常见的原因,也是为什么你的带注释的数据集充满了噪音。全文请看人群真相和人类注释的七大神话。
- 一个事实大多数数据收集工作都假设每个输入示例都有一个正确的解释。
- 不一致是不好的为了提高注释数据的质量,应该避免或减少注释者之间的不一致。
- 详细的指导方针有助于当具体案例持续引起分歧时,增加更多说明以限制解释。
- 一个就够了大多数带注释的例子都是一个人评估的。
- 拥有领域知识的专家是更好的人类注释者提供更好的注释数据。如图 2 所示。
- 所有的例子都是平等的,运用基础真理的数学对每个例子都一视同仁;你要么匹配正确的结果,要么不匹配。
- 一旦完成,永远有效一旦为一项任务收集了人工注释的数据,这些数据就会被反复使用而不会更新。新的批注数据与以前的数据不一致。
图 2: 神话 5 —专家是更好的人类注释者,拥有领域知识,可以提供更好的注释数据。不是 **真的!**以下是专家和众包的对比。我们可以看到,专家收敛得更快,但结果质量相似。
解决方案
是使用多用户注释工具,并在对每个样本进行强制多数投票后,创建一个可以与之前的假设进行比较的数据集,这可以暂时作为您的基本事实(参见误区 7)。此外,我们希望验证我们的团队在多大程度上彼此一致,以及他们是否彼此一致,即评分者间可靠性和评分者内可靠性** 。**
这是我建议你每次进入一个新的领域都要做的事情。如果你想知道你可以使用哪些工具,这几天有很多文本注释工具,如 Doccano (用于本文)、 Prodigy 、 LightTag 等。
如果你好奇的话,我写了一篇关于如何创建带有行业要求和约束的学术级数据集的指南。
多卡诺
Doccano 是一款面向机器学习从业者的开源注释工具。它为文本分类、序列标记和序列到序列任务提供了注释功能。使用 Doccano,您可以为情感分析、命名实体识别、文本摘要等创建标记数据。你可以在几个小时内建立一个数据集。它具有协作注释、多语言支持、移动支持、表情符号支持和 RESTful API。”如果你好奇,你可以试试他们的注释演示这里。
装置
如果您想自己添加注释,安装非常简单
pip install doccanodoccanonavigate to [http://localhost:8000/](http://0.0.0.0:8000/)
但是,如果您想将 Doccano 放在远程机器上,以便允许协作注释,即多用户、持久性和健壮性。您将需要使用 Docker 安装过程。
docker 安装有其独特之处。目前,它允许您将数据保存到 docker 内的一个目录中,但如果发生一些事情,数据将会消失。为了在外部保存您的数据,您需要将 -v data:/data 参数添加到 docker create 命令中。这个命令允许你将你的本地目录指向一个外部目录,因此如果发生什么事情,不会丢失你的 doccano.db 文件。
1\. Install Docker.
2\. docker pull doccano/doccano
3\. mount a persistent drive onto /data.
4\. docker container create --name doccano_db -v /data:/data -e “ADMIN_USERNAME=admin” -e “ADMIN_EMAIL=admin@example.com” -e “ADMIN_PASSWORD=password” -p 8000:8000 doccano_db
5\. docker container start doccano_db
设置
Doccano 允许您轻松地导入和导出数据。我推荐使用 JSONL(图 3a)。Doccano 还允许您轻松地设置类标签及其快捷键,如图 3b 所示。
图 3a:导入用户界面。
图 3b:标签创建 UI。
注释
Doccano 可以开箱即用,用于多类任务,例如,情感分析、命名实体识别和翻译任务,如图 4a、4b 和 4c 所示。
图 4a: Doccano 情感分析任务
图 4b: Doccano 命名实体任务
图 4c: Doccano 翻译任务
管理模式
作为项目的管理员,您可以检查一些统计数据,比如标签分发、项目完成、用户进度,如图 5 所示。这些工具非常方便,尤其是当你在做这个单调乏味而且非常无聊的注释任务的时候,如果你需要游戏化并且给团队成员注入一些激情的话。
图 5:管理仪表板。
指标
在导出多用户注释数据集后,有多种方法可以测量一致性。我推荐使用来自 Github 和 Scikit-learn 的 Oliver 的 Disagree 包。
- Cohen 的 Kappa(0–1,两个注释者,根据概率进行了修正)
- fleiss Kappa(0–1,多个注释者,根据概率进行了修正)
- krippendorff alpha(0–1,多个标注器,随机修正,允许缺少值)
- 精确度/召回/ F1
正如我们在图 6 中看到的,即使是专家也不会完全同意彼此的观点。
图 6:一个一致矩阵,X 和 Y 轴是专家,在对角线上我们可以看到他们同意自己,但不出所料专家之间的一致度不高。
好处
我们从这个过程中得到了一些有价值的东西:
- 我们对数据有了更深入的了解。
- 我们可以让专家讨论分歧和未标记的样本,并进一步了解领域内的困难
- 我们有一个基于多数的基础事实数据集,我们可以计算一段时间。
结论
在本文中,我想说服您为什么注释主要对于理解您的领域很重要,而不仅仅是对于创建数据集以及如何使用 Doccano 来实现这个目标。
我恳求你在进入一个新的领域时练习自我注释,同时制定你的类标签,甚至在考虑寻找算法解决方案之前。
我要感谢塞缪尔·杰弗罗金的宝贵见解,感谢他在许多个月前为我指明了道路。
Ori Cohen 博士拥有计算机科学博士学位,主要研究机器学习和脑机接口(BCI)。他在一家智能城市初创公司领导了一个数据科学团队,主要利用机器和深度学习进行自然语言处理(NLP)和理解(NLU)研究。目前,他是 TLV 新遗迹公司在 AIOps 领域的首席数据科学家。他定期在 Medium.com 的上撰写关于管理、流程和所有数据科学的文章。
理解零射击学习——让 ML 更人性化
原文:https://towardsdatascience.com/understanding-zero-shot-learning-making-ml-more-human-4653ac35ccab?source=collection_archive---------0-----------------------
一个模型如何识别它没见过的东西的直观概述。
梁杰森在 Unsplash 上的照片
简介——什么是零起点学习?
Z ero-shot 学习允许一个模型识别它以前没有见过的东西。
想象一下,你的任务是设计最新最棒的机器学习模型,可以对所有动物进行分类。是的,所有的动物。
使用您的机器学习知识,您会立即理解我们需要一个带标签的数据集,每个动物至少有一个例子。世界上有 1,899,587 种已描述的物种,所以你需要一个包含大约 200 万个不同类别的数据集。
呀。
你的模型要分类的动物。Unsplash 上的照片。
你可能已经注意到了,获取大量高质量的标签数据是很困难的。非常辛苦。
当你的模型需要学习大量不同的种类(比如动物种类)时,这并没有什么帮助。
那么我们如何解决这个问题呢?
一种方法是减少我们的模型对标记数据的依赖。这就是零触发学习背后的动机,在这个过程中,你的模型学习如何对以前没有见过的类进行分类。
在动物物种分类示例中,您的模型可能能够预测右下角的图像是一只“熊猫”,即使它在训练期间没有明确看到一只“熊猫”的标记示例。
很疯狂吧。!
在下一节中,我们将通过一些采用零拍摄设置的模型示例来了解这种看似神奇的方法是如何工作的。
零拍学习是如何运作的?
虽然在文献中有多种零镜头学习的方法,但本文主要关注 OpenAI 最近提出的一种称为对比语言-图像预训练(CLIP)的方法,该方法在零镜头设置中表现良好【2】。
CLIP 的目标是学习如何在没有任何明确标签的情况下对图像进行分类。
直觉
就像传统的监督模型一样,CLIP 有两个阶段:训练阶段(学习)和推理阶段(做出预测)。
在训练阶段,CLIP 通过“阅读”每个图像对应的辅助文本(即句子)来学习图像,如下例所示。
CLIP 架构的可能输入示例。幸运的猫在 Unsplash 上的照片
作为一个人类(假设你以前从未见过猫),你可以阅读这篇文字,并可能破译图像中的三个的东西是“猫”。如果你看到了足够多的配有“猫”字说明的猫的图片,很有可能你会非常擅长判断一张图片中是否有猫。
类似地,通过查看不同对象的 4 亿个图像-文本配对,该模型能够理解特定短语和单词如何对应图像中的特定模式。一旦有了这种理解,模型就可以使用这种积累的知识来推断其他分类任务。
但是等一下。
你可能会疑惑,这种“辅助文本”在技术上不就是一种标签吗,从而渲染这个过程而不是我一开始承诺的无标签学习?
虽然辅助信息(即标题)是一种监督形式,但它们不是标签!通过这些辅助信息,我们能够使用信息丰富的 非结构化数据,而不是必须自己解析非结构化数据来手工制作单个标签(即“这是我的三只可爱的猫……”→“猫”)。
设计一个标签需要时间,并删除潜在有用的信息。通过使用 CLIP 的方法,我们可以绕过这个瓶颈,最大化模型可以访问的信息量。
潜水更深——零射击训练
模型究竟如何能够从这些辅助文本中学习?
正如该架构的名字所暗示的那样,CLIP 使用了一种叫做对比学习的技术来理解图像和文本配对之间的关系。如果你不熟悉对比学习,我建议在继续之前先看看这篇关于对比学习的文章。
剪辑方法概述。图来自[2]。
本质上,CLIP 的目标是*最小化图像编码和相应文本之间的差异。*换句话说,模型应该学会使图像的编码和相应文本的编码尽可能相似。
让我们进一步分析这个想法。
**什么是编码?**编码只是数据的低维表示(上图中的绿色和紫色方框)。理想情况下,图像或文本的编码应该分别代表该图像或文本最重要的、可区分的信息。
例如,所有猫的图像应该有相似的编码,因为它们都有猫在里面,而它们应该有不同于狗的编码。
请注意,在这个理想世界中,相似对象的编码也是相似的,不同对象的编码也是不同的,对图像进行分类变得非常容易。如果我们给模型输入一个图像,编码与模型见过的其他一些“猫”编码相似,它就可以说是一只“猫”!
看起来好的图像分类的关键是学习理想的图像编码。这实际上是 CLIP(和大部分深度学习)背后的整个前提!我们从糟糕的编码开始(即每个图像的随机编码),我们希望模型学习理想的编码(即猫图像有相似的编码)。
为了更直观地了解这种学习数据表示的想法,我推荐下面的文章:
**为什么图像编码应该与其对应的文本编码尽可能相似?**现在我们知道了什么是编码,以及为什么学习好的编码很重要,我们可以探索为什么我们要强制模型使图像和文本编码相似。
回想一下,我们的最终目标是学习如何对图像和图像进行分类,因此我们需要学习好的图像表示(编码)。当我们有标签时,我们能够通过最小化模型输出和预期输出(标签)之间的差异来学习好的编码。
但是在 CLIP 的情况下,我们没有单一的模型输出,也没有单一的期望输出。相反,我们可以将训练图像的图像编码视为模型输出,将相应标题的文本编码视为预期输出。
事实上,我们可以想象**模型正在学习如何为我们创造好的标签。**由于文本编码器也在这个过程中更新,随着时间的推移,模型学习如何从文本中提取更重要的信息,从而给我们一个更好的文本编码(预期输出)。
考虑到这一点,我们应该尽量减少图像和文本编码之间的差异。*这是因为我们知道相似的图像可能会有相似的文本编码,*就像在标签设置中相似的图像会有相同的标签。因此,模型将学习为相似的图像生成相似的编码。
潜得更深——零射击推断
一旦该模型在足够多的图像-文本配对上得到训练,它就可以用于*推理(使用该模型对看不见的数据进行预测)。*这是设置变得非常聪明的地方。
在推理阶段,我们通过首先获得所有可能标签的列表来设置典型的分类任务。因此,如果我们要预测动物物种,我们将需要一个所有动物物种的列表(例如,企鹅、熊猫、刺螈等。)(图中步骤 2)。
Polina Razorilova 在 Unsplash 上拍摄的照片。作者图改编自[2]中的图。
然后,每个标签将由步骤 1 中预先训练的文本编码器进行编码。
现在我们有了标签编码,从 T₁到 Tₙ,我们可以把我们想要分类的图像,通过预训练的图像编码器,并使用一个叫做 余弦相似度 的距离度量来计算图像编码与每个文本标签编码的相似度。
我们现在将图像分类为与图像具有最大相似性的标签*。我们可以这样做,因为我们知道模型已经学会了为图像生成尽可能与其文本副本相似的编码,其中大多数可能包含我们试图分类的标签。*
瞧啊。我们已经实现了零射击能力!
有趣的是, CLIP 是一种相对较新的方法,与更传统的零镜头学习方法相比,它具有独特的简单性。这些概念中的一些,包括基于嵌入的方法和生成方法将在下面的文章中直观地解释。
https://www.kdnuggets.com/2021/04/zero-shot-learning.html
无论使用哪种方法,零射击学习的一个共同主题是,我们可以使用一些不是明确标签的**辅助信息(即文本描述)**作为监督的弱形式。
零射击学习的潜在应用
一般来说,零触发学习在需要大型标注数据集但不容易获得的情况下最有用。
下面,我们来看看【3】中概述的一些潜在的现实应用。
新冠肺炎胸部 x 光诊断
新冠肺炎胸部 x 射线诊断是一个完美的(如果你在 2021 年阅读这篇文章,这是一个热门话题)例子,说明零射击学习如何应用于医学相关和低标签设置。
由于在疫情的初始阶段很少有新冠肺炎阳性的胸部 x 射线,因此很难创建一个高性能的模型来区分 COVID 与非 COVID,或 COVID 与更常见的呼吸系统疾病,如肺炎。
胸部 x 光的例子。照片由疾控中心在 Unsplash 上拍摄
为了解决这个标签很少的问题,我们需要一个模型,它可以了解新冠肺炎只看过其他疾病的图像和新冠肺炎胸部 x 光片的一些辅助信息——没有 COVID 的显式标签。
在这种情况下,我们可以使用新冠肺炎胸部 x 光片的文本描述作为一种辅助信息。下面是一个例子。
"可见双侧多灶斑片状 GGOs 和实变."—【3】
据我所知,还没有正式发表的作品证明零炮适用于 COVID 分类。然而,辅助文本信息的可用性突出了零射击学习应用于这样一个医学上重要任务的潜力。
自动驾驶汽车
特斯拉的图像。亚历山大·赞恩在 Unsplash 上拍摄的照片
人工智能几乎肯定会看到它以前没有看到的东西的另一个关键例子是自动驾驶汽车的感知系统。
事实上,即使是人类在路上看到新的物体,他们也不知道如何做出反应。如果我们想设计安全、坚固的自动驾驶汽车,我们需要让它们具备适应未知环境的能力。
同样,据我所知,很少有作品将零射击方法应用于自动驾驶感知系统。然而,一些有趣的想法包括使用概念车的文本描述来教一个模型区分普通汽车[3],并以零射击的方式将模拟中学习的政策转移到一个城市[1]。
关键要点
- 零镜头学习是一种设置,在这种设置中,模型可以学习识别以前在训练中没有明确看到的东西。
- 有不同的零射击学习方法,但一个共同点是在训练过程中使用或编码辅助信息,如文本描述,而不是显式标签。
- 零射击学习在现实世界中有几个潜在的应用——从新冠肺炎病诊断到无人驾驶汽车。
本文讲解的作品只是冰山一角!随着该领域的发展,我们稳步朝着我们许多人设想的人工智能前进:一个不受标记数据结构严格限制的人工智能,一个可以理解以前从未见过的东西的人工智能,一个更像人类的人工智能。
参考
【1】Jang,k .,Vinitsky,e .,Chalaki,b .,Remer,b .,Beaver,l .,Malikopoulos,a . a .&Bayen,A. (2019,4 月)。模拟成比例的城市:通过自动车辆的交通控制的零射击政策转移。第 10 届 ACM/IEEE 信息物理系统国际会议论文集*(第 291-300 页)。*
【2】拉德福德、a .、金、J. W .、哈拉奇、c .、拉梅什、a .、戈、g .、阿加瓦尔、s .……&苏茨基弗,I. (2021)。从自然语言监督中学习可转移的视觉模型。arXiv 预印本 arXiv:2103.00020 。
【3】雷扎伊,m .&沙希迪,M. (2020)。零触发学习及其在自主车辆新冠肺炎诊断中的应用:综述。智能医学,100005。
笔记
- 是的,“带刺的笨蛋”是真实存在的。请参见https://www . tree hugger . com/animals-with-completely-almony-names-4864307
- 这是对 CLIP 的简化解释。建议看一下 OpenAI 的论文。
- 根据[维基百科](https://en.wikipedia.org/wiki/Concept_car#:~:text=A%20concept%20car%20(also%20known,may%20not%20be%20mass%2Dproduced.)的说法,**概念车**是“展示新款式和/或新技术的汽车”。换句话说,它们看起来很古怪,足以与普通汽车区分开来。
如何撤销 Git 中的最后一次本地提交
原文:https://towardsdatascience.com/undo-last-local-commit-git-5410a18f527?source=collection_archive---------31-----------------------
了解如何在 Git 中撤销最近的本地提交
由 Roman Synkevych 在 Unsplash 上拍摄的照片
介绍
Git 是帮助开发人员、数据科学家和工程师编写代码版本的最强大的工具之一。使用 Git 时,一个非常常见的场景是当您意外提交文件时,您需要撤销最近的提交,以避免将这些文件中所做的更改推送到远程主机。
在今天的文章中,假设您没有将最后一次提交推送到远程主机,我们将讨论几个可能的选项。具体来说,我们将探索如何
- 撤消最近的提交,并清除对提交的文件所做的所有更改
- 撤销最后一次提交,并保留修改文件中的更改
- 撤销最近的提交并且保留文件和索引中的更改
撤消上次提交并放弃对文件所做的所有更改
有时,除了撤销最近的提交,您可能还想放弃对该特定提交中包含的文件所做的所有更改。在这种情况下,你需要做一个硬复位。
**git reset** **--hard HEAD~1**
--hard
标志表示git reset
命令将重置机头、索引和工作树。这意味着提交将被撤销,此外,对文件所做的更改也将被丢弃。HEAD~1
翻译为“使用第一个父代从HEAD
返回 1 次提交”。通常一个提交只有一个父级,所以在大多数情况下这应该可以解决问题。注意HEAD~1
相当于HEAD~
。
撤消上次提交,但保留对文件所做的更改
或者,您可能仍然希望进行最近的提交,但同时在本地保留对文件所做的更改。在这种情况下,您只需在运行git reset
命令时指定HEAD~1
:
**git reset HEAD~1**
该命令将指示 Git 将指针HEAD
向后移动一次。但是,对文件所做的更改不会受到影响。现在,如果您运行git status
,您应该仍然能够在本地看到对文件所做的更改。
撤消上次提交并保留索引和本地文件更改
最后,您可能想要撤销最后一次提交,保留对文件的更改,同时**保留索引,**也是如此。
索引(也称为暂存区)是准备新提交的地方,它包含新提交中要包含的所有内容。例如,每次你运行git add <filename>
的时候,一个文件被从工作的三个文件中添加(或更新)到索引中。实际上,索引是一个存储在<repo>/.git/index
下的二进制文件,包含。
**git reset --soft HEAD~1**
--soft
标志表示git reset
命令只会重置机头,而索引和工作树保持不变。
现在,如果你运行git status
,你应该能够看到相同的文件仍然在索引中。
最后的想法
在今天的简短指南中,我们探索了几种不同的方法来撤销 Git 中最近的本地提交。有时,您可能想要撤消最近的提交,并放弃对已修改文件所做的所有更改,而在其他情况下,您可能只想撤消最近的提交,但同时保留更改。
但是请注意,只有当您尚未将提交推送到远程主机时,我们在本文中讨论的选项才适用。关于git reset
命令的更多细节,您可以在命令行中运行git reset -h
来显示使用说明。
成为会员 阅读介质上的每一个故事。你的会员费直接支持我和你看的其他作家。你也可以在媒体上看到所有的故事。
https://gmyrianthous.medium.com/membership
你可能也会喜欢
https://betterprogramming.pub/how-to-merge-other-git-branches-into-your-own-2fe69f70a2b4 https://betterprogramming.pub/11-python-one-liners-for-everyday-programming-f346a0a73f39
歧视性人工智能举例说明
原文:https://towardsdatascience.com/unethical-ai-this-is-how-it-looks-like-fd14ec94410d?source=collection_archive---------26-----------------------
歧视性人工智能以实例和视觉效果展示
右边的照片由 Unsplash 上的 Divya Agrawal 拍摄,左边的图片由作者拍摄
人工智能越来越多地用于做出直接影响我们的决定,例如工作申请、我们的信用评级、约会网站上的配对。因此,人工智能是非歧视性的,决策不会偏向某些种族、性别和肤色,这一点很重要。
歧视性人工智能是一个非常广泛的主题,超出了纯粹的技术方面。然而,为了让它更容易理解,我将使用例子和视觉效果来展示歧视性的人工智能。这将会给你一个发现歧视性人工智能的方法。
语境
让我首先建立这个例子的背景。业务环境与银行业务中的信用贷款流程相关。让我们假设银行已经建立了一个人工智能,它将查看贷款申请数据,并决定是否批准或拒绝它。
业务内容的图示(作者提供的图片)
贷款申请数据包含以下信息:收入、性别、职业、子女数量、个人是否拥有房屋或汽车等资产。
先看歧视艾
人工智能接受训练的数据也具有关于先前贷款是否被接受的决策的历史信息。
训练数据快照(图片由作者提供)
让我们假设人工智能已经在决策树算法上接受了训练,如下所示。决策树中的每个节点代表数据列和一个阈值。
基于决策树的贷款审批 AI 模型(图片由作者提供)
该决策树的输出是“是”或“否”,指示信用贷款是被接受还是被拒绝。现在,当你看到性别 _ 女性或性别 _ 男性等节点时,这已经表明人工智能模型正在区分男性和女性,以做出贷款批准的决定。这是一个可能的迹象,表明这个人工智能是歧视性的。
确认大赦国际的歧视性质
现在让我们举一些例子来证实人工智能是否具有歧视性。让我们看看这两个应用程序。一封来自职业为护士的女性,另一封来自职业为销售经理的男性。
证实 AI 歧视行为的例子。仅显示示例字段(图片由作者提供)
工资水平大致相等,女性的工资略高于男性申请人。两位申请人都拥有一辆车和一栋房子。
现在让我们为两个申请人做贷款批准预测。女性申请人的决策途径如下所示。决定是不批准贷款。你可以看到路径中的一个决策节点是性别是女性。
女性候选人的决策路径(图片由作者提供)
现在让我们预测一下男性申请人。下面显示的是决策路径。令人惊讶的是,人工智能的决定是批准,并给出了一个大大的是。
男性候选人的决策路径(图片由作者提供)
尽管两位申请人的收入水平相似,拥有的资产也相似,但女性申请人被拒绝了,而男性申请人获得了批准。
这是一个明显的迹象,表明这是一个歧视性的人工智能。
理解为什么这个人工智能是歧视性的
让我们使用 SHAP(Shapely Additive Explanation)分析来深入理解为什么 AI 会做出如此歧视性的决定。这是女申请人的 SHAP 分析。
女性申请人的 SHAP 分析
蓝色条表示对信贷批准有积极贡献的因素,红色条表示对信贷批准有消极贡献的因素。收入和拥有房子是积极的贡献,但身为女性有负面影响。
这是 SHAP 对男性求职者的分析。
男性申请人的 SHAP 分析
对于男性求职者来说,收入和住房是积极因素,但身为男性也是积极因素。所以很明显,身为女性对女性申请者没有帮助。
歧视行为的根源
现在让我们看看歧视行为背后的根源。这是人工智能训练数据的柱状图。X 轴是性别,Y 轴是 AI 的训练数据中的信用贷款批准数。
训练数据中的偏差
培训数据中获得批准的男性申请者人数几乎比女性申请者多 3 倍。这被称为“偏见”,这导致了歧视性的人工智能。
无性别模式——一种可能的解决方案?
我们可以尝试创造一个没有性别的模型。让我们看看是否有帮助。这是没有性别的决策树模型。它在决策过程中没有性别特征。
没有性别的决策树模型(图片由作者提供)
以下是女性候选人的决策路径(不考虑性别领域)。决定仍然是不批准信用贷款。
女性候选人在无性别模型上的决策路径(图片由作者提供)
以下是男性候选人的决策路径(不考虑性别字段)。决定是批准信贷贷款。
无性别模型中男性候选人的决策路径(图片由作者提供)
所以即使我们去掉了性别,也没有什么变化。为什么会这样?现在让我们再一次使用这里显示的热图来分析 AI 被训练的历史数据。
培训数据中批准数量的热图
热图的 X 轴是性别,Y 轴是职业。我们看到人工智能被训练的数据有更多的女性是护士,更多的男性是销售人员。
由于女候选人是护士,申请被 AI 拒绝。同样,由于男性候选人是一名销售人员,申请被 AI 接受。
因此,即使我们去除了性别领域,职业仍然是性别的替代品。
因此,无论有无性别,这两种模式都会导致相同的歧视性结果。
数据中性别的平等代表性
歧视性人工智能的解决方案是在用于训练人工智能的数据中男女具有平等的代表性。
性别平等原则也需要适用于数据。
额外资源
网站(全球资讯网的主机站)
你可以访问我的网站进行零编码分析。https://experiencedatascience.com
每当我发布一个新的故事,请订阅保持通知。
https://pranay-dave9.medium.com/subscribe
你也可以通过我的推荐链接加入 Medium
https://pranay-dave9.medium.com/membership
Youtube 频道
这是我在 https://www.youtube.com/c/DataScienceDemonstrated 的 YouTube 频道
T5 的链接
SQL 中的 UNION:一个必须知道的子句
原文:https://towardsdatascience.com/union-in-sql-a-must-know-clause-1e5a4d7f7bde?source=collection_archive---------19-----------------------
分析多个表的结果
来源:图片来自 Pixabay
我们在 SQL 中学习的许多常见查询(如 GROUP BY)通常用于孤立地分析一个表。在将两个表连接在一起并将它们视为一个表时,也经常使用 JOIN 子句。
但是,经常会有需要跨多个表分析结果的情况。使用 UNION 子句可以做到这一点,本文将举例说明该子句如何工作。
UNION vs UNION ALL vs INTERSECT
考虑以下两个表:
houses=# select * from onebedroom;
city | price
----------+-------
Paris | 1000
Munich | 850
Rome | 930
Helsinki | 1200
(4 rows)houses=# select * from onebedroom_v2;
city | price
-----------+-------
Helsinki | 1200
Berlin | 750
Prague | 500
Amsterdam | 1400
(4 rows)
这两个表格显示了欧洲主要城市一居室公寓的价格(数值是假设的,由作者虚构)。
UNION、UNION ALL 和 INTERSECT 如何组合这两个表的结果?
在这两个表中,我们可以看到城市赫尔辛基有一个重复的值(价格为€每月 1200)。让我们看看这个值在三个子句中是如何处理的。
联盟
当用 UNION 组合这两个表时,我们可以看到只保留了 Helsinki 条目的一个实例——删除了重复的条目。
houses=# select * from onebedroom union select * from onebedroom_v2;
city | price
-----------+-------
Paris | 1000
Prague | 500
Helsinki | 1200
Berlin | 750
Amsterdam | 1400
Rome | 930
Munich | 850
(7 rows)
UNION ALL 怎么样?
联合所有
当使用 UNION ALL 子句时,我们可以看到赫尔辛基的两个条目保留在表中,没有删除重复的条目。
houses=# select * from onebedroom union all select * from onebedroom_v2;
city | price
-----------+-------
Paris | 1000
Munich | 850
Rome | 930
Helsinki | 1200
Helsinki | 1200
Berlin | 750
Prague | 500
Amsterdam | 1400
(8 rows)
横断
INTERSECT 子句与 UNION 子句的工作方式不同,因为该子句只标识两个表共有的条目,并维护该条目—所有其他条目都被删除。
在这个例子中,我们可以看到赫尔辛基条目被返回,因为这个条目对两个表都是公共的——所有其他条目都不存在。
houses=# select * from onebedroom intersect select * from onebedroom_v2;
city | price
----------+-------
Helsinki | 1200
(1 row)
对表格中的值求和并求平均值
现在,让我们考虑下面的表(同样,值是假设的,由作者编造)。
houses=# select * from onebedroom;
city | price
--------+-------
Paris | 1000
Munich | 850
Rome | 930
(3 rows)houses=# select * from twobedroom;
city | price
--------+-------
Paris | 1400
Munich | 1300
Rome | 1500
(3 rows)houses=# select * from threebedroom;
city | price
--------+-------
Paris | 2800
Munich | 2200
Rome | 2000
(3 rows)
在巴黎、慕尼黑和罗马,我们希望:
- 对每个城市的值求和
- 平均每个城市的值
让我们看看如何在第一个实例中对值求和。我们将从前两个表开始。
houses=# select city,sum(price) total
houses-# from
houses-# (
houses(# select city,price
houses(# from onebedroom
houses(# union all
houses(# select city,price
houses(# from twobedroom
houses(# ) t
houses-# group by city;
city | total
--------+-------
Rome | 2430
Paris | 2400
Munich | 2150
(3 rows)
在上面的脚本中,我们可以看到 UNION ALL 子句被用来组合两个表的结果,并且价格的总和( sum(price) )被定义为一个总值。
要对三个表中的值求和,只需使用两个 UNION ALL 子句:
houses=# select city,sum(price) total
houses-# from
houses-# (
houses(# select city,price
houses(# from onebedroom
houses(# union all
houses(# select city,price
houses(# from twobedroom
houses(# union all
houses(# select city,price
houses(# from threebedroom
houses(# ) t
houses-# group by city;
city | total
--------+-------
Rome | 4430
Paris | 5200
Munich | 4350
(3 rows)
对于平均值,该条款实际上保持不变。这一次,我们只是要求价格的平均值,而不是总和。
houses=# select city,avg(price) total
houses-# from
houses-# (
houses(# select city,price
houses(# from onebedroom
houses(# union all
houses(# select city,price
houses(# from twobedroom
houses(# union all
houses(# select city,price
houses(# from threebedroom
houses(# ) t
houses-# group by city;
city | total
----------+-----------------------
Rome | 1476.6666666666666667
Helsinki | 1200.0000000000000000
Paris | 1733.3333333333333333
Munich | 1450.0000000000000000
(4 rows)
在上述子句中还可以使用其他聚合函数,如 MIN、MAX 等。
结论
在本文中,您已经看到:
- 工会条款如何运作
- UNION、UNION ALL 和 INTERSECT 之间的区别
- 如何计算多个表格中数值的总和及平均值
非常感谢您的宝贵时间,非常感谢您的任何问题或反馈。
参考
- 堆栈溢出- SQL:如何对不同表中的两个值求和
- 斯蒂芬斯、琼斯、普勒(2016)。24 小时内 SamsTeachYourself SQL
免责声明:本文是在“原样”的基础上编写的,没有担保。它旨在提供数据科学概念的概述,不应被解释为专业建议。本文中的发现和解释是作者的发现和解释,不被本文中提到的任何第三方认可或隶属于任何第三方。作者与本文提及的任何第三方无任何关系。
概率事件组的联合
原文:https://towardsdatascience.com/union-of-probabilistic-event-groups-b415d23e1a62?source=collection_archive---------35-----------------------
如何计算概率事件分组的并集
由 Unsplash 上的 Edge2Edge 媒体拍摄
概率是对随机实验中某一事件发生的可能性的度量。事件是样本空间的子集(实验的所有可能结果的集合)的表示。随机实验是指我们一遍又一遍地重复类似的过程,但结果却无法预测。
对于两个事件的合并,我们必须有相同的样本空间( S )。让我们考虑 A 与 B 的并集 (A U B) 的两种可能情况。
A∩B =φ
如果集合 A 和 B 的联合形成一个空集,即集合没有共同项(独立事件),考虑到样本空间不为零,我们得出如下结论:
P(A U B) = P(A) + P(B)
如果集合 A 和 B 之间的联合形成一个非空集,则表明它们有共同的元素(依赖事件),因此这两个集合联合的概率可以定义如下:
P(A U B)= P(A)+P(B)-P(A∩B)
作者图片
遵循德摩根 的T21 定律,证明了两个集合的并的补数等于这些集合的补数的和:
然后,三个或更多集合的并集的补集可以被计算为这些集合的补集的乘积。该等式表示如下:
所以,我们可以得到集合的并集,得到这些集合的补集的乘积的补集。
申请
从那里,我们演示了如何从给定数据集的每个组中计算多个集合的并集。数据是随机创建的,考虑到它们代表了一些事件发生的概率,通过 ID 进行分类。在按 ID 分组后,应用 lambda 函数来计算每个组的这些集合的并集。
#import libraries
import pandas as pd
from random import seed
from random import random
from random import randint#generate random data
seed(1)
id = []
prob = []
for _ in range(30):
value_id = randint(0, 10)
value_prob = random()
id.append(value_id)
prob.append(value_prob)#create DataFrame
df = pd.DataFrame(prob, id, columns=['Probabilities'])
df.index.name = 'ID'#grouping by ID
g = df.groupby(df.index)#applying union function
g.apply(lambda x: 1 - (1 - x).prod())
让我们假设每个概率都代表某个设备发生故障的可能性。另外,假设有 10 种不同的设备类型,您想知道每种设备类型中至少有一种会出现故障的概率。这就是函数所做的,每个 ID 代表这些概率的联合。每个概率将代表至少一个该类型(ID)的设备发生故障的可能性。
结论
考虑到德摩根定律,该函数的计算基于多个集合的联合方程。该函数能够聚合概率事件联合中的数据,显示某个事件在每个组中发生的概率。该函数可用于更好地制定决策,提供一种特定的方法来解释数据。
参考文献
安迪·海耶斯和胡炜昇。德摩根定律。https://brilliant.org/wiki/de-morgans-laws/
独特的数据胜过完美的模型
原文:https://towardsdatascience.com/unique-data-is-better-than-a-perfect-model-6a2fabb51806?source=collection_archive---------39-----------------------
卢克·切瑟在 Unsplash 上的照片
作为一名数据科学家,你的目标应该是构建和使用专有数据集
在数据科学领域,人们倾向于认为最重要的是模型。我猜想这部分是由故意遗忘造成的。
我为什么这么说?我们(数据科学家)都愿意相信我们的建模和分析技能是特殊的。正是这些特殊技能让我们能够解决最复杂的业务问题,并释放新的收入洪流。没有什么不可能的问题,我们只是还没有在它上面扔足够多的隐藏层,或者适当地优化我们的随机森林。
但事实并非如此。事实是,真正能够增加实际价值的差异化数据科学产品是因为独特和专有的数据,而不是模型。这可能是一颗难以下咽的苦药丸——意识到我们最期待的工作部分(建模)并不是驱动最大价值的部分。
但这也是一种解脱。作为一名数据科学家,首要任务是找到一个好的数据集。那么,什么是伟大的数据集呢?我认为有两件事需要保持真实,数据集才是特殊的。它需要是专有的(难以复制的)和相关的(解决一个大的商业问题)。
这方面的一个例子是美国运通。因为它运营着一个闭环网络(这意味着它既发行信用卡,又与商家签约加入其网络),任何时候有使用其信用卡的交易,它都知道谁在购买以及他或她从哪个零售商那里购买。得益于此,美国运通对其客户的消费习惯和信用记录了如指掌。这使得它能够在基本信用的基础上提供额外的产品和服务,并使自己与 Visa 和 MasterCard(这些公司不知道他们的持卡人在买什么)等开环网络区分开来。
交易历史
对商业企业最有价值的数据集之一是一个人的金融交易历史。可以说,没有什么比他或她与金钱的关系更能定义一个人了。
- 从购买历史中,我们可以推断出性别、年龄、国籍、教育程度、地点、工作和兴趣等信息。
- 从一段时间内的现金流入与现金流出,我们可以推断出一个人当前的信用质量和财务健康状况。我们还可以发现一个人的财务健康状况随时间的变化,可能比金融机构更快。
因此,通过对一个人的交易历史的详细研究,我们可以了解一个人最值得了解的一切(从商业角度来看)。
获取所有数据
问题是我们如何全面地获得这些数据?如果我们只有一个人的 10%的交易,这不足以真正了解他或她。
传统上,只有像亚马逊和沃尔玛这样的大型零售商或大型金融机构(如美国运通或摩根大通这样的闭环网络,它们既有大型信用卡发行业务,又有众多的商户关系)才知道这种类型的数据。但在过去几年里,智能钱包应用程序通过将有吸引力的用户体验放在一个人的财务之上,使自己处于一个独特的位置,可以看到整个画面。
智能钱包背后的基本原理是,我们的财务很复杂,没有乐趣,这刺激了无知。因此,我们不知道我们花了多少钱(我们甚至可能不知道税后收入),我们支付了多少信用卡利息,我们每个月支付了多少随机订阅,我们在外面吃了多少,等等。
通过整合我们的支出(和收入)流,并在其上添加一个分析层,智能钱包可以帮助我们可视化我们的钱去了哪里。它让讨厌数字的懒人可以像痴迷的会计师一样透明地了解自己的财务状况。
更有趣的部分是数据如何反向流动——作为详细分析我们现金流的回报,智能钱包可以通过我们的交易了解我们的行为和兴趣。智能钱包的软件越有用,我们与它的互动越多,给它的数据也越多(是的,所有的间谍活动听起来确实有点令人毛骨悚然)。
虽然听起来令人毛骨悚然,但这就是你如何着手建立一个专有且有用的数据集。这可能需要几年时间,但是如果成功了,结果是值得的。独特的数据使数据科学家能够产生洞察力、预测事物并进行其他人无法进行的实验。做别人做不到的事情是获得和保持竞争优势的更好方式,而不是加入其他人已经加入的军备竞赛。
因此,当你开始数据科学职业生涯时,寻找那些已经完成了建立独特且难以复制的数据集的艰苦工作的公司——谷歌(用户数据)、Facebooks(社交图)、亚马逊(电子商务交易)、特斯拉(自动驾驶汽车数据)、Stripes(交易)等。当你为他们工作时,不要只考虑如何帮助他们扩大竞争优势和数据优势。此外,花时间研究这些领先的数据公司如何构建、维护和学习大量独特的数据。干杯!
如果你喜欢这篇文章,请在这里查看我写的更多内容。