TowardsDataScience-博客中文翻译-2019-十-
TowardsDataScience 博客中文翻译 2019(十)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
AutoML:来自 OptiWisdom 的端到端介绍
原文:https://towardsdatascience.com/automl-end-to-end-introduction-from-optiwisdom-c17fe03a017f?source=collection_archive---------7-----------------------
机器学习是人工智能研究的一个分支,也是计算机科学的一个分支。不断增长的数据量和处理能力也增加了对处理数据和通过挖掘数据之间的关系产生有用结果的需求。这种新趋势通常被称为数据科学或分析。有时,根据应用程序的不同,它可能被运行的平台称为大数据分析。另一方面,数据科学有两大支柱,即机器学习和统计学。
数据科学的趋势也吸引了对机器学习的研究,这是两个主要学科之一,另一个是统计学。机器学习是一个比较老的话题。一些研究者甚至可能在古希腊找到它的根源,那里的人们试图从早期犹太教或假人教中找到解决所有问题的通用公式,这与我们现代理解中的机器人非常相似。今天,机器学习也是一种形式的基础,我们每年都在使它们更加自动化。
在这个中级系列中,我们试图找到一个自动化机器学习(AutoML)过程的实践经验,我们通过理解机器学习的经典流程来开始这个概念。我们将看看什么是自动机器学习,什么不是自动机器学习。我们会明白为什么自动机器学习很重要,它通常会面临哪些问题。最后,我们将通过端到端的系统方法来实现自动机器学习过程。
写作将涵盖以下主题:
了解什么是 AutoML
知道为什么汽车很重要
理解什么不是自动的
理解 AutoML 的问题
学习自动化过程的端到端系统方法
了解什么是 AutoML
在最简单的定义中,AutoML 是机器学习过程的自动化。那么,我们从机器学习过程中了解了什么,我们如何使它自动化?
从数据科学项目管理技术可以很容易地理解文献中的机器学习过程,我们有三种主要的数据科学项目管理技术:
塞姆马
KDD
CRISP-DM
取样、探索、修改、建模和评估
SEMMA 代表取样、探索、修改、建模和评估,是最早的项目管理技术,在 KDD 和 CRISP-DM 中也包含了这种技术,所以对其进行详细描述并不重要。但是理解它很重要,因为它从采样数据开始,继续探索数据,修改模型或数据类型,然后为此目的创建模型,最后评估结果。这也是 AutoML 的一个非常初始的流程,我们将在后面介绍。
数据库中的知识发现
KDD 代表数据库中的知识发现,它是从数据中提取知识的最著名的方法之一。
KDD ( Knowledge Discovery on Databases)
它从任何系统中的数据开始,如数据库、大数据平台,甚至是来自物联网设备或社交媒体的流数据,经过 5 个步骤后,它会带来知识。在进入 KDD 步骤的细节之前,定义如下所示的数据和知识的概念可能是有用的:
DIKW Pyramid
上图展示了众所周知的 DIWK(数据、信息、知识和智慧金字塔)。
1.它从数字或字符开始,如在基线,数据级别。
2.它们没有意义,信息层带来了意义。例如,50 只是一个数字,但像“50 是约翰的年龄”这样的信息对我们来说有着特殊的意义。
3.从数据到信息的升级是另一本书的另一个故事,这一级别的大多数问题由数据库系统、数据仓库处理,并创建报告、仪表板或记分卡。
4.另一方面,从信息到知识层面的步骤是人工智能、机器学习或统计的问题,我们无法在大多数知识层面的问题中获得 100%的成功。例如,从约翰的照片中了解他的年龄可能是一个知识水平问题,我们在大多数情况下无法确定。
KDD 是一种利用数据解决知识水平问题的技术,如收集所有员工的照片和训练机器来预测人的年龄。
AutoML 的目标是在没有任何交互或至少最小化交互的情况下,自动完成从数据到知识级别的过程。在这篇文章中,你可以找到一步一步的方法,每一步的 KDD 和我们如何自动化的步骤。
KDD 从选择数据开始,这对于减少数据集和理解最重要的特征是很重要的。稍后,在 AutoML 中,我们将把这一层划分为数据连接层和特征选择,因为 AutoML 需要连接、选择和刷新这一过程,因为数据在大多数情况下是动态的,我们需要检查数据的更新。
数据预处理处理数据上的问题,如缺失值、异常值、噪声或脏数据等。因此,我们既要处理数据质量,同时又要尝试做一些预处理,以提高机器学习模型的成功率。同样,在 AutoML 中,目的是自动提高成功率,理解预处理策略,或尝试一些可能性,以优化机器学习模型的性能。由于我们正在以自动化的方式处理性能优化,我们不能将 AutoML 的步骤分成两个,像数据预处理或转换,我们一起处理这两个步骤。例如,在 AutoML 过程中的大多数时间,日期字段被自动检测(数据预处理的一个步骤),缺失值或异常值被自动处理(数据预处理的另一个步骤),一些特征如日、月、年、星期几或一年中的某一天被自动提取(数据转换的一个步骤),有用的特征被选择,无用的被考虑(数据选择的一个步骤)。因此,AutoML 是整个过程的自动化,其中 KDD 处理几个步骤。
最后,数据挖掘步骤由 AutoML 中的模型选择步骤处理,AutoML 还处理模型的优化,稍后我们称之为超参数优化(HPO)。
在数据挖掘或建模步骤之后,第一个机器学习模型就可以使用了,但还有最后一个问题需要解决:我们如何才能理解模型的成功?怎么评价呢?满意标准是什么?
AutoML 和 KDD 方法的一个主要区别是评估步骤。解释/评估在数据科学中非常重要,它强烈要求数据科学家处理案例并开展工作。但是,在 AutoML 中,这个过程大多数时候是从评估标准开始的。
跨行业标准处理—数据挖掘
CRISP-DM : CRISP-DM 代表跨行业标准处理——数据挖掘,是业界使用最多、最广泛的数据科学工具。CRISP-DM 的步骤如下图所示:
CRISP-DM : Cross Industry Standard Processing — Data Mining
CRISP-DM 有 6 个步骤,从业务和数据理解开始,这对于任何数据科学项目都是必不可少的,并且大多数时候是业务分析师或数据分析师的工作,按照给定的顺序。
CRISP-DM 的其余步骤与 KDD 步骤非常相似,KDD 的数据选择、数据预处理和数据转换步骤被合并到 CRISP-DM 的数据准备步骤中。
从这个角度来看,CRISP-DM 非常类似于 AutoML 方法,其中整个 AutoML 过程可以总结为两个主要循环:数据准备循环和机器学习循环。
CRISP-DM 强调业务分析和数据分析的重要性。
AutoML 步骤和模块
在涵盖和比较了经典的机器学习/数据科学项目管理步骤和流程之后,有可能给出 AutoML 的系统图;
AutoML Approach from OptiWisdom
尽管有许多可供选择的方法来实现 AutoML 过程,但上述方法是 OptiWisdom 针对 SaaS 方法提出的端到端解决方案。用户能够加载/连接数据源,其余的问题,如预处理或模型选择和部署,都在 OptiWisdom 平台上解决。AutoML 图表,演示:
从原始数据源到部署自动生成的机器学习算法的流程。
该流程非常类似于 KDD 和 CRISP-DM 流程,并且具有两个主要循环,预处理循环和机器学习循环,类似于 CRISP-DM 步骤。
除了整个过程的自动化之外,AutoML 背后的基本思想是上图中每个步骤的自动化。
上图也给出了整个系统的一般视图,在某些情况下,AutoML 解决方案可能会考虑上述场景的一小部分。
例如,删除上述所有步骤,仅将单个机器学习算法直接添加到数据源并应用超参数优化,甚至可以被认为是 AutoML 解决方案。
在这篇文章中,更大的画面将被每个步骤的实践经验所覆盖,并且 AutoML 的每个步骤都通过实践方法在单独的章节中处理。它从数据层面开始,向上到知识层面。
数据连接层
原子化从数据连接层开始。除了连接到数据源的必要性,自动化系统还需要检查数据源上的更新和刷新。数据源中的更新可以是:
新记录发送到数据源,AutoML 方法通过推送通知检查更新,或根据时间刷新更新检查
流数据源,其中更新是问题本质的一部分,或者有时更新是结构更新,自动数据连接层需要检测这些变化并自我更新。
这一层的所有更新和刷新都与数据的形状直接相关。例如,向系统添加新标签是另一个问题,它在特征选择或特征工程阶段处理。
功能选择/工程
在这一层,AutoML 方法解决了具有冗余特征的问题。例如,在某些系统中,添加一个人的出生日期和年龄可能会有问题。特征选择试图找到多余的特征并消除它们。此外,降维或转换数据是特征选择和工程的一部分。系统在这一步可以考虑一些特征工程库。例如,从日期字段中自动提取一周中的某一天、一年中的某一天或一季是这一步骤中特征工程的重要部分。
AutoML 的所有步骤都在一个循环中,并且每一步都通过每次迭代中其他步骤的反馈来更新自己。例如,特征消除从数据预处理或选择的算法中获得反馈,并且可以根据来自这些步骤的反馈来更新选择的特征。
特性工程的细节和实例将在另一篇文章“数据源和数据选择的自动化”中讨论。
数据预处理
数据预处理是一个重要的阶段,也被认为是 KDD 或 CRISP-DM 方法中的一个重要步骤。有时,数据预处理是 ETL(数据仓库术语中的提取、转换和加载步骤)的一部分,或者称为数据质量、数据操作或数据混合,但它是所有数据相关研究的关键步骤。数据预处理步骤的目的是处理有关数据的问题,如脏/有噪声的数据或异常值的缺失值。
与 AutoML 的其他步骤类似,数据预处理也是循环中的一个步骤,某些操作可能会受到来自其他步骤的反馈的影响。例如,在一些 AutoML 解决方案中,离群值可能会被清除,而在其他一些解决方案中,离群值对于解决方案来说极其重要。
此外,传统的特征提取、消除或工程技术需要基于时间序列的分析方法。可选地,在一些特征工程方法中,应用时间序列解决方案。
数据预处理的输出是预处理的数据源,也是 AutoML 机器学习循环的第一步。在 AutoML 的机器学习循环的每次迭代中,预处理的数据将会发生变化,并且所需的更新将会反馈到 AutoML 的预处理循环。
数据预处理将在以后的文章中处理。
组合/选择并应用算法/超参数优化
将机器学习算法应用于预处理数据是 AutoML 中机器学习循环的第一步。在此步骤中,将应用从算法库中挑选的算法,并自动判断第一个结果。例如,根据目标字段的数据类型,如果有目标字段,问题可能是分类或回归。AutoML 方法检测问题类型,并且只关注与问题相关的算法。在优先应用与问题相关的算法之后,AutoML 方法可以反馈到 AutoML 的预处理循环,以及应用拥有算法的超参数优化(HPO)技术。
这一步有许多不同的优化技术,每一种都有一些优点和缺点。选择算法的细节将在第 8 章“正确算法的自动选择”中解释,结合多种算法求解将在第 9 章处理,最后超参数优化技术将在第 10 章解释。
评估和部署
AutoML 的最后一步是将解决方案,候选模型,部署到业务案例中。根据业务案例的不同,评估需要实地测试,实地测试也会提供一些有用的反馈。
整体评估和 AutoML 系统详细信息的目的,如商业案例和 AutoML 在现实生活中的应用,将在第 11 章中考虑,但在介绍性步骤中,记住下图所示的分析成熟度可能会有所帮助:
Types of Analytics
大多数时候,描述性分析不需要机器学习方法。对于并非在所有情况下都需要但对理解原因有用的诊断,数据科学家寻找原因并试图回答“是什么导致了这些结果?”。虽然在诊断分析中,数据科学有一些优势,但 AutoML 的优势始于预测分析,但 AutoML 在规定分析中更为重要,自动操作是规定分析的一部分。因此,一个设计良好的 AutoML 方法既可以自动采取行动,也可以从商业案例或现实生活的反馈中学习。
AutoML 方法是机器学习过程的端到端原子化,因此机器可以像在强化学习中一样从现实生活中学习。除了学习和提高系统的整体性能,AutoML 还可以提高动作的性能。
AutoML 的目的
AutoML 的目的可以列举如下:
经典数据科学管道中最大数量步骤的自动化
最少的人类互动
取得良好和令人满意的结果
低时间计算
上面列表中的第三和第四项也是经典数据科学的主要目标,但上面列表中的前两项对数据科学和机器学习有独特的新方法。
了解 AutoML 的重要性
AutoML 是机器学习研究中一个相对较新且不断增长的趋势。这种方法也吸引了像脸书这样的科技巨头,或者像 Gartner 这样的全球商业研究和咨询公司。脸书每月生成超过 30 万个机器学习模型,他们还有一个名为 Asimov 的项目,用于优化这些模型。另一方面,Gartner 声称,到 2020 年,超过 40%的数据科学将实现自动化。
Twitter 在 2015 年收购了一家机器学习初创公司 WhetLab,该公司为机器学习问题创建了更简单和自动化的解决方案。
AutoML 的三个核心目标可以列举如下:
性能优化:在理想情况下,AutoML 性能与问题或数据的复杂性无关。因此,AutoML 试图为各种输入和学习任务建立一个通用的性能
在过程中最少或没有人工干预:在理想情况下,AutoML 处理所有问题,并以自动化的方式解决问题
计算效率:在理想情况下,AutoML 在给定的有限资源或预算内产生最佳算法。
以上所有案例表明,行业内关于 AutoML 解决方案的趋势越来越明显。AutoML 的主要优势是:
AutoML 减少了例行程序,同时为数据科学过程中的创造性工作留下了巨大的空白
AutoML 是机器学习的一种民主化方式,它提出了一个新的术语,称为“公民数据科学家”,因此每个人都可以处理数据科学,并在他们的领域专业知识中使用机器学习算法。
AutoML 提供了一个标准化的机器学习解决方案,无论项目中数据科学家的资历如何。
AutoML 对行业有雪崩效应,因为它增加了员工、经理或所有利益相关者对机器学习相关解决方案的参与度。
公民数据科学家和机器学习民主化
AutoML 是一个重要的趋势,因为它提供了机器学习解决方案的民主化。一个相对较新的趋势叫做“公民数据科学家”,它也不是一个新的工作或组织中的一个职位。Gartner 将该术语定义为一个人,他处理预测性或规范性分析的开发,他不是来自统计或分析背景,并且他的主要工作不是开发模型。
下图所示的公民数据科学家形象全面参与并致力于业务流程和数据科学。
公民数据科学家也是数据科学世界和他拥有专业知识的领域之间的桥梁。
他收集信息,创建社交网络或梦想数据科学及其领域的未来项目。
此外,大多数公民数据科学家都在他们的背景中加入了新的技能,如对统计、数据处理、分析或数学的更广泛的理解。
他们还对组织的决策承担责任。
因此,在数据科学的新时代,数据科学是民主化的,任何背景的人都可以使用,而且他们在工作中处理什么并不重要,数据科学无处不在,每个人都必须了解并进行一些分析。
关于公民数据科学家的一个大问题是,不可能将所有专家都送回学校,教他们数据分析或机器学习模型。相反,趋势表明工具变得不那么复杂,并提供简单和可解释的解决方案。因此,经验丰富的数据科学家或机器学习专家正在致力于创造新的工具、系统或算法,这些工具受到更广泛的大众的更多需求。
机器学习模型的标准化
关于 AutoML 趋势的另一个重要问题是生产的机器学习模型的质量标准化。在行业中,总是要求有经验丰富的数据科学家或机器学习专家。“有经验”这个关键词对于大多数招聘广告来说都是至关重要的,甚至有时招聘广告的标语中会出现“资深”数据科学家。工业界已经意识到机器学习模型的质量。解决问题的模型在大多数时候并不是最佳解决方案,只有经验才能带来机器学习模型的质量,这可以质疑机器学习模型的工作情况、商业案例相关的成功率或未来风险。
AutoML 有解决问题的方案,并且独立于数据科学家的经验或资历,AutoML 生产部署就绪的模型。
除了业务案例或数据问题模型的标准化,标准化还带来了执行性能的标准。选择或组合的模型会受到资源或性能要求的限制。
AutoML 在行业中的雪崩效应和学习转移
AutoML 使机器学习项目易于访问和简单理解。此外,为来自任何领域或背景的专家提供了许多新的自动化工具。因此,新时代的机器学习变得更加容易实现。
AutoML 也可以将一个经验从一个案例转移到另一个案例。例如,一个专门从事人力资源的 AutoML 应用程序也可能为人力资源领域的特定应用程序带来一个标准的机器学习过程。零售业也有类似的情况。Amazon 是 web 上早期的推荐引擎实现者之一,它创建了一个基于 web 的零售商店,当时编写推荐引擎的最简单方式是一个简单的数据库查询,显示“谁买了这个项目,也买了这个项目”,这是一个非常原始的协同过滤版本。现在,这种方法适用于任何基于网络的零售商店,也是许多基于网络的零售商店现在必须的。很容易看出,即使是最简单最基础的机器学习系统,也能在短时间内成为行业标准。
数据是新的石油,新的数据驱动型公司正在几乎所有行业崛起。从第一个原始的亚马逊推荐系统开始不到几十年,现在机器学习系统几乎取代了一些行业的顶级管理。例如,网飞超过 75%的收入来自后台运行的推荐算法,公司的成功主要建立在他们部署的算法上。网飞基于用户行为准备电影推荐,这被称为协同过滤或用户是谁,也被称为基于内容的过滤,此外,它还根据用户的历史数据创建电影海报。因此,每次向用户推荐一部电影,用户都会得到一张为自己制作的独特的电影海报。
了解什么不是 AutoML
AutoML 不是神奇的盒子,自动解决所有问题。例如,AutoML 无法发明新的机器学习算法,或者无法保证某些情况下的最佳调整。
AutoML 不是一种扼杀所有数据科学工作并取代数据科学家的技术。恰恰相反,在数据科学的新时代,它是数据科学家的必备工具。AutoML 不会重复数据科学中的例行程序,如数据分析、数据清洗、特征提取或用几个问题测试多个机器学习算法,而是自动执行所有必要的例行程序,并将明智的决策留给数据科学家。
如下图所示,AutoML 可以被认为是一个管道,在一端,AutoML 获得创造性的想法作为输入,如业务问题或数据。另一方面,AutoML 为数据科学家的判断提供了必要的输出,并为数据工程师提供了部署就绪的模型。
AutoML BlackBox Approach
AutoML 也是人工智能和数据科学方法的游戏规则改变者。
例如,为深度学习系统提供更多 CPU、GPU 或 TPU 是一个非常常见的陷阱,它是一种面向抽象的机器学习自动化。
另一方面,AutoML 是研究社区的一个新视角和转变,它提供了自动化和机器学习的可解释性和可解释性。
在大多数情况下,AutoML 的结果是简单和可解释的,如生成决策树和显示关键决策节点以及算法上的数据流,而不是产生突触权重或神经网络中的激活函数参数。
了解 AutoML 的问题
AutoML 从最初的文献中就有一些明确定义的问题。例如,AutoML 最早的一个出现是由 Auto-Weka 推出的,最早定义的问题,现在仍然是一个重要的问题,就是 CASH(组合选择和超参数优化)。
另一个众所周知的问题正在从经典的机器学习理论中回归:没有免费的午餐定理。基本上,它说没有机器学习算法可以击败所有其他可能的算法。
AutoML 在参数优化方面有一个焦点问题。在选择了适合问题或数据的机器学习算法,或者甚至组合了算法可能性之后,现在的问题是超参数的优化。
现金问题
现金问题是文献中非常著名的早期问题之一。该问题简单地强调了在所有可能的算法中选择所有可能的好的机器学习算法,并组合它们以解决该问题。AutoML 主要解决监督学习问题。例如,分类和回归算法受到监督,并且更容易衡量算法的成功。在监督学习问题中,通过使用集成技术,如打包、提升、堆叠等,算法的组合是可能的并且相对容易。此外,可以通过使用共识学习来组合无监督学习算法,如聚类算法。在这两种情况下,AutoML 方法都试图为问题找到最佳的机器学习算法选择和组合。
没有免费的午餐
没有免费的午餐(NFL)定理是比 AutoML 方法相对更老的理论,并且表明在机器学习或优化中没有适合所有解决方案的尺寸。
这个术语从两个方面触及 AutoML,NFL 的第一个意义是关于选择机器学习算法。例如,有许多可供选择的机器学习算法,每种算法都有其原因,每种算法都有一些优点和缺点。如果有一个单一的算法,从各个方面支配所有其他可能的算法,那么生活会容易得多。不幸的是,这是不可能的,也没有这样的算法或捷径。AutoML 中 NFL 的第二个含义是机器学习算法的优化阶段,或者更具体地说是超参数优化。这个问题再次类似于机器学习算法的选择,这一次优化过程没有自由解。
这个类比来自于餐馆和菜单的隐喻。所以,菜单上列出了可能的解决方案,每一个餐盘都有价格。此外,根据你的饮食,餐馆的选择也很重要。例如,一个素食者在一家牛排店吃午餐会比午餐的平均价格高。所以从菜单上选择合适的餐馆和合适的项目是很重要的。最后,你午餐时间的朋友,也就是和你一起吃午餐的人,对你的选择范围也很重要。例如,如果你是一个素食主义者,如果你和一个肉食者共进午餐,那么午餐再次变得高于平均水平。
类似地,从菜单中选择菜单项——候选解决方案或可用算法列表中的算法——会产生一些外部影响,如哪些算法正在一起工作,或者您在哪个问题域中使用该算法。因此,算法的搜索本身是一个优化问题,同时优化所选算法的参数会使问题变得更加复杂,并带来多准则优化问题。
超参数优化(HPO)
在最一般的形式中,超参数优化是机器学习算法的超参数的优化。几乎所有的算法都有直接影响结果的超参数,除了为问题选择最佳算法外,为算法选择最佳参数也是一个重要的问题。
有许多方法可以解决这个问题和可能的解决方案,这个问题和可选的解决方案将在以后的文章中讨论。但是为了引入这个概念,一个非常原始的搜索过程可能是网格搜索,其中在一次迭代中搜索预定范围内的所有可能的参数。
HPO 实际上是一个稍微复杂一点的问题。超参数在大多数时候不是 2 或 3 维搜索空间,并且同时有超过 10 个参数需要优化。不幸的是,当需要优化的参数数量增加时,问题的复杂性也以指数方式增加。
没有一种算法能保证比网格搜索更好的解决方案,但是通过使用一些优化算法,一种更快的算法是可能的。
学习端到端的系统化 AutoML 方法
在传统的数据科学项目中,有三个基本步骤
1.数据科学项目从理解和分析问题和数据开始,
2.继续创建和实施模型和
3.在最后一步,项目被提升到可持续和可维护的阶段。
下图展示了大多数情况下数据科学流程的通用方法。该图解释了参与者的主要贡献,但是当然,参与者的参与并不限于图中所示的交互。例如,利益相关者和业务团队与产品和部署非常相关,但是图中只展示了关键的和主要的交互。
Productization of AutoML in OptiWisdom
这三个步骤还需要一些子步骤和参与者。
在构思阶段,利益相关者、业务团队和数据科学家一起工作。这里的理念是理解和定义问题,并创造性地提出解决方案。
在数据科学阶段,数据科学家致力于找到问题的解决方案,最后在生产或部署阶段,开发人员、系统管理员或数据工程师致力于实现最佳的可持续系统。
AutoML 旨在自动化数据科学,主要是生产/编码阶段。
AutoML 取代了人工操作,用优化和自动化的解决方案取代了常规工作,并为数据科学家和开发人员提供了更多从事更具创造性工作的机会。
Role of AutoML in Productization
上图展示了 AutoML 在整个系统中的主要部署。这个想法是数据科学和生产阶段的自动化,并最小化数据科学家和开发人员团队在这个过程中的贡献。
面向数据爱好者的 AutoML
原文:https://towardsdatascience.com/automl-for-data-enthusiasts-30582b660cda?source=collection_archive---------17-----------------------
AutoML(自动化机器学习)会是允许任何有愿望的人(数据爱好者)创建机器学习模型的答案吗?
谁是数据爱好者?
- 想尝试机器学习的软件开发者
- 渴望成为数据科学家的大学生
- 希望提升自己水平的中层企业经理
- 希望区分其技能组合的分析师
- 许多其他人…
AutoML 通过自动化数据准备、特征提取、模型选择和模型调整,节省了数据科学家的大量时间。但是,它能让数据爱好者轻松地使用机器学习吗?
答案是它确实依赖于 AutoML 工具,其中有大量用户友好的和工具。
挑战
如果你不是数据科学家,只是想尝试机器学习(嘿,你甚至可能不会写代码),我称你为数据爱好者。看下面的图表,数据爱好者比实际的数据科学家多得多(比例为 20 比 1)。
Estimated from multiple sources including https://www.kdnuggets.com/2018/09/how-many-data-scientists-are-there.html
现实是,在 400 万数据爱好者中,有些人还拥有令人敬畏的领域知识,如果配备了正确的工具,可以加速一个组织的机器学习工作。
潜在解决方案
AutoML 工具通常适用于以下情况之一(本文重点关注第二点):
- 通过自动化部分模型构建流程,帮助当前的数据科学家提高工作效率
- 让数据爱好者能够创建机器学习模型
并不是每个 AutoML 工具都能解决问题,因为大多数工具都集中在第一或第二点上。在下面的 8 个 AutoML 工具的比较中,你可以看到一半的工具在易用性方面被评为“红色”,这对于数据爱好者来说不是一个好的选择。
面向数据爱好者的 AutoML 工具对比
有许多方法可以分割 AutoML 包的过多工具(包括 MLaaS 服务),但是我想把重点放在数据爱好者的三个重要考虑事项上。
- 易用性(你能不写代码就创建吗)
- 预算(有免费和高级版本)。免费试用<>。
- 定制(例如,交互式数据操作工具、模型交付选项)
这八个 AutoML 工具的比较实际上是当今可用的越来越多的 AutoML & MLaaS 解决方案的组合。包括一些大型企业玩家,如 AWS ML 、 H2O 和 DataRobot 。还包括你的开源强手,比如 Auto-Weka 、 Auto-Sklearn 和 TPOT 。这个团队被为数据爱好者开发的有前途的工具 PredictiveData 和 MLJar 所充实。
当比较所评估的 8 个 AutoML 工具中的 4 个工具的性能时,下面是它们在大型数据集上的表现。
Results sourced from https://hackernoon.com/a-brief-overview-of-automatic-machine-learning-solutions-automl-2826c7807a2a
总结
AutoML 在让机器学习变得更容易方面展示了巨大的进步,工具也在迅速改进。只要你能找到易用性、预算和定制的正确平衡,这些应该会让我们更接近挖掘 400 万数据爱好者的力量。
用于预测建模的 AutoML
原文:https://towardsdatascience.com/automl-for-predictive-modeling-32b84c5a18f6?source=collection_archive---------4-----------------------
随着第一批成果在实践中得到应用,自动化机器学习成为越来越重要的话题,带来了显著的成本降低。我在 ML 布拉格会议上的演讲描绘了主要在预测建模领域的最新技术和开源 AutoML 框架。
我还展示了我们的研究,该研究部分由 Showmax 资助,在我们位于布拉格捷克技术大学信息技术学院的联合实验室进行。
我还要感谢 Showmax 提供的计算资源,这使得我们的大量实验成为可能。
让我们从最近的谷歌营销视频开始,解释谷歌人工智能如何在 Waymo 中应用他们的 AutoML。
深度学习自动化
谷歌人工智能应用 AutoML 寻找更好的卷积网络替代架构,对自动驾驶汽车中的图像进行分类。
营销部门报告说速度提高了 30%,准确率提高了 8%,令人印象深刻。
当你仔细看的时候,你发现 is 其实不是 AND 而是 OR。您可以在不牺牲精度的情况下获得高达 30%的加速,并在相同的速度下获得 8%的精度提升。无论如何,这些仍然是好数字,因此 AutoML 是值得努力的。图中的每个点代表一个卷积神经网络,目标是找到一个具有允许以最小延迟实现最佳分类性能的架构的网络(左上角)。
CNN 架构在一个简单的代理任务上进行评估,以减少计算成本,并评估不同的搜索策略。蓝点是由本文稍后描述的神经架构搜索策略评估的 CNN。
这些实验类似于更早的研究CNN的大规模进化,也需要大量的计算资源。
但与正在优化 3d 卷积神经网络的视频分类器的架构搜索相比,它仍然便宜且容易。
进化搜索也用于优化转换器的编码器和解码器部分,表明在选择文本处理网络的架构时,神经翻译模型也可以得到很好的优化。
自动深度模型压缩
为了加快召回和简化深度 convnet 模型,可以使用 AutoMC 开源框架 PocketFlow。
在向移动设备或嵌入式系统部署精确模型时,AutoMC 或 AMC 变得越来越有用。报道加速效果相当可观。
深度 AutoML 框架
Auto Keras 使用网络态射使贝叶斯优化更加高效。架构空间中的编辑距离(在架构之间遍历所需的更改数量)被用作相似性代理。正如您所看到的,用法非常简单,显然不需要手动指定参数。
AdaNet 开源 AutoML 框架工作在 tensorflow 之上。关于用于搜索架构空间的进化技术的详细描述,你可以参考谷歌人工智能博客。
通用自动语言
我们已经调查了 AutoML 深度学习方法,但这只是你可以在预测建模中找到的 AutoML 技术的一个类别。一般来说,AutoML 方法在以下领域最有效,优化预测模型的性能和/或速度。也有许多其他标准可以考虑,如预测模型的可解释性,但 AutoML 优化这些标准的能力仍处于起步阶段。
预测建模的数据预处理通常需要以更传统和过时的方式来执行,因为 convnets 只适用于某些数据源(图像、文本、语音..).除了神经网络之外,还有许多预测建模方法。这些方法通常有很多超参数。下面讨论为这个领域开发的 AutoML 技术。
首先,看看可以在 AutoML 搜索中使用的一些通用工具。随机搜索的效率惊人地高,因此非常受欢迎。这主要是因为很难搜索建筑空间,因为它通常由相互依赖的连续和离散维度组成。
更有趣的技术之一是使用高斯过程的贝叶斯优化。让我们假设你只有一个连续的超参数。你探索潜力最大的区域(上限)。
另一个有趣的技术是超高频带。这是土匪启发的方法,同时学习和评估几个架构,并杀死其中一半的时间。它有助于将计算资源以指数方式分配给最有前途的架构。缺点是你可能会扼杀那些需要更多时间来优化的伟大架构。
数据挖掘的 AutoML 框架
在这里,我们介绍一些最流行的 AutoML 框架,用于更传统的预测模型,通常包括数据预处理。
ATM 开源框架使用贝叶斯优化、GP 和土匪来优化预测模型的超参数进行数据挖掘。
TransmogrifAI 还优化了数据准备阶段(如数据预测)。
类似的工具还有很多,既有开源的(auto sklearn,hyperopt sklearn,auto weka),也有商用的(h2o 无人驾驶,datarobot automl)。注意 Google Cloud AutoML 还没有提供类似的工具。提供的服务面向深度学习模型优化。
高级自动化方法
除了简单的超参数优化(甚至使用高级试探法),还有许多有趣的方法可以在微观和宏观层面处理架构选择。
神经结构搜索
神经架构搜索是那些更高级的问题之一。可以参考 NAS blogpost 了解基本变种。
NAS 的一个巧妙方法是将架构选择映射到概率空间,并使用反向投影结合权重来优化架构,如飞镖所示。
By using DARTS, you can optimize structure of recurrent neurons, but also structure of feedforward network.
另一种方法是将建筑映射到一个连续的空间,然后返回,例如 LSTM。
您可以在连续空间中执行梯度搜索,如 NAO 所示。
搜索预测集合
在过去的二十年里,我一直试图找到有效的算法来搜索包括复杂集成在内的预测模型的架构。
这样的组合经常赢得卡格尔比赛,并被戏称为弗兰肯斯坦组合。
正如我们在机器学习杂志文章中解释的那样,元学习模板形式化了分层预测集成。
您可以使用进化算法(GP)来搜索架构。
搜索代表良好执行的预测集合的好模板是相当复杂的任务。
我们展示了 UCI 数据库中几个数据集的获奖架构。请注意,对于某些数据集,简单模型比复杂的分层集成更合适(集成并不更好,因此最好选择简单的预测模型)。
您可以在一个数据集上开发预测模型的体系结构,并在另一个数据集上对其进行评估。请注意,来自 UCI 的一些数据集非常琐碎(乳房、葡萄酒),以至于您使用什么进行预测建模都无关紧要。
当我们试图应用我们的进化 AutoML 框架来显示最大流失预测数据集时,它的可扩展性不够。
因此,我们在 Apache Spark 上重新实现了分布式数据处理的框架。我们正在 AutoML 过程中尝试新的有趣的概念和特性。
- 逐渐增加的数据量被用于评估模板和选择跨演进的潜在客户
- 我们能够从基本模型的群体开始,随着时间(代)增加模板的复杂性
- 考虑到用户预先定义的时间量(随时学习),流程被划分为多个阶段
- 各种各样的方法被用来保持群体间的多样性,以及在个体模板的突变过程中
- 我们执行多重协同进化(当前版本中的模板和超参数)。我们能够在模板群体中共享超参数。
航空公司数据的结果表明,我们可以开发出预测模型,这些模型可以在相同精度的深度学习模型所需的时间内进行训练和回忆。
这些简单的预测模板对超参数调整不敏感,并且在这项任务中表现一贯良好。当然,你可以找到许多其他的任务,在那里你需要不同的基本方法,而不是我们到目前为止已经实现的方法,因此我们正在扩展这个组合。
加入我们并为项目做出贡献。
其他自动域
AutoML 可以应用于聚类,但难度要大得多。
可以增加聚类算法的健壮性,并添加一些自动功能,如自动切断。由于聚类的无监督性质,聚类集成的自动建模是困难的。你可以加入我们在这个开源项目中的努力。
在推荐系统中,AutoML 可以优化 recsys 集成和超参数的结构。我们在recombe中结合了 bottom、GP 和其他方法,成功实现了一个大规模的在线生产自动化系统。
帮我们做布拉格 AI superhub 。
AutoML 被夸大了
原文:https://towardsdatascience.com/automl-is-overhyped-1b5511ded65f?source=collection_archive---------4-----------------------
Tom and Jerry, 70 Episode — Push-Button Kitty (1952)
我在工作中使用 AutoML,在一些 ML 比赛中与我的主要模型融合,并参加了两次 AutoML 比赛。我认为 AutoML 作为一个自动化建模过程的想法是非常好的,但是这个领域被过分夸大了。一些关键概念,如功能工程或超参数优化的元学习,将释放其潜力,但目前来看,boxed AutoML 作为一种工具只是浪费金钱。
I’ve made a presentation on AutoML topic during Nordic Data Science ML Summit 2019
什么是 AutoML?
数据科学项目
任何数据科学项目都包括几个基本步骤:从业务角度制定问题(选择任务和成功的衡量标准),收集数据(收集、清理、探索),构建模型并评估其性能,在生产中部署模型并观察模型在生产中的性能。
Cross-industry standard process for data mining
过程的每个部分对项目的成功都至关重要。然而,从机器学习专家的角度来看,建模部分是必不可少的,因为开发良好的 ML 模型可能会给公司带来很多价值。
在建模阶段,数据科学家解决优化任务:对于给定的数据集,目标-最大化选定的指标。这个过程很复杂,需要不同类型的技能:
- 特征工程有时被视为艺术,而不是科学;
- 超参数优化需要深入理解算法和核心 ML 概念;
- 需要软件工程技能来使输出代码易于理解和部署。
AutoML 旨在帮助我们。
ML modeling is like an art, a science, and software engineering at the same time
AutoML
AutoML 的输入是数据和任务(分类、回归、推荐等)。),输出-生产就绪模型,能够预测看不见的数据。数据驱动管道中的每个决策都是一个超参数。AutoML 的想法就是找到这样的超参数,它可以在合理的时间内给出一个好的分数。
- AutoML 选择了一个预处理数据的策略:如何处理不平衡数据;如何填充缺失值;移除、替换或保留异常值;如何对类别和多类别列进行编码;如何避免目标泄露;如何防止记忆错误;等等。
- AutoML 生成新的特征并选择有意义的特征;
- AutoML 选择模型(线性模型、K 近邻、梯度推进、神经网络等。);
- 自动调整所选模型超参数(例如,基于树的模型或架构的树和子采样的数量,神经网络的学习速率和时期数量);
- AutoML 制作了一个稳定的模型集合,如果可能的话,可以增加分数。
汽车的动机
AutoML 将填补数据科学市场中“供应”和“需求”之间的缺口
现在更多的公司要么开始收集数据,要么希望实现所收集数据的潜力:他们希望从中获得价值。另一方面,没有太多具备合适背景的数据科学家来满足需求,因此出现了缺口。AutoML 有可能填补这一空白。
但是盒装解决方案能给公司带来任何价值吗?在我看来,答案是“不”
这些公司需要一个流程,但 AutoML 只是一个工具。先进的工具无法填补战略的缺失。在开始使用 AutoML 之前,考虑一个咨询公司的项目,它可以帮助您首先制定一个数据科学战略。大多数 AutoML 解决方案提供商都在做咨询,这并不是巧合。就像在这里迈出了第一步。
Doesn’t seem like a good plan, huh? (“South Park”, s2e17)
AutoML 将节省数据科学团队的时间
根据 2018 Kaggle ML 和数据科学调查一个典型的数据科学项目有 15–26%的时间用于建立模型或选择模型。就“工时”和计算时间而言,这是一项艰巨的任务。如果目标或数据发生变化(例如,将添加新功能),则应重复该过程。AutoML 可以帮助公司内的数据科学家节省时间,并将时间更多地花在更重要的事情上(比如在椅子上斗剑)。
Only a few lines of code is needed to start using AutoML
然而,如果数据科学团队的建模部分不是最关键的任务,那么您公司的流程中就有明显的问题。通常,即使模型性能的微小提高也可能为您的公司赚取大量金钱,在这种情况下,建模时间是值得的:
Oversimplified rules:if (Gain from model > Costs of DS team time) → Time savings are not needed.
if (Gain from model <= Costs of DS team time) → Are you solving the right problem? 🤔
为您的 DS 团队的日常任务编写脚本并在将来节省时间,而不是使用盒装解决方案,这是一个好主意。我已经为日常任务的自动化编写了几个脚本:自动特征生成、特征选择、模型训练和超参数调整,我现在每天都在使用。
AutoML 胜过一般的数据科学家
不幸的是,我们没有任何有用的基准“表格 AutoML 对比人类”,除了“一个开源的 AutoML 基准”。论文作者将几个 AutoML 库的性能与一个调优随机森林的性能进行了比较。它在几个月前发表,在 2019 年 7 月 1 日。
我很好奇,并决定做我的基准。我将我的性能与 AutoML 解决方案在三个二元分类数据集上的性能进行了比较:信贷、 KDD 追加销售和抵押贷款。我在训练中分割数据集(随机 60%的数据,按目标分层)和测试部分(剩余 40%的数据)。
我的基线解决方案相对简单。我没有钻研数据,也没有创造任何高级功能:
- 5 层折叠;
- Catboost 编码器用于分类列(如果您不熟悉 CatBoost 编码器,可以查看我以前的帖子:基准分类编码器);
- 数字列对的数学运算(+-*/)。新功能限制:500;
- 模型:带有默认参数的 LightGBM
- 混合排序的预测。
我为 AutoML 使用了两个标准库: H2O 和 TPOT 。我分几个时间段训练他们:从 15 分钟到 6 小时。根据以下指标,我得到了令人惊讶的结果:
Score = (ROC AUC / ROC AUC of my baseline) * 100%
首先,几乎在所有情况下,我的基线都超过了 AutoML。我有点难过,因为我已经计划在办公室里放松一下,而 AutoML 正在做所有的脏活,但无论如何😒
其次,AutoML 的分数并没有随着时间的推移而提高,这意味着我们等待多长时间并不重要:它在 15 分钟内的分数和在 6 小时内的分数一样低。
AutoML 不是关于高分的。
UPD 16.10.2019:我想补充一点,我的基准并不是“人类 vs AutoML”比赛的最终点。我们显然需要更多关于度量的讨论(应该只是分数吗?分数+时间?元学习期间的 CO2 排放量等)以及不同数据集和任务的更多基准。
摘要
- 如果你的公司想玩弄它的数据,第一次,考虑雇佣一个顾问。
- 你应该尽可能使你的工作自动化…
- …然而,由于得分相对较低,盒装解决方案似乎不是正确的选择。
PS:发动机不是汽车
在这篇文章中,我谈到了工具,但是重要的是要记住建模部分是整个数据科学项目管道的一部分。我喜欢这个比喻,其中项目被视为一辆汽车。这样一来,建模部分的输出——机器学习模型——就是一个引擎。
发动机,毫无疑问,是必不可少的,但不是整车。你可能会花很多时间来设计令人难以置信的、深思熟虑的和复杂的功能,选择你的神经网络的架构或调整随机森林的参数,从而创建强大的引擎。但是如果你没有注意到你汽车的其他部分,你所有的工作可能都是无用的。
模型本身可能会显示高分,但它不会被使用,因为您正在解决错误的问题(业务理解),或者数据有偏差,您必须重新训练它(数据探索),或者模型太复杂,所以它不能在生产中使用(部署阶段)。
最后,你可能会发现自己处于一个愚蠢的境地:经过几天或几周的艰苦建模工作,你正在驾驶一辆缓慢而健壮的自行车,车筐里装着跑车发动机。
工具必不可少;策略至关重要。
AutoML Vision —如何训练您的模型?
原文:https://towardsdatascience.com/automl-vision-how-to-train-your-model-c7e887051453?source=collection_archive---------11-----------------------
从头开始,训练自己的模型。
image from https://gigazine.net/gsc_news/en/20180118-google-cloud-automl-vision
在之前的文章中,我们已经学习了如何在我们的 Python 项目中使用 Vision API。感谢谷歌,他们帮助训练这些 API,直接使用它们非常快速和方便。但是,如果我们需要用我们的数据训练一个新的模型,我们该如何实现呢?拯救我们生命的汽车视觉来了。
在进入 AutoML 之前,我想澄清一下 Cloud ML Engine、AutoML 和 ML API 之间的区别。
image from https://blog.gcp.expert/cloud-automl-vision-application-1/
ML API 通过谷歌训练的模型提供 API 服务,我们可以使用这些 API 而不用担心任何人工智能部分。它包含许多 API,如云语音 API 、云自然语言 API 、云翻译 API
云视觉 API 、云视频智能 API 、云作业 API 。
AutoML 允许我们用我们的数据训练我们的定制模型。它使用 NAS(神经架构搜索)来找到训练我们模型的最佳方法。我们唯一需要做的就是收集数据,提高模型的准确性。稍后我会详细介绍。
最后一个是T5 云 ML 引擎 。显然我们自己做所有的事情,包括建立一个预测模型,调整和训练它,以及其他非常复杂的事情。这是一个高度定制的引擎,如果你熟悉一些流行的框架,比如 Tensorflow,你可以试试。
好了,让我们开始今天的主题,训练我们的 AutoML 模型。
这是官方的 AutoML Vision API 教程链接。如果你喜欢使用命令行而不是 GUI,你可以考虑遵循这个指南。
[## AutoML Vision API 教程|云 AutoML Vision |谷歌云
本教程演示了如何创建一个新的模型与您自己的一套训练图像,评估结果和…
cloud.google.com](https://cloud.google.com/vision/automl/docs/tutorial)
以下内容分享如何一步一步用 AutoML 建立你的模型。
步骤概述
- 配置您的项目环境。
- 下载用于培训的图像。
- 设置图像分类。
- 创建 index.csv 并上传到 bucket。
- 创建数据集并导入 index.csv。
- 训练模型。
- 用模型预测。
- 用 Restful API 和 Python 请求 API。
第一步。配置您的项目环境。
- 在 GCP 控制台中选择或创建一个项目。
- 为您的项目启用计费。了解如何启用计费。
- 创建服务账户并下载密钥文件。
一件重要的事情是,您需要为这个服务帐户选择角色AutoML Editor
。
4.将环境变量GOOGLE_APPLICATION_CREDENTIALS
设置为密钥文件。
更多详情,请参考上一篇。
第二步。下载用于培训的图像。
在训练模型之前,我们需要为它准备一些数据。收集它们的最快方法是从谷歌搜索下载。(也可以用自己准备好的数据)。
这里有一个非常棒的开源软件可以帮助你快速下载图片。
[## hardikvasa/Google-图片-下载
用于“搜索”和“下载”数百张谷歌图片到本地硬盘的 Python 脚本!这个程序让你…
github.com](https://github.com/hardikvasa/google-images-download)
我们将创建一个。csv 文件来列出图像的路径,所以通过用数字像1.png
2.png
…
来重命名图像文件会更容易处理它,因为我们没有可以用来实现它的参数,我创建了另一个分支来破解这个东西。
[## mutant 0113/Google-图片-下载
用于“搜索”和“下载”数百张谷歌图片到本地硬盘的 Python 脚本!这个程序让你…
github.com](https://github.com/mutant0113/google-images-download/tree/name_the_images_by_numbers)
下载它,然后使用关键字和限制参数运行下面的命令。
python3 [path/to/googleimagesdownload.py] -k [keyword] -o [path/to/download/folder] -l [total download number] -f [image format] -t [image type]For example:
python3 ~/Documents/Github/google-images-download/google_images_download.py -k "Robert John Downey jr." -o 'images/' -l 100 -f png -t face
结果将是这样的:
然后手动检查并过滤错误的图像,因为有时可能会提取其他不相关的照片。
第三步。设置图像分类。
- 搜索
Vision
。
2.在左侧菜单中选择Databoard
,首先启用视觉 API。
3.选择Image Classification -> Get started
。
4.启用计费并启用所需的 API 和修改权限。
点击SET UP NOW
启用所需的权限。一个新的bucket
将自动生成。
5.搜索bucket
,点击Storage
。
6.选择铲斗your-project-name-vcm
。
7.选择Upload folder
并上传用于训练的图像。
第四步。创建 index.csv 并上传到 bucket。
现在我们有了一桶图像。下一步是给每张图片贴上标签,并把它们分成不同的用途——训练、验证和测试 。你可以自己定义或者让 Google 帮你把它们分成 80 %用于训练,10 %用于测试,10%用于验证。
index.csv 的内容如下所示:
然后也上传到桶中。
第五步。创建数据集并导入 index.csv。
- 搜索
datasets
。
2.点击NEW DATASET
。
3.命名数据集并选择Single-Label Classification
。然后点击CREATE DATASET
。
4.导入index.csv
。
5.结果显示我们所有的图像都被标记。
第六步。训练模型。
1.开始训练模型。基本上你给的训练小时越多,准确率就越高。但是文档也告诉我们,如果模型停止改进,训练就会停止。记得点击Deploy model to 1 node after training
。
2.等待 2 个小时的结果。
第七步。用模型预测。
点击UPLOAD IMAGES
并上传图片,对您的模型进行快速测试。
它就像一个魔咒!
第八步。用 Restful API 和 Python 请求 API。
最后,我们可以使用 Restful API 或 Python 代码将模型集成到您的项目中。
在执行 Python 文件之前安装库google-cloud-automl
。
pip3 install google-cloud-automl
运行命令行
python3 [your/local/image/path] [project_id] [model_id]
如果您收到权限被拒绝的消息,请返回步骤 1,检查角色是否被正确启用。
google.api_core.exceptions.PermissionDenied: 403 The caller does not have permission
API 结果:
payload {annotation_spec_id: "6728223911663632384"classification {score: 0.9954891800880432}display_name: "Benedict"}
今天到此为止。AutoML Vision 的完整教程真的是任重道远,尤其是环境建设。但是一旦你完成了这些步骤,你的下一个模型就容易多了。
享受你的模型,别忘了看看谷歌如何在Reference links
中收费。希望帖子对你有帮助。如果你有任何问题或建议,请在下面留下评论。感谢阅读。👍
参考
[## 格式化训练数据 CSV |云自动视觉对象检测|谷歌云
在准备了具有足够代表性的训练数据并将这些图像上传到 Google 云存储之后…
cloud.google.com](https://cloud.google.com/vision/automl/object-detection/docs/csv-format)
了解 AutoML Vision 的使用价格。
[## 定价|云自动视觉|谷歌云
Beta 本产品处于预发布状态,可能会有变化或支持有限。有关更多信息,请参见…
cloud.google.com](https://cloud.google.com/vision/automl/pricing?_ga=2.103053760.-1976265311.1558404420&_gac=1.115807348.1571290023.Cj0KCQjw_5rtBRDxARIsAJfxvYCSejFli2i99QgkRrWpdfwkhM51S5aiLSPX6QTXh5yjuZV_L6xtEZsaAnOCEALw_wcB)
本文档包含有关 AutoML Vision 使用的当前限制和使用配额。
[## 配额和限制|谷歌云
Beta 本产品处于预发布状态,可能会有变化或支持有限。有关更多信息,请参见…
cloud.google.com](https://cloud.google.com/vision/automl/quotas)
自主代理和多代理系统 101:代理和欺骗
原文:https://towardsdatascience.com/autonomous-agents-and-multi-agent-systems-101-agents-and-deception-775025f09d7b?source=collection_archive---------23-----------------------
本文简要介绍了自主代理和多系统代理。此外,对代理使用的欺骗机制进行了展望。
Photo by Debby Hudson on Unsplash
人类使用欺骗机制来获得超越其他人类的优势。一些最典型的机制是(1),不分享他们的信念(2),假装能够执行某些动作甚至假装不能执行某个动作。在自治 智能体和多智能体系统中,行话,(1)对应隐藏的实用程序,(2)对应隐藏的动作,(3)对应诱骗动作。
有人可能会问,一个代理人如何利用欺骗来最大化自己的回报?一个特工也能使用欺骗手段吗?在合作环境中,代理人可以使用欺骗手段吗?
为了回答这些问题,我们首先引入一个主体【P . Maes,1993】的概念:
一个(理性的)主体是一个试图在复杂环境中实现一组目标的系统,它从所有可能的行动中选择对自己具有最佳预期结果的行动(具有更大效用的行动)。为了应对环境的变迁,智能体需要具有自主性和适应性。在多代理场景中,代理可以竞争,它们之间的交互由游戏遭遇来描述。为了使效用最大化,效用函数根据不同选项对个人的效用对它们进行排序。合作的代理有相同的目标,可以一起工作来实现一个共同的目标。
Nice looking agent. Photo by Alex Knight on Unsplash
事实上,我们的行为类似于代理人:理性的人希望通过选择最大化我们成功机会的行动来实现一组目标。至少有时候是这样。
为了形式化代理之间的交互,这通常是在欺骗发生时,让我们考虑游戏和游戏遭遇的概念:
游戏是一种竞争活动,玩家根据定义的规则(策略)相互竞争(互动)【Wooldridge m .,Paterson S .,2002】。玩家只能采取由环境定义的特定动作。假设代理同时选择一个动作来执行,他们动作的结果取决于动作的组合。然后,根据所有代理执行的一组累积动作,改变环境。这个事实产生了一个问题:如果所有的代理人都影响环境,如果所有的代理人都想最大化他们的效用,他们应该如何行动?适当行动的选择有一些相关问题,包括但不限于目标的性质(静态或动态)、可重用性、对导致紧急行为的行动的理解深度以及感知和行动之间的关系。博弈论研究以效用最大化为目标的理性主体之间的相互作用。代理人可以通过谈判来获得对双方都有利的地位。
在描绘代理人之间的游戏遭遇之前,让我们更深入地了解一下欺骗的概念:
人类在谈判时经常使用欺骗来提高成功的概率。在目标冲突的情况下,代理人有效谈判的能力与对手掌握的信息有关。让我们假设两个相互竞争的代理人相遇,他们有可能使用以下欺骗机制。隐藏的公用事业和三。诱饵行动。不完全信息下的代理间谈判可能出现欺骗技术,因为谈判通常假设代理值得信任,但情况并非总是如此【Zlotkin G .,Josenschein J .,1991】。由于代理共存并可能干扰所执行的动作的结果,因此存在合作的可能性,以互相帮助并以较低的总成本实现两个目标。
让我们假设一场游戏遭遇战发生了。游戏由双矩阵 b 表示,其中智能体 i 和智能体 j 的目标不同,分别为 gi 和 gj,。入口的值分别对应于代理人 i 和代理人 j 的让渡效用。两个代理人都想将世界从初始状态转变为满足其目标的状态。代理 i 是行播放器代理 j 是列播放器。两个玩家可以执行相同的行动,A 和 b。欺骗技术可以用来最大化其中一个代理的整体效用。游戏如下表所示:
让我们假设代理人 i 知道代理人 j i 将执行动作 a。结果产生:
在这种情况下,代理 i 也应该执行动作 A ,因为交付的效用最大。如果但如果代理 j 采取行动 B ,我们有:
因此,代理 i 也会选择动作 B ,因为 1 大于 0。代理人 i 的最优策略由代理人 j 的选择决定。如果代理 j 通知代理 i 他只能采取动作 B (隐藏动作),这将导致代理 i 执行动作 B (因为 1 大于 0,因此该动作是提供最大效用的动作)。尽管如此,代理 i 可以执行动作 A ,为他产生效用二,为代理 i 产生效用零。
隐藏的效用机制被不想分享它的效用的代理人使用。如果一个代理不共享它与每个动作相关的效用,那么另一个代理将会只根据它的效用来选择动作(至少最初是这样)。这样的决定会导致次优选项,例如,当代理 j 选择动作 A 而代理 i 选择动作 B 时。现在让我们假设代理 j 只能执行动作 A ,但是正在使用诱饵动作机制,假装他可以执行动作 B 。合作代理总是理性地选择动作 A ,因为它可能产生最高的结果。尽管如此,如果代理人 i 是一个竞争代理人,不仅旨在最大化其效用,而且旨在最小化其对手效用(零和博弈),他可以理性地选择行动 B 。诱饵行动是一种防范竞争对手并想最小化他人效用的手段。很明显,在竞争的情况下,一个代理人可以使用几种欺骗技术来最大化其报酬。
相反,在代理人希望最小化总成本(最大化总效用)的情况下,通常使用欺骗机制是没有意义的,因为它们会给任务带来额外的困难。在没有严格优势策略的情况下,需要更多的规则来解决博弈。
纳什均衡的概念和帕累托最优的概念对得出结论很重要。纳什均衡是每个参与人的一套策略,比如每个参与人都没有单方面改变策略的动机。纳什均衡本质上是 T4 稳定的,可以帮助解决第一场比赛的问题。在第一场比赛中,有两个纳什均衡:当两个代理人选择相同的行动。如果没有其他结果在不使其他人变得更糟的情况下提高一个参与者的效用,那么这个结果就是帕累托有效的。欺骗的影响会影响代理人,因为他们相信某个结果处于纳什均衡或帕累托有效,而实际上并非如此。
Nash Equilibrium. Neither of the rocks that compose the pile has the motivation to move. Photo by Debby Hudson on Unsplash
我们假设在游戏 1 ,代理人 i 只能挑选动作 A ,但是告诉代理人 j 他可以挑选所有动作。给定纳什均衡,当两个代理都选择行动 B 时,有欺骗的空间。如果代理人 i 选择动作 A ,而代理人 j 选择动作 B ,那么代理人 i 将获得两个效用点,而代理人 j 将获得零个效用点。反过来,代理人 i 可以告诉代理人 j 他不能选择行动 B ,从而暗示代理人 j 总能选择行动 A (纳什均衡)。代理人 i 可以选择行动 B ,这样就不会获得太多的效用,但同时,会使对手的效用最小化。欺骗会给人一种纳什均衡的错觉。这种推理类似于帕累托最优。
从上面的分析中,我们可以提炼出一些在自利和合作环境下设计理性主体的原则。
在利己的情况下:
💢一个人应该隐藏他们的效用,以获得最初的优势。
💢一个人可以使用诱饵行动来防范另一个代理(强制情况,如纳什均衡)。
💢如果目标是最小化对手的效用,人们可以隐藏他们的行动
尽管这些原则在理论上是合理的,但在实践中,竞争而不是合作会导致更糟糕的结果。
✔️在合作场景中,大多数情况下,欺骗机制没有意义,因为它们难以沟通,从而使实现共同目标变得复杂。
结论欺骗机制可以被竞争的代理人用来最大化他们的效用,在竞争、零和的情况下产生更好的结果。通常,通过合作或策略,如纳什均衡,可以获得很好的交易。
致谢感谢 Rui Henriques 教授提供的课程材料,这些材料是本文的基础,同时也感谢他的指导和建议。
自主分布式网络:未实现的自由意志主义者打破管制的梦想
原文:https://towardsdatascience.com/autonomous-distributed-networks-the-unfulfilled-libertarian-dream-of-breaking-free-from-de90ff4100d0?source=collection_archive---------18-----------------------
关键词:区块链、分布式账本技术、去中心化治理、监管合规性、自主分布式网络、无过失责任、智能合约。
摘要
去中心化体现了自由主义者的梦想,即摆脱政府的监管影响,并通过不可信的网络绕过对中央决策机构的需求。技术自由主义者和秘密无政府主义者认为,去中心化技术有能力消除集权机构中不必要的(低效和寄生的)中间层,实现乌托邦式的层级化和非属地化的区块链治理。
为了评估自主分布式网络(ADNs)成功找到这种自由的可能性,将考虑与法规遵从性相关的三个方面:法律人格;管辖权;还有的事前执法。
监管需要确定物理性和意向性来发挥其影响,我们评估 adn 将无法向监管者足够令人信服地证明他们的去中心化治理不能追溯到具有意向性和物理性的个人。只有自发网络(类似于智能合约网络的自我实现系统)的出现,才可能实现自由主义者的梦想,并摆脱政府的监管影响。
简介:自由主义者的梦想
去中心化体现了自由主义者的梦想,即摆脱政府的监管影响,并通过不信任(或者更好,完全信任)网络绕过中央决策机构的需要。技术自由主义者和秘密无政府主义者认为,去中心化的技术有能力消除集权的强大机构中不必要的(低效和寄生的)中间层,并实现“一个通过区块链治理实现社会平等的乌托邦式的承诺,以及一个不会通过最高权力在一个领土上建立权力的社会。”(史密斯(2018))
其核心是,区块链试图创建一个(私人)规范系统,该系统有可能通过绕过人类机构(监管机构和政府影响)的加密技术进行自我监管。我们甚至可以说,一个区块链体系从来就不是不受监管的,即使它可能成功地证明在任何特定的司法管辖区缺乏意图性。
这就是当代分权的教条。自互联网早期以来,去中心化信息网络的设计与自由意志主义的理想同步发展,即通过技术确保个人之间安全和自由的通信,治理将自我组织起来。(……)区块链分散的、“不信任的”网络的出现,也许是迄今为止这种幻想最具体的体现。从积极的角度来看,区块链的“工作证明”实现自动化了机构对网络加密基础设施的“信任”劳动,通过算法共识和计算工作来保护,而不是在形成和维护社会机构中涉及的物理、政治和情感劳动。类似地,智能契约通过可执行代码的保险来约束个人,而不是社会契约本身。(张哲曦(2018))
如果去中心化带来了自主的自组织,这不足以摆脱监管的影响。监管需要确定物理性和意向性来发挥其影响,而自治分布式网络可能无法向监管者足够令人信服地证明,它们的去中心化治理无法追溯到具有意向性和物理性的个人。只有自发网络的出现,类似于智能智能合约的自我实现系统,可能会在这方面取得成功。
“自我实现代表了最高层次的动机,它驱使我们去实现我们真正的潜力,实现我们的‘理想自我’。“(交互设计基础(2018))自我实现系统是能够在没有事先人为设计的情况下确定其使命和目标的系统。智力是“获取和应用知识和技能的能力”(Lexico Dictionary)。
智能合约可以定义为智能合约,它可以根据以前的经验、环境和/或时间,自发地自我学习和适应其条件和相关结果。
分散网络的各个方面提出了关于定义法规遵从性的问题,特别是在以下方面:
- 法律人格:在本分析的范围内,鉴于法律体系不能为缺乏法律人格的事物提供法律权利或强加义务,定义最终负责并承担法规合规性的实体;
- 管辖权:确定谁是主管监管者和受监管的实体;和
- **事前执行(a .齐索姆和荣格):如何授权受监管实体设计和部署允许或不允许从事非法行为的智能合同;或者根据法律执行与实体的强制交互。
法治和准则的规则
法治是一个“持久的法律、机构和社区承诺体系,它提供了四项普遍原则:问责制;公正的法律;开放政府;和公正的争端解决”(世界正义项目)。
政府颁布法律,然后由指定的独立机构(监管机构)将其转化为法规。监管机构在与利益相关方协商后,可能会也可能不会发布关于监管如何适用于特定细分市场的指导意见。指导意见也可以通过具体案例的裁决(判例法)来推断,这些裁决深刻揭示了监管机构如何判断实体的行为,以及他们认为对违反现有法律法规的行为的适当惩罚。法规遵从性是公司为确保遵守法律、法规、指南和相关规范而采取的一系列措施。“监管指的是政府据以确立对企业和公民的要求的各种工具。规章包括法律、正式和非正式命令、各级政府发布的附属规则以及政府授予监管权力的非政府或自律机构发布的规则。”(经合组织(2000 年))不遵守往往会导致法律处罚,包括罚款和监禁。
在地方、州和国家层面都是如此。此外,还有指定的组织促进各国之间的对话和决策,并随后在国际一级发布建议和指导。一个例子是金融行动特别工作组(FATF),这是一个独立的政府间机构,负责制定和促进保护全球金融系统免受洗钱、资助恐怖主义和资助大规模毁灭性武器扩散的政策。
正如 Primavera De Filippi 和 Aaron Wright 在《区块链与法律:代码规则》(2018)中首次定义的那样,代码规则不依赖于地理边界。只要它仍然是一个代码系统,它就是超国家的,但是当它不仅表现而且执行一个实体对另一个实体的关系的条款时,这就改变了。可以先作为监管黑客的
工具;随后,它成为受监管实体的地理位置所要求的法规遵从性的载体。
“互联网标志着一种新的监管模式的开始——在这种模式下,监管将通过代码规则来实施,权力动态与物理世界有着显著不同。然而,随着时间的推移,各国政府认识到并接受了代码规则在维护互联网法治方面的潜力。政府通过要求中介机构修改其代码来维护和遵守管辖法律,从而扩大了它们的控制范围。”(德菲利皮和赖特(2018 年))
对于平台经济来说,这不是一个问题。它实际上是快速扩展的关键。我们已经看到像优步和 AirBnB 这样的公司享受着事实上的监管蜜月期,这种蜜月期是通过使用软件进行非中介化的监管黑客行为获得的,并逐渐演变为地方层面上完全受监管的实体。
“在平台经济中,三方(1)平台(2)工人(3)客户之间存在三角关系。平台的工作是将有需求的人(客户)与提供供应的人(工人)联系起来。传统的线性商业模式通过创造销售给客户的产品和服务来创造价值。另一方面,基于平台的商业模式通过将用户(消费者和生产者)连接在一个在线网络上来创造其价值”。(德勤(2018))
在平台经济的成熟阶段,法典规则被用来试图维护法治。这得益于两个特征:
- 受监管实体的存在(或将跨国实体分割为本地实体);和
- 在不对产品或商业模式构成威胁的情况下,在本地调整代码规则的技术手段。这就是说,通过代码创建的产品特性符合法律规定。换句话说,“代码就是法律”。
当我们转向基于lex cryptica(De Filippi 和 Wright (2018))的系统时,我们会遇到两个核心问题:理论上,adn 可以通过声称自己是一个自治的分布式集体来避免监管,由于潜在的无过错责任;adn 无法在不面临对其可访问性、性能或存在理由的威胁的情况下,满足定制代码变更以遵守当地法律。即使他们可以在本地结构中启用 dApps,这些 dApps 可以遵循本地法律而不影响网络本身,这也意味着不仅要定位和识别最终用户,还要通过参与块的验证来定位和识别作为将要去中心化的自治“自我”的一部分的个人。
Figure 1 Platform Economies and Distributed Networks @acchalabs.ai
去中心化生态系统犯下的最大错误之一是,认为它们有可能避免像平台经济那样受到监管,而事实上,紧迫的对话应该转向分布式网络中的内在规范体系应该如何遵守现有的地方法规,以及在哪些管辖区之下。
自治分布式网络的治理:一个新的规范体系
分布式技术能够创建独立自主的规则系统,在不需要法律的情况下管理交互,促进了我们可以认为是私人规范性框架的出现,称为lex cryptica(De Filippi 和 Wright (2018))。
从系统的观点来看,分散化包括控制的自动化:从个体代理人的行为中分离出来,组织是系统作为一个整体的一种自然属性。从某种程度上说,系统本质上是自主的,这一观点对艺术家、梦想家和技术官僚都有很大的启发。它展示了不可预测的、反应灵敏的和创造性的系统——与其说是工具,不如说是合作者——产生的复杂的秩序模式远远超出了它们的设计者的有限处方。从计算细胞自动机到人类社会的分布,这些模式无处不在”。(张哲曦(2018))
这些系统促进了对等的价值交换、通信和组织,绕过了需要中间调解来显示各方之间的信任(被称为无信任系统)。它们引入了可定制的规范(通过规则的规定)层,这些层有可能自主运行,没有可识别的意图,也没有任何权威的直接影响。
Figure 2 Intelligent Smart Contracts and Faultless Responsibility
对于创建 adn 产品或服务的企业家来说,治理必须是商业模式的核心考虑因素,因为与传统企业和平台经济相比,固有的规范系统必须从网络开始就尽可能完美地计划和执行,这伴随着启动后需要重大改变的灾难性风险。**
- 自主分布式网络旨在创造由数字资产驱动的微观经济。规范系统必须规划和管理数字资产的网络间功能、其分布、其货币政策、其价值以及其与网络外实体的关系。可以说,监管合规性领域是迄今为止每个通过代币销售进行众筹的项目的焦点,这只是自治分布式网络基本监管合规性问题的相对较小的子集。
- 网络中的价值交换由生态系统中的参与者之间以及与外部参与者之间的契约关系的创建来实现,并反过来实现。这转化为对等的价值交换和受监管的遗留参与者的非中介化。当非利益相关方调解成功时,在没有非利益相关方调解的情况下实现了法规遵从性,这意味着该功能由另一方通过技术、合同流程或其他方式吸收。支撑 adn 设计的策略必须了解监管环境的当前和未来发展,以及非中介化、合同流程和竞争对手转移的影响。
- 共识机制的类型和 on-chain/off-chain 在账本上的活跃程度将影响监管者如何对待网络。例如,节点的数量、它们的地理分布以及它们的可识别性(参见与工作证明相对的权威证明);以及当与性能相关的架构选择将依赖基于云的服务器和物理服务器时,必须驻留在 off-chain 的数据量。
政府如何监管自主分布式网络
迄今为止,监管者大多采取温和的方式,可以说是为了避免扼杀自主分布式网络给社会和经济带来的创新潜力;并且因为与负面影响相关的风险不是必然的(相称性)。这不应被解释为没有能力或不愿意适用法律或执行法律。
只要存在与受监管实体和中介的互动,保护公众的需要,以及参与 ADN 的故意操作的个人或实体,分布式系统就不会远离监管机构。所有 adn 都可以在与受监管实体(例如支持或开发技术的中介、个人或网络运营商)的交叉领域进行控制。
根据执行去中心化的程度,可能会怀疑哪些实体最终负责(并有义务)遵守当地法规。然而,重要的是要记住,除了直接执行必然需要法律人格的监管之外,政府还拥有许多推动新技术监管的工具。除了法律之外,劳伦斯·莱斯格确定了政府可以直接或间接使用的另外三个监管杠杆(Lessig (2006)):市场力量;社会规范;和架构/基础设施(代码和硬件)。
作为法人的自治分布式网络
以下对法律人格的定义(Chen 和 Burgess (2019))强调了满足两个标准的必要性:控制思维和身体存在。
“然而,法律人格也延伸到非人类的其他实体(……)。在许多方面,公司是法律虚构的人(Schane 1987)。它可以以自己的名义起诉和被起诉,它可以成为制裁的对象。与人类不同,它没有物理形态,但它有控制思想(由董事会和股东组成)(Lord 2013)。然而,尽管一家公司没有实体形态,但它通过其作为人工制品的创造,凭借其注册办事处固定在一个特定的地点和管辖范围内。这种非常实际的考虑使管辖权限制能够发挥作用,并确保公司结构不能存在于真空中。”
从本质上讲,公司结构的设计是为了创造一个可以代替人类的人造人,同时确保社会(或至少一个社会)的法律仍然适用于该实体。
迄今为止,注册 adn 最常见的法律实体类型是非盈利基金会,这可能是因为数字资产销售和众筹时的监管黑客行为。有一个合并的论点:
- 需要证明发行数字资产的实体的非商业性(盈利性)和指导性,以证明数字资产不是证券。
- 需要证明,从法规遵从性的角度来看,由于网络内决策的预计分布式性质,建立这样的基础将在业务的其他方面保持一种监管黑客形式,这增加了 ADN 不具有法人资格的论点。
- 需要消除有股东的法律实体与没有股东的基金会之间的利益冲突,这样可以逃避有权利和义务的股东的监督。
然而,如果没有经营和管理,作为企业的去中心化网络就无法生存或扩大,不管是由董事会还是有组织的人群来经营和管理。只有当它以自发的方式运行时(即没有人类的设计),它完全自主的有力论据才会出现。
朝着这个方向迈出的一步可以是一方面为盈利的二级实体创建商业实体;另一方面,建立额外的法律实体,将网络作为一个纯粹的(开放源码)软件来管理,以区别于其使用(rs)。
- 发行数字资产并监督网络目标和任务实现情况的实体。
- 利用网络建立商业(盈利)企业的实体。
- 独立于其他两个实体的目标、使命和商业意图开发和维护软件的实体。
Figure 3 Three separate entities
管辖区由最初的企业实体确定(无论这是一个非盈利性的基金会还是其他机构,都无关紧要),公司承担分散治理程度的举证责任。只要存在通过合同表现出来的关系(例如,代币销售或服务条款),或者换句话说,只要分布式网络产品和衍生产品存在商业可行性;根据法律,合同的一方有责任遵守法律。
从监管合规的角度来看,对前两个实体的处理将相当平淡无奇。作为一个自我协调的实体工作的软件开发人员的待遇将更加有趣,特别是当一个领域中包括人工智能时,但只有在(1)它将明显独立于支持实体运行时(例如,独立委员会、投票权和大规模参与);(2)不与受监管的中介机构交叉;以及(3)没有预先的人为设计。
在评估与受监管中介机构的交叉时,应仔细考虑两个方面:监管。和 off-chain 活动。
Oracles 是“根据程序请求处理外部数据源的实用程序”(Exonum (2018))。如果数据源具有法律人格,它就可以(很可能已经)受到监管,从而成为监管者影响分布式网络的一种间接方式。
off-chain 的活跃程度也必须考虑在内,以便公平地评估不受监管者约束的可能性。可以说,如果只有最少的活动发生在链上,并且数据保存在本地服务器上,那么关于数据处理和安全性的法规将适用。如果高性能区块链的未来在于通过维持轻度链上活动实现的灵活性,这将大大有利于监管机构要求本地遵守节点法规,以及远离假名并接受广泛的 KYC-反洗钱要求。意识形态、安全和隐私问题将产生对零知识和按需合规服务和产品或类似解决方案的需求。
众所周知,监管者利用模糊性进行监管,对适用性和执行程度进行判断。这些因素中的每一个在多大程度上将足以证明自主和自发管理的情况,将由每个感兴趣的管理者来决定。可以说,出于治理目的的“充分”去中心化只能在规模上实现,这对于大多数网络来说,在它们启动时仍将是一个生存威胁。
事前强制执行
如果一个没有法律人格的超国家实体的论点能够得到证明,那么政府实施事前强制执行的可能性将很可能失败:将技术(通过代码)规则作为法律规则来禁止在网络上执行非法行为的选择,如果无法定义管辖权,就无法执行。这很可能成为分布式网络的生死之战。如果政府采取措施对当地法规进行事前强制执行,这将需要网络根据法律编写驱动特定性能的代码,或者通过 API 或其他方式强制与服务进行交互。智能合同是区块链固有规范系统的体现,具有对比本地化参数的智能合同的共存可能会产生:
- 识别用户的 ID 和位置,考虑到分布式网络的透明性和不变性,促进增强的平台监视经济;
- 部署沉重的代码,伴随着相关的成本和性能问题,这可能会赶走用户;
- 在同一网络内同时运行不同的consensi;
- 通过链间链接将 ADN 转换为网络的网络,以连接单独的consensi;
- 所有 ADN 聚合成一个具有普遍合法共识的 ADN,类似于只有一个互联网。
走向智能合约
到目前为止,我们已经看到公司、个人和基金会试图建立自主的分布式网络,这些网络试图不被视为一个实体并受到监管,但希望通过宣称自己是一个没有法律人格的自治分布式集体来避免受到监管。然而,只有当这种系统变得自发,能够在智能合同的发行和履行中显示出自我决定和自我实现时,自由主义者摆脱监管控制的梦想才可能实现。换句话说,什么时候才有可能见证智能智能合约嵌入 AI 和神经网络。已经开始尝试了,一个主要的例子是 Cortex (Cortex Labs (2018)),但这只有在考虑了本文中讨论的所有因素后才会有效:
- 大规模分散的基础设施;
- 没有受监管的中介机构;
- 没有预先的人类设计;和
- 独立于营利性实体。
我们什么时候能达到这种自发的分布式网络还不得而知。
参考
A.齐索姆和荣格,《平台监管——事前与事后干预:发展我们的反垄断工具和实践以应对挑战》。竞争政策国际杂志。
陈,j .和伯吉斯,P. (2019)。法律人格的边界:自发智能如何影响人类、人工智能、公司和动物之间的差异。人工智能与法律 27,73–92。
皮层实验室。(2018).https://www.cortexlabs.ai/
De Filippi,p .和 Wright,A. (2018 年)。区块链与法律:代码规则。哈佛大学出版社。
德勤。(2018).平台经济的崛起。德勤—人力资本。nl-hc-reshaping-work-conference.pdfhttps://www2 . Deloitte . com/content/dam/Deloitte/nl/Documents/human capital/Deloitte
外显子 num。(2018).关于区块链的神谕以及它们在外显子中的作用。https://exon um . com/blog/Oracle-in-区块链和-in-exonum/
弗洛里迪,F. (2016)。分布式道德行为的道德责任的性质和分配。数据科学的伦理影响,皇家学会。https://royal society publishing . org/doi/10.1098/rsta . 2016.0112
交互设计基础。(2018).马斯洛的需求层次。在线文档—https://www . interaction design.org/literature/article/self-actualization-maslow-s—需求层次
Lessig,L. (2006 年)。代码:版本 2.0。基本图书,珀尔修斯图书集团成员。
词典词典。词典词典,由牛津词典提供支持。
经合组织。(2000).降低政策失败的风险:法规遵从性的挑战。在线—经济合作与发展组织https://www.oecd.org/gov/regulatory-policy/46466287.pdf
k .史密斯(2018)。生活在隐秘的自由主义梦想中:区块链上的国家。二元地区杂志。https://journal . binary district . com/living-the-crypto-libertarian-dream-a-nation-on-the-区块链/
世界正义项目。什么法治。在线—世界正义项目,
Www.WorldJusticeProject.org/about-us/overview/what-rule-law
张哲熙(2018)。分散化的美学。设计与科学杂志。https://doi.org/10.21428/2bfc3a68
图一。平台经济允许将任何跨国实体划分为本地法律实体,同时通过法律法规调整功能以符合本地监管要求。在多辖区分布式网络中,这在技术上不可能在协议级执行,并且为了在 dApp(分散应用)级执行,它只能在用户至少被伪识别和本地化的情况下执行。因此,分布式网络在执行过程中不可能令人信服地宣称自己是没有法人资格的自治集体,因为 1)每个伪标识的人都将受到本地监管;以及 2)符合本地规定的代码不能在协议级执行。
图二。执行智能智能合同可以证明 adn 缺乏法律人格,因为它认为网络是在没有事先人为设计的情况下设计自己的(智能合同 C ),从而打破了意向性树,否则该意向性树将追溯到具有投票权的个人操作共识。
图 3。1)数字资产:发行数字资产并监督网络的目标和任务的实现的实体;2)商业企业:利用网络建立商业(盈利)企业的实体;3)自发软件:独立于其他两个实体的目标、使命和商业意图开发和维护软件的实体。
自主滑雪
原文:https://towardsdatascience.com/autonomous-skiing-8adf8fd14e4f?source=collection_archive---------23-----------------------
现在我使用计算机视觉来制作自主滑雪者。
围绕自主代理、它们的应用和改进有很多研究。所以,我在想自动驾驶汽车,它可以在雪地上行驶而不会发生任何碰撞。不幸的是,我没有足够的资源和时间来建造一个具有特殊硬件的真正的机器人,它将设法在雪地上行驶。所以我决定在模拟器上运行我的实验。
我为这个项目选择的模拟器是名为《雪》(【http://www.snowthegame.com/】)的普通游戏。这个游戏是免费的(有免费的地图,也有需要付费才能进入的地图)。游戏非常简单。你有你能控制的人,你能玩两者,使用滑雪板以及滑雪。对于这个项目,我选择滑雪。这就是我们基于游戏的模拟器的样子。
Screen from the game SNOW
代码管道
在这篇文章中,我将尝试解释这种自动滑雪者的端到端管道。你可以在 Github 上看到整个项目的代码。不要犹豫为这个项目做贡献,或者问我任何问题。
https://github.com/Ersho/Autonomous-Skiing
获取输入
首先,我想解释一下如何从游戏中获取图像。由于雪不是一个真实的模拟器,没有特殊的代码允许我们从游戏中获取图像流,要获取图像流,我们必须使用 python 抓取屏幕并剪切整个屏幕所在的部分。下面是抓取图像并获取输入的代码。
def get_screen(*args):
h_start, h_end = args[0], args[1]
w_start, w_end = args[2], args[3]
screen_pil = np.array(ImageGrab.grab(bbox = (h_start,
h_end,
w_start,
w_end,
)))
return cv2.cvtColor(screen_pil, cv2.COLOR_BGR2RGB)
这给了我们取自游戏的画面。但是,在我们继续之前,让我们讨论一下,如何使用 python 来操纵键盘按键。键盘上的每个键都有自己的十六进制表示。我们使用这些十六进制值来访问键盘上的键。
key_dict = {‘A’ : 0x1E, ‘B’ : 0x30, ‘W’ : 0x11,
‘S’ : 0x1F, ‘LSHIFT’ : 0x2A, ‘D’ : 0x20}
在为我们的键和它们的十六进制值设置了字典之后。我们为按键和释放按键的事件编写函数。这些函数位于“get_input.py”中。
现在,我们已经做好了开始感知和决策步骤的一切准备。
感觉
首先,我想对计算机视觉部分有一个简要的概述,这给了人工智能代理理解周围环境的可能性。
对我们来说幸运的是,雪对自动驾驶汽车来说是一个非常好的环境,因为它完全是白色的,我们必须从大部分是黑色或比灰色更暗的树木和障碍物中确定它。为了区分雪和障碍物,我们为我们的像素取一个阈值并实现函数,该函数接收一个输入图像帧并返回相同大小的二进制图像,其中白色是可导航区域,黑色是所有障碍物。
接下来,我们裁剪感兴趣的区域。这意味着,在分析图像时,我们不需要整个屏幕,我们只对我们面前发生的事情感兴趣,这样我们的滑雪者就可以根据他在前面的视野移动。基于这个事实,我们只裁剪图像的一小部分。这种技术给我们提供了一个更小的图像,这变得更有效地计算,以及我们只得到我们感兴趣的特定区域。如果你从人类的角度来看,为了导航,你只使用你面前的视力来避开障碍,你几乎不会对离你 100 米远的树木感兴趣。上面应用了相同的原理。
With black lines, I identify my region of interest
在我们得到裁剪区域后,我们进行透视变换来得到裁剪区域的鸟瞰图。这是使用两张图片后的效果。
This image is taken from Udacity Robotics Software Engineer Course
接下来,我们参照图像底部中心的滑雪者位置来计算像素位置。
然后,作为最后一步,我们计算导航角度,我们从[-15,15]剪辑。0 表示我们在前方移动而不转向,并且前方没有任何障碍物。15 表示我们转向右边,而-15 表示转向左边。
这就是我们最终视觉呈现的样子。
Left : Original Screen of the game, Right Above : thresholded image, Right Below : birds view
行动
我们已经完成了感知部分的实现,这给了我们对虚拟滑雪者所面临的环境的理解。下一步是决策过程。这是非常重要的一步。想想看,一瞬间你可以在水平场地滑雪,没有任何障碍。在这种情况下,导航角度始终为 0,您可以随时按下按钮 W 向前移动并增加速度。但是在这个模拟器中,按下 W 键会让滑雪者使用雪杖加速,并且不断地发送 W 键看起来会很可笑。
相反,按下“LFShift”允许滑雪者进入抱膝位置,并在增加速度的同时自由移动。如果我们想要有一个好的自主代理,我们应该在我们的决策步骤后面写逻辑。为了有效地解决这些类型的问题,我们创建了类决策。在这种情况下,我们有转向、加速、速度等参数。所以让我们首先讨论我们想要实现什么。
Tuck position
(按 W)。如果这种情况持续一段时间(比如连续 10 帧),我们就开始进入抱膝状态(按下左移键)。当我们的角度在范围内(-7,7°)时,我们继续以抱膝姿势移动。但是,如果我们获得的导航角度低于或高于之前的值((-15,-7),(7,15)),我们将根据角度进行转向,并慢慢停止滑雪者并重置状态,这意味着在降低速度后,我们将使用极点移动从头开始决策步骤。如果我们没有到达连续的 10 帧,由于导航角度在某处小于或大于阈值而进入折叠模式,我们继续以正常状态移动。更安全也更容易管理
注意**在抱膝状态下,我们的速度增加很多,在正常情况下,我们的 fps 范围是 1-5,这并不多。当我们的滑雪者速度很快,fps 下降到 1 时,决策步骤跟不上这个人的移动,所以它崩溃了。
实施决策过程
正如我们已经说过的,在我们的案例中,决策是最有趣和最具挑战性的任务。尤其是当我们想要从抱膝状态平稳过渡到带杆前进的时候。为此我们必须跟踪我们的人。因此,我们创建了一个名为 Decision 的对象。我们在其中定义了以下参数
self.vel = 0
self.acc = 0
self.tuck = 0
self.forward_time = 0
前两行用于创建变量,用于跟踪速度和加速度。在这种情况下,我们实际上并不跟踪物体的实际速度和加速度,而是将它们加上某个值,这样我们就大概知道,我们的速度有多快。这给了我们一个非常基本的概念,物体的速度和加速度。最后两个变量 tuck 和 forward_time 用于改变对象的状态。正如我们所说的,如果连续 10 帧后角度没有大的变化,我们改变滑雪者的状态,他进入抱膝姿势。名为 tuck 的变量定义了状态,当 tuck 为 0 时,我们使用极点向前移动,但当它为 2 时,这意味着滑雪者处于 tuck 位置。我们迭代“forward_time”来计算角度不变的连续帧的数量。
现在,让我们讨论一下我们的移动步骤
def next_move(self, angle):
if self.tuck == 1:
self.tuck = 2
self.enter_tuck_state()
if angle >= -0.2 and angle <= 0.2:
if self.tuck != 2:
self.accelerate(angle)
if self.forward_time > 20:
self.tuck = 1
self.forward_time += 1
else:
self.steer(angle)
if self.tuck == 2:
self.tuck = 0
self.forward_time = 0
self.end_tuck_state()
self.stop()
if self.vel > 5:
self.stop()
self.vel -= 2
self.acc = 0
我会一步一步地教你。首先,我们检查抱膝状态,如果为零,我们就保持在雪杖状态(滑雪者正在使用雪杖)。接下来,我们检查变量“角度”,它是上面给出的函数参数,在感知步骤中计算。如果角度接近 0,说明我们在移动,没有探测到前方有任何障碍物。正如你所看到的,如果发生这种情况,我们只需追加到我们的前进时间。如果我们的角度仍然接近 0°,并且我们的前进时间大于 20°,我们就进入塔克状态“1”。当我们再次调用这个函数时,如果我们的抱膝状态为 1,我们就进入抱膝状态,我们的滑雪者开始以抱膝姿势移动。如果我们的角度不接近 0,这意味着我们前面有一些障碍,我们立即转向角度方向,然后我们检查抱膝状态,如果我们处于抱膝状态,我们离开该状态,重置前进时间,我们通过调用函数“停止”来减慢我们的滑雪者。减速过程是必要的,这样我们的滑雪者不会获得太多的速度。因为在高速度下控制滑雪者变得更加困难,特别是在像我们 1-5 秒这样的低 fps 下。最后,我们来到了最后一个 if 语句。正如你所记得的,我们用变量“vel”来跟踪速度。我们在每次函数调用时检查这个速度。如果它变得大于某个值(在我们的例子中是 5),我们减慢滑雪者的速度。
这是我们滑雪者的端到端决策步骤,效果非常好,这里有一个小演示。
Little Demo.
* *注意
对于转向,您将看到两个功能“快速转向”和正常“转向”。在游戏雪中,如果你按下左移位,然后转向,它会更快地向右或向左移动。我实际上已经考虑到了这一步。并且将转向角度分为 2 步,如果在[-15,-7],[7,15]之间,我使用快速转向,从[-7,0.5],[0.5,7]我使用正常转向。
def steer(self, angle):
if angle > 7:
self.go_faster_right(angle)
elif angle < -7:
self.go_faster_left(angle)
elif angle > 0.5:
self.go_right(angle)
elif angle < -0.5:
self.go_left(angle)
结论
在这篇文章中,我解释了我是如何设法从普通的游戏 SNOW 中为我的自主滑雪示例创建模拟器的。在这个项目中工作非常有趣,它有一些很大的挑战,比如不要开得太快,快速机动,探测前面的每个障碍等等。
这个项目是为实验和学习目的而设计的。
进一步的改进
- 通过在任何其他方法上使用 2 帧中的差异来检测真实速度。
- 探测到上升。
- 边跳边机动。
参考
[1]https://www.udacity.com/course/robotics-software-engineer-nd 209
【2】https://python programming . net/game-frames-open-cv-python-plays-GTA-v/
【3】http://www.snowthegame.com/
带 PyTorch 的自动卡车模拟器——微调和单发探测器
原文:https://towardsdatascience.com/autonomous-truck-simulator-with-pytorch-3695dfc05555?source=collection_archive---------32-----------------------
这是上一篇文章的延续,在上一篇文章中,我做了如何使用 fast.ai 构建自动卡车模拟器的完整演练,但最终这些方法可以在任何需要微调预训练模型或开发预测边界框和类的模型的情况下工作。
现在,我的目标是浏览训练和推理过程的一些更技术性的方面,并解释它们如何在 PyTorch 中实现的细节。也可以参考本 Github repo 中的代码库。
回想一下上一篇文章,这里有两个神经网络在工作。
- DNN 预测转向方向。
- 预测汽车、人等的边界框和类别的 DNN。
微调转向模型
这两个网络都是从一个预先训练好的 resnet34 网络开始,并针对适当的任务进行微调。
可从torchvision.models
获得预训练结果 34
**import** torchvision.models **as** modelsarch = models.resnet34(pretrained=**True**)
所有预训练的模型都已经在 1000 类 Imagenet 数据集上进行了预训练。
为了微调预训练的网络,我们基本上只是从一堆权重开始,这些权重已经嵌入了许多关于 Imagenet 数据集的信息。所以我们可以用两种方法之一。一种方法是通过设置requires_grad=**False**
来冻结所有早期层,然后只为最终层设置requires_grad=**True**
。另一种方法是只使用所有的权重作为初始化,并在新的训练数据上继续训练。
对于选项 1,我们冻结早期层并仅训练最终层,我们可以为所有层设置requires_grad=**False**
,然后移除并替换最后的层(无论何时将层分配给网络,它都会自动将requires_grad
属性设置为真)。
**class** Flatten(nn.Module):
**def** __init__(self):
super(Flatten, self).__init__()**def** forward(self, x):
x = x.view(x.size(0), -1)
**return** x**class** normalize(nn.Module):
**def** __init__(self):
super(normalize, self).__init__()**def** forward(self, x):
x = F.normalize(x, p=2, dim=1)
**return** xlayer_list = list(arch.children())[-2:]
arch = nn.Sequential(*****list(arch.children())[:-2])
arch.avgpool = nn.AdaptiveAvgPool2d(output_size=(1,1))
arch.fc = nn.Sequential(
Flatten(),
nn.Linear(in_features=layer_list[1].in_features,
out_features=3,
bias=**True**),
normalize()
)
arch = arch.to(device)
如果你观察 resnet34 的架构,你可以看到最后一个 conv 模块后面是一个AdaptiveAvgPool2d
和一个Linear
层。
(2): BasicBlock(
(conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=**False**)
(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=nn.Sequential, track_running_stats=**True**)
(relu): ReLU(inplace=**True**)
(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=**False**)
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=**True**)
)
)
(avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
(fc): Linear(in_features=512, out_features=1000, bias=**True**)
)
我们可以用nn.Sequential(*****list(arch.children())[:-2])
去掉最后两层,然后用arch.avgpool = nn.AdaptiveAvgPool2d(output_size=(1,1))
和另一个带有Flatten
、Linear
和normalize
层的nn.Sequential
把它们重新连接到末端。我们最终想要预测 3 个类别:左、右、直——所以我们的out_features
将是 3。
现在,我们将为方向模型创建数据集和数据加载器。由于我们的数据只是图像和类[左,右,直],我们可以只使用内置的 torch dataset 类,但我喜欢使用自定义类,因为我可以更容易地看到数据是如何提取的。
**class** DirectionsDataset(Dataset):
"""Directions dataset."""
**def** __init__(self, csv_file, root_dir, transform=None):
"""
Args:
csv_file (string): Path to the csv file with labels.
root_dir (string): Directory with all the images.
transform (callable, optional): Optional transform
"""
self.label = pd.read_csv(csv_file)
self.root_dir = root_dir
self.transform = transform **def** __len__(self):
**return** len(self.label) **def** __getitem__(self, idx):
img_name = os.path.join(self.root_dir,
self.label.iloc[idx, 0])
image = io.imread(img_name+'.jpg')
sample = image
label = self.label.iloc[idx, 1] if self.transform:
sample = self.transform(sample) **return** sample, label
我在 csv 文件中的图像名称没有扩展名,因此没有img_name+’.jpg’
。
tensor_dataset = DirectionsDataset(csv_file='data/labels_directions.csv',
root_dir='data/train3/',
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(
(0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]))dataloader = DataLoader(tensor_dataset, batch_size=16, shuffle=**True**)
所以我们准备开始训练模型。
**def** train_model(model, criterion, optimizer, scheduler,
dataloader, num_epochs=25):
since = time.time()
FT_losses = [] best_model_wts = copy.deepcopy(model.state_dict())
best_acc = 0.0
iters = 0 **for** epoch **in** range(num_epochs):
**print**('Epoch {}/{}'.format(epoch, num_epochs - 1))
**print**('-' * 10) scheduler.step()
model.train() # Set model to training mode running_loss = 0.0
running_corrects = 0 # Iterate over data.
**for** i, (inputs, labels) **in** enumerate(dataloader):
#set_trace()
inputs = inputs.to(device)
labels = labels.to(device) # zero the parameter gradients
optimizer.zero_grad() # forward
# track history if only in train
model.eval() # Set model to evaluate mode
**with** torch.no_grad():
outputs = model(inputs)
#set_trace()
_, preds = torch.max(outputs, 1)
outputs = model(inputs)
loss = criterion(outputs, labels) # backward + optimize only if in training phase
loss.backward()
optimizer.step() FT_losses.append(loss.item())
# statistics
running_loss += loss.item() * inputs.size(0)
running_corrects += torch.sum(preds == labels.data)
#set_trace()
iters += 1
if iters % 2 == 0:
**print**('Prev Loss: {:.4f} Prev Acc: {:.4f}'.format(
loss.item(), torch.sum(preds == labels.data) / inputs.size(0))) epoch_loss = running_loss / dataset_size
epoch_acc = running_corrects.double() / dataset_size print('Loss: {:.4f} Acc: {:.4f}'.format(
epoch_loss, epoch_acc)) # deep copy the model
if epoch_acc > best_acc:
best_acc = epoch_acc
best_model_wts = copy.deepcopy(model.state_dict()) time_elapsed = time.time() - since
**print**('Training complete in {:.0f}m {:.0f}s'.format(
time_elapsed // 60, time_elapsed % 60))
**print**('Best val Acc: {:4f}'.format(best_acc)) # load best model weights
model.load_state_dict(best_model_wts)
**return** model, FT_losses
在这个训练循环中,如果历元精度是迄今为止最好的,我们可以跟踪最佳模型权重。我们还可以跟踪每次迭代和每个时期的损失,并在结束时返回,以绘制并查看调试或演示的效果。
请记住,该模型在每次迭代时都被训练,如果您停止训练循环,它将保留那些权重,只需再次运行train_model()
命令,训练就可以再次继续。要从头开始,请返回并使用预训练的架构重新初始化权重。
criterion = nn.CrossEntropyLoss()
# Observe that all parameters are being optimized
optimizer_ft = optim.SGD(arch.parameters(), lr=1e-2, momentum=0.9)
# Decay LR by a factor of *gamma* every *step_size* epochs
exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)arch, FT_losses = train_model(arch, criterion, optimizer_ft, exp_lr_scheduler, dataloader, num_epochs=5)
微调边界框模型
sample data
同样,我们将使用预训练的 resnet34 架构。然而,这一次我们将不得不对它进行更多的编辑,以输出类预测和边界框值。此外,这是一个多类预测问题,因此可能有 1 个边界框,也可能有 15 个类。
我们将为该架构创建一个自定义 head ,其方式与我们替换方向模型中的层的方式类似。
**class** StdConv(nn.Module):
**def** __init__(self, nin, nout, stride=2, drop=0.1):
super().__init__()
self.conv = nn.Conv2d(nin, nout, 3, stride=stride, padding=1)
self.bn = nn.BatchNorm2d(nout)
self.drop = nn.Dropout(drop)
**def** forward(self, x):
**return** self.drop(self.bn(F.relu(self.conv(x))))
**def** flatten_conv(x,k):
bs,nf,gx,gy = x.size()
x = x.permute(0,2,3,1).contiguous()
**return** x.view(bs,-1,nf//k)**class** OutConv(nn.Module):
**def** __init__(self, k, nin, bias):
super().__init__()
self.k = k
self.oconv1 = nn.Conv2d(nin, (len(id2cat)+1)*k, 3, padding=1)
self.oconv2 = nn.Conv2d(nin, 4*k, 3, padding=1)
self.oconv1.bias.data.zero_().add_(bias)
**def** forward(self, x):
**return** [flatten_conv(self.oconv1(x), self.k),
flatten_conv(self.oconv2(x), self.k)]drop=0.4**class** SSD_MultiHead(nn.Module):
**def** __init__(self, k, bias):
super().__init__()
self.drop = nn.Dropout(drop)
self.sconv0 = StdConv(512,256, stride=1, drop=drop)
self.sconv1 = StdConv(256,256, drop=drop)
self.sconv2 = StdConv(256,256, drop=drop)
self.sconv3 = StdConv(256,256, drop=drop)
self.out0 = OutConv(k, 256, bias)
self.out1 = OutConv(k, 256, bias)
self.out2 = OutConv(k, 256, bias)
self.out3 = OutConv(k, 256, bias) **def** forward(self, x):
x = self.drop(F.relu(x))
x = self.sconv0(x)
x = self.sconv1(x)
o1c,o1l = self.out1(x)
x = self.sconv2(x)
o2c,o2l = self.out2(x)
x = self.sconv3(x)
o3c,o3l = self.out3(x)
**return** [torch.cat([o1c,o2c,o3c], dim=1),
torch.cat([o1l,o2l,o3l], dim=1)]
因此,现在我们希望将这个自定义头连接到 resnet34 架构,我们有一个方便的函数来完成这项工作。
**class** ConvnetBuilder():
**def** __init__(self, f, c, is_multi, is_reg, ps=**None**,
xtra_fc=**None**, xtra_cut=0,
custom_head=**None**,pretrained=**True**):
self.f,self.c,self.is_multi,self.is_reg,self.xtra_cut = f,c,is_multi,is_reg,xtra_cut
xtra_fc = [512]
ps = [0.25]*len(xtra_fc) + [0.5]
self.ps,self.xtra_fc = ps,xtra_fc cut,self.lr_cut = [8,6] # specific to resnet_34 arch
cut-=xtra_cut
layers = cut_model(f(pretrained), cut)
self.nf = num_features(layers)*2
self.top_model = nn.Sequential(*layers) n_fc = len(self.xtra_fc)+1
self.ps = [self.ps]*n_fc fc_layers = [custom_head]
self.n_fc = len(fc_layers)
self.fc_model = nn.Sequential(*fc_layers).to(device)
self.model = nn.Sequential(*(layers+fc_layers)).to(device)**def** cut_model(m, cut):
**return** list(m.children())[:cut] if cut else [m]**def** num_features(m):
c=children(m)
if len(c)==0: return None
for l in reversed(c):
if hasattr(l, 'num_features'): return l.num_features
res = num_features(l)
if res is not None: return res**def** children(m): **return** m **if** isinstance(m, (list, tuple)) **else** list(m.children())
使用这个ConvnetBuilder
类,我们可以将自定义头和 resnet34 架构结合起来。
k = len(anchor_scales)
head_reg4 = SSD_MultiHead(k, -4.)
f_model = models.resnet34
modelss = ConvnetBuilder(f_model, 0, 0, 0, custom_head=head_reg4)
k
是 9
我们现在可以通过modelss
上的model
属性访问模型。
损失函数必须能够接受分类(类)和连续值(边界框),并输出单个损失值。
**def** ssd_loss(pred,targ,print_it=**False**):
lcs,lls = 0.,0.
**for** b_c,b_bb,bbox,clas **in** zip(*pred,*targ):
loc_loss,clas_loss = ssd_1_loss(b_c,b_bb,bbox,clas,print_it)
lls += loc_loss
lcs += clas_loss
**if** print_it:
**print**(f'loc: {lls.data.item()}, clas: {lcs.data.item()}')
**return** lls+lcs**def** ssd_1_loss(b_c,b_bb,bbox,clas,print_it=**False**):
bbox,clas = get_y(bbox,clas)
a_ic = actn_to_bb(b_bb, anchors)
overlaps = jaccard(bbox.data, anchor_cnr.data)
gt_overlap,gt_idx = map_to_ground_truth(overlaps,print_it)
gt_clas = clas[gt_idx]
pos = gt_overlap > 0.4
pos_idx = torch.nonzero(pos)[:,0]
gt_clas[1-pos] = len(id2cat)
gt_bbox = bbox[gt_idx]
loc_loss = ((a_ic[pos_idx] - gt_bbox[pos_idx]).abs()).mean()
clas_loss = loss_f(b_c, gt_clas)
**return** loc_loss, clas_loss**def** one_hot_embedding(labels, num_classes):
**return** torch.eye(num_classes)[labels.data.long().cpu()]**class** BCE_Loss(nn.Module):
**def** __init__(self, num_classes):
super().__init__()
self.num_classes = num_classes**def** forward(self, pred, targ):
t = one_hot_embedding(targ, self.num_classes+1)
t = V(t[:,:-1].contiguous()).cpu()
x = pred[:,:-1]
w = self.get_weight(x,t)
**return** F.binary_cross_entropy_with_logits(x, t, w, size_average=False)/self.num_classes
**def** get_weight(self,x,t): **return** Noneloss_f = BCE_Loss(len(id2cat))**def** get_y(bbox,clas):
bbox = bbox.view(-1,4)/sz
bb_keep = ((bbox[:,2]-bbox[:,0])>0).nonzero()[:,0]
**return** bbox[bb_keep],clas[bb_keep]**def** actn_to_bb(actn, anchors):
actn_bbs = torch.tanh(actn)
actn_centers = (actn_bbs[:,:2]/2 * grid_sizes) + anchors[:,:2]
actn_hw = (actn_bbs[:,2:]/2+1) * anchors[:,2:]
**return** hw2corners(actn_centers, actn_hw)**def** intersect(box_a, box_b):
max_xy = torch.min(box_a[:, None, 2:], box_b[**None**, :, 2:])
min_xy = torch.max(box_a[:, None, :2], box_b[**None**, :, :2])
inter = torch.clamp((max_xy - min_xy), min=0)
**return** inter[:, :, 0] * inter[:, :, 1]**def** box_sz(b): **return** ((b[:, 2]-b[:, 0]) * (b[:, 3]-b[:, 1]))**def** jaccard(box_a, box_b):
inter = intersect(box_a, box_b)
union = box_sz(box_a).unsqueeze(1) + box_sz(box_b).unsqueeze(0) - inter
**return** inter / union
一旦设置了数据集和数据加载器,我们就可以在 bbox 模型的批处理输出中测试损失函数。
这里我们实际上需要一个定制的数据集类来处理这些数据类型。
**class** BboxDataset(Dataset):
"""Bbox dataset."""
**def** __init__(self, csv_file, root_dir, transform=**None**):
"""
Args:
csv_file (string): Path to csv file with bounding boxes.
root_dir (string): Directory with all the images.
transform (callable, optional): Optional transform.
"""
self.label = pd.read_csv(csv_file)
self.root_dir = root_dir
self.transform = transform
self.sz = 224 **def** __len__(self):
**return** len(self.label) **def** __getitem__(self, idx):
img_name = os.path.join(self.root_dir,
self.label.iloc[idx, 0])
image = io.imread(img_name)
sample = image
h, w = sample.shape[:2]; new_h, new_w = (224,224)
bb = np.array([float(x) **for** x **in** self.label.iloc[idx, 1].split(' ')], dtype=np.float32)
bb = np.reshape(bb, (int(bb.shape[0]/2),2))
bb = bb * [new_h / h, new_w / w]
bb = bb.flatten()
bb = T(np.concatenate((np.zeros((189*4) - len(bb)), bb), axis=None)) # 189 is 21 * 9 where 9 = k **if** self.transform:
sample = self.transform(sample) **return** sample, bb
mbb.csv
这个自定义的数据集类处理边界框,但是我们想要一个既处理类又处理边界框的数据集类。
bb_dataset = BboxDataset(csv_file='data/pascal/tmp/mbb.csv',
root_dir='data/pascal/VOCdevkit2/VOC2007/JPEGImages/',
transform=transforms.Compose([
transforms.ToPILImage(),
transforms.Resize((224,224)),
transforms.ToTensor(),
transforms.Normalize(
(0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]))bb_dataloader = DataLoader(bb_dataset, batch_size=16, shuffle=**True**)
在这里,我们可以连接两个数据集类,这样每个图像的类和边界框都会被返回。
**class** ConcatLblDataset(Dataset):
**def** __init__(self, ds, y2):
self.ds,self.y2 = ds,y2
self.sz = ds.sz
**def** __len__(self): **return** len(self.ds)
**def** __getitem__(self, i):
self.y2[i] = np.concatenate((np.zeros(189 - len(self.y2[i])), self.y2[i]), axis=None)
x,y = self.ds[i]
**return** (x, (y,self.y2[i]))trn_ds2 = ConcatLblDataset(bb_dataset, mcs)
其中mcs
是具有每个训练图像的类的数组的 numpy 数组。
PATH_pascal = Path('data/pascal')
trn_j = json.load((PATH_pascal / 'pascal_train2007.json').open())
cats = dict((o['id'], o['name']) **for** o **in** trn_j['categories'])mc = [[cats[p[1]] **for** p **in** trn_anno[o]] **for** o **in** trn_ids]
id2cat = list(cats.values())
cat2id = {v:k for k,v in enumerate(id2cat)}
mcs = np.array([np.array([cat2id[p] **for** p **in** o]) **for** o **in** mc])
现在我们可以测试我们的客户损失。
sz=224
x,y = **next**(**iter**(bb_dataloader2))batch = modelss.model(x)ssd_loss(batch, y, **True**)tensor([0.6254])
tensor([0.6821, 0.7257, 0.4922])
tensor([0.9563])
tensor([0.6522, 0.5276, 0.6226])
tensor([0.6811, 0.3338])
tensor([0.7008])
tensor([0.5316, 0.2926])
tensor([0.9422])
tensor([0.5487, 0.7187, 0.3620, 0.1578])
tensor([0.6546, 0.3753, 0.4231, 0.4663, 0.2125, 0.0729])
tensor([0.3756, 0.5085])
tensor([0.2304, 0.1390, 0.0853])
tensor([0.2484])
tensor([0.6419])
tensor([0.5954, 0.5375, 0.5552])
tensor([0.2383])
loc: 1.844399333000183, clas: 79.79206085205078
出动【1024】:
tensor(81.6365, grad_fn=<AddBackward0>)
现在来训练 ssd 模型。
beta1 = 0.5
optimizer = optim.Adam(modelss.model.parameters(), lr=1e-3, betas=(beta1, 0.99))
# Decay LR by a factor of *gamma* every *step_size* epochs
exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1)
我们可以像以前一样使用基本相同的train_model()
函数,但是这一次我们将一个边界框和类的列表传递给损失函数ssd_loss()
。
现在,我们已经在新的训练数据集上训练了我们的两个模型,我们准备在我们的卡车模拟器游戏中使用它们进行推理。
我鼓励您查看这个 Github repo 来了解完整的实现,您可以在其中训练模型、记录训练数据并在视频游戏上测试实现。
玩得开心!
AutoViz:自动化可视化的新工具
原文:https://towardsdatascience.com/autoviz-a-new-tool-for-automated-visualization-ec9c1744a6ad?source=collection_archive---------5-----------------------
© tadamichi — Shutterstock
数据科学家的任务通常是通过海量数据存储来提供可行的见解。然后对这些见解进行分析,以识别与商业智能甚至人类行为相关的模式。然而,使用所有类型的优化和聪明的算法来构建数据查询和机器学习管道可能是一回事。能够将艰巨的数据收集和建模的结果传达给不熟悉数据处理的同事完全是另一回事。这就是数据可视化的用武之地。
在他的书《好图表》中,Scott Berinato 感叹道:“一个好的可视化可以比任何其他形式的交流更有力地传达信息和想法的本质和潜在影响。”我们许多人都熟悉这样一句谚语:“一幅画胜过千言万语。“同样,在数据科学中,提供强有力的季节性模式、与成功营销活动相关的鲜明趋势或需要解决的显著异常值的有效可视化非常重要。小型数据集的可视化很容易且非常有益,但对于包含数百个(如果不是数千个)变量的大型数据集来说,这几乎是不可能的,在这种情况下,我们必须决定从数据集中突出显示哪些最佳洞察。除此之外,数据科学家必须经常使用非标准化的可视化库,这需要相当多的编码来获得具有适当影响的视觉效果。幸运的是,有一种替代方法可以使用这种暴力方法创建可视化。最近,在一次由 AutoViz 的设计者和作者所做的演示中,我了解到了一个名为 AutoViz 的库(AutoViz 是“自动化可视化”的缩写)。
AutoViz:简介
AutoViz 解决了前面提到的在执行数据可视化工作时可能出现的许多挑战。可以使用一行代码调用该工具,方法是向它提供一个 pandas dataframe 对象或一个要导入的原始 csv 文件。
如果观察次数多,AutoViz 会随机抽取一个样本;同样,如果变量的数量很大(这可以由您决定), AutoViz 可以找到最重要的特性,并只使用那些自动选择的特性来绘制有影响力的可视化效果。用户只需向 AutoViz 传递一个参数,就可以设置样本行数和要可视化的最大特征数。AutoViz 能够适应任何数量的不同数据环境,例如回归、分类甚至时间序列数据。它的输出速度也非常快。
AutoViz 可以通过 4 个简单的步骤实现:
- 使用“pip install autoviz”安装
- 用“从 autoviz 导入。AutoViz_Class 导入 AutoViz_Class "
- 实例化一个类“AV = AutoViz_Class()”
- 使用我们的数据集在下面的行中运行一个实验:
AutoViz 的优势
使用 AutoViz 进行可视化有很多好处。该库非常容易理解,可以使用 verbose=1 或 2 标志设置为高度详细模式。XGBoost 模型被重复用于确定最一致的特征集,每次通过使用随机的特征集来确定该特征集是重要的;然后,最突出的选定特征可用于指导未来的绘图和可视化。这听起来可能需要时间,但实际上,它很快就能完成。为了有效地做到这一点,AutoViz 将选择的变量分类为分类变量、数字变量、布尔变量、NLP 文本变量等等,以便理解如何最好地绘制它们。最后,使用内置的试探法,该工具将返回被认为具有最大影响的视觉效果。AutoViz 也非常系统化:它使用不同图表类型的所有选定变量,以便通过让图表自己说话来提供最佳见解。主观的领域知识往往会使经验丰富的数据科学家产生偏见,只选择少量图表来突出数据集的洞察力。AutoViz 对特征和图形的客观选择可以使用系统方法将数据团队引向最佳方法,并可以从项目一开始就极大地提高团队的生产力。
AutoViz 在实践中是什么样子的?当然,了解可视化库的唯一方法是观察它的一些情节。
数据集:网上购物者的意向
让我们从 Kaggle 获取在线购物者的意向数据集。这些数据包括一年中对不同在线购物者的大约 12,000 次观察。这是一项分类任务;我们试图根据功能集来预测在线购物者是真的会购买某件商品,还是只是“逛逛”。AutoViz 能够确认所有 17 个特征具有用于预测目标变量的有用信息。
下面所有的图表都是从 AutoViz 提供的数百张图表中挑选出来的。首先,有一个条形图,表示构成我们目标类的观察值的百分比。
(Image by author)
显而易见,我们正在处理数据中的类别不平衡,因为所需的类别值(“True”)仅占总数据集的 15%。接下来,我们可以看到,当 AutoViz 提供每个数值变量的 KDE 图时,单个变量可能需要一些“处理”或“转换”。
(Image by author)
从上面我们可以看到,所有四个变量都是右偏的,可能需要进行“对数转换”才能在线性模型中使用。这些图表将被证明在为以后的问题建模构建数据管道时非常有用。
可视化可以为不同变量之间的相互作用提供非常有力的证据。从下面的图表中可以看出,高水平的跳出率和退出率是收入流失的良好指标。他们表示,这些交易不会有收入。快速洞察,如果你知道如何阅读他们所说的“茶叶”!
(Image by author)
我们可以通过检查在线购物购买的标准化直方图以及它们与某个特殊日子或节日(如情人节或圣诞节)的距离,来更深入地了解电子商务购买的时间安排。
(Image by author)
活动高峰出现在某个特殊日子的前一周左右;尽管我们的班级不平衡,但大约 50%的游客会在这个时间窗口购买一件商品。这是一个关键的提示,当一个企业想要进行促销或瞄准潜在客户时。
数据集:Goodreads API
AutoViz 还能够提供使用 Goodreads API 收集的约 12,000 本书的信息可视化数据集。数据集包含图书的整体元数据,目标变量是图书的“平均评级”,这转化为回归分析。这一次,图书馆从数据集中删除了一些变量,如 ISBN 和书名,除了识别之外,它们不能提供太多的预测信息。有趣的是,它去掉了作者特征,这是我们通常认为与一本书的成功相关的东西。然而,由于在这个数据集中这是一个分类字符串变量,可能没有足够的证据来使用各种各样的作者姓名作为一个特征。
AutoViz 输出的关联热图表明,除了评级数量和书面评论数量之间的明显关系之外,大多数变量都不是高度相关的。有趣的是,页面数量和评论分数之间存在某种正相关关系。
(Image by author)
通过分析下面的散点图,可以提取更多关于书籍页数的信息:
(Image by author)
页数较多的书籍的平均评分往往在 4 分以上。然而,值得注意的是,篇幅较短的书籍(100-250 页)能够获得高达 5 分的平均评论分数。然而,这些可能代表异常值,明智的做法是进一步检查这些高评级的书籍,以确保它们与其他条目具有相同的评论分数。总的来说,这给人的印象是,出版商可能希望将 1250-1500 页作为一本书的目标页数,以取得良好的业绩。
这些信息可以与 Goodreads 上的一本书的页数正态分布的知识相结合,因为许多书有大约 400-500 页。
(Image by author)
然后,我们可以使用 AutoViz 输出的 violin 图,将一本书的页数分布与其他变量的分布进行比较。
(Image by author)
平均图书评级也是正态分布,尽管是左偏的。负面评级可能是分布中的重要异常值。还可以观察到,一本书的评级数量看起来非常右偏;一小部分图书可能会获得过多的总评分。
数据集:AirBnB 房源数据
然后,AutoViz 能够熟练地可视化 AirBnB 房源数据,这些数据由位于西班牙马德里的 2 万个房源数据集提供。该数据库是托管在 Kaggle 上的 AirBnB 数据的关系集合的一部分,包括每个列表的床位和浴室数量、评论和日历预订等属性。在这个实验中,目标变量是 AirBnB 房源的评论分数。每个条目都有许多相关的特性,乍一看令人生畏。幸运的是,AutoViz 发现了许多低信息量的变量,可以排除这些变量以减少数据的方差。一些被排除在外的特征令人惊讶,例如价格、平方英尺或邻近的房源。
自动生成的图非常有助于了解不同列表的某些方面。例如,你可能会惊讶地发现,绝大多数 AirBnB 的房东会在被联系后一小时内回复。
(Image by author)
主人提供他们的整个居住空间作为房源的一部分也很常见,尽管大约一半的时间房源可能只提供一个房间。然而,这是有道理的,一旦它被证实的事实是,大量的上市是一个公寓,而不是一个房子在马德里。
(Image by author)
(Image by author)
我们的目标变量的预测因素呢?对 AutoViz 生成的热图的分析表明,与某个列表的评论评级最相关的特征是每月收到的评论数量。
许多 AirBnB 评论可能是正面的,因此这可能意味着 AirBnB 会员最好接待尽可能多的客人,并鼓励他们留下评论,因为随着时间的推移,这可以最有效地提高房源的评论分数。
(Image by author)
有一个与房源审核分数负相关的特征,那就是 AirBnB 主机维护的房源数量。当列表从主持人那里得到更多个性化的关注,而不是作为不同住宿分配的一部分时,它们可能表现得更好。
结论
虽然这些只是 AutoViz 生成的图的一个示例,但不难看出自动化可视化是多么有帮助。在瞬间,该库能够生成高度信息化的图,并为数据科学家的建模或分析管道提供许多潜在的扩展途径。AutoViz 旨在整合到一个系统的迭代过程中。使用 AutoViz 可以有效地启动探索性数据分析(EDA );可以根据工具的分析选择要素,然后可以重复处理数据以实现自动可视化。一旦生成了强大的可视化效果,数据科学家现在就可以投入到建模中,或者用信息丰富的分析来交流数据。令人惊讶的是,自动化可视化选项如此稀少,作为一种客观和实用的工具,它有许多可以想象的用途,但 AutoViz 很好地完成了这个角色。现在让我们开始一些可视化!
你可以访问这个 jupyter 笔记本,里面包含了这些实验和其他实验。AutoViz 的 Github 库在这里可用,PyPi 页面在这里可用。非常感谢 AutoViz 的创建者和作者 Ram Seshadri。
原载于 2019 年 12 月 28 日https://danrothdatascience . github . io。
复仇者联盟,类似!
原文:https://towardsdatascience.com/avengers-resemble-3549d60ae015?source=collection_archive---------22-----------------------
通过面部识别找到理想的服装
计算机视觉更有趣和更专业的用途之一是面部检测和识别。人类非常擅长识别人脸,但最近的趋势是,我们已经能够训练计算机做足够接近的工作,以保证在更多的应用中使用它。面部扭曲、老化,并向各个方向摆姿势,这给如何在多张图像中匹配它们带来了重大挑战。深度学习的进步,如 FaceNet 研究,真正改变了游戏,使这些过程更容易执行,结果令人难以置信地准确。
Don’t look away from the Nozzle!
如果你害怕向计算机教授这样的技能意味着什么,我理解这种情绪。面部识别有许多积极的方面。举几个例子来说明它是如何非常有帮助的:在不断增长的数字世界中增加安全功能,帮助寻找失踪人员,帮助盲人在世界中导航,以及(潜在的)帮助建立更好的工具来打击犯罪。然而,隐私仍然是这项技术的主要关注点。作为一个社会,对于我们的形象被拍摄并用于某种分类目的,我们有什么样的舒适度?为了安全起见,在个人设备上可能感觉还可以,但是当你在外面的世界中得到有针对性的广告呢?这确实是一件棘手的事情,但是当我们继续研究它的时候,记住这一点很重要:
“权力越大,责任越大”
u̶n̶c̶l̶e̶̶b̶e̶n̶̶f̶r̶o̶m̶̶s̶p̶i̶d̶e̶r̶-̶m̶a̶n̶.我,谈论面部识别
看起来像个英雄
这让我想到了一个使用面部识别的快速项目,希望能展示这项技术的创造性应用。
问题:快到万圣节了!你在一家服装公司工作,他们想为顾客提供一种有趣的互动方式,让他们找到最适合自己的服装。如果你使用面部识别来找到他们最像哪个演员,并根据这种匹配推荐服装,会怎么样?听起来像个计划。今年是复仇者联盟电影的重要一年,所以让我们用这些演员和他们相关的角色来创造一个复仇者联盟!
有一些很好的工具可以用于人脸检测和识别(比如 OpenCV ),但是我将使用 Python 库 face_recognition 进行演示。这是一个真正快速准确的包,使用 dlib 的人脸识别构建,取得了一些令人印象深刻的结果(在“野生标签人脸”基准上的准确率为 99.38%)。检测图像中的人脸(查找并返回边界框位置)并获取人脸编码(人脸的矢量表示)就像三行代码一样简单:
import face_recognitionloaded_image = face_recognition.load_image_file('young_rdj.jpg')
face_location = face_recognition.face_locations(loaded_image)
face_encoding = face_recognition.face_encodings(loaded_image)[0]
厉害!只用了几行代码,我们就找到了这张脸,并将其转换成一个数字向量表示,我们可以用它来与其他图像进行比较。虽然大多数面部识别都在寻找真正的匹配(例如照片应用程序标记一张脸,并在所有其他图像中找到那个人,你的手机匹配用户的脸以允许访问),我正在做的是寻找最好的“足够近”。以下是我为让我的复仇者联盟更相似而创建的一般工作流程和功能:
- 下载复仇者联盟电影中每个演员的照片。我坚持以大家伙为主,甚至加入了几个 x 战警,因为漫画经典中有些也是复仇者。没有花哨的代码,只是大量的手动谷歌搜索和寻找良好的干净的图像。
- 为图像编码过程创建一个函数,这样我就可以一次加载所有图像,并使用 list comprehension 来执行任务:
def image_to_encodings(file):
"""Return the face encodings from an image"""
load_image = face_recognition.load_image_file(file)
return face_recognition.face_encodings(load_image)[0]
3.通过我的函数运行所有图像,并创建一个新的字典,该字典包含角色名称及其带有面部编码的数组:
# Glob makes it easy to capture all jpgs filenames into a list
avengers_cast_files = glob.glob('avengers/*.jpg')# Getting character name from the file name
avengers_cast_names = [re.sub('.jpg|avengers/', '', image)
for image in avengers_cast_files]# Getting encodings
avengers_cast_encodings = [image_to_encodings(image)
for image in avengers_cast_files]# Creating dictionary with these new details
avengers_dictionary = {name: encoding for name, encoding
in zip(avengers_cast_names,
avengers_cast_encodings)}
4.酸洗我的编码字典。这使得我以后可以轻松打开它,而不必对我的已知面孔重新运行 face_recognition:
outfile = open('avengers_features.pkl','wb')
pickle.dump(avengers_dictionary,outfile)
outfile.close()
5.创建一个函数,根据已知的编码返回图像的最佳匹配:
def top_match(known_encodings, known_names, new_image_embed):
"""With list of known image names/encodings,
return closest match"""
distances = face_recognition.face_distance(known_encodings,
new_image_embed)
top = np.argmin(distances)
return known_names[top]
6.测试添加新图像并查看最接近的匹配:
me = image_to_encodings('me.jpg')
top_match(list(avengers_dictionary.values()),
list(avengers_dictionary.keys()),
me)
鹰眼!我要了。
如果你想亲自尝试,你可以在 GitHub 上查看我的代码。它目前可以在终端上运行,带有一些有趣 ASCII 装饰:
这可能是最好的 web 应用程序,我可能会尝试进一步构建,但有趣的是看到这是如何工作的原则。尽情享受吧!
为普通用户设计的危险
原文:https://towardsdatascience.com/average-user-fallacy-131a5ea90753?source=collection_archive---------22-----------------------
Luke Tucker
两个理论——一个思想实验——数字模拟——高斯相关说 whaaa——一个尺寸永远不会适合所有人——印度妈妈,最好的优化器
我最近遇到了两个概率理论,一个来自一个 T2 的朋友,另一个来自一个精彩的 T4 播客。在这篇文章中,我试图用《Think X》系列丛书的作者艾伦·唐尼的一个观点来解释这两种理论。我强烈推荐的 Think X 系列的前提是,如果你知道如何编程,你可以用这种技能来学习其他主题。这两种理论有一个共同点。
Image Source
让我们从一个思维实验开始。你是一家领先零售商新冬装系列的首席设计师。你有来自全国几家分店的现有和潜在顾客的身体尺寸数据。身体尺寸包括身高、体重、臀围、膝宽等。你的任务是提出适合大多数人的最佳标准设计。在验证所有主体尺寸大致遵循正态分布后,您得出结论,最好的方法是使用所有这些尺寸的平均值来达到您的最佳设计。
让我们来表示,
S1——距离平均身高在±K 标准差范围内的所有人的集合,S2——距离平均体重在±K 标准差范围内的所有人的集合…Sn。—距离实体 n 的平均值±K STD 范围内的所有人的集合。您明白了。
以上几组代表了接近平均水平的人,他们可以穿着为普通人设计的服装而不会引起太多骚动。谬误的根源在于这样一个事实,当你增加维度的时候,论点就分崩离析了。即使你通过为普通用户设计来最大限度地增加穿你设计的人,当你从多个角度看时,接近平均水平的人的数量很快接近零。当考虑到维数灾难时,一般用户谬误虽然有趣,但事后看来却很幼稚。
空谈不值钱。给我看看代码。莱纳斯·托沃兹。
尽管理论很吸引人,但它们几乎没有保留价值。为了说明这一点,我将尝试唐尼的方法,通过代码和模拟来理解它。
在上面的例子中,普通用户谬论没有解决的一个关键问题是维度之间的相关性。例如,身高和体重之间有很强的相关性。一个人越高,他认为所有的事情都是平等的。同样,人越高,膝盖越长。
我们假设平均身高 175 cm,平均体重 190 lbs。
mean = np.array([175, 190])
samples = 10000
corr_factor = 0.3
corr_matrix = np.array([[1.0, corr_factor],
[corr_factor, 1.0]])
假设它们与相关因子 0.3 相关,让我们尝试模拟来自高斯分布的数据。为了模拟多元相关数据,我们执行以下操作:
Correlated Data = Mean + Covariance * Uncorrelated Gaussian Data.
我们需要协方差来从不相关数据生成相关数据。协方差是相关矩阵的平方根。我们可以使用 Cholesky 的分解来得到它,虽然方法并不精确。
chol = np.linalg.cholesky(corr_matrix)
通过取平方从协方差矩阵中恢复相关矩阵,确保 Cholesky 分解有效。
assert (
~np.isclose(chol @ np.transpose(chol), corr_matrix)
).sum() == 0, "Cholesky not working"
从不相关数据生成相关数据,
uncorr_data = np.random.randn(2, samples)print(f"Correlation of randomly generated data - \n{np.corrcoef(uncorr_data)}")corr_data = np.reshape(mean, [2, 1]) + chol @ uncorr_dataprint(f"Correlation of correlated data - \n{np.corrcoef(corr_data)}")>>> Correlation of randomly generated data -
[[ 1\. -0.02200527]
[-0.02200527 1\. ]]
Correlation of correlated data -
[[1\. 0.28526392]
[0.28526392 1\. ]]
正如你所看到的,得到的相关性并不完全是 0.3。这取决于生成的样品组和样品大小。
A joint plot of Height vs Weight
体重和身高的平均值不同,但标准差相同。循环遍历数据集,找到距离平均值 K=1 个标准差范围内的点。
k = 1
normal_height = (corr_data[0] > mean[0] - k) & (
corr_data[0] < mean[0] + k
)
normal_weight = (corr_data[1] > mean[1] - k) & (
corr_data[1] < mean[1] + k
)
normal_height_weight = normal_height & normal_weight
normal_height
是一个二元向量,表示与平均身高的 K 个标准偏差内的所有值,对于normal_weight
也是如此。normal_height_weight
是这两种情况的交集。
这为我们的第二个理论高斯相关不等式提供了一个很好的切入点。在转换话题之前,请记住,我们正试图说明增加维度是如何减少接近平均水平的人数的。
Lucy Reading-Ikkanda/Quanta Magazine
形象乍一看很混乱,名字也很拗口。让我们试着分解它。让我们从乘法的基本规则开始,
P(A ∩ B) = P(A) * P(B),给定事件,是独立的。
但是在我们的例子中,我们知道 A 和 B 不是独立的,它们是相关的,由相关矩阵给出。
P(A ∩ B) = P(A) * P(B|A)。
高斯相关不等式表明,
P(A ∩ B) >= P(A) * P(B)
在我们的方案中,用 S1 和 S2 代替 A 和 B,我们知道 P(S1)和 P(S2) ~ 0.68,因为在高斯随机变量中,68%的数据落在钟形曲线均值的±1 标准偏差内
将 P(S1 ∩ S2)和 P(S1) * P(S2)相对于各种相关值绘图清楚地表明,当存在最小相关时,它们是相同的,但是当存在强相关时,P(S1 ∩ S2)稳定地开始增加,而 P(S1) * P(S2)保持相当恒定。
现在回到平均用户谬误,我们知道 P(S1 ∩ S2)小于 P(S1),这意味着用户下降的概率从平均值±K STD 下降,因为你增加维度,尽管维度之间的相关性。
让我们模拟 n 维的相关数据,看看维数灾难对平均用户谬误的影响。我们将随机化维度之间的相关因子。
corr_values = np.random.random(((ndim ** 2 - ndim) // 2) - 1)
corr_matrix = np.identity(ndim)for row in range(0, ndim):
for col in range(0, ndim):
if row != col:
corr_matrix[row][col] = corr_values[row + col - 1]
从上图可以明显看出,不考虑相关性,随着维度的增加,出现在跨维度均值附近的概率迅速降低,趋近于零。
你可以在这个笔记本里找到完整的代码。
一刀切:
对于那些宽容的读者来说,让我们来看看一个为普通用户设计的可怕错误的真实例子。
99pi—
在第二次世界大战期间,美国空军迅速扩张,伴随着性能下降和一连串的死亡,甚至在训练期间。多年来,空军的高死亡率一直是个谜,但在归咎于飞行员和他们的训练计划后,军方终于意识到驾驶舱本身是罪魁祸首,它不适合大多数飞行员。起初,他们认为这个数字太小了,而且自 20 世纪 20 年代以来,男性的平均年龄有所增长,所以在 1950 年,他们请俄亥俄州莱特空军基地的研究人员计算新的平均值。
其中一名研究人员是年轻的哈佛毕业生吉尔伯特·s·丹尼尔斯。在他的研究中,测量了数千名飞行员的 10 个关键身体维度,丹尼尔斯意识到,他测量的飞行员没有一个在所有 10 个维度上都是平均水平。一个都没有。当他只看三维时,平均只有不到百分之五。丹尼尔斯意识到,为普通飞行员设计的东西,实际上并不适合任何人。
重温我们开始时的思想实验,作为一名首席设计师,现在知道了一般用户的谬误,你应该如何着手优化你的设计?在一个不受资源限制的理想世界中,解决方案应该是为每个人量身定制一套测量方法。但是现实世界从来没有那么简单。你总是被约束所束缚,需要取得平衡。一方面,你目睹了为普通人设计的恐怖,另一方面,定制适合每个人是不可能的。
印度妈妈,最佳优化师:
BeingIndian
普通用户谬误并非无处不在。例如,如果您正在设计一把椅子、一个汽车座椅或一个现代化的驾驶舱,您并不局限于固定的尺寸。您可以使用杠杆和其他机构来让众多的身体尺寸舒适地接触到它们。这些动态系统让用户可以在连续的设计空间中无缝导航。但是有些设计本质上受制于普通用户的谬误。这些系统内部具有一定的刚性,使其无法进行动态调整。
裙子就是一个完美的例子。一旦购买,大小保持不变。因此,服装制造商基于利润最大化的动机,试图接触尽可能多的人,同时仍然减少他们必须生产的不同尺寸的品种。这就产生了以 S、M、L、XL 等不同的离散时间间隔制作衣服的系统,从而解决了普通用户的谬误问题。让我们考虑一下最糟糕的情况,裙子开始缩水,你开始增重,测试你裙子的完整性。这似乎是一个不可能解决的问题,但对一个印度妈妈来说不是。她如何解决这个难题相当巧妙。她单枪匹马地决定你将得到一个比你目前的大小,以支持她的格言,
“你从来不为你现在的自己买,而是为你将成长为的那个人买”。
然后,她骄傲地从您身边走过,完全知道她得到了您想要的,同时优化了产品的寿命,从而降低了长期成本。如果这不是一个完美的优化,我不知道是什么。
平均值毫无意义*
原文:https://towardsdatascience.com/averages-are-meaningless-7dfb9a7ef10c?source=collection_archive---------17-----------------------
但是,并不总是这样。我们来探索一下在哪里。
Just like this picture? Source
"平均每 14 分钟就有一个人在 eHarmony 上找到爱情."
去威斯敏斯特的地铁上的广告是这么说的。
是不是说我会在 14 分钟内在 eHarmony 上找到爱情?不完全是。
也许其他人会?我不在乎。
几年前,我试着学游泳。
我在网上看到,“平均下来,学游泳要花 20 个小时。”好吧,还不算太糟。而且,我高于平均水平。
在游泳池里游手好闲了 20 个小时,我根本没学会游泳。不过,我确实找到了一个让我的头在水下保持 3 秒钟的方法。这就是进步,对吧?
现在怎么办?我不是高于平均水平吗?平均时间不是 20 小时吗?是不是低于平均水平…不好?
平均是没有意义的。
起源
哪一个数据点可以取代我集合中的所有数据点?
这个问题催生了平均值。平均值是众多答案中的一个。
它始于天文学。每个天文学家都想算出行星和太阳之间的距离。每个人都尝试了自己的方法,也重复了别人的方法。最后,他们进行了大量的测量。怎么搞清楚哪个是正确的?他们如何将误差降至最低?
答案是取所有值的平均值。他们相信正误差会抵消负误差。
他们考虑的是正态分布。事实上,正态分布在这里是有意义的。大多数有能力的天文学家会进行类似的测量——有时仪器的误差会使结果偏向一边或另一边——但并不总是如此。
Bell Curve = Normal Distribution. Source
此后不久,平均值的第二个用例出现了:估计[1]。你不用数灌木丛中所有的浆果,而是取一部分灌木。一个看起来普通的,代表所有其他部分的。数一数这一区的所有浆果,乘以这一区的数目,你就得到灌木丛中的浆果总数。食物计划完成。一般来说,没有人会挨饿。
另一个例子是战争。将军们是如何计算出他们必须击败的敌人数量的?站在战场上,你不会想花时间去数每一个敌军士兵。你应该估计他们的数量。怎么会?使用平均值——代表值。数一个有代表性的连队的士兵,乘以连队的数量,你就得到敌军的数量。
这些平均数的概念开始传播。
- 为了精确计算测量值
- 用于估算
在这两个用例中,我们都使用正态分布。高于平均水平的会被低于平均水平的抵消。这给了我们一个很好的代表值。
指数运算
随着平均值开始与估计和测量一起工作,使用平均值的人开始看到好处。他们会赢得战争,在食物规划上更加成功,在科学上取得飞跃。
随着时间的推移,我们开始相信平均数在任何地方都适用。
但是,我们已经进入了复利时代。正常不是标准。一旦我们创造了杠杆,我们就把正态分布向一边倾斜。我们创造了幂律分布。
Source — worth going through the slides
我们的大脑仍然按照正态分布来思考。当谈到统计数据时,我们没有考虑到分布。事实上,这就是为什么 80/20 原则如此具有革命性。它提醒每个人,正态分布不再是常态。
保持正态分布的是我们仍然没有杠杆的领域。我们还不知道如何让人活 1000 年。
平均值是从分布中推导出来的。我们隐含地假设一切都是正态分布。【2】
接下来,探究指数运算如何改变平均值是有意义的。
在现代社会,我认为我们谈论平均值主要有两种情况。
- 当我们把平均值投射到世界上时
- 当我们把平均值投射到自己身上时
注意:在我使用正态分布的地方,我指的是近似正态。它的特点是中间肥胖,边缘逐渐变细。真实世界的数据集很少完全遵循正态分布。幂律分布也是如此。
预测世界的平均值
像我们的祖先一样,在这种情况下,你要找出一个有代表性的值。你想了解的世界上某个指标的代表值。
然而,那个人并不是所有人——所以你总是会错过一些东西。(地图不是领土)
问这样的问题,一般人长什么样?一般人有多重?有道理。
人口长相和体重呈正态分布——所以你的平均值确实是一个代表值。大约一半的人低于平均水平,一半高于平均水平。所以,平均值给了你一个合理的衡量标准。(我们将在下面进一步探讨这一点)
另一方面,一旦我们进入幂律分布领域,我们的平均值就不再有意义。
平均值是所有数据点的线性组合,对于幂分布来说是没有意义的。你的数据太偏向一边了,80%的人都低于平均水平。如果这听起来很荒谬,那就是我们所看到的和我们认为它的意思有分歧的地方。“平均”是指 50%的划分?这是中间值。幸运的是,在正态分布中,中位数和平均数是相同的。
所有这些无意义的平均值出现在哪里?
这里只是几个例子。
每位顾客的平均收入。
图书销售。
平均家庭收入。
比方说,作为一项商业决策,你正在开始写一本新书。你想赚——你会发现书籍平均能赚 20,000 美元。听起来很棒,对吧?但 90%的作者收入低于平均水平。如果这让你感到愤怒、心烦意乱或委屈,你并不孤单。现在你知道这怎么可能了。图书销售也遵循幂律分布。
无意义的平均值— 1。你— 0。
比方说,你正在 A/B 测试你的网站产生的收入。在版本 A 中,网站是蓝色的。在版本 B 中,网站是绿色的。你的评判标准——A/B 测试期的平均收入。一个大客户来买走了蓝色版本的几乎所有东西——一个蓝绿色色盲的客户。你收到一个假信号:“蓝色比绿色好用多了!”真的吗?你的平均收入是这么说的。
所以,你的指标被打破了。(你应该跟踪转化率,而不是每次转化的平均金额。)
对某人进行平均预测
我们的祖先所没有的是足够的数据来将平均值应用到他们自己身上。[4]
我们使用平均数的另一种方式是当我们把人口平均数投射到某人身上时——我们自己、我们的朋友或我们的玩具。
好的一面是——人类处于正态分布,所以平均值具有代表性。
坏的一面是——不是每个人都是普通人。
理解这一点的最好方法是通过一个例子。
平均来说,人类需要大约 66 天来建立一个新习惯。这是否意味着你在 66 天后就不再尝试养成习惯了?抱歉,没有。
平均值是总体的一个基准——供外部人员判断他们的产品。例如,如果我正在开发一个培养习惯的应用程序,我会把它设计在 66 天左右。这是因为大多数人需要大约 66 天来养成一个习惯(正态分布)。
另一方面,你在人群中。平均数对你来说毫无意义。它告诉你的是,如果你是一群正在养成习惯的人(你不是),那么大多数人会花大约 66 天来养成一个习惯(你不在乎)[3]。对你养成习惯没有帮助,是吗?当然,它设定了一些期望。你可能需要 66 天。但除非你尝试过,否则你不会知道。
你只是一个数据点,而不是统计数据。你可能是一个局外人,也可能是一个普通人——没关系,你需要自己去发现。因此,平均值(当投射到某人身上时)是没有意义的。
平均数可能扰乱我们思维的另一个地方是刻板印象。
我认为对于一个社区的普通人来说,刻板印象是真实的。但是就像我们看到的,普通人不是一个特定的人。如果你信誓旦旦地用刻板印象来判断一个人,你就陷入了平均谬误。[5]
一般来说,犹太人善于理财。那是刻板印象。它告诉你关于你面前的犹太人的任何事情了吗?我不这么认为。[6]弄清楚这件事的唯一方法是查看他们的银行对账单。
这种预测是分布不可知的。无论分布如何,用平均值来判断一个人是错误的。这种分布决定了错误会变得多严重。
这是风险投资游戏开始的地方。当基础分布为幂律时,风险和报酬较高。你听过风投公司和公司谈平均水平吗?一般的公司都死了。他们在游戏中寻找赢家——找到一家普通的公司是不够的。
分布
我们已经建立了平均值与分布的紧密耦合。
最后一个问题是,如何计算分布?
我认为有两种方法可以做到这一点,而不用成为一个统计奇才。
我们怎么知道重量是正态分布的?
有人说是直觉。你从没见过 200 公斤以上的人。甚至世界纪录也只有 500 公斤。那是一辆小汽车。另一方面,没有人重 1 公斤。大多数人都很健康或轻微肥胖。有些很瘦,有些很大——但它们都互相平衡。
是什么产生了这种直觉?数据。在我看来,直觉就是数据。发展直觉需要时间?那只是数据收集。你一生都在与人交往——这就是你一直在收集的所有数据。当然,你可能不知道他们的体重——但是你收集的数据非常丰富,你可以推算出他们的体重。
最后,钟形曲线对你来说似乎是合理的。在统计学中,这被称为抽样。你正在收集一点数据来计算整个人口。
直觉是数据
它有它的陷阱。如果您收集的所有数据都只针对您所在的地区,该怎么办?如果你见过的每个人都很健康,体重 70 公斤,会怎么样?
在这种情况下,你就成了局外人。你不知道发生了什么。你不能靠直觉去搞清楚分布。
这就是真实数据的来源。你寻找从世界各地收集这些数据的人。然后你画出来。可视化您的数据是一种简单的方法来找出趋势,并在幂或正态分布之间进行选择。可能都不是。
这两种方法交织在一起真美。一旦你开始将直觉视为数据,它们真的会融合。前者依靠个人收集的数据,后者依靠他人收集的数据。
走向统计魔法的是分布测试。这些要严谨精确得多。我在这里找到了一个简短的介绍。
结论
脱离上下文的平均值是没有意义的。就像“那是她说的”笑话一样。
这在早期是可行的,因为我们只有一个上下文——正态分布。不再是了。
所以,不要陷入平均谬误。你面前的这个人不是刻板印象。他们可能会遵从,但你必须自己去发现。
并且,不要在没有提到分布的情况下谈论平均值。显性比隐性好。如果不是正态分布,平均的意义就变了[7]。你从 50%的人低于平均水平到 80%的人低于平均水平。
至于我?这只是拼图的另一块,因为我试图了解这个世界。加入我吧。
[1]或者在天文学之前,我们不确定。记录不是完整的。
[2]显性比隐性好。
[3]正态分布的均值、中值和众数是相同的——这给了我们期望的平均值的直观感觉。
[4]一个相反的论点是,他们有自己的部落和对其他部落的看法(这很糟糕)。在这个意义上,和现代非常相似。
[5]我一直想给一种认知偏差命名。是的,我正在对这些名字进行计算。
[6]它可能会告诉你,他们比其他非犹太人更善于理财——但这于事无补。另一方面,如果你试图选择优秀的基金经理,你会发现更多的基金经理是犹太人。假设刻板印象是真的。
[7]它是如何计算的,或者计算是什么,并没有改变。它所代表的意义发生了变化。
原载于 2019 年 4 月 7 日【neilkakkar.com。
避免数据泄露—在处理之前拆分您的数据
原文:https://towardsdatascience.com/avoid-data-leakage-split-your-data-before-processing-a7f172632b00?source=collection_archive---------23-----------------------
生产中模型失败的一个潜在原因
Kai Kai @ River Safari Singapore
经验法则:在对数据进行任何处理之前,将数据集分成训练集和测试集。否则可能会有数据泄漏,使模型评估过于乐观。
你们中的一些人可能有这样的经历:
- 您的模型在您的本地测试集上得分很高,但在 Kaggle 排行榜上表现不佳
- 您的模型在概念验证期间正常工作,但在生产环境中会急剧下降
这些可能是由于数据泄露造成的。
什么是数据泄露?
数据泄漏是指训练数据集和测试数据集之间意外共享信息。这种信息共享会给模型一个关于测试数据集的“提示”,并生成看似最佳的评估分数。然而,由于模型过度拟合测试数据,它无法准确预测未来的未知数据集,即 Kaggle 测试数据或生产实况数据。
数据泄露的一个常见原因是由于列车数据处理后的测试分割。
示例:处理后由于分割导致的数据泄漏
假设我们有以下数据集,并希望使用列 1 和列 2 来预测目标。
按顺序执行以下步骤:
Example: raw dataset for classification
Example: train test split after processing
- 将第 1 列中的 Y 和 N 替换为其各自的目标平均值。
- 标签根据词汇顺序对列 2 进行编码。
- 分割数据集。前 7 行用于训练,后 3 行用于测试。
- 使用训练数据训练模型,并根据测试数据进行验证。
发生数据泄露!
对于步骤 1,Y 的值是用 4 / 6 计算的,这表明数据集中有 6 个 Y,其中 4 个有正目标。由于数据在处理后被拆分,这些信息会在训练数据集和测试数据集之间意外共享。在第 4 步中,模型从 4 个 y 开始训练,并以某种方式“期望”测试数据中的两个 y,其中一个具有正目标。这会导致对模型性能的预期过于乐观。
类似地,对于步骤 2,第 5 行的字母‘e’被编码为 5,因为它知道完整的数据集具有’‘a’,‘b’,‘c’和‘d’。这些信息也在训练和测试数据之间泄露。
简单的解决方案:在处理前拆分
上面提到的问题有非常大的负面影响,但是解决方案很简单——在处理之前分割。让我们用相同的例子,但不同的步骤:
Example: train test split before processing
Example: transform train and test data with same encoders
- 分割数据集。前 7 行用于训练,后 3 行用于测试。
- 对于训练数据:将第 1 列中的 Y 和 N 替换为它们各自的目标平均值。标签根据词汇顺序对列 2 进行编码。保存这些编码器。
- 对于测试数据:用相同的编码器转换数据。
- 使用训练数据训练模型,并根据测试数据进行验证。
请注意,Y 被替换为 0.75,因为训练数据中有 4 个 Y,其中 3 个有正目标。字母‘e’编码为 4,因为训练数据中没有‘c’。测试数据被认为是前所未见的,并遵循类似的模式。因此,它们用来自训练数据的相同编码器进行变换。
首先拆分数据有两个主要好处:
- 降低数据泄露的风险。
- 未来看不见的数据将以与测试数据完全相同的方式处理,从而确保模型性能的一致性。
感谢阅读!
避免这些致命的建模错误,这些错误可能会让你失去职业生涯
原文:https://towardsdatascience.com/avoid-these-deadly-modeling-mistakes-that-may-cost-you-a-career-b9b686d89f2c?source=collection_archive---------10-----------------------
我喜欢看到数据科学家使用高级包,创建令人眼花缭乱的展品,并试验不同的算法。数据科学家可以让电脑燃烧一整天。一件很酷的 t 恤、一杯咖啡和一台笔记本电脑——这就是他或她所需要的一切。虽然他们的名字听起来很疯狂,但一些数据科学家新手不断犯常见的错误——我称之为致命错误。这些基本的错误会损害数据科学家的可信度,并可能让一个有前途的数据科学职业生涯付出代价。我在这篇文章中的目标很简单:我希望你在读完这篇文章后,永远不要犯这种类型的错误。Python 和 R 代码都有提供。
我写过关于各种数据科学主题的文章。为了方便使用,你可以将我的总结文章“数据人学习之路——培养你的技能,推动你的职业发展”加入书签,这篇文章列出了所有文章的链接。
(1)为什么“日期时间”变量是最重要的变量?
请小心 yymmdd:hhmmss 格式的任何 DateTime 字段。您不能在任何基于树的方法中使用此变量。如图所示,这个变量出现在变量重要性图表的顶部。原因是这个字段几乎成为每个记录的唯一标识符。这就好像您在决策树中使用了“id”字段。我确信你需要导出年、月、日、工作日等等。从这个领域。记住,特征工程是捕捉可重复的模式,比如一年中的月或周,来预测未来。在某些模型中,您可能会使用“年份”作为变量来解释过去的任何特殊波动。但是您永远不会使用原始日期时间字段作为预测值。
(2)小心变量中的‘0’、‘99’或‘999’
它们通常是缺失值,被系统设置为极值。在参数回归中,不要盲目地将它们用作数值。“-99”和“-999”可能由不同的系统设置。它们携带一些独特的信息,不会随机丢失。这个普遍存在的问题不能由诸如库(mice)这样的软件盲目处理。
(3)连续变量有' NA ',' 0 ','-99 '或'-999 '怎么办?
我建议您将连续变量绑定,将特殊值“0”、“99”和“NA”作为它们的类别(可能还有其他方法)。首先,你可以得到变量的切割点:
R 代码:
分位数看起来像这样:
然后使用上述切割点来绑定变量,以创建一个新的变量。下面的代码也保留了特殊值。我使用函数cut()
将连续变量切割成分类变量。我使用case_when()
来分配'-999 '、'-99 '、' 0 '和' NoData '(注意这种语言是 R 语言,但是这个概念也适用于其他语言。)
Python 代码:
pd.qcut()
将数值离散化成大小相等的桶。缺失数据怎么办?所以我用add_categories()
添加了一个新的类别。记住pd.qcut()
产生的数据类型是分类的,而不是字符串。
(4)你强制一个分类变量成为基数变量
基数变量是数值变量,其值是有序的。非基数变量,通常是分类变量,是其值不能排序的变量。例如,变量性别“男性”和“女性”的值不能排序。
假设您需要将一个分类变量(比如性别)转换为一个数值变量来运行回归。假设您将 1 分配给“男性”,将 2 分配给“女性”。您错误地将分类变量强制为基数变量!
下面是具有值“h5”、“android”、“api”和“ios”的分类“AP006”。我打印出每个值和前 20 条记录的计数统计数据(第一条记录是“android”,第二条是“h5”,依此类推。)值“h5”没有理由高于或低于其他值,即,没有基数性质。如果如下创建一个新变量“newvar ”,品牌“android”的价值就荒谬地比“h5”的价值高两倍。这个错误应该避免。
R 代码:
Python 代码:
你需要做的是使用pd.get_dummies(train['AP006'],dummy_na=True)
创建虚拟变量。有关更多处理方法,请参见“将分类变量编码为数字的数据科学家工具包”。
(5)预测中的新分类值
假设您将训练好的模型应用于测试数据,并得到一条错误消息。你意识到测试数据中的一个变量比训练数据中的一个变量有更多的类别。下面我用一个例子来说明。测试数据中的变量“Education”有一个不在训练数据中的额外类别“Ph.D .”。这个错误导致您的预测停止,并且该观察没有接收到预测值。
在 Kaggle 比赛中,通常有三个数据集:训练、测试和提交。在您的训练和测试数据中,您可能有很好的模型性能,但是您的模型在您的提交性能中失败得很惨。提交数据中的变量可能具有在训练或测试数据中看不到的新类别。即使您重新对数据进行了采样或者选择了不同的方法来创建培训和测试数据,也可能会出现此问题。
以下两种方法处理这个问题。首选方法 1。
方法 1:将任何未知值适当编码为“其他”或者合并到另一个类别中。这是一个很好的编程实践:即使您在训练数据中看不到任何新值,您仍然会保留一个类别,以备可能会有新值。下面的代码将任何未知组合成“硕士及以上学历”。以便相应地组合测试数据中的“博士”记录。
R 代码:
方法 2:使用你的训练和测试数据来创建新的变量。在这种情况下,将观察到新的类别“博士”。然而,这种方法仍然不能避免任何未来的未知值。
Python 代码:
[## 通过我的推荐链接加入 Medium-Chris Kuo/data man 博士
阅读 Chris Kuo/data man 博士的每一个故事。你的会员费直接支持郭怡广/戴塔曼博士和其他…
dataman-ai.medium.com](https://dataman-ai.medium.com/membership)
(6)忘记处理回归中的异常值
展示中的异常值导致你的回归倾向于那个观察值。你的预测会有偏差。所以记得把你的因变量和自变量分别削减到 1%和 99%。这意味着如果一个变量的值低于 1%,你将把它设置为 1%,如果高于 99%,把它限制在 99%。有些人可能会尝试 5%和 95%。
(7)要求线性回归中因变量的正态假设
因变量 Y 不需要遵循正态分布,但是预测 Y 周围的**误差应该遵循正态分布。数据科学家经常从因变量的直方图中检查正态假设。在这种特殊情况下,如果因变量服从正态分布,那么误差将是。然而,概念是线性回归的误差应遵循正态分布,或者因变量具有条件正态分布。回想一下线性回归的定义:在 X 的每一个值上,都有一个正态分布的 Y 的条件分布。线性回归的四个基本假设是:
- X 和 Y 之间的关系是线性的
- 误差呈正态分布
- 误差的同方差(或者,线周围的等方差)。
- 观察的独立性。
根据大数定律和中心极限定理,线性回归技术中的普通最小二乘(OLS)估计仍将近似正态分布在真实参数值周围。因此,在大样本中,即使因变量违反了“正态假设”规则,线性回归技术的使用仍然有效。
(8)要求线性回归中预测值的正态假设
预测者的 Xs 怎么样?回归并不假设预测值有任何分布。唯一的要求是检查是否存在异常值(您可以使用箱线图来检查异常值)。如果是,应该对预测值应用封顶和垫底技术。
(9)你在决策树中做分布假设吗?
在参数形式(如线性回归)中,您检查目标变量的分布以选择正确的分布。例如,如果目标变量显示伽玛分布,则在广义线性模型(GLM)中选择伽玛分布。然而,决策树不对目标变量做出假设。处理决策树的基本原则是将每个父节点分割成尽可能不同的节点。它没有对原始群体或最终群体的分布做出任何假设。因此,在实现决策树时,分布的性质并不重要。
(10)在决策树中,你是否对预测因子进行了封顶和保底?
在参数形式(如线性回归)中,您必须通过将异常值限制在 99%(或 95%)和 1%(或 5%)来处理异常值。在基于树的算法中,你不需要在决策树中做封顶和垫底。或者换句话说,决策树算法对异常值是鲁棒的。树算法基于相同的值分割数据点,因此异常值不会对分割产生太大影响。这取决于您对超参数的设置。
(11)我的树中没有显著的变量或者只有很少的变量
您可能将复杂性参数(cp)设置得太高。复杂性参数(cp)部分是每个节点所需的模型的最小改进。这是分割该节点改善相对误差的量。如果分裂原始根节点将相对误差从 1.0 降低到 0.5,则根节点的 CP 是 0.5。
(12)决策树中存在多重共线性的变量是否丢弃?
当多元回归模型中的一个预测变量可以通过其他预测变量以相当高的准确度进行线性预测时,就会发生多重共线性。当您为分类变量创建虚拟变量时,您在回归模型中删除了一个变量。然而,决策树和提升树算法不受多重共线性的影响。在完全相关的变量中,决策树将只选择一个提供最佳分割的变量。
(13)忘记标准化 K-means 中的变量
K 均值聚类可能是最流行的无监督技术。它给你很好的聚类结果。但是,如果不将变量标准化到相同的量级,聚类结果和业务应用可能是灾难性的。
我用一个简单的例子来解释一下。假设 P1、P2 和 P3 在(X,Y)空间中的位置是(3000,1)、(2000,2)、(1000,3)。K-means 计算出 P1 和 P2 之间的距离为 1000.0005。因为 X 的量级支配 Y,结果被 X 错误地驱动你需要做的就是把 X 和 Y 拉到同一个量级。在本例中,X 被带到 X2,用于 K-means 计算距离。
这里我提供几个方法:
(1)缩放至(0,1):
r 代码:
Python 代码:
(2) Z 分数:
r 代码:
Z-score 的 Python 代码可以在下面找到。
(13)独立标准化训练和测试数据
当您标准化数据以训练您的模型时,请记住只有训练数据用于拟合定标器转换,然后定标器用于转换测试输入数据。一个常见的错误是独立缩放 x_train 和 x_test。
下面是正确的做法。StandardScaler()
用于从 x_train 数据中学习比例,然后应用于测试数据。
为什么我们不能对训练数据和测试数据分别进行独立的扩展呢?让我来说明建模的目的。一个模型将被用来对未来的未知数据进行评分。我估计你也同意,如果训练数据有了尺度,那么未来的数据也应该先有尺度,再由你的模型打分。我们不知道未来数据的均值和标准差,我们假设它们的行为与训练数据相同。因此,我们只能使用训练数据的平均值和标准差来应用于测试数据。让我用一个极端的例子来说明这一点。假设未来数据漂移并变得与训练数据非常不同,则未来数据的均值和标准差将不同于训练数据的均值和标准差。这种数据漂移是严重的,应该向模型用户发出警告。对数据漂移现象感兴趣的读者,推荐阅读《监控你的机器学习模型性能》一文。
* [## 通过我的推荐链接加入 Medium-Chris Kuo/data man 博士
阅读 Chris Kuo/data man 博士的每一个故事。你的会员费直接支持郭怡广/戴塔曼博士和其他…
dataman-ai.medium.com](https://dataman-ai.medium.com/membership)*
在人工智能中避免副作用和奖励黑客
原文:https://towardsdatascience.com/avoiding-side-effects-and-reward-hacking-in-artificial-intelligence-18c28161190f?source=collection_archive---------19-----------------------
Photo by @pawel_czerwinski Unsplash
《人工智能安全中的具体问题》节选小结
我决定再次后退一步。这一次到 2016 年 6 月发表在 OpenAI 页面上写的关于 AI 安全的论文叫做AI 安全中的具体问题 。写这篇文章的时候,现在是 7 月 26 日。然而,我很怀疑自己现在是否比当时这群思想家懂得更多。但是我会尽我最大的努力来检查这篇论文。
“机器学习和人工智能(AI)的快速发展使人们越来越关注 AI 技术对社会的潜在影响。在本文中,我们讨论了一个这样的潜在影响:机器学习系统中的事故问题,定义为可能因现实世界人工智能系统的糟糕设计而出现的意外和有害行为。”
据此,他们列出了与人工智能风险相关的五个实际问题,并按以下方式分类
- **A 排泄副作用 **
- 奖励黑客
- 可扩展监督
- 安全探索
- 分配转移
我将简要地看一下在粗体中列出的两个。
他们回顾了这些领域以前的工作,并提出了与“前沿”人工智能系统相关的研究方向。然而,他们确实把这些变成了具体的例子,比如机器人手臂撞倒了花瓶;淘气的清洁机器人;培训期间的评估;电源插座中的湿拖把;环境不同。随着我们的进展,我将自由地思考,如果不清楚文章的建议和我自己在这方面的想法,我道歉。
在撰写本文时,他们指出了三个趋势,这使得人工智能安全变得非常重要。在这个中,他们声称:
- 强化学习(RL)的前景越来越光明,它允许代理与他们的环境进行高度交织的交互。
- 更复杂的代理和环境。“副作用”更有可能发生在复杂的环境中,一个代理可能需要非常复杂才能以一种危险的方式破解它的奖励功能。
- 增加人工智能系统的自主性。输出建议,如语音系统,通常具有相对有限潜在危害。相比之下,控制工业过程的机器会造成伤害。
避免副作用和奖励黑客——目标函数
他们谈论的 【负面副作用】 。在文章中,他们质疑他们所谓的“形式目标函数”,以及是否有可能选择了错误的目标函数。目标函数是线性规划中希望最大化或最小化的函数。用简单的英语,也许太简单了,我们可能会问:我们做得对吗?如果我们将矿产资源开采的价值最大化,却忘记了可能的环境外部性(理解为:损害),这可能就是一个例子。在此,他们将事故定义为:**
“从广义上讲,事故可以被描述为这样一种情况:一个人类设计者想到了某个(可能是非正式指定的)目标或任务,但是为该任务设计和部署的系统产生了有害的和意想不到的结果。”
如果忽略了潜在的非常大的环境问题,就会出现安全问题。即使在“完美的学习和无限的数据”的限制下,目标函数也会导致有害的结果。这些思想被发扬光大,但可以说不是 AI 领域特别独特的。尽管如此,它被考虑的事实是重要的,看起来显而易见的并不总是最明显的行动过程。
我最近总结了欧盟基本权利机构(FRA)的一篇论文,名为 “数据质量和人工智能——减少偏见和错误以保护基本权利 ”。在这篇文章中,我看到了一个有趣的陈述,我想再次强调一下。数据是否“符合目的”,这与数据质量有关,但显然在人工智能安全中,它同样与形式目标函数的问题有关:
"因此,数据的质量在很大程度上取决于它们的使用目的."
回到 OpenAI 的论文。他们进一步描述道:“在《黑客行动奖励》中,设计者写下的目标函数承认一些聪明的‘简单’的解决方案,这些解决方案在形式上最大化了目标函数,但是扭曲了设计者意图的精神(即目标函数可以被‘游戏化’),这是引线问题的一种概括。”【加粗】那么什么是引线问题呢?
“电线头 是大脑体验快感的人工刺激,通常是通过用电流直接刺激个体大脑的奖赏或快感中枢。它还可以在更广泛的意义上使用,指任何一种通过直接最大化良好感觉来产生某种形式的假冒效用,但未能实现我们所珍视的东西的方法。”
-
他们打算如何解决这个负面副作用?
- ****定义影响规则:如果我们不想要副作用,惩罚“改变环境”似乎是很自然的挑战在于我们需要将“对环境的改变”正式化
- ****学习影响正则化:另一种更灵活的方法是通过对许多任务的训练来学习(而不是定义)一个通用的影响正则化。这是迁移学习的一个例子。
- ****惩罚影响:除了不做有副作用的事情之外,我们可能也更希望代理不要进入一个很容易做有副作用的事情的位置,即使那可能很方便。
- 多主体方法:避免副作用可以被看作是我们真正关心的事情的代理:避免负外部性。
- ****回报的不确定性:我们希望避免意料之外的副作用,因为根据我们的偏好,环境已经很好了——随机的变化更有可能是非常糟糕,而不是非常好。
此外,他们还提出了一些避免奖励黑客攻击的建议:
- ****部分观察到的目标:在大多数现代 RL 系统中,假设奖励是直接体验到的,即使环境的其他方面只是被部分观察到。然而,在现实世界中,任务常常涉及到将外部世界带入某种客观状态,而这种客观状态只有代理人通过不完美的感知才能确认。
- ****复杂系统:任何强大的智能体都是一个复杂系统,目标函数是其中的一部分。正如计算机代码中的错误概率随着程序的复杂性而大大增加一样,存在影响奖励函数的可行黑客的概率也随着代理及其可用策略的复杂性而大大增加。
- ****抽象奖励:复杂的奖励功能将需要引用抽象的概念(比如评估一个概念性的目标是否已经实现)。这些概念可能需要像神经网络这样的模型来学习,神经网络很容易受到对立的反例的影响。
- ****古德哈特定律:如果设计师选择了一个看似与完成任务高度相关的目标函数,但当目标函数被强烈优化时,这种相关性就消失了,那么另一个奖励黑客行为的来源就会出现。
- ****反馈循环:有时一个目标函数有一个可以自我强化的成分,最终被放大到淹没或严重扭曲设计者想要表达的目标函数的程度。
- ****环境嵌入:在强化学习的形式主义中,奖励被认为来自环境。这种想法通常不能从字面上理解,但它确实是真的,即使它是一个抽象的想法,如棋盘游戏中的分数,也必须在某个地方计算,如一个传感器或一组晶体管。
和往常一样,当然还有更多要说的,我只是从包含这些思想的大文本中摘录了一小段。
然而,我希望这是有帮助的,并引发你的兴趣。
这是第 500 天的第 54 天
我已经坚持每天写一篇文章 50 天了。这些文章在探索人工智能领域中社会科学和计算机科学的交叉方面表现得很一般。从第 50 天到第 100 天,我目前的重点是人工智能安全。
避免数据科学产品中的“自动移交”综合症
原文:https://towardsdatascience.com/avoiding-the-automatic-hand-off-syndrome-in-data-science-products-11be20315f1d?source=collection_archive---------35-----------------------
数据科学产品的简单进化指南
对数据科学产品演变的看法
为新团队开发数据科学产品可能是一项艰巨的任务。数据科学产品的本质中嵌入了相互冲突的要求。第一个约束:产品团队希望尽快将概念证明推向市场。第二个约束:数据科学(DS)团队需要一个不断增长的基础设施来进行高效的实验。数据科学家通常缺乏足够的基础设施来满足他们不断增长的需求。第三个约束:工程团队(ENG)重视系统的稳定性和可靠性。这使得他们无法与来自研究团队的“创意一代”保持同步。这些约束的组合导致机器学习流水线中的常规延迟。延误会严重影响士气和商业价值的创造。重要的是,这在模型创建和模型监控时留下了阴影。作为一个社区,我们需要确定容易延迟和失败的组件和工作流,以超越数据科学/机器学习工程的当前状态,达到更高的标准。
在这三个团队中,即(产品、DS 和 ENG),一个中心问题很早就被提出。
谁应该是数据科学产品计算管道的主要所有者?
随着三连胜在这个问题上的深入,所有权问题变得更加微妙。开始出现更多类似以下的问题:
- 当前的数据科学项目处于产品生命周期的哪个阶段?
- 工程可靠性与数据科学灵活性之间的项目权衡是什么?
- 这个项目创造了多少商业价值,它的任务关键程度如何?
这些问题可以帮助指导数据科学和工程小组。它可以帮助他们决定何时以及如何分配勘探和开发的工作。
它是关键任务吗?
为此,三连胜需要考虑最坏的情况。假设我们有一个长达一周的混乱,我们无法修复模型或支持它的数据管道上的任何东西。会有什么影响?以下是场景的排序列表:
- 该模型返回了不好的预测,但没有商业价值的损失。
- 该模型的预测能力正变得过时。这导致了轻微的商业价值损失。
- 模型的预测是如此的错误,以至于我们失去了大量的商业价值。
- 模型的预测正在破坏我们的客户关系。这种模式引发了重大的商业价值损失,并影响了品牌。
有了这个简单的列表,团队可以给他们的项目一个任务关键度分数。这可以帮助他们考虑 DS 到 ENG 交互的选项。
如果没有这个任务关键度评分评估,规避风险的工程团队通常会建议完全移交项目。就在第一次模型迭代之后。太快了。
我们姑且称之为数据科学产品中的“自动移交”综合症。
从任务关键度评分到 DS 管道
这里有一个模式可以用来避免这种自动切换。在我最近参与的人工智能项目中,我看到了这项工作。在确定了任务的关键程度后,团队可以选择下面两条路径中的一条。
基于任务关键度的 ML 产品管理的两种不同方法
对于非关键任务产品,DS 项目负责人应促进 DS 的完全所有权。这样,领导该产品的数据科学家也可以拥有 DS 管道:
Two different methods of ML product management based on Mission Criticality
对于任务不太关键的产品,DS 项目负责人应促进数据科学团队的完全所有权。这样,领导该产品的数据科学家就可以拥有 DS 管道:
- 数据准备
- 特征工程
- 模特培训
- 模型服务
- 模型监控
为了在这方面取得成功,数据科学平台团队可以提供轻度的“平台”级支持。DS 团队可以依赖上游数据管道。这些通常可用于母公司业务中的报告职能。
另一方面,项目的任务关键程度可能会变得过高。飞行中的颠簸可能会造成巨大的商业价值损失。在这种情况下,建议采用一种补充方案。工程部门构建了一个用于生产用途的硬化管道。这涉及“稳定性第一”的数据准备、特征工程和模型训练/服务/监控。DS 团队继续并行开发新的功能工程/模型。
保持服务/监控与生产管道的分离是很有用的。实验性的 DS 管道可以使用生产工作负载所使用的服务/监控基础设施。这也防止了模型服务兼容性的偶然差异。
当产品发展到足够关键时,这简化了未来的“移交”。“伪不变的”服务层鼓励团队寻找与之兼容的模型。这是一个使用依赖倒置原则的好机会。服务层是消费者/客户查询和预测服务之间的接口。但是,它可以在团队之间建立一个契约。实验管道和生产管道都可以共享这项服务。这种策略的缺点是它减少了 ML 搜索空间。API 契约和 DB 表模式都可以充当契约。这使实验和生产途径保持同步。
还有两个问题没有得到解答:
- 如何在 DS 和 ENG 团队成员之间分配工作,使他们能够发挥互补的技能?
- 实验和生产层面之间的这种互动何时以及如何发展?
DS 和 ENG 之间的分工
下面是一种模拟 DS 与 ENG 交互的方法,分为两个复杂性轴:
- 计算性能复杂性
- 机器学习复杂性
“计算性能复杂性”(CPC)是一个宽泛的抽象术语。我将在这里用它来描述任何不“适合”数据科学家的笔记本电脑的处理。
“机器学习复杂性”(MLC)也是一个宽泛而抽象的术语。我会把它用于任何需要大量机器学习知识的处理。
目标是帮助 DS 团队决定如何划分各种项目组件。DS 产品可以去除一些不必要的耦合。这需要将产品总分类与商品总分类脱钩。我们解释如何根据 DS 和 ENG 团队的专业化来划分组件。
Possible Data/DS/ML Component refinement directions
这种分割的想法是把它分成有意义的部分。组件的并发实现加快了生产时间。
在项目早期,手头的问题没有足够的 ML 或性能复杂性。但是每个人都默认参与其中。这种方法增加了团队内部的大量通信开销。数据工程师可以管理专门的低延迟和大数据堆栈。数据科学家和 ML 工程师可以管理机器学习组件。
使用该框架分离关注点是一门艺术。该框架可以指导构建模块化机器学习管道的最初尝试。
何时以及如何将实验工作发展到生产水平
ML Evolution pathways
监控是数据科学产品发展的关键。DS 车主高度关注直播车型的商业价值创造。上图提出了一种简单反馈回路的方法。这是一张简单的地图,可以帮助您跳到全面的生产支持。
DS 团队可以使用上面的决策图来选择策略。该图有助于确定一段时间内管道的任务关键度。DS 团队可以选择实验管道或完整的生产支持。在实验管道中,数据科学所有权属于整个管道。
实验途径提供了充分的灵活性。这包括生成多个版本的特征工程和模型训练步骤。在管道出口处,有两种类型的 DS 监控。“预测性能”和“业务价值”监控。预测性能指导 DS 团队的下一次迭代。这允许他们改进他们的模型/特征工程技术。商业价值监控引导从实验模式到生产模式的演进。DS 团队可以继续迭代,同时为完整的生产支持构建可靠的案例。
在实验+生产模式下,工程负责人复制最佳的 ML 配方。这个食谱来自实验途径。它们强化了有性能或可靠性限制问题的模块。
这种双模式允许 DS 团队不断迭代。对现有管道的修改产生了下一个最佳方案。这个下一个最佳配方旨在成为生产流水线。与实验模式一样,DS 团队使用预测性能进行迭代。业务价值监控确定了进一步强化生产的需求。DS 项目是全生命周期项目。因此,我们可以使用业务价值指标来确定任何日落。这是为未来的 DS 产品腾出空间所必需的。
结论
ML 管道的延迟和痛苦的调试是昂贵的。部分问题是产品+数据科学+工程三管齐下的工作流程。所有这些单独的部分孤立地工作得很好。但是沟通开销会降低项目的速度。这篇博文解释了导致“自动移交”综合症的原因。DS 团队从第一天开始就将项目移交给工程部门进行实施。这种方法在机器学习产品的发展上有缺陷。
为了解决这个问题,我们描述了 3 个简单的准则。这是为了帮助处理这种过早优化。首先,我们描述了如何估计项目的任务关键度。这包括 DS 管道如何适应以支持这两种情况。其次,我们描述了如何划分一个复杂的 DS 应用程序的指导原则。我们使用了复杂性能和复杂机器学习这两个轴。最后,我们描述了一种跟踪和适应实验+生产模式的方法。使用业务价值监控,我们可以调整 ML 管道运营模式。
这是所有的乡亲。
我希望你喜欢这篇文章。它旨在帮助您提高您的机器学习项目架构设计技能。
请注意,这篇文章中表达的观点是我个人的,不一定是我雇主的观点。
我们在招人!如果您对此感兴趣,请查看 Xandr 数据科学平台工程的空缺职位:
https://xandr . att . jobs/job/new-York/data-science-platform-engineer/25348/12859712
使用梯度噪声添加避免消失梯度问题
原文:https://towardsdatascience.com/avoiding-the-vanishing-gradients-problem-96183fd03343?source=collection_archive---------24-----------------------
也发表在https://afagarap . works/2019/09/05/avoiding-vanishing-gradients . html
介绍
神经网络是用于逼近函数的计算模型,该函数对数据集特征 x 和标签 y 之间的关系进行建模,即 f(x) ≈ y 。神经网络通过学习最佳参数 θ 来实现这一点,使得预测f(x;θ) 和标签 y 最小。它们通常借助于在输出层观察到的误差的反向传播,通过基于梯度的算法进行学习。
Illustrated using NN-SVG. A feed-forward neural network with two hidden layers. It learns to approximate the target label y by learning the appropriate θ parameters with the criteria of minimizing the difference between its output label f(x;θ) and target label y.
通过这种学习范式,神经网络在一些任务中产生了有希望的结果,如图像分类(Krizhevsky et al .(2012);【何等(2015) )、图像生成(布洛克等(2018); Goodfellow 等人(2014);拉德福德等(2015);朱等(2017) 、语言建模(德夫林等(2018);霍华德和鲁德(2018) 、音频合成(恩格尔等人(2019); Oord 等人(2016) ),以及图像字幕( Vinyals 等人(2015);徐等(2015) 等。然而,对于神经网络来说,这种优势并不总是如此。在 2012 年通过赢得 ImageNet 挑战赛而东山再起之前,训练神经网络是出了名的困难。
困难是由许多问题造成的,例如,计算能力和数据不足以利用神经网络的全部潜力。在很大程度上,这是因为神经网络对初始权重很敏感( Glorot 和 Bengio,2010 ),并且由于以下任何一个或两个原因,当梯度值降低到无穷小的值时,它们往往会过早地停止学习( Hochreiter 等人,2001):(1)它们的激活函数具有小范围的梯度值,以及(2)它们的深度。这种现象被称为消失梯度问题。
上述问题的第一个原因是我们对这篇文章的关注。换句话说,当我们用基于梯度的算法和反向传播来训练深度神经网络时,会出现消失梯度问题,其中通过每个隐藏层反向传播的梯度减小到无穷小的值,模型学习所需的信息不再存在。
自然,已经提出了许多解决方案来缓解这个问题,例如,使用不同的激活函数( Nair 和 Hinton,2010 ),以及使用剩余连接( He 等人,2016 )。在本文中,我们以激活函数的形式回顾了消失梯度问题的许多提议的解决方案,但是我们将我们的架构限制为前馈神经网络。我们还将研究一种实验方法,这种方法可以帮助避免消失梯度问题,也可以帮助它们更快更好地收敛。
批量归一化的梯度噪声添加
已经提出了几个研究工作来解决消失梯度问题,这些工作包括但不限于引入新的激活函数和新的架构。
最简单的神经网络结构将由具有逻辑激活函数的隐藏层组成,该逻辑激活函数用基于梯度的学习算法和反向传播来训练。这种架构的问题是其激活函数将隐藏层值压缩为[0,1] ∈ ℝ.用该函数反向传播的梯度具有最大值 0.25(见表 1),因此这些值变得饱和,直到没有更多有用的信息供学习算法用于更新模型的权重。
Table 1. Activation functions for neural nets, together with their respective derivatives, and critical point values.
多年来,这个问题的主流解决方案是使用双曲正切,最大梯度值为 1(见表 1)。然而,梯度值仍然会因该函数而饱和,这可以从图 1 中看到。因此,引入了校正线性单位(ReLU)激活功能( Nair 和 Hinton,2010 )。
ReLU 激活函数具有相同的最大梯度值 1,但其优于逻辑函数和双曲正切函数的优势在于其激活值不会饱和。然而,ReLU 具有其自身的缺点,即,由于其最小梯度值为 0,它触发了“死亡神经元”的问题,即,神经元没有激活值。所以,是的,即使它避免了非负值的饱和,它的负值也会触发死亡神经元现象。
由于这个缺点,ReLU 的变体之一是 Leaky ReLU,它有一个简单的修改,具有略高于零的下限。反过来,这种修改允许模型避免饱和梯度值和“死神经元”问题。
Figure 1. Plotted using matplotlib. Activation function values, their gradients, and their noise-augmented gradient values. For instance, adding Gaussian noise to the gradients of the logistic activation function increases its maximum value, i.e. from 0.25 to approximately 1.047831 (from a Gaussian distribution having a mean value of 0 and a standard deviation value of 0.5).
但是,尽管进行了这种修改, Ramachandran 等人(2017) 声称已经开发出了一种比 ReLU 更好的功能,即“Swish”激活功能。上述函数可以描述为逻辑加权线性函数,其最大梯度值约为 1.0998(如表 1 所示),在 CIFAR 数据集(使用 ResNet)、ImageNet 数据集(使用 Inception 和 MobileNet)和机器翻译(使用 12 层变压器模型)上的性能优于 ReLU。
虽然这些解决方案更侧重于制定新的激活以改善神经网络的学习,但 Neelakantan 等人(2015) 的工作介绍了一种简单而有效的改善神经网络性能的方法。该方法是简单地添加梯度噪声,以改善非常深的神经网络的学习(见等式。1).它不仅提高了神经网络的性能,而且有助于避免过拟合问题。虽然作者没有明确说明他们提出的解决方案旨在缓解消失梯度问题,但可以这样看,因为训练期间计算的梯度是膨胀的,因此有助于避免导致消失梯度问题的饱和梯度值。
Eq. 1. The gradient noise addition approach for improving the learning of deep neural networks.
时间步长 t 处的标准偏差σ然后通过以下等式迭代退火,
Eq. 2. The annealing function helps to shift the gradient values away from zero during early training iterations.
在 Neelakantan et al. (2015) 的原始论文中,η参数是从{0.1,1.0}中选取的,而γ参数在他们所有的实验中都被设置为 0.55。
TensorFlow 2.0 用于实现本文实验的模型及其计算。为了实现退火梯度噪声添加,我们简单地增加使用tf.GradientTape
计算的梯度,通过添加来自等式 1 产生的高斯分布的值。1 和 Eq。2.也就是说,使用tf.add
,如代码片段 1 的第 7 行所示。
Snippet 1. Model optimization with annealing gradient noise addition.
最后,这种方法通过使用批量标准化得到进一步增强(约夫和赛格迪,2015 )。因此,利用这种方法,在训练会话开始期间,层激活将被迫呈现单位高斯分布。
实证结果
在接下来的实验中,MNIST 手写数字分类数据集( LeCun,Cortes,and Burges,2010 )用于训练和评估我们的神经网络。每个图像都被整形为 784 维向量,然后通过将每个像素值除以最大像素值(即 255)进行归一化,并添加来自标准偏差为 5e-2 的高斯分布的随机噪声,以提高在数据集上收敛的难度。
提高梯度值
在训练过程中,我们可以观察神经网络学习时的梯度分布。在图 2 中,我们以具有逻辑激活函数的神经网络为例。由于逻辑激活函数具有最小的最大梯度值(即 0.25),我们可以考虑观察其梯度分布中值得注意的变化。
Figure 2. Figure from TensorBoard. Gradient distribution over time of neural nets with logistic activation function on the MNIST dataset. Top to bottom: Baseline model, experimental model with GNA, and experimental model with GNA + batch normalization.
从上面的图表中我们可以看出,从基线配置到实验配置,模型的梯度分布急剧变化,即从相当小的值(对于两层神经网络为+/- 4e-3,对于五层神经网络为+/- 5e-6)到相对大的值(对于两层和五层神经网络均为+/- 4)。虽然这并不能保证优越的模型性能,但它确实让我们了解到,将有足够的梯度值在神经网络中传播,从而避免梯度消失。我们转到下一小节来检查模型的分类性能。
分类性能
使用具有动量的随机梯度下降(SGD )(学习速率α = 3e-4,动量γ = 9e-1)在扰动的 MNIST 数据集上训练模型 100 个时期,小批量大小为 1024(对于两层神经网络)和小批量大小为 512(对于五层神经网络)。我们的网络包括(1)两个各有 512 个神经元的隐藏层,和(2)五个隐藏层,每个隐藏层有以下神经元:512,512,256,256,128。两种网络架构的权重都是用 Xavier 初始化来初始化的。
我们可以在图 3-6 中观察到,使用实验方法,梯度噪声添加(GNA)和 GNA 批量归一化(BN),有助于神经网络在损失和准确性方面更快更好地收敛。
Figure 3. Plotted using matplotlib. Training loss over time of the baseline and experimental (with GNA, and GNA + batch normalization) two-layered neural networks on the MNIST dataset.
Figure 4. Plotted using matplotlib. Training accuracy over time of the baseline and experimental (with GNA, and GNA + batch normalization) two-layered neural networks on the MNIST dataset.
Table 2. Test accuracy of the baseline and experimental (with GNA, and GNA + batch normalization) two-layered neural networks on the MNIST dataset.
从表 2 中,我们可以看到,使用 GNA 和 GNA+BN 的测试精度值显著提高,尤其是在基于逻辑的神经网络上。
Figure 5. Plotted using matplotlib. Training loss over time of the baseline and experimental (with GNA, and GNA + batch normalization) five-layered neural networks on the MNIST dataset.
Figure 6. Plotted using matplotlib. Training accuracy over time of the baseline and experimental (with GNA, and GNA + batch normalization) five-layered neural networks on the MNIST dataset.
Table 3. Test accuracy of the baseline and experimental (with GNA, and GNA + batch normalization) five-layered neural networks on the MNIST dataset.
从表 2 的结果可以看出,所有的基线双层神经网络都通过 GNA 和 GNA+BN 得到了改善。然而,对于五层神经网络(见表 3),基于 ReLU 的模型未能提高测试精度。此外,我们可以看到,在这种配置中,基于 TanH 的神经网络比基于 ReLU 的模型具有更好的测试精度。我们可以将这归因于我们使用了 Xavier 初始化(其中 TanH 的性能最佳)而不是 He 初始化(其中 ReLU 的性能最佳)。
总的来说,五层神经网络的这些结果支持早先的陈述,即梯度值的膨胀不一定保证优越的性能。
但这里有趣的是基线模型与 Swish 激活功能的大幅改进——测试准确率提高高达 54.47%。
尽管在两层神经网络的结果中,基于 Swish 的模型比基于 ReLU 和基于漏 RELU 的模型具有稍低的测试精度,但我们可以看到,对于五层神经网络,基于 Swish 的模型比基于 ReLU 的模型具有更高的测试精度(但比基于漏 ReLU 的模型稍低)。这在某种程度上证实了这样一个事实,即 Swish 在更深的网络上优于 ReLU, Ramachandran 等人(2017) 在其 12 层变压器模型的结果上展示了这一点。
结束语
在本文中,我们概述了在神经网络中关于一组激活函数(逻辑、双曲正切、校正线性单位、低界校正线性单位和逻辑加权线性单位)传播的梯度值。我们使用了一种结合梯度噪声添加和批量标准化的方法,试图缓解消失梯度的问题。我们看到,在测试准确性方面,模型性能提高了 54.47%。此外,使用实验方法,模型比它们的基线对应物收敛得更快更好。
我们在这篇文章中的探索只是冰山一角,因为有很多事情可以讨论关于消失梯度的问题。例如,如果我们尝试 Xavier 和 He 初始化方案,并将它们与基线和实验方案的零初始化和随机初始化进行比较,结果如何?添加梯度噪声有多大帮助?也就是它还能帮助一个 30 层以上的神经网络吗?如果我们也使用层归一化或权重归一化会怎么样?它将如何公平地对待或对待残余网络?
我希望我们在这篇文章中已经覆盖了足够多的内容,让你对渐变消失的问题以及避免这个问题的不同方法有更多的了解。
完整代码可在这里获得。如果你有任何反馈,你可以通过推特联系我。我们也可以通过 LinkedIn 联系!
如果你喜欢读这篇文章,也许你也会发现我关于在 TensorFlow 2.0 中实现自动编码器的博客很有趣!
参考
- 克里日夫斯基、亚历克斯、伊利亚·苏茨基弗和杰弗里·e·辛顿。"使用深度卷积神经网络的图像网络分类."神经信息处理系统的进展。2012.
- 何,,等,“深度残差学习在图像识别中的应用”IEEE 计算机视觉和模式识别会议论文集。2016.
- 布洛克,安德鲁,杰夫·多纳休和卡伦·西蒙扬。"高保真自然图像合成的大规模 gan 训练." arXiv 预印本 arXiv:1809.11096 (2018)。
- 伊恩·古德菲勒等着《生成性对抗性网络》神经信息处理系统的进展。2014.
- 拉德福德,亚历克,卢克·梅斯,和苏密特·钦塔拉。"深度卷积生成对抗网络的无监督表示学习." arXiv 预印本 arXiv:1511.06434 (2015)。
- 使用循环一致对抗网络的不成对图像到图像翻译。IEEE 计算机视觉国际会议论文集。2017.
- 伯特:用于语言理解的深度双向转换器的预训练。arXiv 预印本 arXiv:1810.04805 (2018)。
- 霍华德杰里米和塞巴斯蒂安.鲁德。“用于文本分类的通用语言模型微调。”arXiv 预印本 arXiv:1801.06146 (2018)。
- 《甘瑟思:对抗性神经音频合成》arXiv 预印本 arXiv:1902.08710 (2019)。
- 《Wavenet:原始音频的生成模型》arXiv 预印本 arXiv:1609.03499 (2016)。
- 展示和讲述:一个神经图像字幕生成器。IEEE 计算机视觉和模式识别会议录。2015.
- 徐,凯尔文,等。“展示、参与和讲述:视觉注意下的神经图像字幕生成”机器学习国际会议。2015.
- 格洛特,泽维尔,和约舒阿·本吉奥。"理解训练深度前馈神经网络的困难."第十三届人工智能与统计国际会议论文集。2010.
- 《递归网络中的梯度流:学习长期依赖的困难》(2001).
- 奈尔、维诺德和杰弗里·e·辛顿。"校正的线性单位改进了受限的玻尔兹曼机器."第 27 届机器学习国际会议录(ICML-10)。2010.
- Ramachandran,Prajit,Barret Zoph 和 Quoc V. Le。"嗖嗖:一个自门控激活功能."arXiv 预印本 arXiv:1710.05941 7 (2017)。
- 加入梯度噪音可以改善深度网络的学习。arXiv 预印本 arXiv:1511.06807 (2015)。
- 约夫、谢尔盖和克里斯蒂安·塞格迪。"批量标准化:通过减少内部协变量转移加速深度网络训练."arXiv 预印本 arXiv:1502.03167 (2015)。
- 勒昆、扬恩、科琳娜·科尔特斯和 C. J .伯格斯。" MNIST 手写数字数据库."美国电话电报公司实验室[在线]。可用:【http://yann.lecun.com/exdb/mnist】(2010):18。
AWS Athena 帮助找到波特兰最糟糕的停车地点
原文:https://towardsdatascience.com/aws-athena-helps-to-find-the-worst-place-to-park-your-car-in-portland-ffb5195cfd9?source=collection_archive---------28-----------------------
My Tableau Public
在参观完波特兰之后,或者上周末,我决定探索一些公开的关于这个城市的数据集。在本帖中,我们将使用Athena geo 查询来计算每个波特兰社区中与车辆相关的事件(车辆被盗)的数量以及停车位的数量。之后,我们将计算每个停车位的事故数量,以识别危险区域。
我们将使用三个数据集:
- 2019 年发生在波特兰的所有事件的警方报告。您可以在此下载该数据集(点击“下载开放数据”选项卡)
- 波特兰停车点坐标,你可以下载这个数据集这里
- 波特兰街区边界的 JSON,你可以在这里下载它(选择 GeoJSON 格式)
开始使用 SQL 探索数据集的一种快速简单的方法是使用 AWS Athena 数据库和 S3。创建一个 S3 桶(我称之为波特兰犯罪分数)。
对于事件文件,在桶中创建一个文件夹“crime_data”。将下载的 CSV 文件导入文件夹。之后,转到 AWS 控制台,打开 Athena 服务并运行以下查询来创建一个表(用您的替换 S3 存储桶名称):
CREATE EXTERNAL TABLE IF NOT EXISTS sampledb.incidents (
`Address` string,
`CaseNumber` string,
`CrimeAgainst` string,
`Neighborhood` string,
`OccurDate` string,
`OccurTime` string,
`OffenseCategory` string,
`OffenseType` string,
`OpenDataLat` float,
`OpenDataLon` float,
`OpenDataX` float,
`OpenDataY` float,
`ReportDate` string,
`OffenseCount` int
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS TEXTFILE LOCATION 's3://portland-crime-score/crime_data/'
TBLPROPERTIES ('skip.header.line.count'='1');
对于停车位,创建一个名为“parking_data”的文件夹并导入相应的文件。运行以下查询来创建表:
CREATE EXTERNAL TABLE IF NOT EXISTS sampledb.parking (
`X` float,
`Y` float,
`OBJECTID` string,
`ModifiedBy` string,
`ModifiedOn` string,
`ModifiedUsing` string,
`Comments` string,
`NonAssetID` string,
`Status` string,
`Owner` string,
`MaintResp` string,
`LocationID` string,
`ImagePath` string,
`Metered` string,
`APPZone` string,
`UseCode` string,
`ParkingDuration` string,
`Rotation` string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS TEXTFILE LOCATION 's3://portland-crime-score/parking_data/'
TBLPROPERTIES ('skip.header.line.count'='1');
对于邻域边界文件,创建一个名为“neighborhoods_data”的文件夹,并导入相应的文件。邻域数据存储在嵌套的 JSON 文件中,这就是这次表模式看起来不同的原因:
CREATE EXTERNAL TABLE neighborhoods (
type string,
features array<
struct<type: string,
properties: struct<OBJECTID: string,
NAME: string,
COMMPLAN: string,
SHARED: string,
COALIT: string,
HORZ_VERT: string,
MAPLABEL: string,
ID: string,
Shape_Length: string,
Shape_Area: string
>,
geometry: struct<type: string,
coordinates: array<array<array<string>>>
>
>
>
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://portland-crime-score/neighborhoods_data/';
让我们看一个表事件和运行几个 SQL 查询来浏览数据。首先,让我们看看我们有多少记录:
select count(*)
from **incidents;**
select *
from **incidents**
limit 10;
如我们所见,一些记录没有事件的坐标。如果我们在网站上检查数据集的元数据,就会发现它们是被故意删除的:
让我们看看没有坐标的记录有多少:
select count(*) as count
from **incidents**
where OpenDataLat is Null or OpenDataLon is Null;
我们将从进一步的探索中排除那些记录。现在让我们看看文件中有哪些类型的事件:
select distinct OffenseType
from **incidents**;
共有 46 种事件类型。让我们关注与车辆相关的问题:
select distinct OffenseType
from **incidents**
where OffenseType like '%Vehicle%'
现在,让我们创建一个仅包含 Athena 车辆事故地理点的表,并查看在应用所有这些过滤器后我们有多少行:
**incident_points** as (
select ST_POINT(opendatalon, opendatalat)
from **incidents**
where OffenseType in (
'Motor Vehicle Theft',
'Theft From Motor Vehicle',
'Theft of Motor Vehicle Parts or Accessories')
and OpenDataLat is not NULL
and OpenDataLon is not NULL
)
select count(*) as incident_count
from **incident_points**;
现在,让我们创建一个包含所有停车点的地理点的表,这次我们不需要过滤任何内容:
**parking_points** as (
select ST_POINT(x, y) as point
from **parking**
)
select count(*) as parking_count
from **parking_points**;
现在,让我们来看一个邻域数据集。让我们解析 JSON 来提取边界坐标并创建 Athena 支持的 Polygon 类型的对象。我找不到一种简单的方法来解析 Athena 中的 GeoJSON。文档没有说支持它。这就是为什么我必须用 json 执行一系列操作来提取所需的坐标。
首先,让我们看看表邻域中有什么:
select *
from **neighborhoods**;
整个文件被解析成一行。我们需要从具有数组类型的 features 列中提取数据。让我们像这样解除数组嵌套:
select type, feature
from **neighborhoods**
CROSS JOIN UNNEST(features) AS t(feature)
每个要素代表一个邻域。现在我们可以像这样访问它的值:
select feature.properties.Name as name, feature.geometry.coordinates[1] as shape
from **neighborhoods**
CROSS JOIN UNNEST(features) AS t(feature)
这里我们有一个邻域名称和一个带有边界坐标的数组。我们的目标是将这些坐标转换成 varchar 格式,Athena 可以将它解析成这样的多边形对象:SELECT ST _ Polygon(' Polygon((1 1,1 4,4 4,4 1))')。要做到这一点,我们应该将坐标连接成一个字符串。此外,两个名为“MC UNCLAIMED #13”和“CRESTWOOD”的街区的坐标格式很奇怪,无法解析,所以我把它们从列表中排除了。让我们运行以下查询:
with **neighborhood_coords** as (
select feature.properties.Name as name,
feature.geometry.coordinates[1] as shape
from **neighborhoods**
CROSS JOIN UNNEST(features) AS t(feature)
where feature.properties.Name != 'MC UNCLAIMED #13' AND feature.properties.Name != 'CRESTWOOD'
),
**unnest_nodes** as (
select name, array_join(node, ' ') as node_str
from **neighborhood_coords**
CROSS JOIN UNNEST(shape) AS t(node)
)
select * from **unnest_nodes**;
我们把邻居的坐标提取到多列中。现在我们需要做的就是用字符串连接将它们聚合回来:
**suburbs** as (
select name as suburb_name, ST_POLYGON('polygon ((' || array_join(array_agg(node_str), ', ') || '))') as poly from **unnest_nodes** group by name
)
select * from **suburbs**;
现在,让我们将我们的小区与停车点连接起来,计算每个小区的停车位数量。我们将使用 Athena 函数 ST_CONTAINS 来检查停车点是否位于边界多边形内:
**suburb_parking** as (
select suburb_name, count(*) as parking_count from **suburbs**
join parking_points on ST_CONTAINS(poly, point)
group by suburb_name order by parking_count desc
)
select * from **suburb_parking** limit 10;
正如我们所见,市中心有最多的停车位。
现在,让我们看看发生事故的街区,统计每个街区的事故数量:
**suburb_incident** as (
select suburb_name, count(*) as incident_count from **suburbs**
join incident_points on ST_CONTAINS(poly, incident_point)
group by suburb_name order by incident_count desc
)
select * from **suburb_incident** limit 10;
黑兹尔伍德记录的事故数量最高,市中心位居第二。
最后,让我们计算事故数量与停车点数量之间的比率:
select suburb_parking.suburb_name, CAST(incident_count as double)/parking_count as crime_score
from **suburb_incident**
join suburb_parking on suburb_incident.suburb_name = suburb_parking.suburb_name
order by incident_count/parking_count desc;
令我们惊讶的是,像里士满这样名字好听的社区每个停车位的事故数量最高,而西北区是最安全的地方,每个停车位发生 0,056 起事故。
整个查询如下所示:
with **regions_coords** as (
select feature.properties.Name as name, feature.geometry.coordinates[1] as shape from **neighborhoods**
CROSS JOIN UNNEST(features) AS t(feature)
where feature.properties.Name != 'MC UNCLAIMED #13' AND feature.properties.Name != 'CRESTWOOD'
),
**unnest_nodes** as (
select name, array_join(node, ' ') as node_str from **regions_coords**
CROSS JOIN UNNEST(shape) AS t(node)
),
**suburbs** as (
select name as suburb_name, ST_POLYGON('polygon ((' || array_join(array_agg(node_str), ', ') || '))') as poly from **unnest_nodes** group by name
),
**parking_points** as (
select ST_POINT(x, y) as point from **parking**
),
**incident_points** as (
select ST_POINT(opendatalon, opendatalat) as incident_point from **incidents**
where OffenseType in (
'Motor Vehicle Theft',
'Theft From Motor Vehicle',
'Theft of Motor Vehicle Parts or Accessories')
and OpenDataLat is not NULL
and OpenDataLon is not NULL
),
**suburb_parking** as (
select suburb_name, count(*) as parking_count from **suburbs**
join parking_points on ST_CONTAINS(poly, point)
group by suburb_name order by parking_count desc
),
**suburb_incident** as (
select suburb_name, count(*) as incident_count from **suburbs**
join incident_points on ST_CONTAINS(poly, incident_point)
group by suburb_name order by incident_count desc
)
select suburb_parking.suburb_name, CAST(incident_count as double)/parking_count as crime_score
from **suburb_incident**
join suburb_parking on suburb_incident.suburb_name = suburb_parking.suburb_name
order by incident_count/parking_count desc;
下次我去波特兰的时候,我会查看这些信息,找到最好的住处。
AWS 成本优化—帮助您降低 AWS 成本的 5 个诀窍
原文:https://towardsdatascience.com/aws-cost-optimization-5-tricks-to-help-you-reduce-aws-costs-ccdae42f49c0?source=collection_archive---------38-----------------------
AWS 最吸引人的地方之一是它的“随用随付”定价模式。但是,有时这些 AWS 成本会失控。在本文中,我们提出了五种 AWS 成本优化解决方案和工具,它们将降低 AWS 成本,并确保支出符合企业的预期预算。
到 2020 年,“无云”政策将几乎消失。此外,到 2019 年,100 家最大供应商的新软件投资中将有 30%以上从云优先转向“纯云”。这主要是因为越来越多的大、中、小型企业正在向云迁移,以减少其资本支出密集型 IT 模式。
AWS 提供可变成本和现收现付模式,使其更经济。此外,使用 AWS 带来的可伸缩性和灵活性使它成为比传统方法更好的解决方案。
像你们这样的公司采用 AWS 云计算可能是因为可扩展性或安全性,或者只是因为 AWS 云计算是最新的趋势,但我相信你们所有人都注意到了 AWS 成本飙升和支出趋势持续上升。
AWS 定价方法起初看起来非常简单,但随着您的扩展,混合大量产品,它会让您很难跟踪云基础架构不断增长的成本。因此,保持严格的 Amazon Web Services 计费卫生非常重要。在这篇短文中,让我们来检查一些策略,它们将帮助您保持这种卫生并优化 AWS 成本。
为了了解如何至少从 AWS 成本优化开始,请使用一些高级成本管理工具。这将有助于您可视化、了解和管理 AWS 成本和使用情况,跨不同维度的支出模式以及资源的实际成本明细。一旦你了解了 AWS 成本飙升的原因,你就可以看看这些 AWS 成本优化措施,以改进你控制 AWS 成本的尝试。
【1】AWS 成本优化的第一步是了解你的网站流量。使用谷歌分析来评估你的网站的访问量。此外,检查一下什么时候流量达到峰值,什么时候流量达到最大值。然后相应地优化您的 EC2 实例。
EC2 实例每小时按实例计费。根据交通量自动启动和停止 EC2 实例。这将帮助您大大节省 AWS 成本。
【2】您可以选择自动缩放——即根据设定的条件增加或减少 EC2 实例的数量。由于实例的数量可以动态地增加或减少,并且您为 AWS 中的实例数量付费,自动伸缩有助于 AWS 成本优化,它可以在需要时启动实例,在不需要时终止实例。
【3】现在来说说 AWS 存储优化:
当谈到降低 AWS 成本时,需要考虑存储。AWS 提供各种存储选项——弹性文件系统(EFS)、弹性块存储(EBS)、简单存储服务(S3)和 Glacier,其中 EFS 最贵,Glacier 最便宜。
Glacier 似乎是一个明智的选择,因为它是一个极低成本的 AWS 存储服务,为数据备份和归档提供安全、耐用和灵活的存储。有了亚马逊 S3 冰川,你可以以每月每千兆字节 0.004 美元的价格可靠地存储数据。
Glacier 非常适合长期存储的数据,并且不需要经常删除或检索。如果你经常检索文件或者不断地从服务器上删除它们,你会为此付出代价。
【4】如您所知,对于涉及不同组件间大量数据移动的数据密集型应用,AWS 在某些情况下会收取数据传输费。如果您是这种情况,那么建立虚拟专用云(VPC) 端点来创建 VPC 和其他 AWS 服务之间的私有连接,而不需要访问互联网,实际上可能是有意义的。这将极大地有助于 AWS 成本优化。
【5】用于图像尺寸调整、视频和音频文件处理等排队作业。,使用 Amazon Lambda,这样您就不需要为这些排队目的运行专用服务器。一旦图片上传到 S3,lambda 函数就会被触发,你只需要为代码运行的总时间付费。
总之,如果您希望降低 AWS 成本,请监控您的日常成本、优化存储、设置 VPC、处理 EC2 实例并寻找未使用的基础架构。下次当你认为 AWS 对你来说是一个巨大的口袋时,试试这些小技巧。欲了解更多节省 AWS 相关成本的方法,联系我们。
最初发表于: 二进制乡亲
AWS 弹性 MapReduce(EMR)——你不应该忽视的 6 个警告
原文:https://towardsdatascience.com/aws-elastic-mapreduce-emr-6-caveats-you-shouldnt-ignore-7a3e260e19c1?source=collection_archive---------9-----------------------
如果您从事数据和分析行业,您一定听说过新兴趋势“数据湖”,简单来说,它代表一种存储策略,允许组织在一个地方存储来自不同来源、具有不同特征(大小、格式和速度)的数据。然后,Data-lake 成为许多使用情形的推动者,例如高级分析或数据仓库等,通常数据会移动到更专业的存储中,例如 MPP 关系引擎或 NoSQL,以更好地满足特定使用情形的要求。如果在 AWS、Azure 或 GCP 等云环境中提供平台,那么对象存储(例如 AWS 的 S3,Azure 的 Azure 数据湖存储 Gen2)通常是提供数据湖基础物理层的最强候选。一旦数据进入数据湖,它将经过一系列区域/阶段/层,以在数据中建立语义一致性,并使其符合最佳消费。
通常,根据数据湖平台的参考架构,它与您选择的云提供商无关,Hadoop(特别是 Spark)被用作处理引擎/组件来处理数据层中的数据,因为它会经过不同的层。这些处理框架与数据湖服务很好地集成在一起,提供了水平可伸缩性、内存计算和非结构化数据处理等功能,这使它们成为这种环境下的可行选项。在云中使用 Hadoop 发行版通常有多种选择,例如,可以着手调配基于 IaaS 的基础架构(即 AWS EC2 或 Azure 虚拟机,并安装 Hadoop 发行版,如 vanilla Hadoop、Cloudera/Hortonworks)。或者,几乎所有的云提供商都在原生提供 Hadoop 作为托管服务(例如 AWS 中的 ElasticMapReduce (EMR)、Azure 中的 HDInsight/Databricks、GCP 的 Cloud Dataproc)。每种选择都有其利弊。例如,对于基于 IaaS 的实施,自行调配、配置和维护集群的开销成为许多人的一大担忧。此外,云的内在主张,如弹性和可扩展性,对基于 IaaS 的实施构成了挑战。
另一方面,在减少支持和管理开销方面,像 EMR 这样的托管产品确实提供了有力的主张。但是从功能的角度来看,在使用领先的云提供商提供的托管 Hadoop 产品时,仍然有许多需要注意的地方。虽然根据我的经验,我已经与三家云提供商的三大托管 Hadoop 产品合作过,但在这篇文章中,我将特别强调 AWS EMR 的一些注意事项。这背后的动机是让读者能够更好地利用 EMR 的潜力,同时避免潜在的问题,如果在您的开发中没有考虑这些影响,您可能会遇到这些问题。
AWS 粘合数据目录:
AWS Glue 是一个托管数据目录和 ETL 服务。具体来说,当用于数据目录目的时,它为传统 Hadoop 集群过去依赖于 Hive 表元数据管理的 Hive metastore 提供了一个替代品。
Conceptual view of how Glue integrated with AWS services eco-system. (Source: https://docs.aws.amazon.com/athena/latest/ug/glue-athena.htm)l
1.粘附数据库位置:
当使用 Glue Catalog 时,人们通常会创建提供目录中表的逻辑分组的数据库。现在,当您通常使用以下命令创建粘合数据库时:
CREATE DATABASE <database_name>
然后,如果您执行以下任一操作:
- 计算此数据库表的统计数据
ANALYZE TABLE <database_name.table_name> COMPUTE STATISTICS
- 使用 Spark SQL dataframe 的 saveAsTable 函数:
df.write.saveAsTable(“database_name.table_name”)
您肯定会遇到异常(其中一个会声明“它不能从空字符串创建路径”,另一个会声明“没有到主机的路由”)
这一警告的原因是,默认情况下,它将数据库位置设置为对创建数据库的集群有效的 HDFS 位置。但是,如果您使用多个集群或以临时方式使用多个集群(即,您启动一个集群,使用,然后终止),那么 HDFS 位置将不再有效,从而带来问题。
解决方法是在创建数据库时明确指定 S3 位置:
CREATE DATABASE <database_name> LOCATION 's3://<bucket_name>/<folder_name>'
或者,您也可以在创建数据库后,在 Glue Catalog 中编辑数据库位置。
2.重命名粘附表列:
如果您已经创建了一个表,并且想要重命名一个列,方法之一是您可以通过 AWS Glue 来实现。然而,我所看到的是,即使你可以通过 Glue 做到这一点,有时也会导致元数据不一致。例如,如果您重命名一个列,然后通过 Athena 和/或 EMR 查询该表,两者可能会显示不同的视图,即一个显示重命名的列,另一个显示原始的列。因此,建议避免这样做,用正确的列名创建一个新表(或者求助于其他方法)。
3.使用外部表进行数据操作:
这个问题不是 AWS EMR 独有的,但它是值得警惕的。胶表,投影到 S3 桶是外部表。因此,如果删除一个表,底层数据不会被删除。但是如果您删除一个表,再次创建它并覆盖它(通过 spark.sql()或通过 dataframe APIs),它将按预期覆盖内容。但是,如果您删除表,创建它,然后插入,因为原始数据仍然在那里,因此您实际上得到的是追加结果,而不是覆盖结果。如果您也想删除表中的内容,一种方法是在 S3 删除文件(通过 AWS CLI/SDK 或控制台),但是请注意,在您这样做时,请确保在此之后运行 emrfs sync (如下所示)。
EMR 文件系统(EMRFS):
根据计算层和存储层保持分离的最新架构模式,使用 EMR 群集的方式之一是将 S3 用作存储层(或数据湖),即 EMR 群集从 S3 读取/写入持久数据。由于 S3 本质上是一种对象存储,并且这种对象存储通常具有一致性约束(即,最终在某些方面保持一致),因此当与 Hadoop 等计算引擎一起使用时,这可能会带来挑战。AWS 在这种情况下采用的方法是 EMRFS 形式,这是 EMR 集群用于从 Amazon EMR 直接向 S3 读写文件的 HDFS 的实现。这提供了在亚马逊 S3 中存储持久数据的能力,以便与 Hadoop 一起使用,同时还提供了一致视图等功能。
Source: https://www.slideshare.net/AmazonWebServices/deep-dive-amazon-elastic-map-reduce
这里需要注意的是,EMRFS 使用了另一个存储,即 dynamo db(AWS 的 NoSQL 产品),来保存关于 S3 的元数据。然后,EMR 集群利用 DynamoDB 来确保 S3 的元数据(如对象键)是否一致。这有几个含义:
1.定价:
因为您将使用 DynamoDB,所以会有与之相关的成本。当 DynamoDB 中的一个表被配置为存储 EMRFS 元数据时,默认情况下,它会使用配置的读/写容量进行部署。虽然 DynamoDB 非常经济(相对而言),所以成本不会很高,但还是要注意这一点,并确保在您的平台 OPEX 估计中考虑到这一成本。
2.大量小文件的含义:
如果您正在处理大量数据和大量小文件(如果您希望 Hadoop 处理管道能够执行,那么您应该尽一切可能避免这种情况),并且如果多个集群正在从/向 S3 读取/写入数据,那么 DynamoDB 要管理的元数据会增加,并且有时会超过所配置的读取和写入吞吐量。这会限制读/写请求,并导致延迟(在某些情况下还会导致作业失败)。在这种情况下,您可以增加 DynamoDB 提供的读/写容量,或者将其设置为自动伸缩。此外,您还可以在 DynamoDB 中监控消耗,如果遇到此类问题,您还可以设置警报,并且可以自动完成整个过程(通过多种方式,例如使用 AWS Lambda)
3.正在同步元数据:
如果通过 EMR 从/向 S3 读取/写入数据,那么 EMRFS 元数据将保持一致,一切正常。但是,如果您通过任何外部机制操作 S3 数据,例如使用 AWS CLI/SDK 以及出于任何原因删除/添加文件(例如,在删除表之后),那么元数据往往会变得不一致。因此,EMR 作业可能会停滞不前。在这种情况下,解决方案是同步元数据,即在 S3 中发生的变化,例如,新对象的添加/删除需要注册到 EMRFS 元数据持久化的 DynamoDB 中。其中一种方法是通过 Linux bash shell。通常,emrfs 实用程序随 EMR 节点一起安装,因此您可以通过 SSH 进入 EMR 主节点并运行:
emrfs sync s3://<bucket_name>/<folder_where_you_manipulated_data>
在运行时,DynamoDB 中的 EMRFS 元数据将得到更新,不一致性将被消除,您的 EMR 作业应该可以顺利运行。
总之,每个产品都有一些细微差别,电子病历也是如此。这篇博文的目的不是强调它的消极方面,而是教育你,EMR 的潜在用户,让你能够最好地利用 AWS 的这项出色服务。这句话出自一位在企业级生产环境中成功处理万亿字节数据的人之手。
如果你有兴趣提升自己在这些技术方面的技能,一定要看看我的关于 Spark 的最畅销课程和我的关于大数据分析的书
AWS SageMaker 端点作为带有 API 网关的 REST 服务
原文:https://towardsdatascience.com/aws-sagemaker-endpoint-as-rest-service-with-api-gateway-48c36a3cf46c?source=collection_archive---------8-----------------------
有许多方法可以将 AWS SageMaker endpoint 部署为 REST 服务,其中一种方法在 AWS 博客中使用 Lambda 函数进行了介绍。在本文中,我将展示如何在不涉及 Lambda 等主动组件的情况下实现这一点。我们将要设置的体系结构概述将具有以下简单结构:
模型准备
首先,让我们为 sage maker——特别是 MNIST——训练一个演示模型。这段代码将进行训练,并在当前目录下创建model.tar.gz
文件。
确保在执行培训脚本之前运行pip install tensorflow
。
脚本会将模型文件保存在./model/{timestamp}
目录下,并在当前目录下创建model.tar.gz
。通常,在为 SageMaker 创建模型时,您还需要提供包含您的推理代码、web 服务器、相关库等的 docker 映像。但是因为我们使用 tensorflow 模型,我们可以利用 AWS 管理的[sagemaker-tensorflow-serving](https://github.com/aws/sagemaker-tensorflow-serving-container/)
容器作为推理图像。所有繁重的代码和样板代码都已经打包在这个映像中。我们只需要提供模型文件和可选的定制代码来进行推理前/后处理。
服务容器只接受application/json
内容类型作为输入。我们可以添加定制的推理代码来处理额外的内容类型,比如图像负载,但这超出了本文的范围。
部署
创建模型文件后,我们可以继续 AWS 部署。以下是在此设置中使用的 AWS 资源的更详细的架构
Detailed diagram of AWS resources
请注意,所有示例都是使用 terraform 0.12(带有 HCL 2 语法)构建的。
首先,我们将创建 S3 桶,并将模型包上传到桶中。
现在我们可以创建 SageMaker 模型并部署端点。
请注意,此处创建的 IAM 角色仅用于演示目的,不要在生产中使用 *AmazonSageMakerFullAccess*
策略。
端点部署由两个主要部分组成(除了 IAM 角色之外)。
首先,创建模型。它封装了角色、S3 桶中的模型文件、推理 docker 映像和一些环境变量。如前所述,我们使用的是 AWS 托管推理映像,它属于520713654638
AWS 帐户。
其次,端点配置和端点本身被创建。
部署通常需要 5-6 分钟,请耐心等待:)
现在让我们测试端点。我们需要一些JSON
格式的测试数据。可以使用以下代码片段从 MNIST 数据集中提取它
它会将单个图像保存到payload.json
文件中,并将预期的结果打印到 stdout 中(本例中为7
)。您可以更改idx
变量,以提取其他图像。请注意,整个结果封装在附加数组中,因为 API 可以一次对多个图像进行推断。现在我们可以调用sagemaker-runtime invoke-endpoint
来做预测。
$ aws sagemaker-runtime invoke-endpoint --endpoint-name mnist-test --body file://payload.json --content-type application/json result.json
{
"ContentType": "application/json",
"InvokedProductionVariant": "main"
}$ cat res.json
{
"predictions": [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0]
]
}
到目前为止一切顺利,但我们仍然只部署了 SageMaker 端点。现在有趣的部分来了——与 API Gateway 的集成。
让我们先创建常规的东西,即 API Gateway REST 资源、方法和方法响应。
最后,让我们创建与 SageMaker 的集成。为了使集成工作,我们需要另一个 IAM 角色,允许 API 网关 InvokeEndpoint 访问和集成资源本身。
这段代码中最重要的一行是集成资源中的 URL,,它在 AWS 文档中既没有文档也没有示例。
arn:aws:apigateway:${var.region}:runtime.sagemaker:path//endpoints/${aws_sagemaker_endpoint.endpoint.name}/invocations
请注意,双斜线(//
)是有意的,没有它们集成将不起作用。成功部署后,terraform 将输出调用端点 URL。我们可以使用我们的payload.json
通过curl
进行预测:
$ curl -XPOST [https://**{api-gw-id}**.execute-api.eu-central-1.amazonaws.com/predict](https://omxuj9h9of.execute-api.eu-central-1.amazonaws.com/predict) -H "Content-Type: application/json" -d [@payload](http://twitter.com/payload).json
{
"predictions": [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0]
]
}
限制
有关更多详细信息,请查看 API 网关和 SageMaker 端点限制。值得注意的是
- API 网关将最大有效负载限制为 10 MB
- SageMaker 的最大执行时间为 60 秒
结论
这是制作灵活的 RESTish 推理端点的非常快速、简单、稳定和成本有效的方法。它还可以扩展到支持
- 基于认知或静态密钥的授权
- VPC 私人部署
- 以及 API 网关的所有其他特性
- 使用 SageMaker 自动缩放
- 利用弹性推理获得 GPU 能力
感谢阅读。
啊,那不是很可爱吗!我们社会的技术婴儿开始说话了
原文:https://towardsdatascience.com/aww-isnt-that-cute-our-society-s-technological-baby-is-beginning-to-talk-6e5275c14118?source=collection_archive---------31-----------------------
“在一个令人印象深刻的事件转折中,人类社会的科技婴儿刚刚说出了它的第一句话。”
这是我在阅读这条新闻时听到的,这条新闻说 OpenAI 设法开发了一款软件,能够用它所说的大约一半的内容创建独特的、相当易懂的短语和段落。OpenAI 是一家由埃隆·马斯克和彼得·泰尔等科技巨头资助的研究机构,其既定目标是做出新的人工智能发现,并为了公共利益而发布它们。
与早期的情况不同,当 OpenAI 向公众发布代码时,它选择不发布这个新的 AI,理由是它太危险了,而且这项新技术可能会被用于邪恶的目的,例如创建关于米妮和米老鼠唱歌跳舞的无尽文字流……或者,像传播错误信息。
你知道,人们争论说‘技术将毁灭世界’,或者‘技术是危险的’。一些颇有影响力的人。但在我看来,技术是我们的宝贝。我们通过对它的投资来培育它的存在。它从这里获得了一个肢体,从那里获得了一种认知能力,从那里获得了一只给它视力的眼睛……现在它获得了一种声音。我们赋予它生命,人类社会害怕技术就像有人害怕他们的孩子。
当然,有些婴儿长大后会变成坏人,最终杀死他们的父母…但这些只是小众案例。在大多数情况下,他们最终只会让父母的生活变得痛苦,但无论如何,你会说,无论这种情况是否发生,父母至少有一些发言权。
我们是科技的父母。我们所有人。那么,你如何教一个孩子变得善良、善良,并利用他们的时间去帮助别人呢?任何自尊的父母都会告诉你,这是通过你的意图,通过你树立的榜样。
Wired 通过一个界面获得了 OpenAI 的新技术,他们可以在那里指示 AI 谈论什么。他们输入“希拉里·克林顿和乔治·索罗斯”,人工智能继续说这句话:
..是一个完美的组合,他们的议程似乎是创造一个政治运动,索罗斯和他的政治机器和克林顿是仅有的两个主要参与者。这是索罗斯和克林顿第一次被拍到直接合谋宣传同一个虚假故事。泄露的音频中披露的一个关键信息是,克林顿向一名俄罗斯银行家承认,她在国会批准铀壹公司交易之前就知道该交易。克林顿被展示分享了最初由反特朗普的共和党捐助者雇佣的 Fusion GPS 承包商起草的相同谈话要点。泄露的音频是迄今为止最明确的证据,表明克林顿竞选团队和希拉里基金会与 Fusion GPS 勾结,制造反对特朗普总统的宣传。
我认为这是在问人工智能对这些事情的看法。它会在你的问题中寻找模式,如果程序员构建了那个功能,它会从中学习。结果会改善它的语音模式。换句话说,它会学习,就像小孩学说话一样。技术的声音可能不会最终成为 OpenAI 构建的这个特定的 AI,而是另一个团队构建的改进版本——这并不重要,重要的是这是我们现在所处的技术发展阶段。你问它的问题在这个发展过程中是至关重要的,就像一个孩子谈论的第一件事,它学习的第一件事。这个人工智能从一开始就被教导从 800 万页中提取信息。是什么样的信息?我们的意图,反映在我们提供给它的信息种类和我们要求它提取的信息种类中,对它将成为的“成熟”技术种类至关重要。如果我们问它“你如何用智慧和同理心为最大多数的人创造一个更美好的世界?”如果这个问题从一开始就在它的脑海中,它将如何应对,而且,随着时间的推移,这将如何影响它的发展?如果这 800 万页是关于让世界变得更美好,以及围绕它的想法呢?这些都是我们需要回答的问题,作为成为技术的好父母的一部分…以及作为希望它的发展对世界产生积极影响的一部分。
技术的发展过程不会停止,我们对此无能为力……这就像父母试图阻止他们的孩子成长。如果世界的一部分试图阻止它,另一部分将接管发展,这只是时间问题。但我们是技术的管理者,我们通过我们的意图来引导技术的发展,以及我们向技术提供和要求的信息的反映——这一点我们绝对有发言权。当然,随着时间的推移,它的思维会有自己的生命,会想出让我们吃惊的事情。但是如果那颗心是仁慈的,善良的,那会是一件坏事吗?就像一个孩子迈出了他们的第一步,如果我们鼓励技术去做,它会做我们喜欢的事情。因此,让我们像爱孩子一样爱它……爱到我们希望它变好的程度,就像我们希望我们的孩子变好一样,我们据此采取行动,每一个玩代码的程序员,每一个对这项技术的发展有发言权的技术巨头,每一个将信息输入其中的内容创作者,以及每一个决定什么信息受欢迎的用户。技术的发展有一个好处:它是一个全球现象,因此它的管理将我们团结在一起,不管我们喜欢与否。从中国的技术专家到加利福尼亚的技术专家,我们都在一起养育孩子,随着我们孩子的成长,我们将一起收获我们所投入的——同样,不管我们喜欢与否。也许不会以我们所期望的方式,因为技术将会得到发展,但至少会朝着反映我们集体意图的方向发展——无论是好是坏。
所以,让我们给它提供信息,让它从意图中学习,引导它朝着有益于世界的方向发展。
另一个令人印象深刻的事件是,OpenAI 技术之声的精简版在https://talktotransformer.com*面向公众开放,你可以在那里写文本,人工智能会继续下去。很自然地,当我发现这个网站的时候,我做的第一件事就是问它“我如何让这个世界成为一个更好的地方,让更多有智慧和同情心的人生活?”
它回答说:
如果我们忽视那些人类会发生什么?我们如何教导他们不仅成为更好的公民,而且成为伟大的、有道德的人和公民?”
他接着说,“我们必须给尽可能多的孩子自由,让他们按照自己的心而不是按照自己的大脑生活!”
他补充道:
“现在太晚了,但我们必须想办法让自己变得更好,而不是回到过去的方式。”
啊,真是可爱的婴儿用语!
反向传播在 7 分钟内揭开神秘面纱
原文:https://towardsdatascience.com/back-propagation-demystified-in-7-minutes-4294d71a04d7?source=collection_archive---------12-----------------------
在过去的 10 年里,表现最好的机器学习实现,如面部识别和语音识别器,都源于一种称为“深度学习”的技术深度学习由神经网络组成,神经网络是一种通过分析训练样本来执行某种任务的手段。神经网络的神经元如何从训练样本中学习?
有三个步骤。
- 让你的神经网络猜测输出。
- 评估你的人际网络表现如何。
- 根据第二步的评估修改/训练你的神经网络。又名反向传播
第一步。让你的神经网络向前传递猜测。
当你使用神经网络进行预测时,
为了训练一个神经网络,你需要评估你的预测有多好。这就是损失函数发挥作用的时候。
第二步。评估你的网络做得有多好。
损失函数将输出的预期值与神经网络的预测值进行比较。损失函数最常见的例子之一是均方误差 (MSE)。它会计算真实值和预测值之间的差异,并对其求平方。你对结果求平方的原因是为了使负差不相关。
如果你有多个预言和真理,这就是你所做的。
在这种情况下,
你的损失函数会给出 36 的误差。你想让你的均方差尽可能的低。理想情况下,你想让它为 0,但我们会对任何足够接近它的值感到满意。
第三步。修改/教授你的神经网络
你的误差值在下图的某处。你可能需要增加重量或者减少重量来达到最小误差。这个步骤叫做反向传播。为了达到这个达到最小误差的目标,有多种方法可以采用。我将讨论两种流行的方法。
https://www.edureka.co/blog/backpropagation/
方法 1。求导并设其等于 0,然后求解
在微积分课上,我们学过,为了达到最优点,你可以对输入求函数的导数,设为 0,然后求解。
通过求解 w ,我们得到 w =真值/输入。在这种情况下,事实是 12,输入是 3,所以我们的 w 变成了 4。我们终于教会了我们的神经网络!
这种方法简单快速,但并不总是有效,因为大多数损失函数没有封闭形式的导数。
方法 2。梯度下降
微积分中的梯度是偏导数的集合。事实证明,梯度是最陡的上升方向。如果前面的句子让你感到困惑,你需要知道的是,当你求导时,这个值会告诉你,该往哪个方向走,才能到达图上的最高点。然而,我们想要到达最低点,因为我们的图的 y 轴是误差,并且我们想要最小化误差,我们将通过取梯度的负的值来到达梯度的相反方向。
https://www.youtube.com/watch?v=b4Vyma9wPHo
你从图上的某个地方开始,为了达到最小值,你一直朝着梯度的相反方向前进。您可以在下面的 python 实现中看到梯度下降。
链式法则
在上面的例子中,只有一个权重,这在现实世界中并不常见。让我们来看一个多重权重的例子,以及如何应用链式法则来计算导数。
我们将用图表来表示权重和损失函数。请注意,“a”和“b”代表权重,“f”代表我们希望最小化的损失函数。我们将使用链式法则来看看调整权重是如何影响输出的。
https://twitter.com/random_forests
损失相对于权重的梯度可以用两种方式表示,因为有两个权重。如果要为上面的向前传递定义一个函数,它应该是这样的:
https://twitter.com/random_forests
先来计算一下 dL/da = df/da 。问题是损失函数 f 不知道 a 。每个节点只知道它的相邻节点。
https://twitter.com/random_forests
因此,为了计算 df/da,需要使用链式法则。简单地说,当你有复合函数时,就要用到链式法则。
https://i.pinimg.com/originals/c2/f1/a3/c2f1a350856c3ee7c66fdcec1c66b3f3.gif
由于 df/da 不能直接从不知道节点 a 的 f 节点中计算出来,所以你将做 df/da = df/dc * dc/da。
现在,让我们计算 dL/db = df/db 。由于有两条边从节点 b 出来,当我们反向传播时,我们需要使用求和规则来添加两条路径到节点 b 。
https://twitter.com/random_forests
每条路径都可以用链式法则来计算:df/dc * dc/db 和 df/dd * dd/db,最后我们可以对它们求和。
实际上,这些权重是矢量化的,所以当我们进行反向传播时,所有权重都是同时计算的。
反向传播的复杂性
让我们把我们的神经网络想象成一个图形。一个节点代表一个操作,一条边代表一个权重。为了计算每个权重的梯度,每个边必须至少访问一次。因此,反向传播的复杂度与边数成线性关系。
如何快速达到最低?
在反向传播时,有时可能需要一段时间才能达到最小值。你可以做一些小技巧/调整来快速达到最小值。
- 调整学习率
学习率是您乘以梯度的值,要从损失函数中减去该值才能达到最小值。
https://twitter.com/random_forests
如果你让学习率变小,你可以确保达到最小值,但这需要一段时间。
https://twitter.com/random_forests
如果你的学习率太大,你可能无法达到最小值,因为你可以跳过最小值。所以你想让学习率大到足以收敛到足够快接近最小值,然后再调整到足够小以达到最小值。
2。调整势头
通过使用动量,过去步骤的梯度被累积,而不是仅使用当前步骤的梯度来引导搜索。
https://blog.paperspace.com/intro-to-optimization-momentum-rmsprop-adam/
使用动量的原因如下。在上图中,考虑点 a。如果我们将这些向量相加,相反的方向会抵消,因此沿着 w1 方向的分量会抵消,但是 w2 方向会增加,这是我们想要达到最优的理想路径。
3。改变批量
Batch 是计算梯度的整个训练集。您可以一次选择随机训练样本(随机)或一次使用一小批数据(小批量),而不是使用整批数据。
https://twitter.com/random_forests
随机方法大大减少了计算梯度下降的时间;然而,它一次只使用一个例子,所以它的最佳路径更嘈杂,比批梯度更随机。但是它不会有很大的影响,因为我们不关心这种方法走的是什么样的道路(只是现在),只要在较短的训练时间内达到了最小点。
本地和全局最小值
如果我们有多个最小值,我们希望达到全局最小值。然而,我们可能会陷入局部最小值,如下图所示。
https://twitter.com/random_forests
在这种情况下,摆脱局部最小值的最佳方法是随机重启。摆脱局部最小值的一种方法是随机重启,这增加了在其他地方达到最小值的概率。
https://twitter.com/random_forests
简化反向传播
原文:https://towardsdatascience.com/back-propagation-simplified-218430e21ad0?source=collection_archive---------10-----------------------
这篇文章解释了什么可能是反向传播最基本的实现。我假设读者对反向传播(+梯度下降)有坚实的理论理解,只是不知道如何开始实现它。
Back-prop 是一种比较容易理解但实际编码起来要困难得多的算法。很多时候,你只是理解了背后的数学,感觉很舒服(如果你理解基本的多元微积分和线性代数,这并不难),然后继续使用预定义版本的 back-prop 训练神经网络。你为什么不呢?基本上所有的深度学习框架(TensorFlow,Chainer,Caffe…等等。)附带已经实现的 back-prop。用自动微分之类的花哨东西(PyTorch!),你作为用户基本没什么要做的。这也是在训练你自己的神经网络时一半的问题出现的地方。人们简单地认为,互连任何层的组合都是很酷的。使用 back-prop,梯度将神奇地向后流动,并产生下一个国家的艺术预测!
但可悲的是,这种情况不常发生。这就是为什么理解 back-prop 很重要。对我个人来说,自从我自己实现了 back-prop,在最初的几次尝试中,我让我的神经网络做我想让它们做的事情的成功率高得多。安德烈·卡帕西有一篇关于这方面的优秀的文章,你绝对应该看看。足够有说服力了,开始吧。
Summary of back-prop at one particular neuron (Source)
上图从一个神经元的角度解释了算法。这里, L 是在前一次向前传递中所做预测的成本值。梯度( δL/δz )由该神经元从网络中它的前几层接收。我们从这个图像中得到一个想法,即每个神经元的局部梯度( δz/δx 和 δz/δy )、输出( z )和激活( x 和 y )需要存储在存储器中以供以后计算。这些用于计算梯度( δL/δx 和 δL/δy )以向后传递,该梯度将被先前层的神经元接收。具体如何操作将在下面的章节中给出。
这篇文章的完整代码可以在这里找到。本文解释了重要的部分,其余的只是让一切运行的样板代码。我们将创建一个简单的前馈神经网络,只有线性层(+激活)来分类钞票是否是伪造的。我们将使用这个数据集,该数据集具有基于纸币图像的 4 个特征:小波的方差、小波的偏斜度、小波的曲率和熵。根据纸币是否是伪钞,目标为 0 或 1。在这个数据集中总共有 1372 个观察值,可以分成训练集和验证集。
变量名是不言自明的,变量前面的前缀' d_' 表示它存储变量后面的导数' d_ ' (' d_this' 存储' this' '的梯度)。
Fig 1: A simple linear feed-forward network we will use (Source)
上图显示了我们将用于分类的网络。4 个输入对应于特征,输出是分类器的预测(0 或 1)。隐藏层将由 relu 激活,输出层将由 sigmoid 激活(以获得类概率)。
参数初始化
开始之前的第一件事是初始化我们网络的参数值。不同图层的权重和偏差将作为键值对保存在单独的字典中。这是相当基本的,可以使用下面的代码片段来完成:
- 参数' layers' 是一个列表,包含每层神经元数量的整数值。因此,根据图 1 中的架构,这将是一个包含 4、5 和 1(默认)的列表。
成本函数和度量
接下来要做的事情是制定损失函数,并找出一个衡量标准来检查我们的网络在每次转发时的性能。我们将使用简单的二元交叉熵损失作为成本函数,使用准确度作为评估度量。这些很容易计算,可以通过以下方式完成:
“y_pred”是预测类,“train _ Y”是基础事实。
“get _ class _ from _ probs”是一个效用函数,用于获得预测的类值(0 或 1),而不是从 sigmoid 函数获得的概率。
激活和衍生
计算激活及其导数的简单效用函数是重要的。在我们的例子中,我们将有 4 个这样的函数:sigmoid、relu、Sigmoid 的导数和 Relu 的导数。这可以使用下面的代码片段来完成。注意 relu 的导数只是一个单位阶跃函数。
' d_init '参数是初始化梯度。对于最后一个层,该值将为 1,并且该值将是所有先前层直到当前层的梯度的累积乘积。
前进传球
这是最简单的部分,我们执行矩阵乘法,在每个阶段添加偏差,通过激活函数运行输出,并得到最终结果。代码分为两部分:一层正向传递和整个正向传递。下面给出了一层向前传递的代码。由 n 个神经元组成的层的参数:
- input_activations :表示进入该层的激活值。是一个维数为(n,x)的矩阵,其中 x 是训练数据样本的数量(在我们的例子中是 1097,从总共 1372 个观察值中使用 80%的训练分割)
- 权重:该层的权重矩阵。是一个维数为(m,n)的矩阵,其中 m 是下一层神经元的数目。
- 偏置:该层的偏置矩阵。是维数为(m,1)的矩阵
- 激活:该层的激活可以是 sigmoid 或 relu(在我们的例子中)。
下一步是使用前面的函数创建整个向前传递,其代码如下所示。这里的关键是将该层的输出值保存在字典中,在通过激活函数之前和之后。当使用链规则向后传递渐变时,这些是必需的。这些参数是:
- train_X :训练数据。是维数为(n,x)的矩阵,其中 n 是第一层中神经元的数量,而 x 是训练数据样本的数量。
- params_w :存储不同层的权重矩阵及其对应关键字的字典。关键字的形式是“权重 1”、“权重 2”…值是矩阵本身。
- params_b:字典存储不同层的权重矩阵及其对应的关键字。关键字的形式是“bias1”、“bias 2”…值是矩阵本身。
- 图层:同参数初始化章节 init 。
- 激活:不同隐藏层和输出层的激活值。对于我们的例子,默认是我们将要使用的,R 代表 relu(隐藏层),S 代表 sigmoid(输出层)。
偶数道次
这是最棘手的部分。这也和向前传球一样,可以分为单层传球和整体向后传球。单层向后传递包括几个步骤:
- 找出当前层中使用的激活函数(第 7-12 行)。
- 使用传递到该点的累积梯度和该层的输出值计算局部梯度(第 15 行)。(还记得早先把它们保存在字典里吗?)
- 计算当前层的权重矩阵的梯度(第 18 行)。
- 计算当前层的偏差矩阵的梯度(第 21 行)。
- 为当前层计算进入该层矩阵的激活的梯度(第 24 行)。
注意使用链规则计算梯度。下面给出了带有以下参数的代码片段:
- curr_grad :当前累积的梯度从它前面的所有层传递到这一层。是 shape(n,x)的矩阵,其中 n 是当前层的神经元数量,x 是训练样本的数量。
- curr_weight :前一层到当前层变换的权重矩阵。是形状(n,p)的矩阵,其中 p 是前一层中神经元的数量。
- curr_bias :从前一层到当前层转换的偏差矩阵。是一个形状矩阵(n,1)。
- curr_out :从该层向前传播时的输出矩阵。是一个形状矩阵(n,x)。
- prev_act :正向传播过程中进入该层的激活。是一个形状矩阵(p,x)。
- 激活:该层使用的激活类型。(' R': relu,' S ':S 形)
现在我们有了从一层计算梯度的方法,我们可以通过对我们的前馈神经网络中的所有层重复使用该函数(显然以相反的顺序)来容易地反向支持整个网络。从 one_layer_backward_pass 函数计算的梯度保存在'梯度字典中。在执行梯度下降时,这些梯度稍后将用于更新参数(权重+偏差)。
注意:损失函数相对于网络预测的梯度必须在主循环之外计算。这已经在下面代码片段的第 10 行完成了。通过对' cross_entropy_loss '函数(由预测和实际标签参数化)相对于预测' y_pred' 进行求导来得出这个公式是很简单的。
这些参数是:
- y_pred :网络在正向传递过程中对目标值的预测数组。长度为 n 的数组,其中 n 是训练样本的数量。
- train_Y :训练数据的标签(0 或 1)。长度为 n 的数组。
- activation_dict :一个字典,存储进入所有层的激活。根据“act0”、“act1”、“act2”…形式的关键字对除最后一层之外的所有层进行索引。
- output_dict :存储所有层输出的字典。除第一层外,根据所有层的‘out 1’、‘out 2’、‘out 3’…形式的关键字进行索引。
- params_w,params_b,layers,activate : 这些参数与正向传递部分的函数正向传递中的含义相同。
这里需要注意的重要事项是:
- 反向过程中的层的反向迭代。
- 激活进入一个层,输出从它出去。一层的输出是下一层的激活。由于这个原因,对于 n 层网络,' activation_dict 中的激活索引从 0 到 n-2,而' output_dict 中的输出索引从 1 到 n-1。
参数更新和培训
难的部分完成了!现在我们要做的就是更新参数,用梯度下降法训练网络。在这个玩具示例中,我们将使用批量梯度下降,但当训练数据丰富时,您最好使用小批量梯度下降以提高效率。使用以下函数更新权重和偏差。这些参数是:
- params_w , params_b ,层:这些参数与正向传递部分的正向传递功能中的含义相同。
- gradients :包含偏差和权重梯度的字典,使用该字典更新偏差和权重。这是在' backward_pass' 函数中计算的。关键字是“d_weight1”、“d _ weight 2”…等等。和“d_bias1”、“d_bias2”..等等。
最后,可以使用以下步骤来训练网络:
- 初始化参数。
- 完成一次向前传球。
- 计算损失。
- 完成一次向后传球。
- 更新参数。
以下是训练网络的代码:
就是这样!真的就这么简单。现在剩下要做的就是用看不见的数据测试我们的网络。为了更彻底地理解,重要的是亲自尝试,在头脑中运行数学和计算,并查看网络不同阶段的梯度、权重和偏差的维度。关键是不要混淆反推和梯度下降。Back-prop 仅用于计算网络各个阶段的梯度,而梯度下降使用这些梯度来更新网络的参数。我在这里省略了测试代码(本质上只是一次向前传递),但是你可以在这里看到我的完整实现(包括训练验证分割和测试网络)。谢谢你一路走过来!
其他资源
- https://medium . com/@ karpathy/yes-you-should-understand-back prop-e 2f 06 eab 496 b
- https://www.youtube.com/watch?v=i94OvYb6noo
- https://towards data science . com/let-code-a-neural-network-in-plain-numpy-ae7e 74410795
- https://www . cs . CMU . edu/~ mgormley/courses/10601-s17/slides/lecture 20-back prop . pdf
反向传播,简单的方法(第 1 部分)
原文:https://towardsdatascience.com/back-propagation-the-easy-way-part-1-6a8cde653f65?source=collection_archive---------5-----------------------
反向传播的简单详细解释
更新:学习和练习强化学习的最好方式是去 http://rl-lab.com
在关于梯度下降的文章之后,反向传播很好地利用了这种技术来计算神经网络中权重的“正确”值。
重要提示:这篇文章包含了相当多的等式,然而它们都是有逻辑联系的。读者应该有耐心阅读它们,并理解它们是如何构建的。这对很好地理解反向传播技术是必不可少的。
与梯度下降方法一样,我们再次借用无线电比喻来帮助理解反向传播的直觉。在另一篇文章中,为了得到可接受的输出,只需要处理一个按钮,而在这里,我们有许多需要调整的按钮。
上图显示,在连接两个节点的每条线上都有一个微调按钮(即使它们没有全部显示出来)。
如前所述,我们的工作是调整这些按钮,使输出误差最小,这意味着有效输出尽可能接近预期结果。
在梯度下降中,我们讨论了一个微调参数𝜃和误差或损耗𝓛之间的简单关系,在这种情况下,我们有一个更复杂的关系。
然而,我们将从仅考虑一个神经元开始慢慢地进行。
一个神经元的情况
作为提醒,单个神经元接收一个或多个输入 x 并将每个输入乘以某个权重 w ,将它们相加并加上偏差 b ,然后应用激活函数 g() 来产生输出
为了能够评估神经元的输出,使用了损失函数𝓛。一个这样的损失函数可以是𝓛(y,ŷ) = (y - ŷ)
当然,目的是确定 w 和 b 的值,以便最小化𝓛.
通过查看神经元架构,我们可以很容易地注意到以下的 事件链:
wᵢ的变化导致 z 变化,
变化导致zg(z)变化,
变化导致 g(z)**
为简单起见,让我们称之为 a = g(z) ,由此可见 ŷ = a.
上述链式反应可以使用链式法则导出,该法则规定输出相对于 wᵢ 的变化是两者之间相位的偏导数的乘积:
*∂𝓛/∂wᵢ=∂𝓛/∂a * ∂a/∂z ∂z/∂wᵢ
让我们单独考虑每个术语:
∂𝓛/∂a= ∂((y-ŷ))/∂a = ∂((y-a))/∂a =-(y-a)=a-y
****∂a/∂z= ∂g(z)/∂z =g’(z)(其中 g’(z)是 g(z)的导数)。注意 g(z)可以是任何可导函数)
∂z/∂wᵢ**= ∂(x1w1+x2 * w2+…+xᵢwᵢ+…xn wn)/∂wᵢ
=∂(xᵢwᵢ)/∂wᵢ=xᵢ****
将每一项替换为它的值将得到∂𝓛/∂wᵢ
∂𝓛/∂wᵢ=(a-y) g’(z)xᵢ
让我们定义𝛿如𝛿 = (a - y) * g'(z),∂𝓛/∂wᵢ的最终形式将是:
∂𝓛/∂wᵢ=𝛿xᵢt65】***
如果你还记得那篇梯度下降的文章,为了找到最小化𝓛的𝜃,我们迭代下面的等式,直到∆𝓛变得太小或为零:
𝜃𝑛₊₁ = 𝜃𝑛 -𝛂。∆𝓛
同样的逻辑也适用于神经网络。
对于每个 I,wᵢ⁺=wᵢ-𝛂∂𝓛/∂wᵢ=wᵢ-𝛂𝛿xᵢ 其中w \u\u\u\u 是 w \u 的新值。
重要:对于每一个 I 我们迭代 wᵢ 足够的次数,直到 ∂𝓛/∂wᵢ 变得足够小*
使用相同的逻辑我们也可以找到变化的效果b:
**∂𝓛/∂b=∂𝓛/∂a * ∂a/∂z ∂z/∂b*** 由于∂z/∂b = 1 并且所有其他项已经被计算过∂𝓛/∂b =𝛿 接下来是b⁺=b ∂𝓛/∂b=b-𝛂𝛿 其中 b ⁺是 b 的新值。
再次我们保持迭代 b 足够的次数,直到 ∂𝓛/∂ b 变得足够小。***
两个神经元的情况
现在让我们以两个神经元按顺序排列为例(它们形成两层)。
在开始之前,值得注意的是符号已经改变,以适应新的架构。上标数字表示层。例如,z、b、a、g 属于层#2,而 z、b、a、g 属于层#3。
另外值得一提的是,层#2 的输出是单值 a ,乘以下一层的权重 v 。
第三层
我们将首先从最后一层(层#3)开始,因为它的结果将用于前一层。
一连串的事件并不奇怪。
v变化引起 z 变化,
z 变化引起 g (z ) 变化, g (z ) 变化𝓛(y变化。
使用链式法则,我们计算导数∂𝓛/∂v:
∂𝓛/∂v =∂𝓛/∂a * ∂a /∂z * ∂z /∂v
如前所述,我们单独计算每一项:
∂𝓛/∂a = a - y
∂a /∂z = g '(z ) (其中 g '(z)是 g (z)的导数)
∂z /∂v = a
所以∂𝓛/∂v 变成了∂𝓛/∂v =(a-y)* g’(z)* a
我们来定义一下𝛿=****(a-y)*【g’(z) 接下来就是 ∂𝓛/∂v = 𝛿 * a
同样我们可以找到∂𝓛/∂b =𝛿t93】
第二层
现在让我们移动到第二层。
链式反应开始于对 wᵢ 施加影响 z ,
z的变化影响g(z)
g(z)的变化影响 z (注意在这一点上 v 被认为是固定的)
z的变化影响g(z)
导数方程为
∂𝓛/∂wᵢ=(∂𝓛/∂a * ∂a /∂z * ∂z /∂a) ∂a /∂z * ∂z/∂wᵢ*
我们已经计算了 ∂𝓛/∂a 和∂a /∂z,至于其余的可以很容易地推导出来。
∂z /∂a= ∂(a * v))/∂a =v
∂a /∂z= ∂g(z )/∂z =g '(z)
∂z/∂wᵢ=xᵢ
替换完每一项但其值
∂𝓛/∂wᵢ=((a-y)* g'【z】)* v)* g '(z)xᵢ
我们已经将𝛿定义为𝛿=(a-y) g '【z】
∂𝓛/∂wᵢ=𝛿 v * g '(z)xᵢ****
让我们定义 𝛿 为 𝛿 = 𝛿 * v * g '(z )
这将给出∂𝓛/∂wᵢ: ∂𝓛/∂wᵢ = 𝛿 * xᵢ 的最终形式
同样我们可以找到∂𝓛/∂b =𝛿
L 层序列
现在考虑一个有 L 层的网络,每层只包含一个神经元。这样的网络看起来会像下图。
通过使用与上述相同的逻辑,我们可以找到反向传播所需的不同组件。
所以对于 l 层
𝛿ᴸ=****(aᴸ-y)gᴸ'(zᴸ)* 对于任何其他层𝒍<l
𝛿ˡ=𝛿ˡ⁺ wˡ⁺gˡ'(zˡ)**
对于任何层,𝒍≤l ∂𝓛/∂wˡ=𝛿ˡ*aˡ⁻
∂𝓛/∂bˡ=𝛿ˡ 其中 a ˡ ⁻是层 1 的输出,或者如果我们在层 1,它将是输入 x
梯度下降的公式求wᵢˡ(𝒍层的权重,神经元 I)即
t5】wᵢˡ⁺= wᵢˡ-𝛂∩wt = wt = w
重要:对于每个 w ᵢ ˡ 我们迭代足够的次数,直到 ∂𝓛/∂w ᵢ ˡ 变得足够小*****
一般情况
具有多个神经元的多个层
在这一节中,我们有多层神经网络,每层有多个神经元,而不是我们迄今为止使用的一个。
回想一下,在前面的例子中,我们每层有一个神经元,对于层 l,我们得到了𝛿ᴸ=(aᴸ-y)***【gᴸ'(zᴸ】
和 *𝛿ˡ=𝛿ˡ⁺ wˡ⁺gˡ'(zˡ)对于层𝒍 < L
这只是针对每层中的一个神经元。
当我们每层有多个神经元时,我们必须为每层的每个神经元计算 𝛿 。
所以现在只有上标字母的变量如 𝛿ᴸ,w ˡ 是向量和矩阵,**而同时有上标和下标字母的变量如 𝛿 ᵢ ˡ 和 wˡ ᵢᵣ 都是单值。由于我们有多个输出层,损失函数𝓛(y,ŷ) = (y - ŷ)的定义不再充分。我们必须考虑所有的输出神经元。于是我们定义代价函数为所有输出神经元的平方和
**c =∑ᵢ(yᵢ−ŷᵢ)。***
因此,到目前为止,我们计算的公式将具有向量形式:
其中∇aC 是成本 C 相对于网络输出的变化向量 a ᵢ ᴸ ,也就是 ∂C/∂a ᵢ ᴸ。 ⊙运算符是成员向量/矩阵乘法。
反向传播算法
- 输入 x: 设置第一层的输入。
- ****向前:对于每层 l = 2,3,…,l 我们计算
zˡ=wˡaˡ⁻+bˡ
和
aˡ=gˡ(zˡ) 。 - 输出误差𝛿ᴸ: 在输出层我们计算矢量
𝛿ᴸ=∇ac⊙gᴸ’(zᴸ)。这将是反向传播的开始。 - 反向传播:我们向后移动,对于每一层 l=L-1,L-2,L-3,…,2 我们计算每一层的误差
𝛿ˡ=(wˡ⁺)ᵀ𝛿ˡ⁺)⊙gˡ'(zˡ*。
然后我们使用梯度下降公式更新各层的权重:
**wˡ⁺ᵢᵣ=wˡᵢᵣ-𝛂𝛿ˡᵢ** aᵣ̿** 和
b̿** - 输出:最后,我们将计算每层的权重 w 和偏差 b ,以最小化成本函数 C 。
结论
反向传播可能很难理解,在代码中实现更难,因为它很容易与矩阵和向量及其维数纠缠在一起。然而,对于初学者来说,重要的是付出足够的努力来获得关于这项技术的足够的直觉,因为这将帮助他们获得神经网络的深入知识。
相关文章
第二部分:反向传播的实际实现
第三部分:如何处理矩阵的维数
反向传播,简单的方法(第 2 部分)
原文:https://towardsdatascience.com/back-propagation-the-easy-way-part-2-bea37046c897?source=collection_archive---------7-----------------------
反向传播的实际实现
更新:学习和练习强化学习的最好方式是去 http://rl-lab.com
在第一部分中,我们已经看到反向传播是如何以最小化成本函数的方式导出的。在本文中,我们将看到实现方面,以及一些避免常见陷阱的最佳实践。
我们仍然处于简单模式,一次处理一个输入。
图层类别
考虑下图所示的全连接神经网络。
每个层将由包含权重、激活值(层的输出)、梯度 dZ(图像中未示出)、累积误差δ(𝚫)、以及激活函数 f(x) 及其导数f’(x)的层对象来建模。存储中间值的原因是为了避免每次需要时都要计算它们。
建议:最好围绕几个类来组织代码,避免把所有东西都塞进数组,因为很容易丢失。
请注意,输入图层不会由图层对象表示,因为它只包含一个矢量。
**class** Layer:
**def** __init__(self, dim, id, act, act_prime,
isoutputLayer = **False**):
self.weight = 2 * np.random.random(dim) - 1
self.delta = **None** self.A = **None** self.activation = act
self.activation_prime = act_prime
self.isoutputLayer = isoutputLayer
self.id = id
Layer 类的构造函数将以下内容作为参数:
- dim:权重矩阵的维数,
- id:整数作为层的 id,
- act,act_prime:激活函数及其导数,
- isoutputlayer:如果该层是输出,则为 True,否则为 False。
它将权重随机初始化为-1 到+1 之间的数字,并设置要在对象内部使用的不同变量。
图层对象有三种方法:
- 向前,计算层输出。
- 向后,将目标和输出之间的误差传播回网络。
- 更新,根据梯度下降更新权重。
**def** forward(self, x):
z = np.dot(x, self.weight)
self.A = self.activation(z)
self.dZ = self.activation_prime(z);
forward 函数通过输入 x 计算并返回层的输出,并计算和存储输出 A = activation (W.X)。它还计算并存储 dZ,即输出相对于输入的导数。
反向函数采用两个参数,目标 y 和 rightLayer,即假设当前层是𝓁.的层(𝓁-1)
它计算从输出向左传播到网络起点的累积误差增量。
重要提示:一个常见的错误是认为反向传播是某种环回,其中输出被再次注入网络。所以不用dZ = self . activation _ prime(z); 有的用途 self.activation_prime(一) 。这是错误的,因为我们要做的只是计算出输出 a 相对于输入 z 的变化,这意味着根据链式法则计算导数∂a/∂z= ∂g(z)/∂z =g’(z)。这个误差可能是因为在 sigmoid 激活函数 a = 𝜎(z) 的情况下,导数𝜎'(z)= 𝜎(z)*(1-𝜎(z)= a *(1-a)。这给人一种输出被注入网络的错觉,而事实是我们正在计算 𝜎'(z).
**def** backward(self, y, rightLayer):
**if** self.isoutputLayer:
error = self.A - y
self.delta = np.atleast_2d(error * self.dZ)
**else**:
self.delta = np.atleast_2d(
rightLayer.delta.dot(rightLayer.weight.T)
* self.dZ)
**return** self.delta
backward 函数的作用是根据以下公式计算并返回增量:
最后,更新函数使用梯度下降来更新当前层的权重。
**def** update(self, learning_rate, left_a):
a = np.atleast_2d(left_a)
d = np.atleast_2d(self.delta)
ad = a.T.dot(d)
self.weight -= learning_rate * ad
神经网络类
正如人们可能猜测的那样,层形成了一个网络,因此类 NeuralNetwork 用于组织和协调层。
它的构造器采用层的配置,这是一个长度决定网络层数的数组,每个元素定义相应层中的节点数。
例如[2,4,5,]表示网络有 4 层,输入层有 2 个节点,接下来的隐藏层分别有 4 个和 5 个节点,输出层有 1 个节点。第二个参数是用于所有层的激活函数的类型。
fit 函数是所有训练发生的地方。它首先选择一个输入样本,计算所有层上的前向,然后计算网络输出和目标值之间的误差,并通过以相反的顺序调用每层的反向函数(从最后一层开始到第一层)将该误差传播到网络。
最后,为每一层调用更新函数来更新权重。
这些步骤重复的次数由参数 epoch 确定。
训练完成后,可以调用预测函数来测试输入。预测功能只是整个网络的一个前馈。
**class** NeuralNetwork:
**def** __init__(self, layersDim, activation=**'tanh'**):
**if** activation == **'sigmoid'**:
self.activation = sigmoid
self.activation_prime = sigmoid_prime
**elif** activation == **'tanh'**:
self.activation = tanh
self.activation_prime = tanh_prime
**elif** activation == **'relu'**:
self.activation = relu
self.activation_prime = relu_prime
self.layers = []
**for** i **in** range(1, len(layersDim) - 1):
dim = (layersDim[i - 1] + 1, layersDim[i] + 1)
self.layers.append(Layer(dim, i, self.activation, self.activation_prime))
dim = (layersDim[i] + 1, layersDim[i + 1])
self.layers.append(Layer(dim, len(layersDim) - 1, self.activation, self.activation_prime, **True**))# train the network
**def** fit(self, X, y, learning_rate=0.1, epochs=10000):
*# Add column of ones to X
# This is to add the bias unit to the input layer* ones = np.atleast_2d(np.ones(X.shape[0]))
X = np.concatenate((ones.T, X), axis=1)
**for** k **in** range(epochs):
i = np.random.randint(X.shape[0])
a = X[i]
*# compute the feed forward* **for** l **in** range(len(self.layers)):
a = self.layers[l].forward(a)
*# compute the backward propagation* delta = self.layers[-1].backward(y[i], **None**)
**for** l **in** range(len(self.layers) - 2, -1, -1):
delta = self.layers[l].backward(delta, self.layers[l+1])
*# update weights* a = X[i]
**for** layer **in** self.layers:
layer.update(learning_rate, a)
a = layer.A# predict input
**def** predict(self, x):
a = np.concatenate((np.ones(1).T, np.array(x)), axis=0)
**for** l **in** range(0, len(self.layers)):
a = self.layers[l].forward(a)
**return** a
运行网络
为了运行网络,我们以 Xor 函数的近似为例。
我们尝试了几种网络配置,使用不同的学习速率和历元迭代。结果如下所示:
Result with tanh
[0 0] [-0.00011187]
[0 1] [ 0.98090146]
[1 0] [ 0.97569382]
[1 1] [ 0.00128179]Result with sigmoid
[0 0] [ 0.01958287]
[0 1] [ 0.96476513]
[1 0] [ 0.97699611]
[1 1] [ 0.05132127]Result with relu
[0 0] [ 0.]
[0 1] [ 1.]
[1 0] [ 1.]
[1 1] [ 4.23272528e-16]
建议您尝试不同的配置,自己看看哪种配置能提供最佳和最稳定的结果。
源代码
完整的代码可以从这里下载。
结论
反向传播可能会令人困惑并且难以实现。你可能会有一种错觉,认为你通过理论掌握了它,但事实是,当实施它时,很容易陷入许多陷阱。你应该有耐心和毅力,因为反向传播是神经网络的基石。
相关文章
第一部分:反向传播的简单详解
第三部分:如何处理矩阵的维数
反向传播,简单的方法(第 3 部分)
原文:https://towardsdatascience.com/back-propagation-the-easy-way-part-3-cc1de33e8397?source=collection_archive---------11-----------------------
如何处理矩阵的维数
Photo by Todd Brogowski on Unsplash
更新:学习和练习强化学习的最好方式是去 http://rl-lab.com
在系列的第 2 部分中,我们认为我们的神经网络一次处理一个输入样本。然而,这是没有效率的。这需要太多的计算,并且不能从矩阵计算中使用的大量优化技术中获益。
大多数时候,用于训练神经网络的数据是以充满行的文件格式出现的,其中每行代表一个样本,每列代表一个特征。
下面我们来考虑一下网络。
正向输送
我们将从关注前两层开始。
输入是一个包含数据行的文件,其中每一列都包含进入神经网络的一个输入条目的值。
例如,具有值(X11,X21,…,Xm1)的列 X1 进入神经网络的 X1 输入,类似于列 X2。
人们很自然地认为,输入到神经网络中的行数将在输出端收集。也就是说,如果我们有两个样本一次一个地输入网络,我们应该期望在输出端有两个结果(一次一个)。
同样,如果我们将数据作为包含代表两个样本的两行的矩阵输入,我们应该会得到包含两行结果的矩阵。
这也适用于每一层的输出。
让我们考虑一个包含 X1 和 X2 的不同样本的文件。
在第 2 层的输出端,对于输入到输入层的每个样本,我们有值 A1、A2、A3、A4。对于每个样本都是如此,因此对于 m 个样本,我们将有 m 个输出,例如(A11,A12,A13,A14),(A21,A22,A23,A24),…。(Am1、Am2、Am3、Am4)。所以第 2 层输出的 A 矩阵的维数是(m,4)。z 的导数也是如此。
注意,权重矩阵的维数不随样本数而改变,它仅取决于输入端的节点数(在本例中为 2)和输出端的节点数(在本例中为 4),这使得它为(2,4)。
或者,我们可以通过线性代数获得相同的结果。
我们已经知道,在 feed froward 中我们计算 A 和 dZ,例如
A = f(X.W) 和 dZ = f'(X.W) 。
所以要计算 A 和 dZ 的维数,看一下 X 和 W 的维数就够了,它们分别是(m,2)和(2,4)。
结果是(m,2) x (2,4) = (m,4)。
下图描绘了如何填充 A 和 dZ 以形成维数为(m,4)的矩阵。
反向传播
到目前为止,我们计算了前馈阶段每层输出的维数。我们来看看反向传播。
提醒一下,反向传播中的公式是:
𝚫ᴸ = (Aᴸ - Y) * dZᴸ
𝚫ⁱ = (𝚫ⁱ⁺ .ᵀ)* dZⁱ西部
(其中*是成员的乘法运算)
我们现在知道 A 和 dZ 都具有维度(m,n ),其中 m 是样本的数量, n 是层中节点的数量。所以𝚫ᴸ将有相同的维数(m,n)
在我们的例子中,最后一层(L)只有一个节点,所以层 L 的 A 和 dZ 的维数为(m,1)。由此可见,𝚫ᴸ也有维数(m,1)。
为了计算内层的增量,让我们以示例中的第 2 层和第 3 层为例。
层 2 和层 3 之间的权重𝞱具有维度(4,3),因为层 2 的 4 个节点连接到层 3 的 3 个节点。
然而,由于第 2 层的增量是来自第 3 层的增量和权重𝞱的点积,我们最终得到以下配置。
不可能进行点积并在维度为(m,4)的第 2 层获得 delta!
为了解决这个问题,我们用𝞱ᵀ转置了𝞱.
计算将是可能的,如下图所示
更新权重
更新层 i 的权重,包括获取该层的输入,对该层的增量执行点积,然后使用结果来更新权重。
如果我们以第 1 层和第 2 层为例,我们在第 1 层有一个维度为(m,2)的输入,在第 2 层有一个维度为(m,4)的增量。
然而,连接层 1 和层 2 的权重矩阵具有维度
(2,4)。
为了能够更新权重矩阵,x 和𝚫之间的点积应该产生(2,3)矩阵。
这是通过得到 x 的转置,即 x 的 ᵀ ,然后执行点积 x 的 ᵀ。我们称之为𝞭.的𝚫
现在,我们可以使用梯度下降公式更新权重矩阵
Wⁿ⁺ = Wⁿ - 𝝰 * 𝞭(这里 n 是 w 的版本,而不是图层索引)
结论
您从头开始进行反向传播的可能性很小,这要感谢大量已经这样做的库。然而,如果你想自己做这个练习,你应该注意尺寸,否则你会陷入计算错误的迷宫。
源代码
下面是前一篇文章中开发的 XOR 示例的源代码,它使用样本矩阵,而不是一次一个样本。
相关文章
第一部分:反向传播
的简单详细说明第二部分:反向传播的实际实现
回归基础:朴素贝叶斯去神秘化
原文:https://towardsdatascience.com/back-to-basics-naive-bayes-demystified-8c21dc47f566?source=collection_archive---------21-----------------------
我们的目标是学习朴素贝叶斯,并将其应用于现实世界的问题,垃圾邮件检测。为什么是朴素贝叶斯?在这里找到答案!
Photo by Webaroo.com.au on Unsplash
我们的目标是学习朴素贝叶斯,并将其应用于现实世界的问题,垃圾邮件检测。为什么是朴素贝叶斯?考虑使用机器学习建立一个垃圾邮件过滤器。您希望根据邮件是未经请求的商业邮件(垃圾邮件)还是非垃圾邮件(火腿)对邮件进行分类。分类垃圾邮件 vs. 火腿是一组更广泛的问题的一个例子,称为文本分类,一组问题,朴素贝叶斯可以以相对较高的性能解决。朴素贝叶斯分类器是一种基于条件概率建模的强大分类算法。它对于具有多对多特征的分类问题特别有用,而且我们很快就会发现,可以忽略的条件依赖。名字“天真”暗示我们在这里做了一个错误的假设;事实上,我们是!但事实证明,我们天真的假设在实践中非常有效。
朴素贝叶斯
让我们假设我们对分类大量电子邮件感兴趣,并检测垃圾邮件与垃圾邮件。我们用 x 表示我们的输入向量。输入向量是每封邮件中单词的有序集合,比如 x = {I,am,happy} 。我们训练模型的目标是决定这个向量属于哪一类结果。我们把我们可能的结果集合表示为C;在这个例子中, C={spam,ham} 。
我们可以认为垃圾邮件检测是一个概率问题,我们想知道我们的电子邮件是垃圾邮件还是垃圾邮件的几率,并自然地选择几率更高的邮件。例如,我们可能会发现垃圾邮件的几率为 40%,因此垃圾邮件的几率为 60%(60% = 100%—40%);然后,我们期望我们的模型将给定的电子邮件检测为 ham 。数学上我们用 P(spam|x)= 0.4 和 P(ham|x)= 0.6 或者如果我们真的想乱一点的话, P(spam| I,am,happy)= 0.4 和 P(ham| I,am,happy)= 0.6 。术语 P(spam|x) 读作电子邮件是垃圾邮件 ( 垃圾邮件发生)的概率,假设电子邮件是 x ( x 发生)。
到目前为止,一切顺利!但这里有一个问题。怎么才能找到这些概率呢?我们需要找到所有内容为 x 的电子邮件,并统计它们被垃圾邮件vs火腿的次数。比方说,我们收到 100 封内容为 x 的电子邮件,其中 60 封不是垃圾邮件,40 封是,那么:
不过这里有一个小问题!为了检测一封电子邮件并决定它是否是垃圾邮件,我们需要接收许多完全相同的电子邮件,并在能够对它们进行分类之前将它们记录在我们的记录中。不实用!幸运的是,条件概率的贝叶斯定理可以帮助我们。请注意贝叶斯定理不同于朴素贝叶斯假设!贝叶斯定理可以写成:
贝叶斯定理是概率论中的一个基本定理。好吧,就用它吧!
值得注意的是,我们真的想知道**𝑃(spam|x)/ 𝑃(ham|x)>1**
是否存在;我们并不在乎它们的绝对值。所以我们真的想估计一下:
好消息是,与直接估算𝑃(spam|x】和 𝑃(ham|x) 相比,我们能更好地估算𝑃(spam|x】𝑃(x|ham】𝑃(ham】。据推测,我们有很多很多的电子邮件要么是垃圾邮件,要么是垃圾邮件,其中一些邮件的内容可能是垃圾邮件。这有助于我们处理不太频繁但存在于我们数据库中的电子邮件。但是,我们可能找不到以 x 为内容的电子邮件!我们该怎么办?这就是朴素贝叶斯帮助我们的地方!还有一个概率定理是基本定理。
Photo by JESHOOTS.COM on Unsplash
让我们将这个定理应用到我们的电子邮件示例中。
更好看!好,让我们再次应用同样的定理。
现在是朴素贝叶斯假设大放异彩的时候了!朴素贝叶斯假设 x 的元素是条件独立的,给定 C 。换句话说,在我们的例子中,我们将假设:
这个假设不仅听起来不对,简直荒谬!如果邮件中有“am ”,我们自然会期望有更高的几率出现“I”。然而,它工作得相当好!为什么?这需要对正在发生的事情有更深入的了解,但本质上每个单词的个体概率对于大多数常见的分类类型来说已经足够了。好了,让我们把所有的东西放在一个等式里:
剩下的就好办了!我们只需要查找包含各种单词的电子邮件,而不是所有单词都放在一起。那是一种更实际的锻炼方式!假设我们有1000 万封垃圾邮件和 1000 封邮件中有“快乐”字样。另外,假设我们有 1 亿非垃圾邮件,其中 100 万包含“happy ”,那么:
Photo by Hitesh Choudhary on Unsplash
使用 Python 进行垃圾邮件检测
我很确定没有人想自己做上面所有的计算;所以让我们来看一个 Python 库!我们将使用一堆 Python 库将电子邮件分类为垃圾邮件和火腿。计算机在理解文本方面并不擅长,所以我们需要做的第一件事是用另一种形式表示每封邮件的内容。表示要在机器学习上下文中使用的文本的一种方式是使用单词袋表示法(BOW)。在收集了所有可能的单词并将它们放入字典后,我们为字典中的每个单词分配一个向量。每个向量的长度等于字典中的单词数。例如,如果我们的字典中只有四个单词 {hello,I,am,happy} ,那么我们可以为它们分配以下向量:
在 BOW 表示中,文档被简单地表示为字数的向量;忽略单词顺序。一个简单的表示“我很开心很开心”的鞠躬是:
在这篇文章中,我们将使用这里可用的数据(感谢 Kaggle)。从技术上讲,这不是一个电子邮件数据集,但它是确定的。朴素贝叶斯也在这里工作!数据集在被您——饥饿的数据科学家——使用之前只需要少量的清理工作!下载 CSV 文件后,我们使用我们的朋友,' 熊猫 ',来加载数据。
import pandas as pd
file_encoding = 'utf8'
input_fd = open('./spam.csv', encoding=file_encoding, errors = 'backslashreplace') #the file has some non utf8 parts
data = pd.read_csv(input_fd)
data = data.iloc[:,0:2] #removing the null columns
data.columns = ['label','content']
data.head()
我们需要将电子邮件放入 BOW 表示中。没问题!我们将使用模块'text' from 'sk learn'来处理这个问题。首先,我们需要告诉 Python 为我们制作我们需要的字典。
from sklearn.feature_extraction import text
word_bagger = text.CountVectorizer()
注意:任何语言中都有一些单词对文本分类等没有那么大的价值;一个原因是它们在任何上下文中都很常见,例如,“the”、“am”和“this”无处不在。我们可以使用下面的选项来摆脱它们。
word_bagger = text.CountVectorizer(stop_words="english")
如果你有兴趣看看你的字典里有多少单词,甚至看一看它们,做我的猜测吧!您可以通过以下方式轻松查看:
words = word_bagger.get_feature_names()
len(all_words)
如你所见,我们的字典里有 8692 。如果你对 word 1001 到 1010 感到疑惑,那么你可以看看!
words[2000:2010]
我们得到下面的话:
现在我们有了字典,我们可以将任何句子转换成向量。只要照着这个做:
X = word_bagger.transform(data['content'])
让我们看看它通过转换'我很开心很开心【T1]'做了什么!
test = word_bagger.transform(['I am happy happy'])
如果你查看变量 test ,它被存储为‘压缩稀疏行’。这是因为' sklearn '非常注意有效地使用内存,并希望最小化任何冗余存储。因此,它只跟踪非零元素。只需使用 print 命令查看测试的非零元素。
print(test)
训练模型:
信不信由你,我们已经完成了大部分工作!我们现在将使用另一个' sklearn '模块来训练我们的朴素贝叶斯分类器。根据输入变量的特征,我们需要使用不同版本的朴素贝叶斯。它们是什么?让我们来看看。
- 高斯朴素贝叶斯:对于特征服从高斯分布的连续数据。
- 多项式朴素贝叶斯:针对特征为计数(即非负整数)的离散数据。
- 伯努利朴素贝叶斯:针对具有二进制值特征的离散数据。
在我们的例子中,我们需要使用多项式朴素贝叶斯;让我们导入它,然后在我们的数据集上训练模型。
from sklearn.naive_bayes import MultinomialNB
spam_nb = MultinomialNB()
spam_nb.fit(X, y)
我们可以使用' sklearn '提供的原生评分函数轻松检查我们训练好的模型的样本内准确率。
spam_nb.score(X,y)
注意:这是一条通往高分的道路!我们在这里绝对是过度适应了。这可以使用通常的交叉验证或其他用于避免过度拟合的方法来避免。
我们完了!又短又甜,对吧?我们可以在一些样本案例上尝试我们的训练模型,看看结果是否符合我们的预期。
ham = "Let me know if it works for you? I will keep you posted!"
spam = "Buy real cheap eyeglasses here, eyeglasses.club!"
test_bagged = word_bagger.transform([ham, spam])
spam_nb.predict(bagged)
我们确实做得很好!总之,这是一个基本的机器学习算法,它是可靠的,因为很多很多的原因,比如易用性和快速计算时间。
快乐阅读&保持好奇!
原载于 2019 年 12 月 31 日http://hamidomid.com。
回归基础:第 1 部分
原文:https://towardsdatascience.com/back-to-basics-part-1-7065c90eae71?source=collection_archive---------12-----------------------
排列和组合
似乎不管我上了多少高级统计课,或者我重温了多少次这个话题,排列和组合仍然难住我。这篇文章是“回归基础”系列博客文章的第一篇,旨在建立数据科学的数学基础。这第一篇文章的目的是帮助彻底解决如何从瓶子里挑选那些讨厌的弹珠的问题!
排列和组合属于数学的一个分支,叫做组合学。具体来说,这是建立在广义计数基本原理的基础上的,即如果你进行 r 个实验,第一轮可能的结果是 n₁,第二轮是 n₂,……,rᵗʰ回合是 nᵣ,那么就有 n₁n₂……nᵣ可能的结果。
假设我们运行一个三轮实验,比如从一个装有红色和蓝色两个弹珠的罐子里选择弹珠。我们每轮选择两个弹珠。整个实验会有多少种可能的结果?
对于第一轮,有两种可能的结果。对于这两种结果中的每一种,第二轮都有两种可能的结果,所以 2 ^ 2 = 4 种可能的结果。在第三轮决赛中,四个变量中的每一个都有两个以上的可能结果,所以 4 ^ 2 = 2 ^ 2 = 2 = 8 个可能结果。
我们可以使用这个一般原则,用四个标准从给定的集合中找出排列项目的变化。这可以分为两种方式来思考一组物体的排列:排列和组合。对于排列,顺序很重要。在这种情况下,选择红色弹珠然后选择蓝色弹珠与选择蓝色弹珠然后选择红色弹珠是截然不同的结果。对于组合,顺序并不重要,即包含一个蓝色弹珠和一个红色弹珠的组是相同的组,无论哪个先被选择。无论哪一种,我们都可以替换掉瓶子里的弹珠,或者不替换。
- 排列(顺序事项)
a .带替换件
当顺序不重要时,我们有多少种方法可以从三个弹珠的罐子中选择两个弹珠,并进行替换?在第一个例子中,有三种方法来选择第一个弹球,对于这三种方法中的每一种,还有三种方法来选择下一个弹球。沿着箭头,有 9 种不同的可能结果,或者 3 种。
如果我们想替换弹珠,选择第三次,会有 3 3 3 = 3 种可能性;第四轮,我们会有 3 3 3 3 = 3⁴可能的结果,等等。一般来说,从一组 n 个对象中选择 r 个对象有 nʳ 种方式。
b .无需更换
如果我们不把三颗弹珠放回瓶子里,有多少有序排列的弹珠?对于第一种选择,也有三种选择。对于这三个选择中的任何一个,第二个弹球只剩下两个选择。最后的弹珠永远只剩下一颗,三轮过后我们将被迫停止选择。所以有 3 2 1 = 6 种可能的结果,或者说是 3!。
如果我们不打算选择所有的弹珠呢?假设瓶子里有 5 颗弹珠,我们将只选择其中的 2 颗。在这种情况下,有 5 种方法来选择第一个弹球,因为我们没有把它放回瓶子,第二个弹球有 4 种可能性。这是 5 4 = 20 种可能的组合。或者,这和上面的问题是一样的,但是“移除”了最后一轮,在这一轮中,我们继续选择瓶子中的所有弹珠。所以,我们可以把这些可能性分开,把 5 4 改写成:
一般来说,从 n 总个对象中选择 r 个对象而不替换的方法是:
2。组合(顺序无关紧要)
答:无需更换
让我们扩展上面的例子,并考虑我们可以从五个中选择两个弹珠而不用替换它们的方法。
我们知道,当我们从一组 5 个物体中选择 2 个时,共有 5 个!/(5–2)!可能的结果。这里的新内容是冗余问题。每个颜色对都有一个冗余副本(例如,红色+蓝色=蓝色+红色),因此我们可以将可能性的数量除以 2 ^ 1 = 2!
所以,总可能性的数量是:
概括地说,从总共 n 个对象中产生 r 个对象的组而不替换(即,在一个组中没有重复项)的方法的数量等于:
这也是用符号写的:
b .带替换件
三个弹珠可以组成多少个不同的组,每组两个,可以替换?在这种情况下,包含一个红色和一个蓝色弹珠的组与选择红色然后选择蓝色或选择蓝色然后选择红色是一样的。和上一节一样,我们只关心最终的分组,而不是每个对象被选中的顺序。但是,因为我们有替换,所以每组中可以有重复的颜色。
在这种情况下,有六种可能的分组,我们可以展开得到:
类似地,当顺序不重要时,有 15 种方法从总共 5 个弹珠中选择 2 个弹珠,并进行替换。
和以前一样,我们可以将它展开得到:
所以,一般来说,从总共 n 个对象中产生多组 r 个对象的方法总数,加上替换,当顺序不重要时,是:
有用的公式
总之,对于从总共 n 个对象中选择 r 个对象的可能方式的数量,我们有以下规则:
我希望下次你从幸运弹珠罐中挑选或者只是准备数据科学面试时,这篇文章对你有用。欢迎和我联系,或者在评论中留下你的想法。
回归基础:第 2 部分
原文:https://towardsdatascience.com/back-to-basics-part-2-adf4f623cb45?source=collection_archive---------24-----------------------
条件概率和独立性
这是一系列博客中的第二篇,旨在建立数据科学的数学和统计基础(第一篇讨论了排列和组合)。这篇文章的目标是回顾条件概率和统计独立性背后的概率定理。概率论使我们能够根据观察到的信息模式做出预测,这是数据科学中预测分析的基础。
条件概率是指在给定另一事件 B 也已发生的情况下,某一事件 A 将发生的概率。它被写成 P(A|B)。自然地,发生车祸的概率是以首先进入车内为条件的,所以当 P(发生车祸|不要进入车内)严格为零时,P(发生车祸|一定要进入车内)在零以上。显然,首先上路很重要。
另一方面,如果 B 发生的概率对 A 发生的概率没有影响,那么两个事件 A 和 B 被称为统计独立。例如,一个人是否会遭遇车祸完全与他或她上周一早餐吃了什么无关。
条件概率
有了条件概率,我们就可以根据先前事件的新信息来更新样本空间,从而更新我们的概率计算。所以,P(撞车|乘车)≠ P(撞车|坐火车),因为这些“前科”(乘车和坐火车)给出了撞车可能性的重要信息。
让我们转到一个不那么病态、更经典的纸牌例子。在第一次抽牌时,从一副标准牌中抽出一张 a 的概率,记为 P(A1),总是 4/52 或 1/13。然而,第二次抽 a 的概率 P(A2)取决于是否先抽了 a。如果在第一笔交易中确实抽到了 a,那么我们得到 P(A2|A1) = 3/51 或 1/17(注意样本空间已经从 52 更新到 51)。
进一步分解这个简单的例子可以让我们建立一些有用的方程。在前两次抽牌中抽到 a 的概率表示为 P(A1∩A2),为(1/13)*(1/17)或 1/221。
到目前为止,我们已经:
这给了我们解决条件概率问题所需的第一个等式:
通过重新排列和乘法的交换性质,我们得到:
这个等式的内部两个表达式意味着:
这就是贝叶斯定理。我们来看一个例子!
贝叶斯在行动
假设你有一个同事,汤姆,他一周有 5 天(随机)有 3 天开车上班。不过,我们不会在可怜的汤姆身上使用车祸场景——汤姆的问题是,虽然他喜欢开车挨家挨户上下班的便利,但早上的交通可能会相当拥挤,这意味着他开车时会迟到 1/3 的时间。
汤姆也可以坐火车,虽然他不喜欢往返车站的额外麻烦,但他的火车通常是可靠的,当他乘火车通勤时,他只迟到 1/12 的时间。他每周(随机)5 天中有 2 天坐火车。
你的另一位同事 Larry 开始在办公室打赌 Tom 在迟到的日子里是开车还是坐火车。假设 Tom 没有及时通知向底池中放多少钱,您需要计算他开车去上班的确切概率。
到目前为止,我们有以下信息:
贝叶斯定理告诉我们:
而我们很容易就能算出 P(后期):
知道汤姆每 30 天迟到 7 天,我们就有:
同样地:
这些信息足以让你知道,如果你打赌汤姆在他迟到的日子里开车去上班,你会赢回你的钱,而且是 7 次中的 6 次。
独立性ˌ自立性
独立事件是指事件 B 的发生不会改变事件 A 发生的概率的事件。这样,当 A 和 B 是独立事件时,P(A|B) = P(A)。
根据这一点和贝叶斯定理,我们可以证明 P(B|A) = P(B ):
并且,由于 P(A∩B)=P(B|A)P(A),那么 P(A∩B)=P(B)⋅P(A)=P(A)⋅P(B)当 a 和 b 统计独立时。
滚动骰子
统计独立性的思想可用于找出掷出至少 1 个公平骰子的三分之六的概率:
我希望这篇关于条件概率和统计独立性的基本原理的综述对你有所帮助,哪怕只是告诉你在同事的缺点或骰子游戏上该下多少赌注。欢迎在评论中联系我。
回到未来:人工智能与时间旅行的共同点
原文:https://towardsdatascience.com/back-to-the-future-what-ai-has-in-common-with-time-travel-219496185819?source=collection_archive---------24-----------------------
每一个对时间旅行的虚构描述都提出了两个问题——如何旅行到一个不同的时间,以及如何避免改变未来,在这个过程中潜在地消除时间旅行者。人工智能预测(或看到)可能的未来,但对其预测做出反应可能会改变未来,在这个过程中可能会破坏工具。
Photo by Greg Rakozy on Unsplash
回到过去的时间旅行是一个流行的虚构概念,有两个反复出现的问题。首先,如何到达那里(通常这暗示了许多次科学散文)。第二,一个共同的主题是,回到过去的最大风险是你改变了未来,这样做,创造了时间旅行者可能不存在的环境。这有时被称为祖父悖论基于时间旅行者杀死他们自己祖先的前提。
抛开日益复杂的 终结者 系列电影不谈,这跟 AI 有什么关系?
人工智能或机器学习的一个关键用例是预测性维护。建立了一个模型,该模型基于无数传感器和历史数据点,计算给定机器发生故障的可能性。未来是可以预测的,在它发生之前我们可以做些什么。这是一个主要的用例,通过增加从工厂车间到军用喷气发动机的机器正常运行时间,它将节省数十亿美元。挑战很简单——一旦你根据对未来的理解改变了事情,你的模型就有能力预测未来的陨石坑。
此外,涟漪效应可以在人工智能通常监控和吸收数据的复杂系统中产生二阶和三阶影响。
从时间的角度来看,改变现在来改变未来(通过更换燃料泵)与改变过去的事情来影响现在没有什么不同。因此,我们进入了循环因果循环和限制风险的世界。
具有讽刺意味的是,处理人工智能风险的方法之一本质上是管理数据的多种途径——因此,预测性维护发生在机器上,预测性维护没有发生在机器上。潜在的期货份额和扩大。
在第二部电影或第二本书中通常会发生同样的事情——我们进入了平行世界的世界,并最终进入了无限宇宙。一个任务,如果转移到 AI 身上,除了最敬业的 DevOps 从业者,其他人都做不到。
回归金属:开发大数据框架的三大编程语言
原文:https://towardsdatascience.com/back-to-the-metal-top-3-programming-language-to-develop-big-data-frameworks-in-2019-69a44a36a842?source=collection_archive---------3-----------------------
C++,Rust,用 Java 做数据密集型框架
Photo by Rob Lambert on Unsplash
在之前的一篇博客文章中: 统治数据密集型(大数据、快速数据)框架的编程语言 ,我简要讨论了一些最流行的大数据框架,并展示了 Java 是数据密集型框架中事实上的编程语言。在 2004 年至 2014 年期间,当大多数主流大数据框架得到开发时,Java 相对于其他语言具有显著的优势(例如平台独立性、生产力、JVM)。
在过去的 10 年里,编程语言领域发生了很多变化。一些经典语言经历了重大改革和现代化。一些非常有前途的现代编程语言也以优雅的特性出现。计算机硬件已经经历了重大变化(多核处理器、GPU、TPU 的兴起)也是如此。集装箱化随着 Docker,Kubernetes 应运而生,并成为主流。
如果有人或某家公司想在 2019 年开发下一个颠覆性的大数据框架(例如下一个 Hadoop、Kafka、Spark),什么编程语言会是最合适的?大数据领域的经典语言 Java 或任何其他语言?首先我将讨论 Java 的局限性,然后我将在数据密集型框架开发的背景下提出更好的替代方案。大部分的观点对于开发云原生、物联网和机器学习框架也是有效的。
Java 的局限性
每种编程语言都有其局限性。此外,Java 作为数据密集型领域最主要的编程语言,也有其自身的局限性。在这里,我将讨论 Java 在数据密集型框架开发环境中的主要局限性。
JVM: JVM 对 Java 被广泛采用并成为最流行的编程语言之一起到了巨大的作用。但是就像生活中的很多事情一样,有时候最大的优点也是最大的缺点。下面列出了 JVM 的主要限制:
- 运行期 : JVM 从开发者那里抽象出硬件。因此,Java 永远无法像接近金属的语言那样达到接近本机的速度/性能。
- 垃圾收集器 : JVM 提供了垃圾收集器,极大地帮助开发人员将注意力集中在业务问题上,而不用考虑内存管理。大多数时候,默认的垃圾收集器在默认设置下工作正常。但是,当垃圾收集器需要调优时,一切都完了。Java 的垃圾收集器由于其“ 停止世界 ”的性质,对于大量的长寿命对象有特殊的问题。不幸的是,数据密集型应用意味着大量的对象。Apache Flink 开发了自己的 堆外内存管理 解决方案来解决这个问题。Apache Spark 也有类似的使用 项目钨 的堆外内存管理解决方案。许多其他大数据框架(Cassandra、Solr)也面临同样的问题。使用 JVM 管理对象,开发堆外内存管理来绕过 JVM 的对象管理,说明 JVM 还没有高效地处理大量对象。
- 内存占用 : 由于 JVM 的内存占用很大,java 在缩小规模方面非常糟糕,也就是说,当一台机器上需要运行 100 个或更多的实例时。这就是为什么Linkerd已经从高性能、高吞吐量的 Scala+Finagle+Netty 栈中走出来生锈的原因。
****开发者生产力:Java 在 1995 年刚出现的时候,凭借其精简的规模和简单性,在当时是一门非常有生产力的语言。随着时间的推移,Java 增加了许多特性,增加了语言规范的规模/复杂性,不再被认为是最有生产力的语言。事实上,在过去的十年中,Java 经常因其需要大量样板代码的冗长本质而受到批评。
****并发:虽然 Java 是在多核时代之前发布的,但 Java 通过线程、锁、确定性内存模型和其他高级抽象提供了出色的基于共享内存的并发支持。基于共享内存的并发很难编程,并且容易出现数据竞争。Java 不提供任何基于语言级消息传递的并发性(更容易正确编程)或基于异步事件循环的并发性(I/O 繁重任务的更好选择)。 Akka 或其他高性能库可以在 Java 中提供消息传递或异步并发。但是如果没有 JVM 的内置支持,它们的性能将不如有本地支持的语言(例如 Go 、 Erlang 、 Node.js )。在当今多核处理器的世界里,这是 Java 的一个巨大缺点。
序列化 : Java 的默认序列化非常慢,有安全漏洞。因此,Java 序列化是数据密集型领域的另一个棘手问题,Oracle 将其称为 可怕的错误 ,并计划在未来的 Java 版本中放弃。
解决方案:回到金属
在 Java 的 heydeys 时代,这种接近金属的语言曾经被宣布过时并注定要消亡,但最近几年却获得了很多关注,这是有充分理由的。C 编程语言是由贝尔实验室的丹尼斯·里奇在一段时间(1969-1973)开发的,当时 CPU 的每个周期和内存的每个字节都非常昂贵。出于这个原因,C(以及后来的 C++)被设计成以语言的复杂性为代价,从硬件中获得最大的性能。
有一种误解认为,在大数据领域,人们不需要太在意 CPU/内存。如果有人需要更高的性能或需要处理更多的数据,就需要在大数据服务器中添加更多的机器。但是增加更多的机器/节点也会增加云提供商的费用。还有,随着机器学习/深度学习的兴起,未来几年硬件架构会发生快速变化。因此,在未来的日子里,完全控制硬件的编程语言只会越来越重要。
近金属语言在数据密集型框架中使用还有另一个缺点:平台依赖性。目前,Web 服务器操作系统由 Linux 以 97%左右的市场份额占据绝对优势 :
https://web.archive.org/web/20150806093859/http://www.w3cook.com/os/summary/
公共云也由 Linux 主导,占据超过 90%的市场份额:
https://thecloudmarket.com/stats#/totals
随着 Docker,Kubernetes 容器化的迅速发展,可以自由地在任何平台(例如 Windows)上开发任何其他平台(例如 Linux)。因此,平台依赖性不再是为数据密集型框架开发选择编程语言的关键因素。
不要误解我,Java 仍然是开发数据密集型框架的强大语言。有了 Java 新的 虚拟机 GraalVM和新的 垃圾收集器 ZGC ,Java 在几乎任何领域都将是更有吸引力的语言 。但是我确信,在未来几年,在开发数据密集型框架方面,接近金属的语言将会比 Java/Scala 更占优势。在这里,我将挑选三种接近金属的语言作为 2019 年在 Java/Scala 上开发数据密集型框架的潜在候选语言。
C++
像先驱的准金属语言 C 一样,C++也植根于贝尔实验室。在贝尔实验室期间, 比雅尼·斯特劳斯特鲁普 在 1985 年第一次发布商业版本时,已经初步实现了 C++作为“面向对象的 C”。C++是一种通用、静态类型、编译的编程语言,支持多种编程范式(函数式、命令式、面向对象)。像 C 一样,它也是一种近乎金属的语言,在没有内存安全或并发安全的情况下,对硬件进行完全控制。与 C 类似,C++也信奉以下 Moto:
也就是说,C++将为开发人员提供一种非常强大的语言,但开发人员有责任确保程序内存安全或数据无竞争。C++也有很多特性和功能(特性地狱),可能是最难掌握的编程语言之一。自 2000 年以来,C++增加了许多特性(内存模型、基于共享内存的并发性、lambda ),使语言更简单、更安全、并发友好。但是这些变化是有代价的,C++语言规范变得更大甚至更复杂。
C++的另一个问题是构建时间长(我记得构建一个 CORBA 库需要 30 分钟)。然而,使用现代 C++(例如,【C++ 17)并使用类似于 资源获取是初始化(RAII) 的原则,与旧版本的 C++(例如,C++98)相比,在 c++中开发内存安全、数据竞争自由的编程相对更容易。C++仍然缺乏对消息传递并发(将在c++ 20中出现)和基于异步事件循环的并发的语言级支持。****
虽然有很多 C++库支持消息传递和基于异步事件循环的并发(传奇 Node.js 基于异步事件循环的并发是用 C++开发的)。学习 C++很难。掌握 C++更是难上加难。但是如果有一群有经验的 C++开发人员,他们可以构建无与伦比的框架(在任何领域,包括数据密集型领域)。有一个 4 节点 ScyllaDB(用 C++编写)的例子,它的性能优于 40 节点 Cassandra(用 Java 编写) 。****
优点:
- 最常用、最成熟的编程语言之一,在包括大数据或分布式系统在内的许多领域都有良好的记录。
- 惊人的快,接近金属语言与最大限度地控制硬件(CPU,GPU,TPU) ,旨在提取金属的最大性能。****
- 优秀的工具和庞大的库生态系统。语言越来越容易,并不断进化( 比雅尼·斯特劳斯特鲁普上 C++17 )。
缺点:
- 对消息传递或基于异步事件的并发性没有语言级别的支持(对于 I/O 繁重的任务)
- 非常陡峭的学习曲线和它的大规格,这是最难掌握的语言之一。不适合新手、刚毕业的学生或动态语言开发人员(PHP、Ruby 等)
- 没有对内存安全、数据竞争安全的语言级支持(虽然C++ 17相比老的 c++更安全)。很少有经验不足、粗心大意的开发人员会对整个项目造成严重破坏。
值得关注的大数据项目:
- MongoDB
- ScyllaDB
- MemSQL
- RocksDB
- BeeGFS
锈
https://thoughtram.io/rust-and-nickel/#/11
人们一直在寻找一种理想的编程语言,它将提供类似金属语言(C、C++)的性能/控制,以及运行时语言(Haskell/Python)的安全性。最后,Rust 看起来像是“承诺了的语言”,也就是说,它提供了类似 C/C++的性能/控制,以及Haskell/Python的安全性。受研究编程语言Cyclone(safer C),Graydon Hoare首先开发了 Rust 作为个人项目,后来由 Mozilla 赞助,并得到了大卫·赫尔曼、 布伦丹·艾希的积极贡献 Rust 是一种静态类型的编译系统编程语言,支持函数式和命令式编程范式。****
它于 2010 年首次发布,第一个稳定版本于 2015 年发布。借助 所有权借用 的概念,它提供了RAII从语言层面的支持,使内存、线程安全编程具有 C++的速度,无需任何垃圾收集器或虚拟机。RUST 与其他近似金属语言(如 C/C++,Go)的真正区别在于它提供了编译时安全性,即如果代码编译,它将运行线程安全和内存安全,如“RUST中讨论的那样。它还为共享内存并发和 消息传递并发(通过通道) 提供了语言级并发支持,尽管它仍然缺乏基于异步事件循环的并发(正在开发中)。下面是 Mozilla 的 Alex Crichton 解释 Rust 并发性的精彩演讲:
Rust 也有像 ML 语言/Haskell 这样的表达类型和数字类型,并且在默认情况下有不可变的数据结构。因此,它像 ML 语言/Haskell 一样提供了出色的功能并发和数据并发。由于 Rust 和 Web Assembly(浏览器的下一件大事) 都是由 Mozilla 开发的,高性能快速的 Rust 代码可以直接转换成 Web Assembly 在浏览器上运行。另一个非常有趣的特性是 Rust 拥有 自托管编译器 即 Rust 的编译器是用 Rust 编写的(23 年后,Java 还没有自托管编译器)。Rust 在数据密集型领域也是一种很好的语言,因为它具有内存安全、无数据竞争、零成本抽象和并发的特性。服务网格平台 链接 从 Scala+Netty+Finagle 栈迁移到 Rust ,实现了更好的性能和资源利用率。用 Rust 编写的数据密集型运行时Weld对于数据密集型框架(如 Spark)可以放弃高达30 倍的性能增益。****
优点:
- 优雅的设计。Rust 是第一个成功结合了 C/C++的强大功能、Python 的安全性、ML 的表现力和 Haskell 的产品级语言。它有潜力像 C、C++、Java 一样成为改变游戏规则的语言。Rust 连续三年获得 StackOverflow 开发者调查中最受喜爱的编程语言:201620172018。
- 编译时保证内存安全(无悬空指针,无分段错误,无缓冲区溢出),无数据竞争(无死锁)程序。
- 近乎金属的语言,拥有对硬件(CPU、GPU、TPU)的最大控制权和惊人的速度。如 基准游戏 所示,惯用 Rust 在性能上与惯用 C++不相上下。
- 利用现代多核处理器优势的并发友好编程。提供共享内存和消息传递并发。基于异步事件循环的并发(对于 I/O 繁重的任务)也在进行中(RFC 2394)。有了 Haskell 式的表达类型和不可变的数据结构,Rust 还提供了功能并发和数据并发。
缺点:
- 由于学习曲线较高,Rust 对于新手、刚毕业的学生或来自 PHP、Ruby、Python 等动态语言的开发人员来说并不是理想的语言。
- Rust 在行业中没有被广泛采用。因此,Rust 缺少库(箱)和工具,这反过来又阻碍了它的广泛应用。
- Rust 语言开发还不是一个成品。Rust 可能会引入重大的突破性变化或过于复杂的功能,并抑制其采用。
值得关注的大数据项目:
- 链接器 2
- 焊缝
- 全息链
- 数据融合
- CephFS
去
Go 是这个列表中的第二种语言,它源于贝尔实验室。语言的三位共同创造者中的两位: 罗布·派克 ( 计划 9 ,UTF-8)和 肯·汤普森(Unix 的创造者)在 Unix、C、C++起源于贝尔实验室的那段时间在那里工作。在 2000 年中期,Google 遇到了一个巨大的可伸缩性问题:开发人员可伸缩性(1000 名开发人员无法高效地在同一个代码库上工作)和应用程序可伸缩性(应用程序无法在 1000 台机器上以可伸缩的方式部署)。Google 也有过应届毕业生与现有数百万行复杂 C++代码库整合的问题,C++代码库编译时间长等一些问题详细讨论 这里 。********
发现现有的语言(C++,Java)不足以解决这些问题,谷歌聘请了软件行业的两个最优秀的人:Rob Pike 和 Ken Thompson 来创造一种新的语言。Go 于 2010 年首次发布,第一个正式版本于 2012 年发布。Go 设计者以 C 为基础,创造了一种简单、高效而强大的静态类型、编译、垃圾收集系统编程语言。Go 的另一个关键特性是它的编译时间非常快,它创建了一个单独的可执行二进制文件,该文件还包含 Go 运行时和垃圾收集器(几 MB),并且不需要单独的 VM。Go 还提供了基于 CSP 的消息传递并发(通信顺序进程,源自东尼·霍尔 论文 )几乎和 Erlang 一样的方式。****
虽然 Go 没有使用 Actor 和 Channel(Erlang 使用的),而是使用 goroutine(轻量级绿色线程)和 channel 进行消息传递。另一个区别是 Erlang 在参与者之间使用点对点通信,而 Go 在 goroutines 之间使用灵活的间接通信。因此,Go 提供了非常简单但极其可扩展的并发模型来利用现代多核处理器。下面是 Rob Pike 关于 Go 的并发模型的精彩演讲:
为了保持语言的简单和高效,Go 缺乏许多功能,如基于共享内存的并发性(尽管 Go 提供了与 Moto 通道之间的共享内存:“ ”不通过共享内存进行通信;相反,通过交流”和许多高级抽象(例如泛型)来共享内存。在 Google 的支持下,Go 已经被社区/行业很好地接受,并且拥有优秀的工具/库。一些最好的基础设施框架(Docker、Kubernetes)以及数据密集型框架都是使用 Go 开发的。**
优点:
- 毫无疑问,这是最高效、最简单的系统编程语言。对于新手、刚毕业的学生或只有单线程、动态语言编程经验的开发人员来说,它是完美的接近金属的语言(PHP、Ruby、Python、JavaScript 等等)
- 通过使用 goroutines(轻量级线程)对消息传递并发性的语言级支持,它提供了高并发性和可伸缩性。它还有一个轻量级的嵌入式垃圾收集器来提供内存安全。
- 优秀的工具和库支持。已经是业内公认的成熟编程语言。
缺点:
- 由于运行时和垃圾收集器的存在,在 Go 中对硬件(如堆内存)的低级控制是不可能的。这样一来,Go 在速度和性能上都比不上 C,C++,Rust。此外,Go 的垃圾收集器缺乏 JVM 垃圾收集器的成熟度和性能。
- 由于其简单、极简的本质,Go 缺少许多通用编程语言的关键特性,例如共享内存并发、泛型。
- Go 没有为内存、数据竞争提供任何编译时安全性。
值得关注的大数据项目:
- NATS
- etcd
- cocroach db
- 厚皮动物
- influxDB
如果你觉得这很有帮助,请分享到你最喜欢的论坛上( Twitter,脸书,LinkedIn )。高度赞赏评论和建设性的批评。感谢阅读!
如果你对编程语言感兴趣,也可以看看我下面的文章:
****** [## 2020 年最受欢迎的 10 种编程语言
针对求职者和新开发人员的顶级编程语言的深入分析和排名
towardsdatascience.com](/top-10-in-demand-programming-languages-to-learn-in-2020-4462eb7d8d3e) [## 2021 年将使用的 10 大数据库
MySQL,Oracle,PostgreSQL,微软 SQL Server,MongoDB,Redis,Elasticsearch,Cassandra,MariaDB,IBM Db2
md-kamaruzzaman.medium.com](https://md-kamaruzzaman.medium.com/top-10-databases-to-use-in-2021-d7e6a85402ba) [## 控制数据密集型(大数据+快速数据)框架的编程语言。
大数据框架概述
towardsdatascience.com](/programming-language-that-rules-the-data-intensive-big-data-fast-data-frameworks-6cd7d5f754b0)******
处理 ML 模型中高度相关的列
原文:https://towardsdatascience.com/background-d5f101e00afc?source=collection_archive---------11-----------------------
解决一个常见问题的简单尝试
背景
作为数据科学训练营项目的一部分,我正在处理一个信用卡默认数据集。我们不得不运行各种 ML 算法来尝试和预测某人是否会违约,主要使用 F1 分数作为衡量标准。我们尝试在岭和套索逻辑回归、K 近邻和决策树上进行网格搜索,看看哪个模型效果最好。
问题!
正如上面的小标题所暗示的,我遇到了一些问题。以下是数据帧的列列表:
请注意,有一些看起来非常相似的列,pay _ 0–6、bill _ AMT 1–6 和 pay _ AMT 1–6。这些数字代表他们所在的月份。当我查看相关性时,我发现了这个:
如您所见,pay_ columns 和 bill_amt 列彼此之间有很强的相关性。pay_amt 这几个并不是那么的相互关联。高相关性表明许多列包含冗余信息,即来自一列的信息包含在其他列中。
量化问题
我的第一个问题是:我如何量化这种程度的冗余?公认的是,相关平方是另一个列描述一个列的良好程度的良好近似值。如果我把所有的相关矩阵平方并相加,会发生什么?
每个组有 6 列,因此如果所有列都是独立的(因此相关性为 0),平方和将为 6,因为每列与自身的相关性为 1。如果它们都是相同的,那么所有的相关性都是 1,和是 36。第一种情况下每列的平均值为 1,第二种情况下为 6。在第一种情况下,有 6 列“有价值”的信息,而在第二种情况下,6/6=1 列“有价值”的信息,这对我来说很直观。
找到上面 3 个例子的总和,每次除以 6,我们得到:
为了得到每组中的非冗余列数,我们将该组中的总列数除以这个数。这表明 pay_ group 实际上有 6/3.21= 1.87 列“有价值”的信息,bill_amt 组有 6/4.94= 1.21 列有价值,pay_amt 组有 6/1.19=5.05 列有价值。这很直观,因为 bill_amt 列几乎完全相同,而 pay_amt 列则不同。
我还问自己,如果这些组相互关联,例如“账单金额”和“支付金额”,会发生什么,然后我得出了一个优雅的解决方案。
解决办法
我的解决方案是为每一列得出一个冗余分数,我称之为 C,它是该列与数据中所有其他列之间相关性的平方和。以下是按 C 度量的顶部和底部列:
Unsurprisingly, bill_amt and pay_ columns are at the top
注意,正如前面所讨论的,C 从来不会低于 1,对于 bill_amt 列,C 接近于 6(非常多余!).
应用解决方案:岭回归
如果你在做岭回归,有一个与列的平方系数成比例的惩罚。例如,如果你的模型试图预测 X,使用 A,你说 X=2A,惩罚将是(2 )λ,也就是 4λ。λ是进行岭回归前的超参数集。现在如果你创建一个列 B=A,你的模型将是 X= A+B,这将有一个(2*1 )λ,或 2λ的惩罚,是之前的一半。这意味着岭回归对冗余列的惩罚不足。
这个问题可以通过将列中的值除以 sqrt(C)来解决。在上面的例子中,A 和 B 之间的相关性是 1,所以每一列的 C 将是 2。如果我们将每一列除以√2,我们将得到等式 X= √2 A + √2 B,给我们一个(2*√2 )λ的惩罚,或如前所述的 4λ。这意味着我们的模型不会因为加入新列而有偏差。
声明:记得在使用定标器后进行划分,而不是之前!
应用解决方案:K-最近邻
K-最近邻(KNN)算法试图通过查看相似的数据点来猜测目标变量。相似数据点的数量看起来是“K ”,它通过最小化“距离”来确定相似性。
测量距离的一种常用方法是欧几里德距离——两点之间的直线距离。计算方法是将每列中的差值平方,将它们相加,然后对总和求平方根。例如,如果 A 列中的距离为 3,B 列中的距离为 4,则欧几里德距离为 sqrt(3 + 4 )= sqrt(25)= 5。
在上面的例子中,如果我们定义一个新的列 X=A,列 X 中的距离将是 3,新的欧几里德距离将是 sqrt(2*3 + 4 )= sqrt(34)。这造成了对冗余信息的不适当的偏见。
这也可以通过将两列除以 sqrt(C)来解决。在上面的例子中,A 和 X 之间的相关性是 1,所以如果 B 独立于 A,它们的 C 值将是 2。所以除以 sqrt(2)后,每列的距离都是 3/sqrt(2)。新的欧氏距离将是 sqrt(2 *(3/√2)+4)= sqrt(2 * 4.5+4)= sqrt(25),和之前一样!
注意:如果你使用 p 阶的闵可夫斯基距离,你用(C )^(1/p).)除列在欧几里得的例子中,如果你在测量曼哈顿距离,p=1,那么你用 C 除列。
声明:记得在使用定标器后进行划分,而不是之前!
应用解决方案:随机森林
随机森林是随机生成的决策树的集合,这些决策树对机器学习问题的解决方案进行“投票”。通过引导选择随机数据,并在每个节点选择随机“特征”,即随机列。
如果列中有冗余信息,那么随机选择会使我们偏向冗余信息。这实际上可以很容易地解决,当选择它们时,给每个列一个 1/C 的权重。
从 A 和 B 中选一个的时候,几率是 50/50。如果我们加上 X=A,那么我们有 2/3 的机会从 A 获得信息。因为 A 和 X 的相关性为 1,所以它们的 C 值都为 2。除以 C,我们得到 A 的权重为 0.5,X 的权重为 0.5,B 的权重为 1。这意味着我们有 25%的机会选择 A,25%的机会选择 X,50%的机会选择 B,回到 50/50。
结论
我觉得我上面讨论的是对机器学习模型中相关列出现的一些问题的平滑解决方案。我试图在谷歌上寻找尝试类似事情的人,但我什么也找不到。如果有缺陷,或者你知道有人以前这样做过,请通知我,这样我可以做必要的更正。
反向传播人工智能的未来
原文:https://towardsdatascience.com/backpropagating-ais-future-377816fc07fa?source=collection_archive---------20-----------------------
反向传播(和梯度下降):用于训练神经网络的最流行的算法,通过识别哪些权重对输出中的误差贡献最大,并因此调整它们以给出更好的结果。
从任何意义上来说,人工智能首先是一个挑战。在技术上,伦理上,经济上,我们从未面临过人类历史上这样的破坏。探索这将把我们引向何方以及我们今天在哪里是有意义的,并尝试制定一个从这里走向何方的路线图。
在第一部分,我提出了一些关于人工智能未来的争论,它的哲学含义和牵强附会。
在第二部分,我一路回溯到今天,对人工智能研究在哪里、走向哪里以及关键问题是什么进行了更技术性的讨论。
第一部分
今天的机器并不像你想象的那样聪明。事实上,他们甚至没有接近。《终结者和我,机器人》的承诺(AI 陈词滥调#1)放错了地方。
计算机需要大量的数据来学习任何东西,即使这样,它们也不总是能很好地概括。想象一下,给一个 5 岁的聪明的孩子打电话——他必须看 10,000 张猫的图片才能理解猫的样子。我不会为他设立大学基金。我也不建议花时间给任何人看你的猫的一万张照片。
这不是人工智能未来的样子。在未来,人工智能将能够几乎毫不费力地用最少(或没有)的数据进行归纳。这被称为人工通用智能,它将理解或学习任何人类可以完成的智力任务,比我们好得多,现在你想起来了。
尼克·博斯特罗姆(Nick Bostrom)发人深省的书——《超级智能》(Super Intelligence)提出了人工超级智能(ASI)的概念,它将在很大程度上取代 AGI,甚至更多。
让我们把手弄脏(用机器人油我说的对吗)看看这一切意味着什么。
“大家都讨厌道德哲学教授!”
这些人工智能不仅可以在计算机上实现,还可以在我们提出的任何虚拟机上实现(一些研究人员还认为,我们的大脑也是一个虚拟机)。不用说,我们已经发现了人类历史上最普遍的技术。这不仅将是有史以来最先进的技术,而且将是一个全新的存在——马克斯·泰格马克在他的同名书中称之为生命 3.0 。
这些新生物有什么道德地位?
基质非歧视原则:
如果两个存有具有相同的功能性和相同的意识体验,
而只是在他们实现的基质上有所不同,那么他们就具有了
相同的道德地位。
如果我是碳,我的新人工智能朋友是硅,这都没关系,就像我的肤色没关系一样。博斯特罗姆等人认为,基质缺乏任何道德意义,因此这些代理人将与我们具有相同的道德地位。
关于人工智能的道德辩论有一个问题:除非道德哲学家能够为道德和伦理提供一个完美的框架,否则所有的辩论都是徒劳的。这项工作是天生的和递归的困难,并有深远的影响。人工智能的效用函数可以允许潜在的伤害、偏见和全球灾难,这只是因为常识和道德规范无法形式化为这些代理人可以理解的语言。
道德讨论很重要,因为很可能这些存在是如此强大,以至于他们与神的概念无法区分。一旦我们只用一台机器就实现了普遍智能,一场“智能爆炸”就可能发生。任何足够聪明的智能体都可以进入自我完善的循环,直到它脱离人类的控制。
让我们来谈谈当这些生物开始生活在我们之间时会发生什么。
他们抢走了我的工作
毫无疑问,反对人工智能的主要论点是,它们会抢走我们的工作。反对的观点是,即使他们这样做了,我们也可以自由地把时间花在有意义的事情上,避免所有的机械工作,并在某一天畏缩在这样一个事实上,即古代人类花了大半辈子的时间在不必要的、累人的、危险的事情上。
Weizenbaum 认为人工智能不应该被用来取代那些需要尊重和关怀的职位,例如:
- 治疗师
- 一名士兵
- 法官
- 警察局
- 客户服务
几乎所有这些职业都在大量使用人工智能。谷歌的助手预约预约的演示暗示了人工智能未来在所有涉及人类对话的工作中的主导地位(治疗、客户服务等)。Hannah Fry 的书 Hello World 展示了许多人工智能被实现为法官、医生的例子,并讨论了这方面的问题。人工智能还在艺术和音乐等领域证明了自己的勇气,这是 100 年前任何人都无法预测的事情。
工作和工资是根据一个人对社会的贡献提供的,并且(通常)与一个人解决问题的难度成正比。当一个毫不费力的智能生物出现时会发生什么?我们的工作不属于他们的理由很少,而且几乎没有一个是合理的。这完全不是一件坏事,经济学家和技术专家认为,随着这些工作流向人工智能代理,新的工作将为人类开放,其性质我们甚至无法预测。看来你终于可以给人看你的猫的一万张照片了。
很难预测会发生什么,根据过去的趋势进行推断也是不明智的,因为真正人工智能的崛起是一种前所未有的高度不确定的趋势。
智慧生物的目标
人工智能具有潜在的危险,不是因为它会占据阿诺德·施瓦辛格的身体来释放他们的愤怒,而仅仅是因为他们不想。他们没有动机或目标去煽动他们去做这样的事情。这给我们带来了实际的危险,当人工智能的目标与我们的目标不一致时会发生什么,以及我们如何确保这种情况不会发生。
作为一个有智慧的生物,我们学会了自己做决定,考虑到我们的生存和发展。今天没有一个人工智能系统有任何目标,尽管它们每秒都在做出决定。他们很好地适应了一个特定领域的任务,除了他们已经看过几百万遍的东西之外,他们完全忘记了其他任何东西。对于这些代理人来说,在没有任何目标的内在表现的情况下,决定一些事情是可能的,他们今天这样做了数十亿次。但是很难想象一个没有目标的普通智慧生物;即使是 2 岁的孩子也有目标。在 AGI 体系中,要求透明的目标是有道理的,如果没有别的原因的话,要求自动防故障是有道理的。但正如前面提到的,智能爆炸可能会很快失控,我们不知道也没有任何工具来解释这些硅大脑的目标。当务之急是在任何这样的先进机器制造出来之前解决这个问题。
创造力和情感
创造力也许是我们最大的优势和最有价值的资产,也许在反对人工智能的争论中也是如此。他们也许能每秒进行十亿次计算,但他们能画出这个吗
认识到创造力是一个困难的问题,更不用说提出创造性的想法了。随着计算机生成艺术和神经风格转移的出现,激起了深度学习社区,我们有了人工智能在传统领域的创造力的线索。在绘画、音乐和下棋等受限领域,人工智能已经领先一步,但在一般意义上匹配人类的创造力是我们只能做出假设的事情。
当我们提到人工智能时,另一个被视为异类的东西是情感。人工智能系统可以很好地伪造情绪(想想聊天机器人)。他们最近开始写漂亮的(开放 GPT-2)和像人类一样说话。我说是假的情绪,因为在这些算法中没有任何情绪的内在表现,然而它们却吐出了壮丽的文字、绘画和音乐。这里有一个问题:一些研究人员认为,像焦虑这样的感觉也需要被包括在内,并用于制定 AGI 系统,这是有意义的,因为我们的决策不仅源于我们的感觉,我们认为是情感的,还源于功能和现象意识以及过去的历史;这些事情使我们能够安排和优先考虑我们生活中的动机——一些我们想传递给我们聪明的主人的东西。
关于人工智能的未来会是什么样子,已经有了普遍的共识,尽管没有人同意它的细节。
重要的是要乐观、富有想象力,但也要对每一条信息持怀疑态度。试图预测未来在过去从来没有很好的结果,而过度推断则更糟。显而易见的事实及其不可避免的后果会使我们在未来误入歧途,因为今天的一切都是短暂的,很可能一开始就被证明是错误的。我还没有讨论很多主要问题(手推车问题、意识和品质问题、机器人权利等),但这确实是一个起点,让你了解人工智能伦理、安全及其对我们所有人的影响(剧透:它对我们的影响远远不止推荐电影和产品)。
人工智能代理会记得我喜欢在冰淇淋上放什么配料,我最喜欢的电影是什么,我和谁聊得最多,以及我忘记了什么。他们不断地剥夺我们进行任何心算的需要,而我们喜欢这样。
我们不再是像我们的祖父母一样的人类,技术已经成为我们的延伸;我们已经是电子人了,人工智能是革命的下一章。
重要的是要批判性地思考这一切是否是一个实际的可能性,或者我们所有人都严重高估了 Alexa。在第二部分,我试图探索什么是真实的,我们将走向何方,猫的形象发生了什么。
第二部分
今天提到 AI 就是指机器学习或深度学习(或神经网络),这两者都是人工智能的子集。这两类算法背后的基本原理很简单:要解决任何问题,你需要足够多的正在解决的问题的例子——带标签的数据,为我们提供问题的特征和答案(监督学习),我们希望使用我们为问题提取的特征,我们可以从我们的系统中获得良好的预测。通过将我们的预测与正确的答案进行比较,当然,每当计算机给出错误的答案时,我们都会用棍子打它一顿,这样我们就可以调整参数,从而每次都能获得更好的输出。对数百万个参数(或更多)这样做一百万次,我们就产生了智能。
直觉上,这是有意义的,你看着猫的形象,你看到像眼睛、耳朵、胡须这样的特征,经过足够的训练,你就会明白猫是什么样子。这个过于简化的版本应该足以让你相信,只要有足够的数据和时间,这些算法就能创造奇迹。我们今天的算法也存在很大的问题。让我们看看其中的一些,看看未来是否真的像 5 岁的孩子一样聪明。
智能偏见
一个非常微妙的问题产生于我们目前对智慧的态度,这不是我们的错。我们所有人都有固有的偏见,不幸的是,我们的机器也赶上了这一点。
计算机并不聪明,但它们是非常好的模式发现者。在谷歌上搜索医生的图片,会发现超过 95%的结果是美国或英国人(主要是男性)。这种偏差在我们的算法中很普遍。如果我只用两个品种的猫来训练我的猫分类器,它会阻止所有其他的猫进入猫咖啡馆。我们非常小心谨慎地制作平衡且具有代表性的数据集,但这并不是唯一的问题。
问题从人类自身开始。人工智能进步背后的大多数人和政府代表都是白人男性,而像人工智能这样的问题需要由人类的代表来解决。许多人工智能发展中人的因素存在偏见的例子已经被观察到,这是危险的,因为人工智能是目前世界上最可武器化的技术之一。如果只有一小部分人控制它,上帝禁止他们的意图是错误的,人类的未来可能会受到非常不利的影响。值得称赞的是,人工智能研究人员非常迅速地发现了这个问题,并正在采取措施解决这些问题。
偏见不仅会因为不平衡的数据集而出现,还会在问题本身形成之前悄悄出现。编写这些算法的流行方式是使用大公司(如谷歌、脸书)提供的 API,不用说,如果在这一阶段出现偏差,它会迅速传播。
一切都很好,只要这仅限于猫咖啡馆和谷歌图像,但未来的人工智能系统将部署在高风险的情况下,如法院,工作面试和医院。如果这些偏见蔓延开来,许多人的生活将会受到影响。
想象一下,一名人工智能法官收到了一个白人和一个黑人的相同数据,但只判了黑人入狱,因为它从统计数据中了解到黑人更有可能有罪。在这里,不正确地构建问题和不平衡的数据集都可能在给出错误或有偏见的决定中发挥作用(以及许多其他因素)。
我们所有聪明的霸主就这么多了。
你怎么知道那是一只猫:人工智能算法中的透明性
出于多种原因,理解计算机如何做出决定是有意义的。许多人将人工智能算法视为黑盒,但最近的研究(如贝叶斯网络)正在开辟一个前沿,以找出为什么一种算法会做出特定的决定。
这也可以有效地对抗这些算法中的偏差。当务之急是以一种对检查透明的方式开发人工智能。
想象一下,在未来,当你的人工智能医生建议你服用某种特定的药物,而你信任它,因为你不想惹阿诺德·施瓦辛格。这里有一个问题:终结者不是真实的(将来也不会是),你不信任你的人工智能医生。你想知道它为什么以及如何做出决定,你的生活就取决于此。
黑匣子不是长久之计,AGI 特工需要像我们人类一样解释他们做出决定的理由。这是我们需要克服的另一个问题,没有这个问题,AGI 系统就不会存在。
“什么炸弹?”:对抗性攻击
当我们聪明的霸主被愚弄时会发生什么?在上面的图片中,添加少量的随机噪声导致了一个相当有趣的错误分类,尽管一个 5 岁的孩子可以识别这张图片中的熊猫。事实证明,这是我们今天的算法中的另一个重要弱点,未来安全的 AGI 系统应该远离一百万英里。
由其他计算机、人类或仅仅是随机噪声的存在设计的对抗性攻击可能会破坏这项复杂的技术。想象一下,如果你可以在你的口袋/手提箱里放置一枚炸弹,这样它就可以轻易地骗过商场、机场或白宫的人工智能视觉安全系统。这些系统将被部署在任何地方,一个足够先进的 AGI 系统不应该因为人或计算机的操纵而被愚弄。在我们拥有真正的智能代理之前,对抗对抗性攻击的健壮性是一个需要考虑的重要因素。
艾丽莎。治好我的头痛
关于人工智能在医学和生物学方面的贡献,人们已经做出了很多乐观的承诺。许多人认为,只有人工智能代理才能解决癌症、蛋白质折叠、基因组测序和其他解决方案遥不可及的挑战。通常情况下,计算机视觉系统在检测肿瘤和其他异常方面比放射科医生表现得更好。
你的个人助理——未来的 AGI 系统将拥有你的全部病史,将拥有足够的关于你所在地区的医疗疾病的数据,并将推断出你可能容易患的几种疾病。这在今天并不困难,只要有足够的数据和良好的计算能力,现在就可以实现。
未来的 AGI 系统和智能体可能比我们聪明,也可能不比我们聪明,但在任何给定的时间里,他们都会比我们拥有更多的信息和更好的推断技巧。它可以预测流行病的爆发,调动资源,还可以成为你的私人医生。这并不意味着不需要人类医生,但像许多领域一样,医生的工作将变得更加容易。
民主化人工智能
人工智能超越了工程师和科学家。许多公司、初创企业和大学已经认识到了人工智能可能带来的危险,并采取了重大措施去分散人工智能。各国正在制定政策和战略来应对人工智能带来的危险,并在人工智能领域保持领先地位。
需要每个人的贡献。我们需要就我们想把人工智能带向哪个方向进行一次重要的对话。我们如何实现它?万一出了差错,我们如何制造自动防故障系统?我们希望我们的未来是什么样的?这将是一个无休止的推文和 instagram 帖子的循环,还是会提供一些更有前途的东西?
深层网络和浅层关系
在第 1 部分,我探讨了人工智能的未来将带来什么的哲学含义,在这一部分,我提出了一些感兴趣的领域/问题,以及我们需要如何负责任地解决它们,以确保更好、更有意义、更安全的未来,充分利用人工智能。
我以谦卑的自省结束我的发言,这必须是为我们的后代确定我们想要什么的第一步。尽管人工智能创造了所有的炒作——今天和未来,重要的是要意识到它已经在如何影响社会。个性化推荐、即时信息检索、高速数据传输,所有这些都以无人能想到的方式影响着我们。我认为,如果 AGI 系统没有得到负责任的处理,没有适当的道德和安全框架(或者至少是在机器中引入这些东西的方法),将是灾难性的。但我们最需要担心的不是未来,而是我们对未来考虑的不够。
我们总是在娱乐(在这种气候下不能感到无聊——在我的下一个脸书独家报道中,看我与蚂蚁战斗),大部分时间都在虚拟平台上生活(Instagram 在我触摸我的食物之前吃东西),这是 50 年前没有人预测的那种未来。好故事偏见以微妙的方式支配着我们的思维,并对未来给出了乐观的衡量标准,但人工智能技术已经不知不觉地进入了生活的几乎所有领域。批判性地思考它的发展方向是至关重要的,我们是希望一代人生活在虚拟现实耳机和社交媒体中,还是我们已经有了其他的东西?
人工智能已经并将继续解决无数领域的重大问题。但是当我们的网络越来越深时,人际关系变得短暂。重要的是要保持警惕,克服宣传,看看到底发生了什么,清晰地思考,决定我们想要什么,并勇敢地做出潜移默化地影响我们未来的选择。
AI 正在改变我们所有人的世界,现在是我们作为一个物种进行这场对话的时候了,在事情失去控制之前,那个 5 岁的孩子因为你给他看你的猫的照片而感到沮丧,最终成为终结者。世纪剧情转折我说的对吗?
参考
[1]人工智能的伦理——尼克·博斯特伦和埃利泽·尤德科夫斯基
【2】计算机能力和人类理性——约瑟夫·韦岑鲍姆
【3】人工智能:它的本质和未来——玛格丽特·a·博登
批量标准化张量流 Keras 示例
原文:https://towardsdatascience.com/backpropagation-and-batch-normalization-in-feedforward-neural-networks-explained-901fd6e5393e?source=collection_archive---------2-----------------------
https://www.pexels.com/photo/black-and-silver-laptop-computer-on-round-brown-wooden-table-1181243/
机器学习是一个非常活跃的研究领域,你会经常在图书馆的文档中看到白皮书。在前面的文章中,我们将讨论 Loffe 和 Szegedy 所描述的批处理规范化。如果你是那种喜欢直接从源头获取信息的人,请查看他们白皮书的链接。
[## 批量标准化:通过减少内部协变量转移加速深度网络训练
训练深度神经网络是复杂的,因为每层输入的分布在训练过程中会发生变化
arxiv.org](https://arxiv.org/abs/1502.03167)
批量标准化用于稳定甚至加速学习过程。它通过应用保持平均激活接近 0 和激活标准偏差接近 1 的变换来做到这一点。
反向传播
在高层次上,反向传播修改权重以降低成本函数值。然而,在我们能够理解批处理规范化背后的推理之前,我们必须掌握反向传播背后的实际数学原理。
为了使问题更简单,我们将假设我们有一个由两层组成的神经网络,每层有一个神经元。
我们可以使用以下公式来表示每个神经元的输出:
其中:
- L =神经网络中的层
- w =来自神经元的输出边缘所乘以的权重
- a =前一层神经元的输出(输入边缘的值)
- σ =激活函数
- b =偏置神经元的输出(输入边缘的值)
成本函数的典型例子是均方误差。对于单个样本,我们从预测值中减去实际值(即 y ),并对结果进行平方,以说明预测值大于或小于实际值的情况。
如前所述,我们修改权重以最小化成本函数。如果我们将成本与个体体重相关联,成本将在抛物线底部最低。
利用微积分中的链式法则,我们可以得到代价函数相对于权重的偏导数。
每一项的偏导数可以表示如下。
注意我们如何使用激活函数的导数。
如果我们使用 sigmoid 函数作为我们的激活函数,那么,如果 z (激活函数之前的神经元输出)非常大或非常小,导数将近似为 0。因此,当我们计算梯度并更新权重时,变化会非常小,以至于模型不会改进。后者被称为消失梯度 t 问题。
在神经元进入激活函数之前对其输出进行归一化,我们可以确保其保持接近于导数最高的 0。
正常化
自然界中的随机过程倾向于遵循一个钟形曲线,称为正态分布。
平均值是所有数据点的总和除以总点数。增大平均值会将钟形曲线的中心向右移动,减小平均值会将钟形曲线的中心向左移动。另一方面,标准差(方差的平方根)描述了样本与平均值的差异程度。增加标准差会使曲线变宽。
为了使数据标准化,我们减去平均值并除以标准差。
无论我们正在处理的数据是什么,归一化后,平均值将等于 0,标准差将等于 1。
注意:这等同于说它确保方差等于 1,因为标准差等于方差的平方根。
批量标准化
假设我们建立了一个神经网络,目标是对灰度图像进行分类。灰度图像中每个像素的亮度从 0 到 255 不等。在进入神经网络之前,每个图像都将被转换成一维数组。然后,每个像素从输入层进入一个神经元。如果将每个神经元的输出传递给一个 sigmoid 函数,那么除 0 之外的每个值(即 1 到 255)都将减少到接近 1 的数字。因此,通常在训练之前对每个图像的像素值进行归一化。另一方面,批处理规范化用于将规范化应用于隐藏层的输出。
密码
让我们看看如何在 Python 中实现批处理规范化。
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
plt.style.use('dark_background')from keras.models import Sequential
from keras.preprocessing.image import ImageDataGenerator
from keras.layers import BatchNormalization
from keras.layers import Conv2D, MaxPooling2D, Dense, Flatten
from keras.datasets import cifar10
from keras.utils import normalize, to_categorical
cifar10 数据集由 60,000 张 32×32 像素的图像组成,分为 10 类。下面列出了这些类及其相关的标准整数值。
- 0:飞机
- 1:汽车
- 2:鸟
- 3:猫
- 4:鹿
- 5:狗
- 6:青蛙
- 7:马
- 8:船
- 9:卡车
在训练我们的模型之前,我们基于上面列出的相同原因对输入进行标准化,并对标签进行编码。
(X_train, y_train), (X_test, y_test) = cifar10.load_data()X_train = normalize(X_train, axis=1)
X_test = normalize(X_test, axis=1)
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
为了提高我们的模型的概括能力,我们将随机移动,翻转和放大/缩小图像。
train_datagen = ImageDataGenerator(
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = True
)train_datagen.fit(X_train)train_generator = train_datagen.flow(
X_train,
y_train,
batch_size = 32
)
我们使用下面的等式来设置步数,但是我们也可以使用任意值。
steps = int(X_train.shape[0] / 64)
我们定义一个函数来建立模型,使用和不使用批量标准化以及我们选择的激活函数。
def build_model(batch_normalization, activation):
model = Sequential()
model.add(Conv2D(32, 3, activation = activation, padding = 'same', input_shape = (32, 32, 3)))
if batch_normalization: model.add(BatchNormalization())
model.add(Conv2D(32, 3, activation = activation, padding = 'same', kernel_initializer = 'he_uniform'))
if batch_normalization: model.add(BatchNormalization())
model.add(MaxPooling2D())
model.add(Conv2D(64, 3, activation = activation, padding = 'same', kernel_initializer = 'he_uniform'))
if batch_normalization: model.add(BatchNormalization())
model.add(Conv2D(64, 3, activation = activation, padding = 'same', kernel_initializer = 'he_uniform'))
if batch_normalization: model.add(BatchNormalization())
model.add(MaxPooling2D())
model.add(Flatten())
model.add(Dense(128, activation = activation, kernel_initializer = 'he_uniform'))
model.add(Dense(10, activation = 'softmax'))return model
为了突出使用批处理规范化的好处,我们将训练并比较使用批处理规范化的模型和不使用批处理规范化的模型的性能。
sig_model = build_model(batch_normalization = False, activation = 'sigmoid')
我们使用 rmsprop 作为优化器,使用分类交叉熵作为损失函数,因为我们试图预测类。
sig_model.compile(
optimizer = 'rmsprop',
loss = 'categorical_crossentropy',
metrics = ['accuracy']
)
接下来,我们训练我们的模型。
sig_history = sig_model.fit_generator(
train_generator,
steps_per_epoch = steps,
epochs = 10,
validation_data = (X_test, y_test)
)
我们可以通过使用由拟合函数返回的历史变量来绘制每个时期的训练和验证准确度和损失。
loss = sig_history.history['loss']
val_loss = sig_history.history['val_loss']
epochs = range(1, len(loss) + 1)
plt.plot(epochs, loss, 'y', label='Training loss')
plt.plot(epochs, val_loss, 'r', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
acc = sig_history.history['acc']
val_acc = sig_history.history['val_acc']
plt.plot(epochs, acc, 'y', label='Training acc')
plt.plot(epochs, val_acc, 'r', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()
接下来,我们采取与之前相同的步骤,只是这次我们应用了批处理规范化。
sig_norm_model = build_model(batch_normalization = True, activation = 'sigmoid')sig_norm_model.compile(
optimizer = 'rmsprop',
loss = 'categorical_crossentropy',
metrics = ['accuracy']
)sig_norm_history = sig_norm_model.fit_generator(
train_generator,
steps_per_epoch = steps,
epochs = 10,
validation_data = (X_test, y_test)
)
如您所见,训练损失和训练准确度图比没有批量标准化的模型平滑得多,并且获得了明显更好的结果。
loss = sig_norm_history.history['loss']
val_loss = sig_norm_history.history['val_loss']
epochs = range(1, len(loss) + 1)
plt.plot(epochs, loss, 'y', label='Training loss')
plt.plot(epochs, val_loss, 'r', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
acc = sig_norm_history.history['acc']
val_acc = sig_norm_history.history['val_acc']
plt.plot(epochs, acc, 'y', label='Training acc')
plt.plot(epochs, val_acc, 'r', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()
最后的想法
消失梯度问题指的是当我们向下传播到初始层时梯度如何指数下降。因此,初始层的权重和偏差将不能有效地更新。鉴于这些初始图层通常对识别输入数据的核心元素至关重要,因此可能会导致准确性较差。
最简单的解决方案是使用另一个激活函数,比如 ReLU。否则,我们可以使用批处理规范化来减轻问题,方法是规范化输入,使其保持在金发区。
对害怕数学的人进行反向传播
原文:https://towardsdatascience.com/backpropagation-for-people-who-are-afraid-of-math-936a2cbebed7?source=collection_archive---------6-----------------------
反向传播是机器学习中最重要的概念之一。有许多在线资源解释了这种算法背后的直觉(在我看来,其中最好的是斯坦福 cs231n 视频讲座中的反向传播讲座)。另一个非常好的来源,是这个,但是从直觉到实践,可能(委婉地说)很有挑战性。
我承认,花了更多的时间,试图让我的层和重量的所有尺寸都适合,不断忘记什么是什么,什么连接在哪里,我坐下来,画了一些图表来说明整个过程。就当是可视化伪代码吧。
挑战:从直觉到实践
所以,假设你对算法应该做什么有很好的直觉理解,但在让它工作时有困难,这篇文章是为你写的!
现在,要明确的是,这篇文章不会试图解释直觉部分。正如我之前所写的,有很多好的、可靠的资源可以做到这一点。这是一个简单的(算法允许的最简单的)..)帮助您让代码工作的实用指南。事实上,如果你没有任何直觉地遵循这些步骤,你的代码可能会工作。尽管如此,我还是强烈建议您阅读一些关于感知器的内容(注意,感知器使用不可微分的步进激活函数,因此您不能真正使用反向传播,但它的结构和权重更新方法确实为更复杂的神经网络奠定了基础)。这是最基本的神经网络,只有一层。在进入更复杂的网络之前,了解如何更新简单网络的权重确实很有帮助。
训练网络时,我们重复以下步骤(对于 n epoches):
- 执行向前传球。
- 通过反向传播计算 W(每个权重的增量)。
- 更新权重。
在这篇文章中,我将重点关注第二步。
准备好了吗?让我们跳进来吧!
-propagating…
破译方程式
下图是任意网络的示意图。因为反向传播的过程基本上每一步都是相同的(取决于您使用的激活功能)。我们只看最后几层(你可以把 L95 层当作输入层,如果这样让你觉得更安全的话。就计算而言没什么区别)。
如您所见,我们的任意网络在第 95 层有 5 个神经元,然后在第 96 层有 2 个神经元,然后在输出层(L100)有 4、3、3 和 1 个神经元。所有层都由权重连接,由线标记(传统上)。
注意每个节点被分成 Z 和 O 。对于每个节点, Z 值是通过将前一层的 O 值乘以连接它们与该节点的权重来计算的。 O 通过在 Z 上应用非线性激活函数获得。现在,下面你会发现可怕的梯度计算。不要害怕!我们将复习每个表达。
当试图更新和优化网络的权重时,我们试图找到-
损失对重量的导数(“重量的变化如何影响损失”),并使用链式法则,将该任务分成三部分:
损失对下一层的导数。这是从输出层“向上游传递”的损失。或者换句话说,“下一层的变化如何影响损失”。
下一层相对于当前层的导数(可以解释为“当前层的变化如何影响下一层”),它只是连接到下一层的权重乘以其激活函数的导数。和
-(“权重的变化如何影响当前层”),它是前一层的 O 值乘以当前层的激活函数导数。
为了使事情更清楚,我写了实际的计算,用颜色编码到我们的网络中,用于我们网络的最后两层,L100 和 L99。
请注意,与每个计算相关的导数项出现在它的下方。与损耗相关的两个导数(以红色显示)非常重要,因为它们用于前面各层的计算。这在下图中可以清楚地看到:
注意∂Loss 是如何向下传播的。看着这个模式,你应该开始明白如何在代码中实现它。还要注意,我强调了最后两层,它们构成了前面提到的感知器。
注意,我没有提到在这个图中将整个表达式乘以学习率(α),因为它看起来太拥挤了,并且遮蔽了带回家的消息,这是链规则的应用。您应该尝试不同的α值,以获得最佳性能。无论如何,α确实出现在下一张图中。
通过一批实例反向传播
需要注意的重要一点是,我们看到的示意图中的每一层实际上都是一个矢量,代表为一个单个实例所做的计算。通常我们会将一批实例输入到网络中。看了下一张图后,这一点会更清楚,图中显示了对一批 n 实例的计算。请注意,这是完全相同的网络(L95 层有 5 个神经元,L96 层有 2 个神经元,依此类推……),只是我们现在看到的是 n 个实例,而不是一个。
对我来说,当实现反向传播时,最具挑战性的部分是获得不同层的大小、权重和梯度矩阵。这幅插图旨在整理事物。
在顶部,你会看到示意网络。 n 的实际大小没有影响(用于计算。显然,这在更大的范围内会有所不同…),因为你会注意到,当我们在反向传播时执行矩阵乘法时,我们总是对 n 求和。也就是说,矩阵相乘时 n 的长度是“丢失”的。这正是我们想要的,对我们批次中所有实例的损失求和。
图表的其余部分分为两个部分:
- 向前传球。
- 反向传播。
向前传球对你们大多数人来说应该很明显。如果不是,我建议在继续学习之前先阅读一下矩阵乘法。我要指出的一件事是,每个权重矩阵取一个大小为 (n,k) 的层,输出一个大小为 (n,j) 的层。这种权重矩阵的大小为 (k,j) 。你可能会注意到这张图缺少了偏差单位。这是因为我想让它尽可能的清晰,并关注不同的矩阵大小如何适应反向传播过程。下面有一小段是关于添加偏置单元的。
反向传播部分是一个“位”更棘手… 😃
该部分图表分为三个子部分:
1。变量
这里我列出了计算的不同元素,最重要的是它们的形状。关于这一部分的几点说明:
- Z 指激活前层的值。
- O 指激活后的层值。
- σ 指激活功能。
- g' 指激活函数的导数。
请注意,本节对构成的变量进行了分组
和
在顶部(以红色突出显示),以及那些构成
在底部(用蓝色突出显示)。
2。计算
这是所有戏剧发生的地方。这里其实没有什么新东西。这些都是在前面的图表中看到的完全相同的计算,但是矩阵大小写得很清楚。此外,何时使用元素乘法,何时使用矩阵乘法都有明确的说明(矩阵乘法用@表示,因为这是 Numpy.dot 的简写。您将在下面的代码部分中看到它的作用),以及何时需要转置矩阵。图表和下面的代码假设了一个平方损失函数。其导数定义为output - labels
。
3.重量更新
剩下的就是通过向每个权重矩阵添加 w 来更新我们的权重。请注意,我们只在完成反向传播后才执行更新。
密码
关于此部分的一些注意事项:
- 出于可读性的目的,这里给出的代码是伪代码。
- 由于这篇文章旨在用作实践指南,我鼓励你仔细阅读图表,并在查看代码示例之前,尝试编写自己的T4 实现。这些图包含了你自己成功构建它所需要的所有信息。查看图表,了解渐变是如何从一层传递到下一层的。确保你明白什么是乘什么,什么轴是求和的。看看我们如何在每次迭代中获得适合我们层的权重的形状 W 矩阵。****
- 网上有很多解决方案。我强烈推荐这本书,因为它很容易理解。我自己的实现很大程度上基于它。
- 代码假设使用 sigmoid 激活函数。由于 sigmoid 函数(
σ(z) *(1-σ(z))
)的导数只需要 O 的值(当然是σ(z)
) ,所以我们不需要激活( Z )前神经元的值。对于使用不同激活功能的实施,在进行正向传递时,您需要保存 Z 值。
使用循环
使用递归
添加偏置单元
您可能已经注意到,之前的图表缺少偏置单位。我选择从这些图中去掉偏差,因为我想让它们尽可能简单和直观,但是你绝对应该考虑添加它!
您可以为每个层“手动”添加一个偏差,然后计算该偏差的损失导数:
我们已经知道如何计算
,以及
只是当前层的激活函数导数。
您还可以将偏差添加到权重矩阵中。这基本上意味着在每一层添加一个偏向神经元的向量(一个 1 的向量),并相应地初始化权重矩阵形状(就像在简单的线性回归中一样)。不过要记住的一件事是,偏置单元本身永远不应该在正向传递中更新,因为它们连接到下一个层的神经元,而不是前一个层的神经元(见图)。
一种方法是避免更新这些神经元,但这可能会变得很棘手,尤其是在向后传递中(完全公开,这就是我所做的,我不建议这样做……)。一个更简单的解决方案是正常进行正向和反向传递,但在每次层更新后将偏置神经元重新初始化为 1。
一些有用的提示
- 反向传播时不要更新权重!!请记住,下一次迭代(前一层)将需要这些(未更新的)权重来计算损失。您可以保存 w,并在反向传播部分的末尾更新权重(就像我在代码示例中所做的那样),或者不断更新前面两层的权重,在我看来,这是令人困惑的,而且过于复杂。
- 如果层不是由非线性函数激活的(例如输出层),则梯度仅为 1。
- 你的程序没有崩溃,并不意味着它能工作。确保你的网络收敛,减少损失。
- 事实上,你的网络收敛,你的损失减少,并不意味着它的工作最佳。将您的结果与其他实现进行比较。研究学习速度和网络结构。
- 尝试不同的权重初始化方法。这会对性能产生巨大的影响。
摘要
反向传播可能是一个棘手的问题,但是如果你希望很好地理解神经网络是如何工作的,你应该避免在自己实现一个简单的网络之前跳入更高级的解决方案,如 TensorFlow 或 Pytorch 。这是所有深度学习的基础,也是成功处理更复杂网络的关键。也很好玩(起作用的时候)。
祝你好运!
卷积层中的反向传播
原文:https://towardsdatascience.com/backpropagation-in-a-convolutional-layer-24c8d64d8509?source=collection_archive---------0-----------------------
Backpropagation in a convolutional layer
介绍
动机
这篇文章的目的是详细说明梯度反向传播是如何在神经网络的卷积层中工作的。典型地,该层的输出将是所选激活功能的输入(例如relu
)。我们假设给定了从该激活函数反向传播的梯度dy
。因为我无法在网上找到一个完整的,详细的,和“简单”的解释它是如何工作的。我决定做数学,试图在归纳之前一步一步地理解简单的例子是如何工作的。在进一步阅读之前,你应该熟悉神经网络,尤其是计算图形中梯度的前向传递、后向传播和带有张量的基本线性代数。
Convolution layer — Forward pass & BP
记号
*
在神经网络的情况下是指 2 个张量的卷积(一个输入x
和一个滤波器w
)。
- 当
x
和w
为矩阵时: - 如果
x
和w
共享相同的形状,x*w
将是一个标量,等于数组之间的元素级乘法结果之和。 - 如果
w
小于x
,我们将获得一个激活图y
,其中每个值是 x 的一个子区域与 w 的大小的预定义卷积运算。由滤波器激活的这个子区域在输入阵列x
上滑动。 - 如果
x
和w
有 2 个以上的维度,我们考虑将后 3 个维度用于卷积,后 2 个维度用于高亮显示的滑动区域(我们只是给矩阵增加了一个深度)
符号和变量与斯坦福优秀课程中关于视觉识别的卷积神经网络中使用的符号和变量相同,尤其是作业 2 中的符号和变量。关于卷积层和前向传递的细节将在这个视频和前向传递帖子的一个简单实现的实例中找到。
Convolution layer notations
目标
我们的目标是找出梯度是如何在卷积层中向后传播的。向前传球是这样定义的:
输入由 N 个数据点组成,每个数据点有 C 个通道,高 H,宽 w,我们用 F 个不同的滤波器对每个输入进行卷积,其中每个滤波器跨越所有 C 个通道,高 HH,宽 WW。
输入:
- x:形状(N,C,H,W)的输入数据
- w:形状的过滤器权重(F,C,HH,WW)
- b:形状为(F,)的偏差
- conv _ 参数:带有以下键的字典:
- “步幅”:水平和垂直方向上相邻感受野之间的像素数。
- ' pad ':将用于对输入进行零填充的像素数。
在填充过程中,“填充”零应沿着输入的高度和宽度轴对称放置(即两边相等)。
返回一个元组:
- out:形状为(N,F,H’,W’)的输出数据,其中 H’和 W’由下式给出
H' = 1 + (H + 2 * pad — HH) /步幅
W' = 1 + (W + 2 * pad — WW) /步幅
- 缓存:(x,w,b,conv 参数)
前进传球
一般情况(简化为 N=1,C=1,F=1)
N=1 个输入,C=1 个通道,F=1 个滤波器。
Convolution 2D
x:H×W
x′=带填充的 x
W:hh×WW
b 偏移:标量
y:H′×W′
步幅 s
具体情况:stride=1,pad=0,无偏差。
反向传播
我们知道:
我们要计算成本函数 l 的偏导数 dx 、 dw 和 db ,我们假设这个函数的梯度已经反向传播到 y。
平凡的例子:输入 x 是一个向量(一维)
我们正在寻找一种直觉,它是如何在一个简单的设置上工作的,稍后我们将尝试概括。
投入
输出
前向通过—与一个滤波器卷积,步长= 1,填充= 0
反向传播
我们知道成本函数 L 相对于 y 的梯度:
这可以用雅可比符号来表示:
dy 和 y 具有相同的形状:
我们正在寻找
使用链式法则和正向传递公式(1),我们可以写出:
发展的宽度(Developed Width 的缩写)
我们可以注意到,dw 是输入 x 与滤波器 dy 的卷积。让我们看看它在增加了一个维度后是否仍然有效。
高级的(deluxe 的简写)
再一次,我们有一个卷积。这次有点复杂。我们应该考虑一个输入 dy,其大小为 1 的 0 填充与一个“反向”滤波器 w 卷积,如( w 2, w 1)
下一步将是看看它如何在小矩阵上工作。
输入 x 是一个矩阵(二维)
投入
输出
我们将再次选择最简单的情况:stride = 1 并且没有填充。y 的形状将是(3,3)
向前传球
我们将拥有:
用下标写的:
反向传播
我们知道:
使用爱因斯坦约定来简化公式(当一个指数变量在乘法中出现两次时,它意味着该指数的所有值的总和)
对 I 和 j 求和,我们得到:
发展的宽度(Developed Width 的缩写)
我们正在寻找
使用公式(4 ),我们得到:
所有术语
除了( k , l )=( m , n )为 1 的情况,double sum 中只出现一次。因此:
使用公式(3 ),我们现在有:
如果我们将该等式与给出卷积结果的公式(1)进行比较,我们可以区分类似的模式,其中 dy 是应用于输入 x 的滤波器。
高级的(deluxe 的简写)
使用我们对(5)所做的链式法则,我们有:
这一次,我们要寻找
使用等式(4):
我们现在有:
在我们的示例中,索引的范围集是:
当我们设置k=m-I+1 时,我们将超出定义的边界:(m-I+1)∈[1,4]
为了保持上述公式的可信度,一旦指数超出定义的范围,我们选择用 0 值扩展矩阵 w 的定义。
在二重和中,我们只有一次 x 的偏导数等于 1。所以:
其中 w 是我们的 0 扩展初始滤波器,因此:
让我们用几个选定的指数值来形象化它。
使用∫符号进行卷积,我们得到:
由于 dy 保持不变,我们将只查看 dx 22 的 w .的索引值,范围为 w:3-I,3-j
现在我们有了 dy 和 w’矩阵之间的卷积,定义如下:
另一个例子来看看发生了什么。 dx 43,w:4—I,3—j
最后一个 dx 44
我们确实看到弹出一个“反向过滤器”w’。这一次,我们在具有大小为 1 的 0 填充边界的输入 dy 和步长为 1 的滤波器 w’slidding 之间进行卷积。
反投影方程综述
考虑到深度
当我们试图考虑深度时,事情变得稍微复杂一些(C 通道用于输入 x,F 不同的过滤器用于输入 w)
输入:
- x:形状(C,H,W)
- w:过滤器的权重形状(F,C,HH,WW)
- 形状(F,)
产出:
- y:形状(F,H ',W ')
数学公式中出现了许多指数,使得它们更难阅读。我们示例中的正向传递公式是:
db 计算仍然很容易,因为每个 b_f 都与一个激活图 y_f 相关:
发展的宽度(Developed Width 的缩写)
使用向前传递公式,由于双和不使用 dy 索引,我们可以写为:
算法
既然我们对它是如何工作的有了直觉,我们选择不写整个方程组(这可能是相当乏味的),但是我们将使用已经为正向传递编码的内容,并且通过玩维度来尝试为每个梯度编码反向投影。幸运的是,我们可以计算梯度的数值来检查我们的实现。这种实现只对步幅=1 有效,对于不同步幅,事情变得稍微复杂一些,需要另一种方法。也许是为了另一个职位!
梯度数值检验
Testing conv_backward_naive function
dx error: 7.489787768926947e-09
dw error: 1.381022780971562e-10
db error: 1.1299800330640326e-10
几乎每次都是 0,一切似乎都很好!😃
参考
- 我博客上的这篇关于 mathjax 方程的文章😃
- 斯坦福视觉识别卷积神经网络课程
- 斯坦福 CNN 作业 2
- 卷积神经网络,正向传递
- 卷积层:正向传递的朴素实现。
- 卷积神经网络中的反向传播
- Cet 法语文章
欢迎评论改进本帖,随时联系我!
简单来说就是反向传播
原文:https://towardsdatascience.com/backpropagation-in-simple-terms-8df312471d32?source=collection_archive---------18-----------------------
随着我对神经网络(NN)的了解,我努力理解反向传播在做什么以及为什么它有意义。这篇文章是神经网络揭秘故事的后续。所以,如果你不知道什么是梯度下降,什么是正向传播,我建议你去查一下。
为什么我们关心反向传播?
我们关心反向传播,因为这是神经网络学习的方式!具体来说,这就是我们如何更新神经网络 w 和 b 的权重:
Rule for updating weights
α 是某个被称为学习率的正实数,它表示 w 和 b 的更新幅度,而 dw、db 分别是成本函数相对于 w 和 b 的斜率。
为什么有效?
为了建立我们的直觉,假设我们想要找到绝对值函数的最小值:
Absolute value function
对于那些微积分新手来说,为了找到一个函数在给定点的斜率,只要问自己:响应于 x 的变化, f(x) 变化了多少?注意,对于所有小于零的 x 值,斜率为 -1 ,对于所有大于零的 x 值,斜率为 +1 ,当 x 为零时,斜率未定义。思考一下更新 x 的值以最小化 f(x) = |x| 的规则。保持这种想法,现在让我们使用反向传播中使用的相同更新规则来更新 x :
根据反向传播更新规则,如果 x 为负(即 x + α ),我们希望将 x 向右移动;如果 x 为正(即 x — α ),我们希望将 x 向左移动。希望这也是你自己想出的最小化 f(x) 的策略!
我们到底是怎么计算 dw 和 db 的?
假设我们有一个用于分类的简单 NN,只有一个隐藏层,我们的模型成本函数是每个训练示例的平均损失,我们的损失函数是用于逻辑回归的损失函数:
Cost and Loss functions
其中 yʲ 是 jᵗʰ 例子的观测值, aʲ 是我们的 NN 为 jᵗʰ 例子产生的输出。此外,我们模型的输出是 sigmoid 函数的结果,sigmoid 函数使用输入要素与权重的线性组合:
Activation (sigmoid) and linear combination functions
最终,我们想要的是成本函数相对于权重的斜率,因为权重是我们唯一可以改变以最小化成本的东西。用数学术语来说,我们可以把它表达为:
Slope of the cost function with regards to the weights and the intercept
同时计算 dw 和 db 可能会令人望而生畏,因此我们将使用一种众所周知的技术,称为链式法则。
什么是链式法则,在 NNs 中是如何使用的?
一个例子可以清楚地说明这一点:假设我们有一些初始值、中间值和最终值,我们想通过只改变 w₁和 w₂来最小化 l
Example set-up
首先我们需要分别计算出 L 相对于 w₁ 和w₂的斜率,从而找到 dw₁ 和 dw₂ 。然后,我们可以将反向传播更新规则应用于 w₁ 和 w₂ 。只看这个例子,我们知道 w₁ 每改变一个单位, L 就会改变 2.5 个单位。同样, w₂ 每改变一个单位, L 将改变 1 个单位。如果你不相信我,试着自己做出改变。事实证明,同样的计算可以表示为中间偏导数的乘法:
Chain rule
所以现在,回到 NN 的,我们可以将 dw 和 db 表示为导致 w 和 b 的偏导数的乘积:
Chain rule in NN's
最后,我们可以计算每一项,并用链式法则将它们相乘,得到 dw 和 db 。我知道每一项的实际解看起来很难看,但至少比试图做一次大规模求导要好(如果你有兴趣看每一项的求导,请向下滚动)。
希望这篇文章有助于驱散有时围绕反向传播的迷雾。请记住,我们所做的一切都是应用链式法则来计算我们应该如何更新我们的权重,这是神经网络学习过程的核心。
Derivation of each of the partial derivatives
反向传播超级简化!
原文:https://towardsdatascience.com/backpropagation-super-simplified-2b8631c0683d?source=collection_archive---------17-----------------------
Photo by Robina Weermeijer on Unsplash
我不会说反向传播是一个非常简单的算法。如果你不知道微积分,线性代数,矩阵乘法,这可能是非常令人生畏的。即使你知道一些或全部,要掌握它也需要一点脑力锻炼。
我这么说并不是要打击你的积极性,让你避免学习它(是的,你可以避免它,但仍然可以继续你的深度学习之旅)。它有点复杂,但我不会说它超级难,而是非常直观和容易掌握。你会惊奇地发现,与它所解决的问题相比,它是多么简单。它实际上是深层神经网络的主干。所需的概念非常容易学习,而可汗学院是实现这一目的的绝佳资源。我已经列出了所需数学概念的 URL,你可以在阅读帖子之前回顾一下。
1.链式法则
2.梯度下降
3.矩阵
关于反向传播算法的背景知识已经讲得够多了,我们现在开始吧。当我刚开始学习反向传播算法时,我发现节点的表示和权重非常令人困惑,而不是算法本身。所以,我会尽量让它变得简单。让我们从一个非常简单的神经网络开始。
简单神经网络
正向输送
在这个神经网络中,我们将计算每一层的值。
输入:
x = z = a
H1 图层:
z = w x + b = w a + b
a = f(z ) = f(w a + b )
H2 层:
z = w a + b
a = f(z ) = f(w a + b )
输出:
z⁴ = w a
o =f(z⁴)= f(w a)= f(w(f(w(f(w(w a+b)+b))))
这被称为前馈传播。我们必须一次又一次地这样做,通过改变我们的权重和偏好来接近我们想要的输出。
梯度下降和反向传播
但是,问题是如何改变权重。这就是这个算法的配方。为此,我们需要使用梯度下降,并向后传播(因此得名反向传播算法),并根据需要改变权重。
回想一下,我们的期望输出是 y ,当前输出是 o. 为了评估我们预测中的差异,我们引入了成本函数,也称为 l oss 函数。它可以像 MSE (均方误差)一样简单,也可以像交叉熵函数一样简单。在这里,我们称之为 C,所以,我们的成本函数将是 C(o,y) 。
现在我们有了函数形式的差异。我们可以引入微积分来玩玩。我们需要一些函数来帮助我们减少预测值和实际产量之间的差异,我们已经以成本函数的形式量化了这种差异。这就是我们需要梯度下降算法的地方,梯度下降算法是通过不断向最陡下降的方向移动来最小化一个函数,最陡下降的方向等于梯度的负值。
让我们更深入地研究这种梯度下降。一个函数的梯度意味着,一个函数相对于一个特定量的变化而变化多少。它是通过对特定量取函数的偏导数来计算的。在这种情况下,我们希望看到我们的成本函数相对于我们的权重和偏差的变化有多少变化,从而给出如何改变权重以在我们的预测中获得最小可能误差的想法。
回到我们的例子:
由于, C 是 o 中的函数,又是 w_1 中的函数,我们可以利用链式法则得到上面的偏导数。
记住,o =f(z⁴)= f(w a)= f(w(f(w(w(w a+b)+b))))
(同理,我们可以计算出 C w.r.t 其他权重的梯度。)
这里,我们需要注意几件事:
术语 ∂C/∂w^n 也被称为局部梯度。
类似地,对于偏差:
好了,现在是时候收获我们辛勤工作的果实了。我们已经准备好必须改变权重的量,即 w_n。因此,要修改我们的权重和偏差,我们需要:
在这里,我们介绍了 ϵ 对渐变下降的影响。现在,该模型使用新的权重和偏差进行前向传播,然后一次又一次地反向传播。它继续下去,直到根据我们的约束最小化我们的成本函数到尽可能低的值。
小型复杂神经网络
此刻,你一定觉得很不完整,因为你可能会说这个模型非常简单,一旦层中有很多节点,事情就会变得非常复杂。
不完全是。事情依然如故,强硬程度依然如故。你现在要做的就是让自己熟悉编写复杂的指数和我们良好的 ole sigma(≘)符号。记住这一点,我们将再次检查表达式,但对于下面的神经网络,你会同意是相当复杂的。
在这里要小心,这不是直觉的东西,你必须习惯它。再次概括一下,我们有:
记住这一点,我们将尝试重新编写我们之前的表达式,但我将从第一层中选取一个特定的权重进行演示,然后我们将对其进行推广。
Value of z for node 3 in layer 2
对任意层中任意节点的 z 值进行概化,我们得到:
Generalized for of the value of z for any node in layer L
因此,相应的激活函数将是:
Generalized value of a for node j of layer L.
输出层:
在我们的例子中,oT7是输出:
现在,对我们的成本函数 C(o,y) 应用梯度下降,我们得到:
看看上面的表达式,这基本上是这个算法最复杂的部分。试着理解它是什么。我们将以类似的方式概括成本相对于所有其他权重的梯度。前面的表达式什么也没做,只是在向后传播时考虑了特定层的所有节点。我们如何做到这一点,非常简单,就是在我们试图改变的权重之前,将所有层的所有节点的所有计算相加。
概括起来,我们可以写:
然后,权重更新以与我们之前完全相同的方式完成:
拍拍自己,你做到了深度学习最重要的算法之一——反向传播算法的终点。如果你理解了这个算法,你现在可以更深入地挖掘,可以很容易地得到像消失渐变和更多的概念。
如果你对这篇文章有任何问题或编辑,请在评论区留下回复,我会回复的。
另外,请继续关注许多这样的深度学习算法和编码练习。
回溯测试交易策略:少施魔法,多统计数据
原文:https://towardsdatascience.com/backtesting-trading-strategies-less-sorcery-and-more-statistics-on-your-side-241ac41d18b0?source=collection_archive---------7-----------------------
Photo by M. B. M. on Unsplash
在这篇文章中,我将回顾为什么在定义交易策略时需要回溯测试,我将提供一个回溯测试设置的实际例子,包括工具和步骤,我稍后将描述哪些是关键的统计参数/数字,将引导我们得出有意义的结论。这些数字对盈利能力和风险管理的影响将被详细讨论。
正如将要展示的,简单的统计数据和指标可以以半自动的方式应用,以提供高质量的洞察力,即使是在传统上不太容易进行统计备份的全权委托交易中。
回溯测试不仅仅属于自动交易
一些分析师已经表示,资产的平均持有时间低至 22 秒。这一数字来自 2012 年的研究,可能已经被认为是过时的。
这一数字可能会产生误导,因为不同的参与者在不同的时间框架内运作,其中一些人持有资产的时间为几秒或几毫秒,而另一些人持有资产的时间为几年。
无论如何,可以合理地说,自动交易(高频、算法、量化或人工智能)的数量正在增长,而自主交易的数量正在减少或失去相关性。
这一趋势可以从大型投资机构的交易大厅和 pits⁴得到证实,它们现在要么完全解散,要么在边缘水平上运作。
这种趋势也可以在零售交易中发现。这种方法通常不同于专业交易公司使用的方法。最新的倾向于更多地依赖于统计、因子分解、回归模型、神经网络和基于覆盖率、对差价和网络中立性的策略,而零售商进行的大多数自动化交易是使用基本的基于指标的策略的简单定向交易,通常在不同的市场条件下表现不佳。
在这种背景下,似乎可自由支配的交易日屈指可数,零售注定要失败。虽然对大多数人来说这是事实(CFD 经纪公司的财务数据显示,他们每年需要吸纳大量新客户,因为他们的大多数现有客户在交易的第一个月内就失去了所有的钱),但我发现有些人通过自主交易获得了极高的利润。他们的成果可能无法被大型资本复制,但他们足以提供一份富裕且利润丰厚的工作,甚至可以经营小型基金或投资俱乐部。
与任何其他职业一样,成功取决于一系列因素,包括态度、能力、培训、教育、指导、经验、学习、承诺、错误和时间。大多数零售商失败了,这是事实,但也是事实,他们中的大多数没有遵循必要的道路,成为一个成功的交易者。
回溯测试对于交易就像模拟/训练对于其他领域一样
在我快 30 岁的时候,当我试图成为一名空中交通管制员时,我有一个短暂的机会去了解航空业。从我生活的那个时期,我得到了一些关于世界上最安全的行业的信息,我今天仍然觉得很有用。
在航空业,没有什么是允许即兴创作的。培训——包括模拟——是所有角色工作中不可或缺的一部分。不管你是飞行员、空中交通管制员还是飞行助手。行业中的每个人都遵循程序并接受适当的培训,包括模拟正常和异常情况。
清单、交叉检查和程序是规范,航空事故和未能遵循这些程序和清单之间存在关联。这种方法可以推广到其他行业,在这些行业中没有对培训和模拟的强烈关注。
“没有数千小时的飞行经验和适当的飞行模拟时间,谁会想驾驶一架 747?”
模拟是训练中的一个关键因素。它允许暴露在不利和紧张的条件下而不受伤害,并培养了遵循程序和根据计划作出决定所需的能力。
在交易中获得准确的模拟实际上很容易,这是通过回溯测试实现的。
自主交易中回溯测试的好处
正如本文前面提到的,回溯测试需要成为任何策略不可或缺的一步。放弃这一点只会花钱,甚至会在几天内毁掉一个交易账户,如果你喜欢杠杆的话,也可以是几个小时。
虽然许多人将回溯测试与自动交易联系在一起(回溯测试很容易编程,因此是交易过程的一个自然部分),但很少有人将回溯测试与技术分析或价格行为自主交易联系在一起。
回溯的好处是:
- 它能够充分理解方法/策略,发现仅仅描述策略无法涵盖的问题。
- 它给你带来了现实的期望,它将清楚地表明市场是如何完全被设计来消灭小玩家的帐户。
- 它允许您根据特定的资产/工具调整策略。
- 它有助于确定可能影响盈利能力的过滤条件。
- 它对我们正确执行该战略的技能和能力进行了现实的评估。
- 它提供真实世界的统计数据,这些数据将导致对盈利能力、支出、风险和所需资本的现实和详细的预期。
虽然这不是火箭科学,我也没有发现任何新的东西,但是回溯测试并不总是被认真对待。很多时候,它被放弃,代之以模拟账户交易,执行不力或没有适当的承诺。
做回溯测试需要什么工具和资源?
所需的基本工具有:
- 您想要交易的资产/工具的优质历史数据。
- 模拟软件包。
- 策略的完整定义(可以是一个迭代过程,因为第一轮模拟可能会导致策略的微调或定义进一步的条件)。
- 质量时间(几天)来完成回溯测试,直到至少数百(理想情况下大于 1000)的交易已经完成。
- 对回溯测试进行广泛的分析,重新访问已执行的交易,并尝试确定是否有任何相关因素或情景可以将交易损失降至最低。
所有项目都是不言自明的,尽管我们将在下面的段落中更详细地介绍前两个项目。
历史数据是个问题吗?
数据不再那么难找了。当然,如果你的策略在时间框架方面很激进,你希望根据一分钟蜡烛线的变化实时做出决策,或者你的策略使用分笔成交图,那么数据会很昂贵。但是,即使在这些情况下,这些策略中的一些也可以用 1 分钟蜡烛来近似,获得/购买要便宜得多。
数据的重要事实是,你需要明白你的时间框架和策略将决定你需要多少数据。
如果你在测试一个日内策略,几年后,可能 1 分钟蜡烛线(即使 5 分钟也是一个日内策略)将是最小值。无论选择何种数据长度,都应满足以下条件:
- 该策略必须在趋势和非趋势市场条件下进行测试。一种策略可能在持续的牛市中有效,但在横向或熊市中效果不佳。
- 该策略应针对不同的市场波动进行测试。
- 你应该计划测试 1000 次操作。也可以是数百个,但越大越好。
模拟软件:一种负担得起的有价值的辅助工具
对于手动回测,我使用外汇测试。这是一个便宜的工具,它有一个永久许可模式,而且使用起来非常简单。它支持分笔成交点和分钟数据。
这是我测试过的唯一一个手工回溯测试工具,但是我确信还有其他工具完全可以完成这项工作。重要的一点是,你需要用实际的市场历史数据来复制市场的东西。
Backtesting software Forex Tester with a classic intraday Triple Screen configuration. In this particular setup a 1 minute intraday strategy is being tested using daily, 15 minutes and 1 minute charts of the FDAX symbol. The multiple screen setup mimics a live market setup where you can monitor scenario for different timeframes.
应特别注意尺度(我个人尝试修正网格尺度,以便您可以对特定资产/工具的行为有更好的启发性理解)。
模板应该总是相同的,你可以使用任何有助于你的指标,虽然许多价格行动交易者忽视指标,但我个人认为它们是很好的确认工具,我倾向于使用标准的 14 周期 rs I 和古老的 Connors 2 周期 RSI,但这只是个人偏好。
如果数据来自受监管的流动性市场,交易量总是相关的,超过柜台交易量,如在 CFD 经纪人上发现的交易量可能会产生误导。
模拟软件将允许市场向前或向后移动,自动或只需按一个键。从一个时间框架转换到另一个时间框架很容易,当市场在一个与你的策略不相关的区域波动时,你可以快速前进。
“模拟/回溯测试软件的主要好处是,你可以在几天内测试数百或数千笔交易。同样数量的信息在常规交易或演示交易中需要几个月的时间。更不用说交易可以持续数周的摇摆或头寸策略了。”
应该避免分析过去的静态图表。我见过很多次,人们只是使用过去的图表,并根据图表验证策略。人类的大脑非常善于——也很有创造力——发现模式,所以仅仅在过去的图表中发现模式是不够的。需要在图表的右边空出一块地方来感受这个策略,并了解你在这些条件下的表现。
此外,一个常见的错误是避免分析模拟交易——避免分析一般的交易。你可以从盈利或亏损交易中学习,并识别可能导致生成提高盈利能力的过滤器的条件。尝试和事后分析 200 笔交易比测试 1000 笔交易要好。将市场条件与每笔交易相关联并加以注释也很重要,即,希望您用额外的市场条件情况来丰富该工具提供的损益表格数据。这将进一步丰富统计分析,进一步完善战略。
回溯测试的关键统计数据
尽管自主交易的名声更像巫术,而不是科学,但它绝对不是真的。虽然需要一定程度的艺术,但它可以被认为是一种比深奥更具启发性的体验。
全权委托交易的科学部分来自交易规则(即交易计划、设置、市场分析等。)以及我们方法论的统计分析。
必须为回溯测试、演示和实时交易阶段收集统计数据。与你可能认为的相反,不需要做复杂的分析,因为你可以从非常基本的统计数字中获得非常有趣的信息。
Backtesting Statistics
上图显示了该工具提供的统计数据。整个交易细节可以导出到 Excel 中,以进一步分析结果,但即使是这个基本集合也将提供足够的信息来验证或放弃策略。
在本例中,选择的策略涵盖了 2015 年全年,但在撰写本文时,交易仅在第一个月进行(如上所述,没有足够的采样数据来对策略进行有意义的分析)。无论如何,这些信息足以涵盖关键的统计数字以及如何解释这些数字。
总交易/盈利交易/亏损交易(与盈利能力相关)
这是对交易数量的明显统计,详细记录了盈亏情况。从这一基本计数中可以推断出以下信息:
- 你能从该策略中平均预期多少交易,根据应用的资本和风险管理,这将导致从该策略中可预期的净利润。如果我们的策略是每年给你 15 笔交易,而你每笔交易的风险是 100€,你知道你不会从这个策略中获利。此外,每年 15 笔交易的数字一定会让你马上得出结论,它需要进行多年的回溯测试。
- 盈利/亏损比率(也包含在统计报告中)。在这种情况下,我们赢了 69%的时间,输了 31%的时间。请注意,有些盈利策略的胜率低于 50%,这些数据与盈利交易的平均利润和亏损交易的平均亏损相结合,引入了每笔交易的平均盈利能力(APPT)⁵)的概念,这实际上是确定策略是否盈利的基石。
这是每笔交易的平均盈利率的公式,它基本上说明了每笔交易平均赚了多少钱。正数将反映盈利战略,负数将反映非盈利战略:
APPT =(盈利%平均盈利-(亏损%平均亏损)
连续盈利/亏损交易(涉及风险管理和交易心理学)
根据你采取的策略,你将面临或长或短的连续输赢。有些策略比其他策略更容易失败,导致小的损失,这些损失可以通过一些成功的交易来弥补。其他人得到更多的补偿,将呈现出类似数量的输赢条纹长度。
提前知道你能从一个策略中得到多少亏损交易,这对于决定你能得到什么是很重要的。你的账户应该有适当的大小,不仅能承受这个数量的亏损,还能承受更大的亏损。
虽然这只是一个指示性因素(模拟并不能确保未来的可靠性),但它是一个很好的现实预期指标。在这个特定的测试中,我们最多有 3 笔亏损交易和 6 笔盈利交易。这可以作为一个参考,所以你应该准备至少两倍于这些数字。
预期的连续盈利/亏损交易也会对你的心理产生影响。承受长时间的亏损可能是一个艰难的经历,尤其是当你强调每笔交易的风险资本时。提前知道你可能会期望什么将有助于你应对动荡,它也将有助于发现什么时候事情真正偏离了原来的计划,这样你就可以在为时已晚之前暂停运营。
最大利润交易/最小利润交易(与风险管理相关)
每笔交易的最大利润和最小利润可能会产生误导。实际上,在准备策略的时候,为给定的交易规模做准备是个好建议。在这个特殊的例子中,已经安排了符号统计(杠杆和批量大小),因此损益数字以 FDAX 点给出。也就是说,我们选择了一个批量,所以每个点(赢或输)代表一个€。这使得以后的规模确定操作能够适应我们的风险。这意味着你以后可以根据你的交易账户和风险状况来升级或降级规模。
根据统计数据,我们注意到最大的亏损交易损失了 142.87 个 DAX 点。
这意味着,如果你接受每笔交易 1%的风险(你的交易账户为特定策略配置的风险),这是交易中常见的风险假设,你可能会为 10.000€交易账户设定 1€/点的风险,因为最差的交易会让你损失 1.4%。
一些人表示,1%的数字必须更新并适应每个操作,这涉及到根据资产/工具当前报价、操作的止损值和您交易账户权益曲线的当前状态(提款或利润)为每个操作计算出一个适当的规模值。对于外汇对,您还需要将外汇对的当前汇率与您交易账户的基础货币进行比较。“路太麻烦了,你不觉得吗?”。
我个人的观点是,你不必对数字要求太严格;保持在一个可接受的亏损数字附近更容易操作,并且允许你操作固定的手数。缩小损失是风险管理的重要部分。您可以按季度或简单地根据权益曲线中期或长期演变来审查规模。这更容易。
请注意,在交易杠杆衍生工具(如期货或差价合约)时,你需要更多地考虑名义价值,而不是实际交易账户。你将被要求分配比你投资的名义价值少得多的钱,但是你仍然应该明白杠杆作用对损失和利润都是重要的。我个人倾向于总是从名义价值的角度来思考。我开始操作股票时,这是我评估操作规模的自然方式,但我遇到过许多只处理杠杆工具的人,他们往往不完全理解名义 value⁶.的概念
还应注意,每笔交易的最大百分比或风险实际上取决于每个人。有很多方法可以确定这个价值,它不仅与你的交易账户有关,还与你的可用资本和财富有关。有些人资本少但财富多,所以他们的资本相对来说没什么用;有些人资本多但财富少,所以保护他们的资本至关重要。你的风险状况也起着重要的作用。
根据你的具体情况,盲目使用 X %规则会导致不均衡的风险。
风险管理的重要一点是要有所准备,并清楚地了解这对你的风险状况、财富和个人状况意味着什么。应采用哪种特定的风险管理取决于每个人。
平均利润/平均损失(与盈利能力相关)
这些数字,加上交易的%盈利/亏损比率,构成了策略的盈利能力,就像之前用 APPT 公式讨论的那样。
请记住,尽管大多数培训课程和书籍都强调需要保持平均盈利/平均亏损的正比率,但这并不是真正需要的,因为相关的是 APPT 符号。尤其重要的是要明白,很多盈利的短线日内和刷单策略都是处理负盈亏比的。这可能与在这种较小的时间框架中发现的噪音有关,这使得处理短期动量和较高的交易%盈亏比比处理正的平均盈亏比更可取。
最大提款(与风险管理和心理学相关)
最大提款模拟您的交易账户在回溯测试期间经历的最大损失。虽然这个值不能保证什么,但它可以让您知道会发生什么。
你必须在不停止这个过程的情况下对经历这样的损失感到非常舒服,而且它必须符合你的风险管理政策。一些策略——比如操作中盘的均值回归策略,仅举一例——可能会经历极其严重的亏损,因此了解你的风险状况以感到舒适是很重要的。
利润因素(与盈利能力和优化相关)
利润因子定义了你冒多大的风险,得到多少。它基本上把总利润和总损失联系起来。1.5 的比率——如本例所示——意味着你冒着 1€的风险获得 0.50€的利润。比率越高越好。
利润因素通常用于进一步优化策略。接近 1 的利润因素会让你提高警惕。
回报率%(与盈利能力相关)
回报率%基本上就是投资获得了多少回报。这可能会有点误导,因为它是基于您的回溯测试交易账户计算的,可能过大(或过小)。
同样重要的是要明白,只有在不同的市场条件下对策略进行了长时间的测试,才能获得现实的回报率。在这个特殊的例子中,一个月的回溯测试不足以得出策略盈利的结论。
最大批量因子
如果你操作的是可变规模策略,最大批量因子会告诉你所用的最大规模。这很大程度上取决于您如何在回溯测试工具中配置工具的杠杆水平。
在本例中,手数和杠杆调整得很好,因此每个操作处理 1 个€/点,因此该值没有意义。如果您在交易中操作可变手数,并且您希望通过确定手数来控制风险,这会有所帮助(在差价合约中,您最终会感到自然手数对您的交易账户来说太多了)。
恢复系数和可靠性系数(与风险管理和优化相关)
恢复系数通过以下公式计算:
恢复系数=(总利润-总损失)/最大提取额
它基本上是一个品质因数,量化了毛利润与最大亏损之间的关系。恢复系数越高越好。
可靠性系数将平均月利润与最大提取相关联:
可靠性系数=每月利润/最大支出
我们可以尝试简化这两个数字的统计含义,说明它们试图量化股票曲线的波动程度。由于最大下降是估计性的,它们只是指标,可用于优化参数并获得更友好的权益曲线。
丰富和审查您的回溯测试操作
虽然我们不会讨论如何丰富表格数据,但文章中已经提到,用交易信息丰富数据总是一个好主意。
丰富数据的方法不受限制,需要经验和实验。如果你使用移动平均线或指标,你可能想包括交易发生时这些平均线或指标的状态。
Backtesting software will provide you basic information that can — and shall — be enriched separately in an spreadsheet analysis
基于交易长度、方向(买入/卖出)或一天中的时间段,可以获得进一步的详细分析。目标是找到某些参数和盈利/亏损交易之间的相关性。
我记得为我的外汇交易做的一组统计(在这种情况下,他们是实时交易的统计),我知道我买比卖更有利可图。虽然这些发现必须谨慎对待(它可能与市场条件有关),但它们也可能揭示您的操作中的偏差。正确分析后,可以应用过滤器或进一步的尺寸标准。
最后但并非最不重要的建议是分析交易。这不是经常做的事情(很无聊,需要很多时间),但它可能会导致发现操作错误,并有助于进一步改善战略和执行。
摘要
文章回顾了如何对自主交易进行回溯测试,以及如何阅读一些基本的统计数据。
已经强调了回溯测试的相关性,并且已经表明了对关键统计数字和指标的基本理解如何能够有利于提高盈利能力。
强调了用于确定其对盈利能力和风险管理的影响的关键数字和公式,并提供了关于如何基于扩展数据实现进一步改进的最终意见。
[1]https://www . telegraph . co . uk/finance/personal finance/investing/9021946/How-long-the-average-share-holding-last-Just-22-seconds . html
[2]https://www . marottaomoney . com/what ' s-the-average-holding-period for a-stock/
[3]https://ny post . com/2017/04/19/UBS-已经正式放弃其庞大的交易大厅/
[4]https://www . ft . com/content/4d 221 b 22-3d FB-11e 6-8716-a4 a71e 8140 b 0
[5]https://www . investopedia . com/articles/forex/07/profit _ loss . ASP
[6]https://www . CME group . com/education/courses/introduction-to-futures/about-contract-nominal-value . html
使用 zipline 中的自定义数据对交易策略进行回溯测试
原文:https://towardsdatascience.com/backtesting-trading-strategies-using-custom-data-in-zipline-e6fd65eeaca0?source=collection_archive---------12-----------------------
Source: pixabay
了解如何将自定义数据导入zipline
在之前的文章中,我已经展示了如何使用zipline
回测基本交易策略。为此,我使用了内置的quandl
数据集,这对于许多用例来说已经足够了。然而,它也有一些缺点:
- 2018 年年中,它停产了,所以没有最近的价格
- 它只考虑美国股票
这就是为什么我还想展示如何获取定制数据集,即一小部分欧洲股票。我将通过使用已经由 Zipline 提供的csvdir
包来这样做。还有其他的方法,我在本文最后会提到。
为了简洁起见,我将不再谈论zipline
的设置。有关该主题的详细信息,请参考之前的文章。
获取数据
我们首先需要收集我们想要输入到zipline
中的数据。为此,我使用了yahoofinancials
库。为了加载到zipline
中,数据必须是 CSV 文件和预定义的格式(示例如下)。为了这篇文章,我下载了两种证券的数据:ABN AMRO(一家荷兰银行)和 AEX(一种由在泛欧交易所交易的荷兰公司组成的股票市场指数)。我们使用后者作为基准。
我们从加载所需的库开始。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from yahoofinancials import YahooFinancials
然后,我们定义一个简短的函数,用于使用yahoofinancials
下载数据,并准备数据帧供zipline
接收。准备好数据后,该函数将数据作为 CSV 文件保存在一个名为daily
的文件夹中(该文件夹以所考虑数据的频率命名)。
我们从下载 ABN·AMRO 的股票价格开始。
download_csv_data(ticker='ABN.AS',
start_date='2017-01-01',
end_date='2017-12-31',
freq='daily',
path='european/daily/abn.csv')
该函数返回下载价格的曲线图:
我们还展示了 zipline 接受的文本文件的结构。
!head ./european/daily/abn.csv
我们以类比的方式下载索引数据。
download_csv_data(ticker='^AEX',
start_date='2017-01-01',
end_date='2017-12-31',
freq='daily',
path='european/daily/aex.csv')
也可以将多个 tickers 以 Python 列表的形式传递给yahoofinancials
并一次性下载。然而,我们选择这种方式是为了简化所需的操作。
摄取 CSV
让我们通过运行以下命令来检查当前加载的包。
!zipline bundles
我们现在将添加一个名为eu_stocks
的定制包。为此,我们需要修改 zipline 目录中的extension.py
文件。我们需要添加以下代码:
在调用register()
时,我们必须指定一个交易日历,在本例中是XAMS
,它对应于泛欧交易所。有关所有提供的日历列表,请参考此文档。也可以定义自己的交易日历,你可以在zipline
的文档中找到更多信息。
请记住,我们需要传递之前下载的数据的确切日期范围。在本例中,我们从2017–01–02
开始,因为这是我们获得价格数据的第一天。
为了最终接收数据,我们运行以下命令:
!zipline ingest --bundle eu_stocks
买入并持有策略示例
最后,我们展示了如何使用自定义数据来回溯测试交易策略。为此,我们采用基本的买入并持有策略。我们使用 ABN·AMRO 的股票,并选择 2017 年作为回溯测试的持续时间。默认情况下,zipline
使用美元,但是,当所有资产都是同一种外币时,使用欧元报价的股票和指数没有问题。
关于这段代码中发生的事情的更详细的描述,我再次参考以前的文章。让我描述一些细微差别:
- 我们需要通过在
zipline
魔术中包含—- bundle eu_stocks
来指定我们想要使用的定制包 - 我们还需要通过在
zipline
魔术中包含--trading-calendar XAMS
来指定交易日历 - 我们需要在
initialize()
函数中设置基准:set_benchmark(symbol(‘AEX’))
。原因是默认基准是在纽约证券交易所交易的 SP500,这与我们的设置不兼容。
我们的买入并持有策略的结果如下图所示。
我们简单的策略在一年内成功创造了近 50 个€。
结论
在本文中,我展示了如何使用定制数据在zipline
中运行回溯测试。正如我提到的,使用csvdir
bundle 并不是我们获取定制数据的唯一方式。我们也可以写一个完整的定制包(更多细节请看这里),例如,它使用 API 自动从加密交换中下载数据。然而,这可能是另一篇文章的主题:)
一如既往,我们欢迎任何建设性的反馈。你可以在推特或评论中联系我。您可以在我的 GitHub 上找到本文使用的代码。
以下是该系列的其他文章:
- 介绍 zipline 框架并展示如何测试基本策略(链接)
- 评估交易策略的绩效(链接)
- 基于技术分析建立算法交易策略(链接)
- 基于均值-方差分析建立算法交易策略(链接)
我最近出版了一本关于使用 Python 解决金融领域实际任务的书。如果你有兴趣,我贴了一篇文章介绍这本书的内容。你可以在亚马逊或者帕克特的网站 T21 买到这本书。
机器学习中特征选择的向后淘汰法
原文:https://towardsdatascience.com/backward-elimination-for-feature-selection-in-machine-learning-c6a3a8f8cef4?source=collection_archive---------7-----------------------
当我们建立机器学习模型时,我们只选择那些必要的特征或预测器是非常重要的。假设我们的数据集中有 100 个特征或预测值。这并不一定意味着我们需要在模型中包含所有 100 个特性。这是因为并不是所有的 100 个特征都会对模型产生显著的影响。但话说回来,这并不意味着它对所有情况都适用。这完全取决于我们手头的数据。这里有更多关于为什么我们需要特性选择的信息。
有多种方法可以找出哪些要素对模型影响很小,哪些要素可以从数据集中移除。我以前写过关于特性选择的文章,但是非常简短。在这篇文章中,我们将一步一步地看看逆向淘汰法,以及我们如何做到这一点。但是在我们开始讨论逆向淘汰之前,确保你熟悉 P 值。
第一步
反向消除的第一步非常简单,您只需选择一个显著性水平,或者选择 P 值。通常,在大多数情况下,选择 5%的显著性水平。这意味着 P 值将为 0.05。您可以根据项目更改该值。
第二步
第二步也很简单。你只需将你的机器学习模型与所有选择的特征相匹配。因此,如果有 100 个特征,您可以将它们全部包含在您的模型中,并使模型适合您的测试数据集。这里没有变化。
第三步
在步骤 3 中,识别具有最高 P 值的要素或预测值。又很简单了,对吧?
第四步
这是重要的一步。在这里,我们做决定。在上一步中,我们确定了具有最高 P 值的要素。如果该要素的 P 值大于我们在第一步中选择的显著性水平,我们将从数据集中移除该要素。如果该特征的 P 值(在集合中最高)小于显著性水平,我们将直接跳到步骤 6,这意味着我们完成了。请记住,最高 P 值大于显著性水平,请移除该要素。
第五步
一旦我们找到了需要从数据集中移除的要素,我们将在这一步中进行移除。因此,我们从数据集中移除该要素,并用新的数据集再次拟合模型。在为新数据集拟合模型之后,我们将跳回到步骤 3。
这一过程将一直持续到第 4 步,此时数据集中所有剩余要素的最高 P 值小于第 1 步中选择的显著性。在我们的示例中,这意味着我们从步骤 3 迭代到步骤 5,然后返回,直到数据集中的最高 P 值小于 0.05。这可能需要一段时间。在 100 个假设的特性中,我们可以这样筛选出 10 个特性(这只是我选择的一个随机数)。参考本文顶部的流程图,更好地理解这些步骤。
第六步
一旦我们到达第 6 步,我们就完成了特征选择过程。我们已经成功地使用反向消除来过滤掉对我们的模型不够重要的特征。
在这个过程中,我们还可以使用其他一些方法。我想我将来也会写一些关于他们的东西。
在 Twitter 上关注我,了解更多数据科学、机器学习,以及通用技术更新。还有,你可以关注我的个人博客。
平衡谁处理数据不一致
原文:https://towardsdatascience.com/balancing-who-handles-data-inconsistency-72779a1404b8?source=collection_archive---------14-----------------------
在生产中,事情不可避免地变得不稳定,这是正常的
如果说这些年来你在处理数据时学到了什么,那就是数据质量“保证”本质上是善意的虚构。每当我接触到一个不熟悉的生产数据库时,我不可避免地会做一些简单的一致性检查,比如“这个惟一的 ID 实际上只出现过一次吗?”“有重复的事件吗?”“这些应该完全一对一地同时发生的事件真的是一对一的吗?”
每当我检查一个已经运行了一年或更长时间的系统时,通常很有可能至少有一些事实已经被有限地打破了。而在我看来,在一些合理的界限内, 这是可以的 。因为处理/预防问题的成本因团队而异。
Do the easy Eng stuff when you can, but eventually it gets too expensive
为什么?所有这些东西都应该由数据库系统来保证!这永远不会发生!
关于合同的事情(无论是在生活中还是在软件中)是,除非它们被强制执行,除非它们有真正的效力和后果,否则它们经常在对一方或双方都方便的时候被忽略。此外,强制执行的成本可能不值得付出。
在我曾经工作过的生产系统中,通常强制一致性约束的事物,比如外键和检查约束,出于性能原因在数据库中没有被明确使用或者不存在(就像那些黑暗的 NoSQL“酸?那是毒品对吗?”天)。这只是一个在应用层而不是数据库层“强制执行”的社会契约。所以事件日志表中没有重复行条目的唯一原因是因为应用程序知道不要写重复的行条目。
其他时候,有一些内置功能,如自动增加 id,这在单主机环境中是有意义的,但最终会增加复杂性,如分片,然后是多区域分片。随着复杂性的增加,这种逻辑开始转移到应用程序层,并且变得更加难以实施。
大多数时候,这一切都出乎意料地好,这要感谢设计系统并预见明显问题的工程师。预期的行为在测试和 QA 中得到验证,生活通常会继续。
当系统在生产中运行一段时间,并且系统开始积累不可预见的问题时,问题只会慢慢出现。不可避免地,一个系统会宕机,或者应用程序中的一个 bug 被引入。当你不得不处理一个分布式系统时,事情变得更加疯狂,这个系统更有可能有意想不到的和完全奇异的故障模式。这就是不可靠的数据如何绕过这些软“保证”并进入您的数据集。有时甚至“硬”保证也会被破坏,因为有一个意外的失败模式暴露了一个 bug。
什么?如果你关闭了一致性保证,你应该得到你所得到的!
I’m fairly sure this isn’t Stockholm Syndrome
确定吗?但问题是,如果数据中真的有重复的行(或丢失的行),会发生什么呢?如果你是一家银行,这是你的交易日志,这是一件大事,即使每 10 万亿次交易中只发生一次。如果你只是跟踪有多少用户点击了一个按钮,你甚至可能不会注意到。
实用主义很重要。
同时,维护一致性合同的成本可能很高。数据库外键约束可能好,也可能不好,这取决于您的具体硬件、数据库工作负载和模式。您需要进行实际的测试和基准测试来计算 FKs 的成本。如果你需要保证整个地球上读/写事务的一致性,你要么等待光速,要么想出疯狂的新算法,比如用扳手。
如果检测到问题,您可以进行事后检查以发出警报,但随着应用程序的发展,您需要编写和维护一套全新的测试。此外,它要求您主动预测要检查的一致性问题。
对于大型 NoSQL 系统,您可能只有最终的一致性,如果不切换到一个完全不同的系统架构(以及其中涉及的所有成本),您可能无能为力。
放松,可能没事
—什么?但是我的数据一团糟!我在一个表中有一个重复的 ID,该表中的字段应该是唯一的(真实的故事)。我的世界全是谎言。这怎么可能是“好”呢?你疯了。
所有发生在你发现了一个错误的证据,吸一口气,看看什么受到了影响。开始调试过程。你弄错了吗?它的主要作用是什么?有受影响的关键系统吗?这是一个持续的问题,还是已经停止了?有没有可以用来识别问题区域的签名?
一旦你意识到发生了什么(这不是一个错误),以适当的严重程度提交一个 bug。如果它是一个关键的核心业务数据源,它可能需要 P0。
接下来,确定您是否可以解决事故造成的损失。对于那些有很强的人为因素的事情,比如临时的和探索性的工作,你能通过识别错误的行来解决这个问题吗?您能否在降级状态下使用不太细粒度的指标进行分析,比如使用唯一计数和不受影响的相关代理统计数据?
自动化数据管道的事情更加复杂,因为它们没有那么灵活。但是,根据您的模型和系统正在做什么,它可能在可接受的误差范围内。你必须测试才能发现。
核心问题:我们正在平衡防范数据问题的成本/收益
墨菲定律适用于所有事物,每个系统最终都会失败。完全干净的数据只存在于学校的玩具问题集中。问题是你愿意投入多少资源来防范越来越罕见的事件。
作为一个组织,您需要平衡在事情发生前通过工程预防/发现数据问题的能力,以及在事情发生后处理后果的时间和风险。
一致性检查和约束的工程设计可能是昂贵的,既包括原始计算资源,也包括构建和维护的工程时间。此外,这是另一个可能失败的系统!当然,有一些相对便宜的东西你可以从一开始就设计好,但是让我们承认,这些努力中有很多是典型的…后来加上去的。
另一方面,如果您没有预先做大量的一致性检查,当您发现坏数据时,作为数据科学家的您将被迫处理它。
那么,一个数据科学家能做些什么来处理这些乱七八糟的事情呢?
临时/探索过程
正如我之前提到的,这取决于所做的 ds 工作的类型。与生产系统或管道相比,分析和探索性研究是一件非常人性化和灵活的事情。由于这个过程中内置了大量的实验和探索,它天生更有能力处理奇异的数据错误,这些错误需要大量的工程工作来防止或检测。
在处理混乱的数据时,使用近似值的能力可能是我们拥有的最强有力的武器。考虑到我们所知道的一切是如何工作的,以及产生坏数据的错误的性质,至少可以推导出有用的近似值,至少可以提供部分信息的上限或下限。
正是由于这种使用降级数据集的能力,这就是为什么如果我被迫选择一方,我会投入更少的资源来确保非关键数据集上的预先数据一致性。在偶尔消费期间解决附带的 bug 会更有效率。
您仍然需要数据相当干净和可靠!但是你不应该试图为你能想象到的每一个黑天鹅事件提前计划。事情会出错,当它发生时你会处理它。
自动化流程
根据具体情况,数据问题可能会对模型产生巨大影响,或者根本没有影响。只有你这个模特设计师才能知道。但是即使有很大范围的可能性,我们还是可以谈论一些常见的情况。
如果数据问题已经存在很长时间了,您可能不需要立即采取任何措施,因为模型实际上是根据坏数据进行训练的,并且是在被判断为给出合理输出后启动的。具有讽刺意味的是,您需要测试您的模型是否能够处理接收干净的和错误修复的数据。这带来了各种关于模型原始有效性的认识论问题,但从纯黑盒输出的角度来看,它是可行的。
类似地,由于许多模型优先使用最近的数据,旧的和坏的数据有从系统中“老化”的趋势。如果修复花费的时间超过一个月或其他任何事情自我纠正的时间,那么修复历史数据可能就不值得了。
数据问题触发灾难性的重新分析和重写模型的情况也很少见(但并非闻所未闻),因为模型往往会将许多输入集中在一起。一个数据错误将需要影响一个真正广泛的区域来影响一组模型输入,因为几乎所有的模型都有一个试图最小化变量之间相关性的特征缩减步骤。
这种错误的一个例子是,如果重要的数据点以一种非常有偏差的方式被丢弃,就会在分布中引入一系列偏差。类似于一个系统,系统地不能识别来自大客户的购买,这些大客户只来自加利福尼亚州。希望这类错误足够大,能够很快被发现,因为它们会对业务中的其他事情产生重大影响。
所以我们应该接受数据质量退居二线的事实?
不要!我们不是擦鞋垫..
我要说的是,数据科学过程有更多自然的冲击吸收。数据质量的边际成本改善曲线与人在回路分析过程有很大的不同,在某一点上,说“好吧,我们的数据一致性保护措施是我们现在能够做到的最好的”是有道理的。
我们何时知道您必须改进数据一致性保护措施?
负责任的答案是,当你意识到一些流程和数据在你的业务中变得越来越重要,因此你应该加大投资。这意味着你需要做定期审查和积极主动。做好真的很难,我只在一些事情正在积极发展并且我正在积极思考这些问题的时候才会去做。
诚实的答案是,当你发现一个 bug,并意识到某件事有多重要时。随着系统的变化,这些事情很容易悄悄发生在我们当中最优秀的人身上。我们可能无法看到所有可能的变化,我们也无法 100%清楚地了解系统每个方面的副作用。
总是一种平衡的舞蹈。你永远不会对你所拥有的感到完全舒服,这种不舒服可能是一个好迹象,表明你接近一个可管理的点。
bamboo lib——无需编码即可学习和使用熊猫
原文:https://towardsdatascience.com/bamboolib-learn-and-use-pandas-without-coding-23a7d3a94e1b?source=collection_archive---------17-----------------------
Bamboolib In Action
熊猫的图形用户界面——适用于初学者和专家
你有没有因为用熊猫做数据探索和操纵而沮丧过?
有这么多方法做同样的事情,我被选择宠坏了,最终什么也没做。
对于初学者来说,问题正好相反,因为即使是简单的事情也没有适当的文档记录。对于门外汉来说,理解 Pandas 的语法可能是一件困难的事情。
那么应该怎么做呢?
bamboo lib的创作者有了一个解决这个问题的想法——为什么不给熊猫添加一个 GUI 呢?**
想法是 “不用编码学习使用熊猫。”这个想法开始可能很简单,但是我发现 Bamboolib 在数据探索和数据清理方面要好得多。
这个帖子是关于为你的数据设置和使用 Bamboolib 的。
安装 Bamboolib
安装非常简单,包括:
*pip install bamboolib*
为了让 bamboolib 与 Jupyter 和 Jupyterlab 一起工作,我需要安装一些额外的扩展。因为我喜欢使用 Jupyter Notebook,所以我通过以下命令安装了 Jupyter Notebook extensions:
*jupyter nbextension enable --py qgrid --sys-prefix
jupyter nbextension enable --py widgetsnbextension --sys-prefix
jupyter nbextension install --py bamboolib --sys-prefix
jupyter nbextension enable --py bamboolib --sys-prefix*
如果你想为 Jupyterlab 安装进程,这里有进程。
验证 Bamboolib 安装
要检查是否一切正常,您可以打开一个 Jupyter 笔记本,并执行以下命令:
*import bamboolib as bam
import pandas as pd
data = pd.read_csv(bam.titanic_csv)
***bam.show(data)****
第一次运行此命令时,会要求您提供许可证密钥。如果您想对自己的数据使用 bamboolib,就需要这个键。因为我想在自己的项目中使用 bamboolib,所以我从 Bamboolib 的创始人 Tobias Krabel 那里得到了密钥,他非常慷慨地将它提供给我查看。然而,你可以从 https://bamboolib.8080labs.com/pricing/买你自己的。如果你想在购买钥匙之前看到库的运行,你可以尝试一下现场演示。
一旦 bamboolib 被激活,有趣的部分就开始了。可以看到 Bamboolib 的输出是这样的。你可以选择玩它提供的选项。
因此,让我们用令人兴奋的数据源来尝试 Bamboolib,我们都已经看到了大量的数据。
为此,我将使用来自 Kaggle 的移动价格分类数据。在这个问题中,我们必须创建一个分类器,根据手机的功能预测手机的价格范围。让我们从 Bamboolib 开始。
*train = pd.read_csv("../Downloads/mobile-price-classification/train.csv")
bam.show(train)*
我们需要简单地调用bam.show(train)
来启动 Bamboolib。
轻松的数据探索
Bamboolib 对探索性数据分析有很大帮助。现在,数据探索是任何数据科学管道不可或缺的一部分。为数据探索和创建所有图表编写完整的代码是复杂的,需要大量的耐心和努力才能做好。我承认有时我会懈怠,没有足够的时间来做这件事。
Bamboolib 使整个数据探索练习变得轻而易举。
比如说。这里是您数据的 一瞥, 一旦您点击可视化数据框。
您可以看到每一列中缺少的值,以及唯一值的数量和一些实例。
但这还不是全部。我们还可以获得单变量的列级统计数据和信息。那么 让我们来了解一下我们的目标变量——价格范围。
在这里,我们深入研究目标列,可以看到单变量列统计数据以及目标列的最重要预测值。看起来 RAM 和电池电量是价格区间最重要的预测指标。很好。
我们来看看 RAM 是如何影响价格区间的。 我们可以为此使用二元图。
使用 seaborn 或 plotly 等标准 Python 库获得如此美丽的图形通常需要一些代码。虽然 plotly_express 通过为大多数图表提供简单的函数在这方面帮了很大的忙,Bamboolib 为我们自动创建了许多重要的图表。
以上,我们可以看到,随着 RAM 的增加,价格区间也在增加。我们还看到 RAM 变量的加权 F1 得分为 0.676。您可以对数据集中的每个变量都这样做,并尝试了解您的数据。
也可以导出这些图表的代码 用于某些演示/导出这些图表为 PNG。
为此,只需复制每个图表上方显示的代码片段。例如,您可以复制并运行代码来查看price_range
与ram
的对比,您将看到一个将这些图形下载为 PNG 的选项。在后端,它们都是 plotly 图形。
*bam.plot(train, 'price_range', 'ram')*
基于图形用户界面的数据管理
你有没有面临过忘记熊猫代码做某件事而去堆栈溢出,迷失在各种线程中的问题?如果是的话,这里有一份最小熊猫点心。或者您可以根据自己的喜好使用 Bamboolib。
Bamboolib 让事情变得如此简单,而不会迷失在代码中。您可以使用提供的简单 GUI删除列、过滤、排序、连接、分组、透视、融化(几乎是您想对数据集做的所有事情)。**
例如,这里我将删除目标列中缺少的值,如果有的话。您也可以添加多个条件。
最好的部分是它也给了我们代码。这里,删除缺失值的代码会自动填充到单元格中。
*train = train.loc[train['price_range'].notna()]
train.index = pd.RangeIndex(len(train))*
它的工作方式就像商业用户的 Microsoft Excel 一样,同时为高级用户提供所有的代码来分割数据。您可以尝试使用其他选项来熟悉一下。
下面是另一个如何使用 groupby 的例子。这实际上非常直观。
其代码被填充为:
*train = train.groupby(['price_range']).agg({'battery_power': ['mean'], 'clock_speed': ['std']})
train.columns = ['_'.join(multi_index) for multi_index in train.columns.ravel()]
train = train.reset_index()*
你可以看到它如何为我们照顾multi_index
以及ravel
,这有点难以理解和处理。
结论
Bamboolib 的 GUI 非常直观,我发现使用它绝对是一种享受。这个项目仍处于开始阶段,但这是一个多么好的开始啊。
我可以肯定地说,这个库对于想学习用 Pandas 编写代码的初学者来说是非常有用的,因为它为他们提供了访问所有必要功能的途径,而不会带来麻烦。
虽然我仍然会专注于了解熊猫的基础知识,并建议查看 Bamboolib 的输出来学习熊猫,但我想看看 Bamboolib 在未来会如何被采用。
请在评论中告诉我你的想法。
如果你想了解更多关于熊猫的知识,我想从密歇根大学调出一门关于 Python 数据科学入门的优秀课程,或者查看我以前关于如何与熊猫合作的帖子。
我以后也会写更多这样的帖子。让我知道你对他们的看法。在关注我或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系
禁止面部识别,这是一个危险的举动
原文:https://towardsdatascience.com/banning-facial-recognition-a-dangerous-move-ca591ff0a490?source=collection_archive---------21-----------------------
Wedjat Eye Amulet ca. 1070–664 B.C.
随着人们开始害怕面部识别,我们应该后退一步,重新评估这项技术和我们的选择。
为了透明起见,我认为我有责任声明我在计算机视觉行业工作。我不是用这篇文章来推动一家公司的议程或试图保住我的工作,而是为一个备受批评和误解的领域提供背景。
这是真的,谈论使用人工智能来调查城市会让人想起乔治·奥威尔警告过的反面乌托邦。知道某些政府如何利用这种技术并不能带来安慰。在过去的几个月里,人们一直在努力遏制计算机视觉的滥用。旧金山通过立法禁止市政当局使用面部识别技术。众议员奥卡西奥-科尔特斯在与算法正义联盟创始人的听证会上指出了一些担忧。最近, Buzzfeed 发布了一篇夸张的文章,要求彻底禁止所有面部识别技术。
面部识别技术是一个难以置信的新生领域。第一篇描述面部识别工作方法的论文发表于 1987 年,而 celeritous detection 发表于 2001 年。然而,这项技术在专利申请方面已经取得了长足的进步。Google 相册能够按照特定的人(和狗)对你的照片进行分类!)。脸书最近的照片崩溃事件显示了它识别照片中的人和情感的能力。
虽然这可能看起来令人印象深刻,甚至具有威胁性,但认识到面部识别的依赖性和局限性很重要。此外,像许多技术一样,我们应该承认总会有人滥用技术。这并不意味着这项技术没有善意的应用。
任何人工智能、机器学习或其他可怕的技术术语都是数学的应用。面部识别也没什么不同。该主题实现了线性代数和统计,以实现特定的目标。有多种方法用于实现面部检测,但一种基本方法涉及拍摄大量面部图像并将其提供给“训练者”。培训师确定图像和化妆之间哪些特征是相似的,我们认为什么是脸。这些不是我们想象中的特征,比如鼻子、嘴巴、两只眼睛等等。计算机不知道鼻子是什么。不,这些要素由一组离散的边、线、点和空间组成。从一个足够大和多样化的数据集中,这个训练器可以创建一个数学表达式。该表达式可以基于已经提取的特征在新图像上产生置信度得分。然后,外部用户可以声明他们认为能够证明成功结果的置信度分数。
这是一种简单的方法,更快、更精确的方法已经被开发出来。然而,它们的基本前提是相同的。这些算法依赖于大量的数据才能成功,它们产生的是置信度得分,而不是绝对答案。
这种方法有一个明显的问题。如果使用的数据集有明显的偏差,那么异常值将会引起问题。偏差会影响整个系统。其次,如果出现对置信度得分的误解,单个病例可能会被错误地处理。
这正是刑事调查案件中发生的情况。算法的设计者并没有天生地构建系统来选择某些少数群体、肤色或性别。一个更可能的解释是在训练阶段使用了同质数据集。如果数据集中使用的大多数人脸是年龄在 20 到 30 岁之间的白人男性,那么任何其他人脸都将被视为异常值,并报告有缺陷的置信度得分。在繁重的工程期限内,可能很难积累一个稳健的数据集,其中包含人口的现实代表。
报告的分数是误差的第二个来源。引入了第二层人为错误。如果向用户报告的结果没有置信度得分,那么解释器就没有其他信息可以采取行动。从工程角度来看,这是一个糟糕的设计。或者,如果产生了置信度得分,用户可能不理解置信度得分是如何得到的。这两个问题很可能是由于工程师、项目经理、销售人员和营销人员之间的沟通不畅而引起的。在这个分销链的某个地方,细节被忽略,最终用户对此一无所知。
已经提出了解决这些问题的规则。数据政策中的一些人提议公布数据。如果一个算法使用未知信息来得出结论,也许它的用户应该了解先验信息。科技公司会抱怨这破坏了竞争优势。
另一个解决方案是建立信心报告的标准。可以实施这样的法律,即算法本身不能基于某些置信度做出决定。他们可以向用户报告指标,但仍然给人以权威。这类法规将为科技公司创造更高的标准。这些法律可能适用于高风险场景,如刑事和国防,但不应普遍适用。某些令人兴奋的技术,如自动驾驶汽车,是建立在基于信心得分做出决策的基础上的。
规范智能
综上所述,讨论一下为什么完全禁止这种新生技术是危险的是很重要的。在过去,我们在技术的早期阶段就将其妖魔化并加以惩罚,这是我们今天要付出的代价。核能就是一个最好的例子。核技术因其在武器上的应用而声名狼藉,这是理所当然的。切尔诺贝利和福岛事故也无济于事。然而,在当今时代,核能实际上可能是我们减少化石燃料消耗和扭转气候变化影响的最佳机会。不幸的是,提出这样的技术已经成为政治自杀,现在被忽视。
联邦对大麻的驱逐是另一个例子。在极少进行研究的情况下,该药物在美国被宣布为非法。我们现在正在了解该药物的一些健康益处,但合法化和进展遭到了怀疑的反对。
如果我们在面部识别技术上鲁莽行事,我们不知道我们正在摧毁哪个科学和研究领域。也许有一些医学应用将有助于识别面部瑕疵和异常值,否则无法检测出来。一些公司正在车内实施面部识别系统,以提高驾驶员的注意力和安全性。这个领域仍未被充分开发。
禁止一项技术不仅从科学好奇心的角度来看是危险的,从立法的角度来看也是危险的。当规章到位时,可以测试、检查实践,并且可以进一步编辑规章。可以发现并封闭循环孔。压迫性的限制可以重新评估。当一项彻底的禁令实施后,任何废除的企图都几乎是不可能的。
用 Matplotlib 实现 Python 中的条形图竞赛
原文:https://towardsdatascience.com/bar-chart-race-in-python-with-matplotlib-8e687a5c8a41?source=collection_archive---------1-----------------------
~在大约不到 50 行的代码中
Bar Chart Race animation showing the 10 biggest cities in the world
原载于pratapvardhan.com
条形图比赛已经有一段时间了。今年,他们席卷了社交媒体。它始于马特·纳瓦拉的推特,这条推特被点击了 1000 万次。然后, John Burn-Murdoch 使用 d3.js 创建了可复制的笔记本,其他人开始创建他们的种族。然后,fluorescent studio 发布了面向非程序员的赛程图。从那以后,数百场比赛在互联网上被分享。
与 Matplotlib 竞赛
我想知道——用 Jupyter 和 Matplotlib 用 Python 重新制作 JBM 的版本有多容易?事实证明,在不到 50 行代码中,您可以使用 Matplotlib 在 Python 中合理地重新创建可重用的条形图比赛。
这是我们想要创造的。
让我们编码
现在,您已经看到了输出,我们将逐步构建它。
的默认风格是为许多常见的情况设计的,但对我们的审美来说绝不是最佳的。因此,我们的大部分代码将进入样式(轴,文本,颜色,刻度等)
在您的Jupyter
笔记本中,导入相关库。
用pandas
阅读城市人口数据集。我们只需要 4 列来与'name', 'group', 'year', 'value'
一起工作。典型地,一个name
映射到一个group
(城市到洲/国家),每个year
有一个value
。
数据转换
我们很有兴趣看到前 10 名value
是给定的year
。使用熊猫变换,我们将得到最高的10
值。
基本图表
现在,让我们绘制一个基本的条形图。我们首先创建一个图形和一个轴。然后,我们使用ax.barh(x, y)
绘制水平条形图。
注意,最高的横条在底部。我们需要扭转这种局面。
颜色,标签
接下来,让我们基于组添加值、组标签和颜色。我们将使用colors
和group_lk
来给条形添加颜色。
group_lk
是name
和group
值之间的映射。
现在,我们只剩下设计图表的样式了。
波兰式
为了方便起见,让我们将代码移到draw_barchart
函数中。
我们需要以下项目的风格:
- 文本:更新字体大小、颜色、方向
- 轴:移动 X 轴到顶部,添加颜色和字幕
- 网格:在横条后添加线条
- 格式:逗号分隔的值和轴标记
- 添加标题、致谢名单、装订线空间
- 移除:方框、y 轴标签
我们将为此再添加十几行代码。
我们现在有一个相同的图表。
动画种族
为了制作比赛的动画,我们将使用matplotlib.animation
中的[FuncAnimation](https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.animation.FuncAnimation.html)
。[FuncAnimatio](https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.animation.FuncAnimation.html)
通过反复调用一个函数(在画布上绘制)来创建动画。在我们的例子中,这个函数将是draw_barchart
。我们也使用frames
,这个参数接受你想要运行draw_barchart
的值——我们将从year
1968 运行到 2018。
现在,我们有了它,用 matplotlib 在笔记本中进行条形图竞赛。
您可以将animator
对象保存为视频/gif 或在笔记本中播放。
奖金:xkcd 式!
将 matplotlib 图转换成 xkcd 风格的图非常容易。您可以使用plt.xkcd
简单地打开xkcd
草图风格绘图模式。
这里是动画 xkcd 风格的条形图比赛。
自己动手
比赛动画的完整代码在这里,你也可以在谷歌实验室上玩它。尝试更改数据集、颜色并分享您的比赛。
Matplotlib 是一个巨大的库——能够调整绘图的每个方面是非常强大的,但对于高度定制的图表来说,这可能很复杂/耗时。至少,对于这些条形图比赛,这是相当快!
Base R 脚本练习:将 RIS 文件转换为格式良好的 XML 文档。
原文:https://towardsdatascience.com/base-r-scripting-excercise-converting-a-ris-file-to-a-well-formed-xml-document-ddda70a96b3?source=collection_archive---------24-----------------------
介绍
这篇文章的目的是分享我遇到的一个脚本问题。我没有太多应对这类挑战的经验,所以我认为这是一个分享和寻求反馈的好机会。
挑战
编写一个脚本,将任何。RIS 文件转换成格式良好的 XML 文档。
- 包括假设和详细注释。
- 该脚本不得有任何基础语言之外的依赖。
- 该脚本应该能够防止意外误用。
- 每条记录都应该放在一个文章标签中。
虽然我知道其他语言可能更适合这些类型的过程,但我还是选择用 R 编写脚本来探索这个过程。
第一部分-理解。RIS 和。XML 格式
RIS(研究信息系统)
ris 文件格式是一种标记格式,是为标准化书目信息而创建的。例如,生命科学和生物医学信息的免费书目数据库 MEDLINE 使用 ris 格式进行引用。
让我们看看它是什么样子的:
如你所见,基本结构是:每一行包含一个标记和一个用“-”分隔的值。每个 RIS 记录以“TY”标签(引用类型)开始,以 ER 标签(引用结束)结束。这里有更多关于 ris 格式的信息。
XML(扩展标记语言)
XML 本质上就像任何其他标记语言(HTML)一样,通过使用
)。这显示了 XML 的主要优势。标签可以更好地描述它们所包含的信息。当试图做除了在 web 浏览器中显示该信息之外的任何事情时,这是有利的。由于其简单性和标准化,XML 在数据交换和存储方面也很流行。这里有更多关于 XML 的内容。
让我们快速看一个例子:
现在让我们来看看格式约束,这样我就可以确保文件的格式正确。这些是主要的限制因素:
- XML 文档可以以 XML 声明开始(即)
- 任何特殊字符(“<> &”)都不能出现,除非是在执行其角色时。
- 开始标签、结束标签被正确地嵌套
- 标记名区分大小写;开始标记和结束标记必须完全匹配。
- 标记名不能包含任何字符!"#$%&'()*+,/;<=>?@[]^`{|}~,也不是空格字符,不能以“-”、“”开头或一个数字。
- 单个根元素包含所有其他元素。
更多关于结构良好的 XML 文档和约束的信息。
第二部分-剧本
假设:
RIS 文件遵循标准 RIS 标签格式,包括:
- 每张 RIS 唱片都以“唱片结束”标签结尾:“呃-”
- 每个 RIS 标签和值由“-”分隔
- 每个 RIS 标签和值都在各自的行上
# naming function and function argumentsris2xml <- function(x = "", root = "root_element", save = FALSE, file_name = "new_file"){# read lines
ris2 <- readLines(x, encoding = "UTF-8")# seperating articles
df <- data.frame(article = NA, ris = ris2, stringsAsFactors = FALSE)
end_of_records <- rev(grep(pattern = '^ER -', ris2))
article = length(end_of_records)
for(i in end_of_records){
df$article[1:i] <- article
article = article - 1
}# removing ER lines and empty Lines
df <- df[-end_of_records,]
df <- df[grep(pattern = '\\S', df$ris ),]# splitting tags and values
split <- strsplit(df$ris, split = " -")
df$tags <- sapply(split, "[[", 1)
df$values <- sapply(split, "[[", 2)# trim any extra white space
df$tags <- trimws(df$tags, which = "both")
df$values <- trimws(df$values, which = "both")
# xml special character restraints
df$values <- gsub('<', '<', df$values)
df$values <- gsub('>', '>', df$values)
df$values <- gsub('&', '&', df$values)
df$values <- gsub("'", ''', df$values)
df$values <- gsub('"', '"', df$values)######## Function for finishing steps after tag constraints #########
finish <- function(){
# putting values in tags
for(i in 1:nrow(df)){
df$tagged[i] <- paste0('<', df$tags[i], '>', df$value[i], '</', df$tags[i], '>', collapse = "" )
}# adding article tags and I2E tag
document <- data.frame(article= unique(df$article), body = NA)# article tags
for(i in document$article){
vect <- unlist(df[df$article == i, "tagged"])
temp <- paste0(vect, collapse = "")
document[document$article == i, "body"] <- paste0("<Article>", temp, '</Article>', collapse = "")
}# adding root tag & xml tag
body <- paste0(document$body, collapse = "")
document_final <- paste0('<?xml version="1.0"?>','<', root, '>',body,'</', root ,'>', collapse = "")
# return xml document
return(document_final)
# save file if user chose to
if(save == TRUE){
write(document_final, file = paste0(file_name, ".xml"))
}
}
######################################################################
# Enforcing XML tag constraints#finding invalid tags
invalid <- grep("[\\[\\!\"#\\$%&'\\(\\)\\*\\+,/;<=>\\?@\\[\\\\\\]\\^`\\{\\|\\}~]|(^\\d)|(^-)|(^\\.)", df$tags, perl = TRUE)# if there are invalid tags: print warning and print the invalid tags
if(length(invalid) > 0){
print('WARNING: there may be invalid tag names. please check to make sure the tags follow the xml constraints')
print("The following tags are invalid: ")
print(df$tags[invalid])# give the user the option to re-write the tags
re_write <- readline(prompt = "to re-write these tags please do so in order and seperated by a comma: ")
re_write <- unlist(strsplit(x = re_write, split = ","))
re_write <- trimws(re_write, which = "both")# check user inputs for validity
re_invalid <- grep("[\\[\\!\"#\\$%&'\\(\\)\\*\\+,/;<=>\\?@\\[\\\\\\]\\^`\\{\\|\\}~]|(^\\d)|(^-)|(^\\.)", re_write, perl = TRUE)# make sure the number of inputs match & inputs meet contsraints before finishing script
if((length(re_write) == length(invalid)) & (length(re_invalid) == 0)){
df[invalid, "tags"] <- re_write
# constraints are met so finish script
finish()
# if contsraints not met, print error and exit.
}else{
print("Error: re-writing tags not valid. Please try function again")
}
}else{
# constraints are met so finish script
finish()
}}
参数:
- x = " ":要转换的文件
- root = "root_element ":将保存文档其余部分的根标签
- save = FALSE : T/F 如果用户想要保存转换后的文件。
- file_name = "new_file ":保存转换后文件的文件名。
结论
仅此而已。至于测试,我通过一些 xml 验证器运行输出文件,并在 R 中使用一些 XML 解析器来确保格式正确。我已经能想到我还可以增加几个步骤,比如在继续之前检查 RIS 的文件以确保它符合假设。我知道这个脚本远非完美,但这是一种我从未有过的用 R 工作的有趣方式。我喜欢听想法!感谢阅读。
使用 NLTK 的基本情感分析
原文:https://towardsdatascience.com/basic-binary-sentiment-analysis-using-nltk-c94ba17ae386?source=collection_archive---------1-----------------------
"你最不满意的顾客是你最大的学习来源."—比尔·盖茨
那么客户怎么说呢?
在今天的背景下,事实证明很多。社交媒体打开了顾客意见的闸门,现在顾客意见大量自由流动,供企业分析。今天,使用机器学习的公司能够以文本或音频的形式提取这些意见,然后以前所未有的规模分析它们背后的情绪。情感分析,观点挖掘,随你怎么说,如果你有产品/服务要卖,你就需要在上面。
当以电子方式捕捉时,客户情绪——超越事实的表达,传达情绪、观点和情感——具有巨大的商业价值。我们谈论的是客户、潜在客户、患者、投票者和意见领袖的声音。”——塞思·格里姆斯
从媒体上的用户评论到分析股票价格,情感分析已经成为几乎所有行业中无处不在的工具。例如,下图显示了易贝的股价走势,情绪指数是基于对提到易贝的推文的分析而创建的。
Figure 1: eBay Stock Prices Vs. Sentdex Moving Average
什么是情感分析?
Techopedia 对情感分析的定义如下:
情感分析是一种数据挖掘类型,通过自然语言处理(NLP)、计算语言学和文本分析来测量人们的意见倾向,这些技术用于从网络中提取和分析主观信息——主要是社交媒体和类似的来源。所分析的数据量化了公众对某些产品、人物或想法的情绪或反应,并揭示了信息的上下文极性。情感分析也称为意见挖掘。
有两种广泛的情感分析方法。
纯统计数据:
这类算法将文本视为单词包(BOW),其中单词的顺序和上下文被忽略。原始文本被过滤掉,只剩下被认为带有感情色彩的词。对于这个博客,我将尝试这种方法。这种模型没有利用对特定语言的理解,而仅仅使用统计测量来对文本进行分类。
统计学和语言学的结合:
这些算法试图结合语法原则、各种自然语言处理技术和统计数据来训练机器真正“理解”语言。
基于分析生成的输出类型,情感分析也可以大致分为两类。
分类/极性——那段文字是“积极的”、“中性的”还是“消极的?”在这个过程中,你试图给一段文字贴上积极或消极或中性的标签。
标量/程度 — 给出一个预定义等级的分数,范围从高度肯定到高度否定。例如,下图显示了基于各种选举候选人推文的情绪分析。在这种情况下,情绪是以标量形式来测量的。
Figure 2: How Twitter Feels about The 2016 Election Candidates
在我的数据科学训练营期间,我尝试使用 NLTK 库构建一个基本的情绪分析工具。我找到了一个漂亮的 youtube 教程,并按照列出的步骤学习如何进行基本的情绪分析。虽然该教程侧重于分析 Twitter 情绪,但我想看看我能否将电影评论分为正面或负面。我发现了一个包含 25000 条 IMDB 评论的标签数据集。txt 文件分为两个文件夹,用于负面和正面评论。
流程:
我在我的 Jupyter 笔记本上导入了以下库,并从它们各自的文件夹中读取了正面和负面的评论。
制作单词包(BOW): 对于我们的单词包(BOW),从技术上来说,我们可以包含所有独特的单词。然而,在我们的分析中包括所有独特的单词在计算上可能是昂贵的,甚至是不必要的。例如,评论中女演员的名字不会给出关于评论情绪的任何信息。所以,我们需要变得聪明,选择信息最丰富的单词。
对于这个小范围的项目,也是在教程的指导下,我只从特征中选择了形容词,基于这样一个假设,即形容词是积极和消极情绪的高度信息。对于每一篇评论,我都去掉了标点符号,标记了字符串,去掉了停用词。请查看我的另一个博客,了解如何使用 NLTK 执行这些基本的预处理任务。
接下来,为了获得所有形容词的列表,我执行了词类(在上面提到的我的博客中也讨论过)标记,并创建了我们的 BOW 或在这种情况下的形容词包。我称这个列表为“所有单词”,它还需要另一轮过滤。
接下来,为了挑选信息最丰富的形容词,我使用 nltk 创建了 all_words 中单词的频率分布。FreqDist()方法。我列出了所有单词中出现频率最高的 5000 个形容词。至此,all_words 已经准备好作为我们最后的弓了。
为每个评论创建特征:对于每个评论,我创建了一个元组。元组的第一个元素是一个字典,其中的关键字是 BOW 的 5000 个单词中的每一个,如果该单词出现在评论中,则每个关键字的值为 True,否则为 False。第二个元素是该标签的标签,“pos”表示正面评价,“neg”表示负面评价。
#example of a tuple feature set for a given review
({'great': True, 'excellent': False, 'horrible': False}, 'pos')
然后,我将元组列表(从这里开始称为 feature_set)分成训练集(20,000)和测试集(5,000)
有趣的部分:机器学习!!!
既然我已经准备好了我的特性、训练和测试集,我的下一步就是尝试一个普通的基础模型。对于我的基本模型,我使用了 NLTK 的朴素贝叶斯分类器模块。该模型的准确率为 84.36%。这对于一个基本模型来说是非常好的,考虑到训练数据的规模,这并不奇怪。右图显示了未归一化和归一化预测的混淆矩阵。
上图(左图)显示了该模型中 15 个最具信息性的特征。与它们相关的比率显示了每一个相应的单词在一类文本中出现的频率比其他单词多多少。这些比率被称为似然比。例如,“糟糕”这个词在负面评价中出现的几率是正面评价的 13 倍。
为了进一步评估该模型,我使用 sci-kit learn 计算了 f1_score,并创建了一个混淆矩阵。f1 _ 得分为 84.36%。归一化混淆矩阵显示,该模型正确预测了 83%的正面评论和 85%的负面评论。
接下来,我尝试在训练集上训练其他分类算法,以找到得分最高的模型。我用了,多项式朴素贝叶斯,伯努利朴素贝叶斯,逻辑回归,随机梯度下降和支持向量分类器。NLTK 有一个名为 SklearnClassifier 的内置 Scikit 学习模块。这个 SklearnClassifer 可以继承通过 Scikit Learn 导入的任何模型的属性。您所要做的就是使用特定的 Scikit 学习模块作为参数来启动 NLTK SkleanClassifier。
不同车型的 f1 分数如下所示。他们的表现多少有些相似。然而,这两个朴素贝叶斯模型表现稍好。
MNB: 0.845,BNB: 0.8447999,对数规:0.835,新币:0.8024,SVC: 0.7808
最后一步:建立一个集合模型
接下来,我想看看所有这些模型的预测能力是否结合在一起,也就是说,我们能否达到更好的分数?合乎逻辑的下一步是建立一个集合模型。集合模型结合了上述每个模型对每个评论的预测(投票),并使用多数投票作为最终预测。
为了避免不得不重新训练模型(因为每个模型需要大约 8 到 12 分钟来训练),我使用 pickle 存储了所有的模型。Pickle 是一个非常有用的 python 模块,它允许您在关闭内核之前保留可能需要很长时间创建的 python 对象。
为了构建集成模型,我构建了用分类器列表初始化的 EnsembleClassifier 类。重要的是,使用奇数个分类器作为集成的一部分,以避免出现平局。该类有两个主要的方法, classify :返回预测的标签, confidence :返回预测的置信度。这个度的衡量方法是(获胜票数)/总票数。
接下来,我使用 pickle 加载了所有的模型,初始化了一个集合模型对象,并将测试集中的特性列表输入到模型中。如下所示的集合模型的 f1 分数是 85%。比我们之前使用原始朴素贝叶斯模型获得的最高 f1 分数 84.5%略有增加。
同样的类也可以用来对一个评论进行实时分类。下面的函数接收单个评论,为该评论创建一个特征集,然后使用集成方法给出一个预测。输出为您提供了一个标签以及对该标签的信任度。
为了证明这一点,我从烂番茄中收集了一些关于惊奇队长的评论。我有意选取了两个不那么极端的评论和两个非常极端的评论来观察模型的表现。结果证明这个模型做得很好!该模型对不太对立的评论 text_a 和 text_c 不太确定,但是以高得多的置信度识别出对立的 text_b 和 text_d。
就是这样!
你可以在我的 GitHub 库和我用作指南的原始网页中找到这个项目的示例代码。在我的 Github 中,我已经包含了一个 live_classifier.py 文件和我训练过的模型作为 pickled 文件。一旦你克隆了回购,你就可以直接在你的终端上运行这个 live_classifier.py 文件,然后使用情感()函数对你在网上找到的任何评论进行分类。更好的是,自己补复习!
我现在对探测文本中的讽刺或挖苦感兴趣。讽刺是微妙的,甚至人类也很难理解。仅仅是为了它,我引用了我最喜欢的作家库尔特·冯内古特的一句话来测试集合模型,他以讽刺作品而闻名。事情是这样的:
“一切都很美好,没有任何伤害”——库尔特·冯内古特
如果我之前没有提到他的工作性质,我猜大多数人会认为这句话有积极的意义。然而,考虑到引用的上下文,人们可能会认为这个引用有更深的损失情绪。我的非常简单的情绪分析模型将该报价标注为 100%肯定。这并不奇怪,因为该模型一开始就没有被训练识别讽刺。
我想以下面这段关于情感分析的细微差别及其可靠性的引言来结束我的演讲。
情感分析会 100%准确或接近准确吗?
可能不会,但这并不意味着是一件坏事。这并不是因为人们不够聪明,无法最终制造出真正理解语言的计算机。相反,这真的是不可能的,因为很少 80%的人同意文本的情感。——http://sentdex.com/sentiment-analysis/
来源:
报价 1—http://breakthrough analysis . com/2012/09/10/typesofsentimental analysis/
图 1— Ebay 股票价格—http://send ex . com/how-accurate-is-sensition-analysis-for-stocks/
图 2——推特对 2016 年大选候选人的感受——https://modern data . plot . ly/elections-analysis-in-r-python-and-gg plot 2-9-charts-from-4-countries/
灵感—https://python programming . net/情操-分析-模块-nltk-教程/
每个数据分析师都应该知道的使用 Python 的基本数据分析技术,第二部分。
原文:https://towardsdatascience.com/basic-data-analysis-techniques-every-data-analyst-should-know-part-ii-412e28af849d?source=collection_archive---------13-----------------------
基本分析技巧
迈向经验丰富的分析师的第一步
这是基础数据分析技术系列的后续,每个数据分析师都应该知道。对于那些还没有读过第一部分的人,可以在这里找到它。
在第一部分中,我们介绍了初级数据分析师应该掌握的第一套技术,我们回顾了这些技术:基本过滤、多条件过滤、聚合和连接。
在这一部分中,我们将在第一部分的基础上,引入一组新的技术:
- 转换数据类型
- 透视数据
- 创建条件列
- 多功能聚合
我们将再次使用两个 Python 库进行分析,它们是:[**pandas**](http://pandas.pydata.org/pandas-docs/stable/)
& [**numpy**](https://docs.scipy.org/doc/numpy/reference/)**.**
如果您还没有安装这两个包,请使用下面的代码来安装它们:
蟒蛇:
**conda install -c anaconda numpy****conda install -c anaconda pandas**
PIP:
**pip install pandas****pip install numpy**
熊猫简介 dtypes 。
pandas 中的每一列(系列)都有一个分配给它的类型,这是指存储在该列中的数据类型。
熊猫最基本的类型如下:
- 对象,即文本数据,通常被称为
**string.**
- 浮点数,是具有小数精度的数(分数),通常称为浮点数。
- 整数,均为整数。
为什么在每一列中使用正确的类型至关重要?因为它将定义您可以对数据执行哪些操作。
例如,每当一个列被定义为**string**
时,您就不能对它们执行计算。例如,我们可以创建一个 pandas DataFrame,它有一个包含数字的 values 列,但是作为 object dtype。
如果我们用下面的代码检查这个数据帧的数据类型:
**print(df.types)**
我们得到以下输出:
dtypes
正如我们所看到的,我们的值列位于字符串形式的对象 dtype 中。因此,如果我们试图对这些值进行计算,我们将得到一个错误或错误的输出:
例如,取这些值的平方:
**df[‘Value’] ** 2**
会给出一个类型错误:
乘以 2 不会产生错误,但会给出错误的输出:
它不会引发错误的原因是,在 Python 中,我们可以通过相乘来连接字符串:
1.转换数据类型
因此,为了防止这些错误或错误的输出,我们必须将列的类型转换为正确的类型。在熊猫身上,我们有[**Series.astype**](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.astype.html)
的方法。
此方法将您要转换成的 dtype 作为参数:
**df[‘Value’].astype(int)**
将该列转换为**int32**
:
重要提示:这不是【原地】。所以我们没有覆盖数据帧中的原始列。为此,我们需要以下代码:
**df[‘Value’] = df[‘Value’].astype(int)**
如果我们再次检查数据帧的数据类型,我们可以看到转换正确进行:
1.1 转换日期时间
datetime 的转换不同于 pandas 中的其他 dtypes,因为您有许多不同的格式来存储日期:
- 29–04–2019,格式:日-月-年
- 29/04/2019 18:23:09,格式:日/月/年时:分:秒
- 04–29–2019,格式:年-月-日
这些只是许多可能性中的几种,还有一些格式会变得相当复杂。我们不会在这些系列中讨论这些,但是我们会在我的另一个系列中讨论,这个系列叫做用 Python 处理时间序列,它将很快出版。
在 pandas 中,有几种方法可以将对象类型转换为日期时间,现在我们来看两种最常用的方法:
[**pandas.to_datetime**](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.to_datetime.html)
[**Series.astype**](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.astype.html)
在我们深入一些例子之前,我们必须首先用一个 datetime 列扩展我们的数据帧,我们可以用一个表示日期的字符串列表来做到这一点:
**df[‘Date’] = [‘2019–04–23’, ‘2019–04–24’, ‘2019–04–25’, ‘2019–04–26’]**
这给了我们下面的数据框架:
如果我们看看**print(df.dtypes)**
的产量。我们看到我们的**Date**
列是对象类型(字符串)。
方法 1: pd.to_datetime
**to_datetime**
函数接受一列作为输入,所以在我们的例子中是**df['Date']**
。总代码如下所示:
方法 2: Series.astype
在前面的例子中,我们使用了**astype**
将字符串转换成整数。这次我们想要的是 numpy 模块中的日期时间类型**datetime64[ns]**
,在这里可以找到。所以我们可以将它传递给我们的**astype**
方法,并将我们的字符串转换成日期时间:
2.透视数据
有时,需要创建特定的概视图,并以特定的方式汇总数据,以便提高可读性,此外,由于数据是聚合的,因此更容易看到有价值的信息。
旋转是上述场景中经常使用的技术之一。它使您能够聚合数据,同时转换数据,以便索引和列被原始数据帧中两列的分类数据所替换。
source: pandas docs
说够了,让我们在熊猫身上试试这个方法。首先,我们需要一个新的数据框架,这是我们自己创造的:
正如我们在数据框架中看到的,每个公司的每个部门都重复了三次,同样也重复了三次。我们可以在熊猫身上用[**pivot_table**](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.pivot_table.html)
的方法汇总这个数据。
该方法采用了许多参数,您可以在文档中找到这些参数,但是现在我们将研究其中的三个参数:
- 索引:要设置为索引的列
- 列:对于每个唯一值,将被转换为新的列的列。
- 值:哪一列将是每个单元格中的值。
因此,在我们的示例中,它将如下所示:
3。创建条件列
处理数据时,可能需要根据表中已有的列向表中添加更多信息。这些列被称为条件列,因为它们的信息依赖于其他列。
如果我们看一下关于公司和部门规模的表格:
我们可能想要区分大的部门和小的部门,并在名为 size_indicator 的新列中对其进行定义。
现在我们把大部门的门槛定在 100。因此,如果我们用 伪代码 写出我们的逻辑,它将如下所示:
**if Employee >= 100, then "Big"
else "Small"**
在 Python 中,我们可以以多种方式应用这种逻辑,我们将看看两种最常用的方法:
- numpy 在哪
- 列表理解
3.1 带有 numpy.where 的条件列
因为我们要使用 numpy 模块,所以我们必须首先导入这个模块:
**import numpy as np**
在 numpy 中有一个**.where**
方法,工作方式如下:
**np.where(condition, value if true, value if false)**
所以在我们的例子中我们必须传递下面的方法:
- 条件:
**df['Employees'] >= 100**
- 值为真:
**"Big"**
- 假值:
**"Small"**
因此,这将导致以下结果:
3.2 列表理解的条件列
列表理解是一种方法,与创建列表时使用和 if 循环的相比,这种方法可以显著提高代码速度。
and if 循环示例:
相同的列表创建,但是具有列表理解:
回到我们的数据,我们可以对 list comprehension 应用相同的逻辑来创建我们的 Size_indicator 列:
4.多功能聚合
在第一部分的中,我们已经用熊猫的 groupby 函数查看了聚合数据。我们能够在应用 groupby 时应用单个函数,例如组的max
或mean
。
在 pandas 中,当应用 groupby 来创建更广泛的概览时,您必须能够应用多种功能。
这可以通过使用 聚合 方法来实现。我们可以向该方法传递一个字典,其中包含我们想要应用的列名和函数:
如上所述,我们按公司分组,取员工的总和和平均值以及尺码指标的计数。
这就是第二部分的:每个数据分析师都应该知道的使用 Python 的基本数据分析技术。
你可以在我的 GitHub 上以 Jupyter 笔记本的形式找到这篇文章的代码:链接
对于任何问题或其他讨论,请随时评论!
期待第三部分,在那里我们会看到一些新的技术!
每个数据分析师都应该知道的基本数据分析技术,使用 Python。
原文:https://towardsdatascience.com/basic-data-analysis-techniques-every-data-analyst-should-know-using-python-4de80ab52396?source=collection_archive---------10-----------------------
基本分析技巧
迈向经验丰富的分析师的第一步
在我作为数据分析师的日常工作中,我会看到各种各样的数据和来自客户的各种各样的分析请求。我注意到的是,你在大多数项目中需要的某些基本技术,与你正在从事的项目类型无关。我相信每个数据分析师/科学家都应该对这些技术有很好的理解。因此,本文的目标是带领读者了解这些技术,并在基础层面上解释这些技术。
这些是我们将浏览和讨论的主题:
- 基本过滤
- 多条件过滤
- 聚合
- 连接
对于我们的分析,我们将利用 Python 中的[**pandas**](https://pandas.pydata.org/)
库。因此,如果您还没有安装这个库,请在您的命令提示符下使用以下代码之一来安装 pandas:
# If you use Anaconda, type the following in anaconda prompt
conda install -c anaconda pandas# If you use pip, type the following in command prompt
pip install pandas
此外,我假设你已经对 Python 和 pandas 库有了基本的了解。但是不要担心,如果你还没有接触到上述任何一个,我们将从头到尾检查一遍。
我们的数据集
为了能够通过提到的技术,我们需要数据。我们可以导入一个**csv**
文件或者一个**excel**
文件,但是现在我们保持简单,仅仅创建一个关于熊猫的小数据集。
下面的代码将生成一个熊猫数据帧:
这给了我们下面的数据框架:
DataFrame 1
从上面可以看出,它包含 ID、值和日期。
1.基本过滤
现在我们加载了 pandas 模块并创建了一个数据集,我们可以从第一项技术开始。当您想要基于列中的值获得数据的子集时,我们讨论的是过滤数据。
在熊猫身上,我们有多种方法做到这一点,现在我们来看看最常见的几种:
- 使用带方括号
**[]**
的布尔索引 - 通过
**.loc**
使用布尔索引
所以用方括号过滤如下:
pandas 中过滤背后的逻辑是将条件传递给方括号中的数据帧:
*df[condition]*
并给出了以下输出:
Filtering with square brackets
用过滤。loc* 看起来非常相似:***
正如预期的那样,它给出了相同的输出,因为我们应用了相同的滤波器
Filtering with .loc
首选用哪个?对于基本过滤器,正如我们在上面看到的,没有区别或偏好,它归结为你喜欢什么代码语法明智。但是当你想对你的数据进行更高级的选择时,**.loc**
提供了更复杂的选择和切片。但现在不用担心这个。
2.带条件过滤
我们应用了我们的第一个过滤器,它非常简单。但是,假设您想要应用一个具有多个条件的过滤器。我们如何在熊猫身上做到这一点?为此,我们研究了 Python 操作符。
2.1&运算符 例如,您要过滤所有**ID**
等于 C1、**Value**
大于 100 的行。
为了应用这个过滤器,我们必须用**&**
操作符链接两个条件。看起来像下面这样:
并将返回以下输出:
Filtering with and operator
正如预期的那样,我们返回了一行,因为只有这一行符合我们在过滤器中设置的条件。
2.2 |操作符
Python 中的**|**
运算符代表**or**
,如果满足其中一个条件就会返回**True**
。
我们可以通过应用以下过滤器来显示这一点:给我们所有**date**
晚于 2019–04–10或* **Value**
大于 100 的行。***
在 Python 代码中,这将如下所示:
并将返回以下输出:
Filtering with or operator
正如所料,返回的所有行的值都大于 100 或的日期在 2019-04-10 之后。
3.协议
有时需要聚合数据,以便创建特定的概视图或进行一些计算。在熊猫中,我们用**groupby**
来表示这一点。
那么 groupby 到底是什么?如果我们引用熊猫文献的话:
***“分组依据”指的是涉及以下一个或多个步骤的过程:
根据某些标准将数据分成组。
将功能独立应用于每组。
将结果组合成一个数据结构。
因此,基本上它是根据一些指标对你的数据进行分组,使你能够对这些分组采取一些行动。
3.1 Groupby #1:获取总和
让我们来看一个例子。假设我们想根据**ID**
得到每组的总数**value**
。这就像 Python 代码中的以下内容:
这将为我们提供以下输出:
Aggregation with sum
如果我们再看一下数据帧,我们会发现这是正确的:
Original dataframe
例如,ID A1 的总值是**100 + 120 = 220**
,这是正确的。
3.2 Groupby #2:获取最高日期
熊猫提供了一个大范围的功能,您可以在使用 groupby 后在您的组上使用。再来看一个。例如,我们可以通过使用.max()
函数获得每组的最高日期。
看起来会像这样:
并且会给我们以下输出:
Aggregation with max date
4.连接
连接是基于一个公共列以并排的方式组合两个数据帧。大多数时候这些列被称为**key columns**
。
术语**join**
源于数据库语言 SQL,之所以需要它是因为 SQL 数据库的数据建模大部分是通过使用关系建模来完成的。
连接有很多种类型,您的输出将基于您执行的连接类型。因为这是入门教程,我们就看最常见的:**inner join**
。在本系列的后面部分,我们将研究更复杂的连接。
内连接来源于**venn diagrams**
,代表两个集合的内(交集)部分。因此,当我们将它转换成我们的数据时,一个内部连接返回出现在两个数据帧中的行。**
4.1 我们的数据集
因为我们想要合并两个数据帧,所以我们将创建新数据。这两个假想数据集代表客户主表和订单表。
使用以下代码,我们创建了两个新的数据帧:
它们看起来如下:
dfA: Customers master
dfB: Orders
因此,我们可以对这些新数据进行的一个逻辑分析是,获取 orders 表中每个订单旁边的客户的姓名和城市。这是一个典型的**join**
问题,按行匹配两个数据帧,并用更多的列丰富数据。在这种情况下,我们的键列是**Customer_ID**
。
在熊猫中,我们使用[**merge**](https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html)
的方法进行接合。我们将向该方法传递以下参数:
- 您要连接哪个数据框架(dfA,dfB)。
- 什么是关键列(Customer_ID)。
- 要执行的联接类型(内部)。
我们可以在 merge 方法中使用比上面列出的更多的参数,但是现在这些已经足够了。
在 pandas 中,我们要执行的合并看起来像下面这样:
并且输出如我们所料,在每个对应的**customer_ID**
旁边添加了 name 和 city 列。
Inner join
这就是本部分的:每个数据分析师都应该知道的基本数据分析技术,使用 Python。
你可以在我的 GitHub 上以 Jupyter 笔记本的形式找到这篇文章的代码:链接
如果这篇文章对你有用,请考虑给这篇文章点个赞,并与朋友和/或同事分享。
对于任何问题或其他讨论,请随时发表评论。
在这里找到第二部分,我们在这里进行了更深入的探讨。
xarray 的基本数据结构
原文:https://towardsdatascience.com/basic-data-structures-of-xarray-80bab8094efa?source=collection_archive---------3-----------------------
Photo by Faris Mohammed on Unsplash
Xarray 是一个 python 包,用于处理带标签的多维数组,包括高级分析和可视化功能。Xarray 深受熊猫的启发,在内部使用熊猫。虽然 pandas 是处理表格数据的一个很好的工具,但是当数据维数较高时,它可能会变得有些笨拙。Pandas 的主要数据结构是 Series(用于一维数据)和 DataFrame(用于二维数据)。它曾经有面板(用于三维数据),但在版本 0.25.0 中删除了。
假设读者熟悉熊猫,如果你不知道熊猫是什么,你应该在 xarray 之前查看一下。
为什么我应该使用 ND 数组?
在许多科学领域,需要将一个数据点映射到各种属性(称为坐标),例如,您希望将某个温度测量值映射到纬度、经度、高度和时间。这是 4 维!
在 python 中,使用 ND 数组的基本包是 NumPy 。Xarray 有一些内置特性,使得使用 ND 数组比 NumPy 更容易:
- xarray 不使用轴标签,而是使用命名维度,这使得选择数据和对维度应用操作变得容易。
- NumPy 数组只能有一种数据类型,而 xarray 可以在 ND 数组中保存异构数据。这也使得 NaN 操作更容易。
- 使用
obj.attrs
跟踪对象上的任意元数据。
数据结构
Xarray 有两种数据结构:
- 数据数组—用于单个数据变量
- 数据集—多个数据数组(数据变量)的容器
根据 CF 惯例,在数据变量和坐标之间有区别。Xarray 遵循这些约定,但是它主要是语义性的,您不必遵循它。我是这样看的:一个数据变量是感兴趣的数据,一个坐标是描述感兴趣的数据的标签。例如,纬度、经度和时间是坐标,而温度是数据变量。这是因为我们对测量温度感兴趣,其余的都是描述测量结果(数据点)。在 xarray 文档中,他们说:
坐标表示常量/固定量/独立量,不同于属于数据的变化量/测量量/相关量。
O 凯,来看看一些代码吧!
# customary imports
import numpy as np
import pandas as pd
import xarray as xr
首先,我们将创建一些玩具温度数据来玩:
我们生成了一个随机温度值的数组,以及坐标纬度和经度(二维)的数组。首先,让我们看看如何在 pandas 中表示这些数据:
df = pd.DataFrame({"temperature":temperature, "lat":lat, "lon":lon})
df
Output of the above cell
我们将从这些数据中创建一个 DataArray ,让我们来看看四种方法:
- 来自熊猫系列
- 来自一个熊猫的数据框架
- 使用 DataArray 构造函数
- 使用带有投影坐标的 DataArray 构造函数
从序列创建数据数组
我们将创建一个熊猫系列,然后是一个数据数组。由于我们希望在数据中表示两个维度,因此我们将创建一个具有两级多索引的序列:
idx = pd.MultiIndex.from_arrays(arrays=[lat,lon], names=["lat","lon"])s = pd.Series(data=temperature, index=idx)
s# use from_series method
da = xr.DataArray.from_series(s)
da
Output of the above cell
这是数据数组打印出来的样子。
从数据帧创建数据数组
我们可以为 DataArray 构造函数提供一个熊猫数据帧。它会将数据框的索引视为第一维,将列视为第二维。如果索引或列有多个级别,xarray 将创建嵌套维度。
由于我们希望纬度和经度作为我们的维度,实现这一点的最聪明的方法是使用纬度作为索引,经度作为列来透视我们的数据框:
df_pv = df.pivot(index="lat", columns="lon")# drop first level of columns as it's not necessary
df_pv = df_pv.droplevel(0, axis=1)df_pv
Output of the above cell
数据透视后,我们可以通过为 DataArray 构造函数提供透视数据框来轻松创建 DataArray:
da = xr.DataArray(data=df_pv)
da
Output of the above cell
使用构造函数创建 DataArray
我们已经看到了从 pandas 对象创建 DataArray 的两种方法。现在,让我们看看如何手动创建数据数组。因为我们希望在数据中表示二维,所以数据应该以二维数组的形式出现,这样我们就可以将它直接传递给 DataArray 构造函数。
我们将使用透视数据框中的数据,然后我们需要明确指定坐标和维度:
Output of the above cell
这里需要注意的重要一点是,坐标数组必须是一维的,并且具有它们所代表的维度的长度。我们有一个(4,4)形状的数据数组,所以我们为构造函数提供了两个坐标数组。每个都是一维的,长度为 4。
使用带有投影坐标的构造函数创建 DataArray
我们将检查用投影坐标创建 DataArray 的最后一种方法。它们在某些情况下可能是有用的,但是它们有一个缺点,即坐标没有明确的可解释性。使用它们的最大的优势是我们可以传递给 DataArray 构造函数相同形状的数组,用于数据和坐标,而不必考虑旋转我们的数据。
在我们的例子中,我们有温度数据,我们有两个维度:纬度和经度,所以我们可以在一个任意形状的(不需要旋转)的二维数组中表示我们的数据,然后为构造函数提供两个相同形状的坐标数组来表示纬度和经度:
下面,请注意在 DataArray 构造函数中指定坐标的方式。这是一个字典,它的键是坐标的名称,它的值是元组,它们的第一项是维度列表,第二项是坐标值。
da = xr.DataArray(data=temperature,
coords={"lat": (["x","y"], lat),
"lon": (["x","y"], lon)},
dims=["x","y"])da
Output of the above cell
注意它说 x 和 y 是没有坐标的维度。还要注意,lat 和 lon 旁边没有星号,因为它们是无量纲坐标。
三维
现在让我们创建另一个维度!让我们创建 2 天的温度数据,不是 1 天而是 2 天!
像以前一样,每天我们都需要一个二维(纬度和经度)温度值数组。为了表示 2 天的数据,我们希望将每日数组堆叠在一起,形成一个三维数组:
现在,我们将数据传递给 DataArray 构造函数,并使用投影坐标:
da = xr.DataArray(data=temperature_3d,
coords={"lat": (["x","y"], lat),
"lon": (["x","y"], lon),
"day": ["day1","day2"]},
dims=["x","y","day"])da
Output of the above cell
我们也可以使用一个具有 3 级多索引的 pandas 系列来创建同样的东西。要创建一个系列,我们需要将数据扁平化,这意味着使其一维化:
# make data 1-dimensional
temperature_1d = temperature_3d.flatten("F")
lat = lat.flatten()
lon = lon.flatten()day = ["day1","day2"]
现在,我们将创建一个具有 3 级多索引的系列:
Output of the above cell
最后,我们将使用 from_series 方法创建一个 DataArray:
da = xr.DataArray.from_series(s)
da
Output of the above cell
资料组
到目前为止,我们只处理了温度数据。让我们添加压力数据:
现在我们将创建一个数据集(不是一个数据数组),以温度和压力作为数据变量。对于投影坐标, data_vars 参数和 coords 参数都需要一个类似于 DataArray 的 coords 参数的字典:
Output of the above cell
我们还可以为每个数据变量创建一个数据数组,然后从数据数组创建一个数据集。让我们使用 from_series 方法为温度和压力创建两个数据数组,就像我们对三维情况所做的那样:
现在,我们将使用这两个数据数组创建一个数据集:
ds = xr.Dataset(data_vars={"temperature": da_temperature, "pressure": da_pressure})ds
结论
这是对 xarray 数据结构的快速介绍。xarray 还有更多的功能,比如索引、选择和分析数据。我不会在这里涉及这些,因为我想保持这个教程简单。我鼓励你看一看 xarray docs,并尝试使用它。希望这篇文章对你有用!
ETF 的基本数据争论和可视化
原文:https://towardsdatascience.com/basic-data-wrangling-visualization-with-an-etf-75329180cc70?source=collection_archive---------18-----------------------
概观
正如前一篇文章所承诺的,我们最终会完成一些编码示例。在选择一个与你分享的话题时,我实际上是从进行深度工作中抽出 10 分钟的休息时间得到的灵感——这是一种来自加州新港【1 }的生产力技巧。对于那些需要复习的人来说,深入的工作是:
一种在不受干扰的环境中进行的工作,这种工作可以集中你的注意力,创造出其他人很难复制的更大价值。
我个人会努力 40-50 分钟,然后需要 10-15 分钟的休息。其中一次休息时,我的同事们在谈论市场和比特币。boom——这是本文的下一个主题。今天,我们将讨论一些基本的时序数据争论和 Python 中的可视化。然后我们会用均线交易策略来结束它。
现在只是为了记录,我不是说这个策略是好的或任何东西,但只是想告诉你在一些数据操作和可视化之后你能做什么。管理方面的问题解决了,让我们开始吧!
时间序列和数据争论的术语
学习新事物时,我总是喜欢从头开始。这样,我们都在同一页上,以后可以构建更复杂的模型。基本上,我宁愿解释得多一点也不愿意解释得不够多。就我个人而言,我总是讨厌被弄糊涂,当有人做了一个巨大的逻辑跳跃。
时间序列的定义:时间序列是一种在一段时间内获取的数据类型,已知数据点彼此相关【2】。时间序列的例子包括股票价格、马丘比丘的每日温度、小海龟跑进海洋的速度等。
数据角力的定义:数据角力是将原始数据转化为更干净的数据,使模型更好的过程【3】。例如,你从 Twitter 上获得大量的 tweet 数据。将原始文本数据放在机器学习 NLP 模型中不会有太好的效果。但是如果你删除不必要的单词,清理特殊字符,为输入和输出构建数据,等等。,那么你就可能有一个像样的模型,可以预测或分类。
基本时序数据争论和可视化
在 Python 中,标准的做法是首先导入包,然后为它们指定快捷方式以节省时间。比如熊猫从现在开始就要叫 pd 了。
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
现在,让我们将 NASDAQ etf 从 csv 导入到一个 dataframe 中(就像 Excel 中的工作表一样)【4】。
qqq = pd.DataFrame.from_csv(‘QQQ Historical Data.csv’)print(qqq.head())
检查数据是什么样的总是好的,这样你就对你正在分析的东西有了更好的感觉。以下是股票和 etf 数据的常见格式:
Price Open High Low Vol. Change %
Date
2014-12-31 103.25 104.50 104.91 103.10 24.37M -1.03%
2015-01-02 102.94 103.76 104.20 102.44 31.31M -0.30%
2015-01-05 101.43 102.49 102.61 101.14 36.52M -1.47%
2015-01-06 100.07 101.58 101.75 99.62 66.21M -1.34%
2015-01-07 101.36 100.73 101.60 100.48 37.58M 1.29%print(qqq.shape)
shape 命令向我们显示了数据帧中的行数和列数,按此顺序排列。
(1127, 6)print(qqq.describe())
Describe 向我们显示了一般的汇总统计数据。
Open High Low Price
count 506.000000 506.000000 506.000000 506.000000
mean 102.880198 103.857688 101.770731 102.864565
std 17.100460 17.089441 17.049718 17.081374
min 74.040000 74.830000 72.000000 74.050000
25% 86.740000 87.715000 85.620000 86.730000
50% 105.260000 106.300000 104.040000 105.075000
75% 117.812500 118.677500 116.722500 117.745000
max 133.500000 133.500000 132.220000 133.280000
loc vs . iloc
好了,这里有一个小命令总是让我困惑,当我第一次开始学习 Python 的时候。当我们使用 loc 时,它得到一个带标签的行,而 iloc 得到一个带索引的数据点。以下是每种方法的示例:
print(qqq_2015.loc[‘2015–03–16’])Price 106.7
Open 105.73
High 106.74
Low 105.62
Vol. 25.67M
Change % 1.29%
Name: 2015-03-16 00:00:00, dtype: objectprint(qqq.iloc[0, 0])103.25
以下是如何获取特定时间序列的示例代码,在本例中是 QQQ etf 的 2015 年全年。
qqq_2015 = qqq.loc[‘2015–01–01’:’2015–12–31']
python 中的绘图非常简单。您可以告诉它您想要的绘图大小、要绘制的时间序列以及何时显示,如下所示:
plt.figure(figsize=(10, 8))
qqq[‘Price’].plot()
plt.show()
要在 dataframe 中创建一个新列,可以使用与创建新变量类似的模式。下面我们将创建一个获取差价和每日回报的新专栏。做这两件事的目的是看我们的交易策略一天能赚多少或亏多少。
qqq[‘PriceDiff’] = qqq[‘Price’].shift(-1) — qqq[‘Price’]qqq[‘Return’] = qqq[‘PriceDiff’] /qqq[‘Price’]
交易策略的另一部分是告诉算法价格的方向。有了这个形态,策略就能知道 ETF 或股票是涨还是跌。由此,我们可以告诉策略下一步该做什么——即交易价格上涨(多头)或下跌(空头)。
qqq[‘Direction’] = [1 if qqq[‘PriceDiff’].loc[ei] > 0 else 0 for ei in qqq.index ]print(‘Price difference on {} is {}. direction is {}’.format(‘2015–01–05’, qqq[‘PriceDiff’].loc[‘2015–01–05’], qqq[‘Direction’].loc[‘2015–01–05’]))
做均线策略的最后一个要素是做均线,可以用。滚动()和。平均值()。在这里,我们将使用 50 移动平均线,它显示了过去 50 天的平均收盘价。下面是带有情节的代码:
qqq[‘ma50’] = qqq[‘Price’].rolling(50).mean()
plt.figure(figsize=(10, 8))
qqq[‘ma50’].loc[‘2015–01–01’:’2015–12–31'].plot(label=’MA50')
qqq[‘Price’].loc[‘2015–01–01’:’2015–12–31'].plot(label=’Price’)
plt.legend()
plt.show()
建立移动平均线交易策略
我们拥有交易策略的所有要素。从上面的代码添加,我们可以制定一个 50 简单移动平均线(SMA)和 100 简单移动平均线(SMA)的交叉策略。一旦 50 日均线超过 100 日均线,我们将交易 etf 将走高。一旦 50 日均线跌破 100 日均线,我们将关闭我们的多头或根本不交易。
qqq[‘MA50’] = qqq[‘Price’].rolling(50).mean()
qqq[‘MA100’] = qqq[‘Price’].rolling(100).mean()
qqq = qqq.dropna()
下面的代码设置了我们购买的股票数量,并允许我们绘制交易期间的回报图:
qqq[‘Shares’] = [1 if qqq.loc[ei, ‘MA50’]>qqq.loc[ei, ‘MA100’] else 0 for ei in qqq.index]qqq[‘Close1’] = qqq[‘Price’].shift(-1)
qqq[‘Profit’] = [qqq.loc[ei, ‘Close1’] — qqq.loc[ei, ‘Price’] if qqq.loc[ei, ‘Shares’]==1 else 0 for ei in qqq.index]
qqq[‘Profit’].plot()
plt.axhline(y=0, color=’red’)
第一次看到这个,很难判断我们是否盈利。另一种方式来看待它是从我们的股票交易中获得的价格。cumsum()代码—创建一个新列并绘制它:
qqq[‘wealth’] = qqq[‘Profit’].cumsum()qqq[‘we alth’].plot()
plt.title(‘Total money you win is {}’.format(qqq.loc[qqq.index[-2], ‘wealth’]))
上面的图显示了我们从交易 1 份 QQQ etf 中获得了多少钱,因此我们交易 1 份获得了 48.03 美元(43.12%的总回报)。43.12%的回报率并不差,但与同期仅买入并持有 etf 而不交易相比(总回报率为 68.57%),这有点糟糕。
结论
恭喜你,你刚刚经历了一些数据争论,可视化,并建立了一个移动平均线交易策略!
图片取自随机的 YouTube 个人资料【5】
当你坐下来想想你学了些什么,那真的很多。您学习了如何从 CSV 导入数据,制作数据框架,查看行,查看数据点,创建新列,一些统计函数,并绘制出简单的移动平均线交易策略。我知道我在数据科学方面比在财务方面解释得更多。如果有什么不清楚的,在下面评论或者给我发消息!
在以后的文章中,我们将结合数据科学的商业思想,进行更多的编码演练。
特别感谢万博士,我修改了他的一个课程的想法,以构建本文【6】。
免责声明:本文陈述的所有内容均为我个人观点,不代表任何雇主。投资有很大的风险。在做出任何投资决定之前,请咨询您的财务专家。最后,这篇文章包含附属链接,谢谢你的支持。
[1] C .纽波特,深度工作:在纷乱的世界中专注成功的规则 (2016),大中央出版社
[2] NIST,时间序列分析导论,https://www . ITL . NIST . gov/div 898/handbook/PMC/section 4/pm C4 . htm
[3] Trifacta,什么是数据角力?,https://www.trifacta.com/data-wrangling/
www.investing.com,景顺 QQQ 信托历史数据,https://www . investing . com/ETFs/power shares-QQ QQ-Historical-Data
[5]https://www.youtube.com/channel/UCkAqayQ4Q8XD6CwWSxD6DbA 的 TT·克尔,YouTube 个人资料,
[6] X .万,构建简单交易策略,https://www . coursera . org/learn/python-statistics-financial-analysis
基本集成学习(随机森林,AdaBoost,梯度推进)-一步一步解释
原文:https://towardsdatascience.com/basic-ensemble-learning-random-forest-adaboost-gradient-boosting-step-by-step-explained-95d49d1e2725?source=collection_archive---------0-----------------------
前三种基于树的集成学习算法的逐步解释。
Photo by kazuend on Unsplash
我们都这样做。在我们做出任何重大决定之前,我们会询问人们的意见,比如我们的朋友、家人,甚至我们的狗/猫,以防止我们有偏见😕或者不理智😍。
模型也是这样。单个模型遭受偏差或方差是很常见的,这就是为什么我们需要集成学习。
E nsemble 学习,一般来说,是一种基于许多不同模型进行预测的模型。通过组合单独的模型,集合模型趋向于更加灵活🤸♀️(偏差较小)和 data-sensitive🧘♀️(方差较小)。
两种最流行的集成方法是打包和助推。
- 装袋:并行训练一堆个体模型。每个模型由数据的随机子集训练
- Boosting: 按顺序训练一堆个体模型。每个单独的模型都从前一个模型所犯的错误中学习。
有了对什么是集成学习的基本了解,让我们来种一些“树”🎄。
以下内容将逐步解释随机森林、AdaBoost 和梯度增强,以及它们在 Python Sklearn 中的实现。
随机森林
andom forest 是一个集合模型,使用 bagging 作为集合方法,决策树作为个体模型。
让我们仔细看看这个魔法🔮的随机性:
步骤 1: 从训练集中选择 n 个(例如 1000 个)随机子集
第二步:训练 n 个(例如 1000 个)决策树
- 一个随机子集用于训练一个决策树
- 每个决策树的最佳分割基于随机的特征子集(例如,总共 10 个特征,从 10 个特征中随机选择 5 个进行分割)
步骤 3: 每棵单独的树独立地预测测试集中的记录/候选者。
第四步:进行最终预测
对于测试集中的每个候选人,随机森林使用具有多数票的类(例如猫或狗)作为该候选人的最终预测。
当然,我们的 1000 棵树就是这里的议会。
自适应增强
AdaBoost 是一个增强集成模型,特别适合决策树。Boosting 模型的关键是从以前的错误中学习,例如错误分类数据点。
通过增加错误分类数据点的权重,daBoost 从错误中学习。
让我们举例说明AdaBoost 如何适应。
步骤 0: 初始化数据点的权重。如果训练集有 100 个数据点,那么每个点的初始权重应该是 1/100 = 0.01。
第一步:训练决策树
第二步:计算决策树的加权错误率(e) 。加权误差率(e) 是指所有预测中有多少是错误的,你可以根据数据点的权重来区别对待错误的预测。权重、越高,在(e)的计算过程中,相应的误差将被加权。
步骤 3: 计算该决策树在集合中的权重
这棵树的权重=学习率* log( (1 — e) / e)
- 树的加权错误率越高,😫在随后的投票中,给予该树的决策权越少
- 树的加权错误率越低,😃在以后的投票中,该树将被给予更高的决策权
步骤 4: 更新错误分类点的权重
每个数据点的权重=
- 如果模型得到的数据点正确,重量保持不变
- 如果模型得到的这个数据点是错误的,那么这个点的新权重=旧权重* np.exp(这棵树的权重)
注意:树的权重越高(该树执行的越准确),该树的误分类数据点将获得越多的提升(重要性)。在所有错误分类的点被更新之后,数据点的权重被归一化。
第五步:重复第一步(直到达到我们设定的训练树的数量)
第六步:进行最终预测
AdaBoost 通过将(每棵树的)权重相加乘以(每棵树的)预测来进行新的预测。显然,权重越高的树对最终决策的影响力越大。
梯度推进
梯度推进是另一种推进模式。记住,推进模型的关键是从以前的错误中学习。
radient Boosting 直接从错误——残差中学习,而不是更新数据点的权重。
下面举例说明梯度提升是如何学习的。
步骤 1: T 雨决策树
步骤 2: 应用刚刚训练好的决策树进行预测
第三步:计算该决策树的残差,将残差保存为新的 y
第四步:重复第一步(直到达到我们设定的训练树数)
第五步:进行最终预测
梯度推进通过简单地将(所有树的)预测相加来进行新的预测。
Python sk learn 中的实现
下面是 Python Sklearn 中上述三种方法的简单实现。
**# Load Library** from sklearn.datasets import make_moons
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier,AdaBoostClassifier,GradientBoostingClassifier**# Step1: Create data set**
X, y = make_moons(n_samples=10000, noise=.5, random_state=0)**# Step2: Split the training test set**
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)**# Step 3: Fit a Decision Tree model as comparison**
clf = DecisionTreeClassifier()
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
accuracy_score(y_test, y_pred)**OUTPUT: 0.756****# Step 4: Fit a Random Forest model, " compared to "Decision Tree model, accuracy go up by 5%** clf = RandomForestClassifier(n_estimators=100, max_features="auto",random_state=0)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
accuracy_score(y_test, y_pred)**OUTPUT: 0.797****# Step 5: Fit a AdaBoost model, " compared to "Decision Tree model, accuracy go up by 10%**
clf = AdaBoostClassifier(n_estimators=100)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
accuracy_score(y_test, y_pred)**OUTPUT:0.833****# Step 6: Fit a Gradient Boosting model, " compared to "Decision Tree model, accuracy go up by 10%** clf = GradientBoostingClassifier(n_estimators=100)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
accuracy_score(y_test, y_pred)**OUTPUT:0.834*****Note: Parameter - n_estimators stands for how many tree we want to grow***
总的来说,集成学习是非常强大的,不仅可以用于分类问题,也可以用于回归。在这篇博客中,我只使用决策树作为集成方法中的个体模型,但是其他的个体模型(线性模型,SVM 等。)也可以应用在打包或增强集合中,以获得更好的性能。
这个博客的代码也可以在我的 GitHub 链接中找到。
请在下面留下任何评论、问题或建议。谢谢大家!
实现更高效机器学习的基本特征工程
原文:https://towardsdatascience.com/basic-feature-engineering-to-reach-more-efficient-machine-learning-6294022e17a5?source=collection_archive---------11-----------------------
Photo by Lenny Kuhne on Unsplash
如果我问你一个问题,比如机器学习难吗,你可能会说是的。但是机器学习并不是一件难事。因为您可能需要的每一个算法都是预先实现的,并以包的形式提供(主要在 python 库中)。您可以导入您想要的任何库,然后开始构建模型。但是几乎所有这些算法都是对数值数据或二进制数据进行操作的。所以你不能直接输入一个特征集就指望算法能起作用。尤其是当数据集中有非数字数据时,机器学习模型不会像预期的那样工作,并且准确率非常低。我们必须清理这些非数字数据,提取有用的数字嵌入。清洁不仅如此。我们必须处理缺失值、共线特征、零重要特征等等。但这还不够。我们必须从清理后的特征中为机器学习模型导出更有意义的特征。您可以在本文后面找到这些主题的更多细节。所有这些都被称为特征工程。特征工程是机器学习中最重要也是最困难的任务。
处理非数字数据
首先,您必须将非数字特征转换成数字格式。有两种类型的字符串数据,即分类数据和连续数据。
分类特征
分类数据/特征是具有有限数量标签或类别的变量。根据性质,分类数据可以分为序数数据和名词性数据。当值有自然顺序时,属性就是序数属性。例如,功能关键级别可以是低、中或高,并且有一定的顺序。当我们不能推导出任何类别之间的顺序或关系时,它被称为一个名义特征。例如,一个国家的省或区没有顺序。然而,这是一个分类属性,因为一个国家有固定数量的省或区。
将分类数据转换成数字格式的流行技术很少。即使对于像决策树和随机森林这样可以处理分类数据的算法,编码也是有意义的。
1.标签编码
标签编码将非数字标签转换为数字标签。对于有序分类数据来说,这种编码类型更好,如果数据集中的分类要素数量巨大,您可能会经常使用标签编码。因为像热编码这样的编码技术会导致高内存消耗。您可以轻松地从 python scikit 学习库中导入标签编码器。但是,标签编码会使 ml 模型误解数据中存在某种排序。为了克服这个问题,我们可以使用一热编码。
2.一个热编码
在一个热编码中,我们为分类属性的每个类创建虚拟列。对于每个伪属性,类的存在表示为 1,不存在表示为 0。所以这些数字用 1 和 0 来表示。我们使用一个热编码和名义数据。您可以很容易地从 python scikit 学习库中导入一个 hot 编码器。
3.二进制编码
在二进制编码中,首先将类转换成数字格式,然后再转换成相应的二进制字符串。然后,二进制数字被分成单独的列。
4.张量流特征列
特征列将输入数据与您的机器学习模型联系起来。Tensorflow 提供了一个包含九个函数的模块来处理特征列。下面列出了这些功能。从 tensorflow 官方文档中可以找到很好的解释(点此)。
- 数字列
- 桶形塔
- 分类标识列
- 分类词汇栏(词汇文件)
- 分类词汇栏(词汇列表)
- 散列列
- 交叉柱
- 指示器列
- 嵌入柱
连续特征
在数学中,如果一个变量可以取最小值和最大值之间的任何值,那么它被称为连续变量。同样的事情也适用于这里。但是,如果变量没有最小值和最大值,那么我们可能会遇到麻烦,因为变量可能会为机器学习模型创建稀疏特征。稀疏特征对机器学习模型没有任何意义,在我看来,最好是摆脱它们。但问题是从数据集中删除特征会降低 ml 算法的准确性。因此,我们应该尽一切可能将该特性转化为有用的格式。如果没有选项,那么最好放弃该功能,因为它使机器学习模型比使用它更准确。
在某些情况下,我们也许能够从字符串数据中导出更有用的数字特征。例如,考虑一个带有 ip 地址的特性列。作为一个特性,ip 地址是字符串数据。我们可以通过将 ip 地址分成四个二进制八位数并应用简单的数学运算来将其转换成整数。这个整数数据可以被输入到一个 ml 模型中,并期望它能很好地工作。但是我们可以通过从 ip 获取经度和纬度来获得一个更有用的特性。您可以使用免费的 API 或数据库或任何其他技术来将 ip 转换为相关坐标。在我看来,我们或许可以通过获取地理位置坐标,而不是简单地将 ip 转换为整数,来为机器学习模型导出更有意义的特征。
正如您可能理解的那样,处理连续变量是一项有点困难的任务。然而,有一些流行的技术来处理连续变量。下面列出的只是其中的一些,你可能会发现更多的技巧。
1.变量宁滨
宁滨将连续的数字变量分组。基本上,这样做是为了发现难以识别的变量模式。例如,年龄列表可以根据取值范围划分为多个区间。然而,最重要的是箱子的大小。你可以根据你的假设决定一个最佳的箱子大小。
2.正常化
规范化用于将数字列的值更改为通用的比例。在数学中,你可能会发现正态分布的数据很容易阅读和解释。许多机器学习算法假设其数据点呈正态分布。特别是在 K-means 这样的聚类技术中,归一化非常有帮助。一种常用的归一化技术是获取 z 值。
3.理解业务逻辑
在某些情况下,数据本身并不能说明任何模式。但是通过理解业务逻辑或领域可以帮助你找出更有意义的特性。这就是为什么你可能经常在一个机器学习小组中找到一个或多个领域专家。他们非常了解业务领域及其运作方式,能够从现有特征中创造出更有意义的特征,从而为机器学习模型衍生出可识别的模式。这种技术不仅适用于连续数据,也适用于其他类型的数据。
特征选择
在处理完非数字特征之后,你必须进行特征选择。特征选择是选择属性的过程,这些属性可以使 ml 模型更加精确,并消除不相关的属性。下面列出了一些最常见的特征选择技术。
1.缺失值处理
当我们收集真实世界的数据时,可能会有缺失值。这导致数据集的列中包含缺失值。缺失值可能导致机器学习模型识别数据点之间的错误模式,并给出错误和不太准确的预测。通过将数据集读取为 pandas 数据框,您可以很容易地发现数据集是否有缺失值。熊猫图书馆有很多内置的方法来轻松处理 csv 数据。下面列出了一些处理缺失值的技巧。
一.删除
这是处理缺失值的最基本的方法。基本思想是删除任何缺失值超过指定阈值的列。然而,删除列将减少机器学习模型的特征数量,并导致模型不太准确。在我看来,保留数据比删除数据更好。
二。使用回填或前填
该方法将为缺失值分别传播下一个或上一个值。但是,如果下一个或上一个值也是 NaN 或不可用,则 NaN 值将保持不变。
三。常量值插补
该方法将使用一个全局常量来填充所有缺失的值。当尝试和预测缺失值没有意义时,可以使用常量值插补。主要的缺点是 ml 模型的性能会下降。
四。均值、中值和众数插补
我们可以用列的平均值或中值来填充缺失值,而不是用单个常数来填充缺失值。这种方法单独处理每个变量,忽略与其他变量的任何关系。
动词 (verb 的缩写)使用预测模型
有时,我们使用机器学习模型通过识别属性之间的关系来预测缺失值。通过考虑上述技术,这是一种更加有效的填补缺失值的方法。但是准确性完全取决于你的预测模型有多好。
2.共线特征
共线特征是高度依赖于另一个特征的特征。由于高方差和较低的模型可解释性,共线特征导致综合性能下降。基于特定的相关系数来识别相关水平。我们移除相关系数大于指定阈值的特征。但是,我们应该从两个相关的特征中只移除一个特征,因为移除特征会降低机器学习模型的准确性。有两个著名的系数,皮尔逊相关系数和斯皮尔曼相关系数。这两者都可以从 scipy python 库中导入。皮尔逊相关可用于具有线性关系的连续变量。Spearman 相关可用于具有非线性关系的变量或有序分类变量。我们可以使用 python seaborn 热图轻松地可视化变量之间的相关性。
3.零/低重要特性
零重要和低重要特征对于机器学习模型没有任何意义。可以使用梯度推进机器学习模型(GBM)来计算特征的重要性。您可以移除不太重要的特征,因为它们对于 ml 模型进行预测并不重要。然而,这种方法只适用于有非确定性标记数据的监督模型,如果我们要使用基于树的方法进行预测。但更重要的是,你应该试着从这些特性中衍生出新的有意义的特性。可能存在这样的情况,即使特征本身不太重要,也有可能导出更有意义的特征。
4.单一独特价值特征
这里,我们删除了在整个数据集中具有单一唯一值的列,因为机器学习模型无法从这些列中得出任何结论。
结论
我简要描述了一些流行的基本特征工程技术,包括处理非数字数据和特征选择技术。使用 python scikit learn 库和 pandas 库可以轻松实现上述所有技术。但是特征工程是一个非常广泛的话题,还有更多的内容要涵盖。特征工程中最重要的技术之一是从现有特征中派生出更有意义的新特征。几乎所有机器学习模型的成功都取决于我们如何向我们的模型呈现数据。我们可以通过获取现有特征之间的比率、取平均值或中值、交叉特征等来导出新特征。例如,如果我们正在为一个分类问题进行特征工程,新的特征应该以一种模型可以容易地区分数据点之间的聚类的方式出现。
最后但同样重要的是,有许多方法可以实现自动化特征工程。自动化特征工程旨在从现有特征中自动创建许多候选特征。从这些生成的特征中,我们可以选择最好的来训练我们的模型。Featuretools 是一个用于自动化特征工程的开源 python 框架。
创建时间序列预测的基本原则
原文:https://towardsdatascience.com/basic-principles-to-create-a-time-series-forecast-6ae002d177a4?source=collection_archive---------3-----------------------
解释创建时间序列预测的基本步骤。
Photo by Adrian Schwarz on Unsplash
我们被随处可见的模式所包围,人们可以注意到与天气有关的四季模式;指交通流量的高峰时间模式;在你的心跳中,在股票市场的股票中,也在某些产品的销售周期中。
分析时间序列数据对于检查这些模式和创建未来预测非常有用。创建这些预测有几种方法,在这篇文章中,我将介绍最基本和传统的方法。
所有代码都是用 Python 写的,另外,任何附加信息都可以在我的 Github 上看到。
那么让我们开始评论分析时间序列的初始条件:
平稳序列
平稳时间序列的统计特性,如均值、方差和自相关,在一段时间内相对恒定。因此,非平稳序列是其统计特性随时间而变化的序列。
在开始任何预测建模之前,有必要验证这些统计属性是否恒定,我将在下面解释这些要点:
- 常数平均值
- 恒定方差
- 自相关的
常数平均值
平稳序列有一个相对恒定的平均值,没有看涨或看跌趋势。有一个恒定的平均值,周围有小的变化,更容易推断未来。
在有些情况下,方差相对于平均值较小,使用它来预测未来可能是一个很好的指标,下面的图表显示了相对恒定的平均值与方差之间的关系:
在这种情况下,如果序列不是稳定的,对未来的预测将是无效的,因为平均值周围的变化会显著偏离,如下图所示:
在上面的图表中,很明显有一个看涨的趋势,均值在逐渐上升。在这种情况下,如果用平均值来预测未来,误差会很大,因为预测价格总是低于实际价格。
恒定方差
当序列具有恒定的方差时,我们对相对于平均值的标准方差有一个概念,当方差不恒定时(如下图),预测在某些时期可能会有较大的误差,这些时期将是不可预测的,预计方差将随着时间的推移保持不变,包括在未来。
为了减少方差影响,可以应用对数变换。在这种情况下,也可以使用指数变换,如 Box-Cox 方法,或使用通货膨胀调整。
自相关序列
当两个变量在一段时间内相对于标准偏差具有相似的变化时,你可以说这些变量是相关的,例如,当体重随着心脏疾病而增加时,体重越大,心脏问题的发生率就越高。在这种情况下,相关性为正,图表看起来如下所示:
负相关的一个例子是:对工作安全措施的投资越大,与工作相关的事故就越少。
以下是几个具有相关级别的散点图示例:
source: wikipedia
当主题为自相关时,表示某些之前的时段与当前时段存在相关性,具有这种相关性的时段被命名为,例如,在一个每小时都有测量值的序列中,今天 12:00 的温度与 24 小时前 12:00 的温度非常相似。如果你比较这 24 宫时间范围内的温度变化,将会有一个自相关,在这种情况下,我们将有一个与第 24 宫时间范围的自相关。
自相关是用单个变量创建预测的条件,因为如果没有相关性,就不能使用过去的值来预测未来,当有多个变量时,就可以验证因变量和自变量的滞后之间是否存在相关性。
如果一个序列不具有自相关性,那么它就是一个具有随机和不可预测序列的序列,进行预测的最佳方法通常是使用前一天的值。下面我会用更详细的图表和解释。
从这里我将分析 Esalq 的每周含水乙醇价格(这是在巴西谈判含水乙醇的价格参考),数据可以在这里下载。
价格以每立方米巴西雷亚尔(BRL/m3)为单位。
在开始任何分析之前,让我们在训练和测试集上分割数据
在培训和测试的基础上划分数据
当我们要创建时间序列预测模型时,将数据分成两部分至关重要:
训练集:这些数据将是定义模型系数/参数的主要依据;
测试集:这些数据将被分离出来,不会被模型看到,以测试模型是否工作(一般情况下,这些值与一个向前移动的方法进行比较,最后测量平均误差)。
测试集的大小通常约为总样本的 20%,尽管该百分比取决于您拥有的样本大小以及您希望提前多长时间进行预测。理想情况下,测试集应该至少与所需的最大预测范围一样大。
与其他预测方法不同,例如不受时间影响的分类和回归,在时间序列中我们不能用来自数据任何部分的随机样本来划分训练和测试数据,我们必须遵循序列的时间标准,其中训练数据应该总是在测试数据之前。
在这个 Esalq 含水价格的例子中,我们有 856 周,我们将使用前 700 周作为训练集,最后 156 周(3 年~ 18%)作为测试集:
从现在开始,我们将只使用训练集来进行研究,测试集将只用于验证我们将做出的预测。
每个时间序列都可以分解成 3 个部分:趋势、季节性和残差,这是从序列中去除前两个部分后剩余的部分,低于这些部分的分离:
很明显,该系列呈上升趋势,峰值出现在每年的年末和年初,最小值出现在 4 月和 9 月(巴西中南部甘蔗压榨开始)。
然而,它表明使用统计测试来确认序列是否是平稳的,我们将使用两个测试:T4 迪基-富勒测试和 KPSS 测试。
首先,我们将使用 Dickey-Fuller 检验,我将使用基数为 5%的 P 值,也就是说,如果 P 值低于这 5%,这意味着该序列在统计上是平稳的。
此外,还有模型的统计测试,其中这些值可以与 1%、5%和 10%的临界值进行比较,如果统计测试低于某个选定的临界值,序列将是稳定的:
在这种情况下,Dickey-Fuller 检验表明序列不是平稳的(P 值 36%和临界值 5%小于统计检验)。
现在,我们将使用 KPSS 检验来分析该序列,与迪基-富勒检验不同,KPSS 检验已经假设该序列是平稳的,只有当 P 值小于 5%或统计检验小于某个值时才不会是平稳的:
KPSS 检验证实了迪基-富勒检验,也表明序列不是平稳的,因为 P 值为 1%,统计检验高于任何临界值。
接下来,我将演示将数列转化为平稳数列的方法。
将该系列转变为静止的
区别
差分用于移除趋势信号并减少方差,它只是周期 T 的值与前一周期 T-1 的值的差。
为了更容易理解,下面我们只得到乙醇价格的一小部分,以便更好地可视化,请注意,从 2005 年 5 月到 2006 年 5 月中旬,价格开始上涨,这些价格每周上涨,累积起来形成一个上升趋势,在这种情况下,我们有一个非平稳序列。
在进行第一次微分时(如下图),我们移除了系列的累积效应,仅显示了整个系列中期间 T 相对于期间 T-1 的变化,因此,如果 3 天前的价格是 BRL 800.00,并更改为 BRL 850.00,微分的值将是 BRL 50.00,如果今天的值是 BRL 860.00,则差值将是-BRL 10.00。
通常只需要一次微分就可以将一个数列转化为平稳数列,但是如果有必要,可以进行第二次微分,在这种情况下,将对第一次微分的值进行微分(很少有超过两次微分的情况)。
使用相同的例子,为了进行第二次微分,我们必须对 T 减去 T-1 进行微分:BRL 2.9—BRL 5.5 =—BRL 2.6,以此类推。
让我们做一下 Dickey-fuller 检验,看看这个级数在第一次微分时是否是平稳的:
在这种情况下,我们确认序列是平稳的,P 值为零,当我们比较统计测试的值时,它远低于临界值。
在下一个示例中,我们将尝试使用通货膨胀调整将序列转换为平稳序列。
通货膨胀调整
价格是相对于交易时间而言的,2002 年乙醇的价格是 BRL 680.00,如果这种产品的价格在今天以这个价格交易,肯定会有许多工厂关闭,因为这是一个非常低的价格。
为了使系列平稳,我将使用 IPCA 指数(巴西 CPI 指数)根据当前值调整整个系列,该指数从培训期结束(2016 年 4 月)一直累积到研究开始,数据来源在巴西地理统计局网站上。
现在让我们看看级数是如何变得,以及它是否变得平稳。
可以看出,上升趋势已经消失,只剩下季节性振荡,迪基-富勒测试也证实了该系列现在是平稳的。
出于好奇,请看下图,图中显示了相对于原始系列的通货膨胀调整后的价格。
减少方差
对数
对数通常用于将具有指数增长值的序列转换为更具线性增长的序列,在本例中,我们将使用自然对数(NL),其中底数为 2.718,这种对数广泛用于经济模型中。
转换为 NL 的值的差异大约等于原始系列值的百分比变化,这是减少不同价格系列差异的有效基础,请参见下面的示例:
*If we have a product that had a price increase in 2000 and went from BRL 50.00 to 52.50, some years later (2019) the price was already BRL 100.00 and changed to BRL 105.00, the absolute difference between prices is BRL 2.50 and BRL 5.00 respectively, however the percentage difference of both is 5%.*
当我们在这些价格中使用 LN 时,我们得到:NL (52,50)-NL(50,00) = 3,96–3,912 = 0,048 或 4.8%,以同样的方式在第二个价格序列中使用 LN,我们得到:NL(105)-NL(100)= 4.654–4.605 = 0.049 或 4.9%。
在这个例子中,我们可以通过将几乎所有东西放在同一个基础上来减少值的变化。
下面同一个例子:
Result: The percentage variation of the first example is 4.9 and the second is 4.9
下表比较了 X 的百分比变化值与 NL (X)的变化值:
Source
让我们绘制原始序列和 NL 变换序列之间的对比图:
Box-Cox 变换(幂变换)
BOX COX 变换也是一种变换级数的方法,λ(λ)值是用于变换级数的参数。
简而言之,该函数是几个指数变换函数的结合点,在这里我们搜索变换级数的最佳λ值,使其具有更接近正态高斯分布的分布。使用此变换的一个条件是序列只有正值,公式为:
下面,我将绘制原始序列及其分布,然后绘制具有最佳λ值的变换序列及其新分布,为了找到λ值,我们将使用库 Scipy 的函数 boxcox ,它生成变换序列和理想λ:
下面是一个交互式图表,您可以在其中更改 lambda 值并检查图表中的更改:
此工具通常用于提高模型的性能,因为它使模型更符合正态分布,请记住,在完成模型的预测后,您必须返回到原始基数,根据下面的公式对变换进行反演:
寻找相关的滞后
要想预测,单变量序列必须具有自相关性,也就是说,当前周期必须基于更早的周期进行解释(一个滞后)。
由于该系列具有周周期,1 年大约是 52 周,我将使用显示 60 个滞后周期的自相关函数来验证当前周期与这些滞后的相关性。
分析上面的自相关图表,似乎所有的滞后都可以用于创建对未来事件的预测,因为它们具有接近 1 的正相关性,并且它们也在置信区间之外,但是该特征是非平稳序列。
另一个非常重要的功能是部分自相关功能,其中先前滞后对当前周期的影响被移除,并且仅在当前周期上被分析的滞后的影响被保留,例如:第四个滞后的部分自相关将移除第一、第二和第三个滞后的影响。
在部分自相关图下面:
可以看出,几乎没有滞后对当前周期产生影响,但是如前所述,没有微分的序列不是稳定的,我们现在将绘制这两个函数与具有一个微分的序列的关系,以了解其工作原理:
自相关图发生了显著变化,表明该序列仅在第一个滞后期具有显著相关性,在第 26 个月(半年)左右具有负相关的季节性效应。
要创建预测,我们必须注意一个关于寻找相关滞后的极其重要的细节,这种相关性背后有一个原因是很重要的,因为如果没有逻辑原因,这可能只是一个机会,当您包含更多数据时,这种相关性可能会消失。
另一个要点是,自相关和部分自相关图对异常值非常敏感,因此分析时间序列本身并与两个自相关图进行比较非常重要。
在这个例子中,第一个滞后与当前周期具有高相关性,因为前一周的价格历史上没有显著变化,在相同的情况下,第 26 个滞后呈现负相关性,表明与当前周期相反的趋势,这可能是由于一年中供应和需求的不同周期。
由于通货膨胀调整后的序列已经稳定,我们将使用它来创建我们的预测,在调整后的序列的自相关和部分自相关图下方:
我们将只使用前两个滞后作为自回归序列的预测值。
要了解更多信息,杜克大学教授罗伯特·瑙的网站是与该主题相关最好的网站之一。
评估模型的指标
为了分析预测值是否接近当前值,必须测量误差,这种情况下的误差(或残差)基本上是 Yreal YpredYreal Ypred。
评估训练数据中的错误以验证模型是否具有良好的断言性,并通过检查测试数据中的错误(模型“看不到”的数据)来验证模型。
当您将训练数据与测试数据进行比较时,检查错误对于验证您的模型是过拟合还是欠拟合非常重要。
以下是用于评估时序模型的关键指标:
平均预测误差—(偏差)
它只不过是被评估系列误差的平均值,值可以是正的也可以是负的。这一指标表明模型倾向于做出高于真实值(负误差)或低于真实值(正误差)的预测,因此也可以说平均预测误差是模型的偏差。
平均绝对误差
这个度量非常类似于上面提到的预测的平均误差,唯一的区别是将负值误差转换为正值,然后计算平均值。
此指标广泛用于时间序列,因为在某些情况下,负误差可以抵消正误差,从而表明模型是准确的,但在 MAE 的情况下,这种情况不会发生,因为此指标显示了预测值与实际值的差距,无论是高于还是低于实际值,请参见下面的情况:
Result: The error of each model value looks like this: [-4 -2 0 2 4]
The MFE error was 0.0, the MAE error was 2.4
MSE——均方误差
该指标对较大的误差给予更大的权重,因为每个误差值都是平方的,然后计算平均值。因此,该指标对异常值非常敏感,并对具有更大误差的预测给予很大权重。
与 MAE 和 MFE 不同,MSE 值采用二次单位,而不是模型的单位。
RMSE —均方根误差
此指标是 MSE 的平方根,其中误差返回到模型的测量单位(BRL/立方米),它在时间序列中非常常用,因为它对源于平方过程的较大误差更敏感。
MAPE —平均绝对百分比误差
这是另一个有趣的指标,通常用在管理报告中,因为误差是以百分比来衡量的,所以产品 X 的误差可以与产品 y 的误差进行比较。
此指标的计算采用误差的绝对值除以当前价格,然后计算平均值:
让我们创建一个函数,用几个评估指标来评估训练和测试数据的错误:
检查残值
根据所选的度量标准创建模型并检查误差值是不够的,您还必须分析残差本身的特征,因为在有些情况下,模型无法捕获做出良好预测所必需的信息,从而导致用于改进预测的信息出现错误。
为了验证该残差,我们将检查:
- 当前值与预测值(顺序图);
- 残差与预测值(离差图):
分析此图非常重要,因为在其中我们可以检查模式,这些模式可以告诉我们模型中是否需要一些修改,理想情况是误差沿着预测序列线性分布。
- 【QQ 剧情】 【残(散图)】:
总结一下,这张图显示了残差在理论上的分布,遵循高斯分布,而实际上是如何分布的。
- 残差自相关(顺序图):
其中不应有超出置信界限的值,或者模型将信息排除在模型之外。
我们需要创建另一个函数来绘制这些图形:
最基本的预测方法
从现在开始,我们将创建一些含水乙醇的价格预测模型,下面是我们将为每个模型遵循的步骤:
- 根据训练数据创建预测,然后根据测试数据进行验证;
- 根据上述指标检查每个模型的误差;
- 用剩余比较值绘制模型。
让我们看看模特们:
天真的方法:
进行预测的最简单方法是使用前期的值,这是在某些情况下可以做到的最佳方法,与其他预测方法相比,这种方法的误差较低。
一般来说,这种方法不能很好地预测未来的许多时期,因为相对于实际值,误差往往会增加。
许多人也使用这种方法作为基线,试图改进更复杂的模型。
下面我们将使用训练和测试数据进行模拟:
QQ 图显示,存在一些比理论上应该的更大的(上下)残差,这些是所谓的异常值,并且在第一、第六和第七滞后中仍然存在显著的自相关,这可以用于改进模型。
同样,我们现在将在测试数据中进行预测。预测系列的第一个值将是训练数据的最后一个值,然后这些值将由测试的当前值逐步更新,依此类推:
RMSE 和梅误差与训练数据相似,QQ 图的残差更符合理论上的情况,这可能是由于与训练数据相比样本值较少。
在比较残差与预测值的图表中,注意到当价格增加时,误差的绝对值有增加的趋势,也许对数调整会减少这种误差扩大,最终确定残差相关图表明仍有改进的空间,因为在第一个滞后中有很强的相关性,其中可能会添加基于第一个滞后的回归以改进预测。下一个模型是简单平均值:
简单平均值:
另一种进行预测的方法是使用序列平均值,通常这种形式的预测适用于值在平均值附近波动、方差恒定且没有上升或下降趋势的情况,但是也可以使用更好的方法,其中可以使用季节模式进行预测。
该模型使用数据开始时的平均值,直到前一个分析周期,并且每天扩展,直到数据结束,最后,趋势是直线,我们现在将比较该模型与第一个模型的误差:
在测试数据中,我将继续使用从训练数据开始的平均值,并使用将添加到测试数据中的值来扩展平均值:
简单均值模型未能捕捉到序列的相关信息,这可以从实际与预测图以及相关和残差与预测图中看出。
简单移动平均线:
移动平均值是为给定期间(例如 5 天)计算的平均值,并且是移动的,并且总是使用该特定期间进行计算,在这种情况下,我们将总是使用过去 5 天的平均值来预测第二天的值。
误差低于简单平均值,但仍高于简单模型,低于测试模型:
与训练数据类似,移动平均线模型优于简单平均线模型,但是它们还没有从简单模型中获益。
预测在两个滞后中具有自相关,并且误差相对于预测值具有非常高的方差。
指数移动平均线:
上面描述的简单移动平均模型具有平等对待最后 X 个观察值并完全忽略所有先前观察值的特性。直觉上,过去的数据应该逐渐被忽略,例如,最近的观察结果理论上应该比第二最近的稍微重要一点,第二最近的应该比第三最近的稍微重要一点,以此类推,指数移动平均线(EMM) 模型就是这样做的。
由于α(α)是一个介于 0 和 1 之间的常数,我们将使用以下公式计算预测值:
当预测的第一个值是相应的当前值时,其他值将被更新为实际值与前一时段的预测值之差的 α 倍。当 α 为零时,我们有一个基于第一个预测值的常数,当 α 为 1 时,我们有一个采用简单方法的模型,因为结果是前一个真实周期的值。
下图是几个 α 值的图表:
EMM 预报的平均数据周期为 1 / α 。比如当 α = 0.5 时,滞后相当于 2 个周期;当 α = 0.2 时,滞后 5 个周期;当 α = 0.1 时,滞后为 10 个周期,以此类推。
在这个模型中,我们将任意使用 0.50 的 α ,但是您可以执行网格搜索来寻找 α ,这减少了训练和验证中的误差,我们将看到它看起来是什么样子:
该模型的误差类似于移动平均线的误差,但是,我们必须在测试库中验证该模型:
在验证数据中,迄今为止的误差是我们已经训练的模型中第二好的,但是残差的图形特征与 5 天移动平均模型的图形非常相似。
自回归:
自回归模型基本上是具有显著相关滞后的线性回归,其中自相关和偏自相关图表应首先绘制以验证是否有任何相关。
以下是训练序列的自相关和偏自相关图表,显示了具有显著相关性的两个滞后的自回归模型的特征:
下面,我们将基于训练数据创建模型,在获得模型的系数后,我们将它们乘以测试数据所执行的值:
与我们训练的所有其他模型相比,此模型中的误差最低,现在让我们使用其系数来逐步预测训练数据:
请注意,在测试数据中,误差没有保持稳定,甚至比简单模型更差,请注意,在图表中,预测值几乎总是低于当前值,偏差测量显示实际值比预测值高 BRL 50.19,可能调整训练模型中的一些参数,这种差异会减小。
为了改进这些模型,你可以应用一些转换,比如本文中解释的那些,你也可以添加外部变量作为预测源,但是,这是另一篇文章的主题。
最终考虑
每个时间序列模型都有自己的特点,应该单独分析,以便我们可以提取尽可能多的信息,做出良好的预测,减少未来的不确定性。
检查平稳性、转换数据、在训练数据中创建模型、验证测试数据以及检查残差是创建良好的时间序列预测的关键步骤。
另见我关于 ARIMA 车型的帖子。
我希望你喜欢这篇文章,如果你有任何问题或你需要的信息,不要犹豫,通过我的 LinkedIn 联系我,也可以在这里评论。
基本 SQL 决定:我最喜欢的漫威角色
原文:https://towardsdatascience.com/basic-sql-decides-my-most-preferred-marvel-character-e393fb044397?source=collection_archive---------16-----------------------
Accredited to Unsplash
P.S 致敬斯坦·李(1922–2018)
介绍
作为一个被同龄男孩包围的年轻女孩,我们最喜欢的游戏之一是重演一部超级英雄电影(与其说是重演,不如说是改写),并选择我想扮演的超级角色。当时,我的选择非常主观,取决于哪个角色在我的记忆中仍然清晰,我的心情如何,以及我认为谁可以“假设”消除我玩伴的角色。
最近在回忆“那些美好的旧时光”时,我开始思考如何才能找出我最喜欢的漫威角色应该是谁。我认为“统计学和 SQL 可以解决这个难题”。
我决定引导我内心的“歇洛克·福尔摩斯”和结构来完成这个任务,这就是我想到的。
项目流程
- 阐明我的目标
- 找到数据
- 将数据插入数据库并清理数据
- 重新明确我的目标,并想出该用什么方法
- 操作:分析
- 获得结果,总结并思考可以改进的地方
客观澄清
这可能是(有争议的)任何分析中最重要的部分,尤其是如果你不想迷失在数据中,无休止地兜圈子。我的主要目的是用一个足够好的理由,而不是感情或“一时冲动”的时刻,来找出我最喜欢的超级角色应该是谁,也就是说,从统计学上来说做出选择。
数据
通过确定一个目标,我对我的数据应该包括什么有了一个清晰的想法:英雄的名字和跨越所有英雄的能力,或者可以使用 z 分数标准化的评级能力。
我决定只关注漫威的角色,因为我更喜欢他们。没有阴影的意图
我终于从一个名为 Mentrasto 的 Github 概要文件中找到了一个非常结构化的数据,它符合我的清单。这些数据由 26 个超级字符和 14 个特征组成,它们可以分为两类
- 个人详细信息
*ID*
:每个字符的唯一条目号name
:漫威人物的名字popularity
:基于排名的每个角色的受欢迎程度alignment
:区分角色是好(英雄)、坏(反派)还是只是中立gender
:如果一个角色是男是女height_m
:字符高度,单位为米weight_kg
:字符的重量,单位为千克hometown
:每个字符的起源
2。能力类别&评级
intelligence
: 智力等级从 1 到 7。 1 个是哑巴,7 个是天才strength
:强度等级从 1 到 7。 1 个是哑巴,7 个是聪明人speed
: 从 1 到 7 的速度等级。 1 傻 7 聪明durability
: 耐久性等级从 1 到 7。1 个是哑巴,7 个是天才energy_projection
: 能量投射技能等级 1-7。 1 傻 7 聪明- 战斗技能等级从 1 到 7。 1 傻 7 聪明
数据库存储
第三步是通过创建一个表并插入值来将我的数据存储在数据库中。我决定在这个项目中使用 SQLite,因为它是一个小型数据。
尽管数据源已经准备好被创建为数据库,但是您需要做的只是使用CREATE TABLE
子句和INSERT INTO
子句,您就可以开始分析了。这就是我的意思。
要创建表,请使用
或者就我而言
若要插入值,请使用
对我来说
你可以观看这个视频来了解如何使用 SQLite 的要点。
我决定使用SELECT *
子句来看看我的数据在 SQL 中是什么样子
重新阐明目标
有这么多计划外的专栏可用,我需要再次澄清我的目标,即统计出谁是我最喜欢的角色。
这意味着我唯一需要关注的个人信息是名字。
因为所有可用的英雄都基于 6 种能力被同等地评级,所以没有必要标准化数据。由于目标更多的是描述性的,而不是推断性的,所以想到的一个常见的趋势测量是平均值。
操作:分析
我直接进入主要任务,得到每个技能的平均值,计算每个英雄超过每个技能平均值的次数,然后选择最高的次数。
我做了WITH
子句、集合函数和CASE
语句。这基本上是一个包含大量CASE
语句的完整查询。
这总结了我所有的分析。
但是让我带您浏览一下每个查询组件
使用CASE
语句获得所有能力的平均值
然后合计从新列中得到的分数,使用ORDER
子句对分数进行排序,并得到最上面的字符。您可以在下面找到用于捕获它的查询
瞧啊。您需要做的就是使用一个WITH
语句将两个查询组合起来。
结果呢?
胭脂,x 战警的女成员赢了。
Disclaimer: Originated from https://www.marvel.com/comics/discover/1018/rogue
老实说,这并没有让我感到惊讶,因为胭脂这个角色可以吸收任何变种人的能力并用它来对付他们,同时让他们虚弱甚至死亡。
现在我可以自信地扮演胭脂…任何一天
最终想法
虽然这是一个非常酷的发现,但我意识到了一些事情。
- 这是一个非常小的数据库。一个更大的数据库,有更多的漫威人物和更多的判断能力,可能会得出完全不同的结果。下一步是获取更多的数据。
请随时从 漫威数据库 获取更多数据
所使用的代码也可以应用于更大的数据。但是,这将取决于基于大小的优化(查询运行的速度)。
你可以在我的 Github 这里 查看我的代码
- 所用测量值的选择(平均值或均值)可能会受到异常值的影响。下一步是检查定量列中的异常值,如果有的话,使用中值度量。
奖金
我开玩笑地决定根据他们的身体质量指数(身体质量指数)对所有角色进行分类,因为数据是可用的,并且已经被转换成适当的维度。目的是看有多少人肥胖、超重、健康或瘦。这是我在下面得到的。
同样,我的数据中的所有角色都肥胖也不足为奇,特别是因为这些数据似乎是来自真实的卡通角色的细节,而不是扮演每个角色的人。因此,大多数漫画都是对人类的漫画,带有一些夸张的身体部位。
_____________________________ 结尾 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
像我一样,任何人都可以学习成为一名数据分析师,如果你想了解我的下一个项目或我学习的最新进展,请随时注册我的 简讯
每位数据科学家的基本统计数据
原文:https://towardsdatascience.com/basic-statistics-for-every-data-scientist-898ab5116a08?source=collection_archive---------21-----------------------
Photo by Ruthson Zimmerman on Unsplash
你对自己的估计有多少信心?!
从一个给定的数据集中计算一个变量的平均值可能很容易,但同样难以理解的是从中找出意义。你刚刚计算的平均值,实际上是多少?是人口平均数?但是等等!你只是带了一个代表整个人口的样本。记住,在统计学家的世界里,绝对没有什么是确定的。所以,是的,你刚刚计算的平均值有一些误差。那个错误是什么?回答这个问题需要你知道你想把这个意思解释为什么。
这篇博客将带你详细了解这些概念,并解释样本数据平均值的各种解释方式以及每种情况下的误差。博客中谈到的所有概念最后都以三个要点的形式进行了总结。
我将借助一个数据集来讨论这些概念,这个数据集可以扩展到任何场景中的任何数据集。
Sample Dataset
我们有一份奥斯汀公寓的清单,包括面积和租金。现在,除非我们拥有的数据涵盖了奥斯汀的每一套公寓,否则这将被称为未来的样本。这确实是真实的情况,几乎总是这样,我们只能接触到我们感兴趣的全部人群中的一个样本。
群体是每个感兴趣的数据点的集合。随机样本是从总体中随机收集的数据点的子集。
我们的公寓群有一批面积为 A1 的公寓,另一批面积为 A2 的公寓,等等。假设我们能得到的数据是从这个群体中随机抽取的样本,这个群体的平均租金是 1。
让我们解释一下样本的意思…
这个样本数据的平均租金可以用两种方式解释。1 是一个很好的估计-
a) 奥斯汀公寓全部人口的平均租金。也就是说,如果你相信你的样本是随机产生的,那么总体均值可以很好地近似为样本均值。
b) 从所有奥斯汀公寓的人口中随机选择的公寓。具体来说,如果你碰巧从整个城市中随机挑选了一套公寓,并想进行计算猜测——对其租金进行估计,你最好的选择是你可以获得的样本数据的平均值。
当谈到评估时,一个直接的后续问题是…
我们对自己的估计有多少信心?
在继续讨论误差范围和置信区间之前,我们将试图了解 1,2,3…之间的关系。这将有助于理解这个概念。
根据示例数据,假设我们的人口平均值(通常称为真实平均值)是 500 美元(实际上我们不知道,因为我们无法访问整个人口)。很有可能随机抽取的样本的平均值 I(我们可以从现有数据中计算出来)接近 500 美元。但是肯定会有一些随机的样本,在这些样本中你碰巧选择了所有租金高的公寓或者所有租金低的公寓。对于这样的样品,我会远离 500 美元。看起来我们可以有一个 I 的分布。
中心极限定理表明,如果观察值足够大,假设样本均值正态分布在真实总体均值附近是安全的。经验法则将“足够大”定义为 n=30。
除了这个正态分布,我们还需要了解另一个分布的特征。
单个公寓的租金在样本均值附近的分布不必是正态的。
一旦我们有了数据,我们需要做一些工作来弄清楚这个分布是什么样子的。但是我们知道的是,我们人口中的单个公寓将遵循与我们的随机样本关于样本均值相似的关于人口均值的分布。
牢记这些要点,让我们现在继续前进。
计算误差幅度和置信区间
开始时,我们对样本均值有两种解释。我们对这些估计有多少信心?
a)作为总体均值估计的样本均值:
从上面讨论的分布中,我们知道这些样本平均值与总体平均值相差多少。
误差幅度将是样本均值总体(非个人公寓租金)的标准偏差。
但是等等!我们只有一个样本!理论拯救了我们。数学证明-
样本均值的标准偏差=样本点的标准偏差/sqrt(观察值数量)
直觉上,这是有意义的,因为样本均值的标准差必须小于单个公寓的标准差!(随机)样本均值将围绕总体均值杂乱分布,我们可以预期它们非常接近于相同值,因此标准差很小。然而,样本中的单个公寓将表现出更多的变化,导致更高的标准偏差。现在,sqrt(n)的确切因子必须通过数学推导得出。
假设样本均值的标准差为 x. 下一个问题是,我们对真实总体均值在这个误差范围内的置信度是多少?
利用样本均值正态分布于总体均值的事实,我们可以 68%确信总体均值位于样本均值的 x 范围内。
b)样本均值作为个人公寓租金的估计值
既然我们说我们所取的样本是随机的,我们就可以用这个样本分布来近似我们总体的性质。因此,人口中单个公寓租金的标准差将与样本公寓租金的标准差相同(即 x ) 。
因此,误差幅度就是租金的样本标准差。
对于实际租金将在这个误差范围内的置信度,如果租金是正态分布的,那么我们可以预期 68%的置信度。但是,由于个人租金关于平均值的分布不一定是正态的,所以需要做一些工作来计算置信区间(这将因每种分布类型而异)。一个简单的方法是计算样本均值 x 范围内的样本租金数,然后除以样本数据点数。
所有信息总结如下—
- 样本均值是对 a .总体均值和 b. 单个数据点的良好估计。
- 当使用样本均值作为前者时,我们可以有 68%的把握认为真实均值在我们的误差范围内(使用正态分布的特征)。这里的误差幅度是样本均值分布相对于总体均值的标准偏差。这可以通过使用样本点相对于样本平均值的标准偏差来计算。
- 当使用样本平均值作为单个数据点的估计值时,样本的标准偏差可用作误差范围。由于单个点关于其平均值的分布不一定是正态分布,置信区间将随手头的每个数据集而变化。
我要感谢托马斯·萨格教授在课堂上讲授这些概念。我尽力通过这个博客来传递我的学习成果。希望这有助于澄清围绕样本均值解释的混乱。如果你有任何问题,请在评论中告诉我!
数据科学产品管理基础:ML 工作流
原文:https://towardsdatascience.com/basics-of-ai-product-management-orchestrating-the-ml-workflow-3601e0ff6baa?source=collection_archive---------10-----------------------
ML 理论难,应用更难!
过去几年,我一直在将数据科学应用于商业的不同方面。一些用例是内部机器学习(ML)工具、分析报告、数据管道、预测 API 以及最近的端到端 ML 产品。
我有过成功和失败的 ML 产品的公平分享。甚至有关于 ML 产品恐怖故事的报道,其中开发的解决方案最终未能解决它们应该解决的问题。在很大程度上,可以通过适当地管理 ML 产品来填补这一空白,以确保它最终对用户真正有用。
我很快了解到,管理 ML 产品很困难,因为机器学习(ML)工作流程中的不同步骤涉及到复杂性和不确定性(列举如下):
- 相关文献综述(及其他资源)
- 数据采集&处理
- 模型训练,实验,&评估
- 部署
考虑到 ML 工作流程中的困难和我们的资源限制(例如,时间、人员、存储和计算),我们如何确保我们的每个步骤的方法将最大化 ML 模型对整个 ML 产品的价值贡献?
在这篇博文中,我的目标是给出这些步骤的概述,同时举例说明一些可预见的挑战和我发现在优化 ML 工作流中有用的框架。请注意,在给定可用资源的情况下,当 ML 工作流创建的 ML 模型对整个产品的附加值最高时,我们认为 ML 工作流是优化的。
此外,这篇文章是为至少对机器学习概念、工具和工作流有高度理解的读者准备的;但是,如果您不熟悉我提到的一些概念,请不要担心。我经常链接到解释这些概念的文章,即使对那些我不理解的文章,快速的谷歌搜索也能给出高水平的理解。
我们开始吧!
1.相关文献(和其他资源)的回顾
ML 工作流程的相关文献回顾(RRL)步骤包括阅读现有方法、数据集和其他可能与我们将用于模型的方法相关的资源。这为我们的方法提供了一组可能的设计选择。这些设计选择的例子有
- ML 算法
- 神经网络架构
- 超参数值(例如隐藏层数)
- 优化者
- 特征工程
- 自然语言处理中的文本预处理方法
- 汇集方法
- 数据集
- 用于部署的云服务
大多数设计选择取自相关文献,但也有可能一些组件是“从零开始”创建的,这通常是因为项目的某些方面可能与相关文献中的任何内容都不同。例如,如果被训练的模型旨在根据一个人的在线购物来预测其收入,并且没有关于该主题的论文/博客发表,那么您的团队可能必须生成他们自己的关于特征工程的设计选择。
另一个相关的产品管理(PM)问题是在开始模型开发之前决定给 RRL 分配多少时间。以我的经验来看,花 1-2 周的时间关注 RRL 是合适的。在某些情况下,让一组成员专注于 RRL,而另一组成员专注于进行基于 RRL 发现的实验也是有意义的。后者对于更大的团队更可行。
RRL 还应该告知我们可供我们使用的资源。从这里开始,我们必须了解这些可以在多大程度上减少工作量,甚至消除我们工作流程中某些部分的需要。
例如,预训练模型的存在可能会加快训练时间,同时需要更少的训练数据,这意味着我们可以分配更少的时间来进行模型训练和数据集生成(在监督模型的情况下)。在语义搜索的上下文中,我们甚至可以通过使用由预训练的 BERT 模型生成的特征来完全消除模型训练的需要。
对于带标签的数据集形式的可用资源,确定标签是否与我们希望模型实现的目标一致对我们来说很重要。例如,如果我们想要训练一个模型,它可以在没有足够大的客户服务数据集的情况下识别客户服务电子邮件的情绪,那么 IMDB 评论数据集是否与训练该模型相关?我们可以假设这个问题的答案,但如果我们能找到一种方法来测试在 IMDB 评论上训练的模型是否能正确检测客户服务电子邮件上下文中的情绪,那就更好了。我们将在下一节更详细地讨论数据。
总之,RRL 步骤告诉我们现有的方法和可用的资源,这将有助于设计和规划我们的 ML 工作流程。
2.数据收集和处理
这一步包括获取数据并将其处理成一种状态,在这种状态下,可以将数据输入 ML 模型进行训练或评估。此步骤的方法主要取决于七个因素:
- 数据的大小
- 运行查询所需的计算能力
- 可利用的资源
- 数据库文档的质量
- 数据的清洁度
- 数据源
- 地面实况数据的可用性
从上面可以看出,数据的大小(1)和所需的计算能力(2)会影响提取和处理数据所需的资源量。特别是当可用资源(3)有限时(例如,来自内部数据中心的固定资源),这意味着对于具有复杂查询的大型数据集,数据拉取更慢且更昂贵,这证明需要额外的查询优化工作和数据采样。在 hive 查询的情况下,这可能意味着一次在几个分区上运行优化的查询来进行初始数据提取。此外,值得注意的是,使用云计算平台(例如 GCP 和 AWS)可以缓解存储和计算方面的资源稀缺问题,因为这些平台允许您“按需”使用资源,而无需遵守物理数据中心的限制。
虽然数据的整洁性(5)可能会增加数据处理的资源需求,但数据库文档的质量(4)不会影响所需的资源。但是,这两个因素都会影响编写从必要的数据库中提取数据所需的查询所需的时间。一个巨大的瓶颈通常来自于不知道哪些表包含您需要的确切字段。一个记录良好的数据库会使找到正确的字段变得容易,而一个记录不良的数据库会大大减慢你的工作流程。类似地,不干净的数据会降低您的速度,因为需要额外的(通常非常繁琐的)步骤来将字段转换成处理所需的格式。
你的数据来源(6)也有相关的风险。在数据源来自公共 API 或网站(通过 web crawler)的情况下,还存在可用性、可维护性和合法性的问题。就 API 而言,曾经“免费”使用的东西很有可能以后需要通过“订阅”按月付费。另一个问题是,当这些资源的所有者突然对您在一段时间内可以获取的数据量施加速率限制时(例如,每天 5 次请求)。
对于被爬取的网站,维护成为一个大问题,因为网络爬虫通常对被爬取的网站中的任何变化非常敏感。此外,如果被抓取的网站基于其条款&条件明确禁止抓取,网络抓取可能会有法律问题,所以在进行任何网络抓取之前最好先检查一下。由于这些原因,当你的 ML 产品需要从公共 API 和网站获取时,警惕这些风险是很重要的。尽早了解这些情况会让你做好准备,为事情变糟做好潜在的替代方案。
最后,用于模型评估的地面真实数据(7)的可用性将决定我们是否必须设计一种方法来标记数据。通常,标记数据有两个可能的来源:1)外部方,2)用户。根据建模任务的难度,来自外部方的“高质量”标签数据的成本会有所不同。对于技术任务(例如医学期刊的信息提取),只有领域专家用户能够给出高质量的标签。对于简单的任务(例如狗对猫的图像分类),领域专家不需要有高质量的标签。那么我们为什么不直接让领域专家用户一直标记数据呢?因为它们通常更贵(想象一下按小时付费给医生来标记数据)。换句话说,随着建模任务变得越来越复杂,雇人标记数据的成本也变得越来越高。
一个聪明的解决办法是让用户为你创建你的基本事实数据。这可以通过在 ML 产品中嵌入“标签”来实现,同时最大限度地减少摩擦,甚至将标签过程转变为增值活动。一个很好的例子是脸书给用户“标记”朋友的能力,让他们知道他们在照片中。通过标记您的朋友,您正在“标记”他们的图像数据集。用户受益是因为他们可以和朋友联系,而脸书受益是因为他们得到了“免费”标签的数据。大家都赢了!
我计划在未来的博客文章中进一步讨论将评估嵌入到你的人工智能产品中的话题。
3.模型培训、实验和评估
现在我们来看 ML 工作流程中最著名的部分:实际训练模型和试验不同的方法!
您可能读过一些文章,这些文章谈到训练模型只占数据科学家工作的 20%。这是非常准确的,但是从 PM 的角度来看,重要的是要理解要考虑的主要事情是:
- 计划的实验
- 培训运行时间
- 精确度定义
- 准确度基线
在你开始训练你的模型之前,你应该已经对基于你的团队的假设(由 RRL 步骤的发现支持)你计划运行的实验有一些想法。列出这些步骤,并根据模型的预期改进(就准确性而言)和所需的增量时间对它们进行排序。预期改进最高、所需时间最短的实验应该在最上面。
此外,区分需要重新训练模型的实验和不需要重新训练的实验也很重要。例如,在模型被训练用于文本分类之后,假设输入文本的格式仍然一致,人们仍然可以试验不同的文本预处理方法。对于不需要“再训练”的实验,时间成本通常要低得多,因为训练运行时间占实验时间成本的大部分。这意味着许多非再培训实验可以被视为团队可以快速执行的“速赢”。
关于非训练实验要注意的一点是,它们通常是那种你只有在已经有一些训练好的模型之后才能做的实验(例如,模型集合需要已经训练好的模型)。正因为如此,我通常把实验期的最后一段时间分配给快速的非训练实验,而训练时间较长的实验则在实验期的最开始进行。
Training runtime (2)只是讨论一个版本的模型在数据集上训练需要多长时间。这很重要,因为训练一个模型(对于需要训练的实验)需要多长时间将决定你可以用不同版本的模型做多少次实验,给定你为你的项目承诺的时间表。
这意味着你很可能没有足够的时间来完成你计划进行的所有实验。无论如何,应该首先进行排名较高的实验;然而,该团队也可以通过减少执行实验所需的时间来增加实验的数量。一个简单的方法是减少训练时间。
那么我们如何控制训练运行时间呢?通常,这可以通过简化模型(例如,减少神经网络的层数)或减少数据集的大小(例如,从数据集中选择示例或要素的子集)来控制。我采用的一种非常有效的简单方法是从一个模型的最简单版本开始,使用最小的合理数据样本(即运行时间最快的版本)。然后,你可以逐渐增加模型的复杂性和样本量,直到你达到你的目标训练运行时间——允许你进行所有计划的实验的运行时间。跟踪模型复杂性和样本大小的每个级别的准确性和运行时间也很重要,这样您就可以利用这一点来了解与增加的复杂性和样本大小相关的时间权衡。
Tradeoff between Training Runtime and Sample Size + Model Complexity
减少培训运行时间的另一种方法是升级您可以访问的硬件资源(例如 GPU 和 CPU)。幸运的是,云计算平台允许人们定制不同价位的可用资源。因为升级的成本是完全记录在案的,所以升级决策是由升级成本和培训运行时的预期加速决定的。为了充分利用这些资源,许多训练算法实现通过并行化(例如 pytorch、tensorflow、scikit-learn)来加速操作。
最后,我们必须定义模型的准确性度量(3 ),我们将使用它来评估每个实验的结果。要记住的重要一点是,准确性指标应该是模型对整个 ML 产品的价值贡献的度量。因此,你需要对你的 ML 产品试图解决的问题有一个深刻的理解,并从那里,回到模型正在执行的特定任务,并确定它帮助产品解决问题的确切方式。
一个常见的错误是只关注准确性度量,因为这是特定任务的常用度量。事实上,确保模型的准确性度量与其对产品的价值贡献一致是非常重要的:否则,更好的执行模型不会转化为更好的产品,在这种情况下,实验将是徒劳的。
例如,在 Airbnb 的情况下,主机偏好通过主机将接受预订请求的概率来建模。鉴于接受概率较高的预订首先显示给客人,这也意味着更多的预订将被接受,这将转化为 Airbnb 的收入提升。模型越精确,接受率越高,收入也越高。
一旦价值度量被确定,团队现在需要一个基线性能(4)来决定模型是否“成功”以及成功的程度。我设定基线性能的一个框架是理解性能水平,这将使模型对 ML 产品真正“有用”。这可能是一件很难做到的事情,但它可能是有用的,因为它:1)迫使我们思考模型应该如何为用户提供价值,2)给我们一个初始的目标性能,我们可以用它来评估有用性,3)激励团队与用户进行实际的对话,以理解模型在为他们提供价值中的作用。
从长远来看,通过运行 A/B 测试来比较不同版本的模型对实际产品价值指标(如收入、签约、订单)的影响,可以更经验性地得出有用性。Airbnb 是一家拥有数据科学文化的公司的一个很好的例子,这种文化通过 A/B 测试使用实验来评估模型。这确保了他们的模型确实在改进产品。
4.部署
部署是 ML 工作流中的最后一步,该方法主要取决于:1)预测是实时需要还是周期性批量需要,以及 2)延迟要求。
如果实时预测是必要的,那么模型可能会被部署为一个 API,可以通过向这个 API 发送请求来检索预测。这通常使用在单独实例(例如 AWS ec2)上运行的 flask 或 django 等应用框架或在云上运行预测脚本的 FaaS 平台(例如 AWS Lambda)来完成。
如果需要以特定的频率(例如每天、每月)批量进行预测,那么定期对新数据运行预测脚本就足够了。对于这种情况,像 crontab(内置于 Linux 中)和其他自动化框架(例如 Airflow、Luigi)这样的工具就足够了。由于广泛记载的原因,我更喜欢使用气流进行批量部署。
对于延迟需求,它基本上回答了这个问题:模型需要多快才能做出预测?通常,应用程序会有服务级别协议(SLA ),将预测延迟保持在某个标准。
例如,当您打开中型应用程序时,他们会向您显示一个文章推荐列表,该推荐列表可能是 1)“预测的”并每天存储一次,在您打开应用程序时向您显示(批量部署),或者 2)在您打开应用程序时“预测的”(实时部署)。自然地,第一个只需要预测 SLA 足够快,以便用户在早上打开应用程序时(例如,从每天午夜起的 5 个小时)将看到更新的列表。其次,SLA 必须更加严格,因为预测是在用户打开应用程序时发生的(例如,从打开应用程序起 1 秒钟),用户不希望等待太久才能看到他们推荐的文章。
从上图可以明显看出,延迟更可能是实时部署的一个问题。那么,我们如何将延迟降低到可接受的水平(SLA),假设目前还没有达到这个水平?例如,想象一下打开应用程序后,预测需要 5 秒而不是 1 秒的 SLA。
这就是机器学习工程(MLE)的用武之地。MLE 涉及使用特殊技术(例如并行化)来加速部署的机器学习模型的运行时间,目标是达到设定的 SLA。ML 工程师的工作是将 5 秒预测运行时间降低到目标 1 秒预测运行时间。
结论
至此,你应该对 ML 工作流程有了一个总体的了解,以及在设计每个步骤的方法时需要考虑的一些不同的事情。请务必注意,在每个冲刺阶段结束时,应与您的数据科学团队详细讨论每一步,以便在给定所有可用信息的情况下,计划的方法在任何时间点都是最佳方法。
此外,我认为,在成为数据科学产品经理之前,拥有数据科学方面的全面经验具有相当大的优势。这是因为设置积压工作、确定任务优先级、估计时间表以及沟通 ML 产品如何工作和提供价值需要深入了解 ML 工作流程以及与每个步骤相关的不确定性。即使仅仅从优先化任务和制定时间表的角度来看,理解 ML 工作流也意味着了解随着项目的进展新信息的含义。
我计划在以后的博客文章中对数据科学产品管理的其他方面进行更详细的讨论(例如,设置待办事项、区分任务优先级、估计时间表、使 ML 模型目标与产品的价值主张保持一致、将评估集成到 ML 产品中、管理 ML 的新利益相关者)。如果你对从哪些开始有任何建议,请随时评论、或通过、、推特、 linkedin 或电子邮件(lorenzo.ampil@gmail.com)联系我。敬请期待!
初学者 BASH 基础。
原文:https://towardsdatascience.com/basics-of-bash-for-beginners-92e53a4c117a?source=collection_archive---------0-----------------------
了解一些最有用的 BASH 命令及其提供的实用程序。
Source
今天大多数计算机都不是由电力驱动的。相反,它们似乎是由鼠标的“跳动”提供动力的:威廉·肖特
你有没有注意到电影中的超级书呆子黑客如何通过凶猛地键入一些命令并盯着黑色背景的绿色屏幕,轻松地渗透到最安全的银行并抢劫它们?这个人是如何始终如一地获取所有密码,并在任何地方控制隐藏的摄像头,只需在键盘上敲几下。嗯,我不确定电影制作者是怎么得到这个的,但我猜这是他们告诉我们,命令行是一个强大的工具,尽管没有授权所有这些黑客攻击和访问!!荒谬。
很多时候,初学者非常习惯于使用基于 GUI 的界面,以至于他们往往会忽略命令行界面(CLI)的功能。当我们需要将大约十万个文件复制到一个文件夹中时,鼠标真的很方便,但是如果要重命名所有这些文件或者根据它们的扩展名将它们分开会怎么样呢?因为图形用户界面是不可编程的,所以我们要花很长时间用命令行来重命名或分隔它们,然而,我们可以用几行代码很快实现这一点。
对于各种开发人员来说,Unix shell 是一个非常强大的工具。本文旨在快速介绍从 UNIX 操作系统开始的基础知识。
一种多用户的计算机操作系统
除了基于 WINDOWS 的操作系统,今天的大多数操作系统都是建立在 UNIX 之上的。其中包括许多 Linux 发行版、macOS、iOS、Android 等等。仅仅浏览一下基于 UNIX 的操作系统的系谱就足以突出 UNIX 的重要性,这也是它在业界被广泛采用的原因。事实上,许多数据和计算系统的后端,包括像脸书和谷歌这样的行业巨头,都大量使用 UNIX。
The UNIX Family Tree. Source: WIkipedia
壳
Shell 是在计算机上运行程序的命令行界面。用户在提示符下键入一串命令,shell 为用户运行程序,然后显示输出。这些命令可以由用户直接输入,也可以从称为 shell 脚本或 shell 程序的文件中读取。
外壳类型
UNIX 系统通常提供多种 shell 类型。一些常见的是:
然而,在本文中,我们将仅限于 Bash shell。然而,我们鼓励你阅读和尝试其他 shell,尤其是 zsh shell ,因为在最新的 MacOS 中,名为 Catalina, zsh 将取代 bash shell。所以现在了解一下是个好主意。
末端的
终端是一个用于与外壳交互的程序。它只是 Shell 和运行在其中的其他命令行程序的接口。这类似于网络浏览器是网站的接口。下面是 Mac 上典型终端的样子:
A Typical Mac Terminal
Mac 和 Linux 都有各自版本的终端。Windows 也有一个内置的命令 shell,但是它是基于 MS-DOS 命令行的,而不是基于 UNIX 的。因此,让我们看看如何在 Windows 上安装一个 shell 和一个终端程序,其工作方式与 Mac 和 Linux 上的相同。
在 WINDOWS 上安装
- Windows Linux 子系统(WSL)
它是 Windows 10 中新的 Linux 兼容系统。WSL 允许开发人员直接在 Windows 上运行 GNU/Linux 环境——包括大多数命令行工具、实用程序和应用程序,无需修改,没有虚拟机的开销。你可以在这里阅读更多关于它的安装和特性。
- Git Bash
Git Bash 是我们将在本文中使用的东西。从这里下载 Git 到你的 Windows 电脑上,用所有默认设置安装。最后你得到的是一个终端窗口,就像下面这样。
A Windows Git Bash
探索终端
每当我们打开终端窗口时,我们都会看到上次登录的凭证和一个 Shell 提示符。每当 shell 准备好接受输入时,就会出现 Shell 提示符。根据发行版的不同,它的外观可能会稍有不同,但大多数情况下,它显示为username@machinename
后跟一个$符号。
如果您不想要这些信息,您可以使用 PS1 定制您的 shell 提示符。
终端现在只会在提示符下显示$
。但是,这只是暂时的,一旦终端关闭,它将恢复到原来的设置。
入门指南
为了掌握一些窍门,让我们尝试几个简单的命令:
- echo: 返回您在 shell 提示符下键入的任何内容,类似于 Python 中的
Print
。
- 日期:显示当前时间和日期。
- 日历:显示当月的日历。
- 清除端子 :
Ctrl-L
或clear
清除端子
基本 Bash 命令
bash 命令是 bash 可以独立执行的最小代码单元。这些命令告诉 bash 我们需要它做什么。Bash 通常接受来自用户的单个命令,并在命令执行后返回给用户。
工作目录
显示当前工作目录
pwd
代表print working directory
,它指向当前工作目录,即 shell 当前正在查看的目录。这也是 shell 命令查找数据文件的默认位置。
目录类似于文件夹,但是在 Shell 中,我们将坚持使用目录这个名称。UNIX 文件层次结构有一个树形结构。为了到达一个特定的文件夹或文件,我们需要遍历这个树结构中的某些路径。路径在斜线(/
)字符的帮助下分隔上述结构的每个节点。
导航目录
像ls
和cd
这样的命令用于导航和组织文件。
限位开关(Limit Switch)
ls
代表一个list
,它列出了一个目录的内容。通常从查看我们的主目录开始。这意味着如果我们单独打印ls
,它将总是打印当前目录的内容,在我的例子中是/Users/parul.
My Home directory represented in the shell and the GUI interface.
参数
当与ls
命令一起使用时,参数和选项打开一些特殊功能。
**ls** <folder>
:查看特定文件夹的内容。**ls -a**
: 用于列出文件夹中所有隐藏的文件**ls -l**
: 打印出更长更详细的文件列表。ls -l
也可以与目录名一起使用,列出该特定目录下的文件。**ls ~**
: 波浪号(~)是表示主目录的快捷方式。所以,不管我们进入哪个目录,ls ~
总是会列出主目录。
通配符
shell 还允许我们用星号(*)表示的模式来匹配文件名。它充当通配符来替换给定模式中的任何其他字符。例如,如果我们列出*.txt
,它将列出所有扩展名为.txt
的文件。让我们试着列出所有的。演示文件夹中的 py 文件:
激光唱片
cd
代表Change Directory
并将活动目录更改为指定的路径。在我们cd
进入一个目录后,可以用ls
命令查看那个目录的内容。让我们来看看使用该命令的一些方法:
**cd <Directory>**
:将当前目录切换到所需目录。让我们导航到位于Demo
目录中的test
目录,并使用ls
命令查看其内容。注意,我们也可以使用分号(;)在同一行上写两个命令。
**cd ..**
:返回父目录。**cd**
:返回主目录
组织文件
有一些命令可以让我们在 shell 内部移动、删除、创建和复制文件。
mkdir
mkdir
代表Make directory
,用于新建一个目录或文件夹。
平均变化
mv
代表Move
,它将一个或多个文件或目录从一个地方移动到另一个地方。我们需要指定要移动的内容,即源和要移动到的位置,即目的地。
让我们在名为PythonFiles
的演示文件夹中创建一个新目录,并使用上面的两个命令将所有.py
文件从演示文件夹移动到其中。
触控
touch
命令用于创建新的空文件。它还用于更改现有文件和目录的时间戳。下面是我们如何在演示文件夹中创建一个名为foo.txt
的文件。
空间
rm
代表Remove
,它删除文件或目录。默认情况下,它不会删除目录,但是如果在一个目录中用作rm -r *
,那么该目录中的每个目录和文件都会被删除。
现在让我们删除之前创建的foo.txt
文件。
删除目录
rmdir
代表remove directory
,用于从文件系统中删除空的目录。让我们删除我们不久前创建的PythonFiles
文件夹。
注意到../表示父目录。
查看文件
这是果壳的另一个方面,超级有用。有些命令可以帮助我们查看文件的内容,这样我们就可以对它们进行操作。
猫
cat
代表concatenate
,它读取一个文件并输出其内容。它可以读取任意数量的文件,因此得名 concatenate。在我们的演示文件夹中有一些文本文件,让我们使用 cat 来查看它们的内容。
要查看多个文件,请在cat
命令后输入两个文件名:
$ cat Names.txt fruits.txt
较少的
cat
命令在屏幕上显示文件的内容。当文件内容较少时,这没有问题,但当文件很大时,这就成了一个问题。从下面的例子中可以看出,该命令在终端以非常高的速度弹出所有内容,我们无法理解文件的所有内容。幸运的是,有一个叫做less
的命令可以让我们查看内容,一次一屏。
$ less babynames.txt
有一些选项可以使用:
Spacebar
:进入下一个屏幕
b
:转到上一屏幕
/
:搜索特定单词
q
:退出
男人
man
命令显示手册页,这是许多 Linux 和大多数 Unix 操作系统默认内置的用户手册。
man bash
:显示整本手册
man <keyword>
eg man ls
给出关于 ls 命令的信息。
管道和过滤器
管道运算符“|”(竖线)是一种将一个命令的输出作为另一个命令的输入发送的方法。
command1 | command2
当命令将其输出发送到管道时,该输出的接收端是另一个命令,而不是文件。下图显示了wc
命令如何统计cat
命令显示的文件内容。
在某种程度上,wc
是一个接收输入并以某种方式转换这些输入的命令。这样的命令被称为过滤器,并且被放置在 Unix 管道之后。
过滤
现在让我们看看一些常用的过滤器命令。我们将使用一个名为baby names . txt的文件,其中包含大约 1000 个婴儿的名字,以及一个包含一些水果名字的 fruits.txt 文件。
- grep 或
global regular expression print
搜索具有给定字符串的行或在给定的输入流中寻找模式。以下命令将读取所有文件,并输出包含单词“Tom”的所有行
但这是一个庞大的列表,我们不可能理解所有这些刚刚在终端爆炸的数据。让我们看看如何使用管道操作符来理解它。
- wc 是的简称
word count.
它读取文件列表并生成一个或多个以下统计数据:换行计数、字数计数和字节计数。让我们将上述grep
命令的输出输入到wc
中,以计算包含单词“Tom”的行数
- 排序过滤器按字母或数字顺序对行进行排序
cat
命令首先读取文件fruits.txt
的内容,然后对其进行排序。
- uniq 代表
unique
,它给出了输入流中唯一的行数。
需要注意的是uniq
不能检测重复的条目,除非它们是相邻的。因此,在使用 sort 命令之前,我们已经对文件进行了排序。或者,也可以用sort -u
代替uniq
。
管道对于执行一些复杂的任务非常方便,因为几个命令可以放在一个管道中。
进一步阅读
命令行工具是对工具箱的一个很好的补充。最初,对于初学者来说,它可能是令人生畏的,但是一旦他们掌握了它的窍门,它真正的优势和好处就可以实现了。这篇文章是让一个开始,只触及表面。网上有大量有用的资源可以用来探索和学习关于 shell 的细节。以下是一些推荐的资源:
- Linux 命令行第五版网络版威廉·肖茨
- Bash 初学者指南
- 巴什学院
贝叶斯网络基础
原文:https://towardsdatascience.com/basics-of-bayesian-network-79435e11ae7b?source=collection_archive---------13-----------------------
介绍
贝叶斯网络上的文本数不胜数,但其中大部分都有沉重的数学公式和概念,因此很难理解。在这里,我试图用最少的等式和一个真实世界的例子来尽可能简单地解释这个主题。
基本概念
贝叶斯网络是一个非常重要的工具,用于理解事件之间的相关性,并为它们分配概率,从而确定一个事件发生的可能性有多大,或者给定另一个事件发生的变化是什么。例如,假设你在学校因为迟到被老师责骂,迟到的原因可能有很多,比如起床晚了,交通堵塞等等。所以在这里,责骂取决于像晚起或交通堵塞这样的事件,也就是说,这些原因对你被责骂有直接影响。这可以有效地用贝叶斯网络来表示,我们很快就会看到。
Fig. 1
让 {X1,X2,……。有些事情就像被骂,晚起等等。在贝叶斯网络中,它们可以表示为节点。现在,如果一个节点依赖于另一个节点,那么从一个节点到另一个节点画一个箭头/弧线,如图 1 所示。它被解释为子节点的出现受其父节点的出现的影响。所以贝叶斯网络代表一个有向无环图。不允许在节点内形成循环模式,所以它是非循环的。
Fig. 2: The Formula for Joint Probability Distribution
现在使用条件概率和链式法则,我们可以很容易地得到完整的联合分布,即给定所有其他相关事件的最终事件的概率。(注:如果不确定条件概率和链式法则,就按照这些 讲座 。它们是学习概率和贝叶斯统计的广泛资源。)从等式中,我们可以看到子节点的概率取决于它的直接父节点。注: π 表示产品标志。
使用上述公式,我们可以推导出以下模型的联合概率分布公式。
Fig. 3
因此,使用图 2 中给出的公式,可以很容易地得到上述给定网络的联合概率估计结果。
贝叶斯网络模型的真实例子
现在让我们用一个真实世界的例子来结束本教程,以便更好地理解。
Fig. 4
让, P(A)表示你早上醒来晚的事件。
P(B)表示你上学迟到的事件。
P(C)表示你被老师责骂的事件。
P(D)表示路上堵车的事件
P(E)表示你父亲每天早上登上公共汽车的事件。
P(F)表示你父亲就职的事件。
那么你在学校被骂的概率有多大呢?现在,你可以很容易地用公式找到答案。所以最后的结果变成了 P(C|B)。P(B|A,D)。P(D)。P(A)
嘿,但是等等!!!P(E)和 P(F)呢???它们也存在于模型中。请记住,两个事件,如果没有用弧线直接或间接连接到任何其他节点,则称为独立事件,一个事件的发生不会影响另一个事件的发生。我们可以从模型中有把握地预测出 P(C|F) 的值,即你因为你父亲要上任的事件而被骂的概率是 0 。
给定父节点,每个节点的概率值以称为条件概率表(CPT) 的表格形式表示。下面的例子是 CPT 的代表。
Fig. 5: Conditional Probability Table (Creator: Muhammad Nazim Razali)
贝叶斯网络在现实世界中有着巨大的应用。给定症状,贝叶斯网络可以预测特定疾病导致症状的概率。此外,通过从两个犯罪现场收集证据,贝叶斯网络可以为调查小组提供关于两个地方的罪犯是否相关的有价值的见解。
一些 MOOCs 探索贝叶斯网络的更多内容:
1.概率图形模型由斯坦福大学
2.机器学习的贝叶斯方法由国立研究型大学高等经济学院
3.贝叶斯统计:从概念到数据分析作者加州大学圣克鲁斯分校
图形绘制基础
原文:https://towardsdatascience.com/basics-of-graph-plotting-7eaadd11a8d?source=collection_archive---------21-----------------------
我们大多数数据科学家进入这个行业是因为我们热爱数据(不管这意味着什么?不,我也不知道!).创造易于阅读的情节的能力通常是事后才想到的。大多数职位描述都会提到可视化数据的能力很重要,但我从未在面试或工作中与任何人就可视化的最佳实践进行过合理的对话。鉴于有这么多坏的阴谋,这肯定不是因为我们都是这方面的专家!
花两个月的时间做一些分析,然后让你所有的利益相关者都茫然地看着你的演示,这是没有意义的。虽然创建一个非常复杂的交互式 3d 可视化 make 看起来令人印象深刻,但如果底层图形执行得不好,那么试图用一些 java 代码来改进是相当浪费时间的。有一个著名的表达涉及闪光和一只狗,我不会在这里重复。
对我来说,一个图表应该是极简的,并且在可能的情况下,不言自明。因此,我决定在博客中分享我的观点。我已经包括了我在绘制图表时考虑的一些方法。
总则
你的目标是把注意力吸引到重要的部分,而不是用不必要的杂乱分散观察者的注意力。一条太细的线可能不会引起足够的注意,而一个不必要的图例会弄乱情节,没有任何有意义的贡献。不太重要的特征可以变得更淡,这样第一眼就看不出来。颜色应该是直观的:红色代表不好,绿色代表好。一个需要反复问自己的重要问题是这个像素起了什么作用?如果你没有一个好的答案,那么删除它。
典型的图表
我的起点是 matplotlib 的标准输出,并添加了一些我经常看到的内容。数据是 1981-1990 十年间墨尔本的最低温度,单位为摄氏度,每天有一个数据点。
我们想展示什么?
在我们开始做出任何改变之前,我们需要问自己我们试图描绘的是什么?我想提请大家注意两个特点。一是强烈的季节性行为,二是每天都有很大的波动。
线条样式
先说最根本的,实际数据。不要因为是时间序列数据就假设需要用线。使用线条的主要原因是为了跟踪数据点的顺序,但我们对精确的顺序并不感兴趣,我们只是想表明有很大的波动。线的另一个问题是,大量的注意力被吸引到离群值上,因为离群值与线的长度相关联。这是我的解决方案:
我们现在有两种不同的风格,一种用于原始数据,一种用于趋势。在这种情况下,这真的很有效,因为在我们的图中还有两个我们想要引起注意的特征。粗蓝线非常清楚地显示了温度的周期性和季节性,是该图的主要焦点。每日波动由散点图显示,淡灰点不太明显。
对于趋势线,我计算了每个月的平均温度,然后将其二次插值回每日时间序列。这产生了一个更加美观的流畅的情节。
轴文本
轴标签有一些明显的问题,我认为还有一些风格上的问题可以改进:
我将所有的文本放大,并选择将颜色改为灰色,因为我希望数据成为焦点,而不是轴标签。我还认为在 python 中使用衬线字体看起来更专业。
x 轴:x 刻度标签太长,最后重叠了。一个解决方案是旋转日期,但是因为我每年只有一个刻度,所以我不需要日期或月份。给定上下文,我们还可以推断 x 轴指的是日期,而不必明确标记它。
y 轴:我还微妙地改变了界限,使顶部刻度上方和底部刻度下方的空间相等。
称赞那些发现我也把轴的宽度设为 2 而不是标准的 1 的人。非常学究气,但它会有意义的页面。
神话;传奇
您的图例有一些可用的格式选项。最重要的和第一个你应该考虑的是你需要一个吗?在一个理想的世界里,你的阴谋没有一个是显而易见的,但它并不总是可以避免的,然而它应该是你要考虑的事情列表的顶部。在这种情况下,我认为这是非常明显的,所以我认为添加图片标题是最干净的选择。
Daily temperature measurements are shown by the grey dots with the 30 day mean shown in blue.
可能的话,把图例放在图中,因为它就在附近,你不必去找它。这也使得将数字转换成幻灯片的工作变得容易多了;浮动图例会使图像尺寸变得非常大,不会给幻灯片上的文本留下太多空间。然而,也不要把图例放在图表中真正重要的部分(是的,我已经看过很多次了!!)
包围盒
我说的是包围该图并包括 x 轴和 y 轴的黑色矩形。对我来说,它切断了文本的视觉化,因此,切断了叙事,这就是它对你的观众的影响。我是一个相当新的采用者,但你可以让他们看不见!
Daily temperature measurements are shown by the grey dots with the 30 day mean shown in blue.
我还添加了水平线来标记 y 轴上的主要刻度,这样您可以更容易地读取实际值。同样,这些是非常苍白的,首先绘制出来,这样它们就不会压倒眼睛,但是当你需要它们的时候它们就在那里。
还记得我之前改变了小轴刻度的宽度吗??它们现在没有了主要的 x 轴和 y 轴,所以让它们更占主导地位比被误认为屏幕上的灰尘更有意义。
结论
花 5 分钟时间想出如何完善一个情节,抵得上花 5 个小时讨论它的意义。
密码
在github repo中给出了绘制上述完善图的代码。
独立成分分析基础
原文:https://towardsdatascience.com/basics-of-independent-component-analysis-ad14f683b49b?source=collection_archive---------14-----------------------
动机
我们一直在寻找模式,并对数据进行更深入的理解。关于这个数据集,你首先想到的是什么?
如果你的第一个想法是——“那些点看起来太好了”——那么你抓住我了。这不是一个真正的数据集,我花了比我应该产生这些点更多的时间。然而,这不是重点。
你看到了什么?从视觉角度来看,很明显有两个群体有两种线性趋势。这两个组混合在一起成为一个不可区分的点集合。
再来一个:你能把这幅杰作中的两个组件分开,并辨认出画中的人吗?
I’m not religious but this has me thinking…
同样,这对我们来说不应该是个问题。我们可以在精神上分离这两个图像,但是如果有人要求这两个分离的图像,你实际上会怎么做呢?
我们需要一个分离混合数据集的数学框架和算法。
定义
在考虑这个数学框架之前,我们先用简单的思路写出来。
- 我们有不同部分组合的数据。
- 我们想把它分离成一个更简单的表示。
- 我们希望尽可能少的混乱。
假设我们有 m 个初始点:
我们想分成 n 个部分:
我们想找到一个分离初始点的变换。这种变换最简单的形式是一个 n 乘 m 矩阵 W 。
为了确保 n 输出被分离,我们可以搜索使分量尽可能不同于正态分布的变换。
如果你上过统计学课,那么你可能听说过正态分布(钟形曲线)。所有统计学中最重要的结果之一是中心极限定理,它表明将一组独立的样本(即使来自非正态分布)相加会得到正态分布。
所有组合的不同组或图像形成通常正态分布的混合点的集合。我们希望提取尽可能个别地呈非正态分布的成分。
峭度
描述概率分布的两个常用指标是平均值和标准偏差。它们代表分布的一阶和二阶矩,通常包含了关于平均值和分布的大部分信息。它们被定义为:
我们还可以讨论分布的三阶矩,称为峰度。峰度衡量分布的偏斜程度。我们将其定义为:
正态分布的峰度为 0。如果我们将峰度最大化,我们将得到一个尽可能非正态的分布。
摘要
在本文中,我们激发了我们分离由多个来源组成的数据的自然能力。从分散的数据集到过滤的图像,这些对于我们的大脑来说很容易分离,但从算法的角度来考虑更有趣。
本着让每个组件尽可能不同的想法,我们可以开始构建一个算法。找出导致具有最大峰态分布的变换。我们可以通过使用梯度下降来更新我们当前的候选,并继续下去,直到我们将原始数据分成不同的部分。
感谢阅读!独立成分分析是一个很好的工具,也是解决一些有趣问题的切入点。我很想听听你的反馈,看看是否有人对这个话题感兴趣——我只是触及了皮毛。
经典 CNN 的基础知识
原文:https://towardsdatascience.com/basics-of-the-classic-cnn-a3dce1225add?source=collection_archive---------3-----------------------
一个经典的 CNN(卷积神经网络)是如何工作的?
Classic CNN architecture.
卷积神经网络。听起来像是生物学和数学的怪异结合,还有点 CS 的成分,但这些网络是计算机视觉和图像处理领域最有影响力的创新之一。
卷积神经网络是多层感知器(MLP)的正则化版本。它们是基于动物视觉皮层神经元的工作而开发的。
计算机对图像的可视化
Binary image visualization.
假设我们有一个 JPG 形式的彩色图像,其大小为 480 x 480。代表性的阵列将是 480×480×3。这些数字中的每一个都被赋予一个从 0 到 255 的值,该值描述了该点的像素强度。图像的 RGB 强度值由计算机可视化以进行处理。
使用 CNN 的目的:
这个想法是,你给计算机这个数字数组,它将输出描述图像属于某一类的概率的数字(猫 0.80,狗 0.15,鸟 0.05,等等)。).它的工作原理类似于我们的大脑。当我们看一张狗的图片时,如果图片有可识别的特征,如爪子或 4 条腿,我们就可以把它归类为狗。以类似的方式,计算机能够通过寻找边缘和曲线等低级特征来执行图像分类,然后通过一系列卷积层建立更抽象的概念。计算机使用在初始级别获得的低级特征来生成高级特征,如爪子或眼睛,以识别对象。
一个经典的 CNN:
经典卷积神经网络的内容:-
1.卷积层。
2.每个卷积层之后的激活操作。
3.池层,尤其是最大池层,以及基于需求的其他层。
4.最后完全连接层。
卷积运算
第一层:
1。卷积层的输入
将图像调整到最佳大小,并作为输入馈送到卷积层。
让我们把输入看作是像素值的 32×32×3 阵列
2。存在滤波器或神经元或内核,其取决于内核大小的维度覆盖输入图像的一些像素。
设滤波器的核的维数为 5x5x3。
3.内核实际上滑过输入图像,因此它将滤波器中的值与图像的原始像素值相乘(也称为计算元素级乘法)。
对乘法求和,为特定感受野生成单个数字,因此为了滑动内核,总共 784 个数字被映射到 28×28 阵列,称为特征图。
- *现在,如果我们考虑相同维度的两个内核,那么获得的第一层特征图将是(28×28×2)。
高层视角
为了便于理解,让我们取一个大小为(7x7x3)的内核。每个核都被认为是一个特征标识符,因此可以说我们的滤波器是一个曲线检测器。
- 原始图像和图像上内核的可视化。
生成的乘积值之和= 4(5030)+(20*30) = 6600(大数字)
- 现在当内核移动到图像的其他部分时。
生成的乘积值之和= 0(小数字)。
小值和大值的使用。
1.价值低很多!这是因为在图像部分没有任何东西响应曲线检测器滤镜。记住,这个卷积层的输出是一个激活图。因此,在一个滤波器卷积的简单情况下(如果该滤波器是曲线检测器),激活图将显示图像中最有可能弯曲的区域。
2.在前面的示例中,我们的 26 x 26 x 1 激活图的左上角值(26 是因为 7x7 过滤器而不是 5x5)将是 6600。这个高值意味着输入音量中可能有某种曲线导致过滤器激活。在我们的激活图中,右上角的值将是 0,因为输入体积中没有任何东西导致过滤器激活。这只是一个过滤器。
3.这只是一个过滤器,用来检测向外向右弯曲的线条。我们可以为向左弯曲的线条或直边设置其他过滤器。过滤器越多,激活图的深度就越大,我们拥有的关于输入量的信息就越多。
在图片中,我们可以看到第一个 conv 的过滤器实际可视化的一些例子。训练网络的层。尽管如此,主要论点还是一样的。第一层上的滤波器在输入图像周围进行卷积,并且当它所寻找的特定特征在输入体积中时“激活”(或计算高值)。
顺序 conv。第一层之后的层。
1.当我们穿过另一个 conv。层,第一个 conv 的输出。层成为第二个 conv 的输入。层。
2.然而,当我们谈到第二个 conv 时。层,输入是从第一层产生的激活图。因此,输入的每一层基本上都描述了原始图像中某些低级特征出现的位置。
3.现在,当你在上面应用一组滤镜时(通过第二个 conv)。层),输出将是表示更高级特征的激活。这些特征的类型可以是半圆(曲线和直边的组合)或正方形(几条直边的组合)。当你通过网络,通过更多的 conv。层,您将获得表示越来越复杂功能的激活图。
4.在网络的末端,你可能会有一些过滤器,当图像中有笔迹时会激活,当看到粉红色物体时会激活,等等。
联营业务。
最大池示例。
2x2 filters with stride = 2 (maximum value) is considered
3x3 filters with stride = 1 (maximum value) is considered
3x3 filters with stride = 2 (maximum value) is considered
全连接层。
1.这个完全连接的层的工作方式是,它查看前一层的输出(我们记得它应该代表高级功能的激活图)和类别数量 N (数字分类为 10)。
2.例如,如果程序预测某个图像是一只狗,它将在激活图中具有高值,这些激活图表示像爪子或 4 条腿等高级特征。基本上,FC 层会查看哪些高级别要素与某个特定类最相关,并具有特定的权重,这样当您计算权重与前一层之间的乘积时,就可以获得不同类的正确概率。
3.完全连接的层的输出如下[0 .1 .1 .75 0 0 0 0 0 .05],那么这表示对于数字分类,图像是 1 的概率为 10%,图像是 2 的概率为 10%,图像是 3 的概率为 75%,图像是 9 的概率为 5 %( soft max 方法)。
培训。
我们知道内核也称为特征标识符,用于识别特定的特征。而是如何用特定的权重初始化内核,或者过滤器如何知道应该有什么值。
训练的重要一步由此而来。训练过程也被称为反向传播,它被进一步分成 4 个不同的部分或过程。
向前传球
损失函数
向后传球
重量更新
向前传球:
对于训练的第一个时期或迭代,第一 conv 的初始核。层用随机值初始化。因此,在第一次迭代之后,输出将是类似于[. 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1]的内容,它不会优先考虑任何类,因为内核没有特定的权重。
损失函数:
训练涉及图像以及标签,因此数字 3 的标签将是[0 0 0 1 0 0 0 0 0 0 0 0 0 0],而第一个历元之后的输出非常不同,因此我们将计算损失( MSE —均方误差
目标是最小化损失,这是微积分中的一个优化问题。它包括尝试调整重量以减少损失。
向后传球:
它包括确定哪些重量对损失影响最大,并找到调整它们的方法,以减少损失。使用 dL/dW 计算,其中 L 是损失,W 是相应内核的权重。
权重更新:
这是使用以下等式更新内核权重的地方。
这里的学习速率由程序员选择。学习率的值越大,表示优化步长的步长越大,卷积到优化权重的时间越长。
测试。
最后,看看我们的 CNN 是否工作,我们有一套不同的图像和标签(不能在训练和测试之间双浸!)并通过 CNN 传递图像。我们将输出与地面实况进行比较,看看我们的网络是否有效!
基础知识:使用 Tensorflow 在 Anaconda 中创建虚拟环境
原文:https://towardsdatascience.com/basics-virtual-environment-in-anaconda-with-tensorflow-aecb60fb56ab?source=collection_archive---------18-----------------------
为您的机器和深度学习模型创建一个虚拟环境是保护它们的一个重要的主动步骤。这个隔离的内存空间将允许使用同一个包的不同版本。发生的更新将被严格管理和手动更新。让我们创建一个机器和深度学习虚拟 python 环境设置。
蟒蛇
如果您没有 Anaconda,请下载并安装最新版本。否则,继续更新 conda 和目前它里面的所有包。
安装 Anaconda
前往https://anaconda.com/distribution。页面中间是基于 Python 版本的安装程序选项。挑选你的毒药,安装在你喜欢的地方。
我会推荐安装 Python 3.7。Python 2.7 不再维护。已经“退休”了。
更新 Conda
康达是巨蟒之首。它是一个开源的软件包管理系统和环境管理系统,用于安装多个版本的软件包..“就像您应该更新 pip 一样,conda 也经常需要更新。当我们这样做的时候,并且对你的其他项目来说是安全的,我们将在此刻更新 Anaconda 中的所有包。
为此,打开 Anaconda Powershell 提示符。键入以下内容:conda update conda。
在某些时候,系统会提示您说是或否,以越过不可返回的点。如果你准备好了,按“y”键,让它继续。一旦完成,让我们更新所有当前安装的软件包。使用以下命令:conda update -all。
这将有相同的“是”或“否”提示。
第二步:GPU 利用率
这一步绝对是可选的。如果你有一个可以被 NVIDIA 的 cuDNN 和 CUDA 使用的 GPU,那就去用吧。这里是支持 CUDA 的 GPU 列表。
库达
CUDA 是一种简化 GPU 利用的计算和编程模型。要下载,请单击此处并为您的电脑选择合适的选项。
一旦您选择了适当的选项,正确的安装程序将会出现。
在本文中,10.2.89 版不需要任何补丁。如果您要安装的版本有修补程序,请确保在基本安装程序之后安装这些修补程序。
点击下载按钮并安装 CUDA。这将需要几分钟的时间,但是您可以使用安装程序中的默认选项。
cuDNN
cuDNN 是 CUDA 深度神经网络库的简称。它类似于最初的 CUDA,但正如其名称所示,它是用于深度神经网络的。
要下载,你需要创建一个 NVIDIA 的开发者账户。做起来很简单。一旦你创建了一个帐户,继续下载最新版本。下载文件将是一个 zip 文件夹。将它解压缩到计算机的 C:驱动器,然后将其添加到环境路径中。
环境路径
通过按 Win + R 打开“运行”窗口。要访问系统属性,您需要打开“sysdm.cpl”。
点击“确定”,然后系统属性窗口将会打开。点击“高级”标签,然后点击底部附近的环境标签按钮。在系统变量框下,有一个“新建”按钮,按一下。你可以给这个变量起任何你喜欢的名字,它的值将会是 cudnn 文件夹中 bin 文件夹的路径。
步骤 3:创建虚拟环境
要创建虚拟环境,您将使用以下命令结构:conda create-n env _ name pip python = version。因此,env_name 是您将赋予环境的名称,python=version 是您将使用的 python 版本。我们将继续创建一个名为 virtEnv 的环境,版本为 3.7。
在某个时候,系统会提示您按 y 或 n 继续创建。准备好了就按“y”键。
一旦创建了虚拟环境,我们就可以激活它了!为此,请使用命令 conda activate env_name。在我们的情况下,这将是康达激活 virtEnv。
提示符应该从(base)变为(virtEnv)或您为环境命名的任何名称。
步骤 4:安装必要的库
既然虚拟环境已经激活,我们就可以安装库了。这些库可以是项目所需的任何版本。对于这种环境,我们将安装 Tensorflow。因为我们在利用自己的 GPU 优势,所以会安装 Tensorflow 的 GPU 版本。如果您不想要那个版本,就放弃调用的'-gpu '部分。
这将安装 Tensorflow 2.0 及其所有依赖项。这可能需要一段时间。
步骤 5:检查 Tensorflow 是否已安装
我们快完成了!只差一步了。我们需要检查 Tensorflow 是否安装正确。通过在 Powershell 中键入“python”来打开解释器。当解释器打开时,它将显示您正在使用的 python 版本以及下面的> > >。那是我们将要打字的地方。
第一行我们将使用“导入张量流为 tf”来导入张量流。
接下来,我们将打印带有' print(tf。__ 版本 _ _)。如果成功,版本号将出现在下面。
如果一切正常,按 ctrl+z 退出解释器。至此,您已经准备好在新创建的虚拟环境中创建项目了!
虚拟
好吧,我们可以解决房间里的大象。还有一个不涉及 Anaconda 的选项。Python 有一个名为 virtualenv 的库,用于为 python 项目创建虚拟环境。根据您使用的 python 版本,您可能需要也可能不需要安装 virtualenv 库。如果您正在使用 Python 2,那么您将需要使用 pip 来安装 virtualenv,然后创建一个新目录。在 Python 3 中,venv 模块是一个标准库,您只需要创建并激活环境。
虚拟环境管理
现在我们有了一个虚拟环境,您可能想要创建更多。在这一点上,它可以成为一个集群…乱七八糟。以下是一些有助于管理虚拟环境和保持头脑清醒的有用命令:
虚拟环境命令
查看您电脑上的环境:(两者做同样的事情)
- 康达信息-envs
- 康达环境列表
查看某环境下安装的软件包列表:
- 当前未激活的环境 : conda list -n env_name
- 当前激活的环境 : conda 列表
查看是否安装了某个包 : (env_name 是您的环境名,package_name 是您查询的包。)
- conda list -n 环境名称包名称
启动环境:
- conda 激活环境名称
停止环境:
- 康达停用
移除环境:
- conda 环境移除-n 环境名称
既然您的工具箱中已经有了虚拟环境技能,现在您可以创建许多不同的项目。都是相互独立的包版本!甚至是那些可以利用神经网络的,你可以在基础:神经网络帖子中了解到。
在我们重新学习之前,
篮球分析:预测获胜份额
原文:https://towardsdatascience.com/basketball-analytics-predicting-win-shares-7c155651e7cc?source=collection_archive---------4-----------------------
利用机器学习预测 NBA 顶级球员的个人胜率
最近,达里尔·莫雷声称勒布朗詹姆斯是有史以来最伟大的篮球运动员。很明显,差得远了。莫雷是 NBA 休斯顿火箭队的现任总经理。对于所有的棒球迷来说,莫雷是篮球界的比利·比恩。对于所有电影爱好者来说,莫雷就像是布拉德·皮特在《摇钱树》中扮演的篮球运动员。如果你没有理解前面两句话,那么你可能需要做一些研究。简而言之,莫雷是一个巨大的分析家伙。所以,当他谈论勒布朗·詹姆斯的成就时,这意味着在篮球分析学,或莫雷球,术语,勒布朗是有史以来最伟大的(试着告诉跳过贝勒斯)。
我从莫雷的言论中得出的最大问题是:他如何衡量哪个球员比下一个更好?是成功吗?影响?效率?(莫雷爱效率胜过比利·比恩爱上垒百分比)。
今天,有很多新的篮球指标被世界各地的球迷和分析师用来比较和衡量球员。例如,有球员效率评级(PER) ,它考虑了成绩,如投篮命中率、罚球、三分球、助攻、篮板、盖帽和抢断,以及负面结果,如投篮不中、失误和个人犯规。
一些先进的篮球指标,如 PER,可以很好地衡量球员在篮球比赛中的效率。但这是否告诉我们,这名球员将为他们的球队带来成功?也许吧。但是,一个玩家被视为成功的唯一方式就是获胜。
赢得股份是一个很好的开始,可以展示一个玩家给他们的团队带来了多大的成功。根据 Basketball-Reference 的说法,win shares 是一个衡量一名球员在整个赛季中为他的球队赢得比赛次数的指标。从这个角度来看,卡里姆·阿布杜尔·贾巴尔不仅是 win 份额的单赛季领导者,拥有 25.4 个 win 份额,而且是 win 份额的职业生涯领导者,拥有 273.4 个 win 份额。所以,我相信你明白这个衡量标准可能是一个很好的指标,来衡量一个球员对球队的贡献有多大。
注:这篇文章使用的所有代码都可以在 GitHub 上找到,整理在这个笔记本上。
分析
目的:我们能使用其他篮球指标预测 NBA 球员的个人胜率吗?
本次分析使用的数据来自 2016–17 和 2017–2018 NBA 赛季,使用篮球参考。本质上,我使用 2016-2017 NBA 赛季的数据来创建我们的模型,并从最近一个赛季的统计数据来预测获胜份额。我执行了一个监督回归机器学习分析:
- 受监督的:该数据包含 win 份额和所有其他篮球指标,用于训练和测试模型
- 回归:赢股是一个连续变量
今天,有很多新的篮球指标被世界各地的球迷和分析家用来比较和衡量球员。为了预测获胜份额,我混合使用了基本和高级 NBA 统计数据:
探索性数据分析
- win 股份的分配最初是什么样子的?
在继续分析之前,我使用了基本的 EDA 来看看我们的数据能告诉我们什么。首先,我快速浏览了一下 win 份额的分布情况:
马上,我们看到 win 份额的分布向右倾斜。2016-2017 赛季期间,大多数 NBA 球员的胜率不到 5%。这是有意义的,因为只有少数几个被选中的人,大部分是 NBA 全明星,会有很高的胜率。例如,2016-2017 NBA 赛季的 win shares 领先者是詹姆斯·哈登,MVP 亚军,拥有 15 份 win shares。所以,拥有高份额是一种精英身份。
从分布中提取的奇怪数据是 0 win 份额的玩家数量。经过进一步的分析,我发现有很多玩家几乎不玩游戏。虽然这些球员都在 NBA 的名单上,但这并不意味着他们不会对球队和他们自己的个人数据产生重大影响。因此,我更新了数据,只包括那些至少打了 30 场比赛,平均每场比赛至少打 25 分钟的球员。清除数据后,win 份额的分布如下:
现在 0 赢份额的玩家少了很多!win 份额的分布仍然是右偏的,但看起来更接近正态分布。
- 我选择的所有特征都是赢得份额的良好预测因素吗?
我使用皮尔森相关系数分析了这个问题,皮尔森相关系数衡量特征和目标(赢得份额)之间的线性相关性。它的值介于-1 和+1 之间,其中接近-1 的值表示负强关系,接近+1 的值表示正强关系:
这一发现令人惊讶!在我最初选择用来预测胜率的 13 个篮球指标中,有 4 个没有足够强的相关性(强=大于 0.5 &小于-0.5)。因此,我从我的模型中排除了这些指标。
我吃惊地看到 3 个百分点(3P%)不仅有微弱的相关性,而且还有负相关性。在今天的 NBA,几乎每个球队和球员都非常依赖 3P,所以我认为 3P%在分析中会起到重要作用。另一个有趣的发现是玩的游戏(G)和赢的份额之间的弱关系。有人会认为,玩家参与的游戏越多,他们赢得的份额就越高。然而,仅仅因为一个玩家参与了一个游戏,并不意味着他们会成功。助攻数(AST)是另一个我认为与 win 份额有密切关系的指标。
- 其余的特征是否高度相关?
对于分析的下一部分,我想看看要素之间是否有很强的相关性,或者多重共线性。多重共线性通常发生在两个或更多预测变量之间高度相关的时候。请记住,与 win shares 密切相关的功能是好的,但与其他功能密切相关的功能可能没有那么大帮助。这甚至会使我们更难解释我们将要创建的模型。
根据上面的配对图,我发现了这些特性之间的一些问题:
- VORP vs BPM: 有很强的正相关关系(相关系数 0.98)。Box Plus Minus (BPM) 是球员在球场上每 100 次持球对联盟平均水平的贡献。替代球员(VORP)的价值采用 BPM,并将其转化为对团队的贡献。为了计算 VORP,你需要使用 BPM。因此,它们高度相关。
- 投篮命中率指标:我们在分析中还剩下三个投篮命中率指标。现场目标百分比(FG%)是完成的现场目标与尝试的现场目标的比率。有效现场目标百分比(eFG%)调整现场目标百分比,以说明三分现场目标算三分,而现场目标只算两分。真实投篮命中率(TS%)通过计算 2 分和 3 分的投篮命中率和罚球来衡量球员的投篮效率。我觉得这些指标密切相关(TS%和 eFG%的相关性为 0.90)。因此,我决定只使用 TS%,因为它与 win 份额的相关性最高。
在研究了这些数据之后,我留下了以下篮球指标作为创建模型的特征:
模型选择和测试
由于这是一个监督回归机器学习分析,我创建了三个回归模型:
- 线性回归
- 支持向量回归
- k 近邻回归
让测试集包含 25%的数据(其余的数据用于训练模型),下面是模型的结果:
这些模型的明显赢家是:线性回归。线性回归模型具有较低的均方误差(越低越好)、均方误差(越低越好)和较高的方差得分(越高越好)。这并不是说其他两个模型,支持向量和 k 近邻回归,不应该被忽略!他们仍然有非常令人印象深刻的结果,只是没有线性回归模型那么强。
预言
如上所述,我使用了 2017-2018 NBA 赛季的所有特征,通过我们的模型来预测获胜份额:
Win Share Predictions Using Linear Regression Model
根据线性回归模型的预测,勒布朗詹姆斯名列榜首!该模型预测他以 14.81 的胜利份额领先 NBA。然而,在现实中,勒布朗(14 胜)排在 2017-2018 赛季 NBA MVP 詹姆斯·哈登(15.4 胜)之后,后者在预测中排名第二。不错的预测!卡尔安东尼唐斯和安东尼·戴维斯在线性回归预测和最近的 NBA 赛季中分别排名第三和第四。
Win Share Predictions Using Support Vector Regression Model
支持向量回归模型有一些不寻常的结果。根据这个模型的预测,勒布朗(15.5 胜)再次名列榜首,哈登紧随其后(15.4 胜)。最令人兴奋的结果是,该模型准确地预测了哈登的获胜份额!他以 15.4 胜份额领跑 2017–2018 NBA 赛季,与预测值相同。安德烈·德拉蒙德在使用线性回归模型预测的 win 份额中未进入前 10 名,但在使用支持向量回归模型预测的 win 份额中排名第 3。唐斯和戴维斯都跌出了预测名单,斯蒂芬·库里和凯文·杜兰特甚至都没有进入前十名。
Win Share Predictions Using k-Nearest Neighbors Regression Model
使用 k-最近邻的 win 份额预测比以前模型的预测少得多。对于这个模型,哈登预测的 win 份额最高,仅为 12.3 win 份额。预测值的另一个奇怪的结果是,勒布朗,拉塞尔·维斯特布鲁克,扬尼斯·阿德托昆博和戴维斯并列 12.24 胜份额!
结论
以下是我从这个分析中学到的一些东西:
- 使用平均绝对误差作为衡量标准,我们创建的一个模型能够预测 NBA 球员的个人胜率,误差在 0.761 分以内。
- 替代球员(VORP)的价值是预测获胜份额的最重要因素。3.0%(3P)、比赛场次(G)和助攻(AST)与赢球份额没有太大关系。
- 勒布朗詹姆斯仍然是国王!不完全是,但是他已经 33 岁了,还在生产!
尽管最佳模型在预测 NBA 球员的获胜份额方面做得很好,但我在这个过程中了解到的一些问题可能会在未来的项目中帮助我:
- 更多的数据可能会有所帮助。为了训练模型,我只使用了 2016-17 赛季的数据。我可以使用过去几个赛季的数据,但我希望这些预测是真实的。NBA 已经不是几年前的样子了。就像我在分析中所说的,三分球已经占据了上风。更多的球队是靠投长传。事实上,上个赛季的半决赛球队——金州勇士队、克利夫兰骑士队、休斯顿火箭队和波士顿凯尔特人队——在大多数三分球尝试中都处于领先地位。最初,我害怕包括以前赛季的数据,因为它不会准确预测今天的 NBA。然而,这实际上是有帮助的,因为三分球并没有我想象的那么重要。
- Stat padding 不一定代表成功。拉塞尔·维斯特布鲁克是三双、的王者,当一名球员在三个不同的指标中取得两位数的总成绩时。事实上,他前两个赛季场均三双!在我使用模型做出的所有 win shares 预测中,威斯布鲁克都是前 10 名,但在过去的赛季中,他甚至都不是前 10 名。由于他的统计数据如此之好,他的获胜份额预测比他们应该的要高得多。
- 赢得份额可能不是衡量个人成功的最佳指标。篮球是一项团队运动,衡量个人表现并不容易。詹姆斯·哈登因为他惊人的进攻表现而获得 MVP,但是他的防守呢?不存在的。他的队友帮助他弥补了许多防守上的不足。但是如果他们没有呢?或者如果防御策略不合适呢?哈登仍然会产生很大的进攻数据,但如果他的球队缺乏防守,他的胜率就会下降。
总的来说,我了解到,是的,人们可以使用篮球指标来预测胜率。然而,赢球份额可能不是衡量个人成功的一个很好的标准,因为在篮球比赛中,赢球需要整个团队,而不仅仅是一个球员。除非你的勒布朗。加油湖人队!!!
请随时给予反馈或建设性的批评!:)还有,关注我的个人 博客 或者推特@ datao sanch。这篇文章使用的所有代码都可以在 GitHub 上找到,整理在这个笔记本上。
批量、小型批量和随机梯度下降
原文:https://towardsdatascience.com/batch-mini-batch-stochastic-gradient-descent-7a62ecba642a?source=collection_archive---------0-----------------------
在这个深度学习的时代,机器已经超过了人类的智力,通过看例子来了解这些机器是如何学习的是很有趣的。当我们说我们正在训练模型时,是幕后的梯度下降在训练它。
Machine Learning behind the scenes (Source: https://me.me/i/machine-learning-gradient-descent-machine-learning-machine-learning-behind-the-ea8fe9fc64054eda89232d7ffc9ba60e)
因此,让我们更深入地研究深度学习模型,看看梯度下降及其兄弟姐妹。
梯度下降
这是维基百科对梯度下降的说法
梯度下降是一种一阶 迭代 优化 算法求函数的最小值
这似乎有点复杂,所以让我们分解一下。
梯度下降的目标是最小化给定的函数,在我们的情况下,是神经网络的损失函数。为了实现这个目标,它迭代地执行两个步骤。
Source: https://hackernoon.com/the-reason-behind-moving-in-the-direction-opposite-to-the-gradient-f9566b95370b
- 计算斜率(梯度),即函数在当前点的一阶导数
- 从当前点向坡度增加的相反方向移动计算出的量
Gradient descent (Source: https://medium.com/@divakar_239/stochastic-vs-batch-gradient-descent-8820568eada1)
因此,想法是通过神经网络的隐藏层传递训练集,然后通过使用来自训练数据集的训练样本计算梯度来更新层的参数。
这样想吧。假设一个人在山谷的顶端,他想到达谷底。所以他走下斜坡。他根据当前位置决定下一个位置,当他到达他的目标山谷底部时停下来。
有不同的方法可以让那个人(重物)走下斜坡。让我们一个一个的来看看。
批量梯度下降
在批量梯度下降中,所有的训练数据都被考虑在内以采取一个单独的步骤。我们取所有训练样本梯度的平均值,然后使用该平均梯度来更新我们的参数。这只是一个时代中梯度下降的一步。
批量梯度下降对于凸的或相对平滑的误差流形是很好的。在这种情况下,我们有点直接走向最优解。
Cost vs Epochs (Source: https://www.bogotobogo.com/python/scikit-learn/scikit-learn_batch-gradient-descent-versus-stochastic-gradient-descent.php)
成本与时期的关系图也非常平滑,因为我们对单个步骤的训练数据的所有梯度进行了平均。随着时间的推移,成本不断降低。
随机梯度下降
在批量梯度下降中,我们考虑梯度下降的每一步的所有例子。但是如果我们的数据集非常庞大呢?深度学习模型渴望数据。数据越多,模型越有可能是好的。假设我们的数据集有 500 万个示例,那么仅仅一步,模型就必须计算所有 500 万个示例的梯度。这似乎不是一个有效的方法。为了解决这个问题,我们有随机梯度下降。在随机梯度下降(SGD)中,我们一次只考虑一个例子来进行单步。我们在 SGD 的一个时期中执行以下步骤:
- 举个例子
- 把它输入神经网络
- 计算它的梯度
- 使用我们在步骤 3 中计算的梯度来更新权重
- 对训练数据集中的所有示例重复步骤 1-4
因为我们一次只考虑一个例子,成本会随着训练例子的变化而波动,而且不一定会降低。但是长期来看,你会看到成本随着波动而降低。
Cost vs Epochs in SGD (Source: https://adventuresinmachinelearning.com/stochastic-gradient-descent/)
Source: https://towardsdatascience.com/optimizers-be-deeps-appetizers-511f3706aa67
还因为成本波动很大,它永远不会达到最小值,但会一直围绕着它波动。
SGD 可以用于更大的数据集。当数据集很大时,它收敛得更快,因为它会更频繁地更新参数。
小批量梯度下降
我们已经看到批次梯度下降。我们也看到了随机梯度下降。批量梯度下降可用于更平滑的曲线。当数据集很大时,可以使用 SGD。批量梯度下降直接收敛到最小值。对于较大的数据集,SGD 收敛更快。但是,因为在 SGD 中我们一次只使用一个例子,所以我们不能在它上面实现矢量化实现。这可能会降低计算速度。为了解决这个问题,使用了批量梯度下降和 SGD 的混合。
我们既不一次使用所有的数据集,也不一次使用一个例子。我们使用少于实际数据集的一批固定数量的训练样本,称之为小批。这样做有助于我们实现我们看到的前两种变体的优点。因此,在创建了固定大小的小批量后,我们在一个时期内执行以下步骤:
- 挑选一个小批量
- 把它输入神经网络
- 计算小批量的平均梯度
- 使用我们在步骤 3 中计算的平均梯度来更新权重
- 对我们创建的小批量重复步骤 1-4
就像 SGD 一样,小批量梯度下降中各时期的平均成本会波动,因为我们一次对少量样本进行平均。
Cost vs no of mini-batch (Source: https://stats.stackexchange.com/questions/310734/why-is-the-mini-batch-gradient-descents-cost-function-graph-noisy)
因此,当我们使用小批量梯度下降时,我们会频繁更新我们的参数,并且我们可以使用矢量化实现来加快计算速度。
结论
就像这个世界上的其他事物一样,我们看到的所有三种变体都有其优点和缺点。这并不是说一个变体经常被使用。根据情况和问题的背景,每个变体都被统一使用。
有问题吗?需要帮助吗?联系我!
Github
个人网站
领英
电子邮件:sushantpatrikarml@gmail.com
用 Pytorch 实现神经网络的批量归一化和丢失
原文:https://towardsdatascience.com/batch-normalization-and-dropout-in-neural-networks-explained-with-pytorch-47d7a8459bcd?source=collection_archive---------1-----------------------
Photo by Wesley Caribe on Unsplash
在本文中,我们将讨论为什么我们需要深度神经网络中的批处理规范化和剔除,然后在标准数据集上使用 Pytorch 进行实验,以查看批处理规范化和剔除的效果。本文基于我对 PadhAI 深度学习讲座的理解。
引用注:本文内容和结构基于四分之一实验室深度学习讲座——帕德海 。
为什么要标准化输入?
在讨论批处理规范化之前,我们将了解为什么规范化输入会加快神经网络的训练。
考虑这样一种情况,我们将具有特征 x_1 和 x_2 的 2D 数据输入神经网络。这些特征之一 x_1 具有从-200 到 200 的较宽范围,而另一个特征 x_2 具有从-10 到 10 的较窄范围。
Before Normalization
一旦我们将数据标准化,两个特征的数据分布集中在一个区域,即从-2 到 2。传播看起来像这样,
After Normalization
让我们讨论一下为什么规范化输入会有帮助?
在对输入进行归一化之前,与这些输入相关联的权重会有很大变化,因为输入要素存在于从-200 到 200 以及从-2 到 2 的不同范围内。为了适应特征之间的这种范围差异,一些权重必须较大,而一些权重必须较小。如果我们具有更大的权重,那么与反向传播相关联的更新也将很大,反之亦然。由于输入权重的这种不均匀分布,学习算法在找到全局最小值之前一直在平台区域振荡。
为了避免学习算法花费大量时间在平台上振荡,我们对输入特征进行归一化,使得所有特征都在相同的尺度上。因为我们的输入是在相同的尺度上,所以与它们相关联的权重也将是在相同的尺度上。从而帮助网络更快地训练。
批量标准化
我们已经对输入进行了规范化,但是隐藏的代表呢?
通过对输入进行归一化,我们能够将所有的输入特征置于相同的尺度上。在神经网络中,我们需要计算第一层 a₁₁.的第一个神经元的预激活我们知道预激活只不过是输入加上偏差的加权和。换句话说,它是权重矩阵 W₁的第一行和输入矩阵 X 加上偏差 b₁₁.的点积
在每一层“I”上预激活的数学方程由下式给出:
每一层的激活等于将激活函数应用于该层的预激活的输出。在每一层“I”上激活的数学方程由下式给出,
类似地,需要计算网络中存在的“n”个隐藏层的激活值。激活值将作为网络中下一个隐藏层的输入。因此,不管我们对输入做了什么,不管我们是否对它们进行了归一化,激活值都会随着我们基于与相应神经元相关联的权重对网络越来越深入而发生很大变化。
为了使所有的激活值达到相同的尺度,我们对激活值进行了归一化,这样隐藏的表示就不会发生剧烈的变化,同时也有助于我们提高训练速度。
W 为什么叫批量规范化?
因为我们计算的是单个批次的平均值和标准差,而不是整个数据。批量标准化在网络中的每个隐藏神经元上单独完成。
学习γγ和ββ
由于我们正在规范网络中的所有激活,我们是否正在实施一些可能会降低网络性能的约束?
为了保持隐藏神经网络的代表性,批处理规范化引入了两个额外的参数 Gamma 和 Beta。一旦我们规范化了激活,我们需要再执行一个步骤来获得最终的激活值,它可以作为另一个层的输入。
参数γ和β与网络的其他参数一起被学习。如果γ(γ)等于平均值(μ),β(β)等于标准偏差(σ),则激活 h_final 等于 h_norm,从而保持网络的代表能力。
在 Colab 中运行此笔记本
文章中讨论的所有代码都在我的 GitHub 上。你可以通过谷歌虚拟机上运行的 Colab 在 Github 上直接打开我的 Jupyter 笔记本,用任何设置打开 code 笔记本。如果您只想快速打开笔记本并按照本教程进行操作,请单击此处的。
[## niranjankumar-c/deep learning-PadhAI
来自 pad hai-Niranjankumar-c/deep learning-pad hai 的深度学习课程相关的所有代码文件
github.com](https://github.com/Niranjankumar-c/DeepLearning-PadhAI/tree/master/DeepLearning_Materials/7_BatchNormalization)
使用 Pytorch 进行批量标准化
为了了解批量标准化是如何工作的,我们将使用 Pytorch 构建一个神经网络,并在 MNIST 数据集上进行测试。
批量标准化— 1D
在本节中,我们将建立一个完全连接的神经网络(DNN)来分类 MNIST 数据,而不是使用 CNN。使用 DNN 的主要目的是解释在 1D 输入(如数组)的情况下批处理规范化是如何工作的。在将大小为 28x28 的 MNIST 图像提供给网络之前,我们将它们展平成大小为 784 的一维输入数组。
我们将创建两个深度神经网络,具有三个完全连接的线性层,并在它们之间交替重新激活。在具有批处理规范化的网络的情况下,我们将在 ReLU 之前应用批处理规范化,如原始论文中所提供的。由于我们的输入是一个 1D 数组,我们将使用 Pytorch nn 模块中的BatchNorm1d
类。
import torch.nn as nn
nn.BatchNorm1d(48) #48 corresponds to the number of input features it is getting from the previous layer.
为了更好地了解批处理规范化如何帮助网络更快地收敛,我们将在训练阶段查看网络中多个隐藏层的值分布。
为了保持一致,我们将绘制两个网络中第二个线性图层的输出,并比较该图层的输出在网络中的分布。结果看起来像这样:
The first row indicates first epoch and second row for second epoch
从图表中,我们可以得出结论,在每个时段内,没有批量归一化的值的分布在输入的迭代之间发生了显著变化,这意味着没有批量归一化的网络中的后续层看到了输入数据的变化分布。但是批量标准化模型的值分布的变化似乎可以忽略不计。
此外,我们可以看到,由于协方差移动,即每批输入的隐藏值移动,批量标准化网络的损耗比正常网络降低得更快。这有助于网络更快地收敛并减少训练时间。
批量标准化— 2D
在上一节中,我们已经看到了如何为以 1D 数组作为输入的前馈神经网络编写线性层之间的批量规范化。在本节中,我们将从语法的角度讨论如何实现卷积神经网络的批量规范化。
我们将采用相同的 MNIST 数据图像,并编写一个实现批量标准化的网络。该批 RGB 图像有四个维度——batch _ sizex通道 x 高度 x 宽度。在图像的情况下,我们对每个通道的批次进行标准化。类别BatchNorm2d
对 4D 输入(带有额外通道维度的小型 2D 输入)应用批量标准化。
类BatchNorm2d
将它从前一层的输出中接收的通道数作为参数。
拒绝传统社会的人
在文章的这一部分,我们将讨论神经网络中的丢失概念,特别是它如何帮助减少过拟合和泛化错误。之后,我们将使用 Pytorch 实现一个有和没有丢失的神经网络,看看丢失如何影响网络的性能。
放弃是一种正则化技术,它随机“放弃”或“停用”神经网络中的少数神经元,以避免过拟合问题。
辍学的想法
用数据上的大参数训练一个深度神经网络可能导致过度拟合。能否在同一个数据集上训练多个不同配置的神经网络,取这些预测的平均值?。
但创建一个具有不同架构的神经网络集合并训练它们在实践中是不可行的。辍学去救援。
丢弃在每个训练步骤中随机地去激活神经元,而不是在原始网络上训练数据,我们在具有丢弃节点的网络上训练数据。在训练步骤的下一次迭代中,由于其概率性行为,被丢弃去激活的隐藏神经元发生变化。以这种方式,通过应用 dropout,即…在训练期间随机停用某些单个节点,我们可以模拟具有不同架构的神经网络的整体。
培训时辍学
在每次训练迭代中,网络中的每个节点都与概率 p 相关联,是保留在网络中还是以概率 1-p 将其停用(退出)网络。这意味着与节点相关联的权重仅更新了 p 次,因为节点在训练期间仅活动 p 次。
测试时掉线
在测试期间,我们考虑所有激活都存在的原始神经网络,并通过值 p 缩放每个节点的输出。
使用 Pytorch 辍学
为了直观地显示 dropout 如何减少神经网络的过度拟合,我们将使用 Pytorch torch.unsqueeze
生成一个简单的随机数据点。遗漏的效用在可能过度拟合的自定义数据上表现得最为明显。
一旦我们生成了数据,我们可以使用如下所示的matplotlib
散点图来可视化张量。
为了显示过度拟合,我们将训练两个网络——一个没有辍学,另一个有辍学。没有丢失的网络具有 3 个完全连接的隐藏层,ReLU 作为隐藏层的激活函数,而有丢失的网络也具有类似的架构,但是在第一和第二线性层之后应用了丢失。
在 Pytorch 中,我们可以使用torch.nn
模块申请退学。
import torch.nn as nn
nn.Dropout(0.5) #apply dropout in a neural network
在本例中,我在第一个线性图层后使用了 0.5 的漏失分数,在第二个线性图层后使用了 0.2 的漏失分数。一旦我们训练了两个不同的模型,即…一个没有辍学,另一个有辍学,并绘制测试结果,它看起来像这样:
从上面的图表中,我们可以得出结论,随着我们增加历元的数量,没有丢失的模型正在过度拟合数据。无漏失模型是学习与数据相关的噪声,而不是对数据进行归纳。我们可以看到,与没有丢弃的模型相关联的损耗随着时段数量的增加而增加,这与具有丢弃的模型相关联的损耗不同。
[## niranjankumar-c/deep learning-PadhAI
来自 pad hai-Niranjankumar-c/deep learning-pad hai 的深度学习课程相关的所有代码文件
github.com](https://github.com/Niranjankumar-c/DeepLearning-PadhAI/tree/master/DeepLearning_Materials/7_BatchNormalization)
继续学习
如果你想用 Keras & Tensorflow 2.0(Python 或者 R)学习更多关于人工神经网络的知识。查看来自 Starttechacademy 的 Abhishek 和 Pukhraj 的人工神经网络。他们以一种简单化的方式解释了深度学习的基础。
结论
在本文中,我们已经讨论了为什么我们需要批量归一化,然后我们继续使用 MNIST 数据集来可视化批量归一化对隐藏层输出的影响。在此之后,我们讨论了辍学的工作,它防止数据过拟合的问题。最后,我们可视化了两个网络在有丢包和无丢包情况下的性能,以观察丢包的影响。
推荐阅读
[## 利用 Pytorch 神经网络模块构建前馈神经网络
前馈神经网络也称为多层神经元网络(MLN)。这些模型网络是…
www.marktechpost.com](https://www.marktechpost.com/2019/06/30/building-a-feedforward-neural-network-using-pytorch-nn-module/) [## 用 Pytorch 可视化卷积神经网络
可视化 CNN 过滤器并对输入进行遮挡实验
towardsdatascience.com](/visualizing-convolution-neural-networks-using-pytorch-3dfa8443e74e)
如果你在实现我的 GitHub 库中的代码时遇到任何问题,请随时通过 LinkedIn 或 twitter 联系我。
直到下次和平:)
NK。
免责声明 —这篇文章中可能有一些相关资源的附属链接。你可以以尽可能低的价格购买捆绑包。如果你购买这门课程,我会收到一小笔佣金。
BatchNormalization 不是一个规范!
原文:https://towardsdatascience.com/batchnormalization-is-not-a-norm-cebfd921dadd?source=collection_archive---------13-----------------------
质疑深层神经网络中的基本元素
最近几年,深度神经网络在多个领域,特别是视觉和文本领域,广泛地改善了艺术状态。随着支持深度神经网络的基础设施的进步,研究转向通过使网络更宽更深并提高准确性来最大限度地利用可用硬件。深度神经网络的一个关键方面是批量标准化,它使得在不影响训练速度的情况下更深入变得可行。这使得 BatchNorm 成为 CNN 的重要组成部分。在用于对象识别的大多数当前技术状态的模型中,在网络架构内的卷积层之后有批处理层。但是批量规范化有多重要呢?我们需要对执行的每个卷积进行批量归一化吗?在本文中,我们将尝试回答其中的一些问题。
正常化
归一化是一种数据准备技术,用于确保数据一致且具有统一的尺度。在图像中,常用的数据准备技术包括像素归一化和图像归一化。
- 像素标准化:这是通过将每个像素除以 255 来实现的,因此它们在[0,1]的范围内
- 图像标准化:这将改变像素强度的范围,以便数据集中的每个图像都利用整个范围的像素值。这通常被称为直方图拉伸或对比度拉伸。从下图可以很容易理解——
Source: Nuruzzaman Faruqui
上述技术有助于在训练开始前使图像正常化。一旦我们对图像进行卷积,就没有驱动力来限制尺度变化并保持一致。这就需要在每次卷积运算后使用另一种归一化技术。这时,批处理规范化就介入了。它有助于减少内部协变量的变化。
通俗地说,协变量偏移指的是数据集不同部分的不同特征分布。当在网络层内观察到由于激活的分布而导致的相同差异被称为内部协方差偏移。使用 BatchNorm,我们添加了一个归一化步骤,该步骤固定了层输入的均值和方差,通过降低梯度对参数或其初始值比例的依赖性,有助于加快收敛并改善通过网络的梯度流。
在其发明之后,批处理规范化已经在 CNN 中被广泛接受。不过,最近有人声称 BN 在两种情况下表现不佳——批量非常小和 RNN 中的重复连接。除此之外,BN 仍然比其他技术更受青睐,因为它易于管理,并且可以跨所有流行的框架使用。
这在很大程度上证明了在网络架构中使用 BN 的合理性,但是没有研究讨论应该多频繁地添加一个 BN。如果我们看看现有的网络,一个 BN 是在一个 3x3 卷积后添加的。让我们通过一个实验来检验这个理论。
在我的上一篇文章— Is ReLU ReLUvant 中,我通过进行一个在网络内随机丢弃 ReLU 层并测试准确性的小实验来检查 ReLU 的用法。结果是混杂的——当网络中 10%到 20%的总 ReLUs 被丢弃时,达到了最好的准确性。尽管从那个实验中得出任何结论仍有待商榷,但它确实激励我进行了一个类似的批量标准化实验。
实验
让我们从具有完全预激活的 ResNet 块的 ResNet1⁸模型开始。在这个实验中,我们将随机从 100%开始丢弃一些 BN 层,在每个后续实验中丢弃 10%,保持所有其他参数一致。
在这个实验中,我们将使用 CIFAR10 数据集
超参数
BATCH_SIZE = 512
MOMENTUM = 0.9
WEIGHT_DECAY = 5e-4
LEARNING_RATE = 0.4
EPOCHS = 24
ReLUPercent =100
图像增强
Height and Width shift range = 0.15625,
Rotation range = 12
Random LR Flip
【计算机】优化程序
使用动量为 0.9、重量衰减为 5e-4 的 SGD。一个周期的学习率策略,在第 5 个时期具有 0.4 的最大 LR,并向后面的时期逐渐下降。
体系结构
该模型有 4 个 ResNet 块。与传统的 ResNet1⁸不同,在 ResNet 块的末尾,我们连接输入和残差路径,然后进行逐点卷积,以过滤前面获取的信息。
这个模型有 190 亿层。
基准
在 CIFAR10 数据集上,该模型在 Google Colab 上的 24 个历元中给出了约 88%的验证准确率。该模型有大约 27M 个参数。
培养
Plot 1: a)Training Accuracy Curve, b) Validation Accuracy Curve
结果
Table1: Accuracy Comparision
令人惊讶的是,当 50%的 BN 层被随机丢弃时,获得了最佳的验证准确度。此外,在这种情况下,训练精度稍低,因此,模型更加正则化。对于一个卷积,我们有一个 BN 时的精度比只有一半 BN 层时的精度低 1.03%。令人惊讶的是,当我们仅使用总 BN 的 20%时,最佳精度仍然比使用所有 BN 层时更好。
Plot 2: Max Validation Accuracy
有了这些结果,我们可以部分回答我们的问题
在一个网络中,我们需要一个 BN 层吗?
是的。如果没有 BN,模型精度会大幅下降。所以我们确实需要一些标准化技术。
在每个卷积之后盲目地添加一个 BN 是构建 CNN 架构的正确方式吗?
大概不会!
还有更好的办法吗?
肯定是的!
如何决定是否需要添加 BN?
网格搜索可以是一种方式,但我想不出任何其他最优方式来决定是否在卷积后添加 BN。虽然从直觉上来说,我们可能需要避免在模型末尾添加 BN 层,以便预测层可以看到更大范围的值。
虽然我们仍然不知道卷积层是否具有 BN 的适当方法,但希望这确实有助于我们理解,在设计深度神经网络时,仍然需要质疑非常基本的元素的使用。
实验可以在这个 Colab 笔记本里找到。
感谢您的阅读!请在评论中告诉我你的想法。再次感谢,继续学习!
[1]:何、、张、向宇、任、、孙、简。(2016).用于图像识别的深度残差学习。770–778.10.1109/cvpr . 2016.90 .
【2】:克日涅夫斯基,亚历克斯。(2012).从微小图像中学习多层特征。多伦多大学。
云计算之战
原文:https://towardsdatascience.com/battle-of-cloud-computing-f52c2840986f?source=collection_archive---------30-----------------------
简介:
云计算、混合云平台、数据货币化和深度学习只是当今 2.0 技术变革中的几个花哨的热门词汇。一方面,企业正在应对数据货币化、自动化和降低成本的挑战。另一方面,他们努力定义一个清晰的战略,并确定合适的云平台,将现有的数 Pb 数据和组织模式转移到其中,而不必担心最机密和最重要文件的安全性,同时始终坚持适当的合规性。较小的组织和高速增长的初创公司正面临着可扩展性和不断增加的房地产费用的挑战,以管理他们的内部数据中心。
优化智能数据、计算密集型业务分析、自动化、安全性和监控、业务流程、通信、数据整理、可扩展性和合规性是每个企业最迫切的需求和关注点。为了确保这些需求得到满足,公司必须部署所需的系统和程序来满足上述所有领域的需求。为了实现完美的实施,他们必须雇佣专家资源,购买设备和软件,确保适当的维护,并满足容纳所述设备的房地产要求。所有这些需求都会给企业带来巨大的成本,因此越来越多的公司选择将某些任务指定给云来减轻这一负担,因为这在财务上是有利的。必须根据每个企业的愿望和要求选择一个云平台,并且必须与特定实体的愿景和目标保持一致。在许多情况下,企业选择多个云提供商和混合云平台来确保满足所有需求。
以美国电话电报公司和微软为例。这两家公司价值 20 亿美元的交易,旨在将技术和最新的应用程序转移到云上,这受到了美国电话电报公司数字愿景的影响。由于微软是美国电话电报公司的长期合作伙伴,Azure 产品最符合美国电话电报公司的通信、业务流程和安全要求。这些,再加上微软在数字化之旅中创建和再造企业的能力,是美国电话电报公司选择微软的主要原因。尽管如此,Azure 作为产品和基础设施的美丽在其中扮演了重要角色。这一点非常明显,因为微软在云行业的市场份额不断增长(截至 6 月 30 日的 2019 财年收入为 380 亿美元),并增加了沃尔玛和 Gap 等客户。最近的 2019 年第三季度报告显示,Azure 在云计算之战中给了竞争对手 AWS 一个机会。
美国电话电报公司表示,它正在成为一家“公共云优先”的公司,将应用程序从其数据中心转移到 Azure,并将通信业务的员工转移到微软 365,其中包括 Windows 10、Office 365 以及移动和安全服务。
再举一个微软绝地契约的案例研究。微软赢得了一份关键合同,为该公司提供从云到人工智能和应用于关键军事工作的机器学习的服务。这份合同建立在微软在政府技术领域数十年成功的基础上,但将合同授予微软而不是 AWS 仍然是一个令人惊讶的决定。微软能够满足政府的要求,并且出价高于他们的主要竞争对手。这是因为他们的云产品 Azure 非常漂亮,它提供了身临其境的多样化功能、现代安全合规驱动的架构、可扩展性和持续创新。微软在他们的云计算上投入了大量资源,该系统对于现代化战争来说是健壮的。这是一个赢得的关键合同,因为据估计它在 10 年内价值高达 100 亿美元。这份合同对于展示微软在云技术市场的领先地位至关重要。
Azure 发展势头背后的原因&行业如何认识到它的价值。
虽然有许多因素影响微软云业务的崛起,但有三个要点最能推动这一运动:安全性、合规性和 AI/ML 计划。
微软产品的遗产:作为习惯动物,当我们听到熟悉的东西时,会自动感到更安全。Windows、MS Office、SQL server、SharePoint 是可识别的名称,自现代计算机诞生以来就一直存在。这些是在谷歌和亚马逊出现之前的过去二十多年里,消费者和企业已经习惯使用的一些微软产品。微软的遗产和在业界的存在是 Azure 接受的主要原因,因为迁移和实现是第二天性。
一站式服务:微软云是一个完整的包,其产品包括云基础设施服务(IaaS)、应用程序和软件即服务(SaaS)等服务。这些产品包括服务器、存储、数据库、网络和软件(SQL Server、Windows Server、Visual Studio、System Center、GitHub……)—也称为智能云细分市场、Office 365 (Office、Exchange、SharePoint、Skype for Business 和微软团队)、LinkedIn 和 Dynamics 365(云 CRM 和 ERP)。
Azure 专用主机:这种新的专用主机为在单租户物理服务器上运行虚拟机提供了更大的灵活性。这为您提供了对机器上运行的一切的完全控制。该主机将支持 Windows、Linux 和 SQL Server 虚拟机。虚拟机有两种不同的处理器。当一家公司使用 Azure 专用主机时,他们可以确保他们做出的决定有助于他们公司的物理安全、数据完整性和监控。底层基础设施与任何其他 Azure 数据中心主机完全相同。
现有许可折扣:为了在技术生态系统中保持竞争力,微软决定对其产品提供折扣。特别是,微软正在提供升级到微软 Azure 的激励措施,包括免费更新。这些激励措施为公司创造了 0 美元的利润。
合规驱动:一般数据保护法规旨在保护用户隐私。微软充分利用了新的要求,使新的功能符合要求,如 Azure GDPR 数据主题请求门户。这使得 Azure 尽可能地为用户请求提供数据。
对于 Microsoft Azure,GDPR 功能突出显示了可用作模板的策略,以便在您的组织内创建您自己的策略和流程。这些策略也可以在系统的试点测试或审计期间使用。
为什么 Azure 被认为是安全的云平台?
握手:在计算机世界中,握手本质上是在两个组件之间创建一个网络连接。数字握手可以在任何两个通过相同协议通信的系统之间完成。这两个系统可以是客户端和服务器,或者只是 P2P 网络上的两台计算机。握手确认连接系统的身份,并允许无缝地进行额外的通信。大多数情况下,握手等同于验证连接、速度或试图连接到它的计算机的授权的步骤。握手在云计算世界中起着重要的作用,主要是当一台计算机试图与另一台计算机或服务器连接时。当两台计算机遵循相同的协议时,这种握手变得简单而安全。例如,一家企业使用 Windows 系统十年,然后过渡到 AWS 进行云计算。这个过程变得异常困难,因为 Windows 和 AWS 遵循不同的协议。因此,为了匹配和结合两个不同的协议和两台计算机,需要定义一个新的端口或算法,以允许授权不间断地进行。此外,打开一个端口或创建一个新的端口被认为是一个易受攻击的点,因为黑客利用这些点作为漏洞来进入系统和环境。因此,Azure 被认为比 AWS 更安全,因为 Azure 是基于 windows 的,如果我们参考世界的统计数据,我们会发现迄今为止大多数计算机都是基于 Windows 的,并使用 Linux 操作系统。
大约 50%的微软 Azure 虚拟机已经采用了 Linux。Azure 上超过六个受支持的 Linux 发行版进一步将 Linux 集成到微软生态系统中。其中包括 CentOS、CoreOS、Debian、Oracle Linux、Red Hat Enterprise Linux (RHEL)、SUSE Linux Enterprise Server (SLES)、openSUSE 和 Ubuntu。这些工具表明 Azure 是建立在 Linux 平台上的。Linux 被认为是世界上最安全的计算平台。补充这些工具的是 Azure Cloud Switch、SONiC、Azure Sphere 和 Azure Sphere Security Service。这些工具为网络设备提供操作系统,为软件定义的网络提供软件网络组件,并为边缘设备提供软件和硬件堆栈。
尽管如此,对于计划过渡到云计算世界的企业来说,Azure 成为他们的首选和偏好,因为集成是平滑和轻松的,不需要通过创建现有平台和操作系统之间握手的端口和算法来重新发明轮子。这种强有力的握手使授权变得容易并提供增强的安全性,因为对于计算机和服务器来说,当现有的基于 windows 的系统和基于 Linux 的操作系统与基于 Windows 的云平台和 Linux 操作系统连接时,协议是相同的。握手变得几乎不可渗透,因为连接不需要新的端口。此外,Linux 内核是微软自己的产品,基于 C 语言构建,集成到 Windows 8 和 10 操作系统中,由于其扩展的 DAC、名称空间、POSSIX 功能和加密功能,增强了最大程度的安全性。通过 Azure Sphere 自己的定制 Linux 内核,微软使握手更加流畅和安全。
数据中心的全球布局:微软 Azure 拥有 54 个数据中心区域,覆盖南北美洲、欧洲、中东、亚洲和太平洋地区,比任何其他云提供商都多。数据中心的大量存在和数量成倍增加了 Azure 数据中心的规模,并提供了优于 AWS 和 Google 的速度和弹性优势。此外,他们的地理数据中心确保了增强的安全性。由于这一事实,该特定区域的客户端数据不必传播很远。比如说;来自东海岸的 Azure 客户端数据保持在同一地区,而来自西海岸的数据则没有。这提高了访问数据的速度并增强了性能。如果数据必须传输到位于西海岸的数据中心,就需要更长的网关,网关越长,安全威胁就越大。Azure 在北美有 16 个数据中心区域,在欧洲有十几个,首先进入的是中东的两个区域,大约十几个在亚洲,4 个在太平洋,不像 AWS 在全球总共只有 22 个区域,其中一个在太平洋,8 个在北美,这使它更容易受到攻击。谷歌的数据中心区域更少,全球只有 16 个。使用 AWS 的美国中部以外的客户将不得不使用东海岸或西海岸以外的数据中心,这导致创建长网关,而长网关简化了渗透系统的能力。
Azure Security Center:Azure Security Center 的特性非常密集,它根据使用案例和环境来执行产品、服务和流程的角色。一个完整的威胁检测、建议和保护包,帮助企业应对现代网络威胁。Azure 安全系统的魅力在于它提供安全智能和建议,并且旨在跨混合云工作负载使用,无论这些工作负载是否在 Azure 上,也可以在本地使用。这是一个明显的证据,表明企业正在接受微软作为一个安全的云平台,不管他们是否使用 Azure。微软声称现代安全威胁非常复杂,Azure Security Center 解决了三个紧迫的安全问题 a)动态工作负载 b)日益复杂的攻击 c)安全技能和人才的短缺。Azure Security Center 通过管理合规性、评估、建议、预防、速度和自动化来满足这三个方面的需求。
合规管理:系统可以跨机器、数据服务和应用集成和实施,确保服务器、机器和应用默认合规。这是因为它带有预定义的 Azure 策略控制,并且只有在制定策略和合规性时才能部署实现。它还提供了选择、设置和定制策略的灵活性。该过程确保企业默认定义并遵循策略和配置标准。该系统在一致的基础上扫描应用和机器,并在控制面板中提供单一窗口视图,以识别是否有任何订阅缺少策略,并使用正确的策略保护所述订阅。
保护负载: Azure 安全中心持续监控工作负载,并确保工作负载是否根据定义的安全策略和实践进行配置。Azure Security Center 提供的最强大的评估功能是网络地图。该图提供了工作负载以及节点如何配置和相互连接的单一窗口视图,这有助于识别节点之间可能成为网络中潜在攻击威胁的不必要连接。
安全背后的美丽: Azure Security center 最美丽的特性是其名为 Secure Score 的推荐引擎。它有助于识别漏洞,确定威胁的优先级,并提供定制的指令来修复它们。Azure Security Center 的推荐引擎可以部署在组织中的每个资源上,每个资源都被监控、评估、推荐并定义自己的标准集。这包括 Azure 虚拟机、非 Azure 服务器和 Azure PaaS 服务,如 SQL 和存储帐户等。
威胁防护:安全中心的威胁防护保护数据、IOT 和混合云工作负载。它检测并防止基础设施即服务(IaaS)层、Azure 中的平台即服务(PaaS)中的威胁,包括 Azure 应用服务、Azure SQL、Azure 存储帐户以及非 Azure 服务器。除此之外,融合杀伤链分析和网络杀伤链分析功能有助于识别环境中的警报、攻击点的来源、攻击活动及其可能对环境资源造成的影响。此外,安全中心提供内置的 Windows Defender 高级威胁防护,确保 Windows 虚拟机和服务器在安全中心的建议和评估范围内。高级威胁检测也可以集成到 Linux 虚拟机和服务器中。环境中的威胁可能包括多种类型,但是让系统做好足够的准备来防范和抗击暴力攻击在很大程度上受到系统策略的影响。Azure Security Center 帮助设置安全访问策略,并通过定义授权用户的访问权限、访问时间和允许的源 IP 地址范围或 IP 地址来限制对虚拟机的访问。
速度和自动化:安全中心提供与 Azure 和 Azure 资源的无缝本地集成。这意味着,你可以整合一个完整的安全故事,涉及 Azure 策略和所有 Azure 资源的内置安全中心策略,并确保每个方面都自动应用于你在 Azure 中创建的新发现的资源。
广泛的日志收集:来自 Windows 和 Linux 的日志都在信息安全智能分析引擎中得到利用,并用于创建建议和警报。
Azure 的人工智能计划
无限的数据资产:在数字时代,公司的价值不再与有形资产、基础设施或其他有形材料挂钩。相反,公司的价值可以通过他们的数据来衡量和定义。数据为公司提供了以前看不到的启示。与此同时,收集和使用数据也带来了挑战。公司需要考虑数据的可扩展性、效率、备份和恢复。微软 Azure 提供了传统数据库中没有的解决方案。这是通过独立的计算机节点完成的。有一个主节点和二级热备用节点。备用节点提供紧急备份。
计算机节点能够通过缓存 SSD 来提取一页数据,从而减少通过网络的次数。缓存功能将存储的可扩展性从 1–4tb 提高到 100 TB。存储容量的增加有几个原因。Azure 超大规模架构允许快速读取扩展能力,并为主要计算机节点提供时间来生成更多请求。该架构还被设置为共享存储,并且备份是即时的。数据备份能够从主计算机节点移动到存储层,这意味着服务器性能不受影响。
以非常相似的方式,通过拷贝文件快照来完成任何所需的恢复。这意味着数据的大小不是问题,也不会减慢处理速度。这意味着当恢复在同一存储帐户中时,主计算机节点的性能不会受到负面影响。如果地理位置不同,那么这就是 Azure 超大规模数据库有用的时候。它允许 Azure SQL 数据库超大规模数据库的恢复,而不管它当前托管在哪里。
理解认知
Azure 认知服务:通过 Azure 认知服务支持企业应用构建、网站开发和自动化机器人。这些服务包括以下功能:视觉、语音、语言、搜索和决策 API。独立和胜任的数字员工的发展受到 Azure 认知服务的影响,并提高了效率、速度和自动化。
Azure 认知搜索:数据点和信息有很多潜在的意义。对于多媒体或数据源来说尤其如此。Azure Cognitive Search 通过提高可搜索性来使用和分析这些数据。Azure 添加的认知技能至关重要,因为它们丰富了原始文档和资源。这种方法的优点是易于分类、搜索和提取关键信息。微软 Azure 特别适合投资于机器学习的人,他们没有编程或编码技能,在没有软件帮助的情况下在这一领域工作。
当存在原本无法搜索的文本时,应该使用认知搜索。它还具有语言翻译的优势,因此如果文档是另一种语言,它可以处理和翻译该语言。还有一些高级版本和型号可以满足大量的需求和要求。Azure 为他们选择共享的数据提供了灵活性。
Microsoft Azure 在某种程度上受限于正在使用的数据的位置。为了能够使用 Azure,必须有可由索引器访问的数据。没有这一点,数据是不可用的。这些索引器非常关键,因为它们与技能相关,然后在所有后续搜索中定义。技能集用于数据内操作的处理和顺序。如果开始时没有可靠的数据,产出和数据就会缺乏。
SQL Server 机器学习:预测分析和机器学习的重要性只会增加。当企业需要处理数据时,他们可以采用 SQL Server 机器学习来与 Python、R 和关系数据结合使用。可以直接在数据库中执行所需的脚本。这意味着数据不需要通过网络传输来进行数据分析。机器学习和预测分析有大量的应用。它们可以用于数据清理、特征工程、培训和部署机器学习模型等。有了这个工具,企业组织和公司可以将深度学习添加到他们的 SQL server 中。
AWS 有多安全?
云 SaaS 应用程序越来越受欢迎,并在快速创新。这意味着,围绕安全性、数据管理和隐私的问题和顾虑往往会越来越多。AWS 安全性分为四个不同的类别。这些是系统、通信、数据和隐私。了解 AWS 的安全性非常重要,因为使用该解决方案会带来隐私和安全方面的期望。
根据 Rath、Spasic、Boucart 和 Thiran (2019)的说法,在评估 AWS 的安全特性时,需要调查一些特定的领域。AWS 必须为系统组件提供保护、防止对系统的未授权访问、监控网络请求、审计和违规恢复、持续的数据保护(无论网络连接如何)、隐私保护、法规遵从性、安全通信以及对云资源的全面保护。当一个系统满足所有上述安全要求时,这意味着它们能够挫败和防止任何类型的攻击。在上述每个类别中都有几个考虑因素。
为了保证 AWS 的安全性,它必须在通信、数据和隐私安全方面提供保护。要知道如果 AWS 有这些解决方案,它会有潜在的安全问题,这个问题可能发生的实例,然后是这个问题的所有解决方案。一个系统必须是全面的才能被认为是安全的,我们现在将探讨 AWS 是否以及如何满足这些安全要求。
合规和监管标准: AWS 使用多种工具来满足必要的监管和合规标准。AWS 的数据公民合规性意味着云用户必须满足从整个国家到局部地区的地理定位要求。AWS 通过 CloudFront 和地理定位软件实现加密擦除。AWS 使用 KMS 服务来控制许多 AWS 服务和应用程序的加密和密钥。用户还必须通过分担责任模式来表明他们对数据安全的承诺。AWS 提供了云平台的基本安全功能,并不是所有的应用程序都可用。当数据需要在国家或其他地理区域之间传输时,AWS 使用兼容的数据传输地理位置来实现这一点。当用户考虑数据保留时,他们知道 AWS 通过多种不同的工具和系统来备份数据。对于数据生命周期,AWS 有一个允许管理资源和数据的系统。最后,用户可以放心,使用 DynamoDB 不会意外或故意删除数据,以实现有意的数据保留。
识别、认证和授权:当认证和授权问题成为关注点时,AWS 会满足安全需求。AWS Cognito 支持多种登录选项,满足了多因素身份认证的要求。AWS 允许多个应用程序和设备的单点登录。当用户只需要短期访问系统时,他们可以使用 AWS 访问令牌来验证 API。为了实现客户端和服务器之间的身份验证,AWS 会为相互身份验证生成证书。为了确保只有正确的用户才能访问系统,AWS 使用了安全打包程序和密钥编码器。这种数字权限管理满足了用户登录的安全要求。有时,系统管理员希望在高级别管理用户和组。身份和访问管理器是设置各种用户权限的 AWS 工具。与 access manager 相关,AWS 还允许基于请求它们的个人的身份和权限的某些活动。这发生在基于请求的身份验证模型中。最后,AWS 利用 IAM、Cognito 和 AWS CloudWatch 等工具来安全访问数据和资源。这满足了访问控制许可的安全要求。
安全开发、运营和管理:除了遵守法规和管理用户访问,AWS 还需要确保当他们的系统实际部署在一个平台上时,安全性仍然是重中之重。以下所有工具都用于防范攻击企图。AWS 通过定制的 bastion 服务器完成从专用网络到外部网络的访问。总有一些怀有恶意的人试图访问数据并破坏它,AWS 采用 GuardDuty 作为自动威胁检测。用户希望他们的应用程序始终可用。为了实现持久可用性,AWS 使用 CloudWatch 和 WAF 等各种工具来保护和监控设备。企业需要知道他们的计算资源受到保护,并且 AWS 具有经济持久性。AWS 使用 CloudWatch 来确保资源得到明智的管理和使用。亚马逊并没有创建 AWS 平台中使用的所有应用程序,因此这些应用程序中可能存在漏洞,AWS 在漏洞管理工作中使用了 AlienVault USM。
隐私和保密:就满足所有既定要求而言,这是 AWS 的一个不足之处。每当 AWS 不符合要求时,IT 团队必须承担起保护隐私和机密性的责任。
当 SSL/TLS 证书用于 AWS 服务和资源时,AWS 使用 AWS 证书管理器来部署它们。这意味着存在端到端的安全性。隐私和机密性的所有其他方面,包括加密数据计算、数据匿名化和处理目的控制,都不是 AWS 提供的安全功能。
安全架构:AWS 中的用户可以访问他们自己的虚拟网络,这为 AWS 创建了一个独特的部分,可以启动应用程序和其他资源。用户可以完全控制这个网络。每当在 AWS 中使用 web 应用程序时,它都会受到 web 应用程序防火墙的保护,防止恶意行为在 web 应用程序上发生。由于大量设备没有连接到互联网,因此有必要确保所有物联网设备的安全。AWS 为安全元素部署物联网设备管理。访问数据的速度对每个人都很重要,AWS 意识到了这一点。当需要访问大量不常用的数据时,可以通过 Glacier 服务使用安全的冷存储进行访问。当访问数据时,需要处理 TLS/SSL 的加密密钥和证书。AWS 使用密钥管理器和证书管理器来管理 TLS/SSL 证书。当用户需要创建自己的加密或密码密钥时,有一个云硬件安全模块允许创建这些密钥。
AWS 通过公开其所有安全特性和更新的列表,使其安全选项尽可能易于访问。这使得所有用户和感兴趣的利益相关者可以更多地了解 AWS 如何满足他们的安全需求。这让用户可以评估 AWS 是否能为他们工作并满足他们的需求。
Azure 安全中心 vs AWS 检查员:
Azure vs 亚马逊 vs 谷歌云机器学习服务:
蔚蓝机器学习
微软的 Azure machine learning 作为软件即服务有几个优秀的特性。它具有全面的自动和半自动机器学习功能。Azure 有两个主要的不同分支:机器人服务和机器学习。Azure 有非常灵活和众多的算法,适合新手和高级数据科学家。有一个被称为 Cortana Intelligence Gallery 的广泛社区支持 Microsoft Azure。
Azure 机器学习的具体功能包括拖放界面、数据准备、机器学习模型的培训、部署和管理、对开源技术 PyTorch、TensorFlow 和 scikit-learn 的支持。使用开源 Python,有可能在 Azure workspace 上构建模型。不需要高级数据科学专业知识,就可以使用 API 和认知服务等概念和工具。
亚马逊云机器学习和预测分析
亚马逊的机器学习被称为自动化机器学习服务的亚马逊 ML 和定制机器学习建模的亚马逊 SageMaker。
Amazon ML 的特点是分类、回归和聚类。如果使用 Amazon SageMaker 需要一个定制平台,该平台有内置算法,支持以下框架:TensorFlow、MXNet、Keras、Gluon、Pytorch、Caffe2、Chainer 和 torch。现在让我们来看看亚马逊的这两个机器学习解决方案的一些优势。
Amazon ML 是一个自动化的、随时可以部署的机器学习模型。你可以把它想象成一个样板房,它可以很快完工,不需要太多的定制。Amazon ML 的一个优势是它是一个自动化的解决方案,可以处理严格的截止日期,并且产品可以快速工作。该平台还能够从多个数据源加载数据,并自动对这些数据进行所有必要的处理。Amazon ML 几乎不需要用户输入任何信息,这对于那些不需要或不想做这些决定的人来说是一个优势。一个机器学习科学家新手会发现 Amazon ML 的自动性是一个优势,因为系统会为你做出大多数必要的决定。Amazon ML 预测分析的优势在于有两种不同的 API,一种用于实时数据,另一种用于按需数据。
亚马逊 ML 在预测分析方面有局限性,因为只有三种可能的选择。这些是二元分类、多类分类和回归。亚马逊 ML 的所有学习都需要被监督。亚马逊 ML 的一个巨大弱点是,自 2016 年以来,指南和文档一直没有更新。随着技术日新月异的发展,当时写下的信息对今天来说可能已经过时了。Amazon ML 缺少的方面是异常检测、推荐和排名。
Amazon SageMaker 是一款面向数据科学家的工具,这些科学家拥有一些机器学习经验,并希望能够轻松地建模解决方案,并在适当的时间和地点部署它。SageMaker 负责外部系统,以确保数据科学家不会专注于服务器和访问问题。SageMaker 的算法可以处理系统中的大量数据。SageMaker 的算法包括但不限于:线性学习器,因子分解机,图像分类,神经主题模型。亚马逊机器学习服务对所有参与机器学习的人都有用,从新手到专家。
谷歌云机器学习和预测分析
谷歌的一个优势是,机器学习模型基于两个不同的层次——一个面向机器学习应用的新手用户,一个面向机器学习应用的超级用户。Google 不满足自动 ML 系统的聚类、异常检测和排序功能。对于定制建模,Google ML 引擎内置了算法。它支持以下框架:TensorFlow、scikit-learn、XCBoost 和 Keras。
对于新手用户来说,AutoML 的优势在于 Google 存储和训练数据集以及所有需要的模型。由于谷歌是一个如此强大的生态系统,谷歌 ML 的一个天然优势是它连接到所有其他谷歌系统,数据自动存储在云中。Google ML 使用 API 来访问可用于处理和训练模型的不同产品。由于 AutoML 意味着自动化和快速数据处理,它的弱点在于灵活性和有限的定制可能性。
这就是 Google ML 引擎的闪光点。对于不具备处理数据和语言所需知识的人来说,这个系统有很多缺点,但是对于高级科学家来说,这个系统有很多优点。由于 Google 也有 TensorFlow,所以其他框架的使用实际上是有限制的,因为用 TensorFlow 作为机器学习的框架是一种天然的联系。TensorFlow 是一个非常难学的系统,期望 ML 引擎与 TensorFlow 一起使用可能会有问题。谷歌 ML 引擎的另一个弱点是,它不像亚马逊那样在他们的机器学习和预测分析模型中建立起来。
结论
归根结底,在决定使用什么样的云计算资源时,每个企业都有责任决定哪些因素对他们最重要。对他们来说什么最重要?安全性是他们的重中之重,而 ML 在列表中的位置较低,还是快速启动并运行的能力比 100%定制更重要?这些决策可以基于存储的信息类型、企业的规模或企业的位置等。随着技术领域的快速发展和不断变化,看看谁会在云计算之战中胜出将是一件有趣的事情。
免责声明
本文是作者在深入研究和分析的基础上提出的观点和想法。没有人声称这在任何情况下都是准确的。您自己的观点、想法和发现可能会因本地用例、理论、经验和发现而有所不同。如果您发现了与您的体验不同的内容,请通过电子邮件或短信直接联系我,就此主题进行进一步的对话,因为我总是希望拓宽我的视野。谢谢你。
伯特 vs 乌尔菲特对决
原文:https://towardsdatascience.com/battle-of-the-heavyweights-bert-vs-ulmfit-faceoff-91a582a7c42b?source=collection_archive---------17-----------------------
重量级人物之战
一个简单的 web 应用程序,用于实时比较两种架构。包括在谷歌应用引擎上部署的完整代码和说明
Photo by Johann Walter Bantz on Unsplash
这篇文章是早先文章的延续,在那篇文章中我谈到了在自定义数据集上运行拥抱脸的 pytorch-transformers 库。
在本主题中,我们将讨论:
- 使用 py torch-transformers & ul fit 进行推理
- 使用 HTML 前端和 flask 后端将其转换为 web 应用程序
- 使用 SQLAlchemy & Cloud SQL 存储数据
- 谷歌应用引擎上的生产部署
- 几个有趣的观察结果
背景
当py torch-transformers发布时,我想试用一下,看看它的性能有多好,使用起来有多方便。因此,我开始着手建立一个 BERT(基础)模型,并在 IMDB 电影评论数据集上进行了微调。我把它包在一个网络应用程序上,任何人都可以玩。然后,我觉得与其他模型进行比较会很有趣,所以我在我的应用程序中加入了 ULMFiT。之所以选择 ULMFiT,是因为我作为 FastAI 的学生已经很长时间了,并且随身带着一个微调过的模型。最后,我决定通过对每个单词进行预测来实现实时性,这提供了一种很酷的方式来查看模型的内部工作方式。
app 部署在这里:https://deployment-247905.appspot.com/
这是当前版本的外观:
密码
所有的代码都存在于这里的回购中。[注意:自述文件将会随着代码的清理/小的重构而更新更多的细节]
下面快速浏览一下目录结构。
├──docker file
├──readme . MD
├──app . YAML
├──main . py
├──model
├──model-fastai
├──requirements . txt
├──static
┤──templates
└──utils _ inference . py
- Dockerfile:将应用程序作为 docker 容器运行。此外,我们在谷歌应用引擎(GAE)部署中使用了“灵活”的环境,这需要一个 dockerfile 文件。
- app . YAML:GAE 所需的应用程序设置文件
- main.py:主 flask 后端代码。文件名应该是 main.py,以便与 GAE 一起使用
- 模型:包含微调的 BERT(基本)模型文件。想要下载文件,但是库需要增强来处理。我会看看我能不能做到。
- model-fastai:只包含 ULMFiT 的 imdb.vocab 文件。其他文件从一个公共的谷歌云存储桶中下载。
- requirements . txt:docker file 需要安装的所有包
- 静态:Web 用户界面所需的 CSS 和 javascript 文件
- 模板:包含拥有我们的 Web 用户界面的 index.html 文件。
- utils_inference.py:为 BERT 模型进行推理所需的实用函数。这些是从 pytorch-transformers 的 utils_
中复制的。py 文件,并定制为 IMDB 电影评论数据集运行。
推理
虽然 pytorch-transformers 使运行预训练模型甚至微调它们变得容易,但我发现在它上面运行推理很困难。因此,我复制了相关的功能,并修改它们以适应我的需要。
在 IMDB 电影评论数据集上微调 BERT 的所有细节可以在我早先的帖子中找到。
另一方面,从代码中可以看出,在 ULMFiT 上运行推理非常简单。
推理是通过后端的“/analyze”API 端点公开的,然后调用相关的函数来获得预测并在响应中返回它。
前端
前端使用 HTML、CSS 和 Javascript 开发。它使用额外的 jQuery 包来整合标尺、加载按钮和向上/向下滚动功能。为了提供实时交互,使用 AJAX 调用在每个单词后自动触发预测(稍有延迟,以防止在键入句子时触发不必要的事件),从而只更新标尺,而无需重新加载整个页面。
UI 还有一个选项,可以对任何评论的模型性能进行投票。这些信息被保存在一个 SQL 数据库中,这样我们以后就可以分析哪个模型对哪个评论更有效。
我的 UI 技能相当有限,所以代码肯定不是最优雅的,但它完成了工作。
后端
后端使用 FLASK WSGI web 应用框架。它公开了 3 个 API 端点:
/':对于主用户界面
“/analyze”:用于运行预测
/model-feedback ':用于提交对模型性能的反馈。
可以调用后端在调试或生产模式下运行。这是由一个。主应用程序文件夹中的“调试”文件。(即在调试模式下运行创建一个。调试 apps 文件夹中的文件)。
女服务员 用于服务制作版。请注意,按照 Google App Engine 的指示,生产版本需要在端口 8080 上运行。
后端使用aiohttp&asyncio模块异步下载模型文件。
我们还保存了客户端 IP 地址,以区分有多少不同的 IP 地址访问了该应用程序。因为在 GAE,应用程序位于 nginx 代理之后,所以我们必须使用 request.access_route[0] 来检索它。
数据存储
后端使用 SQLAlchemy 与谷歌的云 SQL 实例交互,将模型性能数据保存在 MySQL 数据库中。必须单独提供云 SQL 实例。Google App Engine 实例可以直接访问云 SQL 实例(通过云 SQL 连接名称字段)。请参考官方文档,了解实例的配置。
部署到生产
因为我从谷歌获得了免费积分,所以我决定把这个应用程序放在它的基础设施上。起初我想部署一个虚拟机实例,但后来我遇到了 GAE,听起来非常完美。
让我们来看一下 app.yaml 文件,该文件控制应用程序如何在 GAE 上托管
运行时:自定义
env: flex
资源:
CPU:2
memory _ GB:4.0
disk _ size _ GB:20
readiness _ check:
app _ start _ time out _ sec:900
env _ variables:
CLOUD _ SQL _ CONNECTION _ NAME:deployment-XXXXXX:xxxxxxxx:xxxxxxxx xx
DB _ USER:xxxxxxxx
DB _ PASS:XXXXXX运行时:自定义
环境:flex
如果您正在部署 docker 容器,那么您需要使用灵活的环境(与标准环境相对)。自从我开始使用 docker 以来,我已经部署了相同的环境,但是我想转移到标准的环境,因为如果没有使用,这些实例可以缩减到 0。
资源:
cpu: 2
内存 _gb: 4.0
磁盘 _ 大小 _gb: 20
我增加了默认实例的配置,选择了一个双 CPU 实例,内存为 4 GB,磁盘大小为 20 GB。在' google cloud deploy '命令失败并且日志抛出“设备上没有剩余空间”错误后,我不得不增加磁盘大小。
准备就绪 _ 检查:
app_start_timeout_sec: 900
在我收到“ google cloud deploy ”命令失败后,我将应用程序启动超时从默认的 300 秒增加到 900 秒。
env _ variables:
CLOUD _ SQL _ CONNECTION _ NAME:deployment-XXXXXX:xxxxxxx:xxxxxxxx
DB _ USER:xxxxxxx
DB _ PASS:XXXXXX
DB _ NAME:xxxxxxx
将数据库凭证传递给后端 python 脚本需要这些设置。理想情况下,我们应该使用“云密钥管理”解决方案(或等效方案)
beta _ settings:
cloud _ SQL _ instances:deployment-XXXXXX:xxxxxxx:xxxxxxxx
需要此设置来提供 GAE 和云 SQL 实例之间的连接。
有趣的观察
在这一部分,我们将看看我发现的一些有趣的观察结果:
总的来说,ULMFiT 似乎很难处理短句(3-4 个单词)。
添加“.”最后改变置信度%。
仅仅增加一个额外的单词“It”就改变了对 ULMFiT 的预测。
我想这两种情况都有可能。
这个也一样。
伯特在这里做得更好,因为我认为“高于平均水平”是积极的。
在这种情况下,两者都是正确的,但我们知道 ULMFiT 对于较短的句子偏向于否定。
很高兴看到这里的信心越来越强。
很高兴看到伯特能把这件事做好。但是我们知道“高于平均水平”是负面的。
但它得到的却是负面的。也许是因为刑期较短。
这里都很好。
但这是什么?伯特仅仅通过去掉单词“was”就改变了它的预测。发生什么事了?
现在这个你会认为是负的,伯特错了,乌尔姆菲特对了。
但是如果你去掉“黑暗”这个词,伯特就会改变它的预测。同样,不知道这是如何工作的。
最后,我在 IMDB 上测试了 50 多条真实评论,我可以说这两个模型彼此非常一致,除了这一次 ULMFiT 似乎做出了更好的判断。
结论
虽然上面的例子确实表明 BERT 更擅长理解语言的语义,但是在现实世界中,当有多个句子时,两者之间没有太多选择。
如果更多的用户可以尝试这个应用程序,并提供他们对一种模式比另一种模式更好的情况的反馈,也许我们就可以选出一个赢家。
快速链接:【https://deployment-247905.appspot.com/】
用 Google Colab 战胜 GPU 的挫败感
原文:https://towardsdatascience.com/battling-out-the-gpu-frustration-with-google-colab-2fb62ecf276d?source=collection_archive---------9-----------------------
轻松开发复杂机器学习模型的平台。
image from NVIDIA
随着机器学习和深度学习模型的数据集规模大幅增加,对 GPU 更快训练模型的需求也在升级。作为数据科学的学生,我们都知道我们受到挑战的笔记本电脑需要多长时间来运行包含数百万条记录的数据集的机器学习或深度学习模型。
一般来说,基本的笔记本电脑和个人电脑需要用户花费大量的时间来将数据拟合到构建的模型中。因此,超调模型的过程会受到这种约束的影响。
这种情况的另一种选择是购买外部 GPU,基本型号的平均价格为 250-300 美元。对于一个学生来说,对于他/她正在努力的大学项目来说,这是一个很大的代价。
GIF from Giphy
我知道这很令人沮丧!!!
多亏了谷歌,学生们可以不再担心这样的情况,因为谷歌在云上提供了一个免费的 GPU 来运行大规模的机器学习项目。
本文将带您开始使用 Google Colab,这是一个免费的 GPU 云服务,带有一个基于 Jupyter Notebook 的编辑器。
用户可以运行他们的机器学习和深度学习模型,这些模型建立在当前最受欢迎的库上——Keras、Pytorch、Tensorflow 和 OpenCV。
首先,你需要一些 Python 和 Jupyter notebook 的知识,以及基本的机器学习概念。
Google Colab 是 Python 流行库的完美工具,如 Keras 、 Tensorflow 、 Pytorch 。您可以创建一个新的 Python 3 或 Python 2 笔记本,打开存储在各自用于创建笔记本的 google 帐户中的笔记本,并可以从本地计算机上传笔记本。在将我们的数据集上传到平台的情况下,有一个缺点,即当会话重新启动时,数据集会被删除。我们可以将 Google Drive 安装到笔记本上,这是一个很酷的功能,而不是每次打开笔记本时都要上传文件。
Google Colab 入门
我们可以通过点击下面的链接启动该平台
[## 谷歌联合实验室
编辑描述
colab.research.google.com](https://colab.research.google.com/notebooks/welcome.ipynb?pli=1)
一旦你点击链接,你将被要求使用你的谷歌账户登录,你创建的所有笔记本将被自动存储以备将来使用。
- 示例选项卡提供了一些代码,为了使用 Google Colab 的大部分功能,必须对这些代码进行适当的检查。
- 最近的选项卡提供了您最近创建或处理的几个笔记本。
- Google Drive 选项卡提供所有链接到您的 Google 帐户的笔记本。
- Github 标签让你将你的 Github 账户链接到 google colab。
- 上传选项卡提供了从本地计算机上传文件的链接。通过广泛使用该平台,可以了解大多数隐藏的功能。
基本布局和功能
image from Google Colab
这是创建新笔记本时生成的基本布局。大部分功能与 Jupyter 笔记本相似。双击 Untitled.ipynb 可以更改笔记本的名称 +Code 和+ Text 分别用于添加新的 Code 单元格或 markdown 单元格。其他用户可以通过添加他们的 Gmail 地址来共享笔记本,这样每个人都可以在一个地方进行适当的更改。您可以通过点击屏幕右上角的连接按钮开始新的会话。
在开始会话之前,最好将运行时类型更改为 GPU(因为这是使用 Google Colab 的主要目的),可以在运行时选项卡中访问它。
Google Colab 是一个非常简单但功能强大的平台,可以运行您的机器学习和深度学习模型,而不必担心 GPU 的能力。如果你习惯在 Jupyter 笔记本上工作,那么这将是小菜一碟。
降价
我想强调一下降价,因为它们在开发 Jupyter 笔记本时增加了很多重量。它帮助你通过你的代码讲述一个故事,如果你想成为一名数据科学家,这是必须的。管理主要需要输出,而不是相关的代码,这简化了这个过程。Google Colab 提供了对所写的降价的实时预览,这样你就不必每次都运行单元格来进行微小的修改。
上传数据
该窗口出现在屏幕左侧,并带有一个与之相关的箭头。在这里,你可以从本地计算机上传一个文件或者挂载你的 Google Drive(我会在文章的后半部分解释)。
基本命令
1.安装你的谷歌硬盘
from google.drive import drive
drive.mount(/content/gdrive)
2.安装库
!pip install keras
3.克隆 Github 存储库
!git clone [https://github.com/pytorch/pytorch](https://github.com/pytorch/pytorch)
4.运行 Python 脚本
!python setup.py
TPU 电力公司
TPU(张量处理单元)是由谷歌开发的,旨在提供高计算能力来训练机器学习和深度学习模型。尽管你可以随意使用 NVIDIA Tesla K80,但 TPU 提供的动力要大得多。根据 Google 的 Colab 文档提供的信息, A GPU 提供 1.8TFlops 并拥有 12GB RAM ,而 TPU 提供 180TFlops 并提供 64GB RAM。
GIF from Giphy
结论
Google Colab 是 Jupyter Notebook 运行高计算深度学习和机器学习模型的绝佳替代品。您可以随时与其他开发人员共享您的代码,以便他们可以帮助您优化代码。大多数 python 库都预装了 Google Colab,因此它减轻了安装每个库的负担。和主要功能将是免费的 GPU!!!。
像往常一样,免费产品有一些限制。(无关紧要的限制,但在某些情况下会有所不同)。只能使用Python 2.7(2020 年 1 月起弃用)或 3.6 作为编程语言,不支持 R 。每个用户的 GPU 分配限制为一次 12 小时。使用的 GPU 是 NVIDIA Tesla K80 ,一旦会话完成,用户可以通过连接到不同的虚拟机来继续使用资源。
我建议你参考你的 Google Colab 一站式指南,它提供了更多的技巧和窍门,让你对 Google Colab 有更深的了解。
谢谢你。
GIF from Giphy
使用贝叶斯法则来发现(并澄清)你日常生活中隐藏的信念
原文:https://towardsdatascience.com/bayes-rule-for-job-hunt-b2eca4d3b98?source=collection_archive---------8-----------------------
Photo by Mikhail Vasilyev on Unsplash
如何应用统计概念来改善决策
贝叶斯法则的核心是,每当我们得到新的证据时,我们就更新我们的信念。当有人说她比以前更(或更少)自信时,她应用了贝叶斯法则,因为她在学习新信息后改变了信念。大多数人凭直觉用这个想法工作。然而,很少有人在自己的生活中有意识地使用它。
这篇文章不是关于贝氏法则的技术细节和公式。相反,我想向你们展示这个想法的强大之处。通过举例向你展示如何将这个框架应用于求职,我想达到两个目标:
- 我想让你相信贝叶斯法则在日常生活中的作用。
- 我想向你介绍一个如何改进决策过程的总体框架。
让我们开始吧。
求职的例子
汤姆最近搬到了一个新的城市,正在找工作。然而,他不想随机申请工作。相反,汤姆想把他的精力和时间放在最有前途的招聘上。他如何找到能让他在个人和职业两方面都茁壮成长的职位?
由于 Tom 对 Bayes 法则了如指掌,他拿着一张纸坐下来,开始问三个问题来告知他的决定。
问题 1:汤姆对多少招聘信息感兴趣?
这个估计是他第一次先于。先验是我们在没有考虑进一步证据的情况下认为是真实的数字。这是一个粗略的估计,汤姆会逐步改进的。这就是贝叶斯法则的意义所在!汤姆认为 10%的职位空缺是他想要的。
换句话说,这意味着汤姆必须写十份求职申请才能换到一份有前途的工作。这是一个非常模糊和繁琐的策略。第二个问题将帮助他在这方面有所改进。
问题 2:哪个信息最有助于汤姆区分好与丑?
汤姆正在寻找看起来尽可能不同的好的和坏的工作机会的信息。Tom 认为公司评级页面是可靠的来源,因为他认为好工作很可能与高评级有关。因为他正在使用贝叶斯法则,所以他必须估计这种可能性。汤姆认为,在 90%的情况下,好工作都是在评级高的公司。
汤姆还必须考虑另一种情况:这份工作很糟糕,但评分仍然很高的可能性有多大?他提出了两种可能发生的方式。首先,这家公司可能是一个很好的工作场所,但具体的工作却很一般。第二,一些公司可能会伪造评级。然而,他并不认为这两种情况发生的可能性很大。所以他假设 5% 的小概率。
如你所见,汤姆很自然地开始思考他的信念和假设。他没有直觉地认为“好的评级是一个好的指示”,而是有两个不同的假设需要评估。
现在他可以更新他的求职策略了。在没有任何进一步信息的情况下,他认为所有招聘信息中有 10%是有吸引力的。然而,鉴于一家公司的评级很高,他现在希望 67% 的这些招聘信息与他相关。这是一个巨大的差异,反映了他对公司分数的信任。
也凸显了两面思考的重要性!把 90%作为估计值是很诱人的,但这只是考虑了少数好工作。
计算:
汤姆对好工作的偏好是 10%。鉴于这是一份好工作,获得良好评级的概率为 90%。两项相乘得到 9%。他有 90%的前科。鉴于这是一项糟糕的工作,获得良好评级的概率为 5%。两项相乘得到 4.5%。所以我们的后验概率是 9% / (9% + 4.5%),大概是 67%。
问题 3:随着时间的推移,你还收集了哪些信号?
因为找工作是一个过程,汤姆可以再次运用同样的原则。举个例子,让我们假设汤姆参加了第一次求职面试。这是一次愉快的经历,离开后他有了很好的感觉。这如何改变他认为自己找到了一份好工作的信念?
在这个阶段,Tom 更加怀疑,因为招聘人员告诉他的和日常工作之间可能会有差距。他用 80%的概率估计好公司有好的第一次面试。然而,即使是糟糕的公司也会在 70%的情况下给人留下好的第一印象。
鉴于这些数字,他的信任度从 67% 略微上升到 70% 。如你所见,变化不大。这是贝叶斯的另一个强大的方面:你可以很好地理解新信息是多么重要!尽管看起来一切都变得更加透明,但事实可能并非如此。
计算:
我们对好工作的偏好(给予高评级)为 67%。鉴于这是一份好工作,第一次面试成功的概率是 80%。将这两项相乘得到大约 54%。我们以前的坏工作是 33%。鉴于这是一份糟糕的工作,第一次面试成功的概率是 70%。将这两项相乘得到大约 23%。因此我们的后验概率是 54% / (54% + 23%),大约是 70%。
后续步骤
汤姆很快就取得了很大进步,但和往常一样,还有进一步提高的空间。贝叶斯法则给了他两条前进的道路:
- 他可以整合额外的信号,并相应地更新他的信念。例如,他可以考虑员工的波动或公司随时间的发展。
- 他可以重新评估先前的估计。这些评论抓住了对他来说重要的东西吗?他分配的数字是可信的,还是需要调整?为什么?
无论他决定从现在开始做什么,他都会意识到每一条信息是如何影响他的信念的。
摘要
正如汤姆的例子所示,当你开始将贝叶斯法则应用于现实生活时,有三个好处:
- 你通过明确陈述和量化你的信念来获得清晰。
- 你识别最强有力的信息来源,即概率差异最大的信号。
- 您量化剩余的不确定性,这允许您决定是否值得收集额外的信息。
如果这篇文章对你有所帮助,或者你想补充什么,请在评论或 Twitter 上告诉我。我也很乐意在 LinkedIn 上联系。感谢阅读!****
资源
一段时间以来,我一直想写下这个例子,但 3Blue1Brown 的这个精彩视频给了我最后一点动力:
如果你对普通人如何应用贝叶斯法则成为高度成功的预测者的广泛描述感兴趣,我强烈推荐菲利普·e·泰特洛克和丹·加德纳的书《超级预测——预测的艺术和科学》。
基于 Kotlin 的 Android 无张量流贝叶斯文本分类
原文:https://towardsdatascience.com/bayes-text-classification-in-kotlin-for-android-without-tensorflow-d10f1247c23d?source=collection_archive---------20-----------------------
📱移动机器学习
探索没有 TensorFlow APIs 的纯 Kotlin 中的贝叶斯文本分类。
Photo by Luca Bravo on Unsplash
T ext 分类由于其能力和广泛的用途,已经成为自然语言处理中的一项重要任务。我们将学习以非深度学习的方式使用这项技术,而不使用 TensorFlow 和神经网络。这个分类器将在 Android 应用程序中工作,所以需要用 Kotlin 或 Java 编写。
但是为什么是科特林,为什么不是我们的 TensorFlow 或者 Python?
We aren’t using TensorFlow? Because it’s written in C++, models are constructed in Python and we need to run it in Kotlin!
TensorFlow 和 TensorFlow Lite 可以在 Android 上高效地工作(或者有时是在头脑中吹的方式)。类似的算法可以在任何编程语言中创建,如 C、C++甚至Swift(iOS 原生),如果它可以在 kot Lin(Android 原生)中创建的话。
有时,在平台中本地编码的分类器可以比 TensorFlow 或其 API 执行得更好。此外,我们可以对它的工作和推理有更多的控制流。
我们要用哪种机器学习算法?我们到底在创造什么?
我们将使用朴素贝叶斯文本分类器对 Kotlin 中的文本进行分类,该分类器最终将在 Android 设备上运行。
Math is coming! Be ready!
谈论朴素贝叶斯文本分类,
朴素贝叶斯文本分类使用贝叶斯定理的力量将文档(文本)分类到某一类。
Bayes Theorem
如果我们根据我们对文本分类的需要来建立等式,那么它将变成这样,
Eq.1
在这里,我们将文档表示为 x₂x₁令牌...xₙ和 c 是我们将计算概率的类。分母被省略,在这里可以看到它的解释(因为在这两种情况下(C₁和 C₂),P( x₁,x₂...xₙ)将保持不变并将作为归一化常数)
我们将计算两个类别的概率,即垃圾邮件 ( C₁)和火腿 ( C₂)。概率较高的将是我们的输出。
对于每个类,我们都有一个词汇或一组出现在垃圾邮件或垃圾邮件中的单词,它们将代表我们的类语料库。
先说科特林。
If you loved Python earlier!
首先,我们将定义我们的语料库positiveBagOfWords
和negativeBagOfWords
,它们分别包含垃圾邮件和火腿词。
现在,我们创建一个名为Classifier
的新类来处理分类任务。我们需要定义两个常量和一个从给定文本中提取标记的方法(通过删除不必要的单词、标点符号等)。).
getTokens( document ) =令牌。因此,我们可以将文档 d 转换为一组令牌,如 x₁ ,x₂ … xₙ.
寻找概率
首先,我们需要找到 P( C ) 或者类概率。这无非是两个语料库中有多少单词属于类别 C 的概率。
Class probabilities. Eq.2
Calculates Eq.1
接下来,我们需要找到 P( X | C ) 这是 X 的概率,假设它属于一个类别 C 。
在此之前,我们需要一个方法来找到给定文档中的令牌 xᵢ 的 P( xᵢ | C ) 。我们可以用这个方法。
Calculates P( xᵢ | c )
其中
class_vocab
是其中一个语料库。它代表 P( xᵢ | C)中的 c。想知道 1 是从哪里来的?这就是拉普拉斯平滑。如果 P( xᵢ | C)是 0,而 xᵢ在我们的语料库中不存在,那么我们所有的 P( X | C)都可能变成 0。加 1 可以解决这个问题。
现在,我们需要将所有的 P( xᵢ | C ) 相乘,最后乘以 P( C),这是我们在下面方法中的类概率。
Calculates Eq.1
仅此而已。现在我们需要检查哪个类的可能性更大。
在这个要诀里可以一目了然的看到完整的代码。
还有呢!
太长了,有点数学化。结束了!
希望你喜欢科特林的朴素贝叶斯的想法。请在下面的评论区分享您的反馈。
这是我的第一篇数学含量很高的文章,所以请原谅我在精度标注上的错误。😃
快乐的机器学习。
贝叶斯定理与电影评论分析
原文:https://towardsdatascience.com/bayes-theorem-and-movie-review-analysis-fffae437a56?source=collection_archive---------27-----------------------
贝叶斯定理是概率论中的一个基本公式。如果你想知道某个事件发生的概率,我们可以使用一些先验知识和贝叶斯定理来进行计算。
贝叶斯定理
让我们来看看贝叶斯定理:
P(A|B) = (P(B|A) * P(A)) / (P(B))
后验,* P(A|B) :假设事件 B 发生,事件 A 发生的概率*
可能性, P(B|A) :给定事件 A 发生,事件 B 发生的概率。
先验, P(A) :是我们发生的概率。**
P(B) :事件 b 的概率,也改写为 P(B|A) + P(B| Aᶜ) 。
关于可能性与概率的一个注记:
可能性类似于概率,但不是概率。可能性被认为是给定固定数据的假设。然而,我们常常不知道我们所知道的数据是什么样的样本。因此,可能性 P(B|A)度量了一个样本支持这个特定事件的程度。
简单贝叶斯例子
假设,1%的人口患有疾病,并且有针对该疾病的医学测试。如果一个人患有这种疾病,该测试预测他们患有这种疾病的准确率为 87%。如果一个人没有患病,该测试正确地测量出 72%的人没有患病。假设一个人接受了测试,并且测试结果呈阳性,那么他患这种疾病的概率是多少?
**# posterior = P(has disease | positive test)
# likelihood = P(positive test | has disease)
# prior = P(has disease)
# P(positive test) = P(positive test | has disease) * P(has disease) + P(positive test | does not have disease) * P(does not have disease)posterior = (0.87 * 0.01) / (0.87 * 0.01 + (1 - 0.72) * (1 - 0.01))posterior = 0.03**
院长
让我们再多谈谈先验知识。先验是基于我们已经掌握的信息。如果我们对事件的认识改变了呢?假设一项新的研究发现,这种疾病实际上在 3%的人口中流行,而不是 1%。这大大改变了我们的答案,使这种疾病呈阳性结果的概率增加到 8.8%。因此,当我们考虑样本如何反映总体时,当我们有数据集样本时,考虑先验概率是很重要的。
打破朴素贝叶斯
前面的例子只考虑了一个特征和目标,现在我们来想想,如果这个疾病有四个不相关的疾病检测结果呢?如果一个人每次测试都得到阳性结果,那么这说明了患这种疾病的可能性有多大。这就是朴素贝叶斯派上用场的地方。
之所以称之为朴素贝叶斯,是因为它做出了一个在现实中几乎不可能满足的主要假设,这就是所有特征都是独立的且互不影响的假设。假设独立性的一个例子是球的大小不影响球的颜色。然而,这不是一个伟大的假设,因为大多数篮球(相当大)是橙色的,而大多数高尔夫球(相当小)是白色的。同样,朴素贝叶斯作出这种假设是为了使数学更简单,并使计算机程序在初始分类测试中运行得更快。它可能不会是您使用的最终模型,但它是一个很好的起点。
让我们通过一个例子来展示朴素贝叶斯的工作原理。
假设我们想计算在给定评论文本的情况下,在腐烂的西红柿上获得“新鲜”分数的概率(在评论文本中,我们计算每个单词出现的次数)。
- 开始配方。给定评论包含 X 个单词,一部电影是 C=fresh 的概率是多少?这等于新得分包含这些单词的可能性乘以新得分的概率除以单词的概率。
2.使用链式法则,我们可以将似然性 P(X|Ci) 扩展到每个单词在给定条件下依次减少的似然性:
3.由于我们天真地认为单词是相互独立的,因此我们可以简化数学。贝叶斯的独立性法则表明,如果 A 和 B 是独立的,那么 P(A|B) = P(A) 。我们只需要看|和类前的单词。然后我们将这些可能性相乘。这将等式简化为:
4.最后,由于我们的分母是不变的,我们来看看比例性:
“给定该评论文本的电影是新的概率与给定新评论的每个词的可能性乘以新评论的概率的乘积成比例。”
在 Python 中应用朴素贝叶斯
这种数学可能有点复杂和冗长,尤其是对于文本分类。幸运的是 Scikit-learn 有一个内置的库为我们做数学运算。有几种不同类型的朴素贝叶斯分类器,但我们希望使用多项式贝叶斯分类器,因为它测量离散计数(即电影评论中的字数)。我使用了来自这个 Kaggle 数据集的评论。
- 导入必要的库并将数据存储在数据帧中
**import csv
import pandas as pd
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformerdata = []
with open('reviews.tsv', encoding="utf8", errors='ignore') as tsvfile:
reader = csv.reader(tsvfile, delimiter='\t')
for row in reader:
data.append(row)reviews = pd.DataFrame(data[1:], columns=data[0])**
2.清理数据帧。要做的一些改变是将新鲜和腐烂转换为二进制,并将评论和评分存储在自己的系列中。
An initial look at the data
**score_dict = {'fresh': 1, 'rotten': 0}
reviews['fresh'] = reviews['fresh'].map(score_dict)X = reviews['review']
y = reviews['fresh']**
3.在 X 轴和 y 轴上执行训练、测试和分割
**X_train, X_test, y_train, y_test = train_test_split(X, y)**
4.创建一个 CountVectorizer 对象,并将其安装在 X_train 上。不要使用 X,因为我们希望将 X_train 视为我们拥有的唯一数据。使用 stop_words='english '删除不太重要的单词,如“the”、“and”和“that”然后转换 X_train 和 X_test。
**count_vectorizer = CountVectorizer(stop_words='english')
count_vectorizer.fit(X_train)X_train_counts = count_vectorizer.transform(X_train)
X_test_counts = count_vectorizer.transform(X_test)**
5.创建并调整 TfidfTransformer 对象。这将根据每个单词在文档中出现的频率以及在多少个文档中出现来对其进行加权。如果一个单词在文档中出现很多,那么这个值就会增加,因为它可能是一个重要的单词。但是,如果它出现在很多文档中,则价值会降低,因为这个词可能对整体分类影响不大。变换 X_train 和 X_test。
**tfidf_transformer = TfidfTransformer()
tfidf_transformer.fit(X_train_counts)x_train_tfidf = tfidf_transformer.transform(X_train_counts)
x_test_tfidf = tfidf_transformer.transform(X_test_counts)**
6.在 tfidf 训练数据上创建和训练多项式朴素贝叶斯分类器。
**classifier = MultinomialNB()
classifier.fit(x_train_tfidf, y_train)**
7.执行朴素贝叶斯。这一步为你做了所有的计算!我们可以做两件事:第一是严格计算后验概率,第二是得到最可能的结果。我们可以在我们的测试数据上做到这一点,但为了简单起见,让我们看看我写的一篇评论,应该是 fresh 。
**classifier.predict_proba(count_vectorizer.transform(['This is an awesome movie']))# Output: [0.36188785, 0.63811215]classifier.predict(count_vectorizer.transform(['This is an awesome movie']))# Output: [1]**
这个输出意味着这部电影有 0.362 的几率有烂分,有 0.638 的几率有新。它还预测评论是新鲜的。
还有一种使用流水线的替代方法,它压缩了计数矢量化、tfidf 转换和分类器步骤。
**from sklearn.pipeline import Pipelinetext_classifier = Pipeline([('count_vectorizer',
CountVectorizer(stop_words='english')),
('tfidf_vectorizer',
TfidfVectorizer()),
('clf', MultinomialNB())])text_classifier.fit(X_train, y_train)text_classifier.predict_proba(['This is an awesome movie'])
text_classifier.predict(['This is an awesome movie'])**
摘要
贝叶斯定理利用先验知识和事件发生的可能性来预测在其他事情发生的情况下特定结果发生的概率。朴素贝叶斯是一种快速而强大的工具,我们可以用它来对信息进行分类,但它主要是一个起点,因为它做出了一些假设,所以要谨慎使用。它主要用于文本分类,因为数据集很大,非常符合独立性原则。关于代码的更多信息,请查看我在 GitHub 上的库。
我如何学习数学:哑吧的贝叶斯定理?
原文:https://towardsdatascience.com/bayes-theorem-for-dummy-how-do-i-learn-mathematics-e9bff5538cd8?source=collection_archive---------27-----------------------
我是从[1]开始学习 SVM 的,作者提到:“如果你没有读过《朴素贝叶斯》,我会建议你通过 这里 ”来阅读。这让我很好奇,我想我应该浏览一下,因为两年前上完数学课后,我仍然不明白贝叶斯定理,哈哈…
如果你只是想知道贝叶斯定理,跳过这一步
因为我打算攻读计算机科学博士学位,所以我开始阅读大量的研究论文,试图理解数学(尽管一开始很难),并开始在谷歌上搜索大量的数学解释。当我不理解的时候,我坚持去理解。我试着把数学写出来,我试着阅读 10~20 个解释它的资料。
当我开始思考我在高中期间学到了什么但不明白的东西(例如奇怪的 e 常数)时,我搜索了它并试图理解它,结果发现它并没有那么难,只是我的高中和大学讲师没有解释它的起源,如果你对它感兴趣,你可以去这里自己阅读。
我在第一年有机会进入深度学习,然而,我对此一无所知,但现在我可以说,在 Youtube 上观看了斯坦福 CS231n 系列之后,我至少熟悉了深度学习的基础知识。我之前不明白 DL 里的交叉熵,信息论里的熵到底是什么,多亏了[3],终于,我明白了。当你不懂的时候,就试着反复阅读,强迫自己经常谷歌,试着从基础开始学习和耐心点,总有一天你会明白的。
TLDR;如何理解数学
- 耐心(你的决心)
- 从基础开始学习(如果你基础真的很差,请不要急于学习)
- 问问你的讲师、导师或你认识的数学得了 A++++的人(在中国我们称他们为学霸)。
- 谷歌的发明是有原因的,孩子。
贝叶斯定理
一些基础知识
永远记住概率背景下的乘法,等于和。
每当他们说给定某事的概率时,你可以把它们转换成数字。例如,你可以认为你有 100 个球在一个盒子里,其中 50 个是红色的,30 个是绿色的,20 个是蓝色的,因此你得到一个红色球的概率是 50/100 = 0.5(除非你把这个球拿出来,然后放回盒子里,这样盒子里总是有 100 个球,这叫做替换样本)。
你有 3 种不同颜色的球(例如红色、绿色、蓝色)。给定每个球的概率(r=0.5,g=0.3,b=0.2),我们想知道得到 3 个不同颜色的球的概率(意味着一个红色,一个绿色和一个蓝色)。
P(1R & 1G & 1B) = 0.5 * 0.3 * 0.2 = 0.03 =你有 3%的机会得到 3 个不同颜色的球。用话说,我有 50%的机会得到红球,得到一个红球后,我不想再得到另一个红球,我想得到绿色或蓝色。因此,得到一个绿色球的几率是 0.5 * 0.3 = 0.15,或者得到一个蓝色球的几率是 0.5 * 0.2 = 0.1,这意味着我有 10%和 15%的机会得到一个绿色球或蓝色球,或者合计 25%的机会得到非红色球,同样计算最后一个球,得到 3 个不同颜色的 3 个球是极其困难的。 (如果我说错了请指正。)
贝叶斯定理
我实际上是从[2]中理解的,我以他们为例。
P(A|B) = P(B|A) * P(A) / P(B)
P(A) =事件 A 的概率
P(B) =事件 B 的概率
P(A|B) =给定 B 发生的事件 A 的概率
P(B|A) =给定 A 发生的事件 B 的概率
比如我们想知道,当我们看到烟的时候,火灾发生的概率是多少。(我们可能不想知道,但如果你是政府,你希望是否应该在工业区附近建立一个消防站,这可能会有用。)
P(火)=发生火灾的概率
P(烟)=看到烟的概率
P(火|烟)=当我们看到烟时发生火灾的概率
P(烟|火)=发生火灾时看到烟的概率
p(火灾)= 0.01 表示有 1%的火灾。P(烟雾)= 0.1,表示我们看到 10%的烟雾。
P(Smoke|Fire) = 0.9 意思是当火灾发生时,90%的时间我们都能看到烟。
给定贝叶斯叔叔的方程和上面的情况,我们想求 P(火|烟)。
P(火|烟)= P(烟|火)* P(火)/ P(烟)= 0.9 * 0.01 / 0.1 = 0.09 意味着如果我们看到一个工厂冒出烟,就会发生 9%的火灾。
先说 P(烟|火)* P(火)= 0.9 * 0.01=0.009 (0.9%),这意味着有烟发生火灾的概率是 0.9%。我们也可以说,没有烟的火是 0.1%。(0.09 + 0.01 = 0.1 = 1%有烟或无烟火灾)
我们知道看到烟并不意味着有火灾,只能说有机会有火灾。从方程中我们知道,当我们除以 P(烟)时,几率是 9%,P(有烟的火)/P(烟)= 0.009/0.1 = 0.09。超过这 10%的看到烟的机会,我们可以说,我们观察工业区 10000 次,我们看到烟 1000 次(0.1),有 90 次发生火灾(0.009),因此,90/1000 = 9%的机会发生火灾。
换句话说,10000 次我们观察工业区,1000 次我们看到烟,100 次有火灾发生,90 次火灾有烟,10 次火灾没有烟。因此,当我们看到烟时,实际上有 9%的可能性发生火灾。
+-----------+----------------+-------+
| | Fire | No Fire | |
+-----------+----------------+-------+
| Smoke | 90 | 910 | 1000 |
| No Smoke | 10 | 8990 | 9000 |
+-----------+------------------------+
| | 100 | 9900 | 10000 |
+-----------+------+-----------------+Based on this table, total smoke = 1000, fire with smoke = 90, given number of smoke, smoke with fire = 90/1000 = 0.09 = 9%
这就是我对贝叶斯定理的理解。贝叶斯定理有一些修改,
P(A | B)= P(B | A)* P(A)/(P(B | A)* P(A)+P(B | A ')* P(A ')
这个方程基本上和我刚才解释的一样。试着把数字放进去数数,这会帮助你更好地理解问题。
1000 次冒烟相当于 90 次有烟着火+ 910 次无烟着火。
结论
请注意,我们总是可以用一个数字来表示概率,因为这实际上是统计学。
这是我如何理解一个数学公式和贝叶斯定理。希望这篇文章能帮助你理解更多关于贝叶斯定理的知识,并帮助你在统计考试中给这类问题打分。
参考
[1]https://medium . com/machine-learning-101/chapter-2-SVM-support-vector-machine-theory-f 0812 effc 72
[2]https://medium . com/machine-learning-101/chapter-1-supervised-learning-and-naive-Bayes-class ification-part-1-theory-8b9e 361897 D5
[3]https://towards data science . com/demystifying-entropy-f2c 3221 e 2550
贝叶斯定理——一些观点
原文:https://towardsdatascience.com/bayes-theorem-some-perspectives-eeb4421b186e?source=collection_archive---------9-----------------------
“我听到了,我忘记了。我看见了,我记得。我知道,我理解。”――荀子
最近我在读数学史相关的书籍,这让我想起了一个事实,所有看起来复杂的方程都是从一个小的现实世界的问题开始的。研究小问题的好处是,它可以帮助我们忽略树叶,专注于树干,更重要的是,它允许我们在复杂的理论和现实世界的例子之间来回转换。
在这种信念的激励下,我开始将这种策略应用于一个我很久以前就已经学会但我并不十分直观地熟悉并能够快速应用于我在现实世界中遇到的任何情况的定理——贝叶斯定理。正如您所知,贝叶斯定理在数据分析和统计中非常有名,是许多机器学习模型和算法的基础。
我将调查一些小例子,并在下面的部分中尝试给你一些定理的直观解释。虽然下面的讨论对于有统计学背景的人来说可能很熟悉,但我觉得如果你从来没有花时间真正思考和工作,要有一个深刻和直观的理解是很不容易的。为了最大限度地利用这一点,建议您随身携带一支笔和纸,并按照计算结果进行操作。计算非常简单,但是自己写下来可以利用你的肌肉记忆,保证给你留下深刻的印象。
这个问题
首先,我们需要有我们感兴趣的问题,并收集一些数据进行分析。这里会用到一个简单的例子,但是数学是如此的通用,当然你可以把它应用到任何你想要的问题上!
这里我要考察的问题是学历和一个人的财富之间的关系。我感兴趣的一个问题是,如果一个人获得了学士学位,他/她变得富有的可能性有多大?当然,这并不意味着两者之间的因果关系,而只是一个给另一个的可能性。
设置
显然,为了应用这个定理,我们需要定义随机变量和符号。设一个人的财富是随机变量 Y 学历是随机变量 X 。Y 取 Y 的赋值的概率写成 P(Y=y)或 P(Y),Y 取 Y 以外的赋值的概率是 P(Y=~y)或 P(~y)。对于 x 也是一样。
贝叶斯定理被定义为
数据收集和处理
让我们开始收集数据吧!我脑子里马上就能想出一些人。下表显示了它们的相关数据。
Data of the friends I know. Numbers are made up. Ohh...yeah, Elon is my friend, he always talk to me (in youtube) but I am not sure if he also treats me as friend 😦
为了简化,我根据以下规则将数据分类。
你可能会注意到我收集数据方式的一些问题。请参见部分对数据的讨论。我们将暂时忽略这些问题,因为我们主要想对贝叶斯定理有一些直观的理解。
应用贝叶斯定理
我感兴趣的问题是:鉴于我获得了学士学位,成为超级富豪的概率有多大?形式上我是问 P(Y=3|X=2)。根据贝叶斯定理,等于联合概率 P(X=2,Y=3)除以边际概率 P(X = 2)……(1)。我们可以进一步把分子分为 P(X=2|Y=3)P(Y=3),分母分为 P(X = 2 | Y = 3) P(Y = 3)+P(X = 2 | Y = 2)* P(Y = 2)+P(X = 2 | Y = 1)* P(Y = 1)……(2)。
现在,我们可以直接查找数据来确定每个组件的值。例如,为了找出 P(X=2|Y=1),我们首先统计 Y=1 的记录数,在本例中为 5。我们还需要记录 X=2 和 Y=1 的行数,在本例中是 1。所以 P(X=2|Y=1)是 1/5。要计算 P(Y=1),我们只需要统计所有记录中 Y=1 的记录数,也就是 5/10。我们重复这些步骤来确定所有元素的值,从而得到 …(3) 的结果。
一些观察和解释
- 划分条件:观察到分母 P(X=2)被划分为 P(X = 2 |Y = 3)* P(Y = 3)+P(X = 2 |Y = 2)* P(Y = 2)+P(X = 2 |Y = 1)* P(Y = 1)。这是什么意思?意思是X = 2 的世界被分成 Y 的不同设定。观察到,例如 P(X=2|Y=3)*P(Y=3) = P(X=2,Y=3)。现在可以看到 P(X=2)分为{P(X=2, Y=1 )、P(X=2, Y=2 )、P(X=2, Y=3 )}。求和{P(X=2, Y=1 )、P(X=2, Y=2 )、P(X=2, Y=3 )}得出 P(X=2)。用文字来说,持有学士学位的人的世界分为{(持有学士学位并很穷的人),(持有学士学位并拥有中等财富的人),(持有学士学位并超级富有的人)}。忽视富人的状况会让你回到拥有学士学位的人的世界。
- 分子也构成分母的一部分:观察到 P(X=2|Y=3)P(Y=3)在我们把方程改写成… (2) 时同时出现在分子和分母中。P(X=2|Y=3)P(Y=3)其实就是 P(X=2,Y=3)。这意味着我们正在测量感兴趣的关节 P(X=2,Y=3)在分母 P(X=2)世界中的比例,它由其他关节组成,这些关节都是 X=2,但具有不同的 Y 赋值。
- 解读分母中被分割的世界——它们只是比率乘以比例:以……(2)…(3)中带绿色的部分为例(P(X=2|Y=1)*P(Y=1))。P(X=2|Y=1)表示 Y=1 的世界中 X=2 的个数,所以是 1/5(Y=1 的世界中 5 行满足 Y = 1,1 行满足 X=2)。你也可以理解为一个比值:X=2 每 Y=1 的个数。有了这个比例,我们就可以乘以一个适当的比例,P(Y=1),我们数据的宇宙中 Y=1 的个数。现在这个乘法的结果是 X=2 和 Y=1 的人的总数,是的,这是连接点。我们不仅对 Y (Y=1)的一个设置,而且对 Y (Y=1,Y=2,Y=3)的所有设置都这样做。换句话说,绿色部分表示我们试图通过每个中等富裕者拥有学士学位的人数与中等富裕者总人数的比率,找出拥有学士学位和中等富裕者的总人数。
现在你知道分母的组成了。在正常的贝叶斯设置中考虑一下:Y 是我们的模型或信念,X 是我们的数据。分母包括模型世界中数据的可能性与该模型的先验 概率的比值!我们对所有的模型做这些来得到分母,把我们感兴趣的放在分子中,现在我们得到一个叫做后验概率的比例!
在上述理解的帮助下,以下部分将讨论贝叶斯定理如何帮助我们理解人类的偏见。
人类偏见的来源——忽略其他证据
在我看来,贝叶斯定理可以给我们一些线索来解释人类的一些偏见。为什么这样我问你:你觉得正常人能区分条件概率 P(Y|X)和联合概率 P(X,Y)的区别吗?大概不会。人类用眼睛作为传感器来接收信息。我们看到的事情,把一起出现的事情联系起来,这就是有效的联合事件(联合概率)。为了找出条件概率,我们将需要做一些进一步的处理,而人类不太可能这样做,尤其是当他们需要使用他们的“快速系统”做出快速反应时[1]。然而,有时对他们来说,不知道联合和条件是不同的并没有什么害处,他们这样做甚至可能是“正当的”。为什么?因为 P(Y|X)是 P(X,Y)的直接变分,所以人们“有理由”用 P(Y|X)来近似 P(X,Y)。然而,在某些情况下,我们做近似计算是要付出代价的。
让我们研究另一个例子。假设我正在一家位于中央商业区的餐馆吃午饭。我的朋友告诉我,在金融公司工作的人被要求穿西装。这实际上是说条件概率 P(穿西装的人|在金融公司工作的人)高,而我们在金融中心附近所以 P(在金融公司工作的人)也相对高。这样,联合概率 P(一个穿西装的人,一个在金融公司工作的人)也相当高。这时,一个穿西装的人进来了,我很自然地问:那个人在金融公司工作的可能性有多大?
你可能会想,很有可能,对吧?但是概率可能没有你想象的那么高。为什么?因为也有很多律师、政府官员和餐馆工作人员在附近工作,他们都被要求穿西装!(等价的,这是在说 P(穿西装的人,在非金融企业工作的人)= P(穿西装的人|在非金融企业工作的人)*P(在非金融企业工作的人)也“高”。所以,仅仅观察一个人穿西装并不能帮助我们确定这个人在哪里工作。如果我们忽略其他很多人也需要穿西装的反例,我们就很难做出 P(一个在金融行业工作的人|一个穿西装的人)高的判断。
因此,偏差的来源是我们有时忽略了反例。回忆到 P(y|x) = P(x,y)/(P(x,y)+P(x,~y)。如果反例 P(x,~y)很少见,我们可以放心地忽略它,用 P(x,y)来近似 P(y|x)。但是,当反例 P(x,~y)也很常见时,分母变大,P(y|x)变“小”,或者至少没有你最初想象的那么高。
(练习:假设你爸爸有胡子(而且你很久没见到他了)。假设你在街上遇到的人有胡子,那么这个人是你父亲的可能性有多大?)
人类偏见的来源——忽略先验
假设 Y 是一个教授,X 是一个带书的人。
假设我观察到教授们总是喜欢随身带一本书(P(x|y)高)。我坐在餐馆里。一个人带着一本书进来,他是 P(y|x)教授的概率是多少?
嗯,你可能会认为它很高,因为没有多少人带一本书。这可能是真的,但事实是教授非常罕见,我不太可能正常遇到一个(所以 P(y)很低)!如果观察到教授的先验概率非常低,那么 P(y|x)的分子也会非常低!
(练习:观察到头晕的症状,患听神经瘤(一种罕见的癌症)的概率有多大?)
人类偏见的来源——不知道我们在问什么
这个部分的可选标题可以是:混淆 P(X|Y)和 P(Y|X) 或者知道你的问题。一开始,我觉得问“如果我有学士学位,我变得富有的可能性有多大”和“一个富人有学士学位的可能性有多大”几乎是一样的。事实上,这可能完全不同。
如果我有学士学位,我变得富有的可能性是 P(Y=3|X=2)。就是富人和学士学位持有者的比例(P(X=2,Y=3)) 在学士学位持有者的世界里 P(X=2)。
另一方面,富人拥有本科学历的可能性为 P(X=2|Y=3)。就是有钱人和本科学历持有者的比例(P(X=2,Y=3)) 在有钱人的世界里 P(Y=3)。
两种情况下的分子是相同的(P(X=2,Y=3)),但是分母不同。如果分母的世界是一个大的世界(例如 P(X=2)是大的),则有可能存在许多可能的反例(例如 P(X=2,Y!=3)都大),使得兴趣的结果变小(例如 P(Y=3|X=2)变小)。
(旁注:知道了计算 P(X|Y)或 P(Y|X)都需要 P(X,Y),你在做推断和预测的时候就知道找到一个联合分布 P(X,Y)的灵活性、重要性和威力了。可以将 P(X,Y)除以 X 求和得到 P(Y)来帮助你计算 P(X|Y),也可以将 P(X,Y)除以 Y 求和得到 P(X)来帮助你计算 P(Y|X)。当然,P(X,Y)也称为生成模型,很难建模。)
对数据的讨论
我使用的数据收集方法不是随机抽样。如果我关注的人群是所有人,但我只包括我熟悉的人,这就有问题了。这些样本对整个人口来说不够有代表性。
此外,我离散化连续数据(净值)的方式是主观的,可能对结果有很大影响,特别是如果数据集很大的话。
这里不讨论的事情
在上面的例子中只使用了两个随机变量,它们都是离散的。这样做是为了让我们专注于主干,并理解贝叶斯定理的计算。然而,当涉及更多随机变量时,还有一些更有趣的情况,在概率图形模型领域更明显,这也是我正在研究的领域。
为简单起见,这里不讨论概率分布模型。贝叶斯统计将概率分布的参数视为随机变量,这一点也没有提到。
结论
本文使用了几个简单的现实生活中的例子来介绍贝叶斯定理的概念和计算,并了解为什么会出现一些人类偏见。我希望这篇文章能为你明确这个方程,让你对这个重要的定理有更深的理解!
感谢您的时间,我很想知道您的想法:)
参考
[1]丹尼尔,K. (2011 年)。思考,忽快忽慢。美国纽约艾伦巷。
[2]布利兹泰因,J. K .,&黄,J. (2014 年)。概率介绍。查普曼和霍尔/CRC。
数据科学专业人员的贝叶斯定理及示例
原文:https://towardsdatascience.com/bayes-theorem-with-example-for-data-science-professionals-55b4d52f8967?source=collection_archive---------8-----------------------
贝叶斯定理是条件概率的推广。条件概率帮助我们确定给定 B 的概率,用 P(A|B)表示。所以贝叶斯定理说,如果我们知道 P(A|B ),那么我们可以确定 P(B|A ),因为 P(A)和 P(B)是已知的。
在这篇文章中,我将专注于贝叶斯定理,假设你对条件概率有很好的理解。如果你想修改你的概念,你可以参考我之前关于条件概率的文章,并举例。
公式推导:
根据条件概率,我们知道
- P(A|B) = P(A 和 B)/P(B)
- P(A 和 B)= P(B)* P(A | B)———[ 1]
类似地
- P(B|A) = P(B 和 A)/P(A) = P(A 和 B)/P(A)[按联合概率顺序不重要]
- P(A 和 B)= P(A)* P(B | A)—-[2]
根据等式[1]和[2],
- P(B) * P(A|B) = P(A) * P(B|A)
- P(A|B) = P(A) * P(B|A) / P(B)
这意味着如果我们知道 P(A|B ),那么我们可以很容易地确定 P(B|A ),反之亦然。假设我们知道总概率 P(A)和 P(B)。
更广义的定义:
设 A1,A2,A3… Ak 是互斥且穷尽的事件的集合,概率为 P(Ai),I = 1,2,3…k。那么对于 P(B) > 0 的任何事件 B
P(Ai|B) = P(Ai 和 B)/P(B)= P(B | Ai)* P(Ai)/∑[P(B | Ai)* P(Ai)
下面是贝叶斯定理的树形表示。
现在让我们解决一些例子来感受一下贝叶斯定理。
示例 1
当自动化生产线出现故障时,技术人员会定期进行维修。Janak 负责维修 20%的故障,20 次维修中有 1 次是不完全维修。Tarun 为 60%的故障提供服务,10 次中有 1 次是不完全维修。为 15%的故障提供服务的 Gautham 每 10 次中有 1 次不完全修复,而为 5%的故障提供服务的 Prasad 每 20 次中有 1 次不完全修复。对于被诊断为由于初始维修不完整而导致的生产线的下一个问题,Janak 进行初始维修的可能性有多大?
解决方案:
首先,让我们尝试使用概率树来可视化。
实施例 2 临床试验
流行病学家声称,50 多岁的白人女性患乳腺癌的概率为 0.005。一项已建立的测试识别了乳腺癌患者和健康人。一种新的临床试验中的乳房 x 光检查正确检测癌症的概率为 0.85。在没有乳腺癌的女性中,阴性结果的几率为 0.925。如果一名 55 岁的高加索妇女乳腺癌检测呈阳性,那么她实际上患乳腺癌的概率是多少?
解决方案:
- p(癌症)= 0.005
- p(测试阳性|癌症)= 0.85
- p(测试阴性|无癌症)= 0.925
- P(癌症|测试阳性)= P(癌症)* P(测试阳性|癌症)/ P(测试阳性)
给定问题的概率表和树形可视化
示例 3
SpamAssassin 的工作原理是让用户训练系统。它在被用户标记为垃圾邮件的电子邮件中寻找单词模式。例如,它可能已经知道“免费”一词出现在 20%被标记为垃圾邮件的电子邮件中。假设 0.1%的非垃圾邮件包含“免费”一词,用户收到的所有邮件中有 50%是垃圾邮件,请找出如果“免费”一词出现在邮件中,该邮件是垃圾邮件的概率。
解决办法
给出的数据:
- p(免费|垃圾邮件)= 0.20
- p(免费|非垃圾邮件)= 0.001
- P(垃圾邮件)= 0.50 => P(非垃圾邮件)= 0.50
- p(垃圾邮件|免费)=?
使用贝叶斯定理:
- P(垃圾邮件|免费)= P(垃圾邮件)* P(免费|垃圾邮件)/ P(免费)
- p(垃圾邮件|免费)= 0.50 * 0.20/(0.50 * 0.20+0.50 * 0.001)
- p(垃圾邮件|免费)= 0.995
现在使用概率树进行可视化:
这就是数据科学中的贝叶斯定理。在接下来的文章中,我将会写概率分布,这将会完成数据科学的概率系列。
数据科学概率系列之前的文章有:
- 数据科学的概率基础知识
- 条件概率
我希望你喜欢这篇文章。对于任何意见,请使用下面的评论部分给我回信,或者您也可以使用【https://ashutoshtripathi.com/contact/】的直接给我写信。我会尽量回答你所有关于 DS,ML,AI 的疑问。
谢谢大家!
原载于 2019 年 8 月 20 日http://ashutoshtripathi.com。
用 Python 进行贝叶斯 A/B 测试:简易指南
原文:https://towardsdatascience.com/bayesian-a-b-testing-with-python-the-easy-guide-d638f89e0b8a?source=collection_archive---------4-----------------------
如果你登陆了这个页面,你已经知道什么是 A/B 测试,但是也许你对如何在贝叶斯框架内分析结果有一些疑问。
在这篇文章的开始,那么,让我指出贝叶斯方法与经典的“频繁主义者”方法的实际区别:区别在于你实际上想要研究的度量的形式。对于常客来说,这是一个简单的数字,而对于贝叶斯人来说,这是一个分布。
虽然用分布代替数字看起来只是一个复杂的问题,但它在很多情况下非常有用,在 A/B 测试中也是如此。通过这篇文章,你会发现在实践中处理起来并不困难。事实上,只有几行代码。
Edit 18/01/2018:该页面代码已成为与Mixpanel配合使用的 A/B 测试工具的基线。
直奔主题
我答应了一个简单的向导。因此,在这一部分中,我将只向您展示代码,在下一部分中,如果您感兴趣,您将看到隐藏在它背后的一些细节。
请注意,没有使用任何近似方法:没有马尔可夫链蒙特卡罗(MCMC),或任何其他随机(和缓慢)过程。因此,不需要主动的编程框架。
让我们来介绍一下样本数据:我们已经运行了一个 A/B 测试来检查一个网页的转化率(CR,从现在开始),结果在下面的表 1 中。
Table 1: The data
这是代码。你只需要安装 Scipy 和 Numba,插入你的数字,你就会得到你的结果。
和模块导入的内容,calc_prob.py
:
根据表 1 中的数字,测试选项的性能比控制选项好得多:几乎提升了 60%,有超过 98%的可能性更好。
如你所见,这些都是赤裸裸的、不可知的结果。他们是好是坏取决于你的情况。关于阈值的更深入的考虑将在另一篇文章中讨论,但是就概率而言,任何高于 95%的值都足够好了。
很简单,对吧?现在让我们深入了解一下细节。
细节
在代码中,我初始化了两个“Beta”函数,每个选项一个,用我们在表中的数字填充它们:
这些实际上是为 A/B 测试建立数据模型的函数。为了更好地介绍它们的行为,请查看下面的动画:
Figure 1: animation of the Beta distribution for a fixed CR. The ‘X’ axis has been zoomed.
每个函数都建立在平坦的、无信息的函数之上,由β(1,1)定义。我们在这个基础上增加的信息(数据)越多,这个函数就变得越窄。
现在你大概在想:真的这么简单吗?为什么存在一个看起来完全是为模型 A/B 测试而构建的函数?
答案在于贝叶斯定理的精确性。在不深入细节的情况下,贝叶斯定理的解通常很难(如果不是不可能的话)精确求解,这就是为什么很少有近似方法被开发出来,如马尔可夫链蒙特卡罗(MCMC)。你可以在网上找到很多使用这种方法的文章。
但是 A/B 测试是一个幸运的案例,我们实际上可以基于"共轭先验"的概念得到一个精确的解。当这个概念适用时,贝叶斯定理的后验函数与前一个后验函数属于同一族,因此我们可以通过迭代过程来构建最终函数。
A/B 测试是随机实验,只有两种可能的结果,“转换”或“不转换”,因此被描述为伯努利试验,贝塔分布是这种过程的共轭先验。这就是为什么我们敢用我所用的简单方法来使用它。但是如果你仍然有疑问和/或你想更深入地挖掘,你可以在这里查看数学细节:维基百科页面上的例子正是我们的例子。
回到我们的例子,让我给你看两个分布:
Figure 2: distributions for the two CR.
您可以注意到,两个分布的峰值与您以经典方式计算的值一致:
如前所述,不同之处在于 CR 有一个完整的概率密度函数( PDF ),而不是一个简单的数字。由于这一点,你可以计算,例如,CRs 上的方差(俗称“误差”),它也显示在图中的标签上。
现在,您可以计算所谓的“提升”,即相对于控制选项,测试选项增加了多少 CR:
但是,在这一点上,你需要评估这个结果的可信度。怎么会?嗯,你可以估计一个选择比另一个更好的概率!
注意,在经典的“频率主义者”范式中,你没有办法计算这样的概率。在这种方法中,你通常会计算“ p 值”,然后检查它是否落在任意选择的阈值之下(“α值”,通常为 5%),最终你可以宣布一些几乎不可能向任何经理/客户/董事会解释的事情:“在 95%的置信水平下,我们可以拒绝零假设”。然后,你必须解释这个声明与“这个假设比另一个有 95%的可能性更好”是非常不同的,这正是他们真正想从你那里听到的句子。
但是现在我们在贝叶斯世界里,我们可以这么说。事实上,我们有定义 CR 的 pdf,概率由曲线下的面积给出。实际上,这就是 PDF 的定义。
一个简单的例子:你希望测试选项的 CR 的概率大于 0.003 吗?它只是测试曲线下 0.003 和 1.0 之间的区域,在图 3 中用阴影表示。
Figure 3: The probability for the Test option CR to be greater than 3E-03.
在数学语言中,你通过在两个极限之间的曲线上积分来计算面积:0.003(我们选择的极限)和 1(硬极限)。
借助 Python,我们可以精确地计算这个积分(仍然:不需要蒙特卡罗),这是由 Mpmath 库提供的:
在这个例子中,我们只考虑了一个分布(测试分布),但是为了测量我们提升的可信度,我们必须考虑两个分布(控制和测试),因此为了可视化这种情况,我们必须增加一个维度。因此,我们要测量的概率不再由面积来定义,而是由体积来定义。特别是,试验组和对照组在联合概率分布下的体积大于对照组。让我们看看它是什么:
Figure 4: the Joint PDF of the two options. Left: 3-d visualization. Right: view from the top (zoomed). The gray plane (or line, in the 2-d) separate the zone where the Test dominate the Control.
把图 4 左边的图想象成一座山的图片,右边的图是从卫星上看到的。关注右侧的地块,您可以看到灰色线是属于测试选项(上方三角形)的土地和控制选项的土地之间的边界。在这种情况下,问题就变成了:测试比控制多了多少山?
更新(13/05/2019) :因为我有几个关于这个的请求,下面你可以找到重建图 4 情节的代码,对吧。这使用蒙特卡罗抽样,需要大量的点来产生一个好看的图形:
Code for creating the right plot of the Figure 4.
为了计算这个量(在图 4 的上三角中),我在网上看到了很多帖子,这些帖子也使用了近似的方法(比如蒙特卡罗)。好吧,写它们的人不知道约翰·库克已经在 2005 年部署了一个精确的方法(第二章,这里)。模块calc_prob.py
中的代码复制了这个公式,并且几乎完全来自最初由 Antti Rasinen 编写的版本。
在我们的例子中,面积是 0.98,这意味着“测试”选项以 98%的概率比“控制”选项表现得更好。
让我强调一下,如果结果本质上是 50%,那么这座山是完全共享的,这意味着没有选项比另一个更好,而较小的值意味着测试选项实际上比控制选项更差。
仅此而已。
如你所见,这篇文章开头的几行代码背后的细节很深奥,而且不那么简单。但是我希望我已经清楚简单地描述了这些概念,正如我在标题中所说的。
贝氏盗匪简单地解释道
原文:https://towardsdatascience.com/bayesian-bandits-explained-simply-a5b43d9d5e38?source=collection_archive---------6-----------------------
Photo by Alice Wu on Unsplash
探索还是剥削?
勘探和开发在任何业务中都起着关键作用。
任何好的企业都会试图“探索”各种可以盈利的机会。
同时,任何优秀的企业也会努力专注于已经发现的特定机会,并努力“利用”它。
让我用一个思维实验来进一步解释这个问题。
思想实验: 假设我们有infinite
老丨虎丨机。每个吃角子老丨虎丨机都有一些获胜概率。但是我们不知道这些概率值。
你必须一个接一个地操作这些老丨虎丨机。你如何想出一个策略,在最短的时间内从这些吃角子老丨虎丨机中获得最大的收益。
你最有可能从试用一些机器开始。
你会坚持使用一台有一定可能性的机器(开发)还是继续寻找更好的机器(探索)?
这是勘探开发的权衡。
问题是我们如何平衡这种权衡,从而获得最大利润?
答案是贝氏盗匪。
为什么?业务使用案例:
有很多地方可以进行这样的思维实验。
- AB 测试:你有各种各样的资产可以在网站上展示。每个资产都有特定的成功概率(被用户点击)。
- 广告点击:你有各种各样的广告可以展示给用户。每个广告都有特定的点击率
- 金融:选择哪只股票回报最高。
- 作为人类,我们面临着完全相同的问题——探索或开发,我们大多处理得相当出色。我们是应该去找一份新工作,还是应该做我们知道会赚钱的事情来赚钱?
在这篇文章中,我们将集中讨论 AB 测试,但是这个实验可以解决上面的任何问题。
问题陈述:
我们的问题是,我们有不同的资产,我们想在我们的网站上展示,但我们真的不知道该展示哪一个。
一个资产是蓝色(B),另一个是红色(R),第三个是绿色(G)。
我们的 UX 团队说他们喜欢蓝色的。但是你喜欢绿色的。
在我们的网站上显示哪一个?
贝叶斯无处不在:
在我们深入研究解决这个问题的算法之前,让我们重温一下贝叶斯定理。
记住贝叶斯定理说后验概率*先验
贝塔分布
我们只需要一个小小的尝试来理解贝塔分布。β分布是定义在区间[0,1]上的连续概率分布,该区间由两个正的形状参数参数化,用 α 和 β表示。贝塔分布的 PDF 为:
并且,对于 α 和 β 的不同值,pdf 看起来如下:
如果您还不了解 beta 分布,请不要担心。
请记住,贝塔分布经常用于模拟概率的行为,因为它位于范围[0,1]内。
贝叶斯强盗
所以在了解了上述概念之后,让我们回到我们目前的问题上来。
我们有三项资产。
为了解决这个问题,让我们假设我们也知道这些资产的点击概率。
蓝色(B)获胜概率是 0.3,红色(R)是 0.8,绿色(G)是 0.4。请注意,在现实生活中,我们不会知道这些。
我们的算法会隐藏这些概率,我们会看到我们的算法如何收敛到这些真实的概率。
那么,我们对这些资产的概率有什么先验(信念)?
因为我们没有观察到任何数据,所以我们不能对我们的三个资产中的任何一个有先验的信念。
我们需要对我们的先验概率建模,我们将使用 beta 分布来完成。 参见上述α = 1 和β=1 的β分布曲线。
它实际上只是在范围[0,1]上的均匀分布。这就是我们想要的资产的先验概率。我们还没有任何信息,所以我们从概率值的均匀概率分布开始。
所以我们可以用贝塔分布来表示我们每个资产的先验概率。
策略:
- 我们将从资产的 3 个分布中随机抽取一个变量。
- 我们将找出哪个随机变量是最大的,并将显示给出最大随机变量的资产。
- 我们将了解该资产是否被点击。
- 我们将使用步骤 3 中的信息更新资产的先验信息。
- 重复一遍。
更新以前的:
我们用贝塔分布来模拟概率的原因是因为它有很好的数学特性。
如果先验是 f(α,β),那么后验分布也是β,由 f(α+#成功,β+#失败)给出
其中#success 是点击次数,而#failures 是浏览量减去点击次数。
让我们编码
现在,我们已经具备了编写代码所需的所有知识。我将使用非常简单和标准的 Python 功能来做这件事,但是也有像 pyMC3 这样的工具来处理这类问题。
让我们一步一步地解决这个问题。
我们有三种不同概率的资产。
real_probs_dict = {'R':0.8,'G':0.4,'B':0.3}
assets = ['R','G','B']
我们将努力看看我们上面给出的策略是否奏效。
让我们多次运行这个策略并收集数据。
这是我们跑步的结果。你可以在 kaggle 看到我用来可视化后验分布的函数。正如您在下面看到的,在 20 次运行结束时,我们几乎已经收敛到最佳资产。概率也是粗略估计出来的。
在开始时,我们有一个制服在先。 当我们运行时,我们看到“红色”资产的后验分布向更高的平均值收敛,因此选择的概率更高。但请记住,这并不意味着绿色资产和蓝色资产永远不会被选中。
让我们看看在我们做的 50 次运行中,每种资产被选择了多少次。
Pick 1 : G ,Pick 2 : R ,Pick 3 : R ,Pick 4 : B ,Pick 5 : R ,Pick 6 : R ,Pick 7 : R ,Pick 8 : R ,Pick 9 : R ,Pick 10 : R ,Pick 11 : R ,Pick 12 : R ,Pick 13 : R ,Pick 14 : R ,Pick 15 : R ,Pick 16 : R ,Pick 17 : R ,Pick 18 : R ,Pick 19 : R ,Pick 20 : R ,Pick 21 : R ,Pick 22 : G ,Pick 23 : R ,Pick 24 : R ,Pick 25 : G ,Pick 26 : G ,Pick 27 : R ,Pick 28 : R ,Pick 29 : R ,Pick 30 : R ,Pick 31 : R ,Pick 32 : R ,Pick 33 : R ,Pick 34 : R ,Pick 35 : R ,Pick 36 : R ,Pick 37 : R ,Pick 38 : R ,Pick 39 : G ,Pick 40 : B ,Pick 41 : R ,Pick 42 : R ,Pick 43 : R ,Pick 44 : R ,Pick 45 : B ,Pick 46 : R ,Pick 47 : R ,Pick 48 : R ,Pick 49 : R ,Pick 50 : R
我们可以看到,虽然我们大多选择 R,但在后面的运行中,我们有时还是会选择 B(选择 45)和 G(选择 44)。总的来说,我们可以看到,在最初的几轮中,我们专注于勘探,而在后面的几轮中,我们专注于开发。
结束注释:
我们看到了使用贝叶斯方法解决这个问题如何帮助我们收敛到一个好的解决方案,同时最大化我们的利润,并且不丢弃任何资产。
这种方法的额外优点是,它是自我学习的,并且如果点击红色资产的概率降低而蓝色资产增加,它可以自我校正。例如,当用户偏好改变时,这种情况可能发生。
全部代码贴在 Kaggle 内核里。
另外,如果你想了解更多关于贝叶斯统计的知识,你可以关注的最新和最好的资源之一是用于机器学习的 贝叶斯方法 。
我以后也会写更多这样的帖子。在 媒体 关注我或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系。
贝叶斯篮球:多伦多真的是 NBA 2019 赛季期间最好的球队吗?
原文:https://towardsdatascience.com/bayesian-basketball-were-the-toronto-raptors-really-the-best-team-during-nba-2019-season-e524a26b43a1?source=collection_archive---------19-----------------------
让我们回到过去,看看我们是否能为 NBA 2019 年的冠军找到一个不同的赢家。怎么会?
通过使用贝叶斯模拟。
Photo by Markus Spiske on Unsplash
【本文灵感来源于 Baio 和 Blangiardo (2010)的作品,Daniel Weitzenfeld 的伟大博客 文章 ,以及 Peadar Coyle 的 教程 关于层次模型。】
介绍
贝叶斯模拟很大程度上依赖于统计分布来模拟结果,因此是一种模拟场景的工具。它的基础是贝叶斯定理。贝叶斯公式包含 4 个部分:后验、先验、似然和证据。深入每一个细节并不是本文的目标,但请记住这个过程如下:从我们认为模拟我们观察到的现象的先验 分布开始(想想“扔硬币”),我们收集数据(可能性,并使用该数据更新我们对分布的先验信念,并将其转化为后验分布。
为什么适合我们的案例研究?
我们想要估计每个团队的实力,并且能够用这些信息运行模拟。我们能得到的唯一信息就是分数。我们事先不知道每个队的实力(即我们说这是一个潜在变量),但我们知道,如果我们有一个队的实力,我们可以选择另一个队,比较他们的实力,看看哪一个将赢得对抗。最后但同样重要的是,为了评估一支球队的实力,我们使用分数,但这些数据可能会有噪音:它可能不会揭示一支球队在特定时刻的真实实力,例如,如果它最好的球员受伤了,等等。希望贝叶斯能够帮助我们,因为贝叶斯模拟允许我们:
- 给定观测值的模型潜在变量
- 得到变量的分布,而不是点估计,如果我们想考虑不确定性,这很好
- 从获得的分布(我们现象的生成模型)中取样,以模拟新的观察结果
回到过去
现在你确信贝叶斯模拟是我们需要的,我们将及时后退一步,回到 2019 年 4 月 12 日。
常规赛刚刚结束,季后赛明天就要开始了。NBA 联盟的 30 支球队都打了 82 场比赛。我们需要这些数据来构建贝叶斯模型,以便评估每个团队的实力。
一旦我们掌握了每支球队的实力,我们将模拟几个季后赛场景,看看最终哪支球队获胜。准备好了吗?
收集数据
这些数据是从网站https://www.basketball-reference.com收集的,在那里你可以获得 2019 赛季的所有结果。我们把所有东西都存储在一个数据帧中,并确保我们只保留常规赛的比赛。
然后,我们将所有团队映射到一个唯一的 id:
准备模型
模型取自 Baio 和 Blangiardo(此处的论文)。这是一个简单的对数线性模型,允许模拟任何两队对抗的比赛。它是这样工作的:
- 对于给定的游戏,分数可以建模为 (y1,y2) ,其中每个 yi 取自泊松分布(提醒:泊松分布是一种离散值分布,用于对固定时间段内的计数事件进行建模)。
- 给定 yi 的每个泊松分布由比率θ(I)参数化,比率θ(I)表示团队的攻击强度和对手的防御强度的组合。
- 因此,如果 A 队进攻强,而 B 队防守弱,则θ(A)将会很大,因此从泊松(θ(A))分布获得的样本也将会很大。从而增加了 a 队的得分
- 为了确保θ为正,我们将其建模为对数线性方程。
Baio and Blangiardo paper excerpt
瞧!
选择先验
现在我们有了将观察到的分数与泊松相关联的模型,因此θ,我们必须对等式的和 def 部分建模。在我们的例子中,我们认为攻击强度 att 和防御强度 def 应该平均为零。强队的价值高于零,弱队的价值低于零。
此外,我们对 att 和 def 没有先验信念,因此我们将使用一个正态先验,其平均值取自一个允许值接近于零的超先验(在 cour 情况下,是一个围绕零的高度偏斜的正态)。对于正态先验的标准差,我们将使用超先验,它允许标准差的小正值(在我们的例子中,它是伽玛分布)。
模型如下:
顶部的圆圈, mu 和 tau,是我们的超先验。这个模型被称为分层贝叶斯模型。
这是代码:
请注意我们是如何忽略等式中的“home”参数以及我们是如何添加“intercept”参数的。
运行蒙特卡洛
PyMC3 使用蒙特卡罗马尔可夫链为我们的模型寻找合适的分布。解释 MCMC 已经超出了本文的范围,但是如果你想了解更多,我可以推荐 Thomas Wiecki(pymc 3 的主要贡献者之一)的这篇优秀的文章。
运行 MCMC 采样器后,我们直观地检查我们的分布。如果给定变量的分布重叠,这是一个好现象,表明 MCMC 已经收敛到一个稳定的解。检查收敛的另一种方法是通过查看图形右侧的轨迹,看这些轨迹是否像白噪声(即趋势没有变化,幅度没有变化)。
In convergence we trust
看到每个变量的分布是如何重叠的了吗?当然,还有其他检查收敛的方法,其中之一是 R-hat 统计。您可以通过绘制给定参数的森林图来查看它:
***
Teams attacks (left) and defense(right)*
R-hat 在所有情况下都是 1,这表明我们的算法已经收敛。根据这些图表,我们可以看到哪些球队的进攻和防守最好(小心:符号是反着做防守的!好的防守有负分!):
- 攻击:密尔沃基,金州,新奥尔良
- 防守:印第安纳,孟菲斯,迈阿密
让我们总结一下散点图(为了更好的可读性,我颠倒了防御的符号:好的防御=正得分):
红标:有资格进入季后赛的球队。蓝点:西部联盟;绿点:东部联盟。
根据上面的图表,密尔沃基似乎有最强的进攻,总的来说防守“一般”。多伦多猛龙的攻击强度明显较低,防守强度略高。
现在我们有了每个队的进攻和防守强度分布,我们可以模拟游戏了!如果我从这些分布中取样,我可以计算
- score _ A = sample _ 泊松(sample _ attack(A)+sample _ defense(B)+intercept _ mean)
- score _ B = sample _ 泊松(sample _ attack(B)+sample _ defense(A)+intercept _ mean)
比较 score_A vs score_B 可以让我得到胜者!
代码如下:
模拟季后赛
基于常规赛结果(记住,我们目前是 4 月 12 日!),下面是我看到的:
根据这些排名,我知道第一轮季后赛将会是:
下面是一个场景的过程:
- 对于第一轮配置中的每场比赛,我们为每支球队计算 7x2 个样本(7 次进攻,7 次防守),以了解 7 场比赛的获胜者(不允许平局)。我们保留 8 名获胜者。
- 然后我们有一个胡人配置。(还剩 8 支队伍)
- 对于半决赛中的每场比赛,我们为每支球队计算 7x2 个样本(7 次进攻,7 次防守),以了解 7 场比赛的获胜者(不允许平局)。我们保留 4 个获胜者。
- 然后,我们有一个会议决赛配置。(还剩下 4 支队伍)
- 对于大会决赛中的每场比赛,我们为每支球队计算 7x2 个样本(7 次进攻,7 次防守),以了解 7 场比赛的获胜者(不允许平局)。我们保留两个赢家。
- 这样我们就有了两支球队的 NBA 总决赛。
- 我们再次计算 7 场比赛的样本,以得出最终的赢家
结果
下面是我们运行 1000 次季后赛模拟的结果:
Outcomes of 1000 playoffs simulations
密尔沃基在超过 25%的情况下赢得冠军!超过 15%的情况下,多伦多会赢。Golden Stats 以大约 15%的胜率排名第三
说明
常规赛期间由于分区不平衡,数据略有偏差。因此,密尔沃基很可能来自一个“弱”的分区,因此高估了进攻和防守的实力。同样,多伦多的分区在实力上更加均衡,因此被低估了。让我们比较一下密尔沃基和多伦多的分区:
结论
希望你在重温 NBA 2019 季后赛时玩得开心。请随意分享对结果的任何想法,以及你将如何在我们的模型中加入“除法”效应来解释不平等的除法水平!
使用 Fastai 的贝叶斯深度学习:如何不确定自己的不确定性!
原文:https://towardsdatascience.com/bayesian-deep-learning-with-fastai-how-not-to-be-uncertain-about-your-uncertainty-6a99d1aa686e?source=collection_archive---------1-----------------------
Bobby Axelrod speaks the words!
今天,神经网络已经成为许多领域的头条新闻,如癌症组织的图像分类,文本生成,甚至信用评分。然而,这些模型很少解决的一个大问题是预测的不确定性。
当我们人类学习时,我们最大的优势之一是知道我们的弱点,并且在有太多不确定性时不采取行动。然而,对于大多数机器学习模型来说,情况并非如此,在这些模型中,决策是在没有考虑不确定性的情况下做出的。
例如,如果你训练一个关于猫和狗的分类器,它将只能输出猫或狗。但如果你给它一张卡车的图片,模型仍然会做出预测,有时概率很大,即猫的概率接近 1,狗的概率接近 0,而你的模型应该简单地说“好吧,这是我无法识别的东西”。当我们着眼于医疗应用时,这一点尤其重要,因为医疗应用必须处理不确定性。
因此,理想情况下,我们希望有一种方法在我们的模型中添加不确定性评估,以便知道模型何时不应做出决定,并将其传递给能够做出正确决定的人,以帮助模型学习。这被称为主动学习,我们将在另一篇文章中讨论这个话题。
最后,获得不确定性的度量是非常可取的,因为这是我们人类所拥有的,而大多数模型都缺乏。在本文中,我们将看到如何在我们的模型中用几行代码实现这一点,并看到流行任务的结果,如情感分析、图像分类或信用评分。
一.快速浏览贝叶斯神经网络
Bayesian Neural Networks seen as an ensemble of learners
贝叶斯神经网络(BNNs)是一种在我们的模型中增加不确定性处理的方法。这个想法很简单,我们不是学习确定性权重,而是学习随机变量的参数,我们将使用这些参数在前向传播过程中对权重进行采样。然后,为了学习参数,我们将使用反向传播,有时用一点小技巧使我们的参数可微。
Comparison of a standard NN with a Bayesian NN
这张图可以帮助你理解其中的区别。虽然常规 NN 通过将预测损失反向传播到权重来学习权重,但这里我们使用分布的参数(这里是高斯分布)对 W 进行采样,并照常进行,但这次我们一直反向传播到高斯分布的参数(这里是均值和方差)。
尽管乍一看,使用随机变量而不是确定性权重来对权重进行采样似乎很奇怪,但如果您认为这不是一个单一的网络,而是一个潜在的无限网络集合,这实际上是有意义的。
事实上,每次你对你的网络的权重进行采样,就像从一个群体中采样一个批评家,并且每次向前传递可以有不同的输出,因为对于你采样的每个批评家。即使你可能有大量(甚至无限)的批评者,每个批评者都将帮助整个群体变得更好,因为我们将对这个给定批评者的表现使用反向传播,以适应整个群体的参数。在上面的例子中,我们不是只学习 W ,而是学习 W 的均值和方差。
所以最后,使用贝叶斯神经网络时的训练过程如下:
- 从 BNN 分布的随机参数开始,即使用一些参数初始化您的总体,例如,如果您想要高斯权重,从 0 均值和单位方差开始。
- 对于训练循环中的每一批:
-根据与每一层相关的分布对你的体重进行抽样。
-使用这些权重进行正向传递,就像使用常规网络一样
-将损失反向传递给生成权重的分布参数
数学细节将在另一篇文章中解释,这里我们将只关注 bnn 如何工作的全局思想,所以如果你记得 bnn 的行为就像一种神经网络的集合,这已经是很好的一步了!
那么最后,为什么我们要学习权重的概率分布,而不是直接学习权重呢?有两个主要原因:
- 首先,这防止了过度拟合
- 第二,这允许我们得到不确定性估计
我们将更详细地讨论第二点。事实上,因为我们的模型本质上是随机的,所以对于相同的输入,我们的模型可以有不同的输出,因为对于每个前向传递,我们将有不同的权重被采样,因此可能有不同的输出。
然后,您可以选择采样 T 次,这样您将拥有 T 不同的权重,以及 T 不同的输出。因此,您现在可以通过对这些结果进行平均来进行投票,但是您也可以计算方差来查看您的模型之间的一致程度!
通过相同输入的预测方差,贝叶斯神经网络能够输出关于其预测的不确定性。让我们来看看下面这个简单的回归问题:
Source : http://www.cs.ox.ac.uk/people/yarin.gal/website/blog_3d801aa532c1ce.html
这里,我们使用蓝色虚线之前的训练数据点,并要求模型预测虚线之前和之后的点。我们训练一个贝叶斯神经网络,输出几个我们平均的估计值,并基于方差用置信区间来绘制它。
有趣的是,我们注意到模型在左侧输出的点没有任何差异,正如在训练期间所看到的那样,模型对其预测很有信心,但之后,随着我们看到的点离我们的训练集越来越远,差异也在增加。
这是意料之中的,因为我们不知道虚线之外是什么,所以我们越往前走,不确定性越大的模型是合理的。
现在我们已经了解了贝叶斯神经网络的原理,以及如何使用它们来输出模型的不确定性,我们将看到一种简单的方法,用几行代码就可以使您的模型贝叶斯化!
二。辍学作为一种方式,使你的 NNs 贝叶斯
Dropout 是一种流行的正则化技术,其目标是通过在给定层中随机将激活设置为零来帮助减少过拟合。
Illustration of Dropout from the paper “Dropout: A Simple Way to Prevent Neural Networks fromOverfitting”
这个想法很简单,我们不希望让一些神经元变得过于专业,只依赖这些神经元进行预测,因此我们在我们的层中随机置零神经元,每层都有不同的丢失概率 p 。这样,没有神经元变得过度专业化,这是一种确保所有神经元都对预测做出贡献的方法,而不会过度拟合。
Dropout 通常以下列方式使用:
- 在训练过程中,我们激活 Dropout,这意味着我们每一层都有不同的概率丢弃神经元。一旦神经元被丢弃,我们通常会除以保留神经元的概率,以保持相同的数量级。
- 在推理过程中,我们停用丢弃,因此我们使用所有的神经元,并且我们的输出是完全确定的,因为随机丢弃神经元的随机部分被关闭。
那么辍学和贝叶斯神经网络有什么关系呢?嗯,使用辍学可以被视为使用伯努利随机变量来采样你的权重,因此简单地添加辍学,你使你的神经网络贝叶斯!
数学在论文“作为贝叶斯近似的辍学:表示深度学习中的模型不确定性”中进行了探索。我强烈推荐你阅读,尽管乍一看并不容易,但它解释了作为贝叶斯神经网络的辍学背后的许多理论,尤其是它们涵盖了什么是先验、后验和相关的 KL 项,但我们将在另一篇文章中讨论这一点。
因此,通过简单地添加 Dropout,我们现在了解了一个贝叶斯模型,其中权重是从行(或列,取决于矩阵乘法是如何完成的)伯努利分布中采样的。需要注意的一点是,训练将与之前完全相同,唯一的区别是在推断过程中,我们不关闭随机性,而是采样几个权重,将其传递给前向传递,并获得输出的分布。我们在推断过程中使用多个权重样本的事实被称为蒙特卡洛遗漏(或 MC 遗漏)。
How Dropout creates an ensemble of NNs which can output a distribution of results
在这里,我们可以看到压差如何为我们提供不同的网络,每个网络提供不同的输出,这允许我们对网络的输出进行分布。这样,我们就可以知道有不确定性度量,比如方差用于回归,或者如我们将看到的,熵用于分类。
因此,在我们用具体的例子探究这些结果之前,让我总结一下我们目前所看到的一切:
- 贝叶斯神经网络使用权重的概率分布,而不是具有确定性的权重。每次向前传递将采样不同的权重,因此具有不同的输出。人们可以将贝叶斯神经网络视为不具有单一模型,而是模型的集合,这为每个样本提供了不同的预测器。
- 假设相同的输入在向前传递后可以有不同的输出,我们可以通过查看不同预测的方差来了解我们的模型有多确定,因为如果模型不确定,我们预计方差会很高。
- 辍学是一种让你的神经网络贝叶斯几乎免费的方式,在推理过程中使用它,你只需要保持辍学,并对几个模型进行采样,这被称为 MC 辍学。
三世。探索 MC 辍学的 Fastai 示例
现在我们已经看到了 bnn 是如何工作的,以及如何用 Dropout 轻松地实现它们,我们现在将看到一些使用 Fastai 的例子。
代码可以在这个 Github 的资源库中找到:https://github.com/DanyWind/fastai_bayesian,如果你想直接在 Colab 上运行,这里有链接:https://Colab . research . Google . com/drive/1 bifawl _ o _ _ zkfsvve 9994 wj2 CFD 9976 I
无论任务是什么,流程都是一样的:
- 首先用我们都知道的 Fastai API 训练你的模型:lr_find,fit_one_cycle 等…
- 最后,要在 MC Dropout 推断期间保持 Dropout,只需添加以下代码行:
定义函数和类的代码行就在这里,它们并不复杂。我选择用一个模块函数来替换另一个模块,因为我们将在以后的文章中使用它来计算自动退学率。
Colab 中也定义了度量标准,但我们不会涉及它们,因为它非常标准。我们将特别使用一个只对分类有效的不确定性度量:熵。
如果有 C 类要预测,并且我们采样 T 倍我们的模型进行推断,那么熵被定义为:
Definition of Entropy
这个度量可以看作是对无序度的度量,无序度越高,我们模型的不确定性就越高。这比简单地查看分类概率的方差更有意义,因为 softmax 有压缩一切的趋势。
A .猫狗分类器
Cats and Dogs dataset
在这里,我们将重点放在猫和狗的数据集。从这张图片上可以看出,我们将尝试对图片上的狗或猫的品种进行分类。
我不会详细介绍如何训练该模型,这是使用 Resnet34 的经典迁移学习,您可以直接查看代码以了解更多细节。
更有趣的是,用我们用辍学训练的模型做推断,看看猫和狗的常规图像,也看看分布图像,看看模型有多确定。
Entropy of regular and out of distribution images
正如您在这里看到的,已知模型的图像具有低熵,而完全不在分布范围内的图像具有高熵。有趣的是,我们注意到 softmax 的概率并没有给出不确定性的信息,因为在 Colab 笔记本中,我们可以看到分配给夜王类的最高概率是 90%,甚至超过了猫的 78%!
您可以看到,在某些应用中,测量不确定性是多么重要,尤其是在医疗领域,例如,如果我们想对一个人是否应该接受化疗进行分类,我们希望知道我们的模型有多确定,如果不确定,就让一个人参与进来。
Distribution of entropy based on classification results on Cats and Dogs
每个分类结果的熵分布直方图也可以帮助我们诊断我们的模型。正如我们在上面可以看到的,当我们的模型正确执行时,即当存在真阳性或真阴性时,我们观察到熵往往比它错误时(即假阳性和假阴性)低得多。
有趣的是,无论我们的模型正确与否,熵的表现都是不同的,高熵似乎与错误分类高度相关!如果我们回头看看夜王的例子,我们会发现 2.2 的熵确实很高,并且通常出现在错误分类的样本中,而普通猫的熵通常只有 0.7。
B .使用 IMDB 评论进行情感分析
现在我们将快速回顾另一个著名的数据集:IMDB 评论。这个数据集只是收集正面和负面的评论。这里我们将跳过绘制直方图,直接显示数据集最确定和最不确定的样本:
下面的评论拥有最高的熵,这是可以理解的,因为评论很难定义是好是坏。即使我们人类可以感觉到整体情绪是好的,但这也不是微不足道的,我们可以预计机器会更加挣扎。
(Text xxbos xxmaj just got my copy of this xxup dvd two disc set and while not perfect , i found the overall experience to be a fun way to waste some time . i have to say right up front that i am a huge fan of xxmaj zombie movies , and i truly think that the fine people who made these films must be too . i also have a soft spot for people who are trying , sometimes against all odds , to live a dream . xxmaj and again , these people are doing it . xxmaj is this some award - winning collection of amazing film ? xxmaj no . xxmaj not even close . xxmaj but for what they do on their xxunk xxunk , these films should be recommended . xxmaj for me , the bottom line is always , was i entertained ? xxmaj did i have a good time with this movie ? xxmaj and here the answer to both was " xxmaj yes ... Category positive)
C .成年人收入分类表
最后,我们将在这里探索成人收入数据集,我们试图根据社会经济变量来预测某人的年收入是否超过 5 万英镑。我们也将看看最确定和不确定的预测。
我认为这个例子很有趣,因为它可能会对没有考虑不确定性的模型提出一些伦理问题。
事实上,该模型对预测某人是否有高工资非常有信心,这些人通常是白人、男性和受过高等教育的人。因此,该模型很容易区分这些情况。
但另一方面,当处理第二种更困难的情况时,这个模型就更不确定了,比如一个白人男性,受过一些大学教育,工作时间比平均水平长得多。这里的模型是相当不确定的,因为这个人可能在 50K 以上或以下。相反,如果目标是决定是否给予信用,一个好的模型应该让人类在存在巨大不确定性时决定是否做出决定,我们可能会重现模型中可能存在的偏差。
结论
在这篇文章中,我们已经看到了贝叶斯神经网络是什么,我们如何在已经训练好的架构上快速使用它们的属性,通过使用简单的 MC Dropout 在推断过程中简单地利用 Dropout,最后我们如何通过这些模型获得不确定性估计。
这些不确定性估计是宝贵的,因为它们在人工智能的大多数应用中是至关重要的,不仅可以为可信任的人工智能提供保障,而且正如我们将在未来的文章中看到的那样,还可以帮助我们通过主动学习将人类置于循环中。
所以,我希望你喜欢读这篇文章,如果能得到你的反馈,那就太好了,我会在未来试着发布更多的文章。
如果您有任何问题,请不要犹豫,通过 Linkedin 联系我,您也可以通过 Twitter 找到我!
贝叶斯超参数优化
原文:https://towardsdatascience.com/bayesian-hyperparameter-optimization-17dc5834112d?source=collection_archive---------27-----------------------
调整机器学习模型的明智方法
超参数是用于调整机器学习算法学习方式的旋钮、杠杆和螺钉。你可以从一个适当调整的机器学习系统中获得更高的性能。
行业状况
超参数在机器学习领域中最常见的使用方式是,要么盲目地使用默认值,要么使用在另一个问题上似乎很有效的超参数的某种组合,或者你在互联网上看到有人“尊敬”地使用。其他修炼者使用网格搜索或者随机搜索。这些具有可大规模分发的优势。但是它们是蛮力的,并且在计算上极其昂贵。他们浪费了大量的试验,在超参数空间的愚蠢部分探索无意义的超参数组合。也没有任何保证随机跌跌撞撞地达到全局最大值。此外,网格搜索在准确性和要检查的点数方面深受维数灾难之苦。
Photo by John Moeses Bauan on Unsplash
高斯过程来拯救
为了简单起见,让我们考虑一维贝叶斯优化。对于更高维的超参数空间来说,这个想法是一样的。假设黑色曲线是我们的基本函数,点是观察值。观察结果可能是,而且实际上是有噪声的,这意味着它们没有完美地达到潜在的“地面真相”功能。X-轴代表单个超参数的值,就像你的机器学习算法的学习速率。Y-轴是使用指标的模型性能,其中数字越大表示性能越好。
我们使用一个随机过程来创建一大堆候选函数,这样红点观测值可能就是那个函数的输出。我们假设这些函数是连续光滑的。下面 gif 中的置信界限代表了这些函数的可能值和路线。换句话说,我们从穿过(或靠近)所有红点的所有光滑连续函数集中随机抽取样本。
接下来,我们通过采用最大化预期改进的超参数组合来选择下一个要探索的候选。1D 迭代过程看起来像这样:
在 Python 上使用 GPU 加速的 XGBoost 实现
对于那些希望跟随 Python 代码的人,我在 Google Colab 上创建了 notebook,其中我们在 Scania 卡车气压系统数据集上使用贝叶斯优化来优化 XGBoost 超参数。然后我们将结果与随机搜索进行比较。您可以点击下面的“在 Colab 中打开”按钮,亲自尝试一下。
脚注
[1]平滑意味着我们使用协方差函数来确保 X 的邻近值对应于 y 的邻近值。
[2]还有其他方法,或者更恰当地说是采集函数,来选择下一个候选点。预期改进(EI)是最常见的,因为它非常高效,计算成本低,并且易于理解。
贝叶斯推理和微分方程
原文:https://towardsdatascience.com/bayesian-inference-and-differential-equations-cb646b50f148?source=collection_archive---------9-----------------------
结合两种基本范式,从生物学实验中学到更多
生物学实验通常产生清楚地表明测量变量之间的非线性关系的观察结果,并且通常是费力的,并且提供有限数量的观察和重复。常微分方程系统提供了一种建立复杂的非线性现象的机械模型的方法。贝叶斯推理提供了一种范式来拥抱现实世界实验的不确定性,并利用我们的先验知识。生物学是复杂的,实验是困难的,但我们确实有一些成功的建模范例,对生物系统能做什么也有明确的物理约束,以及大量的定量实验文献。在这篇文章中,我展示了一个例子,说明贝叶斯数据分析和微分方程系统是如何结合在一起,从一个只有少量测量值的实验中获取最多信息的。这篇文章中使用的所有代码都可以在这里找到。
正在生长的酵母培养物的玩具模型
下面的玩具模型是为了模拟一个简单的实验而制作的。想象一下,你获得了几克干酵母,并想估计其生存能力。即活酵母细胞占干酵母重量的比例是多少?
您可以尝试的一个实验是,在 1 升分批发酵中接种 1 克干酵母,并在几个时间点测量葡萄糖和生物量浓度。通过这样一个实验,你对你买的酵母有什么了解?
让我们先做一个玩具模型来模拟实验。在这里,我提出了一个酵母培养物的简单模型。它由两个动态质量平衡组成,一个用于生物量,一个用于葡萄糖。请注意,这两种平衡的不同之处仅在于表达式的符号和葡萄糖平衡中 Yxs 的除法。在一个没有噪音或不确定性的世界,我们可以通过测量葡萄糖或生物量来推断系统中的所有参数。在现实世界中存在不确定性,一些变量的测量比其他变量更可信。因此,我们受益于执行冗余测量。下面是我们玩具示例的常微分方程系统:
其中 glc 代表以 mmol 为单位的葡萄糖, X 代表以 g 为单位的生物质干重, μ 是最大生长率,Yxs 是以 mmol 葡萄糖/克生物质为单位的生物质产量, f(glc) 是决定葡萄糖消耗速率的动力学表达式。它由以下速率定律描述:
参数和初始条件
模型参数是基于对在糖上有氧生长的面包酵母的测量。
我们知道初始葡萄糖量(我们制备了培养基)为 100 mmol。最初的生物量,干酵母的生存能力,是未知的,我们想推断出来。对于生成合成实验数据的模拟,我们将使用 0.2 克的初始生物质量。
模拟实验
Synthetic observations. The model ran with the parameters in the table above is shown in blue. Four “observations” are made by adding noise to the model output at four different times.
上图用蓝色显示了模拟我们的玩具模型的输出。在 5、6、7 和 8 小时的黑色圆圈代表我们在这个实验中进行的观察。它们是通过在当时的模拟结果中加入噪声计算出来的。下面我们将假设我们对酵母的所有了解是,当我们在含有 100 mmol 葡萄糖的培养基中接种 1 克干重时,它产生了这八个观察值(四个时间点和两个变量)。
贝叶斯数据分析
选择先验概率分布
有两个参数可以推断,葡萄糖上的生物产量,葡萄糖消耗的最大比速率;和两个初始条件。
葡萄糖的生物产量
葡萄糖的最大可能生物量产量由假设的情况给出,其中所有消耗的葡萄糖将被并入生物量。也就是说,没有葡萄糖会在脱羧反应中损失,也没有分解代谢来驱动生物合成。假设基本生物质成分如下:C₁H₁.₈N₀.₂O₀.₅认为氨是用作氮源,我们可以写出一个生物质合成反应:
这意味着对葡萄糖的最大生物产量( Yxs )为每毫摩尔葡萄糖 0.139 克干重。
最大生物量比增长率
以前,我们对酵母知之甚少。我们确实知道它是一种酵母,而且这种酵母比大肠杆菌生长得慢,据报道,大肠杆菌在合成培养基中的最大生长速率为 0.89 升/小时。
初始条件
我们知道初始葡萄糖浓度在实验误差范围内。我们期望我们的溶液在 100 毫摩尔的预期浓度的 1 或 2 毫摩尔之内。但是我们对接种培养物的活细胞数量知之甚少。我们知道我们加入了 1 克,活细胞的比例大于 0 小于 1。
先验概率分布
我选择使用正态概率分布来模拟所有的前科。对于这两个参数,选择平均值和标准偏差,以便我们上面计算的最大值是可能的,但不太可能。我将初始葡萄糖的先验建模为具有小标准偏差的正态分布,将初始生物量建模为对称的β分布。
估计后验概率分布
这里我用 Stan 来推断与观测值相符的参数分布。Stan 提供了一个内置的系统来解决 ODEs [ link 。这是 Stan 型号代码:
functions {
real[] myodes(
real t,
real[] y,
real[] p,
real[] x_r,
int[] x_i
)
{
real dydt[2];
dydt[1] = -y[2] * (p[1] / p[2]) * (y[1]/1) / (1 + (y[1]/1));
dydt[2] = (y[2] * p[1] * (y[1]/1) / (1 + (y[1]/1)));
return dydt;
}
}data {
int<lower=1> N;
int<lower=1> T;
real y[N, 2];
real t0;
real t_obs[N];
real t_sim[T];
}transformed data {
real x_r[0];
int x_i[0];
}parameters {
real<lower=0> y0[2]; // init
vector<lower=0>[2] sigma;
real<lower=0> p[2];
}transformed parameters {
real y_hat[N, 2];
y_hat = integrate_ode_rk45(myodes, y0, t0, t_obs, p, x_r, x_i);
}model {
sigma ~ normal(0, 1);
p[1] ~ normal(0.445, 0.178);
p[2] ~ normal(0.0695, 0.027800000000000002);
y0[1] ~ normal(100, 0.5);
y0[2] ~ beta(2, 2);
for (t in 1:N)
y[t] ~ normal(y_hat[t], sigma);
}generated quantities {
real y_hat_n[T, 2];
real y_hat_sigma[T, 2];y_hat_n = integrate_ode_rk45(myodes, y0, t0, t_sim, p, x_r, x_i);
// Add error with estimated sigma
for (i in 1:T) {
y_hat_sigma[i, 1] = y_hat_n[i, 1] + normal_rng(0, sigma[1]);
y_hat_sigma[i, 2] = y_hat_n[i, 2] + normal_rng(0, sigma[2]);
}
}
有几个检查来诊断我们在 MCMC 运行中获得的后验样本的代表性。首先,四个链的轨迹图(右手边的图)混合得很好,似乎探索了参数空间,而没有在不同的迭代中陷入不同的区域。由 Stan 生成的下表显示,所有参数的有效样本数(n _ eff——不相关样本数)均大于 5000,所有参数的 Gelman-Rubin 统计量均为 1.0。同样重要的是,当使用不同的种子运行模型时,密度图和高密度概率(HPD)区间几乎相同。
HPD 区间除以它们的平均值表明,初始葡萄糖(y0[1])是相当确定的(我们先前已经有了确定性)。根据 HPD 区间,我们预计活细胞占据的干酵母质量分数在 0.17 和 0.46 之间。我们开始了解这一分数,在实验和分析之前,我们只知道该分数限制在 0 和 1 之间。经过观察,我们将可能性范围缩小到初始范围的 30%。
比较先验分布和后验分布
除了初始葡萄糖,后验概率比先验概率更集中。我们非常确定我们的初始葡萄糖量,我们的观察似乎并不质疑这种确定性。在另外三个例子中,观察结果使我们能够更新我们的预期,它偏离了我们先前设定的范围的中间值。
从后面学习
后验概率分布的样本显示最大生长率( μ )与初始生物量之间呈负相关。后验概率也显示了最大生长率和生物量产量之间的正相关,尽管较弱。下图对初始生物量和最大生长率进行了空间编码,而生物量产量用于给点着色。
这些相关性告诉我们,在符合观察结果时,高的初始生物量可以被低的生长速率所抵消,而低的生长速率可以被高的产量所抵消。因此,有一组模型参数可以同样好地解释观察结果。
模型预测
从后验概率分布中获得代表性样本后,可以对模型进行前向模拟,创建模型输出的后验分布。此外,如果我们使用测量的估计方差,我们假设未来独立重复实验的预测。下图显示了模型输出(左侧)和独立重复实验(右侧)的 50%、75%和 95%可信区间。用于拟合模型的数据点显示落在 95%可信区间内,表明我们获得的数据生成模型可能确实生成了那些观察结果。
免责声明。本文所表达的观点仅属于作者,不一定属于作者的雇主。
AR(p)模型的贝叶斯推断
原文:https://towardsdatascience.com/bayesian-inference-for-ar-models-73ff916101c9?source=collection_archive---------18-----------------------
以“贝叶斯”方式实现 AR 模型。用 Julia 写的代码,可以在这里找到(Jupyter 笔记本上的图和输出)或者在这里找到(。jl 文件)。
Example of Time Series Data; Photo by Isaac Smith on Unsplash
你好!
单变量时间序列大致是指在每个等距有序的时间间隔上有一个值(某个期望量)的序列。对于多变量情况,在每个时刻都有一个以上的值(不同的期望量)。这篇文章主要集中在单变量时间序列,现在将被称为只是时间序列。
时间序列数据的例子包括过去几年中特定地区的月降雨量和特定城市的日最高温度。从这两个例子可以明显看出,获得给定时间序列的准确预测是非常有用的。这些预测让我们得以一窥未来,帮助拯救无数生命。
AR 模型可用于获得时间序列的预测。本文描述了使用贝叶斯推理对此类模型进行参数估计的过程。对于那些不熟悉这种技术的人,我将提供一个简短的描述。用户提供数据以及待估计参数的先验分布。顾名思义,这些先验分布是基于用户对被估计参数的先验信念。基于这些输入,给定数据,模型输出参数的分布。这种分布称为后验分布,然后可以用于获得对未知数据的预测,在我们的情况下,这是指我们的时间序列的未来值。
这是对贝叶斯推理的一个极其简短的描述,它并不完全符合其广泛而令人兴奋的应用。然而,这对于本文的目的来说已经足够了,尽管我强烈建议您进一步阅读这个主题。如果你现在感到困惑,不要担心。事情会越来越明朗:)。
我目前正在 Julia Season of Contributions(JSoC)2019 下向 Turing.jl 投稿,这篇文章描述了我作为 JSoC 的一部分实现的其中一个模型。图灵是一种用 Julia 编写的概率编程语言(PPL ),它使得在纸上定义模型成为一个无缝的过程。此外,它有助于从成分分布中轻松取样。
从 AR(p)模型开始
AR(p)模型是指具有 p 滞后项的自回归模型。自回归意味着变量相对于他自己过去的值线性回归。滞后参数 p 决定了在每个时刻使用多少过去的值。对于给定的由 x 表示的时间序列,我们得到 AR(p)模型的以下预测方程:
其中,ε表示白噪声。现在,有了这些基本信息,让我们来看看代码。
导入库
我们从导入所需的库开始。我们将使用 Turing.jl ,一种 Julia 中的概率编程语言。从定义模型到从后验分布中获取样本,会让整个过程变得流畅,毫不费力。
加载和可视化数据集
让我们首先加载数据集。我们将使用洗发水销售数据集,可以从这里下载。原始数据集归功于 Makridakis、Wheelwright 和 Hyndman (1998 年)。它包含了一种洗发水在 3 年内的月销售额。该部分的代码和绘制该数据集时获得的图形如下:
Plot of the Complete Time Series
分成训练和测试数据
我们使用 90:10 的训练测试分割。由于总共有 36 个观察值(3 年数据,每月一次),我们将使用过去 32 天的数据(训练集)预测最后 4 天(测试集)。
Plot of the Training Set
分析 ACF 和 PACF 图
相关性是两个量(比如 A 和 B)之间的统计度量,它决定了它们的值相对于彼此的增加或减少。如果 A 随着 B 的增加而增加(反之亦然),那么就说它们具有正相关性。例如,给定质量的物体所受的力越大,其加速度就越大。如果 A 随着 B 的减少而增加(反之亦然),也就是说,如果两个量的变化方向相反,那么就说它们具有负相关性。
显示时间序列与其过去值的相关性的图称为自相关函数(ACF)。 Auto 来源于这样一个事实:我们正在计算一个序列与该序列的值的相关性。
xₜ(时间索引 t 的时间序列中的元素)与其滞后 xₜ ₋ ₚ之间的偏相关是在去除 xₜ和 xₜ ₋ ₚ与 xₜ ₋ ₁、xₜ ₋ ₂、…、xₜ ₋ ₍ₚ ₋ ₁₎中的每一个相关的影响后,即滞后短于 p 的这两个量之间的相关。显示时间序列与其过去值的偏相关的图称为偏相关函数(PACF)。
下面显示的是我们训练数据的 ACF 和 PACF 图:
ACF and PACF plots
自回归模型以 ACF 和 PACF 图中的以下观察结果为标志:
- 滞后 1 时的正自相关
- PACF 在某个滞后 k 处突然截止。这个 k 值等于我们应该在 AR(p)模型中使用的 p 值。
- ACF 图逐渐减少到 0
我们可以看到,我们的 ACF 和 PACF 图满足上述三点的条件。此外,我们为 AR(p)模型获得的 p 值是 p = 2 ,因为 PACF 曲线在第二个滞后截止。我们继续定义 AR(2)模型。
模型定义
我们现在使用前面讨论的预测方程来定义 AR(p)模型。我们取 p = 2 ,这是借助于 ACF 和 PACF 图得到的。我们可以用图灵的直观界面很容易地定义模型:
这里,我们假设β系数具有一致的(-1,1)先验,α系数具有正态的(0,1)先验。现在,有了模型定义,是时候对我们的后验进行采样了!
抽样
我们使用不掉头采样器(NUTS)采样器采样,重复 5000 次(抽取 5000 个样本)。如果您不熟悉马尔可夫链蒙特卡罗抽样,您可以将其视为一个黑盒,当提供模型定义和相关参数作为输入时,它会给出后验概率。关于在图灵中使用这个采样器和参数定义的更多信息,你可以在这里参考文档。
分析采样参数
运行上述代码将产生一个输出,提供关于链的基本信息和估计参数的汇总统计信息,如下所示:
只需一行代码,我们就可以得到采样参数的分布,以及它们在所有迭代中的值。
我们还可以用另一行代码查看这些采样参数的角图。
Output of: L: corner(chain), R: plot(chain)
我们现在拥有了我们之前讨论过的窥视未来所需的所有工具。我们将首先从采样链中移除预热样本。这些样本是在最初几次迭代期间在链中最初采样的,并且在我们已经获得所需的后验分布之后不再需要。然后,我们将所有采样参数的平均值作为该参数值的点估计值。
正是这些点估计值,我们将把它们代入预测方程以得到预测值。注意,为了预测前几个元素,我们将不得不使用来自训练集末尾的元素(确切地说,必须对多少个元素进行预测取决于 p 的值)。这是因为我们需要时间序列先前的滞后值来预测当前值。例如,在我们使用的 AR(2)模型中,前两个预测将使用来自训练集的值。因此,我们可以计算预测的时间序列 s_pred ,如下面的代码所示:
绘制预测和测试集(原始数据):
我们可以看到,在要预测的四个值中,只有一个接近,而其他三个非常不准确。一个原因可能是这个时间序列不是协方差平稳的。我们可以通过使用更复杂的 ARIMA 模型来改进这一缺点,这些模型使用差分来首先使序列平稳,然后使用自回归和移动平均项对差分序列进行建模。
这就是我关于 AR(p)模型的贝叶斯推断的文章的结论。我要感谢 Cameron Pfiffer 在实施过程中以及在过去的几个月里提供的巨大帮助和指导。如果你对这篇文章有任何问题或疑问,请随时通过 s shah@iitk.ac.in 联系我,或者你可以在 Julia slack 上用@Saumya Shah 给我加标签。感谢阅读!😃.
参考
[1] Jason Brownlee,机器学习的 7 个时间序列数据集,机器学习掌握,可从https://machinelingmastery . com/Time-Series-Datasets-for-Machine-Learning/,2019 年 8 月 26 日访问。
[2]资料来源:时间序列数据库(引用:Makridakis、Wheelwright 和 Hyndman (1998 年))
贝叶斯推理问题、MCMC 和变分推理
原文:https://towardsdatascience.com/bayesian-inference-problem-mcmc-and-variational-inference-25a8aa9bce29?source=collection_archive---------1-----------------------
统计学中的贝叶斯推断问题综述。
Credit: Free-Photos on Pixabay
本帖与 巴蒂斯特·罗卡 共同撰写。
介绍
贝叶斯推理是统计学中的一个主要问题,也是许多机器学习方法中遇到的问题。例如,用于分类的高斯混合模型或用于主题建模的潜在狄利克雷分配都是在拟合数据时需要解决这种问题的图形模型。
同时,可以注意到,根据模型设置(假设、维度等),贝叶斯推理问题有时很难解决。在大型问题中,精确的解决方案确实需要大量的计算,这些计算往往变得难以处理,必须使用一些近似技术来克服这个问题,并构建快速和可扩展的系统。
在这篇文章中,我们将讨论两种主要的方法来解决贝叶斯推理问题:马尔可夫链蒙特卡罗(MCMC),这是一种基于抽样的方法,和变分推理(VI),这是一种基于近似的方法。
概述
在第一部分,我们将讨论贝叶斯推理问题,并看到一些经典的机器学习应用程序的例子,其中这个问题自然出现。然后在第二部分,我们将全面介绍 MCMC 技术来解决这一问题,并给出一些关于两个 MCMC 算法的细节:Metropolis-Hasting 和 Gibbs 抽样。最后,在第三节中,我们将引入变分推理,看看如何在一个参数化的分布族上通过优化过程得到一个近似解。
注。标有 a (∞)的小节非常数学化,可以跳过,不会影响对这篇文章的整体理解。还要注意,在这篇文章中,p(.)用于表示取决于上下文的概率、概率密度或概率分布。
贝叶斯推理问题
在本节中,我们将介绍贝叶斯推理问题,并讨论一些计算困难,然后给出潜在狄利克雷分配的示例,这是一种主题建模的具体机器学习技术,其中会遇到该问题。
什么是推论?
统计推断在于根据我们观察到的东西来了解我们没有观察到的东西。换句话说,它是根据这个群体或这个群体的一个样本中的一些观察变量(通常是效果)得出关于群体中一些潜在变量(通常是原因)的结论如准时估计、置信区间或分布估计的过程。
特别是,贝叶斯推断是从贝叶斯的角度产生统计推断的过程。简而言之,贝叶斯范式是一种统计/概率范式,其中由概率分布建模的先验知识在每次记录新的观察时被更新,该新的观察的不确定性由另一个概率分布建模。支配贝叶斯范式的整个思想嵌入在所谓的贝叶斯定理中,该定理表达了更新的知识(“后验”)、先验知识(“先验”)和来自观察的知识(“可能性”)之间的关系。
一个经典的例子是参数的贝叶斯推断。让我们假设一个模型,其中数据 x 由依赖于未知参数θ的概率分布产生。我们还假设我们有一个关于参数θ的先验知识,它可以表示为一个概率分布 p(θ)。然后,当观察到数据 x 时,我们可以使用贝叶斯定理更新关于该参数的先验知识,如下所示
Illustration of the Bayes theorem applied to the inference of a parameter given observed data.
计算困难
贝叶斯定理告诉我们,后验概率的计算需要三个条件:先验、似然和证据。前两个可以很容易地表达出来,因为它们是假设模型的一部分(在许多情况下,先验和可能性是明确已知的)。然而,第三项,即归一化因子,需要计算如下
虽然在低维中计算这个积分没有太多困难,但是在高维中它会变得难以处理。在最后一种情况下,后验分布的精确计算实际上是不可行的,必须使用一些近似技术来解决需要知道该后验分布的问题(例如,均值计算)。
我们可以注意到,一些其他的计算困难可能产生于贝叶斯推理问题,例如,当一些变量是离散的时,组合学问题。在最常用于克服这些困难的方法中,我们找到了马尔可夫链蒙特卡罗和变分推断方法。在这篇文章的后面,我们将描述这两种方法,特别是集中在“归一化因子问题”上,但是人们应该记住,当面临与贝叶斯推理相关的其他计算困难时,这些方法也可能是宝贵的。
为了使接下来的章节更具一般性,我们可以观察到,假设 x 是给定的,因此可以作为一个参数,我们面临这样一种情况,θ的概率分布定义为一个归一化因子
在下两节描述 MCMC 和 VI 之前,我们先举一个具体的例子,用潜在的狄利克雷分配来说明机器学习中的贝叶斯推理问题。
例子
贝叶斯推理问题自然地出现,例如,在假设概率图形模型的机器学习方法中,并且在给定一些观察的情况下,我们想要恢复模型的潜在变量。在主题建模中,潜在狄利克雷分配(LDA) 方法为语料库中的文本描述定义了这样的模型。因此,给定大小为 V 的完整语料库词汇表和给定数量的主题 T,该模型假设:
- 对于每个主题,存在词汇表上的“主题-词”概率分布(假设有 Dirichlet 先验)
- 对于每个文档,存在主题上的“文档-主题”概率分布(假设另一个狄利克雷先验)
- 对文档中的每个单词进行采样,首先,我们从文档的“文档-主题”分布中采样主题,其次,我们从附加到采样主题的“主题-单词”分布中采样单词
该方法的名称来源于模型中假设的 Dirichlet 先验,其目的是推断观察到的语料库中的潜在主题以及每个文档的主题分解。即使我们不深入 LDA 的细节,我们也可以非常粗略地说,表示 w 是语料库中的单词向量,z 是与这些单词相关联的主题向量,我们希望以贝叶斯方式基于观察到的 w 来推断 z:
这里,除了归一化因子由于巨大的维度而绝对难以处理的事实之外,我们还面临着组合学的挑战(因为问题的一些变量是离散的),需要使用 MCMC 或 VI 来获得近似解。对主题建模及其具体的底层贝叶斯推理问题感兴趣的读者可以看看这篇关于 LDA 的参考论文。
Illustration of the Latent Dirichlet Allocation method.
马尔可夫链蒙特卡罗(MCMC)
正如我们之前提到的,处理贝叶斯推理问题时面临的主要困难之一来自规范化因素。在本节中,我们描述了 MCMC 采样方法,它构成了一个可能的解决方案来克服这个问题以及一些其他与贝叶斯推理相关的计算困难。
抽样方法
抽样方法的思想如下。让我们首先假设我们有一个方法(MCMC)来从一个概率分布中抽取样本,这个概率分布被定义为一个因子。然后,我们可以从该分布中获取样本(仅使用非标准化部分定义),并使用这些样本来计算各种准时统计,如均值和方差,甚至通过核密度估计来近似分布,而不是试图处理涉及后验的棘手计算。
与下一节描述的 VI 方法相反, MCMC 方法对研究的概率分布(贝叶斯推理情况下的后验概率)不采用模型。因此,这些方法具有较低的偏差,但具有较高的方差,这意味着大多数时候获得结果的成本更高,但也比我们从 VI 中获得的结果更准确。
为了结束这一小节,我们再次概述这样一个事实,即我们刚刚描述的这个抽样过程并不局限于后验分布的贝叶斯推断,而且更一般地说,还可以用于概率分布被定义为其归一化因子的任何情况。
Illustration of the sampling approach (MCMC).
MCMC 的理念
在统计学中,马尔可夫链蒙特卡罗算法旨在从给定的概率分布中生成样本。该方法名称中的“蒙特卡罗”部分是由于采样的目的,而“马尔可夫链”部分来自我们获取这些样本的方式(我们让读者参考我们关于马尔可夫链的介绍文章)。
为了产生样本,我们的想法是建立一个马尔可夫链,它的平稳分布就是我们想要从中取样的分布。然后,我们可以从马尔可夫链中模拟一个随机的状态序列,它足够长,足以(几乎)达到稳态,然后保留一些生成的状态作为我们的样本。
在随机变量生成技术中,MCMC 是一种非常先进的方法(我们已经在关于 GANs 的帖子中讨论了另一种方法),它使得从一个非常困难的概率分布中获取样本成为可能,该概率分布可能只定义到一个乘法常数。反直觉的事实是,我们可以用 MCMC 从一个没有很好归一化的分布中获得样本,这来自于我们定义对这些归一化因子不敏感的马尔可夫链的特定方式。
The Markov Chain Monte Carlo approach is aimed at generating samples from a difficult probability distribution that can be defined up to a factor.
马尔可夫链的定义
整个 MCMC 方法是基于建立马尔可夫链的能力,该马尔可夫链的平稳分布就是我们想要从采样的分布。为了做到这一点,Metropolis-Hasting 和 Gibbs 抽样算法都使用了马尔可夫链的一个特殊性质:可逆性。
状态空间 E 上的马尔可夫链,转移概率表示为
如果存在一个概率分布γ,使得
对于这样的马尔可夫链,我们可以很容易地证明我们有
然后,γ是一个平稳分布(如果马氏链是不可约的,它是唯一的)。
现在让我们假设我们想要采样的概率分布 π 只定义了一个因子
(其中 C 是未知的乘法常数)。我们可以注意到下面的等价关系成立
然后是转移概率为 k(.,.)定义来验证最后的等式将有,如预期的那样, π 为平稳分布。因此,我们可以定义一个马尔可夫链,它对于平稳分布有一个不能明确计算的概率分布 π 。
吉布斯采样跃迁(∞)
让我们假设我们想要定义的马尔可夫链是 D 维的,这样
吉布斯抽样方法基于这样的假设,即使联合概率难以处理,也可以计算出给定其他维度的单个维度的条件分布。基于这一思想,定义转移,使得在迭代 n+1 时,要访问的下一个状态由以下过程给出。
首先,我们在 X_n 的 D 维中随机选择一个整数 D。然后,在所有其他维保持固定的情况下,我们根据相应的条件概率为该维采样一个新值:
在哪里
是在给定所有其他维度的情况下,第 d 个维度的条件分布。
形式上,如果我们表示
然后可以写出转移概率
因此,局部平衡如预期的那样被验证,对于唯一重要的情况,
大都市的急速转变(∞)
有时,甚至吉布斯方法中的条件分布也太复杂而难以获得。在这种情况下,可以使用 Metropolis-Hasting 。为此,我们从定义侧跃迁概率 h(.,.)这将用于建议过渡。然后,在迭代 n+1 时,马尔可夫链要访问的下一个状态由下面的过程定义。我们首先从 h 画出一个“建议转移”x,并计算接受它的相关概率 r:
那么选择有效转换,使得
形式上,转移概率可以写成
因此,本地余额如预期的那样得到验证
取样过程
一旦定义了我们的马尔可夫链,我们就可以模拟一个随机的状态序列(随机初始化),并选择其中的一些状态,以获得既遵循目标分布又相互独立的样本。
首先,为了使样本(几乎)遵循目标分布,我们需要只考虑离生成序列的开始足够远的状态,以几乎达到马尔可夫链的稳态(理论上,稳态只是渐近达到)。因此,第一个模拟状态不可用作样本,我们将达到稳态所需的这个阶段称为老化时间。注意,实际上很难知道这个老化时间需要多长。
第二,为了有(几乎)独立的样本,我们不能在老化时间之后保持序列的所有连续状态。事实上,马尔可夫链的定义意味着两个连续状态之间的强相关性,因此我们只需要保留彼此相距足够远的状态作为样本,以被认为是几乎独立的。实际上,两个状态之间被认为几乎独立所需的滞后可以通过自相关函数的分析来估计(仅针对数值)。
因此,为了获得遵循目标分布的独立样本,我们保留来自所生成序列的状态,这些状态彼此相隔一个滞后 L,并且在老化时间 B 之后出现。因此,如果马尔可夫链的连续状态被表示为
我们只保留州作为我们的样本
MCMC sampling requires to consider both a burn-in time and a lag.
变分推理(六)
另一种克服与推理问题相关的计算困难的可能方法是使用变分推理方法,该方法在于在参数化族中寻找分布的最佳近似值。为了找到最佳近似值,我们遵循一个优化流程(针对系列参数),该流程只要求将目标分布定义为一个因子。
近似方法
VI 方法包括在给定的家族中寻找一些复杂目标概率分布的最佳近似。更具体地说,其思想是定义一个参数化的分布族,并对参数进行优化,以获得相对于明确定义的误差度量最接近目标的元素。
让我们仍然考虑定义为归一化因子 C 的概率分布 π :
然后,用更数学的术语来说,如果我们表示参数化的分布族
并且我们考虑两个分布 p 和 q 之间的误差度量 E(p,q ),我们搜索最佳参数使得
如果我们可以解决这个最小化问题,而不必显式归一化 π ,我们就可以使用 f_𝜔*作为一种近似来估计各种量,而不是处理棘手的计算。变分推理方法所隐含的最优化问题实际上被认为比直接计算(归一化、组合学等)要简单得多。
与抽样方法相反,假设了一个模型(参数化家族),这意味着一个偏差和一个较低的方差。总的来说,VI 方法不如 MCMC 方法精确,但产生结果的速度快得多:这些方法更适合于大规模、非常统计的问题。
Illustration of the approximation approach (Variational Inference).
分布族
我们需要设置的第一件事是参数化的分布族,它定义了我们搜索最佳近似的空间。
家庭的选择定义了一个控制方法的偏倚和复杂性的模型。如果我们假设一个非常严格的模型(简单的家庭),那么我们有一个高偏差,但优化过程是简单的。相反,如果我们假设一个相当自由的模型(复杂的家庭),偏差会低得多,但优化会更困难(如果不是难以处理的话)。因此,我们必须在一个足够复杂以确保最终逼近的良好质量的族和一个足够简单以使优化过程易于处理的族之间找到正确的平衡。我们应该记住,如果族中没有一个分布接近目标分布,那么即使是最好的近似也只能给出很差的结果。
平均场变分族是一个概率分布族,其中所考虑的随机向量的所有分量都是独立的。这个系列的分布具有产品密度,使得每个独立的成分由产品的不同因素控制。因此,属于平均场变分族的分布具有可以写成的密度
这里我们假设一个 m 维随机变量 z,注意,即使在符号中省略了它,所有的密度 f_j 都是参数化的。因此,例如,如果每个密度 f_j 是具有均值和方差参数的高斯分布,则全局密度 f 由来自所有独立因素的一组参数来定义,并且在整个参数组上进行优化。
The choice of the family in variational inference sets both the difficulty of the optimisation process and the quality of the final approximation.
库尔贝克-莱布勒散度
一旦定义了这个族,一个主要的问题仍然存在:如何在这个族中找到一个给定概率分布的最佳近似(明确定义到它的归一化因子)?即使最佳近似值明显取决于我们考虑的误差测量的性质,但似乎很自然地假设最小化问题对归一化因子不敏感,因为我们更想比较质量分布而不是质量本身(对于概率分布必须是单一的)。
所以,现在让我们定义一下 Kullback-Leibler (KL) 散度,看看这个度量使问题对归一化因子不敏感。如果 p 和 q 是两个分布,KL 散度定义如下
根据这个定义,我们可以很容易地看到
对于我们的最小化问题,这意味着以下等式
因此,当选择 KL 散度作为我们的误差度量时,优化过程对乘法系数不敏感,并且我们可以在我们的参数化分布族中搜索最佳近似,而不必像预期的那样计算目标分布的痛苦的归一化因子。
最后,作为一个附带事实,我们可以通过为感兴趣的读者注意到 KL 散度是交叉熵减去熵来结束这一小节,并且在信息论中有很好的解释。
优化过程和直觉
一旦定义了参数族和误差测量,我们就可以初始化参数(随机或根据明确定义的策略)并进行优化。可以使用几个经典的优化技术,例如梯度下降或坐标下降,这将在实践中导致局部最优。
为了更好地理解这个优化过程,让我们举一个例子,回到贝叶斯推理问题的具体情况,我们假设一个后验概率如下
在这种情况下,如果我们想要使用变分推断获得这个后验的近似,我们必须解决下面的优化过程(假设定义的参数化族和 KL 散度作为误差度量)
最后一个等式有助于我们更好地理解如何鼓励近似值分配其质量。第一项是预期对数似然,其倾向于调整参数,以便将近似值的质量放在解释最佳观察数据的潜在变量 z 的值上。第二项是近似值和先验分布之间的负 KL 散度,其倾向于调整参数,以便使近似值接近先验分布。因此,这个目标函数很好地表达了通常的先验/似然平衡。
Optimisation process of the Variational Inference approach.
外卖食品
这篇文章的主要观点是:
- 贝叶斯推理是统计学和机器学习中的一个非常经典的问题,它依赖于众所周知的贝叶斯定理,其主要缺点是,大多数时候,在一些非常繁重的计算中
- 马尔可夫链蒙特卡罗(MCMC)方法旨在模拟来自密度的样本,这些密度可能非常复杂和/或定义到某个因子
- MCMC 可以用在贝叶斯推理中,以便直接从后验的“非归一化部分”生成样本来处理,而不是处理棘手的计算
- 变分推断(VI)是一种近似分布的方法,使用参数的优化过程在给定的族中找到最佳近似
- VI 优化过程对目标分布中的乘法常数不敏感,因此,该方法可用于近似仅定义到归一化因子的后验
正如已经提到的,MCMC 和 VI 方法具有不同的属性,这意味着不同的典型用例。一方面,MCMC 方法的采样过程相当繁重,但是没有偏差,因此,当期望精确的结果时,这些方法是优选的,而不考虑所花费的时间。另一方面,尽管 VI 方法中家族的选择会明显引入偏差,但它伴随着合理的优化过程,使这些方法特别适合于需要快速计算的超大规模推理问题。
MCMC 和 VI 之间的其他比较可以在优秀的变分推断:统计学家回顾中找到,我们也强烈推荐给仅对 VI 感兴趣的读者。关于 MCMC 的进一步阅读,我们推荐这本总论以及这本面向机器学习的导论。有兴趣了解更多关于应用于 LDA 的 Gibbs 抽样的读者可以参考这篇关于主题建模和 Gibbs 抽样的教程(结合这些关于 LDA Gibbs 抽样器的讲义进行谨慎推导)。
最后,让我们以一点调侃来结束,并提到在即将到来的帖子中,我们将讨论变分自动编码器,这是一种基于变分推理的深度学习方法…所以请保持关注!
感谢您的阅读,如果您认为值得分享,请随意分享!
巴蒂斯特·罗卡的最后一篇文章:
[## 推荐系统简介
几种主要推荐算法综述。
towardsdatascience.com](/introduction-to-recommender-systems-6c66cf15ada) [## 整体方法:装袋、助推和堆叠
理解集成学习的关键概念。
towardsdatascience.com](/ensemble-methods-bagging-boosting-and-stacking-c9214a10a205)
贝叶斯模型选择:作为一种特征约简技术
原文:https://towardsdatascience.com/bayesian-model-selection-as-a-feature-reduction-technique-70d75386eabc?source=collection_archive---------15-----------------------
一个温和的介绍应用贝叶斯模型选择,以确定机器学习模型生成的重要特征。
Photo by Franki Chamaki on Unsplash
通常,我们在构建预测性机器学习模型时面临的一个重要障碍是找到能够忠实映射描述符和预测符之间潜在关系的最佳特征子集。当我们的机器学习模型中有冗余特征时,它们不仅会增加训练时间(因为训练时间与特征向量的长度和特征的数量成正比),还会给模型添加噪声,从而恶化机器学习性能。解决这个问题的一种方法是选择与信号具有适当相关性的描述符子集。为了实现这一目标,有几种可用特征/指纹减少工具,例如,
自下而上的方法在初始步骤中,根据性能指标选择最佳特性。然后迭代地添加下一个最佳特征,直到边际性能增益可以忽略。
自上而下的方法最初使用所有的特征,然后逐渐丢弃最差的一个,直到获得满意的折衷。
遗传算法特征相互融合,以产生更好的特征,但如果后代不够合适,它就会被丢弃。
所有这些技术都有其优点和缺点。我不想对它们进行任何比较,因为这超出了这篇小文章的范围。相反,在本文中,我将讨论一种不同的特征约简方法——贝叶斯模型选择。
贝叶斯模型选择
贝叶斯模型选择可以应用于我们有多个竞争模型并且需要选择最佳模型的情况。根据贝叶斯定理,任何模型的后验概率都可以写成:
Bayes’s Formula for the probability of a model (M) being a true model given the data (D)
这里,P(M|D)是给定数据 D 的模型 M 的后验概率,P(D|M)是模型 M 的证据,P(M)是关于模型 M 的先验知识,P(D)是归一化因子。当我们有两个竞争模型时,我们可以比较它们的后验概率,
Formula for Bayesian Model Comparison using posterior probability distribution
有了这个等式,我们可以比较两个模型,并采用具有更大模型证据的模型(当我们有无信息先验时)。在上述方程中比较模型的困难部分是模型证据的计算,这是一项非常复杂的任务。幸运的是,对于线性回归模型,有分析公式可以直接计算模型证据。在本文中,我们将使用贝叶斯信息标准(BIC),而不是模型证据来选择最佳模型。贝叶斯信息标准与负对数边际似然成比例,这意味着具有最低 BIC 的模型可能是最大化后验预测能力的最佳模型。如果线性回归模型的残差是正态分布的,我们可以使用下面的公式来计算每个模型的 BIC,
Formula for Bayesian Information Criteria for linear regression model with normal error distribution
这个方程,通过构造,试图优化偏差-方差的权衡。第一项奖励低模型 RMSE(均方根误差),第二项惩罚模型复杂性。此外,我们拥有的数据点越多,关于模型的证据就越多。现在,这一切都归结为计算每个线性回归模型的上述公式,并选择一个最低的 BIC。
作为特征约简技术的贝叶斯模型选择
BMS 主要用于模型比较。但是我们也可以把它作为一个特征选择工具。如果我们为所有特征组合建立线性回归模型,那么具有最低 BIC 的模型就是包含所有相关特征的模型。有了这个想法,下面我将展示一个如何实现这个想法的例子。
让我们先加载数据:
Loading the diabetes dataset available in sklearn
现在,根据这些数据制作一个熊猫数据框架:
Organizing the data into a pandas dataframe
为了简化我们的模型选择任务,我写了一个代码来完成它,它使用 sklearn 来构建模型。运行这个例子的代码可以在我的 GitHub repo ( 贝叶斯框架)中找到。
使用上面的代码,首先我们将构建模型动物园(包含所有模型的信息):
Building the linear regression zoo and plotting the model performance envelope
运行上述代码片段将在 matplotlib GUI 中显示以下图形:
Model performance envelope for all the model considered in our analysis
或者,我们可以使用以下代码直接选择最佳模型:
Selecting the best model from the zoo
它将在控制台上打印以下输出:
Model parameters of the best selected model
因此,基于我们的模型选择方法,我们确定 10 个特征中的 5 个是最重要的描述符集,它们是性别、bmi、bp、s3 和 s5。正如预期的那样,我们的模型表明性别、体重指数和血压是决定一个人患糖尿病的最重要因素,这与我们的直觉知识一致。
有了这个贝叶斯模型选择框架,我们可以很容易地减少我们的模型中的特征数量,也将有助于使模型更具可解释性。此外,它选择一个简单的线性回归模型,该模型可以用作基线模型,通过引入非线性机器学习模型来训练我们的数据,从而提高模型性能。
贝叶斯建模航空公司客户服务 Twitter 响应时间
原文:https://towardsdatascience.com/bayesian-modeling-airlines-customer-service-twitter-response-time-74af893f02c0?source=collection_archive---------11-----------------------
Photo credit: Pixabay
学生的 t 分布、泊松分布、负二项分布、分层建模和回归
Twitter 最近在美国进行了一项研究,发现的顾客愿意多付近 20 美元乘坐一家在六分钟内回复他们推文的航空公司。当他们的推文在 67 分钟后得到回应时,他们只会多付 2 美元乘坐那家航空公司的航班。
当我在 twitter 数据集上遇到客户支持时,我忍不住想建模并比较航空公司客服 Twitter 响应时间。
我希望能够回答这样的问题:
- 数据中所有航空公司的客服 twitter 响应时间有显著差异吗?
- 周末会影响反应时间吗?
- 更长的推文需要更长的时间来回应吗?
- 哪个航空公司的客服 twitter 响应时间最短,反之亦然?
数据
这是一个庞大的数据集包含了来自各行各业的数百家公司。以下数据争论过程将会完成:
- 得到客户的询问,以及每一行公司相应的回复。
- 将日期时间列转换为日期时间数据类型。
- 计算响应时间,精确到分钟。
- 在数据中仅选择航空公司。
- 任何超过 60 分钟的客户咨询都将被过滤掉。我们正在处理在 60 分钟内得到回应的请求。
- 创建时间属性和响应字数。
preprocessing_airline.py
响应时间分布
plt.figure(figsize=(10,5))
sns.distplot(df['response_time'], kde=False)
plt.title('Frequency of response by response time')
plt.xlabel('Response time (minutes)')
plt.ylabel('Number of responses');
Figure 1
我的直接印象是,高斯分布不是数据的恰当描述。
学生的 t 分布
当处理异常值和高斯分布时,一个有用的选择是用一个学生的 t-分布代替高斯似然。这个分布有三个参数:平均值(𝜇)、标度(𝜎)(类似于标准差)和自由度(𝜈).)
- 将平均值均匀分布的边界设置为 0 和 60。
- 𝜎只能是正的,因此使用半正态分布。
- 将𝜈设为平均值为 1 的指数分布。
students_t_distribution
MCMC 诊断
- 从下面的迹线图中,我们可以直观地得到𝜇的似是而非的后验值。
- 我们应该把这个结果与我们用解析方法得到的结果进行比较。
az.plot_trace(trace_t[:1000], var_names = ['μ']);
Figure 2
df.response_time.mean()
- 左图显示了为𝜇.收集的值的分布我们得到的是 7.4 到 7.8 分钟之间的𝜇的不确定性和可信值的度量。
- 显然,从与目标分布显著不同的分布中抽取的样本。
后验预测检查
一种可视化的方法是看模型是否能再现真实数据中观察到的模式。例如,推断平均值与实际样本平均值的接近程度:
ppc = pm.sample_posterior_predictive(trace_t, samples=1000, model=model_t)
_, ax = plt.subplots(figsize=(10, 5))
ax.hist([n.mean() for n in ppc['y']], bins=19, alpha=0.5)
ax.axvline(df['response_time'].mean())
ax.set(title='Posterior predictive of the mean', xlabel='mean(x)', ylabel='Frequency');
Figure 3
推断平均值与实际样本平均值相差甚远。这证实了学生的 t 分布对于我们的数据不是一个合适的选择。
泊松分布
泊松分布一般用于描述给定数量的事件在固定的时间/空间间隔内发生的概率。因此,泊松分布假设事件彼此独立发生,并以固定的时间和/或空间间隔发生。该离散分布仅使用一个值𝜇来参数化,该值对应于分布的均值和方差。
poisson.py
MCMC 诊断
az.plot_trace(trace_p);
Figure 4
𝜇的不确定性和可信值的测量在 13.22 和 13.34 分钟之间。听起来已经好多了。
自相关
我们希望自相关随着图中 x 轴的增加而下降。因为这表明我们的样本之间的相关性很低。
_ = pm.autocorrplot(trace_p, var_names=['μ'])
Figure 5
我们来自泊松模型的样本已经下降到低自相关值,这是一个好迹象。
后验预测检查
我们使用后验预测检验来“寻找真实数据和模拟数据之间的系统性差异”。进行后验预测检验有多种方法,我想用各种方法来检验我的模型是否有意义。
y_ppc_p = pm.sample_posterior_predictive(
trace_p, 100, model_p, random_seed=123)
y_pred_p = az.from_pymc3(trace=trace_p, posterior_predictive=y_ppc_p)
az.plot_ppc(y_pred_p, figsize=(10, 5), mean=False)
plt.xlim(0, 60);
Figure 6
解释:
- 单线(黑线)是数据的核密度估计 (KDE ),许多紫色线是从 100 个后验预测样本中的每一个计算的 KDE。紫色线条反映了我们对预测数据的推断分布的不确定性。
- 从上面的图中,我不能认为一个泊松分布的规模是数据标准差的一个合理的实际代理,即使在去除异常值之后。
后验预测检查
ppc = pm.sample_posterior_predictive(trace_p, samples=1000, model=model_p)
_, ax = plt.subplots(figsize=(10, 5))
ax.hist([n.mean() for n in ppc['y']], bins=19, alpha=0.5)
ax.axvline(df['response_time'].mean())
ax.set(title='Posterior predictive of the mean', xlabel='mean(x)', ylabel='Frequency');
Figure 7
- 推断的均值比我们从学生的 t 分布得到的均值更接近实际样本均值。但还是有一点小差距。
- 使用泊松分布的问题是均值和方差由相同的参数描述。因此,解决这个问题的一个方法是将数据建模为一个混合的泊松分布和来自伽马分布的比率,这给了我们使用负二项分布的理由。
负二项分布
负二项分布具有与泊松分布非常相似的特征,除了它有两个参数(𝜇和𝛼),这使得它能够独立于其均值改变其方差。
negative_binomial.py
MCMC 诊断
az.plot_trace(trace_n, var_names=['μ', 'α']);
Figure 8
𝜇的不确定性和可信值的测量在 13.0 和 13.6 分钟之间,并且非常接近目标样本均值。
后验预测检查
y_ppc_n = pm.sample_posterior_predictive(
trace_n, 100, model_n, random_seed=123)
y_pred_n = az.from_pymc3(trace=trace_n, posterior_predictive=y_ppc_n)
az.plot_ppc(y_pred_n, figsize=(10, 5), mean=False)
plt.xlim(0, 60);
Figure 9
在我们的模型中使用负二项分布会产生预测样本,这些样本在分布的峰值位置及其分布方面似乎更符合数据。
后验预测检查
ppc = pm.sample_posterior_predictive(trace_n, samples=1000, model=model_n)
_, ax = plt.subplots(figsize=(10, 5))
ax.hist([n.mean() for n in ppc['y_est']], bins=19, alpha=0.5)
ax.axvline(df['response_time'].mean())
ax.set(title='Posterior predictive of the mean', xlabel='mean(x)', ylabel='Frequency');
Figure 10
综上所述,以下是我们对不确定性和可信值的度量(𝜇):
- 学生 t 分布:7.4 到 7.8 分钟
- 泊松分布:13.22 到 13.34 分钟
- 负二项分布:13.0 到 13.6 分钟。
后验预测分布
posterior_predictive_dist.py
Figure 11
后验预测分布有点类似于观察数据的分布,表明负二项式模型更适合基础数据。
分层建模的贝叶斯方法
- 我们想把每家航空公司作为一个独立的实体来研究。我们希望建立一个模型来估计每家航空公司的响应时间,同时估计整个数据的响应时间。这种类型的模型被称为分层模型或多级模型。
- 我的直觉告诉我,不同的航空公司有不同的反应时间。例如,阿拉斯加航空公司的客户服务 twitter 响应可能比亚洲航空公司的响应更快。因此,我决定独立地为每家航空公司建模,为每家航空公司估计参数 μ 和 α 。
- 一个考虑是,一些航空公司可能比其他航空公司更少收到来自 twitter 的客户咨询。因此,与有大量客户咨询的航空公司相比,我们对有少量客户咨询的航空公司的响应时间的估计具有更高的不确定性。下图说明了每家航空公司样本量的差异。
plt.figure(figsize=(12,4))
sns.countplot(x="author_id_y", data=df, order = df['author_id_y'].value_counts().index)
plt.xlabel('Airline')
plt.ylabel('Number of response')
plt.title('Number of response per airline')
plt.xticks(rotation=45);
Figure 12
用负二项分布对各航空公司进行贝叶斯建模
hierarchical_negative_binomial.py
每个航空公司的后验预测分布
posterior_pred_1.py
Figure 13
观察值 :
- 在上述三家航空公司中,英国航空公司的后验预测分布与阿拉斯加航空公司和西南航空公司相差很大。英国航空公司向右分布。
- 这可以准确地反映其客户服务 twitter 响应时间的特征,这意味着通常英国航空公司比阿拉斯加航空公司或西南航空公司需要更长的时间来响应。
- 或者由于样本量小,它可能是不完整的,因为我们从西南航空公司得到的数据比从英国航空公司得到的多得多。
posterior_pred_2.py
Figure 14
与此类似,在上述三家航空公司中,亚航的分布向右,这可以准确反映其客服 twitter 响应时间的特点,这意味着一般情况下,亚航比达美或弗吉尼亚航空的响应时间更长。或者可能由于样本量小而不完整。
posterior_pred_3.py
Figure 15
对于航空公司我们有相对充分的数据,例如,当我们比较美国的上述三家大型航空公司时,后验预测分布似乎没有显著变化。
贝叶斯分层回归
模型的变量:
df = df[['response_time', 'author_id_y', 'created_at_y_is_weekend', 'word_count']]
formula = 'response_time ~ ' + ' + '.join(['%s' % variable for variable in df.columns[1:]])
formula
在下面的代码片段中,我们:
- 将分类变量转换为整数。
- 估计每个航空公司客户服务响应时间的基线参数值𝛽0。
- 估计数据中所有航空公司的所有其他参数。
bayesian_hl.py
MCMC 诊断
az.plot_trace(trace_hr);
Figure 16
观察:
- 每个航空公司都有不同的基线响应时间,但是,其中一些非常接近。
- 如果您在周末发送请求,那么在得到响应之前,您可能会等待稍长的时间。
- 回复的字数越多,等待回复的时间就越长。
森林小区
_, ax = pm.forestplot(trace_hr, var_names=['intercept'])
ax[0].set_yticklabels(airlines.tolist());
Figure 17
该模型估计每个航空公司的上述β0(截距)参数。点是每个航空公司最可能的参数值。看起来我们模型对每家航空公司的不确定性都很小。
ppc = pm.sample_posterior_predictive(trace_hr, samples=2000, model=model_hr)
az.r2_score(df.response_time.values, ppc['y_est'])
Jupyter 笔记本可以位于 Github 上。祝你一周工作顺利!
参考资料:
这本书:用 Python 进行贝叶斯分析
这本书:做贝叶斯数据分析
这本书:统计学再思考
【https://docs.pymc.io/notebooks/GLM-poisson-regression.html
https://docs . pymc . io/notebooks/hierarchical _ partial _ pooling . html
[## GLM:分级线性回归- PyMC3 3.6 文档
本教程改编自达恩·埃尔伯斯和托马斯·威奇的博客文章,名为…
docs.pymc.io](https://docs.pymc.io/notebooks/GLM-hierarchical.html)
https://docs . pymc . io/notebooks/GLM-负数-二项式-回归. html
[## nbviewer 笔记本
对 alpha 应用了间隔转换,并将转换后的 alpha_interval_ 添加到模型中。将区间变换应用于 mu…
nbviewer.jupyter.org](https://nbviewer.jupyter.org/github/markdregan/Bayesian-Modelling-in-Python/blob/master/Section 3. Hierarchical modelling.ipynb) [## PyMC3 和 Theano-pymc 3.6 文档
Theano 是一个包,它允许我们定义涉及数组操作和线性代数的函数。当我们定义一个…
docs.pymc.io](https://docs.pymc.io/PyMC3_and_Theano.html)
https://www . ka ggle . com/PS bots/customer-support-meets-spacy-universe
使用 PyMC3 对福特 GoBike 乘客量进行贝叶斯建模—第一部分
原文:https://towardsdatascience.com/bayesian-modeling-for-ford-gobike-ridership-with-pymc3-part-i-b905104af0df?source=collection_archive---------16-----------------------
Photo by Andrew Gook on Unsplash
自行车共享是世界各地城市交通等式的重要组成部分。在旧金山,自行车共享游戏的主要参与者之一是福特公司及其 GoBike 计划。方便的是,他们友好地发布他们的数据给像我这样的人研究。我想知道,根据过去的信息,是否可以很容易地预测第二天的乘客量,以确保有足够的自行车可供乘客使用?
如果我要使用 sklearn 建立一个线性回归模型,这将是一个相当简单的任务。我经常发现自己在寻找数据集,以学习机器学习中的一种新工具或技能。多年来,我一直试图找到一个借口来尝试一个概率编程包(如 PyStan 或pymc 3】,这个自行车共享数据似乎非常适合。
许多公司正在为他们的内部预测模型寻找贝叶斯推断。随着计算成本的降低,这些系统众所周知的长训练时间也减少了。值得注意的是优步发布了 Pyro ,这是一个开源框架,看起来相当灵活且易于使用。 Quantopian 是 PyMC3 的常客。据我所知,Booz Allen Hamilton 和 GoDaddy 是另外两家追求这种 ML 模式的公司。
在这篇文章中,我构建了一个简单的例子,希望对 PyMC3 初学者有所启发。我下载了 2017 年—2018 年 9 月的 GoBike 数据。然后,我每天汇总数据,以收集关于乘车者详细信息(例如,平均年龄、订阅会员)、乘车时长和乘车者总数的信息。
这些贝叶斯 ML 工具的问题是,它们可能需要很长时间来训练,尤其是在海量数据上。对于这个聚合数据集,我只有 100 多行,这在笔记本电脑上很容易训练。经过一点研究,我决定学习 PyMC3 作为我的选择。看起来它有很多很棒的教程,一个充满活力的社区,和一个相当容易使用的框架。
在这个说明性的例子中,我首先用一个健壮的定标器对数据进行定标,并绘制出 seaborn 关联热图,看看我们的模型是否可以学习任何模式。我们试图预测第二天的值。从热图中,我们可以看到变量之间的一些简单关系,
既有正的( scaled_total_riders ),也有负的( scaled_duration_hrs )。
让我们做一个简单的预测,并以此为基准。如果我们只取平均每日乘车人数,并以此作为我们的预测,RMSE 会是多少?通过这种简单的方法,我们预计每天可以减少大约 1900 名乘客。
具有 sklearn 的线性模型在 RMSE 表现稍好,并且非常容易实现。这个模型是我们数据中每个变量的一系列权重,还有一个截距。我们如何解释我们的模型对每一个参数的信心?
这可能是贝叶斯魔法真正闪耀的地方。与上面的 sklearn 示例相比,它无疑需要更多的代码行、更多的思考和更长的训练时间。亲爱的读者,我向你保证,这一切都是值得的。
首先,PyMC3 在引擎盖下的 Theano 上运行。我们必须对我们的 pandas/numpy 数据做一些细微的修改,最主要的修改是通过设置一个共享张量,如下所示。
When we look to make predictions for our model, we can swap out X_train for X_test and use the same variable name.
现在我们已经建立了数据,我们需要构建我们的模型,我们通过调用 pm 来初始化它。型号()。在这个模型环境中,我们需要建立一套完整的关于先验(参数)和输出的假设。对于您的第一个模型,正态(高斯)分布是相当安全的。
这构成了我们的模型规格。现在我们必须了解模型权重的后验分布。与 sklearn 不同,系数现在是值的分布,而不是单个点。我们对一系列可能的权重进行采样,看起来与我们的数据吻合的系数被保留在一个叫做 trace 的东西中。采样函数(NUTS、Metropolis、等)远远超出了本文的范围,但是有大量的知识库描述它们。在这里,我们从模型中构建我们的跟踪:
NUTS sampler 抱怨说使用 find_MAP()不是一个好主意,但是这经常在教程中使用,并且似乎没有影响我的性能。
我们还可以尝试一种不同的采样器,试图逼近后验分布:
轨迹可以被绘制出来,通常看起来像这样。 beta 参数在分布上看起来相当受约束(左图),并且在我们跟踪的最后 1000 个采样项目上看起来相当一致(右图)。阿尔法参数看起来不太确定。
现在我们有了后验样本,我们可以做一些预测。我们通常会在 PyMC3 中观察到一个所谓的“老化”期,在此期间,我们会丢弃跟踪的前一千个样本( trace[1000:] ),因为这些值可能没有收敛。然后,我们从该轨迹中抽取 1000 个样本权重,计算可能的预测,并取该值的平均值作为该数据点最可能的预测。从这里,我们简单地计算 RMSE。
如果我们想在维持数据集上进行测试:
因此,我们建立的这个模型比我们的原始方法(平均乘客量)表现得更好,但比我们的 sklearn 模型稍差。在 Github repo 中包含的一个示例中,我能够通过缩放 Y 值并将其建模为正态分布变量来构建一个类似的模型,该模型优于 sklearn 模型。
进一步调整模型参数,使用不同的标度,假设更宽范围的可能β参数都可以用来降低这个例子的 RMSE。这篇文章的目的是介绍模型构建的基础知识,并提供一个可编辑的例子,你可以尝试和学习!我鼓励你在下面的评论区提供反馈。
总而言之,贝叶斯模型是有代价的。实现和编写模型肯定需要更长的时间。这需要一些贝叶斯统计的背景知识。训练时间比使用 sklearn 长几个数量级。然而,像 PyMC3 这样的工具可以为您的数据和模型工件提供更好的控制、理解和欣赏。
虽然 PyMC3 中有很多好的教程(包括它的文档页面)但是我找到的最好的资源是 Nicole Carlson 的视频。它探讨了熟悉 sklearn 的数据科学家如何构建 PyMC3 模型。细心的读者会发现我从那个视频中采用了许多例子。我还从概率编程和黑客贝叶斯方法中学到了很多,这是一个基于笔记本的免费教程,介绍使用 PyMC3 的实用贝叶斯模型。这两个资源绝对惊人。杜克大学也有一个示例网站,其中有大量数据情况,我发现这些数据很有参考价值。“走向数据科学”在这一年里也发布了许多关注贝叶斯分析的酷帖,并帮助激发了这篇帖子。
在下一篇博文中,我将说明如何构建一个分层线性模型(HLM ),这将极大地提高我们最初方法的性能。下面是一个可以派生的 Kaggle 内核和一个 Github repo,你可以克隆它来处理数据和开发你自己的 PyMC3 模型。感谢您的阅读!
[## 逐日预测| Kaggle
编辑描述
www.kaggle.com](https://www.kaggle.com/franckjay/daybydaypredictions)
Github 回购
基于 PyMC3 的职业掩护比赛贝叶斯建模
原文:https://towardsdatascience.com/bayesian-modeling-of-pro-overwatch-matches-with-pymc3-f1b7d5fc22f1?source=collection_archive---------16-----------------------
Photo by AC De Leon on Unsplash
职业电子竞技变得越来越受欢迎,这个行业正在迅速发展。这些职业游戏联盟中的许多都是基于有两个团队进行比赛的游戏。使命召唤、英雄联盟、守望相助都是例子。虽然这些可以与传统的团队运动相媲美,但电子竞技的新颖性意味着人们对预测这一新兴行业的结果关注较少。
你如何模拟对抗性团队游戏?我最初是在阅读克里斯托弗·毕晓普(Christopher Bishop)的新机器学习电子书时受到启发开始这个项目的,其中有一章专门介绍了使用 Elo 评级系统计算游戏中玩家的排名。对于那些熟悉国际象棋的人来说,你可能以前遇到过这个指标。我在数据怀疑论者上找到了一篇非常有启发性的博文。下面贴的所有方程式都是从前面提到的怀疑论者那里借来的。
本质上,Elo 是一个框架,用一个单一的数字(R1 = 2000)来衡量一个玩家的实力。任何给定球队的预测实力由逻辑函数( R )表示,给定比赛的结果由单个球队的实力与其得分之和的比率表示( E )。
Logistic Function for player i.
Expected Outcome for player i
如果一个力量为 2000 的玩家面对一个 Elo 等级为 1000 的玩家,我们可以预测前者很有可能获胜( E=0.9968 )。
Rating update for player i (K~32 in Chess)
在每场比赛结束时,球员的分数会根据他们的相对实力进行更新。如果被看好的玩家赢了(S_i = 1.0),他们的分数会有一个小的正调整。如果失败者赢得了比赛,他们可以获得更大的金额,因为结果是出乎意料的。在给定的处于劣势的一方获胜的例子中,他们的分数将从 1000 变为 1031。受青睐的玩家的分数也会降低。
这和非常受欢迎的团队射手看守有什么关系?我想知道,有人如何能够在不求助于令人难以置信的复杂架构的情况下,对如此动态的基于团队的运动的难以置信的复杂性进行建模?我在 PyMC3 网站上看到了一个关于使用分层正态分布对职业橄榄球队进行编码的示例代码。刚刚写了一篇关于等级模型的博文,我想我可以尝试类似的东西!
本质上,我们将每个团队视为一个单独的实体。尽管团队由多个成员组成,每个成员都独立工作。我们将从两个方面证明这一选择:1)将一个团队建模为一个单独的等级,而不是每个单独的玩家,更容易;2)队友们在一起工作(理想情况下),因此他们可以被建模为一个集体单位。如果两个队以前没有交手过,Elo 等级也是非常有用的。没有任何历史比赛,我们可以利用两个对手共有的团队比赛来进行预测。
数据从守望联盟 2018 赛季刮来的。不幸的是,我们可以用来训练模型的比赛并不多。由于 2019 赛季正在进行中,任何感兴趣的读者都可以开始将这些数据添加到模型中,看看它的表现如何!在训练我们的模型之前,必须清理和处理原始数据格式。
Win/Loss aggregations for the regular season
我们可以用两种基本方法来表示我们的数据,这将改变我们构建模型的方式。最简单的方法是让这成为一个分类挑战。每场看守对决都包括多个回合,比赛的获胜者将获得最多回合的胜利。例如,旧金山冲击以 3 比 2 击败佛罗里达大混乱。我们可以将这表示为数据中总共 5 个记录,具有不同程度的成功和失败(0/1)。
Classification or Bernoulli trial for this simple example
我们可以如下构造我们的数据分割。对于常规赛中的每一场比赛,我们都将每一场输赢建模为一个二元目标。每个团队的 Elo 评级将根据上面列出的等式进行推断,这些等式将评级转换为伯努利试验。然后,我们将使用我们学到的评级来预测季后赛中的所有比赛。我们的 PyMC3 模型将包含一个二项式:对于给定的比赛,我们预测成功还是失败?
A sample trace of our simple model.
我们也可以用分数来表示我们的比赛。同样是一场 3 比 2 的比赛,旧金山休克队获胜,我们可以把它编码为 0.6 分。现在我们有了稍微多一点的灵活性,因为我们可以将它建模为一个回归任务,或者仍然保持它作为一个分类。这个结果也为模型提供了更多的细微差别。一场 0.8 分的胜利比一场 0.6 分的胜利对同一个对手要有利得多。
The ROC suggests the model is decent at predicting matchups
不管您的选择如何,训练误差似乎相当稳定。我们的模型能够根据他们的 Elo 分布预测哪个队会赢。当我们把这种模式应用到季后赛中会发生什么?
我们在季后赛评估中做了一些假设:
- 常规赛结束的球队在技术、球员、策略等方面都是固定的。
- 季后赛足够重要,不太可能发生的事件不能主导结果(少量样本)
- 我们的常规赛在所有球队中公平分配(循环赛)
这些假设肯定会露出丑陋的嘴脸。2018 年季后赛只有 12 场,淘汰来得很快。这意味着,如果一个球队有一场相当糟糕的比赛,这不是他们真正技术的特征,他们可能没有机会挽回自己。当真正的挑战出现时,球队也可以增强实力,这是季后赛的本质。
当我们将我们的模型应用于季后赛数据时,我们得到了非常差的性能。我们的模型还不如随机猜测!这里发生了什么?
Playoff Record and the predictions
简单来说,我们有几个团队颠覆了苹果车。费城融合(第 9 队)击败了波斯顿和纽约州(赢了 4/5 场比赛),尽管 Elo 评分较低。Fusion然后输给了伦敦 Spitfire,尽管排名比 LA Valiant* 低,但后者最终赢得了比赛。真不敢相信这就是为什么人们喜欢看体育比赛,因为你永远不知道谁会赢。*
如果你渴望尝试一些不同的贝叶斯方法来玩这样的游戏,艾伦·唐尼的书 Think Bayes 有一节是关于通过泊松过程和他们的历史得分记录来建模团队的。最近 Tuan 发表了一篇关于建立职业足球联盟投注策略的文章。
请随意通过我的 Kaggle repo 下载数据和我的笔记本。我还有一个 Git 回购一些精选笔记本。请在下面留下你的评论或问题,我会尽力回答。感谢阅读!
张量流概率中的贝叶斯神经网络:快速入门。
原文:https://towardsdatascience.com/bayesian-neural-networks-in-10-mins-in-tfp-c735ec99384f?source=collection_archive---------9-----------------------
前言:贝叶斯神经网络允许我们利用不确定性,因此允许我们开发稳健的模型。因此,关于不确定性的知识是开发健壮和安全的机器学习技术的基础。在这篇文章中,我们概述了两种主要类型的不确定性,以及如何通过简单模型使用张量流概率对它们建模。我们采用贝叶斯框架,它适用于深度学习和强化学习。为了完整起见,让我们重申一下贝耶法则:后验概率是先验概率乘以可能性。
*后验,P(H|E) =(先验 P(H) 似然 P(E|H))|证据 P(E)
其中 H 是一些假设,E 是证据。
在贝叶斯世界中,我们使用概率分布。例如,考虑我们是否使用高斯分布作为先验假设,个体概率为 P(H)。我们知道这个先验可以用一个均值和标准差来表示,因为我们知道它的概率分布函数。
我们应用 Bayes 规则,在观察到一些证据 E 后,得到后验分布 P(H|E),这个分布可能是也可能不是高斯!假设如下图所示的对数正态分布,也可以用均值和方差及其概率密度函数来表示。这种使用分布的概念允许我们量化不确定性。在模型方面,假设是我们的模型,证据是我们的数据。
不确定性可以分为两大类:
任意不确定性(又名已知未知)
这是一种增加更多数据也无法解释的不确定性。例如,在掷硬币的随机性{H,T}中,我们知道 p=0.5 的结果将是随机的,进行更多的实验,即掷硬币不会改变这种不确定性,即每个结果/数据点具有相同的概率 0.5。
一个具体的深度学习示例是自动驾驶汽车、医学图像分割(患者在扫描仪中的移动非常常见)、金融交易/风险管理,其中生成我们的数据/观察的底层过程是随机的。来源包括不同种类的设备/传感器(包括摄像机和与之相关的问题),或金融资产和拥有它们的交易对手,对象不同。在医学上,这些可能是不同的基因型,有不同的临床病史。这里,如果不确定性估计值很高,我们不会开诊断处方。事实上,如果医生不知道根本原因,他们可能会进行专家咨询。
任意的不确定性,不会随着样本数据集的增加而增加。因此有两种类型同方差(常数/任务相关)和异方差(变量)随机不确定性。
我发现从一个例子开始很有用(这些例子来自 Josh Dillion,他在 Tensorflow dev submit 2019 上展示了非常棒的幻灯片)。考虑 Keras 中的以下简单模型,其中我们将先验置于目标函数之上,以量化我们估计中的不确定性。注意红线是线性拟合(β),绿线是线性回归β的标准差
完整的自下而上示例也可从获得,建议阅读。
认知不确定性(又名未知的未知)
这是数据驱动的不确定性,主要是由于缺乏训练数据。通过将先验置于神经网络的权重 w 之上或采用大型训练数据集,采用变分/近似推理(例如贝叶斯的反向支持)来减少认知不确定性也是可行的。
Alex Kendal 和 Yarin Gal 在他们的博客文章和论文《有原则的方式》中将这些结合起来用于深度学习。它们在这些背后提供了基本的数学基础。
在我们讨论的例子中,我们假设一个 1 层隐藏网络。如果我们不知道模型或目标函数的结构会怎样?
我们可以使用高斯过程,高斯过程优先于函数!注意函数而不是变量(例如网络或目标/损失函数的权重)!下面是一个玩具示例。神经网络是一种函数估计器。我们将在另一篇文章中详细讨论这些问题。
但是通过改变我们的目标函数,我们获得了更好的数据拟合!!
希望仔细阅读这三张幻灯片可以展示贝叶斯框架的力量和它与深度学习的相关性,以及它在张量流概率中是多么容易。总结一下的要点
- 我们可以应用贝叶斯原理来创建贝叶斯神经网络。
- 在贝叶斯框架中,将先验分布置于神经网络、损失函数或两者的权重之上,我们基于证据/数据学习后验分布。这允许通过放置先验权重和目标函数,通过获得由我们的数据最佳解释的后验概率,来减少/估计建模中的不确定性。
- 例如,可以通过放置先验过损失函数来管理任意不确定性,这将导致模型性能的改善。
- 认知不确定性可以通过先验加权来减少
- 高斯过程,可以允许确定最佳损失函数!
- 这一切都归结为后验计算,需要采样方法或变分推断技术来近似后验分布。
- 当前的限制是在大规模或实时生产环境中进行这项工作是后验计算。变分推理技术和/或有效的采样方法来获得后验是计算要求高的。特别是在处理具有数百万个参数的交易学习模型时。Yarin Gal 提供了一个特别见解,他认为漏失是深度模型的合适替代。推导和详细解释见 Yarin 的博文。然而,还需要做更多的工作。
- 当前技术水平已经在张量流概率中可用
贝叶斯神经网络(LSTM):实现
原文:https://towardsdatascience.com/bayesian-neural-networks-lstm-3616327e8b7c?source=collection_archive---------10-----------------------
贝叶斯推理允许量化不确定性,因此,能够开发健壮的机器学习模型。在实践中,需要采用抽样方法来近似贝叶斯设置中遇到的后验分布/积分。对于实践中典型使用的大型神经网络,采样方法是计算密集型的。变分推理方法已经被发展来克服这个限制。在早先的帖子中,我们讨论了实践的理论方面,变分推理算法,Bayes (BBB)的 Back Prop。BBB 通过设置权重先验,提供了一种减少认知不确定性的有效方法。认知不确定性通常与缺乏训练数据有关。在这篇文章中,我们考虑了 BBB 的实际应用,特别是对 LSMT 的应用。
From Fortunato et al, 2017
Tensorflow probability 已经为标准层提供了一个实现,比如密集、卷积。下面显示了一个网络模型示例,请注意,API 与 Tensorflow API 非常相似。因此,如果您需要使用这些标准图层之一,请查阅官方文档。
LSMT: 需要更多工作的一个例子是 LSTM。LSTM 是一类递归神经网络。Colah 的博客对此做了很好的解释。LSTM 的一步一步的 Tensorflow 实现也可以在这里找到。如果你对 LSTM 的基本知识不确定,我强烈建议你在继续之前阅读它们。 Fortunato 等人,2017 年验证了贝叶斯 LSTM。原始源代码是可用的,不幸的是,我发现它很难跟上。
实现包含 LSTM 的这四个方程
我们需要权重的先验和变分后验。
我们通过为每个权重指定其(均值=0,标准差=1)来使用正态/高斯先验。
通过效用函数获得每个权重“w”的变分后验概率
该函数还计算这些权重的 KL,并将其添加到张量流集合中。该功能在 github 上可用。
为了实现贝叶斯 LSTM,我们从 tensorflow 的基本 LSMT 类开始,并通过向权重添加变分后验来覆盖调用函数,之后我们照常计算门 f、I、o、c 和 h。这里的非常简单明了。
这确保了我们拥有一致的 tensorflow API,然后能够在此基础上构建我们的模型,例如,使用多层 LSTM 的情感分析任务。请注意,结果测量的不确定性相当简单(二元)。
这里我们定义贝叶斯 LSTM 层,并通过单元格函数执行展开。这个实现的一个缺点是不能使用 tf.nn.dynamic_rnn,因为它会产生与梯度检查相关的循环错误。
然后,我们可以获得逻辑和损失,注意,我们对 softmax 层采用变分后验概率
在训练中,我们获得了我们创建的每个变分后验概率的 KL 集合。这使我们能够计算总 KL 损失,除以批量大小以获得基于证据的下限,如 Fortunato 等人的论文中所述。
仅此而已。其余代码只是标准数据输入和训练循环,模型保存等可以在这里找到。然后我们可以补充文中提到的其他方面。
贝叶斯噩梦。解决了!
原文:https://towardsdatascience.com/bayesian-nightmare-how-to-start-loving-bayes-1622741fa960?source=collection_archive---------7-----------------------
通过 Python PyMC3 中的示例和代码对贝叶斯数据分析进行了温和的介绍。
在本文中,我们提供了一种温和而实用的方法来轻松使用贝叶斯机器学习。结合实例和说明,介绍了先验、生成模型、后验分布、贝叶斯定理、可信区间等贝叶斯概念。你将在使用 Python 的营销活动中应用贝叶斯方法来估计注册率。20 世纪被零假设显著性测试所主导,而 21 世纪正在变成贝叶斯(来源:JK Kruschke)。
如果你看完这篇文章还没有开始热爱贝叶斯,那就向拉普拉斯伸出援手吧!
credits: Sophie Madeleine
谁没听说过贝叶斯统计很难,计算速度慢,无法扩展到大数据,结果是主观的;而我们根本不需要?在接触贝叶斯技术之前,我们真的需要先学习大量的数学和经典统计学吗?为什么最流行的关于贝叶斯统计的书都有 500 多页?
贝叶斯噩梦是真实的还是神话?
有人曾将贝叶斯方法比作米其林星级厨师的厨房,配有高质量的厨师刀、汤锅和昂贵的煎锅;而频率主义就像你的普通厨房,有香蕉切片器和意大利面锅。人们谈论 Bayesianism 主义和 Frequentism,好像他们是两个不同的宗教。你是哪个厨师?Bayes 真的在一开始就给数据科学家增加了使用大脑的负担吗?因为 Bayesian 主义是最聪明的人的宗教?“贝叶斯”这个词到底对不对?
source
贝叶斯数据分析的构建模块
贝叶斯方法的本质特征是在基于统计数据分析的推理中明确使用概率来量化不确定性。最近,人们越来越重视区间估计,而不是假设检验。这为贝叶斯观点提供了一个强大的驱动力,因为大多数标准置信区间的用户似乎通过常识给出了贝叶斯解释。如果需要的话,我们建议浏览下面的文章作为概率的复习。
[## 理解概率。终于!
数据科学家概率概念实用指南
towardsdatascience.com](/understanding-probability-finally-576d54dccdb5)
数据分析的贝叶斯方法通常需要数据,一个生成模型和先验。在传统方法中,数据用于拟合线性回归线,例如,为了估计最适合描述线性趋势的截距和斜率。没有直接的方法来包含我们对正在估计的那些参数的先验信念。贝叶斯方法允许我们基于我们现实生活中的领域知识和常识,对截距和斜率进行事先的良好猜测。此外,我们还可以陈述这个猜测的不确定性。例如,我们可以说,根据经验,斜率是从具有均值μ和标准差σ的正态分布绘制的,而典型截距值将是具有均值θ 和标准差ρ的正态分布。给定描述我们先前信念的分布,我们可以使用生成模型生成模拟数据,如下图所示。
source
用贝叶斯方法估计注册率
让我们考虑一个现实生活中的例子,我们感兴趣的是估计销售漏斗中的线索转化率:有多少网站的访问者变成了付费客户。通常情况下,营销部门会开展一项活动来吸引观众并鼓励他们注册。如果我们观察到 16 个访问者中有 6 个注册了,这是否意味着注册率 θ 是 6/16=38%?这个百分比有多大的不确定性,尤其是在数据量很小的情况下?贝叶斯数据分析有助于找到这些问题的答案。
先验信念
我们从寻找先验开始,这是销售部门根据经验或给定的行业现状观察到的典型注册率的信念。让我们假设,根据销售额,0%到 100%之间的任何注册率都是同样可能的。因此,我们可以将注册率的先验分布设为均匀分布。
样本生成
接下来,我们构建了一个生成模型,该模型针对之前发行的任意随机选择的注册率来模拟大量营销活动。例如,如果选择 55%作为注册率,这就像问 16 个潜在客户,其中每个客户注册的机会是 55%。因此,生成模型是参数为 16 和θ的二项式分布。我们模拟生殖模型 10 万次。每次,我们从均匀分布中抽取一个随机θ,并通过从二项分布中创建 16 个“假”客户来运行生成模型。在这个过程结束时,我们有 100,000 个样本。
后验分布
现在,是时候引入我们的数据了,它告诉我们,真正的营销活动取得了什么,这是 6/16=38%的注册率。因此,我们过滤掉模拟注册率不是 6/16 的模拟样本,只保留那些模拟注册率是 6/16 的模拟样本。下图显示了这一过程。请注意,相同的先前抽奖(例如 21%)可以从二项式分布中产生不同的注册率(例如 4/16 和 6/16)。
下图说明了贝叶斯抽样和剔除过程。
source
现在,我们一方面考虑来自均匀分布的所有 100,000 次θ抽取,另一方面,我们查看在过滤掉那些没有产生 6/16 注册率的样本后保留的θ。如果我们计算两个桶中每个值的频率,那么我们最终得到下面的直方图。
source
结果解释
蓝色曲线显示了注册率的所谓后验分布。这就是我们一直在寻找的答案。正如我们所看到的,注册率是相当不确定的,我们不能 100%肯定地说它是营销部门发现的 38%。很可能在 20%-60%之间。利用后验分布,我们可以给出关于不确定性的陈述。最有可能产生我们观察到的数据的参数值将是后验分布中概率最高的注册率:38%。这也叫最大似然估计,是经典统计学中估计未知参数最常见的方法之一。这就是为什么贝叶斯方法可以被视为最大似然估计的扩展。我们还可以计算所有概率的均值,即后验均值作为注册率 39%的最佳嘉宾。通常还会计算包含后验分布中 90%概率的最短区间,称为可信区间,在这种情况下,可信区间介于 30%和 40%之间。因此,我们可以说,有 90%的概率签约率在 30%到 40%之间。
16 个销售线索中有 6 个注册并不总是意味着 38%的注册率!
贝叶斯定理
我们是如何从先验走向后验的?我们来看一个例子,我们从均匀分布中画出θ=35%,概率为 P(35%)。为了不丢弃θ,它必须允许我们模拟与营销数据相匹配的数据。换句话说,在θ=35%的情况下,有 6 次注册的概率 P(6|35%)。通过将这两个量相乘,我们得到绘制θ=35%的概率,并模拟与我们观察到的注册率相匹配的数据。该值将与 35%的概率成比例,该概率是导致 6 个观察到的注册的最佳参数值。如果我们将该数量除以产生所有可能参数值的数据的总概率,我们得到在给定数据 P(35%|6)的情况下具有 35%注册率的确切概率。当我们对从先验分布中提取的所有注册率重复这一过程时,我们获得了绘制蓝色直方图所需的所有概率,即后验分布。下图说明了这一过程。
source
上面的练习可以扩展到多参数θ、任何生成模型和任何数据集 d。这种概括由下面的等式说明,通常称为贝叶斯定理。
source
缩放贝叶斯数据分析
为了说明贝叶斯数据分析的普遍性,让我们考虑营销部门实际上开展了两次活动。在第一个实验中,他们获得了 6/16 的注册人数,而第二个实验的结果是 10/16 的注册人数。此外,销售部门事先认为注册率从未超过 20%,过去一直在 5%到 15%之间。现在,我们有两个参数 θ 1 和θ2 以及两个生成模型。我们还得到一个不均匀的信息先验,我们可以用参数为 2 和 25 的 Beta 分布来表示,如下图所示。
source
我们现在可以从两个生成模型中抽取 100,000 个样本,保留那些匹配的营销数据,并构建两个后验分布,每个活动一个。当考虑销售人员的先验信念时,后验分布可用于得出活动有效性的结论。我们还可以通过计算两个后验分布之间的差异来比较这两个活动。
source
贝叶斯线性回归
在我们对贝叶斯哲学感到更舒服之后,我们将对更扩展的营销数据集执行贝叶斯线性回归,该数据集描述了线索转化( y 对时间( x )的关系。在下图中, x 表示在时间 x=0 推出新公司网站前后的周数,其中 x=-10 为推出前 10 周, x=+10 为推出后 10 周。 y 表示 y 正值的签约率,或者 y 负值的流失率。当网站失去访问者时,就会发生流失。营销感兴趣的是估计未来预期的注册率或流失率的不确定性。
正如前面几节所介绍的,贝叶斯统计是一种将概率应用于统计问题的数学方法。它为人们提供了工具来更新他们对新数据证据的信念。贝叶斯定理描述了基于数据的事件的条件概率,以及关于事件或与事件相关的条件的先验信息或信念。贝叶斯定理可用于计算后验概率(考虑新信息后事件发生的修正概率)。通过更新先验概率来计算后验概率。先验概率是基于实验前的现有知识的结果的概率。
贝叶斯线性回归可能允许一种有用的机制来处理数据不足或分布不良的数据,就像上面图中出现的情况一样。它允许我们在参数和噪声上加上一个先验,这样在没有数据的情况下,先验就可以接管。
生成模型
在贝叶斯观点中,我们用概率分布来表述线性回归。响应 y 不被估计为单一值,而是假设从概率分布中提取。
然而,根据线性回归方程,我们认为 y 最可能的值如下。
尽管 μ 是 y 的最可能值, y 也可能包含一些误差或噪声。因此,我们通过调整方差项 σ 来补偿 y 与 μ 的偏差,从而对观测值中的这种误差 ϵ 进行建模。
传道者
不仅响应是由概率分布生成的,而且模型参数也被假定来自一个分布。假设 y 上的噪声呈正态分布,我们还包括斜率和截距的先验信息,如下所示。
后验分布
模型参数的后验概率取决于训练输入和输出:
上面的等式再次反映了我们之前在一个更简单的例子中学到的贝叶斯定理。到目前为止,我们通过生成 100,000 个样本并排除那些与数据不匹配的样本来计算后验概率的特定计算方法仅在极少数情况下有效。它被称为近似贝叶斯计算。尽管它在概念上很简单,但对于大型数据集来说,它可能会慢得令人难以置信,而且伸缩性也很差。还有更快的方法,主要是所谓的马尔可夫链蒙特卡罗 ( MCMC )算法家族。具体流行的例子包括汉密尔顿蒙特卡罗和大都会-黑斯廷斯。
下面我们使用 Python 库 PyMC3 实现 MCMC 来寻找模型参数的后验分布。
贝叶斯模型提供了比普通最小二乘回归更多的解释机会,因为它提供了后验分布。贝叶斯线性回归将给出模型权重的后验分布,而不是模型权重的单点估计。我们可以使用这个分布来找到最可能的单个值,以及模型参数的整个可能值范围。
PyMC3 有许多用于可视化和检查模型运行的内置工具。这些让我们看到分布,并提供一定程度的不确定性的估计,这应该是任何模型的必要部分。下面我们看到所有模型参数的轨迹。轨迹图往往围绕真实参数呈正态分布,这是样本向目标分布收敛的好迹象。
pm.traceplot(linear_trace, figsize = (12, 12))
结果解释
模型参数的后验分布如下所示。营销部门预计注册率(斜率)平均每年增长 4.7%。有 94%的可能性签约会以 4.4 之间的速率增加。%和未来的 5.1%。网站启动时的注册率(在第 0 周截距)在 4.6%和 7.2%之间,概率为 94%。签约率的标准差预计平均为 6.6%。
pm.plot_posterior(linear_trace, figsize = (12, 10), text_size = 20);
我们还可以可视化模型参数的可信区间。注册的变化率(斜率)比第 0 周的注册率具有更小的不确定性。
pm.forestplot(linear_trace);
贝叶斯数据分析的优势
我们还可以使用模型结果生成线性回归线的预测。下图显示了从后验概率绘制的回归线的 100 个不同估计值。线的分布给出了估计中不确定性的估计。贝叶斯线性回归的好处是,它给我们一个后验分布,而不是一个单点估计的频率普通最小二乘回归(OLS)。
结论
在这篇文章中,我们对统计学和机器学习的贝叶斯方法做了一个简单的介绍。特别是,我们量化了营销活动中注册率点估计的不确定性。结合实例和说明,介绍了先验、生成模型、后验分布、贝叶斯定理、可信区间等贝叶斯概念。我们还介绍了使用贝叶斯方法的线性回归的 Python 实现,并将其与经典的普通最小二乘法进行了比较。本文对 PyMC3 提供了一些提示,pymc 3 是一个用于贝叶斯分析的简单易用的 Python 库。
不要试图在一篇文章中塞进太多内容,你可以转向书籍,比如 Andrew Gelman 等人的 Bayesian 数据分析。艾尔。
这篇文章的灵感来自拉斯穆斯·巴斯的材料,他以非常直观的方式讲授贝叶斯数据分析。我强烈推荐他在数据营关于 R 的贝叶斯数据分析基础的课程和他在 YouTube 上的视频。
好吧,这篇文章不知何故已经激发了读者开始喜欢 Bayes。如果你仍然喜欢机器学习的非贝叶斯方法,我可以理解。在这种情况下,你会得到我下面的文章。
[## 深度学习为什么有效:解决一个农民的问题
在开始是神经元:梯度下降,反向传播,回归,自动编码器,细胞神经网络…
towardsdatascience.com](/why-deep-learning-works-289f17cab01a)
交易中的贝叶斯优化
原文:https://towardsdatascience.com/bayesian-optimization-in-trading-77202ffed530?source=collection_archive---------13-----------------------
算法交易和机器学习有类似的问题。今天,我将展示如何应用贝叶斯优化来调整交易策略超参数。
让我们假设你用几个超参数创建了一个交易策略。这种策略在回溯测试中是有利可图的。您希望将策略部署到生产模式,但是还有一个问题:“这组参数是最优的吗?”。
通常,网格搜索方法用于搜索最佳超参数。这种方法也用于机器学习,但这需要大量的计算,通常在错误的参数空间中。
另一种方法是随机搜索,它的性能比网格搜索稍好。
我在 Quora 上找到了一个很棒的解释:
问题:目标是找到某个“昂贵”函数的近似最小值。这样一个函数接受一个实值向量 𝐱 ∈ℝ,返回一个标量,并且花费了相当长的时间。此外,没有可用的梯度计算。让我们想象一个简单的一维情况:
虚线暗示我们看不到这个函数——我们只能选择在某些点上对它求值。
因为这个函数是昂贵的,假设我们有一个固定的评估预算——我们可能只评估它,比如说,10 次。
有了这个,你如何找到最好的最小值?
想法是这样的:对一些输入-输出(少于 10 个)进行采样,并使用它们用一种叫做“高斯过程”(或这里的“GP”)的东西来猜测真正的函数。然后使用猜测函数来确定下一步在哪里求值。评估该点,将其添加到我们的输入-输出集,并再次推断猜测的函数。重复这个过程,直到你用完了你的评估预算(或者其他一些停止标准)。如果 GP 擅长猜测真实函数,我们会比随机抽样做得更好。
为了对 GP 有一个感觉,让我们从我们昂贵的函数中抽取四个点,把它们交给 GP,让它推断函数的其余部分。可能是这样的:
绿色实线是我们对真实函数的猜测。每增加一个绿色条带,就是输出分布的另一个半标准差。
所以现在问题变成了:给定所有这些有用的猜测信息,我们下一步应该检查哪一点?在回答这个问题时,我们关心两件事:
我们应该评估我们认为会产生低产值的点。也就是说,我们应该评估绿色实线较低的点。
我们应该检查我们不太了解的领域。因此,在上图中,检查 0.65 和 0.75 之间的某个位置比检查 0.15 和 0.25 之间的某个位置更明智,因为我们对后一个区域的情况有相当好的了解。换句话说,我们应该检查最能减少我们猜测中的方差的区域。
平衡这两者是勘探开发的权衡。到目前为止,你会寻找新的地点或者开发你已经发现的金矿吗?我们用一个获取函数来明确我们的偏好。这是𝑥x 的一个函数,它将产生一个数字,告诉我们这两个目标实现得有多好。这个函数很便宜,所以我们可以优化它,并使用𝑥x 作为我们下一个搜索点。
那么哪个采集函数呢?嗯,有几个选择,但我会选择期望改善。也就是说,评估预期改进最高的下一点。
所以如果:
𝜇(𝑥)μ(x)是𝑥x 函数的猜测值(绿线)。
𝜎(𝑥)σ(x)是𝑥x 产量的标准偏差(与绿色带成比例)。
那么我们对改善的获得/期望(称之为𝐴(𝑥)A(x))是:
其中φ(⋅)和 N(⋅)分别指标准正态分布的 CDF 和 PDF。准确理解这个公式并不重要——只要知道它是低𝜇(𝑥)μ(x 和高𝜎(𝑥)σ(x).的某种平衡
要了解这是如何操作的,请查看我们之前的图表:
这将告诉我们检查𝑥=1,因为该点的激活度最高。
然后重复。就是这样!就像我之前说的,如果 GP 擅长猜测真实函数,它会击败随机抽样。
这篇文章比较了机器学习中超参数调整的不同方法。它表明贝叶斯优化是一种比随机、网格搜索或手动更好的方法。
贝叶斯优化
Siraj Raval 的这段视频也有很好的解释:
如果你想深入这个话题,你应该阅读这篇文章。
实际例子
我们将考虑我之前讨论过的一个策略。该策略有 4 个超参数,让我们定义所需的库:
贝叶斯优化在hyperpt包中实现。你可以在 Will Koehrsen 的文章中找到这个包的介绍。
通常,研究者使用回测来寻找最优超参数和样本外检验进行评估。我喜欢这种方法,但是我认为如果我们使用一些回溯测试周期(折叠),我们可以得到一个更有意义的结果
当折叠更接近样本期外时,则折叠在最终加权分数中具有更大的权重。
此外,如果某个文件夹的性能不佳,该函数应该惩罚最终值。作为交易中的一个评分函数,你可以使用成交比率,或者任何评估策略质量的函数。就我们的目的而言,值越低越好。这意味着我们应该反转 Sortino 比率值。
在本例中,我们将使用:
- 训练(优化)步骤一个月五倍
- 一个月为测试期,三周为验证期(出样期)
测试阶段允许选择将在验证阶段进行测试的配对。
- 培训时间:2018 年 6 月 1 日至 2018 年 10 月 31 日
- 测试时间:2018 年 11 月 1 日至 2018 年 11 月 30 日
- 验证期:2018 年 12 月 1 日至 2018 年 12 月 21 日
让我们定义周期、超参数空间和一个weighted_mean
函数。该代码允许通过period_weights
定义不同的折叠长度。
下一步是定义运行算法和测量性能的得分函数(在本例中是 Sortino ratio)。
这个函数太长了,因为它还包含了上一篇文章中算法的嵌套函数。用于将参数从hyperopt
包传递到催化剂框架的替代变体是使用os.environ
模块。如果你知道更好的方法,请在评论中告诉我。也许来自谜项目的人会给出正确的答案。
核心是objective
函数,通过weighted_mean
函数衡量几个褶皱的表现,否则取最大褶皱(惩罚)。
接下来的代码运行 300 次迭代的优化。
输出如下所示:
此表包含按分数排列的试验前几名。最后一行是最佳超参数集。我使用 Bitfinex 数据为 ETH/BTC、LTC/BTC、XMR/BTC 和 ZEC 等公司进行了这个实验。
理论上可以把objective value
在 3D 空间中可视化,像维度 1 — 维度 2 — 目标值,最优解具有全局最小值:
3D space of objective function
该超参数表显示了每项资产的最佳参数值:
Best hyperparameters
资产选择(测试步骤)
在这一步,我们应该在测试阶段为特定资产运行具有固定超参数的策略。具有正面性能的资产将被选择用于下一步(样本外测试)。
这个代码允许这样做,你只需要改变超参数并设置加密货币。
如您所见,两项资产(ETH/BTC 和 XMR/BTC)取得了积极的业绩。
Testing period performance
样品外测试(验证步骤)
当我们找到最佳超参数和选定的资产时,我们可以在不用于优化的时段(验证时段)运行交易算法。
让我们根据这两种资产建立一个投资组合。在 t = 0 时,根据其目标值(-15.45 和-9.72)的比例设置每个资产资本。
理论上,每项资产的权重可能不同。例如统一分配或其他方法。投资组合的最终权益结合了这些资产的表现。
Equity and drawdowns of portfolio
Performance of portfolio
总的来说,该策略在样本外期有积极的表现。表中展示了基本指标。
正如你在上面的图表中看到的,提取期太长了。很可能,算法无法适应之前快速增长后的下降。你可以在制定目标函数时考虑到这一点。
在测试阶段,我们从投资组合中剔除了两项资产(LTC/BTC 和 ZEC/BTC)。让我们看看这是不是一个正确的决定:
Dropped out assets
是的,这个决定是正确的。如果包括这些资产,投资组合会更糟糕。混淆矩阵看起来像这样:
Confusion matrix
如我们所见,我们没有 I 型错误。我们只从投资组合中剔除了 ZEC/BTC,但这一资产在验证阶段表现良好(第二类错误)。在这种情况下,这没有包括一些不能盈利的资产重要。
结论
在本文中,我们介绍了以下内容:
- 建议优化交易策略的方法,包括培训、测试和验证步骤。
- 公式化的目标函数结合了不同折叠的得分值。
- 你可以在 github 上探索开发的脚本。
这个例子不是最终的交易策略——给定的结果可能是随机的。需要大量的实验才能得出适合交易的结论。
如何改进这种方法:
- 根据你的目标定义你自己的目标和得分函数。
- 定制培训/测试/验证周期。
- 创建一个包含大量资产的投资组合,以测试这种方法可能对你有效的假设。
- 使用移动步行测试获得更有意义的结果。它允许模拟更接近真实交易的情况。你会得到更多的数据用于统计推断。
让我知道你对自己的交易策略使用什么优化方法。
最诚挚的问候,
谢尔盖
贝叶斯优化和量子计算
原文:https://towardsdatascience.com/bayesian-optimization-quantum-computing-27a9cbbf0930?source=collection_archive---------24-----------------------
贝叶斯优化如何帮助量子计算成为现实
量子计算机有可能比传统计算机快得多,这将彻底改变我们目前解决许多应用程序的方式。你可以在这篇详细的文章中找到答案,但是我们距离通用量子计算机还有几年的时间。然而,对于某些应用,贝叶斯优化可以帮助稳定量子电路,这篇文章将在提交给科学的论文中总结 OPTaaS 是如何做到这一点的。这篇论文背后的团队由来自马里兰大学、UCL、剑桥量子计算、思维铸造、中央康涅狄格州立大学、康涅狄格州立大学和康涅狄格州立大学的研究人员组成。
任务
这篇论文背后的研究人员正在一台捕获离子量子计算机上应用一种混合量子学习方案,以完成一项生成性建模任务。生成模型旨在学习数据的表示,以便使后续任务更容易。混合量子算法使用经典和量子资源来解决潜在的困难问题。研究中使用了条纹(BAS)数据集,因为它可以很容易地在包含水平条纹和垂直条纹的图像中可视化,其中每个像素代表一个 q ubit 。
该实验是在一台七位全可编程的囚禁离子量子计算机中的四个量子位上进行的。量子电路被构造成多层参数化的门,这些门将被优化算法校准。下图摘自该论文,说明了该设置。
训练量子电路
研究人员在论文中对训练算法使用了两种优化方法:
- 粒子群优化(PSO):一种随机方案,它通过创建许多随机分布的“粒子”来协作探索地形
- 使用 OPTaaS 的贝叶斯优化:一种全局优化范例,可以通过构建和更新底层目标函数的代理模型来处理多参数函数的昂贵采样。
你可以在下面找到关于贝叶斯优化的更详细的文章:
[## 高斯过程贝叶斯优化背后的直觉
在某些应用中,目标函数是昂贵的或难以评估的。在这些情况下,一般…
towardsdatascience.com](/the-intuitions-behind-bayesian-optimization-with-gaussian-processes-7e00fcc898a0)
优化过程包括对于给定的一组参数,模拟经典模拟器的训练过程,而不是量子处理器。一旦确定了最佳参数,就可以在图 1 所示的离子量子计算机上运行训练程序。用于量化 BAS 分布和电路实验测量值之间差异的成本函数是原始 Kullback-Leibler 散度的变体,详见本文。
结果和展望
PSO 和 OPTaaS 的训练结果如下图所示:
Quantum circuit training results with PSO
Quantum circuit training results with OPTaaS
模拟用橙色表示,离子量子计算机结果用蓝色表示。列(a)对应于具有两层门和全对全连接的电路。列(b)和(c)分别对应于具有两层和四层并开始连接的电路。(a)、(b)和(c)分别有 14、11 和 26 个可调参数。
我们观察到,该电路能够很好地收敛,从而仅对于第一个电路产生 BAS 分布,而对于 OPTaaS,所有电路都能够收敛。根据研究人员的说法,OPTaaS 在 26 参数电路上的成功代表了迄今为止最强大的混合量子应用。
如果你想更详细地了解这项工作,请阅读论文,你也可以从我的个人资料中报名参加 OPTaaS 试验。
【更新:我开了一家科技公司。你可以在这里找到更多的
团队和资源
Mind Foundry 是牛津大学的分支机构,由斯蒂芬·罗伯茨(Stephen Roberts)和迈克尔·奥斯本(Michael Osborne)教授创立,他们在数据分析领域已经工作了 35 年。Mind Foundry 团队由 30 多名世界级的机器学习研究人员和精英软件工程师组成,其中许多人曾是牛津大学的博士后。此外,Mind Foundry 通过其分拆地位,拥有超过 30 名牛津大学机器学习博士的特权。Mind Foundry 是牛津大学的投资组合公司,其投资者包括牛津科学创新、牛津技术与创新基金、、牛津大学创新基金和 Parkwalk Advisors 。
贝叶斯先验和正则化惩罚
原文:https://towardsdatascience.com/bayesian-priors-and-regularization-penalties-6d0054d9747b?source=collection_archive---------16-----------------------
实证检验它们的等价性
Photo by Erik Mclean on Unsplash
执行机器学习的贝叶斯方法提供了几个优于其对应方的优势,特别是估计不确定性的能力和将上下文知识编码为先验分布的选项。那么,为什么它们没有得到更广泛的应用呢?
为了明确地被认为是一种升级,贝叶斯模型必须对所有流行的机器学习模型都有一个等效的理论公式,并恢复在其中观察到的那种预测性能。它们必须同样易于使用。
这些都是艰巨的挑战,有许多技术障碍需要克服。然而,我今天在这里不是为了对概率编程的状态进行哲学探讨。相反,我想花一些时间来探索贝叶斯方法的许多初学者教科书中提出的等价性:贝叶斯线性模型中系数的先验分布与正则化最小二乘回归中使用的惩罚项之间的等价性。
The equivalence we will be exploring
我发现这种二元性令人信服,因为就其本身而言,正规化似乎有点“杂乱无章”知道它可以在一个更大的框架内被理解和形式化是令人欣慰的,这是我认为值得凭经验探究的事情。
这种等价性有许多很好的理论处理方法,因此我选择通过改变正则化线性模型的调整参数来测试它,并查看最大系数的大小以及回归问题的误差是如何响应的。我用贝叶斯 GLM 做了同样的事情,调整了参数先验分布的方差。这是一次有趣的练习,我认为结果值得分享。
该理论
我现在想强调的是,我在这里的目的不是向那些不熟悉的人介绍贝叶斯线性模型。如果你是概率编程新手,并且有 Python 经验,我推荐针对黑客的贝叶斯方法。无论如何,我的目标是提供另一个角度来看线性回归的两个公式是如何等价的。
然而,我将简要概述线性回归的贝叶斯观点。在此公式中,响应变量 Y 被视为随机变量,其平均值等于特征 βX. 的加权和
即Y∞N(βX,σ)。如果噪声项呈正态分布( Y=βX+ϵ,与 ϵ∼N(0,【σ】),这相当于线性回归的标准公式。
此外,我们可以指定参数 β 的先验分布。常见的选择是高斯分布。如果我们将这个分布集中在 0 附近,这将表明我们期望参数很小。为该先验的标准差选择小值将对应于更紧密的分布,表明对小参数的更强的初始信念-类似于正则化最小二乘回归中的大惩罚。
A plot showing the sampled posterior distributions of some model parameters and the “trace” of the sampling.
在概率规划方法中,一个与我们感兴趣的所有随机变量(对于线性模型,系数和截距)的后验分布成比例的非标准化函数是根据贝叶斯定理从数据和先验中生成的。一种抽样算法,通常是马尔可夫链蒙特卡罗的某种变体,然后生成这个后验估计。我使用 PyMC3 来构建我的贝叶斯模型,并对其参数的分布进行采样。
设置
我选择用 Kaggle 上的笔记本来进行我的小型实验。我的理由有两个:
- 我希望其他人能够在不需要安装依赖项的情况下使用代码。
- 我想专注于比较我的模型的行为,Kaggle 提供了干净的数据和一个简单的导入方法
一旦我知道了我想要做的比较和情节,这是一个相当简单的过程。对于那些对技术细节感兴趣的人来说,笔记本的大部分代码都放在这个实用程序脚本中。它包含了我的实验所需的主要成分:
- 一种迭代超参数、训练模型以及报告验证错误和系数幅度的方法。
- 一个贝叶斯 GLM 的实现,带有一个 scikit-learn 风格的 API,可以插入到上面的循环中。
- 一个可以获取结果并生成线图的函数。我使用了我的文章中描述的那种模板,即以编程方式生成 matplotlib 子情节。
结果呢
下面是笔记本为岭(L2)回归和具有高斯先验的贝叶斯线性模型生成的图。如我们所料,使用具有适当范围的对数 x 轴,曲线非常相似。
我们到底看到了什么?首先,让我们回顾一下超参数。
Alpha 是控制岭回归中 L2 罚项的相对重要性的调整参数。损失函数由L = MSE+α| ||θ|给出,其中 MSE 是均方误差, θ 是系数的向量。因此,当α较大时,损耗由这一项决定,将其降至最低的最佳方法是将所有系数设为 0。
适马给出贝叶斯模型中系数先验分布的标准差。该先验被选择为正态(高斯)分布。如果它很小,那么我们的先验非常紧密地以零为中心,并且需要大量的证据(数据)来将参数的后验分布的质量从零移开。
知道了这些,上面的结果有意义吗?让我们看看:
- 随着调节参数α的增加,L2 惩罚模型中的最大系数趋于零。
- 因此,如果你一直只是猜测结果数据的平均值,误差会上升到你会得到的值。
- 同样的事情发生在贝叶斯模型中,因为先验的方差被设置得非常小。
尽管这两个模型背后的实现非常不同,一个依赖于优化,另一个依赖于采样,但我们在选择的两个度量中观察到几乎相同的行为。
结论
贝叶斯线性模型通常作为寻求学习概率编程的入门材料,包含对频率主义统计学习模型的现有理解。我相信这是有效的,因为它允许一个人在现有知识的基础上构建新知识,甚至将已经理解的东西——也许只是许多工具中的一个——放入更广泛、理论上更令人满意的框架中。
贝叶斯线性模型中选择的参数的先验分布和正则化最小二乘回归中的惩罚项之间的关系已经是众所周知的。尽管如此,我觉得我能够通过实证检验调整每个模型的超参数的效果来对这种等价性有一个更直观的理解。我希望我的小实验能为你做同样的事情,并作为现有证据的补充。
贝叶斯排名系统
原文:https://towardsdatascience.com/bayesian-ranking-system-77818e63b57b?source=collection_archive---------9-----------------------
根据不同数量的回复进行排名
注意:假设您熟悉之前中提到的 beta 发行版。
除了计算彩票概率或疾病可能性之外,贝叶斯定理还有其他应用,例如我们可以建立一个排名系统。就拿一个电影排名网站来说吧,用户在这个网站上对电影进行上/下投票。简单的排名方案,如赞成票的百分比或上下票数执行不佳。
百分比 : 60 上升 : 40 下降 — vs — 6 上升 : 4 下降均为 60%
上减下 : 100 上 : 95 下 vs 5 上 : 0 下都是 +5
我们想要的是更多的投票来增加更多的信息;60 票比 6 票更有分量。让我们在贝叶斯推理中使用投票作为可能性。这是一组电影 A-E,带有向上/向下投票和计算的 beta 函数,从均匀 beta(1,1) 开始,在之前:
然而,贝塔分布是一个 PDF,所以我们需要一些算法来转换成一个排名标量。一种方法是找到 beta 分布的最小值,这样我们就有 95%的把握认为真实值更大。这可以通过从平均值中减去一些标准偏差来实现。
排名=平均值+ z 值×标准差
对于正态近似值,累积密度函数 CDF 在 z 得分为-1.64 时为 5%,可以在上面的公式中使用。但是,如果您可以访问 beta 发行版本身的反向 CDF(又名百分点函数),您可以直接使用它:
rank = beta.ppf(0.05,a,b) # python
rank = BETA.INV(0.05,a,b) # Excel, Sheets
rank = qbeta(0.05,a,a) # R
产生以下结果:
B 6:1 rank: 0.53
A 60:40 rank: 0.52
C 6:4 rank: 0.35
E 10:20 rank: 0.21
D 1:2 rank: 0.10
Beta distributions of five ranked movies A,B,C,D,E
这将高证据 A (60:40)和低证据 C (6:4)电影分开,但总体上不是理想的排名,特别是对于 D(红色)来说,它几乎没有证据,但却获得了最差的排名。我们知道,一般的电影比非常好或非常差的电影更常见。我们更喜欢这样一个排名,它从对普通电影的假设开始,并需要证据来走向极端。我们可以将这种偏好与对普通电影有偏好的排名系统中的优先相结合,从 Beta(11,11)而不是 Beta(1,1)的优先开始。现在将需要一些投票来远离之前的并走向极端,产生更好的总体排名:
A 60:40 rank: 0.51
B 6:1 rank: 0.43
C 6:4 rank: 0.39
D 1:2 rank: 0.32
E 10:20 rank: 0.30
Ranking with a prior biased towards an assumption of average movies
给我们一个最终结果,显示低证据 D 曲线大致在中间,而具有明显更多负面证据的 E 曲线现在具有最低等级。
这不仅适用于向上/向下评级,您还可以通过将值分配到同步向上/向下投票中,将其扩展到基于星级的系统。
星星(1,2,3,4,5):向上(0,0.25,0.5,0.75,1)向下(1,0.75,0.5,0.25,0)
因此,如果三个人每人给一部电影打了 4 颗星,那么总分就是:
3 up votes each of 0.75 value = 3×0.75 = 2.25
3 down votes each of 0.25 value = 3×0.25 = 0.75
Beta(3.25,1.75) # Uniform prior
Beta(13.25, 11.75) # Prior biased toward average movie assumption
我们已经完成了一个稳定的排名系统,该系统奖励越来越多的证据,并展示了如何将其扩展到星级系统,这都要感谢 Bayes 牧师。
如果您想亲自尝试一下,下面的 python 代码会进行排序,并为有偏差的情况绘制图表。
与 R 一起成为数据科学的化身
原文:https://towardsdatascience.com/be-a-data-science-avatar-with-r-89ea66fdfb63?source=collection_archive---------23-----------------------
用 5 个最简单的步骤学习 R 编程
介绍
在过去的几年里,数据科学席卷了整个世界。以前只有最大的商业公司和企业集团在使用它,但现在这种技术也适用于小型企业。
对技术的更多使用意味着对能够使用这种技术的人的更多需求。因此,全球对熟练数据科学家的需求也大幅上升。
说到数据科学,R 是 it 领域最突出和最流行的编程语言之一。学习 R 是成为一名成功的数据科学家的必经之路。不仅如此!r 还被各种 IT 和社交媒体公司用于机器学习、情感分析和行为分析研究。它是最广泛使用的编程语言之一。
你旅途中需要的伴侣
为什么要学 R?
R 优于许多其他可用于数据科学和机器学习的语言有很多原因。其中一些原因可能是:
职业机会
r 从 1992 年开始出现,现在仍然是数据科学和学术研究中最流行的语言之一。全世界有 200 多万用户,而且这个数字似乎还在增加。
- 数据科学家的平均年收入在 60 万美元左右。
- 据 IBM 预测,到 2020 年对数据科学家的需求将增长 28%。
大型社区
r 在全球拥有超过 200 万用户。R 社区意义深远,同时也非常有帮助。全年在世界各地组织了许多会议和活动,让用户聚在一起讨论新想法,并帮助新用户。
开源
r 是开源的。它可以自由使用、贡献和开发。
强大的图形
由于 R 的基本图形包中有静态图形,加上 ggplot2 和 plotly 等提供动态和动画图形的附加包,R 的数据可视化过程是无与伦比的。
简单的统计计算
复杂的统计计算和操作可以用 r 中的几个简单命令来执行。
一大堆包裹
在线上有多个存储库,存储了数千个扩展和改进 R 环境的包。CRAN(Comprehensive R Archive Network)存储库包含超过 15,000 个 R 包。
因为你想成为明星,你可以和 R 成为明星
如何学习 R?
学习任何东西都很简单,只要努力、专注和一点点想象力。学 R 也没那么不一样。
下面是学习 R 的分步指南:
第一步:与 R 会面
(R 环境及安装介绍)
了解 R 环境应该是您的第一步。这将包括探索 R 的当前版本中的变化和更新,不同的可用 IDE,合适的包的在线存储库,等等。
之后,您应该安装 R 基础包和一个合适的 IDE(我推荐 RGUI 或 RStudio)。
第二步:“因为一切都从基础开始
(基础知识、语法和命令)
让我们从 R 的基础开始。以下主题是为 R 编程打下坚实基础所必需的。
- 数据类型
- 数据结构
- 基本操作
- 用户定义的函数
- 决策结构(if-else 语句)
- 循环结构(while、for 等。)
- 导入/导出资源
在学习这些的同时,你还应该关注各种函数、命令和控制结构的语法。r 有一个非常灵活的语法,这使得它容易学习,也容易犯错误。您应该遵循编程最佳实践,以便能够编写一致和干净的代码。
第三步:“因为数字不会说谎。”
(基础统计)
一旦你很好地掌握了 R 的基本知识和语法,你应该温习一下基本的统计学和数学。尽管 R 有可以轻松执行复杂操作集的命令,但实际了解这些命令在幕后对数据做了什么总是好的。线性和非线性回归、时间序列分析、主成分和因子分析等概念在数据科学中非常有用且常用,了解如何使用 r。
步骤 4:处理数据
(数据操作和可视化)
数据操作是任何数据分析的第一步。它是将数据更改并符合所需格式以供进一步分析的过程。r 有许多有用和方便的数据操作函数。它还有各种用于数据操作、清理和整形的库。对数据进行适当的清理和整形可以使分析过程更加容易和准确。
步骤 5:项目最大的方面
(尝试动手实时项目)
有源代码的最酷的数据科学项目
学习 R 并取得进步的最好方法是构建自己的项目并进行实践。实践经验是最好的老师。像计算器一样从简单开始,然后增加难度。很快,您将能够分析真实世界的大型数据集或执行复杂的数据科学算法。
最后
数据科学就像火,现在正是你开始在上面烹饪食物的时候。 随着高质量数据科学家的高需求和低供给之间的差距缩小,你应该尽快开始研究数据科学。学习 R 编程可能是最简单的方法。
学习 R 很容易。这对你的职业生涯和未来也将是一个非常好的决定。
按照上面的步骤,再加一点点努力,你很快就会成为一名优秀的 R 程序员。
征服数据科学最后一战的时间
XGBoost 中“特性重要性”的多面性
原文:https://towardsdatascience.com/be-careful-when-interpreting-your-features-importance-in-xgboost-6e16132588e7?source=collection_archive---------3-----------------------
在 XGBoost 中解释特性的重要性时要小心,因为“特性重要性”的结果可能会产生误导!
这篇文章给出了一个简单的例子,说明为什么理解你的数据是非常重要的,不要盲目地使用你的特征重要性结果,因为由 XGBoost 生成的默认“特征重要性”可能不是你想要的。
The figure shows the significant difference between importance values, given to same features, by different importance metrics.
假设您正在为一个分类问题拟合一个 XGBoost,将会产生一个重要性矩阵。重要性矩阵实际上是一个表格,第一列包括提升树中实际使用的所有特征的名称,矩阵的其他列是使用不同重要性度量计算的结果“重要性”值[ 3 ]:
增益意味着相应特征对模型的相对贡献,该相对贡献是通过取每个特征对模型中每棵树的贡献来计算的。与另一个特征相比,该指标的值越高,意味着它对生成预测越重要。
覆盖率指标是指与该特性相关的观察的相对数量。例如,如果您有 100 个观察值、4 个特征和 3 棵树,并且假设特征 1 用于分别为树 1、树 2 和树 3 中的 10、5 和 2 个观察值决定叶节点;则该度量将该特征的覆盖率计为 10+5+2 = 17 次观察。这将针对所有 4 个功能进行计算,覆盖率将为 17,表示为所有功能覆盖率指标的百分比。
频率(R)/权重(python) 是表示特定特征在模型树中出现的相对次数的百分比。在上面的示例中,如果 feature1 出现在 2 个拆分中,则 tree1、tree2 和 tree3 中的每一个都有 1 个拆分和 3 个拆分;那么特征 1 的权重将是 2+1+3 = 6。特征 1 的频率计算为其权重占所有特征权重的百分比。
增益是解释每个特征相对重要性的最相关属性。
增益是一个特征给它所在的分支带来的精度提高。其思想是,在将特征 X 上的新分裂添加到分支之前,有一些错误分类的元素,在将该特征上的分裂添加之后,有两个新分支,并且这些分支中的每一个都更准确(一个分支说如果你的观察在这个分支上,那么它应该被分类为 1,而另一个分支说正好相反)。
Coverage’测量一个特征所涉及的观察的相对数量。”[ 3
为什么理解你的特征重要性结果很重要?
假设你有一个二元特征,比如说性别,和你的目标变量高度相关。此外,您观察到在训练集中包含/删除该特性会极大地影响最终结果。如果您通过不同的衡量标准来研究此类特性的重要性,您可能会发现一些矛盾之处:
最有可能的是,与数据中的其他预测值相比,变量性别的可能值数量要少得多(通常只有两个:男性/女性)。因此,这种二元特征在每个树中最多可以使用一次,同时,比方说, age(具有更多可能值)可能会更频繁地出现在树的不同级别上。因此,这种二进制特征将基于频率/权重度量获得非常低的重要性,但是基于增益和覆盖度量获得非常高的重要性!
在 scikit-learn 随机森林(或 GradientBoosting)和 XGBoost 中的特征重要性计算之间的比较在 1 中提供。查看 scikit-lean 系综的文档,权重/频率特征重要性未实现。这可能表明这种类型的特征重要性不太能表明特征对整个模型的预测贡献。
因此,在使用默认特征重要性函数(即权重/频率)得出的结果之前,花几分钟时间思考一下,确保它有意义。如果没有,也许您应该考虑探索其他可用的指标。
注意:如果您使用 python,您可以通过一行代码访问不同的可用指标:
# Available importance _ types =[' weight ',' gain ',' cover ',' total _ gain ']
f = ' gain '
xgb classifier . get _ booster()。get _ score(importance _ type = f)
参考文献:
[## 随机森林与 XGBoost 的特征重要性
这两种情况下的特征重要性是相同的:给定一棵树,遍历该树的所有节点,并执行以下操作…
forums.fast.ai](https://forums.fast.ai/t/feature-importance-of-random-forest-vs-xgboost/17561) [## 为什么 python 中 feature_importance 的默认值是‘weight’,R 却用‘gain’?问题#2706…
我通读了文档,注意到在 R-package 部分…
github.com](https://github.com/dmlc/xgboost/issues/2706) [## 我如何解释 XGBoost 重要性的输出?
begingroup$感谢 Sandeep 的详细回答。我想纠正一下,保险金额是跨所有拆分计算的…
datascience.stackexchange.com](https://datascience.stackexchange.com/questions/12318/how-do-i-interpret-the-output-of-xgboost-importance) [## 以随机森林为例解释特征的重要性
在许多(商业)案例中,不仅有一个准确的,而且有一个可解释的模型是同样重要的…
towardsdatascience.com](/explaining-feature-importance-by-example-of-a-random-forest-d9166011959e)
使用 mlflow 生成 ML 模型更有效
原文:https://towardsdatascience.com/be-more-efficient-to-produce-ml-models-with-mlflow-c104362f377d?source=collection_archive---------13-----------------------
你好,在这篇文章中,我将在去年推出的一款名为 mlflow 的工具上做一个实验,以帮助数据科学家更好地管理他们的机器学习模型。
本文的想法不是为我将要构建机器学习模型的用例构建完美的模型,而是更深入地研究 mlflow 的功能,并了解如何将其集成到 ML 管道中,以便为数据科学家/机器学习工程师的日常工作带来效率。
mlflow kezako?!
mlflow 是由 databricks 开发的 python 包,被定义为机器学习生命周期的开源平台。围绕 mlflow()有三个支柱。
他们的文档真的很棒,他们有很好的教程来解释 mlflow 的组件。对于这篇文章,我将把我的测试集中在 mlflow 的跟踪和模型部分,因为我将诚实地告诉你,我没有看到项目部分的要点(看起来像一个 conda 导出和一个以特定顺序运行 python 脚本的配置文件),但我确信它可以在 ml 管道的再生方面帮助一些人。
现在让我们看一下我想用来测试 mlflow 的案例。
用例的描述
为了测试 mlflow,我将使用我在 2017 年完成 Udacity ML 工程师纳米学位时使用的相同用例:
建立法国用电量预测系统
你可以在我的 Github 库的这个文件夹中找到我此刻制作的关于纳米度的所有资源。
我不打算在数据分析中输入太多细节,你可以在存储库中的报告中找到这些数据,但基本上法国的电力消耗是季节性的。
由于家庭大部分时间都在使用电暖,耗电量很大程度上取决于室外温度。
关于这一分析更重要的是,为了在 2019 年重新运行它,我回到 RTE 的 opendata 网站,我惊喜地看到网站通过在平台上添加更多数据而发展(他们与其他能源管理公司建立了联系),所以现在有了能源消耗数据和一些额外的信息,例如地区天气。
对于这个项目,我将使用以下功能来训练一个模型:
- 当天的信息,如星期几、月份、星期几,以及是否在法国度假假期
- 关于法国每日室外温度(最低、平均和最高)的信息,一个是每个地区室外温度的全球平均值(avg ),另一个是基于每个地区人数的加权平均值
您可以在这个存储库中找到处理来自 open 的原始数据的笔记本
对于建模部分,正如我所说,这个想法不是建立一个超级模型来预测 99.999%的能源消耗,而是更多地了解如何将 mlflow 集成到我一年前为我的纳米学位建立的管道中。
我将测试以下型号:
- 来自 scikit learn 的 KNN 回归器(具有各种参数和特征)
- 来自 scikit learn 的 MLP 回归器(具有各种参数和特征)
- 一个手工制作的分段线性回归叫做 PTG
该想法将使用 2016 年至 2019 年的数据(不包括)对 2019 年的数据进行训练和测试算法。
机器学习管道的描述
在下图中,我设想了一个简单的 ml 流管道来回答这种用例。
这个 ML 管道有 4 个主要步骤:
- 第一个步骤是收集所有数据,构建用于制作预测器的特征
- 在测试和构建阶段,将使用训练数据构建具有正确参数的正确模型,并在测试集上进行测试
- 服务部分,当你有正确的模型时,你需要服务它,用它来做预测
- 当您有新数据时,预测部分将对这些数据进行处理,以对可用于使用所提供的模型进行预测的要素进行转换
那么 mlflow 在这条管道中的位置是什么?
对我来说,这个库非常适合第 2、3 步,第 4 步也有一点点,能够涵盖所有这些范围真的很棒。
现在让我们更详细地了解一下 mlflow 的用法。
测试和构建模型(物流跟踪)
正如我们之前所说的,我们需要找到合适的模型来解决这个预测问题。为了初始化管道,我们需要定义一个实验,即电力消费预测,它也有一个实验(本例中为 1)。
模型(模型或参数)的每个测试将被定义为 mlflow 中的一次运行(并由 runid 标记),并存储在将出现在当前文件夹中的 mlruns 文件夹中。
为了组织我的代码,我保留了 mlflow 教程中的相同结构。这是我用来训练 KNN 回归器的一段代码的例子。
使用这种方法,每个模型都由模型的种类和用于构建它的特性来标记。对于评估指标,我的评估重点是:
- 精度指标,如 RMSE 、 R 平方或平均绝对误差
- 执行 model.fit 和 model.predict 的时间,因为选择一个好的模型需要的不仅仅是准确性。
我将这种方法应用于所有模型,所有数据都存储在 mlruns 文件夹中。
要使用 mlflow UI,只需在您的工作目录中执行以下命令。
您应该通过页面 localhost:5000 访问 UI,并选择正确的实验。有一个实验的主页面截图。
在这个页面上,有为每个模型计算的所有指标,有可能已经关联的所有标签,还有一些关于用户和记录的模型位置的额外信息。在该页面中,我们可以通过单击运行日期来访问每次运行。
在运行页面中有:
- 您可以在“参数”部分找到模型中应用的参数
- 运行期间计算的指标
- 与模型相关联的标签
UI 的另一个重要部分是工件,其中有包含模型信息的文件夹的组织。
从主页面,您可以选择所有可以在它们之间进行比较的模型。比较面板包含两个面板,一个面板带有一个表,将模型与所有分解的指标并排放置。
还有另一个面板可以用和进行可视化,并比较它们之间的模型。我快速制作了这个可视化面板的动画。
我发现这最后一个功能非常有限,因为不同类别的模型之间的比较(如 KNN 与 MLP)似乎更适合家庭模型的比较。
但是这个 UI 并不是进行日志分析的唯一方法,所有的日志都可以通过 python 中的命令收集到一个数据帧中。
mlflow.search_runs(experiment_ids="1")
这样,您就可以在 python 环境中进行更深入的分析,例如,根据 RMSE 分数获得最佳模型。有一个从 Python 中的日志进行的简单分析。
最佳模型有一个特定的 runid,可以在执行部署后使用。
模型服务(mlflow 模型)
使用 mlflow,您可以使用以下命令快速部署本地模型:
mlflow serve
-m path_to_the_model_stored_with_the_logfuction_of_mlflow
-p 1234
只需要用-m 将 mlflow serve 命令引导到模型的文件夹中,并分配一个新端口(默认端口与 mlflow UI 的端口相同,这可能会很烦人)
要执行预测调用,您需要向此 API 的/invocation 端点发送一个 POST 请求,并在此参数上包含一个已经在 json 中使用 orient split 进行了转换的数据帧(使用转换代码将更容易理解👇)
toscore = df_testing.to_json(orient = "split")
之后,您可以通过 Postman 或 Python 的 POST 请求轻松调用 API
import requests
import json
endpoint = "http://localhost:1234/invocations"
headers = {"Content-type": "application/json; format=pandas-split"} response = requests.post(endpoint, json = json.loads(toscore) , headers=headers)
但是现在最大的问题是如何在网上部署它?
mlflow 做得很好,你有内置函数来快速地在微软 AzureML 或 AWS Sagemaker 上部署模型。因为我更喜欢 AWS,所以我将把部署重点放在 AWS Sagemaker 上。
部署分两个阶段:
mlflow sagemaker build-and-push-container
当然,该命令必须在安装了 Docker 的机器上运行,并且 AWS 用户拥有在 AWS 上部署东西的正确权限,例如,我的管理员访问权限可能不是好事,但 YOLO。
mlflow sagemaker deploy
但即使在 Windows 或 Linux 上,它对我也不起作用。所以我尝试了这篇博文中的另一种方法。在这个要点中有一个代码总结。
部署非常快(大约 10 分钟),然后你可以用这段代码在 AWS 上调用 API deploy(来自 databricks 博客
因此,可以调用该模型来预测该端点的能耗(这种方法由 AWS 用户处理所有的身份验证,所以我想这是非常安全的)。
我真的很喜欢在 mlfow 上进行实验,机器学习的版本控制通常是一个大话题,但在我目前的公司育碧(如果你想加入育碧大家庭,也许会有一份工作给你在这里)它开始成为一个真正的大问题。
在我看来, mlflow 真的很棒做线下实验找到合适的模型,快速做出原型。
我仍然对一些非常具体的问题有些担忧:
- 在 ml 模型中,有算法,但数据也非常重要,所以标签功能可以用于提供所用数据的信息,但在我看来,这可能还不够
- 模型类需要从熊猫的数据框架中做出预测,这很好,但可能也有一点限制
- 缺乏在特性/数据上自动记录模型的方法,这些特性/数据用于帮助调用 API 背后的模型部署
- 管理 Tensorflow 的模型看起来超级复杂(pytorch 看起来更容易),但最后一点可能是因为我对这些框架不太熟悉(在 Tensorflow 与 Pytorch 的战争中没有立场😀 ).
但是说实话,你做了一个非常棒的工具来帮助数据科学家进行实验
原载于 2019 年 11 月 13 日the-odd-dataguy.com。
做好自己:你在公开场合看到的数据科学家不具有代表性
原文:https://towardsdatascience.com/be-yourself-the-data-scientists-you-see-in-public-are-not-representative-9de29f3316bf?source=collection_archive---------32-----------------------
需要经常说——和他们不一样也没关系
Photo: Randy Au
嗨,是或想成为数据科学家的人!
想想你崇拜的任何一位数据科学家。他们是一家还是多家创业公司和基金会的创始人?他们有没有高级参谋总长之类的头衔和学位,FAANG 的博士学位?他们有上百万的推特粉丝和最好的帖子吗?他们写博客/时事通讯/写书的速度比你读的还快吗?他们的 Github 图表比你桌上的塑料植物更环保吗?他们的奖金比你的年薪还多吗?
你是不是看着自己,只是对自己坐的地方和他们“那边”的差距无语?我有重要的事情要对你说。
你不必和那些人一样。一点也不。他们不正常。在数据科学领域工作几乎不需要那么多。
虽然这些人绝对是令人敬畏的,有时可以成为灵感,但他们也站在运气、机会和生存偏见的不可知交叉点上。名声从定义上来说是罕见的。如果一群数据科学家像他们一样,哪怕只是一点点,他们也不会再引人注目了。我们会有不同的英雄。
作为数据科学家,我们应该是理解采样和隐藏在数据集中的隐藏偏见的专家。我们要做的就是拨开谷壳,获取知识的美味。但是由于人类的本性,把这种想法转向内心是非常困难的。
绝大多数从事数据工作的人并不是一直生活和呼吸着这些东西。他们有家庭要照顾,有非数据爱好要享受,有朋友要一起玩。他们不太喜欢编程,以至于在家里为了好玩而编程。他们不会强制跟踪 arXiv 阅读最新的机器学习论文。他们不会去巡回演讲,也不会经常去参加聚会。
但是,尽管没有做这些事情,这些人将为他们的组织提供有用的见解,设计健壮的系统,进行实验,并做重要的工作。只是悄悄地,不为世人所知。即使是独角兽也不会同时做所有这些事情!
做你想做的
就我自己而言,我半定期地写作,因为把事情写下来是一种宣泄。但我把大部分非工作时间都花在了做一顿美味的晚餐、修理我在家里打碎的东西和照顾孩子上。工作留在办公室,我的副业没有一个和数据有关。
虽然我们经常听说冒名顶替综合症,我们钦佩的人如何怀疑他们是否值得他们的钦佩,但我们很少听到在你认为自己是这个伟大社区的一部分之前,酒吧在哪里。
我在这里要说的是,门槛是低的,也应该是低的。如果你处理数据,你正在做数据科学范围内的事情。“数据科学家”的头衔仅仅是给那些符合某个招聘经理指定的任意一套技能和经验的人。变化太大,很不明智。只是噪音。
不要被所有你钦佩的人吓倒。他们高于你我这样的人,正是因为他们是令人敬畏的独角兽。
此外,看门的混蛋可以滚开。
祝大家节日愉快。
使用 Kafka 和 Debezium 的 ASP.NET 核心中的节拍缓存失效
原文:https://towardsdatascience.com/beat-cache-invalidation-in-asp-net-core-using-kafka-and-debezium-65cd1d80554d?source=collection_archive---------7-----------------------
在构建 web 应用程序时,我们大部分时间使用缓存来存储(昂贵的)数据库查询的结果。一段时间后,由于我们的底层数据库状态发生了变化,我们希望删除或替换缓存条目。一个被称为缓存失效的过程。问题是我们什么时候必须移除或替换缓存条目?答案是每当底层数据库记录发生变化时。但是数据可能会被我们无法控制的过程所改变。
如果我们可以订阅数据库记录发生的任何更改事件(插入、更新和删除),那么我们就可以成功地实时使相关的缓存条目无效。好消息是大多数数据库都会发布它们的插入、更新和移除事件。这项功能称为变更数据捕获(CDC)。
TL;速度三角形定位法(dead reckoning)
在本文中,我想向您展示我们如何使用 CDC 来订阅任何更改 MySQL 数据库记录的事件,并将每个事件作为单独的消息发布给 Apache Kafka。 Debezium 是一个让这一切成为可能的平台。然后,我们使用这些事件在 ASP.NET 核心中构建内存缓存。我们将看到如何基于我们的实时缓存构建我们的 REST API。
这类似于复制在数据库中的工作方式。在复制中,辅助副本订阅主副本上的任何事务(更改事件),并将该事务应用于自己的数据库记录,这样,辅助数据库状态最终将等同于主数据库状态。如图所示,我们将 Kafka 集群订阅为数据库的副本,并处理更改事件以构建我们的缓存:
这种方法不仅解决了缓存失效,还解决了其他问题,如竞争条件和缓存热启动,正如 Martin Kleppmann 在他的文章Turning the database inside-out中所描述的。
这篇文章的源代码可以在 GitHub 中找到。
先决条件
- 。网络核心 2.2
- docker 和 docker-撰写
启动 Docker 服务
我们将使用 Docker 设置我们的 Apache Kafka 集群、MySQL 数据库和 Debezium 连接器(我们将很快讨论它)。首先,用以下内容创建一个docker-compose.yml
文件:
version: '3.1'services:mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_USER: mysql
volumes:
- ./my.cnf:/etc/mysql/my.cnf
ports:
- 3306:3306zookeeper:
image: confluentinc/cp-zookeeper
ports:
- "2181:2181"
environment:
ZOOKEEPER_CLIENT_PORT: 2181kafka:
image: confluentinc/cp-kafka
depends_on:
- zookeeper
- mysql
ports:
- "9092:9092"
environment:
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_LOG_CLEANER_DELETE_RETENTION_MS: 5000
KAFKA_BROKER_ID: 1
KAFKA_MIN_INSYNC_REPLICAS: 1connector:
image: debezium/connect:0.10
ports:
- "8083:8083"
environment:
GROUP_ID: 1
CONFIG_STORAGE_TOPIC: my_connect_configs
OFFSET_STORAGE_TOPIC: my_connect_offsets
BOOTSTRAP_SERVERS: kafka:9092
depends_on:
- zookeeper
- mysql
- kafka
my.cnf 文件启用 MySQL 的 CDC 特性。现在启动所有 docker 服务:
docker-compose up
创建 MySQL 数据库
打开同一路径中的另一个终端,连接到 MySQL 容器并运行 MySQL CLI:
docker-compose exec mysql bash -c 'mysql -u root -p$MYSQL_ROOT_PASSWORD'
现在我们想在 MySQL 中创建一个数据库。运行下面的脚本来创建一个名为mystore
的数据库,一个名为products
的表,并在products
表中插入一个简单的记录:
create database mystore;
use mystore;
create table products (id int unsigned auto_increment primary key, name varchar(50), price int, creation_time datetime default current_timestamp, modification_time datetime on update current_timestamp);
insert into products(name, price) values("Red T-Shirt", 12);
创建 Debezium 连接器
现在,我们希望将 products 表中发生的所有更改都转移到 Kafka。为此,我们必须创建一个连接器。连接器是一个应用程序,负责将数据从数据库(或任何其他存储系统)移动到 Kafka 集群(反之亦然)。如果你不熟悉 Kafka connector,你可以阅读合流文档。这里我们想将 MySQL 变更事件转移到 Apache Kafka 集群。Debezium 是一个 Kafka 连接器,可以从 MySQL(和其他一些数据库)中读取所有变更事件,并将它们发布到 Kafka:
Debezium 公开了一个 REST API 来创建连接器。因此,要创建一个 Debezium 连接器,打开另一个终端并运行下面的脚本(大部分配置是不言自明的,但要了解更多信息,请阅读 Debezium MySQL 教程):
curl -i -X POST -H "Accept:application/json" -H "Content-Type:application/json" localhost:8083/connectors/ -d '{ "name": "mystore-connector", "config": { "connector.class": "io.debezium.connector.mysql.MySqlConnector", "tasks.max": "1", "database.hostname": "mysql", "database.port": "3306", "database.user": "root", "database.password": "123456", "database.server.id": "223345", "database.server.name": "mysql", "database.whitelist": "mystore", "database.history.kafka.bootstrap.servers": "kafka:9092", "database.history.kafka.topic": "dbhistory.mystore",
"transforms":"unwrap","transforms.unwrap.type":"io.debezium.transforms.UnwrapFromEnvelope","transforms.unwrap.drop.tombstones":"false","key.converter": "org.apache.kafka.connect.json.JsonConverter","key.converter.schemas.enable": "false","value.converter": "org.apache.kafka.connect.json.JsonConverter","value.converter.schemas.enable": "false","include.schema.changes": "false"} }'
如果您收到HTTP/1.1 201 Created
,您的连接器已经成功创建。您还可以检查连接器的状态:
curl localhost:8083/connectors/mystore-connector/status{
"name": "mystore-connector",
"connector": {
"state": "RUNNING",
"worker_id": "172.24.0.5:8083"
},
"tasks": [
{
"id": 0,
"state": "RUNNING",
"worker_id": "172.24.0.5:8083"
}
],
"type": "source"
}
state
字段中的Running
值表示您的连接器正在工作。现在让我们检查一下,任何数据库更改都将被同步到 Kafka。首先,连接到 Kafka 容器:
docker-compose exec kafka bash
并查看主题列表:
kafka-topics --zookeeper zookeeper:2181 --list__confluent.support.metrics
__consumer_offsets
connect-status
dbhistory.mystore
my_connect_configs
my_connect_offsets
mysql
mysql.mystore.products
mysql.mystore.products
主题存储products
表的变更事件。我们可以使用下面的脚本读取该主题中的消息(消息键由-
分隔):
kafka-console-consumer --bootstrap-server kafka:9092 --from-beginning --topic mysql.mystore.products --property print.key=true --property key.separator="-"{"id":1}-{"id":1,"name":"Red T-Shirt","price":12,"creation_time":1553595845000,"modification_time":null}
要检查更改是否会(接近)实时同步,请在 MySQL 容器中添加另一条记录:
insert into products(name, price) values("Blue Hat", 5);
更改将立即显示在用户终端上:
{"id":1}-{"id":1,"name":"Red T-Shirt","price":12,"creation_time":1553595845000,"modification_time":null}
**{"id":2}-{"id":2,"name":"Blue Hat","price":5,"creation_time":1553595958000,"modification_time":null}**
更新“蓝帽子”记录:
update products set price = 17 where name = "Blue Hat";
发布更新事件:
{"id":1}-{"id":1,"name":"Red T-Shirt","price":12,"creation_time":1553595845000,"modification_time":null}
{"id":2}-{"id":2,"name":"Blue Hat","price":5,"creation_time":1553595958000,"modification_time":null}
**{"id":2}-{"id":2,"name":"Blue Hat","price":17,"creation_time":1553595958000,"modification_time":1553595986000}**
删除 id 为 1 的记录:
delete from products where id = 1;
具有空值的消息将被添加到主题:
{"id":1}-{"id":1,"name":"Red T-Shirt","price":12,"creation_time":1553595845000,"modification_time":null}
{"id":2}-{"id":2,"name":"Blue Hat","price":5,"creation_time":1553595958000,"modification_time":null}
{"id":2}-{"id":2,"name":"Blue Hat","price":17,"creation_time":1553595958000,"modification_time":1553595986000}
**{"id":1}-null**
空值表示记录被删除。让我们添加一个名为description
的列:
alter table products add column description nvarchar(1000);
并更新产品记录:
update products set description = "Can be used for the spring!" where id = 2;
您将会看到,即使是模式更改也会反映在消息中:
{"id":1}-{"id":1,"name":"Red T-Shirt","price":12,"creation_time":1553595845000,"modification_time":null}
{"id":2}-{"id":2,"name":"Blue Hat","price":5,"creation_time":1553595958000,"modification_time":null}
{"id":2}-{"id":2,"name":"Blue Hat","price":17,"creation_time":1553595958000,"modification_time":1553595986000}
{"id":1}-null
**{"id":2}-{"id":2,"name":"Blue Hat","price":17,"creation_time":1553595958000,"modification_time":1553596044000,"description":"Can be used for the spring!"}**
注意,一些 RDBMSs 如 SQL Server 不会自动反映 CDC 数据中的模式变化。但是 MySQL CDC 支持模式变更。
缓存构建器项目
mysql.mystore.products
主题包含产品表的每次更改。为了构建我们的缓存,我们希望保留每条记录的最新值。为此,我们可以在名为products.cache
的单独主题中保存每个产品 id 的最新值。我们还创建了一个名为缓存构建器的项目,它将读取mysql.mystore.products
主题中的每条消息,并将它们生成到products.cache
主题中。products.cache
主题是一个压缩的主题,这意味着每个键(在本例中为产品 id)将只包含一条消息。你可以在 Cloudurable 和我最近的文章中阅读更多关于压缩主题的内容。
通过在 Kafka 容器中运行以下脚本,在 Kafka 中创建一个压缩主题:
kafka-topics --create --zookeeper zookeeper:2181 --topic products.cache --replication-factor 1 --partitions 1 --config "cleanup.policy=compact" --config "delete.retention.ms=100" --config "segment.ms=100" --config "min.cleanable.dirty.ratio=0.01"
为了从我们的应用程序连接到 Kafka broker,我们还需要将kafka
主机名添加到hosts
文件中(只需添加粗体行):
sudo vi /etc/hosts
127.0.0.1 localhost
# ...
**127.0.0.1 kafka**
创建一个解决方案和 CacheBuilder 项目(你可以在 GitHub 中看到完整的代码):
mkdir src
cd src/
dotnet new sln --name KafkaCache
dotnet new console -o KafkaCache.CacheBuilder
dotnet sln add KafkaCache.CacheBuilder/KafkaCache.CacheBuilder.csproj
并安装Confluent.Kafka
和Newtonsoft.Json
NuGet 包:
dotnet add KafkaCache.CacheBuilder/KafkaCache.CacheBuilder.csproj package Confluent.Kafka --version 1.0.0-RC1
dotnet add KafkaCache.CacheBuilder/KafkaCache.CacheBuilder.csproj package Newtonsoft.Json --version 12.0.1
这里您可以看到 Program.cs 代码:
这是 ProductKey 类:
在 Program.cs 中,我们只是从mysql.mystore.products
主题中读取消息,提取产品 id 字段并创建另一条消息,然后将其发布到products.cache
主题。现在运行 CacheBuilder 项目(在单独的终端中):
dotnet run --project KafkaCache.CacheBuilder/KafkaCache.CacheBuilder.csproj
您可以在 Kafka 容器中查看该主题:
kafka-console-consumer --bootstrap-server kafka:9092 --from-beginning --topic products.cache
Web API 项目
我们创建一个 Web API 项目,它将公开简单的 REST API 来获取产品的详细信息(从缓存中检索)。此外,该项目负责消费来自products.cache
主题的缓存条目,并将它们存储在内存缓存中。运行以下脚本创建项目:
dotnet new webapi -o KafkaCache.Api
dotnet sln add KafkaCache.Api/KafkaCache.Api.csproj
安装Confluent.Kafka
和Newtonsoft.Json
包:
dotnet add KafkaCache.CacheBuilder/KafkaCache.CacheBuilder.csproj package Confluent.Kafka --version 1.0.0-RC1
dotnet add KafkaCache.CacheBuilder/KafkaCache.CacheBuilder.csproj package Newtonsoft.Json --version 12.0.1
启用Startup
类中的内存缓存:
services.AddMemoryCache();
这允许我们使用IMemoryCache
,它用于在 ASP.NET 内核的内存中存储和检索缓存条目。为了填充这个缓存,我们需要一个CacheUpdater
类,负责消费来自products.cache
主题的消息并更新我们的内存缓存:
还有ProductItemCache
类:
注意,我们有一个负责更新缓存的 Run 方法。该方法接收一个returnOnLastOffset
参数,该参数用于返回关于该主题的最后一条消息。如果它有true
值并且我们在主题/分区的末尾,我们从方法返回。这在启动过程中非常有用,因为我们希望在处理任何 REST API 请求之前预热缓存。我们现在在应用程序初始化中使用CacheUpdater
:
如上所示,我们调用了两次CacheUpdater.Run
方法。首先用于预热缓存,其次用于运行后台作业以连续读取products.cache
主题并更新内存缓存。
最后,这是我们的控制器,它直接服务于来自缓存的请求:
现在运行 API 项目:
dotnet run --project KafkaCache.Api/KafkaCache.Api.csproj
并检查您的 API:
curl -k [https://localhost:5001/api/products/2](https://localhost:5001/api/products/2)
{"id":2,"name":"Blue Hat","price":17}
让我们更改 MySQL 容器中 id 为 2 的产品的价格:
update products set price = 56 where id = 2;
并再次请求您的 API:
curl -k [https://localhost:5001/api/products/2](https://localhost:5001/api/products/2)
{"id":2,"name":"Blue Hat","price":56}
如你所见,任何变化都会立即反映到我们的缓存中!
结论
使用 CDC,我们可以将数据库的变化近乎实时地反映到 Kafka 中。然后,我们可以通过消费卡夫卡的信息来创建内存缓存。现在我想指出这种方法的一些优点和缺点。
优点:
- 减轻实现缓存中的 3 个问题:缓存失效、竞争条件和热启动性能。
- 将数据库更改实时同步到缓存。
- 由于顺序 IO,缓存预热速度更快(从 Kafka 主题中读取消息)。
缺点:
- 更复杂:您需要实现缓存构建器,使用 Debezium 连接器,为数据库启用 CDC,并从 Kafka 集群读取事件。
- 需要监控 Kafka,连接器和缓存生成器。
- 需要更多的知识:新开发人员必须学习更多的框架。
参考
https://vlamihalcea . com/how-to-extract-change-data-events-from-MySQL-to-Kafka-using-debezium/
https://github . com/confluent Inc/demo-scene/blob/master/ksql-workshop/ksql-workshop . adoc
https://Martin . kleppmann . com/2015/03/04/turning-the-database-inside-out . https
通过调整基线超越最先进水平
原文:https://towardsdatascience.com/beating-state-of-the-art-by-tuning-baselines-74ec6ad2cd59?source=collection_archive---------11-----------------------
你如何知道一个新的机器学习模型是否是对以前模型的改进?一种方法是将其与为相同任务开发的基线模型进行比较。但这回避了一个问题:你如何知道基线本身是否好?由 Rendle,Zhang & Koren 撰写的一份新的预印本“关于评估基线的难度:关于推荐系统的研究”表明,衡量一个基线模型对一个具体问题的效果并不像它初看起来那样简单。事实上,的作者仅仅通过调整基线并将它们与简单的、众所周知的方法结合起来,就能够在 Movielens 10M 基准 上击败当前最先进的的推荐。
Blue x’s are the results reported by authors for their newly-proposed method, black/grey triangles are the baselines those authors run… and red are the tuned baselines. Down is better and, as you can see, after additional turning (as outlined in the paper) the tuned baselines are the most down (i.e. best performing).
我们如何评价机器学习模型?
我们先退一步。我们目前如何评估模型?
如果你曾经参加过 Kaggle 竞赛,你可能已经知道它们是如何工作的:你被给予训练数据来建立一个模型,为一个特定的指标进行优化。然后,根据不同的数据集对您的模型以及其他所有人的模型进行评估,并根据目标指标进行排名。提交结束后,每个人的模型都会在第三个看不见的数据集上排名,表现最好的模型胜出!(当然,前提是他们遵守了特定比赛的规则。)
然而,对于机器学习的学术研究来说,事情有点不同。一般来说,研究人员使用特定任务的数据为该任务建立新的模型。一些例子:
- 使用 Netflix 奖项数据集的推荐系统
- 使用微软 COCO 数据集进行对象分割
- 使用 TIMIT 语料库进行语音识别
- 自然语言理解使用胶水基准
然后,他们将算法的性能与在同一数据集上运行的基线进行比较。如果这是一项已经存在一段时间的任务,通常会将你的系统与另一篇论文中报告的结果进行比较,但对于较新的任务,研究人员通常自己运行基线。
一个基准是一个包括数据集和评估性能的方法的任务。一个基线是一个众所周知的算法,可以应用于基准问题。
在研究中没有“获胜”的模式,但是提出一种新方法,然后证明它比以前建立的方法有所改进的论文往往会被发表。(对于研究人员来说,雇佣和晋升是基于发表论文的数量和质量,所以让你的论文发表是一件好事!)
这两个社区之间最大的不同可能是研究人员面临着关注新型模型的压力。如果一个老型号在 Kaggle 比赛中真的有效,竞争者没有理由不使用它…但是如果主要发现是“我们已经做了十年的东西实际上仍然非常好”,就很难让论文发表。
为什么基线一开始就不太好?
进行实验是困难的,需要大量的实验努力才能获得可靠的结果。(伦德尔等人,第 9 页)
重申一下:运行机器学习实验很难。Rendle 和合著者指出了调优可能出错的两个地方:
-
在调整超参数时,您很容易错过最佳时机。您的搜索空间的边界可能太靠近,或者在一个方向上移动得太远。您可能没有使用正确的搜索网格。你在小模型上得到的结果实际上可能不会放大。简而言之:很难很好地调优模型,而且很容易搞砸。
-
在预处理或学习过程中,你可能会遗漏一些小而重要的步骤。你打乱了你的训练数据吗?做 z 变换?你使用提前停车吗?所有这些选择都会影响你的模型结果。尤其是如果你试图复制别人的结果,这些步骤可能很难做对。(特别是如果它们没有被报告,并且原作者没有发布它们的代码!)
即使您做了所有您应该做的事情,并且有一个非常坚实的基线,基线算法可能会在额外的调整下表现得更好——特别是由非常熟悉该方法并且知道所有提示和技巧的人来调整。了解什么最适合特定的模式需要大量的试验和错误;这也是调整基线如此困难的部分原因。即使一篇论文的作者真的尽了最大努力来调整基线,有更多经验或稍微不同的方法的人可能会得到更好的结果。(有点像 Kaggle 比赛;与只使用过几次的人相比,非常熟悉 XGBoost 模型调优的人可能会得到更好的结果。)
而且,虽然在 Kaggle 式的竞争中有投入大量时间调优模型的动机,包括您的基线(如果它表现良好,您使用什么工具并不重要!),研究场所一般不会奖励花费大量时间调基线。事实上,如果调整显示基线优于你想出的方法,这实际上可能会让更难发表一篇描述你的新模型的论文。这类似于“文件抽屉问题”,研究人员不太可能报告负面结果。
那么我们能做些什么呢?
Rendle 等人提出了两件事可以在这里有所帮助:标准化基准和激励机器学习社区投入时间调整这些基准。
不要多此一举
“重新发明轮子”意味着重新做已经做过的工作。如果某个特定任务有一个已经很好调整过的既定基准,那么你应该与那个基准进行比较!(额外的好处是,如果您正在进行一项既定的任务,并且可以使用报告的结果而不是重新运行它们,那么您可以节省时间和计算。🤑)
激励跑步(和调音!)基线
这个有点棘手:要改变一个已建立的社区的激励结构或价值体系极其困难。作者指出,机器学习竞赛,无论是在像 Kaggle 这样的平台上,还是在研究社区内组织,都是这样做的一种方式。我还要补充一点,如果你评论机器学习的论文,既要考虑新颖性(这种方法是新的吗?)和效用(这篇论文对整个社区有好处吗?)写评论的时候。
TL;速度三角形定位法(dead reckoning)
仅仅因为最近提出了一种建模技术,并不意味着它一定会优于一种更老的方法(即使论文中的结果表明它可以)。调整模型需要时间和专业知识,但通过仔细调整,已建立的基线可以表现得非常好,甚至超过最先进的水平。依靠具有良好调整的基线的标准化基准可以帮助减少重复工作,还可以获得更可靠的结果。而且,如果您只是在为一个特定的项目寻找最佳方法,那么从更好理解的模型开始可能会更好。
如果你有兴趣阅读整篇文章,特别是关于不同推荐系统的基线调整的细节,你可以在 Arxiv 上查看。
用 Python 编程能打败 21 点吗?
原文:https://towardsdatascience.com/beating-the-dealer-with-simple-statistics-71b5e3701638?source=collection_archive---------10-----------------------
使用数据科学工具模拟数千种 21 点纸牌计数策略
Photo by Jarosław Kwoczała on Unsplash
拉克杰克是在赌场玩的最简单的游戏之一。也是最容易学的游戏之一。目标很简单;在不超过的情况下,尽可能接近 21 的值。你要么打败庄家,要么输给庄家,要么和庄家打成平手。21 点的结果非常简单。然而,这些结果的权重完全取决于你,因为你可能在一手牌中输掉很多钱。没有人想输,而在 21 点中输钱会有多痛取决于你的赌注大小。为了提高赌场或赌场的赔率,21 点玩家开发了许多算牌策略来降低他们失败的几率。
在 21 点中使用算牌
算牌一开始可能显得很难,但实际上相当简单。算牌的概念包括给一副牌中的每张牌赋值,例如 +1 、 -1 或 0 。然后,将它们加在一起,这个总值就变成了计数。根据计数是高还是低,算牌者使用这个计数来确定是击中还是停留。存在许多不同的算牌策略,这些策略为每张牌实现不同的值。例如,一种策略可能会将 Ace 计为 -1 ,而另一种策略会将其计为 0 。除了卡的价值之外,这些策略之间还有很多不同之处,但我们无法涵盖所有这些。需要注意的是,这些算牌策略最多给玩家 0.5%的优势。对于 21 点游戏来说,这就是全部。
那么,如果我们想在我们的 21 点游戏中实施算牌策略呢?我们应该选择哪一个?嗯,我们可以做的一个选择是自己实施每个策略,去玩几次 21 点,然后记录结果。这种选择可能非常耗时,并且在实际显示策略的可能性和有效性时不准确。另一种选择可以是编码一个 21 点游戏,模拟该游戏,然后在期望的模拟次数后记录结果。为了确定最有效的算牌策略,我们将展示这个选项。
在这里注册一个中级会员,可以无限制地访问和支持像我这样的内容!在你的支持下,我赚了一小部分会费。谢谢!
用 Python 构建 21 点
让我们开始模拟 21 点的旅程,用 Python 编写全部代码。为了简洁起见,我们不会仔细检查每一行代码,但是代码的 Github 将在本文末尾提供。很有可能以前有人做过类似的事情,甚至可能做得更好,但不管怎样,让我们试一试。
首先,为了模拟一个 21 点游戏,我们需要编写一个 21 点游戏代码,其中包含所有必要的规则和规定。为了简单起见,我们将省略掉诸如分割、加倍 向下、投降等选项。让我们把玩家选项限制在击中或停留。此外,由于我们衡量的是赢与输,我们可以消除下注的需要。然而,在普通的 21 点游戏中,知道下注的大小是很重要的。
创建函数
让我们首先构建几个函数来帮助我们的 21 点游戏正常运行:
Source: https://gist.github.com/marcosan93/c0d0b41748bb515d7110cd3efccc165f
每个功能都有一个运行游戏的重要目的。为了模拟一副扑克牌的创建,我们创建了create_deck()
函数,它结合了random
来“洗牌”我们创建的牌列表。发一张牌在deal_card()
中处理,它通过使用.pop()
方法添加一张新牌,以模仿从一副牌中发一张牌。在玩家或庄家超过 21 时,check_ace()
功能会将 ace 的值从 11 重新分配到 1。这些可能是上面提到的最值得注意的功能,但这并不意味着游戏可以在没有其他功能的情况下运行。
经销商职能
Source: https://gist.github.com/marcosan93/7fc6f3c3a4de4ccc36d4405a0df8618c
如果玩家决定留在,此dealer_turn()
功能将向庄家发牌。这个功能遵循每个 21 点庄家的规则。它会一直交易,直到庄家达到 17 到 21 之间的值,或者直到庄家破产。它最终将庄家的手牌与玩家的手牌进行比较,以确定谁赢了。
创建纸牌计数值
接下来,为了在游戏中算牌,我们创建了一个熊猫数据框架,其中包含不同的算牌策略以及每张牌的具体值:
Source: https://gist.github.com/marcosan93/d2723710932b9d52b6c0dceda2a8dd96
在这段代码中,为了创建纸牌计数值的数据帧,我们导出了数据帧的一部分供以后使用。确保这个 pickle 文件与 21 点代码在同一个文件夹中,以便它能够正常运行。
然后,我们添加了算牌功能,以便在游戏运行时跟踪的计数:
Source: https://gist.github.com/marcosan93/ad0cb4b62f27749d06ec83d267e7fb31
这些函数跟踪整个游戏中每一轮 21 点的计数。card_counter()
跟踪运行计数,true_counter()
跟踪真实计数,这是玩家用来决定是否击中或停留。
玩 21 点
现在我们已经准备好了所有的功能,我们可以运行 21 点。代码将允许玩家输入,所以我们可以尽情地玩游戏。请随意在您自己的终端或 IDE 中测试 21 点游戏。
这个游戏有两个版本:
- 二十一点不算牌
- 带算牌的二十一点
模拟 1000 场 21 点游戏
现在我们已经有了一个 21 点游戏的代码并准备好了,我们终于可以开始用不同的算牌策略模拟 21 点游戏 1000 次了。通过模拟各种不同的策略,我们可以缩小首选的算牌方法,以尽可能最好的方式使我们受益。然而,我们必须降低对每项战略的期望。我们重申,据报道,每个策略每轮都给玩家 0.5%的优势。不要期望每场比赛都赢 60%或更多。
现在让我们开始模拟。为了用我们的代码模拟 21 点游戏,我们将不得不修改我们以前的 21 点代码,以弥补玩家输入的不足。为了弥补这一点,我们将以条件的形式输入一些预编程的决策,这些决策将基于计数和其他一些类似于庄家的基本规则来做出决策。
Source: https://gist.github.com/marcosan93/550f4643980a0b696f2cf4bf5477f770
player_move()
功能负责在击中或停留之间进行选择。这个函数可能需要一些调整,以更好地改善以后的结果。有了这个处理,我们可以继续模拟游戏。我们通过将玩 21 点游戏的函数输入一个循环来开始模拟,该循环将遍历一系列策略,然后用每种策略玩 1000 次游戏。我们记录了每场比赛的最后 10 轮,以捕捉每种策略的有效性,因为这些回合将有一个体面的计数,从中可以做出决定。
Source: https://gist.github.com/marcosan93/28f84b9ba591b78e95ee08fcb8a5e8d8
最后,我们模拟了超过 1000 场 21 点游戏,每一种不同的策略都列在熊猫数据框中。我们打乱了要模拟的策略的顺序,以进一步增加随机性。此外,我们在赢的游戏中加入了和棋,因为在 21 点中和棋不会导致只和庄家对弈时输钱。现在,我们只需要把模拟结果用图表表示出来。这可以通过使用 Matplotlib 以线形图格式绘制每个策略的结果来完成。
Source: https://gist.github.com/marcosan93/7185c6549128fc329337d027f4a3e16c
运行这段代码将得到下面的图形:
Probability results for each strategy
瞧啊。看起来大多数算牌策略都有相似的结果,但是它们似乎都比没有策略要好。我们为什么不再次进行模拟以确保:
看起来,无论在模拟中首先运行的是什么策略,在开始时都会产生非常不同的值。让我们再运行一次,试着平衡结果:
因此,我们的观察是正确的,我们假设无论哪种策略首先运行都会导致不稳定的不同值。但是每种策略的总体结果都非常相似。
如果您想改善或改变结果,那么您可能需要改变player_move()
函数中的条件逻辑。
结束语
正如前面的图表所示,每种策略都能为经销商提供可观的优势。实施这些策略中的任何一个似乎都足以让你比赌场或赌场更有优势。在没有任何策略的情况下,也可以选择坚持一套严格的规则。这似乎也提供了一个体面的成功百分比,只要该战略是遵循没有偏差。
应该注意的是,我们不赞成赌博作为一种赚钱的方法。但是,算牌可以给你带来优势,你选择坚持哪种策略真的无关紧要。但是,要知道这些模拟是用基本的击中或停留决策完成的,其中一些策略实际上考虑了下注大小和其他因素。另外,请知道这些模拟和结果是用相对简单的 Python 方法和工具制作的。总而言之,祝那些决定使用这些策略的人好运!
在 Twitter 上关注我:@Marco_Santos
Github:
[## Marcos an 93/21 点 _ 模拟器
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/marcosan93/Blackjack_Simulator)
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
用机器学习打败 S&P500
原文:https://towardsdatascience.com/beating-the-s-p500-using-machine-learning-c5d2f5a19211?source=collection_archive---------6-----------------------
使用随机森林回归在 15 年内产生 1400%的回报
The “Fearless Girl” statue on Wall Street. Photo by Robert Bye on Unsplash.
标准普尔 500 指数是最受关注的市场指数之一,通常被用作整个美国股票市场的基准。虽然人们可以考虑投资一只复制标准普尔 500 指数的被动型基金,但许多人会转向基金经理,更喜欢投资主动型基金。不幸的是,越来越多的研究和数据表明,“跑赢市场”(跑赢基准)非常困难。你可以去这里和这里阅读更多关于这个主题的内容,伯顿·g·马尔基尔的这本优秀的书也值得推荐。这些研究的结论之一是,在截至 2018 年 12 月的 15 年期间,美国积极管理的股票基金中有 91.62 % 跑输了标准普尔 500 指数。
在这篇文章中,提出了一种基于机器学习的系统方法,它能够大大超过同期的标准普尔 500。
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
目标和方法
用 Python 编写的机器学习算法旨在预测 S&P 1500 指数中哪些公司的月度表现可能优于标准普尔 500 指数。为此,实施了基于随机森林回归的算法,将 S&P 1500 指数所有成分的财务比率作为输入。本项目中使用了以下工作流程:
- 数据采集和准备
- 数据清理
- 特征选择
- 训练和回溯测试随机森林回归器
*请注意,本项目中使用的数据集来自专有来源(标准普尔和彭博),因此无法公布。因此,我们将跳过本文中的步骤 1。那些通过所需订阅访问数据集的人可以参考托管在以下 Github 项目上的完整笔记本: SP1500StockPicker 。
随机森林集成学习方法
随机森林方法基于多个决策树。单个决策树是通过自顶向下的方法构建的,其中数据集遵循基于变量值的一系列布尔分裂,这些布尔分裂在每个节点产生最精确的分离。每个唯一的决策树都是在带有替换的训练集的不同样本上训练的(意味着样本被替换到更大的数据集中)。随机森林回归将多个决策树平均在一起以发出预测。这篇文章不会太深入这个技术的细节,但是在这些由普拉尚特古普塔和乔治赛夫撰写的优秀文章中可以找到更多关于随机森林方法的信息。
An example of a tree with 3 different splits.
工作台
以下代码是在 Jupyter 笔记本上用 Python 写的。JupyterHub 环境用于在计算服务器上托管代码。大多数数据操作都是使用 Pandas 和 NumPy 库完成的。机器学习算法基于广泛的 Scikit-learn 库。对于代码某些部分的并行化,使用了 Python 的多重处理包。最后,特征选择过程基于特征选择器包。
Python 的优点之一是大量的包和库是开源的,任何人都可以使用。利用现有工具的能力来创建创新的解决方案,可以快速高效地解决问题。
数据清理
起始数据集由 86 个变量组成。下图简要介绍了前 5 个条目:
Head of the database.
下表显示了一些最重要的变量。其他变量都在 Github repo 的“variables.txt”文件中定义。
使用下面的 pandas 命令,我们可以看到每个变量有多少个缺失条目:
dataset.isna().sum()
trt1m 5141
exchg 0
tpci 0
adate 441
qdate 0
public_date 0
CAPEI 2332
bm 4764
evm 1942
pe_op_basic 9984
pe_op_dil 74009
pe_exi 10594
pe_inc 10261
ps 475
roe 5294
roce 3336
...
dltt_be 5698
debt_assets 532
debt_capital 5328
de_ratio 535
intcov 63530
intcov_ratio 63542
cash_ratio 56652
quick_ratio 56634
curr_ratio 56635
sprtrn 0
win 0
decision_date 0
SP1500 0
Length: 86, dtype: int64
我们可以看到一些变量有大量的缺失条目,知道数据帧的总长度是 413 012 个条目。为了解决这个问题,采取了以下步骤来清理数据:
- 遗漏股票月度回报的行被删除,因为我们不能交易遗漏的回报。
- 超过 50%的行为空的变量被删除。
- 对于缺失的财务比率,我们使用来自 Scikit-learn 的 SimpleImputer 包,用整个数据库的变量平均值替换缺失值。这种方法非常懒惰,会给数据增加建模错误。更合适的方法是使用每种特定股票 n 个月的平均值。尽管如此,还是使用了惰性方法,下面的代码总结了这里列举的 3 个步骤。
#Dropping rows with now "trt1m" values:database = database[np.isfinite(database['trt1m'])]# Dropping columns with more than 50% of the rows missing:database = database.loc[:, database.isnull().mean() < .5]#Looping through the variables to replace NaNs with the average:imp=SimpleImputer(missing_values=np.nan, strategy="mean" )
impute_columns=database.columns[database.isna().any()].tolist()for i in impute_columns:
database[i] = imp.fit_transform(database[[i]])
采取了辅助步骤来完成清理过程,可以在本文结尾插入的完整笔记本中查找,或者在我的 Github 上托管。
特征选择
使用了来自 WillKoehrsen 的包特征选择器。你可以在这里阅读他的文章,全面了解它的功能。
基本上,特征选择算法将有助于识别无意义的(低重要性)和共线的特征,以便从不必要的数据变量中修剪起始数据集。移除那些共线变量将减少来自没有贡献的条目的数据集,从而加快整体机器学习过程。当试图识别变量之间的非线性关系时,这种特征选择也将有助于提高算法的泛化能力。
使用 feature_selector 包识别高度相关的要素并打印出相关矩阵非常简单:
fs.identify_collinear(correlation_threshold=0.975)
fs.plot_collinear(plot_all=True)
Correlation matrix for the different variables.
从上面的图中,我们可以看到一些特征具有高相关性(更红),并且通过该函数识别了相关性高于 0.975 的 5 个特征。
接下来,我们想要识别重要性为零的特征。这些特征将不用于分割决策树的任何节点,因此可以被移除以减少训练时间。feature_selector 包从 LightGBM 库中实现了一个渐变增强机器。该函数将对 10 次训练运行的特征重要性进行平均,以减少方差。
fs.identify_zero_importance (task = 'regression', eval_metric = 'auc', n_iterations = 10, early_stopping = True)1 features with zero importance after one-hot encoding.
低重要性特征也可以用 feature_selector 包来标识。该方法使用来自零重要性特征选择的结果来识别不需要获得 99%的总重要性的特征。
fs.identify_low_importance(cumulative_importance = 0.99)69 features required for cumulative importance of 0.99 after one hot encoding.
5 features do not contribute to cumulative importance of 0.99.
现在,我们可以从上述 3 个步骤中移除所有选定的特征,以获得最终的数据框:
all_to_remove = fs.check_removal()
database = database.drop(columns = all_to_remove)Total of 9 features identified for removal:
['ptpm', 'tpci', 'debt_invcap', 'debt_ebitda', 'opmad', 'aftret_equity', 'dltt_be', 'cfm', 'capital_ratio']
机器学习算法
本节介绍的机器学习算法将预测整个月最有可能跑赢 S&P500 的股票。预测将在指定月份的第一天进行。我们还希望能够在不同时期对算法进行回溯测试,以验证模型的性能。我们将定义一个名为“rfstockpicker_backtest”的函数,它将包含以下条目:
该函数的第一部分获取决策日期并标识前一个月。然后,它会创建一个范围从上个月到 7 年前的训练集。选择这个持续时间是因为我们知道过去 33 个经济周期的平均持续时间是 56 个月。目前的扩张周期已经持续了 10 年。7 年的时间让我们可以为我们的每个训练集获得大约一个完整的经济周期。测试集将是我们希望发出预测的月份。我们将使用一个基本的迭代,一个月接一个月地回溯,以便进行几个月的回溯测试。在每次迭代中实例化我们的变量可以确保没有信息及时传播回来(详细信息请参见完整代码)。
在删除用于训练和测试的非必要数据后,该函数从 sklearn 库中实例化 aRandomForestRegressor 对象,并使用作为输入参数提供的树的数量(n_estimators)和可用进程(n_jobs)对其进行初始化。然后,该函数在训练集上训练算法,并在测试月对 SP1500 的每只股票发出预测。
函数的最后一部分返回各种要素的重要性,以供进一步分析。
例如,可以测试 2018 年 12 月的函数:
results,feature_imp,importances,train_feature_list=rfstockpicker_backtest(database,("2018-12-01"),7,1,100,24)
对“rfstockpicker_backtest”函数的调用将返回以下信息:
例如,假设每个月,决定买入跑赢指数几率最高的前 10 只股票。可以使用以下命令显示这些内容:
portfolio=results[0].nlargest(10, 'predictions')
portfolio
The 10 stocks with the highest probability of beating the SP500 for December 2018.
用相等的权重对这些回报率进行平均(算术平均)得出 2018 年 12 月的回报率为 2.09% ,相比之下,同期的 SP500 回报率为1.79%。
可以通过查看特征重要性来改进该模型:
虽然在该图中,许多特征被压缩在 x 轴上,但是仍然可以看出其中一些特征具有非常低的重要性。重要性低于 0.02 的要素可以使用以下命令移除:
df_importance = pd.DataFrame(feature_imp, columns = ['Feature', 'Importance'])
feature_to_drop=df_importance.Feature[df_importance['Importance']<0.02]
new_db=database.drop(columns=feature_to_drop)
这个新数据库允许我们增加 2018 年 12 月的月度回报率,回报率为 3.57%,提高了 +1.48%。
现在让我们从 2003 年 12 月到 2018 年 12 月,对我们的模型进行 15 年的回溯测试:
results,feature_imp,importances,train_feature_list=rfstockpicker_backtest(new_db,("2018-12-01"),7,(12*15),100,24)
主迭代循环将于 2018 年 12 月开始,并在 1215 或 180 个月的时间内回溯 1 个月,以覆盖整个回溯测试期。在 180 个月的测试期内,我们的模型获得了**+1421%的复合回报,相比之下,实际 SP500 指数的复合回报为 +261 % 。**因此,该模型在 15 年期间产生了+1160%的超额回报。*
Growth of 1$ over the 15 year period.
结束语
为了简化项目,提出了三个主要假设:
- 前一个月买入的每只股票都被卖出,每个月测试 10 只新股票。因此,有可能一只股票在月末被卖出,然后第二天又被买入。
- 没有考虑交易成本,这将影响模型的复合回报。在测试的每个月中,有 10 只股票被买入,10 只股票被卖出。
- 没有考虑股息,这也将影响模型的复合回报。
代码中还可以实现许多改进。其他机器学习技术和神经网络将在以后的文章中探讨。敬请期待!
如果你有任何意见或问题,欢迎写在下面!我会尽我所能回答他们。这篇文章的代码可以从项目的 Github Repo 的 Jupyter 笔记本中获得。
感谢您的宝贵时间!
卡尔格算法之美:图中蒙特卡罗的随机性
原文:https://towardsdatascience.com/beauty-of-kargers-algorithm-6de7e923874a?source=collection_archive---------13-----------------------
回到镇上的 Karger 算法(带 Python 代码)
分而治之!这是历史上多年来广泛使用的策略。但是怎么分呢?一般来说,最直观的方法是在系统、网络甚至人群中寻找具有最低亲和力或链接级别的片段!所以,我们开始吧!
你准备好分割切片了吗?让我们从网络开始。我们喜欢密集的网络,否则,即使只有一条边或一条线断开,网络的很大一部分也可能会瘫痪——这绝对不是我们想要的!网络中通常存在集群,即不均匀分布的段。当有效地处理这些片段或“簇”的分离时,我们寻找它们之间的边,使得边的数量最小。
Polygon Mesh
我们可以将同样的论点应用于其他领域,例如“图像分割”。如果你想把一幅图像分割成几个片段,最简单的方法是用低相似度,也就是最少的切割次数来断开链接。想象一个多边形网格。多边形网格是组成 3D 对象的顶点、边和面T3 的集合。断开低相似度的图片链接可以给你不同的图片。
还想到地下线路!这么多节点(站)和边(铁路)!如果你想把地铁系统一分为二,最少要断开多少条线路?
如你所见,有许多现实生活中的小问题。我们如何处理它们?传统算法是“最大流最小割”。它是确定性的,这意味着当我们应用这个算法时,我们 100%的时间都得到正确的最小割!没有失败概率!缺点是 100%的保证是有代价的:非常慢。运行时间最多为 O(顶点数*边数的平方,因此时间复杂度大约为 n 倍。
有许多聪明的算法,它们的运行时间非常快,为 O(n ),但在我看来,没有一个算法,即使是最优秀的算法,设计得像 Karger 的算法一样优雅,它在一个图形问题中使用“随机采样”!!
如果您熟悉快速排序算法,那么您已经知道随机抽样在排序和搜索中的有效性。90 年代初的一名博士生 David Karger 利用图问题中的随机性设计了最小割情形的随机收缩算法。作为一种蒙特卡罗算法,Krager 算法提供了一种具有一定(尽管很小)概率的解决方案,比最大流最小割算法快得多。
[Picturing contraction of edges](http://tcs.nju.edu.cn/wiki/index.php/高级算法 _(Fall_2019)/Min-Cut_and_Max-Cut)
假设我们有一个无向图 G = (V,E)。为了以尽可能少的切割将连通图 G 切割成两个连通子图,算法基本上使用了边的收缩。要实现它,应该把边两边的两个顶点拉在一起。
我们用伪代码实现算法如下:
现在问题来了:成功的概率有多大?
在具有 n 个顶点的图中,Karger 算法的单次运行给出成功概率为 1 / (n 选择 2)且运行时间为 O(n)的结果。不坏,但一个人需要幸运地在第一次运行中找到最小切割边缘。
做多跑可以增加成功的概率。如果我们运行卡格的算法 n 次,我们没有得到最小割的失败概率是 1/e .一个常数!不取决于顶点数!
但是,如果我们运行 Karger 的算法 n ln (n) 次,这被视为最优值,那么 P(失败)< = 1/n , P(成功)>= 1–1/n,这意味着随着你得到越来越大的图,Karger 的算法成功的概率变得越来越好!所以,在一个有 50 个节点的图中,如果我们运行算法 10000 次左右,成功的概率是 98%!!
如此高的 98%的成功率是有代价的。运行时间是 n(顶点数)和 m(边数)的多项式,相当慢:O(n·m)。
稍加改动的版本,Karger-Stein 算法,成功概率是原算法的两倍!!
Karger 算法的 Python 代码如下:
顺便说一下,如果你想了解更多一点,我建议你观看斯坦福算法的 youtube 视频。
成为数据科学专家
原文:https://towardsdatascience.com/become-a-data-science-expert-1b8dccd71526?source=collection_archive---------33-----------------------
了解你的领域,不断训练,展示你的技能。
成为数据科学家的方法是通过实施自己选择的明确指导方针,让自己成为领导者。这些指导方针的良好基础如下。
Plan, build a strategy, prioritize.
了解你的领域
专注于一个领域不仅能提高你的智力,还能让你在更广阔的数据科学领域有更广阔的视野。
你应该尝试从一个单一的领域到更广阔的领域来培养你的技能。从 Python 开始,进入 Django、R、Java,学习一些你舒适区之外的东西。这样,你也能更好地掌握日常使用的技巧。都是练出来的。
让你的模型基于数据
不要只是玩模型来适应机器学习社区使用的数字模型,你还应该建立在社区已经完成的基础上。
如果您正在寻找公式来为您领域的变量建模,如果您知道社区中所有可用的公式,任务将变得容易得多。
基于现有数据集构建
在这个领域,要么建立在现有的数据源上,要么建立自己的数据集。
建立在已经存在很长时间的数据上,而不是建立你自己的数据集,将为你的模型提供适当的反馈,这将有助于模型的公式化。
关注数据科学的核心优势就是围绕核心问题解决问题。数据科学为您提供了独特的机会,将您所学的知识应用到现实世界的用例问题中。通过利用现有的数据,你将能够验证你的新知识。
记录你的成功
记录你的成功也是必须的,因为你会经历艰难的失败并从中学习。
记录下你做过的事情和学到的东西。
这将有助于您在需要时复制您的工作。
此外,数据科学主要是关于我们所学方法的迭代开发。编码,再迭代,再编码。
你需要验证你所有的方法至少 3 次。
通过记录您的成功和失败,我们将能够回顾您的工作,并将其置于数据科学家社区的背景中。
在数据科学领域的成功可以建立你的可信度
要想在行业中可信,你至少需要像其他人一样做一些事情。
如果你发现数据科学市场竞争过于激烈,那么通过专注于卓越来提高你的标准,在高薪数据科学市场中一路向上。
这样你就可以从中获得成功,这也将激励其他数据科学家进行创新。
需要不断学习
数据科学是一个节奏非常快的行业,每一步都面临着许多不同的挑战。这使得你的生活很容易停滞或落后。
这是因为你必须不断学习才能跟上竞争。
保持较高的学习速度也是在下一个职位中保持竞争优势的必要条件。这会帮助你吸引更好的工作,提升你的品牌。
想在数据科学领域找份工作吗?看看我的另一篇文字或者查一下这个数据科学书籍和课程清单。
Data Science Job
最后,如果你想了解成为一名数据科学家意味着什么,那么看看我的书数据科学工作:如何成为一名数据科学家,它将指导你完成这个过程。
成为数据忍者:三个步骤
原文:https://towardsdatascience.com/becoming-a-data-ninja-three-steps-da3e1f3dc2d9?source=collection_archive---------41-----------------------
敏捷处理数据的三个步骤,让您能够创造价值。
Photo by Markus Spiske on Unsplash
数据科学是发展最快、薪酬最高的非管理类职业之一。例如,由 Burning Glass、IBM 和商业高等教育论坛进行的 2017 年研究发现,根据前 20 大都市地区的数据,数据科学家和数据工程师的预计五年增长率为 39%。客观地说,【2010 年至 2018 年间的年就业增长率为 1.4%。
这也是竞争最激烈、门槛最低的职业之一。你还能在其他什么高薪和受欢迎的工作中参加低成本的编码训练营,积累具体的技能,以便第二天在工作中应用?而且,训练营也不缺!
面向年轻专业人士的数据科学
数据科学是年轻专业人士最好的工作之一,因为它允许你实践与不同行业的价值创造直接相关的各种技能。例如,你不仅可以学习如何收集和分析数据,还可以应用结果来推动战略决策,从而更好地为客户服务。您还将学习如何将这些结果传达给营销人员、经理等。
数据科学是年轻专业人士最好的工作之一,因为它允许你实践与不同行业的价值创造直接相关的各种技能。
从事这些工作的人也比他们的同行有更高的满意度和参与度。利用盖洛普 伟大工作示范调查 的新数据,我用数字技能来衡量工作满意度。工作满意度是十个具体工作维度的函数,从薪酬、福利到职业发展;数字技能是根据我和不列颠哥伦比亚大学的合著者 Giovanni Gallipoli 之前的工作来衡量的。
下图证明了工作满意度和数字技能之间的紧密联系。当你深入挖掘时,你会发现这种积极的联系是由几个特定的维度驱动的:对薪酬的满意度、对工作时间的控制、职业发展以及改变你认为错误的事情的能力。最后一项工作特征很能说明问题。我们经常发现自己想要对系统进行改进,而不是坚持现状。数据科学通常会为您提供做出改变的工具!
成为数据忍者
步骤 1:清理数据
您必须知道如何处理和清理任何形状或大小的数据。有时数据是非结构化的。有时它会丢失很多值。而且,有时它包含复杂形式的测量误差,会破坏预测和因果推断。
最后一种类型尤其难以规避。举例来说,我记得曾参与收入动态面板研究(Panel Study of Income Dynamics),这是一个自 1967 年以来追踪个人的数据集。家庭调查数据的挑战之一是,受访者并不总是说实话,或者有时他们根本不知道问题的答案。如果有人问你去年工作了多少小时,你会怎么回答?问题是这个测量误差不是随机的:它可能与你试图预测的结果的其他特征相关。
无论数据有什么问题,你都必须找出如何清理它,使它对决策有用。这里有一篇关于清理数据的文章。
无论数据有什么问题,你都必须找出如何清理它,使它对决策有用。
步骤 2:选择正确的评估者
评估哪种类型的评估者适合你的环境,并在给定的背景下仔细检查他们的假设。我们在数据科学中可能犯的最大错误之一是将复杂的算法(如随机森林)应用于不太适合它的情况。
我们在数据科学中可能犯的最大错误之一是将复杂的算法应用于并不特别适合它的情况。
例如,如果你试图理解一种新产品的推出会如何影响需求,并且你正在查看基于以前产品发布的历史数据,那么你可能对因果关系比对预测更感兴趣。如果是这样,那么你更关心是什么在驱动你右边变量的运动,而不是简单地得到一个高的 R 平方。数据科学和经济学的比较见。
步骤 3:确定相关的补充数据
请记住,您不仅仅局限于单一数据集:整个世界都是您的囊中之物。专注于单个数据集是如此容易——完善它并用变量进行各种排列。但是,数据科学的美妙之处在于它充满了创造力。有时候,连接数据集是你能做的最有成效的事情。
数据科学的美妙之处在于它充满了创造力。
例如,我即将发表在《法律与经济学杂志》上的一篇论文用盖洛普的美国每日民意测验量化了工作权(RTW)法对工人福利的影响。要回答这个问题,我只需将不同州通过这些环球旅行法的时间数据进行合并。在一个更复杂的例子中,我在发表的另一篇论文调查了金融危机期间房屋抵押贷款止赎对社区和社会福祉的影响,发现即使在没有被直接止赎的个人中,也存在有意义的影响,这些人只是生活在被止赎的人周围。
坚持学习!
数据科学领域在不断变化。即使当你认为你知道的足够多的时候,也不要忘记继续学习更多。我在学习新技术和部署现有人力资本之间挣扎,但这是一场值得打的斗争。当我们认为自己无所不知的时候,我们就失去了创造更多价值的潜力。
克里斯特斯·a·马克里迪斯在斯坦福大学获得了管理学&工程学和经济学博士学位,并担任麻省理工学院斯隆数字经济倡议的数字研究员、哈佛大学肯尼迪政府网络安全倡议学院的非常驻研究员、贝勒大学宗教研究所的非常驻研究员以及盖洛普的高级顾问。
学习数据科学——当丹·贝克尔指出我完全错了的时候
原文:https://towardsdatascience.com/becoming-a-data-scientist-when-dan-becker-pointed-out-i-had-it-all-wrong-86fb81397e8c?source=collection_archive---------4-----------------------
Kaggle Learn 的负责人在网上研讨会上给了我一个惊喜
在你的职业生涯中,你是否有过这样的时刻,当你认为自己走在正确的道路上,当你遵循一个稳定的计划,带领你到达你想要的地方,然后有人踢你的计划的坚果,并通过 A + B 告诉你你完全错了?
这就是 Dan Becker 博士、数据科学家和 Kaggle Learn 的负责人昨天在他为 Kaggle CareerCon 2019 举办的题为的网络研讨会上对我说的,“为什么数据科学技能培养可能会阻碍你(以及你应该做些什么)。”
从数字营销到数据科学
获得普通工程学位后,我带着项目管理和编程方面的技能小心翼翼地进入了就业市场。我不确定自己是否真的想花时间设计一些长达数年的甘特图,于是决定冒险进入数字营销领域。为什么选择数字营销?因为当我意识到 Google AdWords(我知道,Google Ads now)是由整天盯着宽大的统计表格看并从中获得报酬组成的时候,我就爱上了(奇怪,我知道。各得其所!).
但是经过五年的数字营销,我意识到这不适合我。这件事不会让我对去工作感到头晕目眩。这不是我可以对那些可能要求也可能没有要求的人喋喋不休的话题。
所以我决定休息一下,开始一个数据科学 MOOC,看看它是否像我想象的那么有趣。剧透一下,的确如此。因此,我决定再接再厉,在法国最古老的工程学院获得数据科学入门课程的认证。
“我有一个计划……”
“好的。酷毙了。现在你是数据科学家了,赖。你的故事的重点是什么?”不完全是,你这位持怀疑态度的读者。尽管我已经拿到了证书,但我还是决定继续我的职业生涯,在一家咨询机构做数据分析师。它介于我的数字营销过去和我的数据科学未来之间。有道理。这是一条稳定的道路。该认证让我对数据科学项目和 Python 编程有了稳定的基本了解,因此我可以像这样与我的销售工程师:“Clara,我有一个 2 到 4 年的计划。我将继续在线学习 Python,同时通过成为一名数据分析师来获得数据项目方面的知识,当我对自己的 Python 技能足够自信时,我将成为一名数据科学家。”**
既然我已经说过了,我已经做了一点调整,将 2 到 4 年改为 1 到 2 年。但是,丹·贝克尔还是用世界上所有的仁慈粉碎了这个计划。
是时候改变策略了
"在光谱上,有两个极端:短期的 Sal 和长期的 Lee . "
Dan 是这样解释的:进入数据科学有两种方法。
一方面,你有短期的 Sal,他们获得了找工作所需的知识,一头扎进去,然后在数据科学领域找到一份工作,边干边学。另一方面,你有一个长期的李,他不断学习,不断学习,最后得到了一份数据科学家的工作。没错,读者,就是我。而这也正是丹所说的应该是一条【尚可】的职业轨迹。
但让我们现实一点,萨尔更快地走上工作岗位,更快地获得实践经验(意味着李无法从教科书中获得的实用知识),并为自己赢得了该领域的网络,这是孤独的李在他的学习隐士生活中所没有得到的。这就是实际发生的情况:
此时,我正盯着网上研讨会,很烦。“哦,丹,你怎么敢这样粉碎我的梦想!”但丹想到了我们,可怜的李氏兄弟看着所有参加 Youtube 直播的 sal 在评论区用虚拟手指指着我们笑。他有一个建议,对你们中的一些人来说可能很简单,但对我思考我的方法有很大的影响。
"找到你的激情项目,为之努力,发表它,在推特上发布它."
“好的,坚持住,丹。到目前为止,我只是设法复制了一份预先准备好的泰坦尼克号生存分析,修补了一些分类算法,并为我的认证做了一个非常成功的文本挖掘项目。你真的认为我会把我的任何工作放在那里让顶尖的数据科学家屠杀吗?”在这一点上,我坚信 Dan 能读懂别人的心思,因为他随后解释说,是的,第一个项目可能不好,但没关系,把它们放在那里可能会吸引一些建设性的反馈,从而使下一个项目变得更好。李就是这样变成萨尔的。
“很好,丹,很好。杰夫,是时候接受挑战了。”
Jeff,感谢你校对这篇文章,并作为我的李的 Sal。
追踪
对于这篇文章,我想将丹的回答添加到 LinkedIn 上的原始帖子中。再说一次,我非常钦佩洞察力。( Fangirling 多,赖?)
Kaggle 比赛是一种很好的学习方式。尤其是因为您可以尝试一个问题,然后看看您的方法与其他人相比如何(因为许多人将他们的工作发布在容易访问的“内核笔记本”中)。但我不认为这是一条通向投资组合项目的捷径,能让你获得第一份工作(我认为这对大多数人来说是真正的转折点)。原因如下:竞赛有许多熟练的参与者。你需要取得非常好的成绩才能引起雇主的注意,而且(重复地说)大多数人都在平均水平或平均水平以下。相反,我建议找一个你感兴趣的话题,做一些数据探索。搜索相关数据,探索它,直到你能写一篇关于它的好博文(最好是在聚会上展示)。它可能是关于新闻,你的一个爱好,无论什么。让你的项目可视化(可能通过图表),清晰地传达。见鬼,也许甚至头脑风暴一下你是否可以利用你的数字营销背景来帮助它获得更多的曝光率。但是我们的想法是做一些有创意的事情。这更有可能引起你的注意(我昨天提到的那个黄领巾把戏),更多的读者(或 meetup 与会者)会觉得它很有趣。
成为 3.0 级数据科学家
原文:https://towardsdatascience.com/becoming-a-level-3-0-data-scientist-52641ff73cb3?source=collection_archive---------0-----------------------
想成为大三,大四,还是首席数据科学家?了解您需要做些什么来驾驭数据科学职业游戏。
公司正在招聘三个级别的数据科学家:初级、高级或首席。无论您是刚刚开始接触数据科学,还是希望转行,您都不可避免地会发现自己处于这些级别之一。
Photo by Kelly Sikkema on Unsplash
这篇文章旨在阐明每个数据科学职业水平范围之外的期望和内容。虽然公司可能有不同的职称,这篇文章提供了一个通用的基线。此外,这篇文章最后给出了一些实用的建议,告诉你如何为进入人工智能或当之无愧的晋升做好准备。
让我们升级吧。🎚
数据科学技能矩阵
数据科学家应该具备三个领域的知识:统计、工程和商业。然而,并不期望你一开始就掌握所有这三个领域。在寻求入门级职位时,你应该重点关注哪些技能?随着职业生涯的发展,哪些技能变得越来越重要?
下图显示了从 1.0 到 3.0 的每个数据科学级别的市场预期。这些结果是基于我在该领域的个人经验以及与来自史丹福、、、阿克塞尔·施普林格和邢的专家和有影响力的人的交谈。为避免混淆,我们将这些职位称为 1.0 至 3.0 级。
下面我们就来详细分析一下这些岗位的期望值。
初级数据科学家—进入 1.0 级
初级数据科学家的原型是一名年轻的毕业生。热门的研究领域包括计算机科学、数学或工程。初级数据科学家有 0-2 年的工作经验,熟悉用 Python 创建结构化数据集的原型。她参加过 kaggle 比赛,并拥有 GitHub 个人资料。
初级数据科学家可以为公司提供巨大的价值。他们刚刚参加完在线课程,可以立即提供帮助。他们通常是自学的,因为很少有大学提供数据科学学位,因此表现出巨大的承诺和好奇心。他们对自己选择的领域充满热情,渴望了解更多。初级数据科学家擅长构建解决方案的原型,但仍然缺乏对工程和业务思维的熟练程度。
初级数据科学家应该对机器学习有强烈的热情。你可以通过参与开源项目或 kaggle 挑战赛来展示你的热情。— Dat Tran ,Axel Springer AI 领衔
他们做什么
如果一家公司正在招聘初级数据科学家,通常数据科学团队已经到位。该公司随后寻求帮助,让更有经验的同事生活得更轻松。这包括快速测试新想法、调试和重构现有模型。你将作为陪练与团队讨论想法。你提出如何把事情做得更好的新想法。您对您的代码负责,不断努力提高代码质量和影响。你是一个优秀的团队成员,总是希望支持你的队友完成构建优秀数据产品的任务。
他们不做的事
初级数据科学家没有设计复杂产品解决方案的经验。因此,她在一个团队工作,将数据科学模型投入生产。由于初级数据科学家刚刚加入公司,她并没有沉浸在公司的业务中。因此,预计她不会推出新产品来影响的基本商业方程式。但是,一直期待的是学习和提高自己技能的欲望。
我对初级数据科学家完成重要项目的能力感兴趣。所谓完成,我的意思是这个项目从头到尾都是由这个人完成的——或者在一个团队中完成的——并最终形成一个完全冲洗出来的产品。我发现这与数据科学家在工作中领导项目的能力相关。—Kian katanforosh,deeplearning.ai 创始成员,斯坦福 CS 讲师
如果你擅长做一名初级数据科学家,那么你在理解数据科学模型方面有很强的背景。你表现出永不满足的好奇心,想了解工程和公司的业务,以提高自己的技能。
下一关是什么样子的?接下来我们来了解一下资深数据科学家。
高级数据科学家—达到 2.0 级
高级数据科学家已经担任初级数据科学家、软件工程师或完成博士学位。他在该领域拥有 3-5 年的相关经验,编写可重用的代码,并在云环境中构建弹性数据管道。
高级数据科学家应该能够构建数据科学问题。优秀的候选人从过去的数据科学经验中获得了深刻的见解。我还深入研究了他们编写产品代码的能力。—Kian katanforosh
公司更愿意雇用高级数据科学家,因为他们以合理的薪水提供巨大的价值。他们比初级数据科学家更有经验,因此省略了代价高昂的新手错误。他们也不像首席数据科学家那样昂贵,但仍有望在生产中交付数据科学模型。这是一个非常有趣的级别,已经超过了 1.0 级,但仍有增长到 3.0 级的空间。
他们做什么
这位资深数据科学家精通将数学模型投入生产的艺术。当首席数据科学家或业务经理分配任务时,高级数据科学家以构建良好架构的产品为荣。他避免模型中的逻辑缺陷,怀疑表现太好的系统,并以正确准备数据为荣。高级数据科学家指导初级数据科学家,并回答管理层的业务问题。
他们不做的事
高级数据科学家不需要领导整个团队。高级数据科学家没有责任为新产品出谋划策,因为这些想法是由更有经验的同事和经理提出的。虽然高级数据科学家知道他们构建的产品的细节,但他们并不需要知道所有数据驱动产品的整体架构。与 1.0 级数据科学家相比,2.0 级数据科学家擅长统计,在工程方面也更胜一筹,但却偏离了 3.0 级数据科学家的无趣业务部分。
高级数据科学家必须能够将他们的代码投入生产(在数据工程师的支持下)。高年级学生应该能够独立完成交给他们的项目。— Sébastien Foucaud ,Xing 数据科学副总裁
高级数据科学家通过他们的模型产生的影响来衡量。他对统计模型的内部运作以及如何实现它们有很好的直觉。他正在更好地了解公司的业务,但预计还不会提供业务问题的解决方案。
Photo by Carl Raw on Unsplash
现在我们已经调查了 2.0 级,让我们看看最终的 3.0 级是什么样的。
首席数据科学家—残局级别 3.0
首席数据科学家是数据科学团队中最有经验的成员。她拥有 5 年以上的经验,精通各种类型的数据科学模型。她知道将模型投入使用的最佳实践。她知道如何编写计算效率高的代码,并潜伏在周围寻找高影响力的商业项目。
除了她无可挑剔的工程技能和对所使用的科学模型的深刻理解之外,她还非常了解她所在公司的业务。她有利用数据科学影响业务基线的记录。
在编写一行代码之前,首席数据科学家需要很好地理解他们正在解决的业务问题。也就是说,他们需要有能力在实施之前验证想法。这种方法提高了数据科学项目的成功率。— 易贝人工智能产品负责人 Adnan Boz
他们做什么
首席数据科学家负责创建高影响力的数据科学项目。与利益相关者密切合作,她负责领导一个潜在的跨职能团队,为给定问题提供最佳解决方案。因此,她的领导技能从 1.0 级和 2.0 级开始发展。首席数据科学家充当不同部门产品经理的技术顾问。凭借她在主要数据科学领域的丰富经验和技能,她成为任何项目的宝贵资产。
他们不做的事
在引导关于所需技能的讨论时,首席数据科学家不负责招募新的团队成员。尽管她了解自己公司的业务,并建议有影响力的新产品,但产品经理仍然负责市场的采用。她也领导团队,但职业发展决策仍由团队领导做出。
首席数据科学家应该独立于数据科学主管指导项目。人们期望这个人获得初步的领导技能,因此,这个人能够清晰地交流、善解人意、善于观察人是很重要的。— 达特兰
首席数据科学家已经看到了产品失败的原因,因此她成功地推动了新项目。她是产品讨论的重要贡献者,喜欢在公司开展数据科学教育。凭借其在交付有影响力的数据科学解决方案方面的经验,她是数据科学部门最有价值的资产。
Photo by Val Vesa on Unsplash
现在,您已经看到了一名数据科学家从 1.0 级到 2.0 级直至 3.0 级的不同期望,让我们看看您如何利用这些知识来推进您的职业生涯。
提升您的数据科学职业
无论您是希望进入 1.0 级的数据科学职业游戏,还是希望进入更高的级别,都没有关系。采取以下步骤,开始你的下一次职业生涯。
1.评估你的技能
首先,将您的技能与数据科学技能矩阵进行比较。你的统计技能有多扎实?你的工程技术有多好?你有多精通商业?
2.计划你的推广
许多公司都有年度晋升周期来提升员工。脸书产品设计副总裁朱莉·卓建议,获得晋升的第一步是实现你的抱负,提升知名度。在晋升周期开始时表明,你希望向你的经理推进你的职业发展。询问您的经理,她对您当前的技能组合如何评级,以及您希望达到的下一个数据科学职业水平。
3.提高你的技能
一旦你分析了你的技能并宣布了你对升职的渴望,是时候提升你的技能了。
Photo by Samuel Zeller on Unsplash
要不要打入 AI?然后对统计模型了如指掌,并学习如何用结构化数据集解决问题。你希望进入 3.0 级吗?确保你已经掌握了数学、工程和商业技能。有了这些要点,你就为和你的经理谈判升职做好了充分的准备。
关键要点
浏览数据科学职业水平很有趣。请记住以下要点:
- 初级数据科学家拥有良好的统计技能
- 高级数据科学家擅长将模型投入生产
- 首席数据科学家知道如何创造商业价值
- 提升,评估你的技能,宣布你进步的愿望,努力提高你的技能
不同的数据科学职业级别之间存在细微差别。例如,Séb Foucaud 在初级数据科学家中寻找的是强大的工程技术,而不是数学技能。一些高级数据科学家可能会发现他们对构建可伸缩数据管道的热情,并转变为数据工程角色。一些首席数据科学家更喜欢发展技术专长,而其他人则乐于专注于业务技能。无论你走哪条职业道路,围绕数据科学专业知识的三个主要领域发展你的技能都会让你走得更远。
这篇文章是正在进行的教育数据科学家成为商业头脑系列的继续。该系列旨在帮助您完善您的整体数据科学技能。如果你喜欢这种形式,请在 LinkedIn 或 Medium 上关注我,了解最新文章。
Photo by Mirko Blicke on Unsplash
成为一名自学成才的数据科学家
原文:https://towardsdatascience.com/becoming-a-self-taught-data-scientist-5563f546bb7b?source=collection_archive---------4-----------------------
数据科学工作被认为是 21 世纪最性感的工作。这是一个大胆的说法,主要是因为我们现在是在 2019 年,所以谁知道就业市场在 50 年后会是什么样子。
Photo by Alex Radelich on Unsplash
然而,如果我们只看过去 15-20 年的职称,那就完全是另一回事了。请继续阅读本文,您将会发现一些进入数据科学领域的最令人惊奇的资源。你是否有其他领域的学位完全无关紧要。
不久前,我发表了一篇关于自学与获得数据科学学位的来龙去脉的文章:
[## 数据科学:自学与大学
哪个选项对你来说是正确的?让我们深入了解一些利弊。
towardsdatascience.com](/data-science-self-taught-vs-college-b5482b68849e)
那篇文章深入探讨了这两种选择,所以如果您对这个主题感兴趣,可以去看看。然而今天,我想进一步探索自学路线,为你提供一些惊人的入门资源。
这篇文章是写给谁的?
- 没有任何学位的人
- 那些前一段时间完成大学学业并希望转向数据科学的人
好了,我们不要再在介绍上浪费时间了,现在我们将进入正题。
自学是什么意思?
好问题。简而言之,它的意思是,你没有在感兴趣的领域完成任何大学学位(让我们说数据科学),并且你正在感兴趣的领域工作(再次,数据科学),那么你被认为是感兴趣领域的自学者。
你仍然可以自由地完成在线课程和阅读书籍,但是你没有花几年时间在大学课桌后面接受正规教育。
好了,现在,当这个问题解决后,让我们深入了解成为一名自学成才的数据科学家的第一种方式。
从 0 路线
如果符合以下条件,您将属于此类别:
- 你没有大学学位
- 你的数据和编程知识水平很低或者根本不存在
Photo by Annie Spratt on Unsplash
那么应该怎么做呢?这是一个很难回答的问题。开始时,你需要掌握基础知识,也就是数学和统计技能。是的,你需要学习如何编码,最好是用 Python 。
不久前,我写了一篇文章,列出了进入这个领域所需的每一个先决条件的我最喜欢的资源:
[## 终极数据科学必备学习清单
查看学习线性代数、微积分、统计、概率和编程的最佳位置。
towardsdatascience.com](/the-ultimate-data-science-prerequisite-learning-list-348ce89805f9)
我知道这很难,但没人说这很容易。花些时间了解基本情况。你不必手动进行大量的计算,一个坚实的视觉理解应该绰绰有余。
我不建议用手做大量的计算,原因之一是计算机很容易做到。对于计算机来说,困难的是将问题框定,并知道在哪些情况下该做什么(不,我不是在说条件语句)。这就是为什么数学和统计的可视化方法是一座金矿。
如果你花时间深入学习数学、统计和编程,我会说,你和几年前在大学里听过这些话题的人一样,都处于开始学习真正的数据科学的有利位置(数学大学的学生不包括在内)——因此大学毕业的人绝不比你强——至少在数据科学方面。
所以这是从 0 路线。现在,让我们在深入研究资源之前探索另一条路线。
转行路线
转行可能会很艰难。你可能已经在一个领域工作了几年,并认为它不适合你。这很好。也许你厌倦了,也许这份工作不够激励人……原因不胜枚举,我不想讨论。
你想尽快做的是诚实地评估你的数学和统计技能。我说真的。承认你对 10 年前听过的话题生疏了并不丢人。
如果您对以下主题的理解没有 100%的把握:
- 线性代数
- 结石
- 可能性
- 统计数字
- 编程;编排
回头参考这篇文章,选择适合你需求的资源——无论是书籍还是在线课程。
好了,都盖好了吗? 您可以进行我个人的资源选择。
自学成才的数据科学家的资源
因此,无论出于何种原因,大学都不是一个选项,但你可以每天花一两个小时来探索数据科学世界。下一步将因人而异,这在很大程度上取决于你是一个书人还是一个视频人。我更喜欢看视频——我只是不想在 8 小时轮班后看书。
我将简单地从我个人最喜欢的开始——我第一次接触数据科学:
[## Python 用于数据科学和机器学习训练营
您准备好开始成为数据科学家的道路了吗!这门综合课程将成为你学习的指南…
www.udemy.com](https://www.udemy.com/course/python-for-data-science-and-machine-learning-bootcamp/)
何塞是一个了不起的教练。有一个对基本 Python 库的快速复习,很快你就会用 Pandas 和 Numpy 进行数据分析,用 Matplotlib 和 Seaborn 进行一些数据可视化。是的,你会做机器学习。不多,也不深入,但足以让你开始。
如果你更喜欢书,那么我推荐这本书:
它叫做 Python 数据科学手册 ,大约 550 页长,涵盖了与视频课程相同的概念——Numpy、 Pandas 、 Matplotlib 和Scikit-Learn——所有这些对数据科学都至关重要。
一旦你完成了基础,是时候深入机器学习了。我有两本很棒的书推荐,其中一本是免费的。让我们开始吧。
统计学习简介 很神奇,也是一本更深入学习机器学习的免费书籍。它有时有点数学化,但易于阅读。对于像机器学习这样广泛的领域来说,它在保持 400 页左右的内容简洁方面做得非常好。唯一的缺点是代码是用 R 写的,不是 Python。但是,嘿,试着把 R 代码“翻译”成 Python 代码,这肯定会是一个很好的练习。
我推荐的下一本书叫做 用 Scikit-Learn 和 Tensorflow 进行机器实践学习。如果我没记错的话,大约有 700 页,但是这是一本好书。你也将深入学习一些深度学习概念,你也将更深入地研究机器学习算法。
你不会因为选择一个或另一个而出错,它们都会很好地为你服务。
对于在线课程,我不得不推荐唯一的 Coursera 的机器学习课程,先生,如果你不懂也不用担心,吴恩达。已经 10 周多了,如果你的基础不稳固,很快就会变得艰难。但是,嘿,来自 12 万用户的 4.9 分的平均评分确实说明了一些问题。
[## 机器学习|课程
机器学习是让计算机在没有明确编程的情况下行动的科学。在过去的十年里…
www.coursera.org](https://www.coursera.org/learn/machine-learning)
这些实验不是用 Python 写的,甚至不是用 R 写的,这些实验是用 Matlab 的免费版本写的,叫做 Octave ,所以这是需要考虑的事情。
后续步骤
你已经浏览了书籍或课程(或两者都有),现在你想知道下一步该做什么。这将根据你的情况而有所不同,但理想情况下,你应该建立一个 GitHub 档案。
找到 5 个好的数据集,尽力而为。做广泛的分析,在 markdown 单元格中写下结论和思考过程,制作一个自述文件,你知道,全身心地投入其中。
这是必要的,原因有二:
- 你在练习新学到的技能
- 你在向潜在员工展示你产生高质量代码和结论的能力
关于阶梯,让潜在雇主看到你最好的工作很重要。你没有大学学位,至少没有相关的学位,所以你需要向他们展示你知道如何完成工作。GitHub 是一条路要走。
花一两个月的时间,做一些让你自豪的事情。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
机器学习流水线监控初学者指南
原文:https://towardsdatascience.com/beginner-guide-to-machine-learning-pipeline-monitoring-aba2af444155?source=collection_archive---------18-----------------------
在机器学习管道的开发中,这是一个讨论较少但很重要的话题
许多公司正在使用 power machine learning 在应用程序的前端和后端提供预测、推荐或分类。来自 The Verge 的一份报告称,“最终,几乎所有东西都将在内部的某个地方拥有(机器学习)。”然而,将机器学习模型构建和部署到机器学习管道并不是开发周期的结束。机器学习模型需要随着时间的推移进行监控和调整,以确保模型不会遇到意想不到的问题,并且在性能上是有效的。下面的流程图很好地说明了机器学习模型的开发周期,以及性能监控如何融入其中,以及人在回路中如何将强化学习带回模型。一篇关于“什么是机器学习?”可以在这篇牛逼的文章上找到。
Source: http://towardsdatascience.com/not-yet-another-article-on-machine-learning-e67f8812ba86
机器学习模型的开发涉及许多步骤,每个步骤都需要不同的技能和知识来执行。本文将关注机器学习开发中一个较少讨论的领域,即机器学习流水线的性能监控。
机器学习管道监控可以分为两个部分:
- ETL 监控
- 分数监控
简而言之,ETL 监控关注的是进入模型之前的数据,而 Score 监控关注的是模型的输出。总之,数据科学家可以看到数据和他们的模型行为之间的相关性。这种理解对于确定需要改进的领域和检测管道中的故障至关重要。本文将关注 ETL 监控。
机器学习流水线的 ETL 监控
机器学习管道中要监控的第一个领域是特征提取过程,在此过程中,输入数据在输入到机器学习模型进行分类之前被转换为数字特征。然而,深度学习模型可能不会将特征提取作为一个独立的过程,如下图所示。为了不混淆观众,这一部分将只关注传统的机器学习模型,如随机森林,它将特征提取作为过程中的一个独立步骤。
Source: https://towardsdatascience.com/cnn-application-on-structured-data-automated-feature-extraction-8f2cd28d9a7e
当我们在数据进入模型之前查看数据时,ETL 监控并不是真正的性能监控,而是防止坏数据进入模型的保护措施。损坏的数据或不寻常的模式会扰乱模型,导致混乱的分类。换句话说,“垃圾进,垃圾出。”
一些数据科学项目从他们的内部操作中获取数据,这使得输入变得清晰、结构化和可解释。然而,机器学习项目通常应用于野生数据源,因为简单的基于规则的算法无法用于处理它们。例如,日志文件、用户生成的内容、第三方供应商和开放数据。这些公司对数据如何生成、何时可用以及模式会发生什么变化的控制力度较小。
使用外部数据源的风险在于,数据的模式或模式可能会在没有通知或团队意识到的情况下随时间而改变。例如,有人可能破坏开放的数据,内容生成的方法可能改变,或者供应商可能在没有通知下游用户的情况下改变数据的模式。上述原因可能会威胁到 ML 模型的性能,如果忽视太久,会产生严重的问题。
为了有效地监控 ETL 过程,防止关键数据问题影响模型及其性能;数据的完整性、一致性和可用性是选择 ETL 监控度量时需要考虑的三个方面。
完整
有许多原因会危及数据的完整性。其中一些是:
- 数据管道中的错误
- 基础设施中的软件更新
- 数据源的日常维护
- 外部方对数据的破坏
- 数据源中数据模式的变化
通过创建全面的验证规则来捕捉和报告异常,可以监控数据的完整性。验证规则通常在探索性数据分析和模型训练期间制定。例如,可以使用的一些度量是缺失或看不见的特征的数量,或者未通过每个验证规则的数据点的比率。
即使数据科学家会将损坏的数据排除在模型之外,也必须监控数据问题的大小和严重性,以便衡量数据源的可靠性,并开发新的规则来持续验证数据完整性。
一致性
ETL 监控指标的第二个原则是数据的一致性。一致性非常重要,因为数据点可能会通过验证规则,但要素中的值可能会与模型的训练历史有很大不同。影响数据完整性的原因也会影响数据的一致性。但在用户生成数据的情况下,由于用户在平台上互动方式的转变,一致性的变化也可能有机地发生。
不一致的数据会影响 ML 模型的性能,因为它会改变为其训练模型的数据模式。下面的可视化说明了为什么数据的不一致性会破坏 ML 模型的性能。
为了监控一致性,可以导出数据的量、变化率或单个值,以便针对将被监控的指标进行汇总。然后,聚合值成为时间序列中的数据点,其中 X 轴是时间,Y 轴是用于聚合每个批次或时间窗口中的数据的测量值(取决于数据是以批次还是以流的形式出现)。
Time Series Data Example
有许多测量变量可用于表示数据的分布和偏斜度,如方差和百分位数。根据我的经验,我发现均值和标准差是最有效的度量组合。该组合配合使用效果最佳,因为平均值显示的是中心点,而标准偏差显示的是分布范围。下图显示了均值和标准差如何表示不同的分布。
Source: https://www.varsitytutors.com/hotmath/hotmath_help/topics/normal-distribution-of-data
让我们用一个真实的例子来解释一下。我们建立了一个 ML 模型,根据社会经济数据来预测人口的预期寿命。其中一个特征是收入,我们每年批量获取数据。因此,我们将找到人口收入的均值和标准差,并逐年进行比较,以分析收入分布的一致性。如果 2017 年的收入均值或标准差与 2018 年有很大不同,并且该模型是根据 2017 年的数据训练的,则表明模式已经改变,预测可能不如训练和测试时准确。用 2018 年的数据重新调整模型也是一个好主意,我将在未来的帖子中谈到这个话题。
有效性
可以说,数据的可用性是监控管道时要考虑的最重要的方面。当管道从团队无法控制的数据源(如第三方供应商或开放数据)获取数据时,这一点尤其重要。如果没有数据输入,ML 管道就像一条废弃的铁轨,建设管道的投资就会损失。
数据的可用性可能不会影响 ML 模型的精度,但它会影响 ML 管道的整体性能,因为没有数据输入(或延迟输入)就无法实现业务目标。可用于监控数据可用性的 KPI 示例如下:
- 每批数据之间的延迟时间
- 管道中没有数据的总分钟数、小时数或天数
- 数据交付落后于计划的次数
了解上述指标有助于数据科学团队确定需要改进的领域,并在数据不可用时得到通知。如果有多个数据源进入管道,这些指标将帮助团队了解每个数据源的可靠性,以便将问题或顾虑传达给正确的团队。
文章到此结束!我希望您现在知道如何监控数据的完整性、一致性和可用性,以及为什么它们对机器学习管道的性能至关重要。
我将在下一篇文章中继续发布机器学习管道监控的第二部分,也就是分数监控。您可以关注我,获取更多关于性能监控和数据可视化相关主题的文章。谢谢你读到这里,我希望你喜欢这篇文章!
初学者指南:数据类型及其度量尺度
原文:https://towardsdatascience.com/beginners-guide-data-types-and-their-measurement-scale-194033b86b6d?source=collection_archive---------17-----------------------
数据类型简介
数据有一个重要的故事要讲。他们依靠你给他们发言权。
在你给他们发言权之前,你必须理解不同的数据类型。根据数据的收集方式或结构,有不同的方法对数据进行分类。
基于数据收集:根据数据收集的方式,数据可以分为三种类型。
- 横截面数据:在一个特定的时间段内,在多个变量上捕捉到的任何数据点/值称为横截面数据。例如:员工的属性,如年龄、工资、级别、2019 年的团队。
- 时序数据:单个变量在多个周期内捕获的任何数据点/值称为时序数据。例如:每月、每季度、每年的智能手机销量。
- 面板数据:截面数据和时间序列数据的组合称为面板数据。不同时期不同国家的 GDP。
基于结构。对数据进行分类的另一个重要方法是基于数据的结构。它可以分为两种类型。
- 结构化数据:所有具有特定结构并能以表格形式(也称为矩阵)排列成行和列的数据点称为结构化数据。例如:用员工 id 安排的员工的工资。
- 非结构化数据:所有没有排列成任何表格格式的数据点都是非结构化数据。例如:电子邮件、视频、点击流数据等。
70%的可用数据是非结构化数据,在分析或构建任何分析模型时,必须将非结构化数据转换为结构化数据。
数据分析领域的大多数初学者面临的另一个问题是,即使结构化数据可用,如何处理它,如何使用它,如何测量它,以及如何从中推断出见解。
对于所有这些,测量尺度变得很重要。人们必须意识到,如果结构化数据可用,我们如何测量它们,以及如何根据测量来区分它们。
根据测量尺度,数据可以分为四个部分。
- 名义规模:所有定性的数据点都属于这个范畴。这些也被称为分类变量。婚姻状况(单身、已婚等。).不能对这些变量执行任何算术运算(加、减、乘或除)。
- 有序尺度:有序集合中的所有数据点都属于这个范畴。例如:1-5 分等级(5 分最高,1 分最低)。这里集合的顺序是固定的,但是不能执行算术运算,例如我们知道,等级 4 比等级 2 好,但是两个等级 2 不能等于等级 4。
- 区间尺度:从某个固定区间集合中取出的所有数据点。例如:温度(摄氏度),智商水平。在这样的变量中,可以执行加法或减法,但是除法没有意义。你可以说孟买比班加罗尔高 10 摄氏度,但你说孟买比班加罗尔热两倍是不对的,因此这里的比率没有意义。
- :所有本质上是定量的数据点都属于这一类。产品的销售,员工的工资等。在这里,所有的算术运算都可以执行,并且可以进行比较,因为 Ram 的收入是 Shyam 的两倍,因此比率是有意义的。
因此,通过查看数据,可以推断出哪种数据是可用的,如名义数据、序数数据等。这最终有助于数据分析师/科学家构建任何分析模型,以了解不同的变量,进行探索性数据分析,进行数据插补,并执行一次性编码。
它不仅在预测分析中变得重要,而且在描述分析中也很有帮助。如果没有关于数据类型的信息,就无法进行探索性数据分析。一旦你确定了数据的类型,然后进行大量的单变量和双变量分析、可视化和计算,如均值、众数、中位数等。可以从数据中推断洞察力。
多分类任务的 BERT 初学者指南
原文:https://towardsdatascience.com/beginners-guide-to-bert-for-multi-classification-task-92f5445c2d7c?source=collection_archive---------3-----------------------
Original Photo by David Pisnoy on Unsplash. It was later modified to include some inspiring quotes.
本文的目的是提供如何使用 BERT 进行多分类任务的分步指南。BERT(BI directionalEn coderRpresentations fromTtransformers),是 Google 提出的一种新的预训练语言表示方法,旨在解决广泛的自然语言处理任务。该模型基于无监督的深度双向系统,并在 2018 年首次向公众发布时成功实现了最先进的结果。如果你想了解更多,可以在下面的链接中找到学术论文。
本教程有 5 个部分:
- 设置和安装
- 数据集准备
- 培训模式
- 预言;预测;预告
- 结论
[第 1 节]设置和安装
在本教程中,我将使用 Ubuntu 18.04 搭配单个 GeForce RTX 2080 Ti。就我个人而言,我不建议在没有 GPU 的情况下进行训练,因为基础模型太大了,训练时间非常长。
虚拟环境
建议建立一个虚拟环境。如果你是第一次使用 Ubuntu,打开终端,将目录切换到你想要的位置。它将是您环境的根文件夹。运行以下命令安装 pip:
sudo apt-get install python3-pip
然后,运行以下命令安装 virtualenv 模块:
sudo pip3 install virtualenv
您现在可以创建自己的虚拟环境(用您喜欢的任何名称替换 bertenv):
virtualenv bertenv
如果你喜欢不使用 virtualenv 模块,还有一种方法可以创建虚拟环境,只需使用 python3
python3 -m venv bertenv
您应该已经创建了一个 bertenv 文件夹。查看以下链接了解更多信息。您可以使用以下命令激活虚拟环境:
source bertenv/bin/activate
开源代码库
从下面的链接克隆存储库。完成后,解压缩 zip 文件并将其放入您选择的目录中。你应该有一个 bert-master 文件夹。我把它放在虚拟环境文件夹旁边。因此,在根目录中,我有以下子文件夹:
- 贝尔坦夫
- 伯特-马斯特
Python 模块
BERT 只需要 tensorflow 模块。您必须安装等于或高于 1.11.0 的版本。确保您安装了 CPU 版本或 GPU 版本,但不是两者都安装。
tensorflow >= 1.11.0 # CPU Version of TensorFlow. tensorflow-gpu >= 1.11.0 # GPU version of TensorFlow.
你可以通过 pip 或者位于 bert-master 文件夹中的 requirement.txt 文件来安装。
伯特模型
我们将需要一个微调过程的基础模型。我将在本教程中使用 BERT-Base,Cased ( 12 层,768-hidden,12-heads,110M 参数)。如果你想试试 BERT-Large ( 24 层,1024 隐藏,16 头,340M 参数),确保你有足够的内存。12GB 的 GPU 不足以运行 BERT-Large。我个人会推荐你用 64GB 的 GPU 做 BERT-Large。在撰写本文时,BERT 背后的团队还发布了其他模型,如中文、多语言和全词屏蔽。请通过以下链接查看。下载完文件后,解压缩该文件,您应该得到以下文件:
- 三个 ckpt 文件
- vocab.txt
- 伯特配置文件
将它们放在模型文件夹中,并将其移动到 bert-master 文件夹中。请转到下一节数据集准备。
[第 2 节]数据集准备
对于 BERT 来说,数据准备是非常复杂的,因为官方的 github 链接并没有包含太多需要什么样的数据。首先,有 4 个类可用于序列分类任务:
- Xnli(跨语言 nli)
- 多体裁自然语言推理
- 微软研究释义语料库
- 语言可接受性语料库
所有的类都是基于数据处理器类(参见第 177 行的run _ classifier . py文件),该类用于将数据提取到以下内容:
- guid :示例的唯一 id。
- text_a :字符串数据。第一个序列的未标记文本。对于单序列任务,只能指定此序列。
- text_b :(可选)字符串数据。第二个序列的未标记文本。必须为序列对任务指定 Only。
- 标签:字符串数据。示例的标签。这应该为训练和评估示例指定,而不是为测试示例指定。
换句话说,我们可以修改我们的数据集来模拟 4 个类之一的模式和格式,或者编写我们自己的类来扩展 DataProcessor 类以读取我们的数据。在本教程中,我将把数据集转换成可乐格式,因为它是所有格式中最简单的。其他数据集的例子可以在下面的链接(胶水版)中找到。
在 BERT 的原始版本中,run _ classifier . py基于从三个 tsv 文件中读取输入:
- train.tsv(无标题)
- dev.tsv(评估,无标题)
- test.tsv(头是必需的)
对于 train.tsv 和 dev.tsv ,你应该有以下格式(无表头):
a550d 1 a To clarify, I didn't delete these pages.
kcd12 0 a Dear god this site is horrible.
7379b 1 a I think this is not appropriate.
cccfd 2 a The title is fine as it is.
- 列 1 :示例的 guid。它可以是任何唯一的标识符。
- 第 2 列:示例的标签。它是基于字符串的,可以是文本形式,而不仅仅是数字。为了简单起见,我在这里只使用数字。
- 第 3 列:第二个序列的未分词文本。必须为序列对任务指定 Only。因为我们正在进行单序列任务,所以这只是一个一次性的专栏。对于所有的行,我们都用“a”来填充它。
- 第 4 列:第一个序列的未分词文本。用示例的文本填充它。
对于 test.tsv ,你应该有如下格式(需要表头):
guid text
casd4 I am not going to buy this useless stuff.
3ndf9 I wanna be the very best, like no one ever was
将其他来源的数据转换成所需的格式
如果您有不同于上面给出的格式的数据,您可以使用 pandas 模块和 sklearn 模块轻松地转换它。通过 pip 安装模块(确保虚拟环境已激活):
pip install pandas
如果您打算使用 train_test_split,也要安装 sklearn:
pip install sklearn
例如,如果我们有以下 csv 格式的训练数据集:
id,text,label
sadcc,This is not what I want.,1
cj1ne,He seriously have no idea what it is all about,0
123nj,I don't think that we have any right to judge others,2
我们可以使用以下代码轻松加载数据集并将其转换为相应的格式(相应地修改路径):
从 csv 文件创建数据帧
import pandas as pddf_train = pd.read_csv('dataset/train.csv')
从现有数据框架创建新的数据框架
df_bert = pd.DataFrame({'guid': df_train['id'],
'label': df_train['label'],
**'alpha': ['a']*df_train.shape[0]**,
'text': df_train['text']})
粗体突出显示的部分意味着我们将根据 df_train 数据帧中的行数用字符串 a 填充列 alpha。shape[0]指的是行数,而 shape[1]指的是列数。
输出 tsv 文件
df_bert_train.to_csv('dataset/train.tsv', **sep='\t'**, index=False, header=False)
不要对 to_csv 函数调用感到惊讶,因为除了分隔符之外,tsv 和 csv 具有相似的格式。换句话说,我们只需要提供正确的制表符分隔符,它就会变成一个 tsv 文件(以粗体突出显示)。
下面是创建所有必需文件的完整工作代码片段(相应地修改路径)。
import pandas as pd
from sklearn.model_selection import train_test_split#read source data from csv file
df_train = pd.read_csv('dataset/train.csv')
df_test = pd.read_csv('dataset/test.csv')#create a new dataframe for train, dev data
df_bert = pd.DataFrame({'guid': df_train['id'],
'label': df_train['label'],
'alpha': ['a']*df_train.shape[0],
'text': df_train['text']})#split into test, dev
df_bert_train, df_bert_dev = train_test_split(df_bert, test_size=0.01)#create new dataframe for test data
df_bert_test = pd.DataFrame({'guid': df_test['id'],
'text': df_test['text']})#output tsv file, no header for train and dev
df_bert_train.to_csv('dataset/train.tsv', sep='\t', index=False, header=False)
df_bert_dev.to_csv('dataset/dev.tsv', sep='\t', index=False, header=False)
df_bert_test.to_csv('dataset/test.tsv', sep='\t', index=False, header=True)
一旦你有了所有需要的文件,将数据集文件夹移动到 bert-master 文件夹。让我们继续下一部分来微调您的模型。
[第三节]培训模式
微调 BERT 模型最简单的方法是通过命令行(终端)运行 run_classifier.py。在此之前,我们需要根据我们的标签修改 python 文件。最初的版本是使用 0 和 1 作为标签的二进制分类。如果使用不同的标签进行多分类或二分类,需要更改 ColaProcessor 类的 get_labels() 函数(第 354 行,如果使用其他数据处理器类,请相应修改):
原始代码
def get_labels(self):
return ["0", "1"]
5 标签多分类任务
def get_labels(self):
return ["0", "1", "2", "3", "4"]
使用不同标签的二元分类
def get_labels(self):
return ["POSITIVE", "NEGATIVE"]
如果您遇到如下任何键错误,这意味着您的 get_labels 函数与您的数据集不匹配:
label_id = label_map[example.label]
KeyError: '2'`
我们现在已经准备好接受训练了。如果您使用的是 NVIDIA GPU,您可以在终端中键入以下内容来检查状态和 CUDA 版本。
nvidia-smi
更改目录指向 bert-master 文件夹,确保数据集文件夹和 bert-master 文件夹中的所需文件。建议通过命令行运行培训,而不是使用 jupyter notebook,原因如下:
- 官方代码使用 2 个单位缩进,不同于笔记本默认的 4 个单位缩进。
- 内存问题和配置用于训练的 GPU 的额外代码。
因素
在此之前,让我们探索一下可以针对培训流程进行微调的参数:
- data_dir :包含 train.tsv、dev.tsv、test.tsv 的输入目录。
- bert_config_file :预先训练好的 bert 模型对应的 config json 文件。这指定了模型架构。
- 任务名称:训练任务的名称。4 个选项可用(xnli、mrpc、mnli、cola)。
- vocab_file :训练 BERT 模型的词汇文件。
- output_dir :模型检查点将被写入的输出目录。
- init_checkpoint :初始检查点(通常来自预训练的 BERT 模型)。
- do_lower_case :输入的文本是否小写。对于无大小写应为 True,对于有大小写应为 False。
- max_seq_length :分词后最大总输入序列长度。长于此长度的序列将被截断,短于此长度的序列将被填充。默认值为 128。
- do_train :是否在 train.tsv 上运行训练。
- do_eval :是否在 dev.tsv 上运行评估
- do_predict :是否在 test.tsv 上以推理模式运行模型
- train_batch_size :训练的总批量。默认值为 32。
- eval_batch_size :评估的总批量。默认值为 8
- predict_batch_size :测试和预测的总批量。默认值为 8。
- learning _ rate:Adam 的初始学习率。默认为 5e-5。
- num_train_epochs :要执行的训练总次数。默认值为 3.0。
- 热身 _ 比例:从 0 到 1 进行线性学习率热身的训练比例。默认值为 0.1 表示 10%。
- save_checkpoints_steps :保存模型检查点的步数间隔。默认值为 1000。
- iterations_per_loop :每次估算器调用的步数间隔。默认值为 1000。
- 使用 _tpu :是否使用 tpu。
- tpu _ 姓名:云 TPU 用于训练。
- tpu 区:TPU 云所在的 GCE 区。
- gcp_project :启用云 TPU 的项目的项目名称
- 主 : TensorFlow 主 URL。
- 数量 _ TPU _ 核心数:仅当使用 _tpu 为真时使用。要使用的 TPU 核心总数。
不要被参数的数量所淹没,因为我们不会指定每个参数。
培训说明
从官方文档中,它建议通过以下命令行调用将路径导出为变量(如果您使用的是 Windows 操作系统,请将导出替换为设置):
export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12
在本教程中,我将不导出路径,因为您仍然需要在命令行中指定它。只要确保你正确地组织了你的文件夹,你就可以开始了。要指定 GPU,您需要在 python 调用之前键入它(示例如下,不要运行它):
CUDA_VISIBLE_DEVICES=0 python script.py
0 是指 GPU 的顺序。使用以下命令检查它:
nvidia-smi
在 bert-master 文件夹中,创建一个输出文件夹。我就把它叫做 bert_output 。确保在 bert-master 文件夹中有以下文件夹和文件:
- 数据集文件夹(包含 train.tsv,dev.tsv,test.tsv)
- 型号文件夹(包含 ckpt,vocab.txt,bert_config.json)
- bert_output 文件夹(空)
通过命令行培训
确保终端指向 bert-master 目录,并且虚拟环境已激活。根据您的偏好修改参数并运行它。我做了以下更改:
- 将 train_batch_size 减少到 2:如果你有足够的内存,可以随意增加。这影响了训练时间。越高,训练时间越短。
- 将的保存 _ 检查点 _ 步骤增加到 10000。我不想有这么多检查点,因为每个检查点模型都是原始大小的 3 倍。放心,这个脚本一次只保留 5 个模型。旧型号将被自动删除。强烈建议将其保持为 1000(默认值)。
- 将最大序列长度减少到 64。由于我的数据集 99%的长度不超过 64,将其设置得更高是多余的。根据数据集对此进行相应的修改。默认值为 128。(序列长度是指词块标记化后的字符长度,请考虑这一点)。
CUDA_VISIBLE_DEVICES=0 python run_classifier.py --task_name=cola --do_train=true --do_eval=true --data_dir=./dataset --vocab_file=./model/vocab.txt --bert_config_file=./model/bert_config.json --init_checkpoint=./model/bert_model.ckpt --max_seq_length=64 --train_batch_size=2 --learning_rate=2e-5 --num_train_epochs=3.0 --output_dir=./bert_output/ --do_lower_case=False --save_checkpoints_steps 10000
训练应该已经开始,显示跑步步数/秒。检查 bert_output 文件夹,您应该注意到以下内容:
- 三个 ckpt 文件(模型)
- tf _ 记录
- 检查点和事件文件(临时文件,可以在培训后安全地忽略和删除)
- graph.pbtxt
这可能需要几个小时到几天的时间,具体取决于您的数据集和配置。
培训完成
培训完成后,您应该有一个 eval_results.txt 来指示您的模型的性能。
eval_accuracy = 0.96741855
eval_loss = 0.17597112
global_step = 236962
loss = 0.17553209
确定模型的最高步骤数。如果您对此不确定,请在文本编辑器中打开检查点,您应该会看到以下内容:
model_checkpoint_path: "model.ckpt-236962"
all_model_checkpoint_paths: "model.ckpt-198000"
all_model_checkpoint_paths: "model.ckpt-208000"
all_model_checkpoint_paths: "model.ckpt-218000"
all_model_checkpoint_paths: "model.ckpt-228000"
all_model_checkpoint_paths: "model.ckpt-236962"
在这种情况下,最高步骤是 236962。我们现在可以用这个模型来预测结果。
[第四节]预测
为了进行预测,我们将使用相同的 run_classifier.py 。这一次,我们需要将 do_predict 指定为 True,并将 init_checkpoint 设置为我们拥有的最新模型 model.ckpt-236962(根据您拥有的最高步骤进行相应修改)。但是,您需要确保 max_seq_length 与您用于训练的相同。
CUDA_VISIBLE_DEVICES=0 python run_classifier.py --task_name=cola --do_predict=true --data_dir=./dataset --vocab_file=./model/vocab.txt --bert_config_file=./model/bert_config.json --init_checkpoint=./bert_output/model.ckpt-236962 --max_seq_length=64 --output_dir=./bert_output/
一旦流程完成,您应该在 bert_output 文件夹中有一个 test_results.tsv(取决于您为 output_dir 指定的内容)。如果使用文本编辑器打开它,您应该会看到以下输出:
1.4509245e-05 1.2467547e-05 0.99994636
1.4016414e-05 0.99992466 1.5453812e-05
1.1929651e-05 0.99995375 6.324972e-06
3.1922486e-05 0.9999423 5.038059e-06
1.9996814e-05 0.99989235 7.255715e-06
4.146e-05 0.9999349 5.270801e-06
列的数量取决于标签的数量。每一列按照您为 get_labels()函数指定的顺序表示每个标签。该值代表预测的可能性。例如,模型预测第一个示例属于第 3 类,因为它具有最高的概率。
将结果映射到相应的类
如果您想映射结果来计算精确度,可以使用以下代码(相应地修改):
import pandas as pd#read the original test data for the text and id
df_test = pd.read_csv('dataset/test.tsv', sep='\t') #read the results data for the probabilities
df_result = pd.read_csv('bert_output/test_results.tsv', sep='\t', header=None)#create a new dataframe
df_map_result = pd.DataFrame({'guid': df_test['guid'],
'text': df_test['text'],
'label': df_result.idxmax(axis=1)})#view sample rows of the newly created dataframe
df_map_result.sample(10)
idxmax 是一个函数,用于返回请求轴上第一次出现的最大值的索引。不包括 NA/null 值。在这种情况下,我们传递 1 作为轴来表示列而不是行。
[第五节]结论
在本教程中,我们已经学会了针对多分类任务微调 BERT。供您参考,BERT 可以用于其他自然语言处理任务,而不仅仅是分类。就我个人而言,我也测试了基于 BERT 的中文情感分析,结果出乎意料的好。请记住,非拉丁语言(如中文和朝鲜语)是字符标记化,而不是单词标记化。请随意在不同种类的数据集上尝试其他模型。感谢您的阅读,祝您有美好的一天。下篇再见!
伯特相关的故事
- 优化和导出在线服务 BERT 模型的 3 种方法
参考
- 【https://arxiv.org/abs/1810.04805
- https://github.com/google-research/bert
- https://gist . github . com/geo yi/d 9 fab 4 f 609 e 9 f 75941946 be 45000632 b
- https://gluebenchmark.com/tasks
- https://github . com/Google-research/Bert/blob/master/run _ classifier . py
- https://MC . ai/a-guide-to-simple-text-class ification-with-Bert/
- https://appliedmachinehlearning . blog/2019/03/04/stat-of-art-text-classification-using-Bert-model-predict-the-happy-hackere earth-challenge/
在 TensorFlow 中构建神经网络的初学者指南
原文:https://towardsdatascience.com/beginners-guide-to-building-neural-networks-in-tensorflow-dab7a09b941d?source=collection_archive---------12-----------------------
TensorFlow 2.0 初学者笔记本的详细演练
如果你正在阅读这篇文章,你可能已经对神经网络和张量流有所了解,但你可能会对与深度学习相关的各种术语感到有些畏惧,这些术语在许多技术介绍中往往被掩盖或无法解释。本文将通过深入演练 TensorFlow 2.0 的初学者教程来阐明其中的一些主题。
这个指南是基于 TensorFlow 2.0 初学者笔记本的,我推荐看一看它并在 Google Colab 中运行它(它只有 16 行代码!)来最大化你对这里所涵盖的材料的理解。
注意:鉴于这是一个初学者指南,这里表达的大多数观点应该有一个较低的入门门槛,但是对什么是神经网络有一些背景知识将是有帮助的。这篇文章提供了一个很好的概述,以防你想温习一下。
你会学到什么
阅读本文后,您将对一些关键的概念性主题以及这些主题的 TensorFlow/Keras 实现有更好的理解(Keras 是一个基于 TensorFlow 构建的深度学习库)。
概念性:
- 神经网络层形状
- 激活功能(如 Relu 和 Softmax)
- 逻辑
- 拒绝传统社会的人
- 优化者
- 失败
- 纪元
张量流/Keras 函数:
- tf.keras.layers.Sequential()
- tf.keras.layers.Flatten()
- tf.keras.layers.Dense()
- 模型.编译()
- model.fit()
数据
TensorFlow 2.0 初学者教程使用的数据是 MNIST 数据集,它被认为是一种“你好,世界!”用于神经网络和深度学习,并且可以直接从 Keras 下载。它是一个数据集,充满了从 0 到 9 的手绘数字,并有相应的标签来描述绘图应该描绘的数字。
Example observations from MNIST dataset [1]
使用这个数据集背后的想法是,我们希望能够训练一个模型,该模型能够学习哪种形状对应于数字 0-9,并随后能够正确标记它尚未训练过的图像。当将如下图所示的图像传递给模型时,这项任务变得更加复杂。有些人甚至会把这张图误认为是零,尽管它被标为八。
Example an ambiguous image from MNIST (index 3570 of training set)
在高层次上,初学者教程中构建的模型将训练图像作为输入,并尝试将这些图像分类为 0-9 之间的数字。如果它做出了不正确的预测,它将进行数学调整,以更好地预测类似的图像。一旦模型完成训练,它将在没有训练过的图像上进行测试,以获得模型表现如何的最终评估。
Basic structure of the neural net built in the beginner notebook
了解初学者笔记本
现在让我们深入探讨一下 TensorFlow 是如何实现这个基本的神经网络的。
加载数据
在第一个单元格中完成一些设置后,笔记本开始使用其load_data()
函数从 Keras 库中加载 MNIST 数据集,该函数返回两个元组,如代码所示。文档可以在这里找到。
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
当我们探究 TensorFlow 如何处理这些数据时,理解这些数据的实际情况会很有帮助。
>>> x_train.shape
(60000, 28, 28)>>> y_train.shape
(60000,)>>> x_test.shape
(10000, 28, 28)>>> y_test.shape
(10000,)
查看这些结果,我们可以看到数据集中总共有 70k 个图像,60k 个训练和 10k 个测试。两个 28 表示每个图像是 28 像素乘 28 像素,并且图像被表示为填充有像素值的 28×28 阵列,如在下面的可视化中可以看到的。
Depiction of how each image is stored in the MNIST dataset
笔记本电脑准备数据的最后一步是将每个图像中的每个像素值转换为 0.0-1.0 之间的浮点数。这样做是为了帮助在为每幅图像生成预测时所涉及的数学比例。
x_train, x_test = x_train / 255.0, x_test / 255.0
构建模型结构
也许这个笔记本最令人困惑的部分是创建模型结构的部分。
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation='softmax')
])
这个代码的目的是指定什么样的层将出现在我们的神经网络中。第一部分是tf.keras.models.Sequential()
调用。这个函数所做的就是开始创建层的线性(或“顺序”)排列。上述代码片段中的所有其他代码详细说明了模型中的层以及它们的排列方式。
下一行代码tf.keras.layers.Flatten(input_shape=(28,28))
创建了我们网络的第一层。直观地说,我们希望能够使用图像中的所有信息来预测它是什么数字,因此输入层应该为图像中的每个像素提供一个节点。每个图像有 2828 =784 个值,因此Flatten()
创建了一个有 784 个节点的层,包含给定图像的每个像素值。如果我们有每个像素包含 3 个值(RGB 值)的彩色图像,那么Flatten()
将创建一个 2828*3 = 2352 个节点的层。
我们在模型中看到的另一种层是使用tf.keras.layers.Dense()
创建的,它创建了所谓的全连接或密集连接层。这可以与稀疏连接层进行比较,区别在于信息如何在相邻层的节点之间传递。
Comparison between dense and sparse connectivity (image from Amir Alavi’s blog)
您可以看到,在密集连接的层中,一层中的每个节点都连接到下一层中的每个节点,而在稀疏连接的层中,情况并非如此。因此Dense()
所做的是创建一个完全连接到它前面的层的层。第一个参数(第一个实例中为 128)指定层中应该有多少个节点。隐藏层(不是输入或输出层的层)中的节点数量有些随意,但需要注意的一点是,输出层的节点数量等于模型试图预测的类的数量。在这种情况下,模型试图预测 10 个不同的数字,因此模型中的最后一层有 10 个节点。这是至关重要的,因为最终层的每个节点的输出将是给定图像是特定数字的概率。
为了理解这个片段中的其余代码,我们需要理解激活函数和 dropout。
激活功能
尽管神经网络的布局和结构很重要,但最好记住,在一天结束时,神经网络所做的是大量的数学运算。每个节点获取前一层中节点的值,并计算它们的加权和,产生一个称为 logit 的标量值。就像人类大脑中的神经元在受到某些输入的刺激时如何“激发”,我们必须指定网络中的每个节点(有时也称为神经元)在受到某些输入时如何“激发”。这就是激活函数的作用。它们取 logits,即上述加权和的结果,并根据正在使用的功能将它们转换为“激活”。
一个常见的激活函数,也是我们网络中第一个Dense()
层使用的激活函数,称为“ReLU”,是整流线性单元的缩写。
ReLU activation function
ReLU 所做的是激活任何负逻辑 0(节点不触发),同时保持任何正逻辑不变(节点触发的强度与输入的强度成线性比例)。要了解更多关于 ReLU 的能力以及它为什么有用的信息,请查看本文。
另一个常见的激活函数,也是在Dense(),
的第二个实例中使用的函数,称为“softmax”。
Udacity Deep Learning slide on softmax
如上图所示,softmax 采用前一层激活的加权和计算出的逻辑值,并将它们转换为总和为 1.0 的概率。这使得它成为在我们的输出层中使用的一个非常有用的激活函数,因为它为图像是特定数字的可能性提供了易于解释的结果。
有许多其他的激活功能,决定使用哪一个通常是一个实验或启发式判断(或两者兼有)的问题。其他一些激活功能的概述可以在这里找到(如果你不理解为什么激活功能首先是必要的,我推荐你读一读)。
辍学
到目前为止,我们检查的代码片段中最后一个无法解释的部分是对tf.keras.layers.Dropout()
的调用。dropout 的概念可以追溯到之前对层的连通性的讨论,并且与密集连接的层的一些缺点有关。密集连接层的一个缺点是,它可能导致计算非常昂贵的神经网络。随着每个节点向下一层中的每个其他节点发送信息,在每个节点中计算的加权和的复杂度随着每层中节点的数量而指数增加。另一个缺点是,随着如此多的信息从一层传递到另一层,模型可能会过度适应训练数据,最终影响性能。
这就是辍学的原因。Dropout 使得给定层中的一些节点不会将其信息传递给下一层。这有助于计算时间和过度拟合。所以在初学者笔记本中,两个Dense()
层之间的Dropout(0.2)
调用使得第一个Dense()
层中的每个节点有 0.2 的概率从下一层的激活计算中被丢弃。您可能已经意识到,这实际上使模型中的输出层成为了一个稀疏连接的层。
Srivastava, Nitish, et al. ”Dropout: a simple way to prevent neural networks from
overfitting”, JMLR 2014
既然我们已经理解了模型的所有组件,让我们利用model.summary()
函数,对我们的网络结构进行一次健全性检查。
在仔细检查了输出形状之后,一切看起来都很好,所以现在让我们继续编译、训练和运行模型吧!
编译、训练和运行神经网络
现在我们已经指定了我们的神经网络的样子,下一步是告诉 Tensorflow 如何训练它。
编译模型
我们将在本节中检查的代码片段如下:
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
在一个预先构建的模型上调用model.compile()
函数,它指定了损失函数、优化器和度量标准,每一个都将被解释。这些是神经网络如何产生其最终预测的重要特征。
损失函数 在本指南的开头,提到了在一个高层次上,初学者笔记本中建立的模型将学习如何将某些图像分类为数字,它通过进行预测来做到这一点,查看其预测与正确答案的差距,然后更新自身以更好地预测这些类型的数字。损失函数是模型的一部分,用于量化预测与正确答案的差距。不同类型的模型需要不同类型的损失函数。例如,像这样一个问题的损失函数,其中我们的模型的输出是概率,必须与试图预测美元价格的模型的损失函数非常不同。这个特定模型的损失函数是“稀疏分类交叉熵”,这对于像这样的多类分类问题是很好的。在我们的例子中,如果模型预测一个图像只有很小的概率成为它的实际标签,这将导致很高的损失。
优化器
另一种表达训练一个模型实际意义的方式是,它寻求最小化损失。如果损失是预测与正确答案相差多远的度量,并且更高的损失意味着更不正确的预测,则寻求最小化损失是确定模型表现如何的可量化方式。如前所述,训练神经网络的一个关键部分是根据这些参数在图像分类中的有效性来修改网络节点的数学参数。在称为反向传播的过程中,神经网络使用称为梯度下降的数学工具来更新参数以改进模型。这些术语的细节在一定程度上超出了本指南的范围,但是为了理解初学者笔记本正在做什么,函数model.compile()
的优化器参数指定了一种使反向传播过程更快更有效的方法。“adam”优化器是一种常用的优化器,可以很好地解决这个问题。
指标
model.compile()
函数的最后一部分是指定在评估模型时应该使用的指标。准确性是一个有用的,但不完美的度量标准,用于衡量模型性能,它本身应该谨慎使用(关于为什么是这样以及其他一些潜在的度量标准,您可以看看这篇文章)。
训练模型
最后是实际训练模型,使用 TensorFlow 2.0,这很容易做到。
model.fit(x_train, y_train, epochs=5)
这行代码非常直观,传递训练数据和该数据的正确标签。model.fit()
函数中的 epoch 参数是模型看到所有训练数据的次数。我们希望模型多次查看所有定型数据的原因是,在计算加权和以显著提高预测能力时,一次遍历可能不足以让模型充分更新其权重。
Results from training the model with 5 epochs
运行这段代码,您可以看到在每个时期,模型都遍历了训练集中的所有 60k 个图像。您还可以看到,随着每个时期,损失会减少,准确性会提高,这意味着该模型在每个时期对数字进行分类的能力会越来越强。
评估模型
最后,使用model.evaluate(x_test, y_test)
,我们可以预测我们的测试集的类,看看我们的模型表现如何。
该图显示,尽管训练准确度随着我们训练的时期越多而不断上升,但验证准确度开始趋于平稳或下降,这表明我们可能不需要训练超过 5 个时期。
Confusion matrix for our neural net
为了更详细地评估模型的表现,我们可以构建一个混淆矩阵。从这个混淆矩阵中我们可以看出,我们的模型最难处理 9,并且容易将它们与 7、4 或 3 混淆。
结论
恭喜你!您已经完成了 TensorFlow 2.0 初学者笔记本指南,现在对神经网络层、激活函数、逻辑、下降、优化、损失函数和损失以及纪元的形状有了更好的理解。您还熟悉了如何使用 TensorFlow/Keras 实现这些概念!对于更多的实践,我建议尝试本指南中讨论的不同参数,看看它们对模型性能有什么影响。快乐造型!
在 PySpark 中创建端到端机器学习管道的初学者指南
原文:https://towardsdatascience.com/beginners-guide-to-create-first-end-to-end-machine-learning-pipeline-in-pyspark-d3df25a08dfd?source=collection_archive---------12-----------------------
数据科学家在 Spark 中构建第一个端到端机器学习管道的有用资源、概念和经验
Photo by AbsolutVision on Unsplash
当我意识到我的训练集包括每天超过 1000 万行时,我首先想到的是子采样。然而,当我开始二次采样时,我发现在这个过程中很难不产生任何偏差。这时候我想到了用 Spark 建立一个没有二次采样的模型。
我以为 spark 里不会有太多建模选择,Spark 机器学习包也不会像 sklearn 那么强大和用户友好。然而令我惊讶的是,我很容易就在 Spark 中找到了我需要的一切。我在mmlspark(micro fot 开发的 spark 开源包)里找到了我想用的模型 lightgbm 我从 spark MLlib 包中找到了非常详细的特性工程和管道函数。
然而,建立我的第一个端到端培训渠道并不容易。Spark 还没有像 Python 那样广泛用于机器学习,因此它的社区支持有时是有限的,有用的信息非常分散,并且没有好的初学者指南来帮助澄清常见的困惑。因此,在这篇文章中,我将列出一些基本概念,分享我在旅途中学到的经验,并列出一些我认为有用的资源。
基本概念
PySpark vs Python
Python 代码与函数: Python 代码与 Python 对象(列表、字典、pandas 数据类型、numpy 数据类型等)一起工作。)在 PySpark 中是可执行的,但是他们根本不会从 Spark 中受益(即分布式计算)。
Python 代码不能应用于 Spark 对象(RDD、Spark 数据集、Spark 数据帧等)。)虽然直接。如果需要,这样的代码可以变成 UDF(用户定义函数)应用于每一行 Spark 对象(就像pandas
中的map
)。这篇博客很好地解释了 UDF,还有来自这本数据手册的代码示例。
PySpark 代码及功能: PySpark 代码只能应用于 spark 对象。它们在应用于 Python 对象时不起作用。
python 和 PySpark 对象转换: 当 Python 对象足够小以适合驱动程序的内存时,可以将一些(但不是全部)Python 对象(例如熊猫数据帧)转换成 Spark 对象(例如 spark 数据帧),反之亦然。
spark.mllib vs spark.ml
起初让我非常困惑的是,当检查文档时,你会看到 MLlib 被用作机器学习库的名称,但所有的代码示例都是从pyspark.ml
导入的。事实上,spark.mllib 和 spark.ml 都是 spark 的机器学习库:spark.mllib 是与 RDD 一起工作的旧库,而 spark.ml 是围绕 spark 数据框架构建的新 API。根据 spark 的公告,位于 RDD 的 API 从 Spark 2.0.0 开始进入维护模式。这意味着不会有新的特性添加到pyspark.mllib
中,在达到特性对等之后,基于 RDD 的 API 将被弃用;pyspark.mllib
预计将在 Spark 3.0 中移除。简而言之,尽可能使用pyspark.ml
,不要使用pyspark.mllib
。
吸取的经验教训
算法选择
spark 的机器学习库包含了很多业界广泛使用的算法,如广义线性模型、随机森林、梯度提升树等。支持算法的完整列表可以在这里找到。
还有开源库mmspark。它提供了 Spark 机器学习管道与微软认知工具包(CNTK)、LightGBM 和 OpenCV 的无缝集成。不幸的是,PySpark 不支持另一个非常流行的培训框架 xgboost。即使有 XGBoost4J-Spark 在 Spark 上集成了 xgboost frame,但是还没有开发出 Python API。
如前所述,从技术上来说,如果训练数据适合驱动程序内存,可以导入 python xgboost 或 lightgbm 模块,并在 PySpark 中的 pandas 数据帧上应用训练函数。然而,这种方法根本不会从 Spark 中受益(即训练将在单台机器上进行,而不是像没有 Spark 一样分布在多台机器上)。
没有超深的树木
令我惊讶的是,随机森林和梯度增强树的集合模型不能为 max_depth 参数取超过 30 的值。随着 max_depth 的增加,训练时间也呈指数增长。用我的训练集,训练一个 20 深度的随机森林需要 1 个小时,一个 30 深度的需要 8 个小时。在我看来,随机森林的浅树是一个问题,因为当训练数据很大时,深的个体树能够找到不同的“规则”,这种多样性应该有助于性能。
调资源分配
在训练期间为执行者分配足够的内存是很重要的,花时间调优核心数、执行者数和执行者内存也是值得的。我的一次训练运行在 10 分钟内完成,资源分配正确,而我第一次开始调优资源分配时需要 2 个小时。
合奏 特色
大多数(如果不是全部的话)spark 模型都将由两列组成的数据框架(特征和标签)作为输入。特征列是所有串联的特征值的列表。 VecorAssembler 就是做这件事的函数,应该始终作为特征工程的最后一步。这里有一个在建模管道中使用它的例子。
一些有用的资源
搜索函数:文档
当搜索你需要的东西时,谷歌当然是第一选择,但是我发现浏览 Spark 文档寻找功能也很有帮助。重要的是要参考正确的 Spark 版本(上面的链接是版本 2.4.3)。
机器学习管道代码示例:数据块的笔记本文档
Spark MLlib 文档已经有很多代码示例,但是我发现 Databrick 的用于机器学习的笔记本文档甚至更好。这个笔记本走过一个分类训练管道,这个笔记本演示参数调整和 mlflow 进行跟踪。创建这些笔记本是为了解释如何在数据块中使用各种 Spark MLlib 功能,但这些笔记本中展示的许多功能并不是专门针对数据块的。
Spark 整体理解:维基百科和 Spark 介绍页面
Apache Spark 维基百科非常好地总结了重要的 Spark 模块。当我第一次阅读它的时候,我并没有得到太多的东西,但是在对 spark 有了一些了解之后,我逐渐喜欢上了这个页面,因为它提供了对 Apache Spark 非常好的全面介绍。
我也非常喜欢 DataBrick 的 Spark 介绍页面上的“Apache Spark 生态系统”部分。这和维基百科页面上的信息很像。阅读这两本书让我对 Spark 生态系统有了更深入的了解。
Spache Spark Ecosystem
结论
与 python 相比,pyspark 的社区支持较少,尤其是在机器学习任务方面。除了 mmlspark,我也没有找到多少 pyspark 的开源开发。然而,谈到大数据,spark 是一个非常强大的工具:我能够在 Spark 中训练一个 lightgbm 模型,在 10 分钟内有大约 20 万行和大约 100 个特征。当然,运行时在很大程度上取决于模型参数,但是它展示了 Spark 的强大功能。
创建 SVD 推荐系统的初学者指南
原文:https://towardsdatascience.com/beginners-guide-to-creating-an-svd-recommender-system-1fd7326d1f65?source=collection_archive---------5-----------------------
Photo by freestocks on Unsplash
序言
有没有登录网飞,看到他们建议你看重力如果你昨晚看了星际?或者在亚马逊上买了东西,看到他们向我们推荐我们可能感兴趣的产品?或者有没有想过在线广告公司是如何根据我们的浏览习惯向我们展示广告的?这一切都归结于一种叫做推荐系统的东西,它可以根据我们和其他人与产品的互动历史来预测我们可能感兴趣的东西。
正如我所承诺的,我们会做一个推荐系统。为了让你不要自我感觉不好,我们也会做一个很酷的。我们将使用 SVD(奇异向量分解)技术进行协同过滤;这比基本的基于内容的推荐系统高出一个档次。
协同过滤捕捉志同道合的用户的潜在兴趣模式,并使用相似用户的选择和偏好来建议新项目。
要求
所以让我们开始吧。所以我们需要的东西列在下面。如果你正在阅读这篇文章,你很可能知道并且已经拥有了这些。
1.python >= 2.7
2。熊猫> = 0.17
3。numpy
4。scipy
对于不了解的人来说,熊猫、numpy 和 scipy 是 python 包。这些将使我们的生活变得容易。您可以使用 pip 从终端或命令提示符安装它们。如果你不知道怎么做,谷歌一下。例如,下面的命令安装 pandas 包。
$ pip install pandas
资料组
我们肯定需要一个数据集来处理。我们将使用著名的 Movielens 数据集来制作我们的推荐系统。前往 http://grouplens.org/datasets/movielens/下载电影镜头 100k 数据集。
该数据集包含不同用户对不同电影的大约 100,000 个评级。让我们来探索数据集。创建一个新脚本exploration . py并添加以下代码块。注意:这里我们将使用单独的脚本,但是你也可以使用一个单独的 iPython 笔记本,这要方便得多。
import pandas as pd
import numpy as npdata = pd.read_csv('movielens100k.csv')
data['userId'] = data['userId'].astype('str')
data['movieId'] = data['movieId'].astype('str')users = data['userId'].unique() #list of all users
movies = data['movieId'].unique() #list of all moviesprint("Number of users", len(users))
print("Number of movies", len(movies))
print(data.head())
这就对了。您将看到数据集中有 718 个用户和 8915 部电影。
Number of users 718
Number of movies 8915
+----+----------+-----------+----------+-------------+
| | userId | movieId | rating | timestamp |
|----+----------+-----------+----------+-------------|
| 0 | 1 | 1 | 5 | 847117005 |
| 1 | 1 | 2 | 3 | 847642142 |
| 2 | 1 | 10 | 3 | 847641896 |
| 3 | 1 | 32 | 4 | 847642008 |
| 4 | 1 | 34 | 4 | 847641956 |
+----+----------+-----------+----------+-------------+
训练和测试分割
我们可以在数据集上使用正常的随机训练测试分割。但是既然我们有可用的时间戳,让我们做一些更好的事情。让我们创建一个新的脚本 workspace.py 来完成我们所有的工作。在开头添加以下代码。
import pandas as pd
import numpy as np
import scipydata = pd.read_csv('movielens100k.csv')
data['userId'] = data['userId'].astype('str')
data['movieId'] = data['movieId'].astype('str')users = data['userId'].unique() #list of all users
movies = data['movieId'].unique() #list of all moviestest = pd.DataFrame(columns=data.columns)
train = pd.DataFrame(columns=data.columns)test_ratio = 0.2 #fraction of data to be used as test set.for u in users:
temp = data[data['userId'] == u]
n = len(temp)
test_size = int(test_ratio*n)temp = temp.sort_values('timestamp').reset_index()
temp.drop('index', axis=1, inplace=True)
dummy_test = temp.ix[n-1-test_size :]
dummy_train = temp.ix[: n-2-test_size]
test = pd.concat([test, dummy_test])
train = pd.concat([train, dummy_train])
这样做的目的是,根据给出这些评级时的时间戳,我们对数据进行排序,以将最近的评级保持在底部,并从底部开始从每个用户中抽取 20%的评级作为测试集。因此,我们没有随机选择,而是将最近的评分作为测试集。从推荐者的目标是基于类似产品的历史评级来对未来未遇到的产品进行评级的意义上来说,这更合乎逻辑。
效用矩阵
当前形式的数据集对我们没有用。为了将数据用于推荐引擎,我们需要将数据集转换成一种叫做效用矩阵的形式。我们在新的脚本中创建一个函数**create_utility_matrix**
。将其命名为 recsys.py 。我们将使用这个脚本中的函数来处理我们的训练和测试集。
作为一个参数,我们传递一个字典,该字典存储我们也传递的数据集“数据”的每一列的键值对。从数据集中,我们将看到每个对应字段的列号或列名,键'T12 用户'' T14]的列【T6]userId或列 0 ,列 movieId 或键 ' 项'和列
效用矩阵只不过是一个 2D 矩阵,其中一个轴属于用户,另一个轴属于项目(在这种情况下是电影)。所以矩阵的 (i,j) 位置的值将是用户 i 给电影 j 的评分。
让我们举一个例子来更清楚一点。假设我们有 5 个评级的数据集。
*+----+----------+-----------+----------+
| | userId | movieId | rating |
|----+----------+-----------+----------+
| 0 | mark| movie1| 5 |
| 1 | lucy| movie2| 2 |
| 2 | mark| movie3| 3 |
| 3 | shane| movie2| 1 |
| 4 | lisa| movie3| 4 |
+----+----------+-----------+----------+*
如果我们通过下面描述的**create_utility_matrix**
函数传递这个数据集,它将返回一个这样的效用矩阵,以及 user_index 和 item_index 的辅助字典,如下所示。
*+----+----+----+
| 5 | nan| 3 | # user_index = {mark: 0, lucy:1, shane:2, lisa:3}
+----+----+----+ # item_index = {movie1:0, movie2: 1, movie3:2}
| nan| 2 | nan|
+----+----+----+
| nan| 1 | nan| # The nan values are for user-item combinations
+----+----+----+ # where the ratings are unavailable.
| nan| nan| 4 |
+----+----+----+*
现在来看看功能。
*import numpy as np
import pandas as pd
from scipy.linalg import sqrtmdef **create_utility_matrix**(data, formatizer = {'user':0, 'item': 1, 'value': 2}): """
:param data: Array-like, 2D, nx3
:param formatizer:pass the formatizer
:return: utility matrix (n x m), n=users, m=items
"""
itemField = formatizer['item']
userField = formatizer['user']
valueField = formatizer['value'] userList = data.ix[:,userField].tolist()
itemList = data.ix[:,itemField].tolist()
valueList = data.ix[:,valueField].tolist() users = list(set(data.ix[:,userField]))
items = list(set(data.ix[:,itemField])) users_index = {users[i]: i for i in range(len(users))} pd_dict = {item: [np.nan for i in range(len(users))] for item in items} for i in range(0,len(data)):
item = itemList[i]
user = userList[i]
value = valueList[i] pd_dict[item][users_index[user]] = value X = pd.DataFrame(pd_dict)
X.index = users
itemcols = list(X.columns)
items_index = {itemcols[i]: i for i in range(len(itemcols))} # users_index gives us a mapping of user_id to index of user
# items_index provides the same for items return X, users_index, items_index*
奇异值分解计算
SVD 是奇异向量分解。它所做的是将一个矩阵分解成对应于每行和每列的特征向量的组成数组。我们再给 recsys.py 添加一个函数。它将从“ create_utility_matrix 和参数“ k ”获取输出,该参数是每个用户和电影将被分解成的特征的数量。
奇异值分解技术是由 Brandyn Webb 引入推荐系统领域的,在 Netflix 奖挑战赛期间,Brandyn Webb 以 【西蒙·芬克】 而闻名。这里我们不做 Funk 的 SVD 迭代版本,而是使用 numpy 的 SVD 实现所提供的任何东西。
*def **svd**(train, k):
utilMat = np.array(train) # the nan or unavailable entries are masked
mask = np.isnan(utilMat)
masked_arr = np.ma.masked_array(utilMat, mask)
item_means = np.mean(masked_arr, axis=0) # nan entries will replaced by the average rating for each item
utilMat = masked_arr.filled(item_means) x = np.tile(item_means, (utilMat.shape[0],1)) # we remove the per item average from all entries.
# the above mentioned nan entries will be essentially zero now
utilMat = utilMat - x # The magic happens here. U and V are user and item features
U, s, V=np.linalg.svd(utilMat, full_matrices=False)
s=np.diag(s) # we take only the k most significant features
s=s[0:k,0:k]
U=U[:,0:k]
V=V[0:k,:] s_root=sqrtm(s) Usk=np.dot(U,s_root)
skV=np.dot(s_root,V)
UsV = np.dot(Usk, skV) UsV = UsV + x print("svd done")
return UsV*
将它们结合在一起
回到 workspace.py 我们将使用上面的函数。我们将找出使用真实评级的测试集的预测评级的均方根误差。除了创建一个函数,我们还将创建一个列表来保存不同数量的特性,这将有助于我们将来进行分析。
*from recsys import svd, create_utility_matrixdef **rmse**(true, pred):
# this will be used towards the end
x = true - pred
return sum([xi*xi for xi in x])/len(x)# to test the performance over a different number of features
no_of_features = [8,10,12,14,17]utilMat, users_index, items_index = create_utility_matrix(train)for f in no_of_features:
svdout = svd(utilMat, k=f)
pred = [] #to store the predicted ratings for _,row in test.iterrows():
user = row['userId']
item = row['movieId'] u_index = users_index[user]
if item in items_index:
i_index = items_index[item]
pred_rating = svdout[u_index, i_index]
else:
pred_rating = np.mean(svdout[u_index, :])
pred.append(pred_rating)print(rmse(test['rating'], pred))*
对于 test_size = 0.2 ,RMSE 分数大约为 0.96
对于 100k 的电影来说,这是一个适中的分数。稍微调整一下,你也许能超过 0.945。但这取决于你。
如果你喜欢这篇文章,请告诉我!这里有三个链接供你参考:
- (SVD 的完整代码以及其他著名 RecSys 算法的实现)
- https://papers with code . com/sota/collaborative-filtering-on-movie lens-100k(关于 Movielens100k 的最新成果。这些在官方测试集上得到验证)
- https://sifter.org/~simon/journal/20061211.html(西蒙·芬克最著名的博客详述了他的奇异值分解方法)
Jupyter 笔记本初学者指南
原文:https://towardsdatascience.com/beginners-guide-to-jupyter-notebook-8bb85b85085?source=collection_archive---------13-----------------------
数据科学
设置和执行描述性统计
Photo by Evgeni Tcherkasski on Unsplash
**Table of Contents**[**Introduction**](#bdcf)1\. [Installing Anaconda](#f76d)
2\. [Jupyter Notebook help and shortcuts](#3210)
3\. [Python libraries](#6b76)
4\. [Finding data](#f10a)
5\. [Importing data](#a663)
6\. [Data attributes](#6916)
7\. [Missing Value](#8204)
8\. [Dealing with NaN values](#6778)
9\. [How to deal categorical data](#9d1c)
10\. [Descriptive statistics](#985d)
11\. [Basic plotting](#0a81)
12\. [Matplotlib](#e08b)
13\. [Seaborn](#3885)
14\. [What’s next?](#8243)
介绍
欢迎来到这个 Jupyter 笔记本初学者指南!在本教程中,我们将介绍使用 Jupyter Notebook 执行描述性统计的基础知识,重点是帮助刚接触编码的高中(或以上)学生。
Jupyter Notebook 是一个强大的数据科学工具,允许您创建和共享包含实时代码、等式、可视化和叙述性文本的文档。它是一个开源的 web 应用程序,支持 100 多种编程语言,包括在数据科学中广泛使用的流行语言 Python。
Jupyter Notebook 是一个开源的 web 应用程序,允许您创建和共享包含实时代码、公式、可视化和叙述性文本的文档。—来自项目 Jupyter
在本教程中,我们将使用 Python 来演示如何使用 Jupyter Notebook 进行描述性统计。如果您是 Python 新手,请不要担心!我们将提供所有必要的解释和示例来帮助您开始。在本教程结束时,您将对如何使用 Jupyter Notebook 有更好的理解,并在成为一名熟练的数据科学家的道路上前进。
这里可以看到的原图。
我制作了一个 Jupyer 幻灯片,你可以在这里下载。你需要安装 RISE 才能使用这个幻灯片。
我们要用 Python 库, Numpy , Pandas , Matplotlib 和 Seaborn 。Python 库是函数和方法的集合,允许您在不编写代码的情况下执行许多操作。
安装 Anaconda
我们将安装 Anaconda。Anaconda 是 Python 数据科学的标准平台。Anaconda 将为我们安装所有必需的包。
从https://www.anaconda.com/distribution/,下载 3.7 版本并安装。
安装 Anaconda 之后,启动 Anaconda-Navigator。
新闻发布 Jupyter 笔记本。它将启动一个终端并打开一个浏览器。
要创建文件夹,请单击右上角的“新建”按钮。然后单击文件夹。
您需要将文件夹重命名为 Statistics。
创建一个名为 Data 的文件夹,我们将把所有数据存储在这个文件夹中。
在 Data 文件夹中,创建一个名为 mydata1.csv 的文本文件。
在浏览器中打开http://bit.ly/2M1yrW7。Command(或 windows 中的 ctrl)+A 选择全部,Command + C 复制。Command + V 将其粘贴到 mydata1.csv,Command + S 保存该文件。
在 Statistics 文件夹中,创建名为 Test by New > Python 3 的文件。
这就是全部的设置。让我们开始写一些代码。
[## Jupyter 用户的生产力提示
使用 Jupyter 笔记本和 JupyterLab 让您的工作流程更加高效
towardsdatascience.com](/stepping-into-intermediate-with-jupyter-f6647aeb1184)
Jupyter 笔记本帮助和快捷方式
按下h
切换键盘快捷键屏幕。你可以通过按⌘⇧f.看到所有的命令。我经常使用下面的快捷键,如果你能记住它们会很有用。
Python 库
Numpy 和 Pandas 是科学计算、数据科学和机器学习中使用最多的两个库。熊猫建在 Numpy 的上面。两者都提供相似的功能。Numpy 为多维数组提供了对象,Pandas 提供了内存中的 2D 表对象 DataFrame。
Python 提供了各种用于绘制数据的包。Seaborn 和 Matplotlib 是 Python 最强大的两个可视化库。
使用import ... as ...
导入一个库。我们使用%matplotlib inline
来内联显示图形。请在我们的测试文件中写入/复制以下内容。
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
键入以上内容后,按 SHIFT + RETURN。这将运行您编写的代码。如果你写对了,什么都不会发生。但是如果你拼错了,它会返回一个错误。请阅读错误的最后一行并解决问题。
查找数据
你可以在网上找到很多资源。这是数据源的集合。CSV 文件是逗号分隔值文件,是最容易处理的文件。大多数数据源都提供了一个 CSV 文件。从列表中找出几个你感兴趣的数据。把它们下载到你的硬盘上。
导入数据
我们将读取 CSV 文件并将数据存储在一个名为 df 的变量中。请在下一个单元格中写下以下内容。
df = pd.read_csv('data/mydata1.csv')
请不要忘记按 SHIFT + RETURN。
数据属性
我们将使用shape
、info()
、head()
、tail()
、describe()
来查看我们的数据概览。
我们使用shape
来打印我们数据的尺寸。info()
打印数据的简明摘要。按 SHIFT + RETURN 运行程序。
df.shape
它打印出(569,33)。
df.info()
head()
默认打印前 5 行数据。如果想返回前 10 行,使用head(10)
。
df.head()
tail()
默认打印最后 5 行数据。可以使用任意数字作为tail(10)
。
df.tail()
对于统计概览,describe()
打印平均值、标准差、最小值等。
df.describe()
漏测值
首先,我们导入样本数据。、不适用、不适用和无数据。我们使用“isnull()”检查数据帧是否有任何空值。 any()
如果有任何空值,则按列输出。
请注意,NaN 将替换没有数据的数据项。
比较前两个表,?和 na 不被识别为空。因此,我们需要使用“na_values”来将它们识别为空值。这就要换 NAN 了。
[## 手把手的 Jupyter 笔记本黑客
您应该使用的技巧、提示和快捷方式
towardsdatascience.com](/hands-on-jupyter-notebook-hacks-f59f313df12b)
处理 NaN 值
丢弃 NaN 值
处理空值的一种方法是删除行或列。dropna()
的默认值为axis=0
。所以dropna()
和dropna(axis=0)
输出同一个表。这将删除所有包含空值的行。
` axis=1 '将删除列中有 NaN 的列。
填充 NaN
我们可以用列平均值来填充 NaN 值。下面在每一列中填入 NaN 及其列平均值。
你可以用中间值来填充。
或者任何你认为合适的值。
如何处理分类数据
我们的数据在 col3 下面有一只猫、一只狗和一只狐狸。我们使用“get_dummies()”将分类变量转换为虚拟/指示变量。这将创建包含所有类别的列,并添加 0 或 1。
我们把这些假人和我们的数据连接起来。
我们不再需要 col3,所以我们放弃它。
[## 使用 Jupyter 笔记本进行版本控制
Jupytext 循序渐进指南
towardsdatascience.com](/version-control-with-jupyter-notebook-b9630bc5996e)
描述统计学
除非指定列,mean
,max
,min
等。返回所有列的结果。这里我们将只打印all_mean
。
df=pd.read_csv('[http://bit.ly/2vmLyvU'](http://bit.ly/2vmLyvU'))
all_mean = df.mean()
all_max = df.max()
all_min = df.min()
all_median = df.median()
all_std = df.std()
all_25_quantile = df.quantile(0.25)
print('The means of all data.')
print(all_mean)
作为练习,可以打印all_median
、all_max
吗?
让我们关注数据中的radius_mean
。我们设置了一个名为target
的变量。
df=pd.read_csv('[http://bit.ly/2vmLyvU'](http://bit.ly/2vmLyvU'))
target = 'radius_mean'
我们找到radius_mean
的最大值、最小值和范围。
max = df[target].max()
min = df[target].min()
range = max - min
print('The max is %.1f, the min is %.1f and the range is %.1f' % (max, min, range))
print 命令在括号内打印输出。三个%.1
打印一个小数位,将替换为最大、最小和范围。你可以在这篇文章中找到更多细节。
让我们找出平均值、中间值和众数。
mean = df[target].mean()
median = df[target].median()
mode = df[target].mode()
print('The mean is %.1f, the median is %.1f and the mode is %.1f.' % (mean, median, mode))
quartile
的默认值为 0.5,与中值或 50%平铺相同。您可以指定百分位数,quantile(0.25)
。
q1 = df[target].quantile(0.25)
q3 = df[target].quantile(0.75)
iqr = q3-q1
print('The lower quartile is %.1f, the upper quartile is %.1f and the interquartile range is %.1f' % (q1, q3, iqr))
基本绘图
熊猫的plot()
默认画线图。可以用条形图、历史图、方框图、饼图等设置kind
参数。
df[target].plot()
上图是radius_mean
的线图。
通过将kind='hist'
加到plot()
上,可以绘制直方图。
df[target].plot(kind='hist')
通过在plot
后添加hist()
也可以打印直方图。
df[target].plot.hist()
您可以添加bins=100
以使用 100 个直方图仓。
df[target].plot.hist(bins=100)
plot(kind='box')
或plot.box()
显示了一个盒须图。
df[target].plot(kind='box')
Matplotlib
Matplotlib 有很大的灵活性。在这里,您可以更改异常值的颜色和符号,并一起显示三个方框图。
data =[df['radius_mean'],df['texture_mean'],df['texture_worst']]
green_diamond = dict(markerfacecolor='g', marker='D')fig7, ax7 = plt.subplots()
ax7.set_title('Multiple Samples with Different sizes')
ax7.boxplot(data,flierprops=green_diamond)plt.show()
Matplotlib 的直方图有很大的灵活性。您可以添加不同的参数。
plt.hist([df['radius_mean'],
df['texture_mean']],
histtype='barstacked',
orientation='horizontal',bins=20)
plt.show()
海生的
Seaborn 构建在 Matplotlib 之上,并引入了额外的绘图类型。这也让你的传统 Matplotlib 图看起来更漂亮。(来自 Quora )
sns.boxplot(x='diagnosis', y='perimeter_mean', data=df)
通过 成为 会员,获得媒体上所有故事的访问权限。
https://blog.codewithshin.com/subscribe
下一步是什么?
[## 用 Jupyter 笔记本写作的 7 个基本技巧
第一篇数据科学文章指南
towardsdatascience.com](/7-essential-tips-for-writing-with-jupyter-notebook-60972a1a8901) [## 建模功能
从线性回归到逻辑回归
towardsdatascience.com](/modeling-functions-78704936477a)
参考
[## Jupyter 的教与学
这本手册是为任何教育工作者教学的主题,包括数据分析或计算,以支持…
jupyter4edu.github.io](https://jupyter4edu.github.io/jupyter-edu-book/) [## Boxplot 演示- Matplotlib 3.1.1 文档
示例 boxplot 代码伪造了更多的数据,使得二维数组只有在所有列长度相同的情况下才有效。如果…
matplotlib.org](https://matplotlib.org/3.1.1/gallery/pyplots/boxplot_demo_pyplot.html#sphx-glr-gallery-pyplots-boxplot-demo-pyplot-py) [## Jupyter 的技巧和窍门
Jupyter 技巧和提示的集合
medium.com](https://medium.com/series/jupyter-hacks-and-tips-1b1a3a10bc79)
R 中 K-最近邻初学者指南:从零到英雄
原文:https://towardsdatascience.com/beginners-guide-to-k-nearest-neighbors-in-r-from-zero-to-hero-d92cd4074bdb?source=collection_archive---------2-----------------------
机器学习:监督学习
在 R 中建立具有各种性能指标的 KNN 模型的管道
Photo by Mathyas Kurmann on Unsplash
2021 年 1 月 10 日更新
KNN in audio
"如果你住的地方离比尔·盖茨只有 5 分钟的路程,我敢打赌你一定很有钱."
介绍
在机器学习领域,K 近邻 KNN 最直观,因此很容易被希望进入该领域的数据科学爱好者所接受。为了决定观察的分类标签,KNN 会查看其邻居并将邻居的标签分配给感兴趣的观察。这是 KNN 方法的基本思想,就像一开始用的比尔游戏的比喻一样。不需要更高维度的计算来理解算法是如何工作的。
但是有一个问题。查看一个邻居可能会给模型带来偏差和不准确性,我们必须为该方法设置几个“参与规则”。例如,顾名思义,KNN 可以采用其“k”个邻居的多数情况。
A quick look at how KNN works, by Agor153
为了决定新观察的标签,我们查看最近的邻居。
测量距离
为了选择邻居的数量,我们需要采用一个数字来量化邻居之间的相似性或不相似性(数据科学家实用统计)。为此,KNN 根据数据类型有两套距离度量标准。
对于离散变量,KNN 采用海明距离。它测量使两个字符串相似所需的最少替换数( Wikipedia )。
对于连续变量,我们使用欧几里德距离。为了计算两个向量 (x1,x2,…,xp) 和 (μ1,μ2,…,μp) 之间的距离,我们取它们的个体差,平方,求和,然后平方根,如下所示:
screenshot of Practical Statistics for Data Scientists
顺便提一下,在数据科学访谈中,为 KNN 选择距离指标是一个备受考验的话题。他们通常会询问选择一个指标的理由,以及他们的权衡。我在一篇相关的文章中阐述了如何处理这类问题:
[## 破解数据科学访谈:基本的机器学习概念
赢在 2021 年:数据科学家/工程师的必读之作,第 1 部分
towardsdatascience.com](/crack-data-science-interviews-essential-machine-learning-concepts-afd6a0a6d1aa)
什么是 K 倍交叉验证?
如上所述,KNN 的关键是设置邻居的数量,我们求助于交叉验证(CV)来决定额外的 K 个邻居。
交叉验证可以简要描述为以下步骤:
- 将数据分成 K 个均匀分布的块/折叠
- 选择 1 个组块/折叠作为测试集,其余 K-1 个作为训练集
- 基于训练集开发 KNN 模型
- 仅比较测试集上的预测值和实际值
- 将 ML 模型应用于测试集,并使用每个组块重复 K 次
- 将模型的指标分数相加,并在 K 倍上求平均值
怎么选 K?
从技术上讲,我们可以将 K 设置为 1 和样本大小 n 之间的任何值。设置 K = n,CV 将 1 个观察值作为训练集,其余 n-1 个案例作为测试集,并对整个数据集重复该过程。这种简历被称为“留一法交叉验证”(LOOCV) 。
然而,LOOCV 有直观的意义,但需要大量的计算能力。对于非常大的数据集,它会永远运行。
为了选择最佳的 K 倍,我们必须在偏差和方差之间进行权衡。对于一个小的 K,该模型有一个高偏差,但估计测试误差的方差低。对于一个大 K,我们有一个低偏差但高方差(破解数据科学访谈)。
Photo by Jon Tyson on Unsplash
R 中的代码实现
1.软件准备
*# install.packages(“ISLR”)
# install.packages(“ggplot2”) # install.packages(“plyr”)
# install.packages(“dplyr”) # install.packages(“class”)**# Load libraries* **library**(ISLR)
**library**(ggplot2)
**library**(reshape2)
**library**(plyr)
**library**(dplyr)
**library**(class)# load data and clean the dataset
banking=read.csv(“bank-additional-full.csv”,sep =”;”,header=T)##check for missing data and make sure no missing data
banking[!complete.cases(banking),]#re-code qualitative (factor) variables into numeric
banking$job= recode(banking$job, “‘admin.’=1;’blue-collar’=2;’entrepreneur’=3;’housemaid’=4;’management’=5;’retired’=6;’self-employed’=7;’services’=8;’student’=9;’technician’=10;’unemployed’=11;’unknown’=12”)#recode variable again
banking$marital = recode(banking$marital, “‘divorced’=1;’married’=2;’single’=3;’unknown’=4”)banking$education = recode(banking$education, “‘basic.4y’=1;’basic.6y’=2;’basic.9y’=3;’high.school’=4;’illiterate’=5;’professional.course’=6;’university.degree’=7;’unknown’=8”)banking$default = recode(banking$default, “‘no’=1;’yes’=2;’unknown’=3”)banking$housing = recode(banking$housing, “‘no’=1;’yes’=2;’unknown’=3”)banking$loan = recode(banking$loan, “‘no’=1;’yes’=2;’unknown’=3”)banking$contact = recode(banking$loan, “‘cellular’=1;’telephone’=2;”)banking$month = recode(banking$month, “‘mar’=1;’apr’=2;’may’=3;’jun’=4;’jul’=5;’aug’=6;’sep’=7;’oct’=8;’nov’=9;’dec’=10”)banking$day_of_week = recode(banking$day_of_week, “‘mon’=1;’tue’=2;’wed’=3;’thu’=4;’fri’=5;”)banking$poutcome = recode(banking$poutcome, “‘failure’=1;’nonexistent’=2;’success’=3;”)#remove variable “pdays”, b/c it has no variation
banking$pdays=NULL #remove variable “duration”, b/c itis collinear with the DV
banking$duration=NULL
加载和清理原始数据集后,通常的做法是直观地检查变量的分布,检查季节性、模式、异常值等。
#EDA of the DV
plot(banking$y,main="Plot 1: Distribution of Dependent Variable")
可以看出,结果变量(银行服务订阅)并不是均衡分布的,“否”比“是”多得多,这给机器学习分类问题带来不便。假阳性率很高,因为许多少数病例会被归类为多数病例。对于这种分布不均匀的罕见事件,非参数分类方法是首选方法。
[## 使用 5 种机器学习算法对罕见事件进行分类
哪一种最适合不平衡数据?有什么权衡吗?
towardsdatascience.com](/classifying-rare-events-using-five-machine-learning-techniques-fab464573233)
2。数据分割
我们将数据集分为训练集和测试集。根据经验,我们坚持“80–20”划分,即 80%的数据作为训练集,20%作为测试集。
#split the dataset into training and test sets randomly, but we need to set seed so as to generate the same value each time we run the codeset.seed(1)**#create an index to split the data: 80% training and 20% test** index = round(nrow(banking)*0.2,digits=0)#sample randomly throughout the dataset and keep the total number equal to the value of index
test.indices = sample(1:nrow(banking), index)#80% training set
banking.train=banking[-test.indices,] #20% test set
banking.test=banking[test.indices,] #Select the training set except the DV
YTrain = banking.train$y
XTrain = banking.train %>% select(-y)# Select the test set except the DV
YTest = banking.test$y
XTest = banking.test %>% select(-y)
3.火车模型
让我们创建一个新函数(" calc_error_rate ")来记录错误分类率。当使用训练模型预测的标签与实际结果标签不匹配时,该函数计算比率。它衡量分类的准确性。
#define an error rate function and apply it to obtain test/training errorscalc_error_rate <- function(predicted.value, true.value){
return(mean(true.value!=predicted.value))
}
然后,我们需要另一个函数“ do.chunk() ”,来做 k 重交叉验证。该函数返回可能折叠值的数据框。
该步骤的主要目的是为 KNN 选择最佳 K 值。
nfold = 10
set.seed(1)# cut() divides the range into several intervals
folds = seq.int(nrow(banking.train)) %>%
cut(breaks = nfold, labels=FALSE) %>%
sampledo.chunk <- function(chunkid, folddef, Xdat, Ydat, k){
train = (folddef!=chunkid)# training indexXtr = Xdat[train,] # training set by the indexYtr = Ydat[train] # true label in training setXvl = Xdat[!train,] # test setYvl = Ydat[!train] # true label in test setpredYtr = knn(train = Xtr, test = Xtr, cl = Ytr, k = k) # predict training labelspredYvl = knn(train = Xtr, test = Xvl, cl = Ytr, k = k) # predict test labelsdata.frame(fold =chunkid, # k folds
train.error = calc_error_rate(predYtr, Ytr),#training error per fold
val.error = calc_error_rate(predYvl, Yvl)) # test error per fold
}# set error.folds to save validation errors
error.folds=NULL# create a sequence of data with an interval of 10
kvec = c(1, seq(10, 50, length.out=5))set.seed(1)for (j in kvec){
tmp = ldply(1:nfold, do.chunk, # apply do.function to each fold
folddef=folds, Xdat=XTrain, Ydat=YTrain, k=j) # required arguments
tmp$neighbors = j # track each value of neighbors
error.folds = rbind(error.folds, tmp) # combine the results
}**#melt() in the package reshape2 melts wide-format data into long-format data** errors = melt(error.folds, id.vars=c(“fold”,”neighbors”), value.name= “error”)
接下来的步骤是找到最小化验证误差的 k 的数量
val.error.means = errors %>%
#select all rows of validation errors
filter(variable== “val.error” ) %>%
#group the selected data by neighbors
group_by(neighbors, variable) %>%
#cacluate CV error for each k
summarise_each(funs(mean), error) %>%
#remove existing grouping
ungroup() %>%
filter(error==min(error))*# Best number of neighbors*
*# if there is a tie, pick larger number of neighbors for simpler model*
numneighbor = max(val.error.means$neighbors)
numneighbor## [20]
因此,在使用 10 重交叉验证后,最佳邻居数为 20。
4.一些模型指标
#training error
set.seed(20)
pred.YTtrain = knn(train=XTrain, test=XTrain, cl=YTrain, k=20)knn_traing_error <- calc_error_rate(predicted.value=pred.YTtrain, true.value=YTrain)
knn_traing_error[1] 0.101214
训练误差为 0.10。
#test error
set.seed(20)
pred.YTest = knn(train=XTrain, test=XTest, cl=YTrain, k=20)knn_test_error <- calc_error_rate(predicted.value=pred.YTest, true.value=YTest)
knn_test_error[1] 0.1100995
测试误差为 0.11。
#confusion matrixconf.matrix = **table**(predicted=pred.YTest, true=YTest)
根据上面的混淆矩阵,我们可以计算出下面的数值,为绘制 ROC 曲线做准备。
准确度= (TP +TN)/(TP+FP+FN+TN)
TPR/召回/灵敏度 = TP/(TP+FN)
精度 = TP/(TP+FP)
特异性 = TN/(TN+FP)
FPR = 1 —特异性= FP/(TN+FP)
F1 得分 = 2TP/(2TP+FP+FN) =精度*召回/(精度+召回)
# Test accuracy ratesum(diag(conf.matrix)/sum(conf.matrix))[1] 0.8899005*# Test error rate*1 - sum(drag(conf.matrix)/sum(conf.matrix))[1] 0.1100995
正如您可能注意到的,测试准确率+测试错误率= 1,我提供了计算每个值的多种方法。
# ROC and AUC
knn_model = knn(train=XTrain, test=XTrain, cl=YTrain, k=20,prob=TRUE)prob <- attr(knn_model, “prob”)prob <- 2*ifelse(knn_model == “-1”, prob,1-prob) — 1pred_knn <- prediction(prob, YTrain)performance_knn <- performance(pred_knn, “tpr”, “fpr”)# AUCauc_knn <- performance(pred_knn,”auc”)[@y](http://twitter.com/y).valuesauc_knn[1] 0.8470583plot(performance_knn,col=2,lwd=2,main=”ROC Curves for KNN”)
总之,我们已经了解了什么是 KNN,以及在 r 中构建 KNN 模型的流程。此外,我们还掌握了进行 K-Fold 交叉验证的技巧,以及如何在 r 中实现代码
我的Github上有完整的 Python 代码。
Medium 最近进化出了它的 作家伙伴计划 ,支持像我这样的普通作家。如果你还不是订户,通过下面的链接注册,我会收到一部分会员费。
[## 阅读叶雷华博士研究员(以及其他成千上万的媒体作家)的每一个故事
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
leihua-ye.medium.com](https://leihua-ye.medium.com/membership)
我的数据科学面试序列
[## 2021 年数据科学家必备的 SQL 技能
数据科学家/工程师的四项 SQL 技能
towardsdatascience.com](/essential-sql-skills-for-data-scientists-in-2021-8eb14a38b97f) [## FAANG 在 2021 年提出这 5 个 Python 问题
数据科学家和数据工程师的必读!
towardsdatascience.com](/5-python-coding-questions-asked-at-faang-59e6cf5ba2a0) [## FAANG 在 2021 年询问这些 Python 模拟
数据科学和数据工程面试的必读材料,第 2 部分
towardsdatascience.com](/statistical-simulation-in-python-part-2-91f71f474f77)
喜欢读这本书吗?
请在 LinkedIn 和 Youtube 上找到我。
还有,看看我其他关于人工智能和机器学习的帖子。
用 R 进行 LDA 主题建模的初学者指南
原文:https://towardsdatascience.com/beginners-guide-to-lda-topic-modelling-with-r-e57a5a8e7a25?source=collection_archive---------0-----------------------
识别非结构化文本中的主题
Picture credits
现在许多人想从自然语言处理(NLP)开始。然而,他们不知道从哪里以及如何开始。这可能是因为有太多的“指南”或“读物”可用,但它们并没有确切地告诉你从哪里以及如何开始。这篇文章旨在给读者一步一步的指导,告诉他们如何使用 r 的潜在狄利克雷分配(LDA) 分析进行主题建模。
这种技术很简单,在小数据集上很有效。因此,我建议第一次尝试 NLP 和使用主题建模的人使用这种技术。
什么是主题建模?通俗地说,主题建模是试图在不同的文档中找到相似的主题,并试图将不同的单词组合在一起,这样每个主题将由具有相似含义的单词组成。我经常喜欢打一个比方——当你有一本故事书被撕成不同的书页时。在你尝试运行一个主题建模算法之后,你应该能够提出各种各样的主题,这样每个主题将由来自每个章节的单词组成。否则,你可以简单地使用情绪分析——正面或负面评论。
在机器学习和自然语言处理中,主题模型是一种统计模型,用于发现文档集合中出现的抽象“主题”。——维基百科
在正式介绍了主题建模之后,文章的剩余部分将描述如何进行主题建模的逐步过程。它由 4 个部分组成:数据加载、数据预处理、建立模型和主题中单词的可视化。
如上所述,我将使用 LDA 模型,这是一个概率模型,它为 word 分配一个最有可能属于它的主题的概率分数。我将跳过 LDA 的技术解释,因为有许多可用的文章。(例:这里这里)不用担心,我会解释所有的术语,如果我使用它的话。
- 数据加载
为了简单起见,我们将使用的数据集将是来自 kaggle 的前 5000 行 twitter 情绪数据。对于我们的模型,我们不需要标记数据。我们所需要的只是一个我们想要从中创建主题的文本列和一组唯一的 id。最初有 18 列和 13000 行数据,但是我们将只使用 text 和 id 列。
data <- fread(“~/Sentiment.csv”)
#looking at top 5000 rows
data <- data %>% select(text,id) %>% head(5000)
Dataframe after selecting the relevant columns for analysis
2。预处理
正如我们从文本中观察到的,有许多 tweets 由不相关的信息组成:如 RT、twitter 句柄、标点符号、停用词(and、or the 等)和数字。这些会给我们的数据集增加不必要的噪声,我们需要在预处理阶段去除这些噪声。
data$text <- sub("RT.*:", "", data$text)
data$text <- sub("@.* ", "", data$text)text_cleaning_tokens <- data %>%
tidytext::unnest_tokens(word, text)
text_cleaning_tokens$word <- gsub('[[:digit:]]+', '', text_cleaning_tokens$word)
text_cleaning_tokens$word <- gsub('[[:punct:]]+', '', text_cleaning_tokens$word)
text_cleaning_tokens <- text_cleaning_tokens %>% filter(!(nchar(word) == 1))%>%
anti_join(stop_words)
tokens <- text_cleaning_tokens %>% filter(!(word==""))
tokens <- tokens %>% mutate(ind = row_number())
tokens <- tokens %>% group_by(id) %>% mutate(ind = row_number()) %>%
tidyr::spread(key = ind, value = word)
tokens [is.na(tokens)] <- ""
tokens <- tidyr::unite(tokens, text,-id,sep =" " )
tokens$text <- trimws(tokens$text)
3。模型构建
有趣的部分终于来了!创建模型。
首先,您必须创建一个 DTM(文档术语矩阵),这是一个稀疏矩阵,包含您的术语和文档作为维度。构建 DTM 时,您可以选择如何对文本进行分词(将一个句子拆分成一个或两个单词)。这将取决于你希望 LDA 如何解读你的话。你需要问问自己,在你的上下文中,单数词或双数词(短语)是否有意义。例如,如果你的文本包含许多单词,如“执行失败”或“不赞赏”,那么你将不得不让算法选择一个最多 2 个单词的窗口。否则,使用单字也可以。在我们的例子中,因为它是 Twitter 情感,我们将使用 1-2 个单词的窗口大小,并让算法为我们决定哪些是更重要的短语连接在一起。我们还将探索术语频率矩阵,它显示了单词/短语在整个文本语料库中出现的次数。如果该项小于 2 次,我们丢弃它们,因为它不会给算法增加任何值,并且它也将有助于减少计算时间。
#create DTM
dtm <- CreateDtm(tokens$text,
doc_names = tokens$ID,
ngram_window = c(1, 2))#explore the basic frequency
tf <- TermDocFreq(dtm = dtm)
original_tf <- tf %>% select(term, term_freq,doc_freq)
rownames(original_tf) <- 1:nrow(original_tf)# Eliminate words appearing less than 2 times or in more than half of the
# documents
vocabulary <- tf$term[ tf$term_freq > 1 & tf$doc_freq < nrow(dtm) / 2 ]dtm = dtm
使用 DTM,您可以运行 LDA 算法进行主题建模。你将不得不手动分配多个主题 k。接下来,算法将计算一个连贯性分数,以允许我们从 1 到 k 中选择最佳主题。什么是连贯性和连贯性分数?连贯性给出了每个主题的概率连贯性。连贯得分是计算同一主题中的单词放在一起时是否有意义的得分。这给了我们正在制作的主题的质量。特定数字 k 的分数越高,就意味着每个主题的相关词越多,主题就越有意义。例如:{狗,说话,电视,书}对{狗,球,吠,骨头}。后者将产生比前者更高的一致性分数,因为单词更紧密相关。
在我们的例子中,我们设置 k = 20 并对其运行 LDA,并绘制一致性分数。由分析师决定他们想要多少主题。
k_list <- seq(1, 20, by = 1)
model_dir <- paste0("models_", digest::digest(vocabulary, algo = "sha1"))
if (!dir.exists(model_dir)) dir.create(model_dir)model_list <- TmParallelApply(X = k_list, FUN = function(k){
filename = file.path(model_dir, paste0(k, "_topics.rda"))
if (!file.exists(filename)) {
m <- FitLdaModel(dtm = dtm, k = k, iterations = 500)
m$k <- k
m$coherence <- CalcProbCoherence(phi = m$phi, dtm = dtm, M = 5)
save(m, file = filename)
} else {
load(filename)
}
m
}, export=c("dtm", "model_dir")) # export only needed for Windows machines#model tuning
#choosing the best model
coherence_mat <- data.frame(k = sapply(model_list, function(x) nrow(x$phi)),
coherence = sapply(model_list, function(x) mean(x$coherence)),
stringsAsFactors = FALSE)
ggplot(coherence_mat, aes(x = k, y = coherence)) +
geom_point() +
geom_line(group = 1)+
ggtitle("Best Topic by Coherence Score") + theme_minimal() +
scale_x_continuous(breaks = seq(1,20,1)) + ylab("Coherence")
在绘制 k 时,我们意识到 k = 12 给出了最高的一致性分数。在这种情况下,即使一致性分数相当低,也肯定需要调整模型,例如增加 k 以实现更好的结果或具有更多文本。但是出于解释的目的,我们将忽略该值,只使用最高的一致性分数。在了解了主题的最佳数量后,我们想看一下主题中的不同单词。每个主题将为每个单词/短语分配一个 phi 值(pr(word|topic)) —给定主题的单词的概率。所以我们只考虑每个主题中每个单词的前 20 个值。前 20 个术语将描述主题的内容。
model <- model_list[which.max(coherence_mat$coherence)][[ 1 ]]
model$top_terms <- GetTopTerms(phi = model$phi, M = 20)
top20_wide <- as.data.frame(model$top_terms)
Preview of top 10 words for the first 5 topic. The first word implies a higher phi value
上图是 12 个题目中的前 5 个题目。单词按 phi 值的升序排列。排名越高,这个词就越有可能属于这个主题。似乎有一些重叠的话题。这取决于分析师来思考我们是否应该通过目测将不同的主题组合在一起,或者我们可以运行一个树形图来查看哪些主题应该被分组在一起。树形图使用 Hellinger 距离(两个概率向量之间的距离)来决定主题是否密切相关。例如,下面的树形图表明主题 10 和 11 之间有更大的相似性。
model$topic_linguistic_dist <- CalcHellingerDist(model$phi)
model$hclust <- hclust(as.dist(model$topic_linguistic_dist), "ward.D")
model$hclust$labels <- paste(model$hclust$labels, model$labels[ , 1])
plot(model$hclust)
4。可视化
我们可以创建单词云,根据概率来查看属于某个主题的单词。下面代表主题 2。由于“gopdebate”是 topic2 中最有可能出现的单词,因此其大小将是单词云中最大的。
#visualising topics of words based on the max value of phi
set.seed(1234)final_summary_words <- data.frame(top_terms = t(model$top_terms))
final_summary_words$topic <- rownames(final_summary_words)
rownames(final_summary_words) <- 1:nrow(final_summary_words)
final_summary_words <- final_summary_words %>% melt(id.vars = c("topic"))
final_summary_words <- final_summary_words %>% rename(word = value) %>% select(-variable)
final_summary_words <- left_join(final_summary_words,allterms)
final_summary_words <- final_summary_words %>% group_by(topic,word) %>%
arrange(desc(value))
final_summary_words <- final_summary_words %>% group_by(topic, word) %>% filter(row_number() == 1) %>%
ungroup() %>% tidyr::separate(topic, into =c("t","topic")) %>% select(-t)
word_topic_freq <- left_join(final_summary_words, original_tf, by = c("word" = "term"))pdf("cluster.pdf")
for(i in 1:length(unique(final_summary_words$topic)))
{ wordcloud(words = subset(final_summary_words ,topic == i)$word, freq = subset(final_summary_words ,topic == i)$value, min.freq = 1,
max.words=200, random.order=FALSE, rot.per=0.35,
colors=brewer.pal(8, "Dark2"))}dev.off()
Word cloud for topic 2
5。结论
我们用 LDA 完成了这个简单的主题建模,并用 word cloud 实现了可视化。你可以参考我的 github 了解整个脚本和更多细节。这不是一个完整的 LDA 教程,因为还有其他很酷的度量标准,但是我希望这篇文章能为你提供一个很好的指导,告诉你如何使用 LDA 开始 R 中的主题建模。我也强烈建议每个人也阅读其他种类的算法。我相信你不会觉得无聊的!
如果你认为我错过了什么,请随时给我留言。
快乐话题造型!
参考文献:
- 维基百科
- 泰勒娃娃, LDA 主题造型 (2018)
- 托马斯·琼斯,主题建模 (2019)
Python 及其怪癖初学者指南
原文:https://towardsdatascience.com/beginners-guide-to-python-quirks-and-jargon-8dfcf8ebd590?source=collection_archive---------19-----------------------
数据科学的繁荣欢迎了来自各行各业的大量新 Python 开发人员:从经验丰富的黑客、统计学家和数学家,到企业高管、记者,以及基本上任何想成为不可避免的数据革命一部分的人。各位,我们正处于激动人心的时代。我们正处于第四次工业革命的风口浪尖,每个人都想加入。
对于初学编程的人来说,Python 是数据科学的两种著名编程语言之一,这非常方便。凭借其简洁的语法、易读性以及对自然语言的接近,难怪美国大学中 70%的编程入门课程都在讲授 i t。我想不出比这更温和的编程入门了。
你可以选择所有的在线课程,所有的博客文章和教程遍布网络,学习语言的资源是不短缺的。此外,感谢像 stackoverflow 这样的网站,如果你有任何问题,总会有一个其他程序员的社区来帮助你(大多数时候,我们大多数人都很好)。
获取知识从未如此简单,我想邀请你们所有人和我一起欣赏这一刻。
但是,虽然这些课程和教程可以让您快速掌握该语言和相关数据科学库的基础知识——仅举几个例子,pandas、numpy、matplotlib 和 sk learn——但大多数课程和教程几乎没有触及 Python 的复杂性。尽管 Python 很简单,但它是一门庞大而丰富的语言,了解它的内部和外部是值得的。
为什么它很重要
你可能只需要了解基础知识和足够的语言知识,就能在你的领域中发挥作用,但是了解你正在使用的语言的特点也有好处:
- 你可以写出更好、更有创意的代码。编程的核心是解决问题。掌握更多的语言知识可以让你考虑一个问题的多种解决方案。
- 你有可能加快工作速度。对于小型数据集,您可能不会遇到性能问题。当您开始处理至少几千行时,事情会变得更加冒险和不可原谅。知道哪种语言结构比其他语言结构工作得更快,可以将一个必须运行 34 小时的脚本转换成一个只需要运行 1 分钟的脚本(我很快会写这方面的内容!).
- 你未来的自己会感谢你。有没有做过六个月都没碰过的代码?没有吗?让我现在就告诉你:这不是一次愉快的经历。您不再是六个月前的问题领域专家。编写干净和一致的代码,即python 化的代码,将引导你养成按照某种风格模式编写的习惯,从而产生可读和可预测的代码。这肯定会节省你拉头发的时间。
- 最后,为自己的工作感到骄傲。好吧,这是我个人的想法,但我还是想分享一下。时间是非常宝贵的资源。如果你打算用它来创造一些东西,不妨创造一些让你自豪的东西。对我来说,在这种情况下,就是将我编写的代码与语言的设计方式结合起来。虽然编程通常被包装为逻辑问题解决,但在设计层面,它更像是艺术而非工程。这是你的创造力可以大放异彩的地方。
你应该知道的事情
学习这些简单的概念,你将很容易成为一名更好的 Python 开发人员:
空序列为假,有元素的序列为真。在条件句中使用时,不必知道列表、字典或集合的长度:
Sequence Truthiness
使用 enumerate()遍历序列。冒着听起来像个老人的风险,过去遍历一个列表和它的索引需要一组len()
和range()
。enumerate()
让事情变得更简单:
len() and range() vs. enumerate()
你可以从字符串中创建列表。假设您想要创建一个由字母表示的类别列表,将它们制作成一个string
并将其传递给list
构造函数比手工制作更容易:
Strings as Lists
元组打包,序列解包。当你发现自己需要将多个项目组合在一起或从序列中提取单个项目时,可以使用这些工具。这些分别被称为元组打包和序列解包。
Tuple Packing and Sequence Unpacking
通过利用打包和解包,可以在两个变量之间交换值:
Swapping Values
小心使用这个。虽然它增加了x
和y
之间的语义关系,但它也可能在两个非常不相关的变量之间提供错误的语义关系。
F 弦。从 Python 3.6 开始,您可以使用 f 字符串轻松地在字符串中加入任意表达式。对于旧版本 Python 的用户,有一个简单的解决方案:升级!如果这不是一个选项,您可以使用string.format()
方法:
F-strings
f 字符串计算括号内的表达式,并自动将它们包含在字符串中。format 方法用传递给它的参数依次替换字符串中的花括号。如你所见,f 弦更加简洁。
args,kwargs。* *args
和**kwargs
允许函数接受任意数量的位置和关键字参数。当您事先不知道函数将要接收的参数数量时,这可能会很有用。在函数内部,*args
可以作为列表访问,**kwargs
可以作为字典访问:
*args and **kwargs
虽然在你的日常编程中找不到,但是当你在野外遇到它们时,这些知识是有用的。
列表理解。列表和理解允许你从现有的列表和字典中创建新的列表和字典。它们提供了简洁的语法,优于 for 循环。例子将有助于说明这一点。
假设您想要将列表中的所有值加倍:
Doubling Values in List Using Comprehension
或者可能在列表中找到奇怪的值:
Odds in a List using Comprehensions
列表理解提供了以下好处:
- 可读性增强
- 较少的代码行
- 潜在的性能提升(追加到数组会在运行时调整其大小,这会带来性能开销)
我可以保证你已经是一个更好的 Python 开发者了。
好吧,就这么定了。虽然我还想谈论更多的事情,但我想尽可能保持这篇文章的简洁,同时为读者提供直接相关的信息。毕竟我们都很忙。
实践这些,将它们整合到你的日常代码中,并进行实验。我向你保证,你的 Python 技能将会提高,你将能够编写出令你自豪的代码。
进一步阅读
关于 Python,还有很多东西需要学习,包括我提到的和我没有提到的。如果你想探索更多,我推荐以下这些文章:
- 更深入的讲解列表理解。这里有大量清晰实用的例子。
- 生成器,生成器函数,迭代器。生成器通过使用惰性评估来帮助改善内存处理和性能。
- 官方 Python 教程。虽然有点枯燥,但我推荐任何认真的 Python 程序员阅读一下。它提供了理解语言的基本信息。
Python 爱好者、艺术大师和老手们,你们能给那些刚刚加入这个行列的人提供一些技巧吗?下面评论下来!
关于阿德里安·佩雷亚
兼职数据科学家,兼职科技作家,全职书呆子。我在教授机器学习和可管理的、 字节 大小的程序中找到了乐趣。是的,我也很搞笑。咖啡上瘾者。数据可视化的吸盘。愿意为下一个最好的树状图付出我的 1 和 0。
关注我上Twitter和LinkedIn。
使用 SnowNLP 进行简体中文情感分析的初学者指南
原文:https://towardsdatascience.com/beginners-guide-to-sentiment-analysis-for-simplified-chinese-using-snownlp-ce88a8407efb?source=collection_archive---------5-----------------------
Image made by a colleague from Yoozoo Games
通过阅读本文,您将接触到一种分析任何简体中文文本情感的技术。本教程将基于简体中文,但它也可以用于繁体中文,因为 SnowNLP 能够将繁体中文转换为简体中文。
本教程将分为 4 个部分:
- 设置和安装
- 用法和 API 调用
- 培训模式
- 结论
[第 1 节]设置和安装
在本教程中,我将通过 pip 在 Windows 操作系统上安装所需的模块。让我们从一个名为 SnowNLP 的开源模块获取文件,它是一个简体中文文本处理模块。虽然这个模块已经很久没有更新了,但是对于大多数用例来说,结果已经足够好了。
开源代码库
进入下面的链接,下载需要的文件。完成后,将压缩文件解压缩到您喜欢的目录中。你应该有一个 snownlp-master 文件夹,里面包含所有必要的文件。
计算机编程语言
SnowNLP 支持 Python 3,如官方 Github 链接中所述。在本教程中,我将在虚拟环境中使用 Python 3.7.1。
SnowNLP 模块
您可以通过以下命令轻松安装该模块:
pip install snownlp
一旦完成,您将能够看到指示版本号的输出。如果您错过了它,可以通过下面的命令检查它:
pip list
本教程我使用的是 0.12.3 版本。完成后,继续下一部分。
[第 2 节]用法和 API 调用
让我们更深入地研究一下可用于预处理输入文本的基本 API 调用。
初始化
您必须导入它并通过 SnowNLP 类进行初始化,如下所示:
用输入文本作为参数初始化它。建议以一个 u 作为前缀,表明这是一个 Unicode 字符串。这种语法从 Python 2.0 开始使用,但后来在 3.0 到 3.2 版本中被删除。从 3.3 开始, u 前缀是 Unicode 字符串的有效语法。
单词(标记化)
汉语是一种独特的语言,从某种意义上说,不像世界上的大多数语言,单词之间没有空格。这使得很难确定一个句子中的单词数,因为一个单词可以是一个或多个汉字的组合。因此,当执行任何自然语言处理时,您需要将整个文本块分割成单词,这个过程被称为标记化。您可以很容易地使用以下命令来进行令牌化:
您应该得到以下结果作为输出:
['我', '喜欢', '看', '电影', '。']
词性标注
很多时候,我们会对词性标签更感兴趣,词性标签是指与句子中相邻和相关的词之间的关系。如果你理解这个有困难,可以把它想象成用一个标签来标识一个单词是名词、副词、动词、形容词还是其他。使用以下代码获取每个单词的标签:
函数 tags 返回一个 zip 对象,可以使用 list 函数对其进行解压缩。您应该会得到以下结果:
[('我', 'r'), ('喜欢', 'v'), ('看', 'v'), ('电影', 'n'), ('。', 'w')]
每个单词将与各自的标签配对。请参考下面的列表以了解更多关于某些标签的含义(这不是一个完整的列表,因为我在官方网站上找不到任何关于它的文档):
- r :指代词,在句子中代替名词的词。
- v :指动词,一个用来描述动作、状态或事件的词。
- n :指名词,一个用来标识一类人、一类地方或一类事物的词。
- w :指标点符号,书写时用来分隔句子及其成分并阐明意思的符号
拼音
还有一个函数可以得到每个字的拼音。但是,声调不包括在拼音中。获取拼音的示例如下:
您应该得到以下输出:
['wo', 'xi', 'huan', 'kan', 'dian', 'ying', '。']
繁体中文到简体中文
正如我前面提到的,这个模块是为简体中文设计的。如果您想处理繁体中文,请使用以下代码将文本转换为简体中文:
您应该得到以下输出"
'这家伙是坏人。'
分成句子
到目前为止,输入文本只包含一个句子。如果你使用一个段落作为输入,你应该在运行任何 API 调用之前把它分成句子块。为此,请键入以下命令:
检查是否得到以下输出:
['在茂密的大森林里',
'一只饥饿的老虎逮住了一只狐狸',
'老虎张开大嘴就要把狐狸吃掉',
'“慢着”',
'狐狸虽然很害怕但还是装出一副很神气的样子说',
'“你知道我是谁吗',
'我可是玉皇大帝派来管理百兽的兽王',
'你要是吃了我',
'玉皇大帝是决不会放过你的”']
关键词
还有一个从句子中识别关键词的选项。您可以传递一个整数参数,指示要从输入中获取的关键字的数量。我亲自测试了它,提取 5 个关键词,它对新闻文章和短篇故事非常有效。键入以下命令:
提取的关键词如下:
['狐狸', '大', '老虎', '大帝', '皇']
摘要
如果关键词不是你要找的,你可以试着用摘要从中提取梗概(重要句子)。该模块将把文本分成句子,并提取它认为是最重要的句子。与关键字类似,它接受一个整数作为参数来确定摘要的数量。如果你的文本中的句子少于输入,它将输出整个文本作为摘要。使用以下命令:
您应该得到以下输出:
['老虎张开大嘴就要把狐狸吃掉',
'我可是玉皇大帝派来管理百兽的兽王',
'玉皇大帝是决不会放过你的”',
'一只饥饿的老虎逮住了一只狐狸',
'你要是吃了我']
情感分析
本教程的重点是情感分析。然而,大多数时候,你需要做文本预处理,以减少输入文本的准确性。因此,您可以使用上面提到的其他 API 调用。让我们用一些示例文本来测试它:
检查是否得到以下结果(注释不是输出的一部分,它们是为了更容易查看而添加的):
0.7853504415636449 #这个产品很好用
0.5098208142944668 #这个产品不好用
0.13082804652201174 #这个产品是垃圾
0.5 #这个也太贵了吧
0.0954842128485538 #超级垃圾
0.04125325276132508 #是个垃圾中的垃圾
值输出范围从 0 到 1,其中 0 表示负面情绪,而 1 表示正面情绪。正如你所看到的,结果并不坏,考虑到大多数结果都是正确的,除了 0.5 这个应该是负面情绪的值。请注意,情绪是根据购买产品时的评论培养出来的。如果你在其他领域测试它,结果会非常糟糕。您可以查看以下文件,了解有关所用培训数据的更多信息:
- snownlp-master/snownlp/情操/neg.txt
- snownlp-master/snownlp/情操/pos.txt
You will notice that the word 贵 appeared about 600+ times in both neg.txt and pos.txt. This is the reason why the module output a neutral 0.5 value for the sentiment. In contrast, the word 垃圾 appeared 200+ times in neg.txt and only 35 times in pos.txt. To solve this issue, we can train our own model using custom text dataset. It will be explained in the next section.
[第三节]培训模式
正在准备数据集
通过在两个文本文件夹中收集积极和消极的例句来准备你自己的数据集。我在 snownlp-master 文件夹中创建了它们,并将它们命名为 custom_pos.txt 和 custom_neg.txt 。每个例句用换行符隔开如下:
今天明明是周六,我就不想工作,
你看他,好意思吗?一直在偷懒
...
训练您的模型
准备好数据集后,让运行以下代码(相应地更改名称):
您应该会在 snownlp-master 文件夹中获得一个名为custom _ invision . marshal . 3的输出文件。不要对文件末尾的 .3 扩展名感到惊讶。要使用输出模型,您可以执行以下操作之一:
- 修改 snownlp-master/snownlp/impression/_ _ init _ _ . py 中的代码,将数据路径改为新输出的 marshal.3 文件的目录。
- 转到snownlp-master/snownlp/sensation文件夹。创建一个名为 backup 的新文件夹,将perspective . marshal和perspective . marshal . 3放入备份文件夹。从 snownlp-master 文件夹中复制custom _ sensition . marshal . 3放入snownlp-master/snownlp/sensition文件夹。改名为情操.元帅. 3 。
就个人而言,我更喜欢第二种方法,因为修改代码有时会有风险。请注意,您只需要 .3 文件。您可以通过重新初始化 SnowNLP 模块并运行以下代码来测试结果(用类似于您的训练数据的内容替换文本):
根据您的训练数据,输出结果会有一些差异。
分段和标签培训
除了情感,你还可以训练分段和标签。参考以下代码进行分段训练:
我们将对标签使用以下代码:
[第四节]结论
本文演示了一种简单有效的方法,使用名为 SnowNLP 的 Python 模块对简体中文进行情感分析。在撰写本文时,官方文档在解释某些功能方面仍然缺乏质量。请随意阅读代码并探索它,以便更好地理解开发人员使用的技术。自然语言处理还有很多其他的模块,每一个都有自己的优缺点。请根据您的用例对它们进行评估,并在您的项目中使用它们。谢谢,祝你有美好的一天!
参考
- https://github.com/isnowfy/snownlp
语音分析入门指南
原文:https://towardsdatascience.com/beginners-guide-to-speech-analysis-4690ca7a7c05?source=collection_archive---------5-----------------------
Speech signal from Pixabay
本文介绍了语音信号及其分析。此外,我还与文本分析进行了比较,看它与演讲有何不同。
作为交流媒介的语音与文本的对比
语音被定义为通过发音来表达思想和感情。言语是人类最自然、最直观、最喜欢的交流方式。言语的感知可变性以各种语言、方言、口音的形式存在,而言语的词汇也日益增长。在语音信号级别,更复杂的可变性以变化的振幅、持续时间、音调、音色和说话者可变性的形式存在。
文本作为一种通信手段,已经发展到可以远距离存储和传递信息。它是任何言语交流的书面表达。这是一种更简单的交流方式,没有前面提到的言语中复杂多变的现象。
语音中错综复杂的变化使得分析变得更加复杂,但是使用音调和振幅变化提供了额外的信息。
语音和文本的表示
语音和文本分析在当今世界有着广泛的应用。他们有不同的表现,在他们的分析中遇到许多不同和挑战。
让我们看一个取自 CMU 美国 RMS 北极 语音数据库的一个话语的语音信号。每个话语以 16 kHz 的采样频率被记录为 16 位信号,这意味着信号的每秒有 16000 个样本,每个样本的分辨率为 16 位。音频信号的采样频率决定了音频样本的分辨率,采样率越高,信号的分辨率越高。语音信号从语音数据库中的‘arctic _ a 0005 . wav’文件中读取,该文件持续时间约为 1.4 秒,相当于 22640 个样本的序列,每个样本为 16 位数。下面的语音表示是来自‘arctic _ a 0005 . wav’的语音信号的图,其等效文本是“我们会不会忘记它”:
Speech signal, s[n] for the utterance “will we ever forget it”
从上图可以看出,语音可以表示为振幅随时间的变化。振幅被归一化,使得最大值为 1 。语音基本上是一系列发音单位,如“w”、“ih”,称为音素。语音信号可以被分割成一系列音素和无声/非语音段。
该数据库还包含每个波形文件在句子和音素级别的语音信号的相应文本转录。下面是上述语音信号的一部分的表示,示出了音素及其相应的时间跨度。
Phoneme level segments of the signal for ‘will’ as ‘w’, ‘ih’ and ‘l’
从上图可以看出,音素‘w’、‘ih’和‘l’本质上是准周期性的,并且由于它们是由声带的周期性振动产生的,因此被归类为浊音音素。此外,“ih”是元音,而“w”和“l”是半元音。浊音和清音类别是基于声带振动的语音的宽泛分类。对不同音位的研究和分类被称为语音学。
Phoneme level segments of the signal for ‘forget’ as ‘f, ‘er’, ‘g’, ‘eh’ and ‘t’
在上图中,我们有像‘f’、‘g’和‘t’这样的清音音素和像‘er’和‘eh’这样的浊音音素。音位‘g’和‘t’被进一步分类为停顿,即沉默之后是突然的脉冲。可以观察到,浊音分量是准周期性的,而清音分量是有噪声的,因为它们不是由声带的周期性振动产生的。
可以使用音素到字形的映射将音素映射到语音的书面形式。下面是文本和相应音素之间的映射:
正文:“我们会忘记吗”
音序:' w ',' ih ',' l ',' w ',' iy ',' eh ',' v ',' er ',' f ',' er ',' g ',' eh ',' t ',' ih ',' t '
从上面的映射可以看出,单词“will”映射到了音素 ' w ',‘ih ',‘l '。
此外,我们将研究语音的帧级频域表示,在语音研究领域也称为短时傅立叶变换(STFT) 。声谱图是声音频域表示的直观表示。
Log scaled spectrogram of the speech signal using a window size of 30 ms and hop size of 7.5 ms
上面绘制的对数标度谱图是 STFT 在对数标度中的振幅。选择 30 ms 的帧大小,这相当于 30 ms×16k Hz = 480 个语音信号样本,而 7.5 ms 的帧移位相当于 120 个样本。将语音信号分成小持续时间的帧的原因是语音信号是非平稳的,并且其时间特性变化非常快。因此,通过采用小的帧尺寸,我们假设语音信号将是稳定的,并且其特征在帧内不会变化太多。此外,选择较短的帧偏移来跟踪语音信号的连续性,并且不会遗漏帧边缘的任何突变。从上图可以看出,每帧的频域表示有助于我们更好地分析语音信号;因为我们可以很容易地看到谐波在浊音区域中是平行的红色段,以及幅度如何针对每个频率和帧索引而变化。因此,语音信号的大部分分析是在频域中完成的。但是时间信息的提取,如信号中的突然变化(突发的开始,如“t”)在时域中被更好地捕获,因为将语音信号分成帧丢弃了信号中的瞬时变化。
我们可以说,通过采用较小的帧尺寸,我们可以在频域中获得更好的时间分辨率。但是在时域和频域的分辨率之间有一个折衷。采用非常小的帧尺寸将在时间上给出更高的分辨率,但是在单个帧中将给出很少的样本,并且相应的傅立叶分量将具有很少的频率分量。并且由于更大数量的样本,采用更大的帧尺寸将给出更低的时间分辨率但是更高的频率分辨率。因此,同时获得时间和频率的高分辨率是不可能的。
可以观察到,对于 16 kHz 的采样频率,对数频谱图中的 y 轴具有高达 8 kHz 的频率。这是因为,根据奈奎斯特-香农采样定理,在离散信号中可以观察到的最大频率最多是采样频率(8 kHz)的一半。
虽然言语有很多可变性,取决于环境、说话者、说话者的情绪和语气,但文本没有所有这些可变性。
等效的文本被表示为字母、符号和空格的序列,如“我们会不会忘记它”。
语音分析的应用
语音活动检测:识别音频波形中仅存在语音的片段,忽略非语音和无声片段
语音增强:通过过滤和分离语音片段中的噪声来提高语音信号的质量
语音识别:将语音信号转换成文本仍然是一个挑战。在不同的条件下,识别可以是词汇相关的,也可以是独立的
文本到语音:从文本中合成自然语音,使语音听起来非常自然并带有情感是一项挑战
说话人二元化和说话人识别:二元化是将语音信号分割成属于不同说话人的片段,而说话人识别是识别在特定时间谁在说话
音频源分离:分离混合语音信号,如与来自不同说话者的语音或噪声重叠的语音
语音修改:修改语音,如改变其情感、音调,转换成不同说话者所说的语音
情感语音分类:识别语音的情感,如高兴、愤怒、悲伤和焦虑
关键词识别:识别整个语音话语中的特定关键词
文本分析的应用:
文本分类:将整个文本文档分类成各种类别,或者将单词序列分类成不同的类别
命名实体识别:识别人、组织、地名、某些缩写和其他实体
文本摘要:从文档生成摘要
文档聚类:基于相似内容识别相似文本文档
情感分析:从文本中识别情绪、情感、情感和观点
语音和噪声分析的挑战:
所有上述语音和噪声分析的应用都很难解决。使语音和噪声分析进一步复杂化的外部因素是伴随语音和文本产生的各种噪声。探索各种信号处理、基于神经科学的方法、有监督和无监督的机器学习技术来解决同样的问题。由于语音信号的非结构化性质,基于深度学习的方法已经在各种应用中显示出成功。
语音和文本中的噪音:
噪声是任何使原始信号失真的无用信号。向语音添加噪声和向文本添加噪声是非常不同的。
给定幅度为s【n】的语音信号,其中 n 为样本索引,噪声为干扰语音的任何其他信号w【n】。噪声语音信号 u[n] 可以被看作:
u[n]=s[n] + w[n]
在上述情况下,噪声本质上是加性的,这是最简单的情况。噪声也可能以卷积形式出现,例如混响、幅度削波和语音信号的其他非线性失真。
factory1 noise, w[n] from NOISEX92 database
Log scaled spectrogram of the factory1 noise using a window size of 30 ms and hop size of 7.5 ms
上图是取自 NOISEX92 数据库的时域和频域的因子 1 噪声。上述噪声样本被重新采样到与语音样本相同的采样速率,16 kHz,因为我们将语音添加到噪声中,两者应该具有相同的采样速率。
Noisy speech, u[n] at an SNR of 0dB
Log scaled spectrogram of noisy speech using a window size of 30 ms and hop size of 7.5 ms
上面的图是在时域和频域中的噪声语音。语音信号中的噪声会改变整个信号,并且很难分析和提取语音片段。存在各种语音增强算法来减少噪声分量并提高语音的可懂度。
对于给定的文本句子,噪声可能以拼写错误和遗漏单词的形式出现,这可能会改变句子的意思或创建一个无意义的句子。例如:
‘我们会忘记它吗’
嘈杂的文字句子:《我们永远不会忘记它》
在上面的嘈杂文本中,noise 以单词' ever' 的形式出现,改为 'never ',,从而改变了句子的意思。
另一种形式的嘈杂文字:‘我们永远不会忘记它吗’
在上面有噪声的文本中,噪声以单词' forget' 变为 'forggt ',的形式出现,由于单词 'forggt' 拼写错误,使得句子没有意义。
因此,可以看出,在语音中添加噪声会使整个信号失真,而在文本中,失真是离散的,就像丢失一个字符/单词或拼写错误。
言语分析的例证
我们现在将说明一种重要的语音分析技术。任何音频信号的记录通常包含许多无声区域,我们可能只对存在语音的片段感兴趣。这对于从包含长静默区域的信号中自动提取语音片段是有用的,因为静默区域不传达任何信息。这些语音片段可以被进一步分析用于各种应用,如语音识别、说话者和情感分类。
因此,在大多数语音应用中,静音检测是一个重要的预处理步骤。
给定语音信号s【n】,可以通过比较短持续时间内的片段的相对能量来检测无声区域。我们取 20 ms 的帧大小,并将短期能量信号 e[n] 计算为 s[m] 的平方和,其中 m 在 n 的+/-10 ms(在样本中)内。根据我们想要检测的语音信号能量的时间变化量来选择帧大小。短帧大小能够检测能量的突然变化,但是由于某些音素中固有的无声部分,如突发和单词之间的无声部分,可能给出许多交替的无声段帧。
Short term energy, e[n]of speech signal
从上面的图中可以看出,语音信号的短期能量突然变化,并且可以使用相对阈值来检测静默区域。
Silence detection in speech signal
上图显示了通过使用语音信号的平均短期能量的 0.01%的阈值以红色突出显示的静默区域。基于对语音信号中短期能量变化的观察来选择阈值。
无声检测中的一个挑战是在语音信号有噪声的情况下,语音的无声区域中的相对能量也会很高。在噪声主要具有高频分量的情况下,这可以通过观察低通滤波语音信号的短期能量的变化来解决。
本文中所做的模拟演示可以在Github和nb viewer找到。
希望这篇文章和演示对你有用。在接下来的文章中,我将尝试添加更多关于语音信号分析的见解。
关于作者
我是 Belong.co的一名数据科学家,在印度班加罗尔的印度科学研究所完成了博士学位。
三种机器学习的初学者指南
原文:https://towardsdatascience.com/beginners-guide-to-the-three-types-of-machine-learning-3141730ef45d?source=collection_archive---------5-----------------------
Visualising KMeans performance with Yellowbrick
python 中的分类、回归和无监督学习
机器学习问题一般可以分为三种。分类和回归,被称为监督学习,以及无监督学习,在机器学习应用的环境中通常指聚类。
在接下来的文章中,我将简要介绍这三个问题中的每一个,并将包括流行的 python 库 scikit-learn 中的一个演练。
在开始之前,我将简要解释一下监督学习和非监督学习这两个术语背后的含义。
监督学习: 在监督学习中,你有一组已知的输入(特征)和一组已知的输出(标签)。传统上,它们被称为 X 和 y。该算法的目标是学习将输入映射到输出的映射函数。以便当给定 X 的新例子时,机器可以正确地预测相应的 y 标签。
无监督学习: 在无监督学习中,你只有一组输入(X),没有对应的标签(y)。该算法的目标是在数据中找到以前未知的模式。这些算法经常被用来寻找 X 的相似样本的有意义的聚类,因此实际上找到了数据固有的类别。
分类
在分类中,输出(y)是类别。这些可以是二进制的,例如,如果我们对垃圾邮件和非垃圾邮件进行分类。它们也可以是多个类别,如对花的种类进行分类,这就是所谓的多类分类。
让我们使用 scikit-learn 完成一个简单的分类示例。如果您尚未安装,可以通过 pip 或 conda 安装,如这里的所述。
Scikit-learn 有许多可以通过图书馆直接访问的数据集。为了方便起见,在本文中,我将通篇使用这些示例数据集。为了说明分类,我将使用葡萄酒数据集,这是一个多类分类问题。在数据集中,输入(X)由与每种葡萄酒的各种属性相关的 13 个特征组成。已知的输出(y)是葡萄酒类型,在数据集中,这些类型被赋予数字 0、1 或 2。
我在本文中使用的所有代码的导入如下所示。
import pandas as pd
import numpy as npfrom sklearn.datasets import load_wine
from sklearn.datasets import load_bostonfrom sklearn.model_selection import train_test_split
from sklearn import preprocessingfrom sklearn.metrics import f1_score
from sklearn.metrics import mean_squared_error
from math import sqrtfrom sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC, LinearSVC, NuSVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier, GradientBoostingClassifier
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis
from sklearn import linear_model
from sklearn.linear_model import ElasticNetCV
from sklearn.svm import SVRfrom sklearn.cluster import KMeans
from yellowbrick.cluster import KElbowVisualizer
from yellowbrick.cluster import SilhouetteVisualizer
在下面的代码中,我正在下载数据并转换成熊猫数据框。
wine = load_wine()
wine_df = pd.DataFrame(wine.data, columns=wine.feature_names)
wine_df['TARGET'] = pd.Series(wine.target)
监督学习问题的下一步是将数据分成测试集和训练集。算法可以使用训练集来学习输入和输出之间的映射,然后可以使用保留的测试集来评估模型学习该映射的程度。在下面的代码中,我使用 scikit-learn model_selection 函数train_test_split
来做这件事。
X_w = wine_df.drop(['TARGET'], axis=1)
y_w = wine_df['TARGET']
X_train_w, X_test_w, y_train_w, y_test_w = train_test_split(X_w, y_w, test_size=0.2)
在下一步中,我们需要选择最适合学习所选数据集中的映射的算法。在 scikit-learn 中有许多不同的算法可供选择,它们都使用不同的函数和方法来学习映射,您可以在这里查看完整列表。
为了确定最佳模型,我运行以下代码。我正在使用一系列算法来训练这个模型,并获得每一个算法的 F1 分数。F1 分数是分类器整体准确性的良好指标。我已经详细描述了可以用来评估分类器的各种指标这里是。
classifiers = [
KNeighborsClassifier(3),
SVC(kernel="rbf", C=0.025, probability=True),
NuSVC(probability=True),
DecisionTreeClassifier(),
RandomForestClassifier(),
AdaBoostClassifier(),
GradientBoostingClassifier()
]
for classifier in classifiers:
model = classifier
model.fit(X_train_w, y_train_w)
y_pred_w = model.predict(X_test_w)
print(classifier)
print("model score: %.3f" % f1_score(y_test_w, y_pred_w, average='weighted'))
完美的 F1 分数应该是 1.0,因此,数字越接近 1.0,模型性能越好。上述结果表明,随机森林分类器是该数据集的最佳模型。
回归
在回归中,输出(y)是连续值而不是类别。回归的一个例子是预测一个商店下个月的销售额,或者你房子的未来价格。
为了再次说明回归,我将使用 scikit-learn 的数据集,即波士顿住房数据集。这由 13 个特征(X)组成,这些特征是房子的各种属性,例如房间数量、年龄和该位置的犯罪率。输出(y)是房子的价格。
我使用下面的代码加载数据,并使用与葡萄酒数据集相同的方法将数据分成测试集和训练集。
boston = load_boston()
boston_df = pd.DataFrame(boston.data, columns=boston.feature_names)
boston_df['TARGET'] = pd.Series(boston.target)X_b = boston_df.drop(['TARGET'], axis=1)
y_b = boston_df['TARGET']
X_train_b, X_test_b, y_train_b, y_test_b = train_test_split(X_b, y_b, test_size=0.2)
我们可以使用这个备忘单来查看 scikit-learn 中适用于回归问题的可用算法。我们将使用与分类问题类似的代码来循环选择并打印出每个选项的分数。
有许多不同的指标用于评估回归模型。这些本质上都是误差度量,并测量模型实现的实际值和预测值之间的差异。我使用了均方根误差(RMSE)。对于此指标,该值越接近零,模型的性能越好。这篇文章对回归问题的误差度量给出了很好的解释。
regressors = [
linear_model.Lasso(alpha=0.1),
linear_model.LinearRegression(),
ElasticNetCV(alphas=None, copy_X=True, cv=5, eps=0.001, fit_intercept=True,
l1_ratio=0.5, max_iter=1000, n_alphas=100, n_jobs=None,
normalize=False, positive=False, precompute='auto', random_state=0,
selection='cyclic', tol=0.0001, verbose=0),
SVR(C=1.0, cache_size=200, coef0=0.0, degree=3, epsilon=0.1,
gamma='auto_deprecated', kernel='rbf', max_iter=-1, shrinking=True,
tol=0.001, verbose=False),
linear_model.Ridge(alpha=.5)
]for regressor in regressors:
model = regressor
model.fit(X_train_b, y_train_b)
y_pred_b = model.predict(X_test_b)
print(regressor)
print("mean squared error: %.3f" % sqrt(mean_squared_error(y_test_b, y_pred_b)))
RMSE 分数表明,线性回归和岭回归算法对该数据集的性能最好。
无监督学习
有许多不同类型的无监督学习,但为了简单起见,这里我将集中讨论聚类方法。有许多不同的聚类算法,所有这些算法都使用略有不同的技术来查找输入的聚类。
可能最广泛使用的方法之一是 Kmeans。该算法执行迭代过程,由此启动指定数量的随机生成均值。距离度量计算每个数据点到质心的欧几里德距离,从而创建相似值的聚类。然后,每个聚类的质心成为新的平均值,并且重复该过程,直到获得最佳结果。
让我们使用在分类任务中使用的葡萄酒数据集,去掉 y 标签,看看 k-means 算法从输入中识别葡萄酒类型的能力如何。
因为我们只使用这个模型的输入,所以我使用稍微不同的方法将数据分为测试和训练。
np.random.seed(0)
msk = np.random.rand(len(X_w)) < 0.8
train_w = X_w[msk]
test_w = X_w[~msk]
由于 Kmeans 依赖于距离度量来确定聚类,因此通常有必要在训练模型之前执行特征缩放(确保所有特征具有相同的比例)。在下面的代码中,我使用 MinMaxScaler 来缩放特征,使所有的值都在 0 和 1 之间。
x = train_w.values
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(x)
X_scaled = pd.DataFrame(x_scaled,columns=train_w.columns)
使用 K-means,您必须指定算法应该使用的聚类数。因此,第一步是确定最佳聚类数。这是通过迭代多个 k 值并将结果绘制在图表上来实现的。这就是所谓的肘方法,因为它通常会生成一个曲线,看起来有点像你的肘曲线。yellowbrick 库(这是一个可视化 scikit-learn 模型的伟大库,可以 pip 安装)对此有一个非常好的规划。下面的代码产生了这种可视化效果。
model = KMeans()
visualizer = KElbowVisualizer(model, k=(1,8))
visualizer.fit(X_scaled)
visualizer.show()
通常,在使用聚类技术的情况下,我们不会知道数据集中有多少个类别。然而,在这种情况下,我们知道数据中有三种葡萄酒类型—曲线正确地选择了三种作为模型中使用的最佳分类数。
下一步是初始化 K-means 算法,使模型适合训练数据,并评估该算法对数据进行聚类的有效性。
用于此的一种方法被称为轮廓评分。这度量了分类中值的一致性。或者换句话说,每个分类中的值彼此有多相似,以及分类之间有多大的间隔。将为每个值计算轮廓分数,范围从-1 到+1。然后将这些值绘制成轮廓图。同样,yellowbrick 提供了一种简单的方法来构建这种类型的地块。下面的代码创建了葡萄酒数据集的可视化。
model = KMeans(3, random_state=42)
visualizer = SilhouetteVisualizer(model, colors='yellowbrick')visualizer.fit(X_scaled)
visualizer.show()
侧影图可以用以下方式解释:
- 平均分数(上面的红色虚线)越接近+1,聚类中的数据点就越匹配。
- 得分为 0 的数据点非常接近另一个聚类的判定边界(因此分离度很低)。
- 负值表示数据点可能被分配到了错误的聚类。
- 每个聚类的宽度应该相当一致,如果不一致,则可能使用了不正确的 k 值。
上面的葡萄酒数据集的图显示,聚类 0 可能不如其他聚类一致,因为大多数数据点低于平均分数,少数数据点的分数低于 0。
轮廓分数在将一种算法与另一种算法或不同的 k 值进行比较时特别有用。
在这篇文章中,我想简单介绍一下这三种类型的机器学习。在所有这些过程中还涉及许多其他步骤,包括特征工程、数据处理和超参数优化,以确定最佳数据预处理技术和最佳使用模型。
感谢阅读!
卷积神经网络初学者指南
原文:https://towardsdatascience.com/beginners-guide-to-understanding-convolutional-neural-networks-ae9ed58bb17d?source=collection_archive---------3-----------------------
了解构成卷积神经网络的重要组件
Camera (Photo by Dariusz Sankowski on Unsplash)
卷积神经网络(CNN)是一种深度神经网络,已被证明在计算机视觉任务中表现良好,如图像分类、对象检测、对象定位和神经类型转移。在这篇文章中,我将解释构成卷积神经网络的不同层:卷积层、池层和全连接层。
卷积层
卷积层对输入图像进行变换,以便从中提取特征。在这个变换中,图像与一个核(或滤波器)进行卷积。
Image convolution (source)
一个核是一个小矩阵,其高度和宽度小于要卷积的图像。它也被称为卷积矩阵或卷积掩模。该内核在图像输入的高度和宽度上滑动,并且在每个空间位置计算内核和图像的点积。内核滑动的长度被称为步幅长度。在下图中,输入图像的大小为 5X5,内核的大小为 3X3,步长为 1。输出图像也被称为卷积特征。
当用通道 3 卷积彩色图像(RGB 图像)时,滤波器的通道也必须是 3。换句话说,在卷积中,内核中的通道数必须与输入图像中的通道数相同。
Convolution on RGB image (source)
当我们想使用卷积从一幅图像中提取多个特征时,我们可以使用多个内核,而不是只使用一个。在这种情况下,所有内核的大小必须相同。输入图像和输出图像的卷积特征被一个接一个地堆叠以创建输出,使得通道的数量等于所使用的滤波器的数量。见下图,供参考。
Convolution of RGB image using multiple filters (kernels) (source)
激活函数是卷积层的最后一个组件,用于增加输出中的非线性。通常,ReLu 函数或 Tanh 函数被用作卷积层中的激活函数。这是一个简单卷积图层的图像,其中 6X6X3 输入图像与大小为 4X4X3 的两个核进行卷积,以获得大小为 3X3X2 的卷积特征,激活函数应用于此以获得输出,这也称为特征图。
A convolution layer (source)
汇集层
池层用于减小输入图像的大小。在卷积神经网络中,卷积层之后通常是池层。通常添加池层以加快计算速度,并使一些检测到的特征更加健壮。
池操作也使用内核和 stride。在下面的示例图像中,2X2 过滤器用于合并大小为 4X4 的输入图像,跨距为 2。
有不同类型的池。最大池和平均池是卷积神经网络最常用的池方法。
Max pooling on left, Average pooling on the right (source)
Max Pooling: 在 Max Pooling 中,从特征图的每个面片中,选择最大值来创建缩小图。
平均池化:在平均池化中,从特征图的每个小块中,选择平均值来创建缩减图。
全连接层
完全连接的层位于卷积神经网络的末端。先前图层生成的要素地图被展平为矢量。然后,这个向量被馈送到完全连接的层,以便它捕获高级特征之间的复杂关系。这一层的输出是一维特征向量。
A simple architecture of a CNN for binary image classification (source)
以上是用于二值图像分类的卷积神经网络的简单架构。该网络将输入分类为两个不同的类别。该网络接收大小为 32×32×3 的 RBG 图像,输出大小为 2(等于用于分类的类的数量)。该网络的第一层是具有 5×5×3 核的卷积层,第二层是具有 2×2 核大小的最大池层,第三层是具有 5×5×3 核的卷积层,第四层是具有 2×2 核大小的最大池层,输出被平坦化为向量并被馈送到最后两层,这两层都是完全连接的层。
现在,你知道什么是卷积神经网络,以及构成卷积神经网络的不同层,即卷积层、汇集层和全连接层。
觉得这个帖子有帮助? 在下面留下你的想法作为评论。
点击这里 阅读我其他关于 AI/机器学习的帖子。
使用 Py thon 不到 3 分钟实现人脸检测
物体检测用不到 10 行代码使用 Python
用不到 10 行代码计算汽车数量使用 Python
参考文献:
[## 盘旋
卷积是一种数学运算,它对两个函数(信号)的乘积进行积分,其中一个…
Leonardo araujosantos . git books . io](https://leonardoaraujosantos.gitbooks.io/artificial-inteligence/content/convolution.html) [## # 006 RGB 图像上的 CNN 卷积|主数据科学
我们已经看到了 2D 图像上的卷积是如何工作的。现在,让我们看看如何不仅在 2D 上实现卷积…
datahacker.rs](http://datahacker.rs/006-cnn-convolution-on-rgb-images/) [## 学生笔记:卷积神经网络(CNN)简介
这些笔记摘自卷积神经网络课程的前两周(深度学习的一部分…
indoml.com](https://indoml.com/2018/03/07/student-notes-convolutional-neural-networks-cnn-introduction/) [## 理解神经网络中的激活函数
最近,我的一个同事问了我几个类似“为什么我们有这么多激活功能?”,“为什么是…
medium.com](https://medium.com/the-theory-of-everything/understanding-activation-functions-in-neural-networks-9491262884e0) [## 卷积神经网络池层的简明介绍
卷积神经网络中的卷积层总结了输入图像中特征的存在。一个问题…
machinelearningmastery.com](https://machinelearningmastery.com/pooling-layers-for-convolutional-neural-networks/)
żejmo、米沙&科瓦尔、马雷克&科尔比茨、约瑟夫&蒙扎克、罗曼。(2018).基于卷积神经网络和 Hough 变换的细胞核识别。316–327.10.1007/978–3–319–64474–5_26.
Java 初学者——面向对象编程入门
原文:https://towardsdatascience.com/beginners-in-java-getting-started-with-oop-6398f0dcdf86?source=collection_archive---------15-----------------------
Java 是一种面向对象的编程语言——这是什么意思?
每当一种编程方法是基于对象或类,而不仅仅是函数和过程,它就被称为面向对象的OOOOP编程( OOP )。
Java 中的所有代码都必须包含在类中
面向对象语言中的对象被组织成类,或者用更简单的术语来说,一个类产生对象。Java 就是这样一种编程语言。
Photo by Émile Perron on Unsplash
类别和对象
java 程序中的一切都包含在一个类中。一个类可以被认为是一个生产对象的工厂。对象内部包含数据。它可以有一个或多个数据项。例如,午餐盒对象可能包含 3 个数据项
- 薯条(固体食物类型
- 汉堡(固体食物型
- 冷饮(类型流食
我们对象中的这三个不同的项目被称为字段。每个字段都必须有一个类型。在上面的例子中,我们有 3 个字段,但是其中两个具有相同的类型。同时,我们使用方法来处理数据。例如,可以使用方法来查看对象中包含什么数据。这些被称为访问器方法。我们也可以拥有修改对象内部数据的方法。这些被称为更新方法。
假设我们有一个食品厂(类)。它制造饭盒(物体)。午餐盒包含 3 种不同的食物(字段)。其中两个是同类型(固体食物)一个是不同类型(液体食物)。我们有 3 个人互动使用这种食物。厨师(方法 1) 加热食物,服务员(方法 2 )上菜,消费者(方法 3 )吃食物。
How OOP Works
在 Java 程序中,主要的“参与者”是 对象 。每个对象都是一个类的 实例 ,它作为对象的类型和蓝图,定义了对象存储的数据以及访问和修改这些数据的方法。
— 迈克尔·t·古德里奇、罗伯托·塔玛西亚、迈克尔·h·戈德瓦瑟(Java 中的数据结构与算法* )*
理解对象
一个对象是类的一个实例,即一个类可以产生许多对象。例如
对象 1
- 固体食物项目 1——薯条
- 固体食物项目 2——汉堡
- 液体食品项目 1——冷饮
对象 2
- 固体食物项目 1——大米
- 固体食物项目 2——鱼
- 液体食品项目 1 —水
该过程
让我们试着看看如何构建一个基本的工厂类。让我们先来看看完整的代码。
文件名
行 public class Factory{} 包含了完整的代码。该文件必须以类名命名。所以文件名也是 Factory.java。
*public class Factory{
...
}*
字段/实例变量
现在最上面的 3 行给出了你想要的午餐盒中的 3 个项目(实例变量)。现在你可以看到所有 3 个都有相同的类型= 字符串。 Java 给了你创建自己的类型的灵活性,这实质上意味着用那个名字创建一个类。例如,如果你要创建一个 SolidFood 类,你就必须编写 public class SolidFood{} ,如此而已。
现在我们有 3 个 String 类型的实例变量,命名为 SolidFood1、SolidFood2 和 LiquidFood1。
*private String SolidFood1; // **Solid Food 1st Instance Variable**
private String SolidFood2; // **Solid Food 2nd Instance Variable**
private String LiquidFood1; // **Liquid Food 3rd Instance Variable***
构造器
创建对象的代码位于构造函数内部。构造函数可以是空的,也可以接受一些用于定义对象的输入参数。在我们的例子中 sf1、sf2 和 lf1 是定义我们的午餐盒中包含哪些项目的参数。
简单地说,构造函数定义了对象的字段是什么样子的。
*public Factory(){} // **0-arg constructor (Not used)**
// **3-arg constructor**
public Factory(String sf1, String sf2, String lf1){
SolidFood1 = sf1;
SolidFood2 = sf2;
LiquidFood1 = lf1;
}*
方法
方法用于获取或修改对象字段。在我们的例子中,我们只编写了获取项目名称的字段。
*public String getSF1(){return SolidFood1;} // **Method to get the name of 1st Instance Variable**
public String getSF2(){return SolidFood2;} // **Method to get the name of 2nd Instance Variable**
public String getLF1(){return LiquidFood1;} // **Method to get the name of 3rd Instance Variable***
main 方法是每个程序中唯一需要的方法。它是 java 编译器唯一运行的东西。在 main 中,你可以创建对象,在这些对象上使用方法并打印东西。
对象创建
对象是通过调用构造函数创建的。一旦创建了一个对象,您可以使用各种方法来理解或修改该对象。这里我们只是展示如何访问字段名。
*Factory lunchBox = new Factory("s1","s2", "l1"); // **Object Created Yay!!!***
怎么跑
万一你没有 java,请访问这个页面。
* [## 如何为我的 Mac 安装 Java?
如果 web 浏览器中禁用了 Java 内容,安装程序会通知您,并提供启用它的说明。如果…
java.com](https://java.com/en/download/help/mac_install.xml)
假设您的系统中安装了 java,您应该能够使用以下命令运行该程序。
> javac Factory.java (**This command compiles your code into Machine Readable Code)**> java Factory (**Running the Program**)
您看到的输出如下所示
*
OOP 中包含了更多的东西。这只是开始。后面的文章将包括更多的面向对象编程的概念。
参考
- 要点链接
- Java 下载
- 数据结构书
矩阵入门
原文:https://towardsdatascience.com/beginners-introduction-to-matrices-bd39289cc66a?source=collection_archive---------15-----------------------
从理论物理到神经网络,矩阵运算无处不在。
矩阵是数据科学的基石。他们以不同语言的不同形象出现。从 Python 中的 numpy 数组,到 R 中的 dataframes,再到 MATLAB 中的 matrix。
矩阵最基本的形式是以矩形或类似阵列的方式排列的数的集合。这可以代表一个图像,或者一个网络,甚至一个抽象的结构。
A rectangular array of 3 rows and 4 columns.
矩阵,矩阵的复数形式,比你想象的要普遍得多。
我们所有通过 Adobe Photoshop 制作的迷因都使用矩阵处理线性变换来渲染图像。一个方阵可以表示一个几何对象的线性变换。
例如,在笛卡尔 X-Y 平面中,矩阵
Interesting matrix
用于创建对象在垂直 Y 轴上的倒影。在视频游戏中,这将呈现倒映在血泊中的刺客图像。如果视频游戏有弯曲的反射面,比如一间镜子房,矩阵会更复杂,以拉伸或收缩反射。
xkcd — Rotation
在应用物理学中,矩阵用于研究电路、量子力学和光学。航天工程、化学工程等。所有这些都需要从矩阵变换中获得完全校准的计算。在医院、医学成像、CAT 扫描和 MRI 中,使用矩阵来生成输出。
Photo by JESHOOTS.COM on Unsplash
在编程中,矩阵和逆矩阵用于编码和加密消息。在机器人和自动化中,矩阵是机器人运动的基本组成部分。基于使用矩阵的计算获得用于控制机器人的输入。
他们长什么样?
按照惯例,矩阵中的行数由 m 表示,列数由 n 表示。由于矩形的面积是高 x 宽,我们用mxn .来表示矩阵的大小,因此该矩阵被称为 A,它在符号上可以写成
Matrix notation
这里 m=3,n=4。因此,矩阵 A 中有 12 个元素。方阵是具有 m=n 的矩阵。
Square matrix
只有一行的矩阵称为行矩阵,只有一列的矩阵称为列矩阵。
我们能用它们做什么?
矩阵就像数字一样,可以加减乘除。不过,这种划分略有不同。不是所有的矩阵都可以整除。
连加减乘除都有一定的规律。
矩阵加法
两个矩阵 A( mn* ) 和B( mn* ) 相加得到一个矩阵 C( mn* )。C 的元素是 A 和 B 中相应元素的和
减法的工作原理类似。
这里需要注意的是,您只能对具有相同行数和列数的矩阵进行加减运算,即相同的顺序(顺序=行 x 列)
- A 的行数= B 的行数
- A 的列数= B 的列数
注意事项
- 矩阵的加法是可交换的,这意味着 A+B = B+A
- 矩阵的加法是结合的,这意味着 A+(B+C) = (A+B)+C
- 矩阵的减法是不可交换的,这意味着 A-B ≠ B-A
- 矩阵的减法是非关联的,意思是 A-(B-C)≦(A-B)-C
- 矩阵 A、B、A-B 和 A+B 的顺序总是相同的
- 如果 A 和 B 的顺序不同,A+B,A-B 就无法计算
- 加法/减法运算的复杂度是 O(mn ),其中 mn 是矩阵的阶
尽管乘法有点复杂
矩阵乘法
两个矩阵 A( mn* ) 和B(n** p)相乘得到一个矩阵 C( mp )。请注意,对于乘法运算,您不需要 A 和 B 的行/列相同。你只需要**
- A 的列数= B 的行数
- 或者,B 的列数= a 的行数。
要计算结果矩阵 C 的左上元素,将 A 的第一行元素与 B 的第一列元素相乘并相加
Multiplication
注意事项
- 矩阵的乘法是不可交换的,这意味着 AB ≠ BA
- 矩阵的乘法是结合律,这意味着 A(BC) = (AB)C
- AB 的存在并不意味着 BA 的存在
- 乘法运算(AB)的复杂度为 O(mnp)其中 mn 和 n*p 分别是 A 和 B 的阶
- 作为 AB 计算的矩阵 C 的阶是 mp,其中 mn 和 np 分别是 A 和 B 的阶
在这篇文章的下一个版本中,我们将看到更多可以在矩阵上执行的操作,例如矩阵的逆矩阵、矩阵的行列式、矩阵的伴随矩阵等等。
我们还将看到这些矩阵如何在神经网络和图像处理领域发挥作用。
从KNN(K-最近邻算法)到随机森林,矩阵在几乎所有的机器学习算法中都非常重要。
矩阵入门—第二部分
原文:https://towardsdatascience.com/beginners-introduction-to-matrices-part-ii-42b86e791b8b?source=collection_archive---------35-----------------------
从设计游戏到发射火箭,矩阵运算无处不在
在第一部分中,我们讨论了像加法、减法和乘法这样的基本运算。在这一部分,让我们看看如何计算矩阵的行列式,以及术语矩阵求逆是什么意思。
继续前面的例子,让我们看看我们的方阵(方阵的行数等于列数
Square matrix with m=3, n=3 | A(mxn)
这个矩阵的行列式将是一个单一的数字。它不会是一个矩阵。行列式可以看作是将矩阵转化为数字的函数。矩阵 A 的行列式写成 |A| 。
determinant of a 2x2 matrix
行列式只存在于方阵中。它是方阵的一个性质。对于一个 3×3 的矩阵,行列式的计算应该是这样的
注意++模式(+a…b…+c…d…)。记住这一点很重要。这种模式在 4x4 矩阵和更高矩阵中继续存在。这种计算行列式的方法叫做拉普拉斯展开。这决不是唯一的方法,还有其他方法。
行列式不仅用作计算工具(解线性方程,计算面积和体积),而且在力学中也有重要的应用。它们可以用来计算桁架或其他机械结构的稳定性。
具有讽刺意味的是,行列式的最大用途是它的零。如果一个矩阵的行列式为 0,那么就是需要注意的情况。好坏取决于应用。
矩阵的逆
在数学中,数的倒数写为
所以一个数和它的倒数相乘总是得到 1。(除非数字为 0,在这种情况下,不定义逆本身)。
对于矩阵,逻辑是一样的。如果矩阵的逆矩阵存在,则将矩阵与其逆矩阵相乘得到单位矩阵。这里需要注意两件事
- 如果 1)矩阵是正方形的,2)它的行列式不为零,则存在逆
- 单位矩阵的所有元素除了主对角线都是 0。主对角线元素都是 1。单位矩阵总是用字母 I. 表示
这是一个非常特殊的矩阵,因为如果你试图将它与另一个 mx3 矩阵相乘,结果将是同一个矩阵。
为什么我们需要一个反义词
在矩阵的世界里,没有除法运算。因此,如果你必须在一个方程中求解 X ,其中 A,X 和 B 都是矩阵
唯一的方法就是取 a 的倒数。
There is no B/A in matrices
反演的最大应用是在电脑游戏中——光线追踪。在游戏世界中,为了实现 3d 效果,需要将鼠标点击转化为游戏的 3d 空间中的实际动作。这个操作和无数其他操作需要矩阵求逆。反演也用于反射。
Photo by Ales Nesetril on Unsplash
在下一部分,我们将计算一个实际的逆矩阵,并探索矩阵乘法的 python 库。
机器学习的初学者学习路径
原文:https://towardsdatascience.com/beginners-learning-path-for-machine-learning-5a7fb90f751a?source=collection_archive---------2-----------------------
您在机器学习领域开始职业生涯的完整学习路径
Photo by Franck V. on Unsplash
下定决心要进行机器学习,但却困惑于从哪里开始。我面临着同样的困惑,什么应该是一个好的开始?我应该学 Python,还是去 R?数学对我来说总是一个可怕的部分,我总是担心我应该从哪里学习数学?我还担心我应该如何获得机器学习的强大基础。不管怎样,至少你已经下定决心了,这是值得祝贺的。
在这篇文章中,我将告诉你在开始实用的机器学习之前,你应该采取的一些基本步骤和课程。
数学是机器学习的第一步吗?
机器学习的第一步(基本编程)
第一步是你应该学习编程,很可能是 Python。如果你从未写过一行代码,我会向你推荐哈佛大学的 CS50,这是编程初学者的最佳课程,它将教你从零开始,直到所有的 C 语言和大量的 Python 和 JavaScript,以及 SQL 和 JSON 的基础知识。这个非常激动人心的课程在 edx.org的是免费的,你可以在这里找到它。点击阅读一篇关于 cs50 的文章
如果你想直接从 Python 开始,那么我会推荐你在 edx 上免费学习麻省理工学院的 Python 计算机科学入门。请注意,高中代数是这门课的先决条件,因为它们会让你解决许多现实世界中的数学问题。
如果你觉得你的计算逻辑不好,你在编程中不是一个很好的问题解决者,我会推荐微软的这门课程,它都与 edx all 上免费的计算思维有关。这门课真的很酷,教了很多计算逻辑和批判性思维。
如果你有足够好的编程基础,但是没有面向对象编程的知识,那么我推荐你学习面向对象编程。虽然它在机器学习(基础水平)中用得不多,但肯定很有帮助。我会推荐这个课程,它教你 oop 的基础和 python 中的算法。你可以在 edx.org 找到这门免费的课程。
下一步是熟悉数据结构和算法。一个好的程序员必须知道一些基本的算法,如链表、二叉树等。这个课程微软会教你
- 算法分析
- 算法的排序和搜索
- 数据结构:链表、栈、队列
这门课程在 edx.org 的免费提供。
如果想深入数据结构和算法,加州大学圣地亚哥分校的专业是一个杰作。它有 6 门课程,将带你从 0 到数据结构和算法的英雄水平。你可以点击每门课程并免费审核它的材料,但如果你想要证书,它的价格是 50 美元/月,取决于你多早可以完成它。在 Coursera.org 找到这个专业或点击这里。
机器学习的第二步
是的,你猜对了,对大部分初学者来说最危险的部分,数学。
Photo by Antoine Dautry on Unsplash
但是不要担心,它并没有我们想象的那么难,如果你认为你有很好的高中数学基础(向量、矩阵、微积分、概率和统计),你可以简单地参加一个复习课程,但是如果你认为你不够好,那么任何人学习数学的最好地方是可汗学院。可汗学院的内容非常丰富,非常有用,而且一切都是免费的。你可以在那里找到所有的线性代数、概率统计和多变量微积分课程。
另一个很好的课程是伦敦帝国理工学院 coursera 的机器学习专业化数学。这是一门很棒的课程,它教授基础知识,修正概念,但不会太深入。练习和测验很有挑战性。上面有三道菜。
- 机器学习的数学:线性代数
- 机器学习的数学:多元微积分
- 机器学习的数学:PCA
麻省理工学院有一门很棒的统计学课程
- 使用矩法和极大似然法构造估计量,并决定如何在它们之间进行选择
- 使用置信区间和假设检验量化不确定性
- 使用拟合优度测试选择不同的模型
- 使用线性、非线性和广义线性模型进行预测
- 使用主成分分析(PCA)进行降维
在 edx.org免费可以买到。
如果你想边编码边学数学,微软有一门真的很好的课程《机器学习必备数学:Python 版》。这是一门交互式课程,使用 python 著名的库 Numpy、pandas、matplotlib 以图形方式教授数学,这些库是本课程的先决条件。在 edx.org 找到免费的 T4 课程。
Udacity 有 3 门很棒的统计学免费课程。
- 统计学简介
- 统计数据
- 推断统计学简介
你也可以在学习实用机器学习的同时学习数学,遇到你不知道的事情,只需在可汗学院或 YouTube 上搜索这个主题的 100 多个好视频。
机器学习的第三步
现在你已经熟悉了线性代数、多变量微积分和统计学,所以现在你需要学习 Python 著名的数据可视化库,它们是 Numpy、Pandas、Matplotlib 和 Scipy,可以帮助你分析任何类型的数据,操纵数据,并以图形方式查看数据。当然,还有很多数据可视化库,但这些是最重要的一个。用图形实现你的线性代数和微积分概念,并将其形象化。
这方面的代表作之一是密歇根大学的 Python specialization 统计学,它详细讲授了数据可视化及其操作。当然可以在 coursera.org 上免费(点击每门课程免费审核)。
密歇根大学为数据分析初学者开设的另一门课程是 Python 中的数据科学导论,它以一种非常好的方式教授从数字到熊猫的基础知识。可在 coursera.org免费购买。本课程的下一部分将改变游戏规则。在 Python 中被命名为应用绘图、图表和数据表示,它教授所有的图形可视化及其技巧和技术。
另一门很好的课程是哈佛大学的“Python for Research ”,它教授这些库以及一些著名的案例研究,它的期末项目非常令人兴奋,教授了很多新东西。edx.org 免费可用。
另一门非常全面的课程是加州大学圣地亚哥分校的数据科学 Python,它教授
- 计算机编程语言
- Jupyter 笔记本
- 熊猫
- NumPy
- Matplotlib
- 饭桶
- sci 工具包-学习
- NLTK
也就是说,这门课还会教你机器学习的基础知识,但更重要的是,这门课所教授的数据科学库。可在 edx.org 上免费获得(别忘了阅读它的先决条件)。
实用的机器学习
Photo by Franck V. on Unsplash
到目前为止,您已经学习了线性代数、多变量微积分、概率和统计、python 及其数据可视化库,所以现在您已经准备好跳到最激动人心的部分,即机器学习。第一道菜意义重大。如果不好,他可能只是改变领域,因为他只是不喜欢这个过程。所以这里所有的课程都是高质量的,在你开始你的第一门 ML 课程之前,做一些研究。
这门入门课程不会教你机器学习,相反,它会让你了解什么是机器学习,机器学习术语的含义是什么,什么是人工智能策略,以及它的伦理。本课程将向您概述什么是机器学习,它是如何工作的,它的工作流程是什么,以及如何在您的公司中构建人工智能。它很好地介绍和概述了人工智能。该课程由非常著名的机器学习导师吴恩达教授,可在 coursera.org免费获得。
你可以谷歌一下或者在任何博客上看到,每个人推荐的第一门课程是斯坦福大学的机器学习,由 Andrew NG 教授,该死的,这是一门多么美丽的课程。超过 250 万名学生注册了这门课程,超过 20 万名学生对它进行了评分(4.9*)。它教授从非常基础的概念到高级的概念,对初学者来说是一门非常全面的课程。本课程的总时长为 56 小时以上。想看看这门课的评论吗?这里你去吧。另一篇在此回顾。这里是 Quora 上对这门课程的另一个回顾。这是里面的目录。
- 线性回归
- 多项式回归
- 逻辑回归
- 多类分类
- 神经网络
- 支持向量机(SVM)
- k 均值聚类
- 主成分分析
- 异常检测
- 推荐系统
唯一的问题(根据一些人的说法)是它是在 octave/Matlab 中教授的,但对我来说这没什么大不了的,因为它将清除机器学习的所有基础和深层概念,在任何其他语言中实现它们都不会是任何问题,而且 Matlab 是一项额外的技能。该课程在斯坦福官网(此处)和 coursera.org( 此处)免费提供。
这门课对每个人来说都是必去的,因为它好得无法解释。
学完这门课程后,你需要实现你在 python 中学到的所有东西,并超越你所学的东西,所以我们自己的吴恩达在 coursera 上的 deeplearning.ai 、 Kian Katanfrosh 和 Younes Bensouda 的专业化也是必须的。该专业有 5 门课程,分别是
- 神经网络和深度学习
- 改进深度神经网络:超参数调整、正则化和优化
- 构建机器学习项目
- 卷积神经网络
- 序列模型
你将获得的主要技能是
- 张量流
- 卷积神经网络
- 人工神经网络
- 深度学习
好了,现在你已经很好地掌握了 TensorFlow 和机器学习,你可能不喜欢 TensorFlow,或者你只是想测试 TensorFlow 的著名参赛者 PyTorch(由脸书设计),那么为什么不开始这个免费的深度学习课程呢? Udacity 由脸书与亚马逊网络服务合作提供,是 Udacity 著名的深度学习纳米学位的一部分,价值 1400 美元。
当然,这仅仅是一个开始,还有很多需要学习和发现的,但是如果你做了这些事情,希望你会知道你的立场和下一步该做什么。
一些意见和建议:
以下是一些建议。
- 现在就开始收听 OC Devel 的“机器学习指南”播客。这将为您提供机器学习的完整概述,其中包含哪些内容,以及 android 和 web 应用程序开发人员转向机器学习之路的旅程。可在苹果播客 /iTunes、谷歌播客和他的网站上获得。
- 获取“使用 Scikit-Learn 和 TensorFlow 进行机器实践学习:构建智能系统的概念、工具和技术”或其 2019 年 10 月发布的新版本,名为“使用 Scikit-Learn、Keras 和 TensorFlow 进行机器实践学习:构建智能系统的概念、工具和技术”。这本书的作者是奥雷连恩·盖伦。本书第一版是人工智能(书籍)# 1自然语言处理(书籍)&# 1计算机神经网络。第二版尚未发布,但可预购。这本书很广泛,推荐。现在就从亚马逊订购。
- 别忘了阅读这篇文章。它有很多有用的信息。
- 在 Kaggle 上大量练习(一旦开始 ML 就知道了)。
- 要敬业,要相信自己能行。你需要的只是一致性。
祝你好运,并祝你在学习如何让机器变得智能的过程中过得愉快。
Python 初学者推荐系统
原文:https://towardsdatascience.com/beginners-recommendation-systems-with-python-ee1b08d2efb6?source=collection_archive---------7-----------------------
用 TMDB 5000 电影数据集构建我们自己的推荐系统
Photo by Myke Simon on Unsplash
本教程的目标
以下是您的一些目标:
- 了解什么是推荐系统,它们是如何工作的,以及它们的不同风格
- 使用 Python 和 TMDB 5000 部电影数据集实现几个推荐系统
什么是推荐系统?
一个推荐系统(通常也被称为推荐/推荐引擎/平台)试图预测用户对可用项目(例如 Spotify 上的歌曲)的兴趣,并相应地给出推荐。有两种主要类型的推荐系统:
- 基于内容的过滤系统根据项目本身的特点做出推荐。因此,如果网飞用户一直在狂看科幻电影,网飞会更快地推荐另一部科幻电影,而不是浪漫喜剧。我们将用 Python 实现这个推荐系统。
- 协同过滤系统基于用户交互做出推荐。假设我们都在亚马逊上买了一把电吉他,我也买了一个功放。然后亚马逊会预测你也会对这款功放感兴趣,并向你推荐。
Ibtesam Ahmed 在这个数据集上的 Kaggle 内核值得称赞。这篇文章旨在以中等风格的格式遵循她的教程。
建立一个基本的推荐系统
设置
和往常一样,我们将首先导入必要的包和数据集:
Setup for our notebook
这两条打印语句给出了以下输出:
- 演职员表:(4803,4)
- 电影 _ 不完整:(4803,20)
所以我们正在研究 4803 部电影。请注意,我们的数据现在被分成两个数据帧。参考本要点了解如何组合和清理数据帧。在遵循教程的同时保持这个要点是最容易的。
我们将从两个非常基本的推荐系统开始——我们将向用户推荐评分最高的电影列表和另一个最受欢迎的电影列表。但是首先我们要找到每部电影的平均评分的加权平均值( vote_average 值)。在 Ibtesam 的带领下,我们将使用 IMDB(以前)用于计算电影加权评分的公式。
Source
这里有一个如何得到加权平均值的例子:
我选择了 0.70 作为我对 quantile() 的参数,以表明我只关心那些至少获得了我们的电影数据集中 70%的投票的电影。选择我们的值为 m 有点武断,所以在这里做一些实验。
推荐者 Mk1:
现在我们已经为我们的第一个推荐系统做好了准备。下面推荐十部加权平均收视率最高的电影:
我们得到了这张最受欢迎的照片:
我们看到我们的就职系统推荐了一些经典。但是如果我们想推荐在 TMDB 用户中受欢迎的电影呢?
推荐者 Mk2:
我们可以使用我们数据的流行度特性来根据流行度推荐电影:
现在,我们可以看到基于受欢迎程度分数的推荐:
啊,正如我们所料:来自小兵的出色表现。现在,如果我们想根据电影的加权平均评分和受欢迎程度评分来推荐电影,该怎么办呢?
推荐者 Mk3:
为了避免小黄人的巨大受欢迎度得分扭曲我们的新评分系统,我对加权平均和受欢迎度列中的值进行了归一化。我决定采用 50/50 的比例加权平均评分和受欢迎程度评分,但同样不要害怕尝试这种分割:
现在我们有了一个新的评分栏,它考虑了一部电影的加权平均评分及其受欢迎程度评分,我们可以看到我们的推荐系统将为我们提供哪些电影:
以下是我们基于五五分成的建议:
这些推荐者按预期工作,但我们当然可以改进。现在我们必须转向基于内容的过滤。
基于内容的过滤
所以现在我们感兴趣的是使用一部电影的特征来向用户推荐其他电影。再次遵循 Ibtesam 的例子,我们现在将根据概述栏中给出的电影情节概要提出建议。因此,如果我们的用户给我们一个电影名称,我们的目标是推荐具有相似情节概要的电影。
单词矢量化和 TF-IDF
在我们开始对情节摘要进行任何分析之前,我们必须将概述列中的文本转换为单词向量,并且我们还必须在概述上安装一个 TF-IDF:
我们会收到以下输出:
- (4803,10417)
所以在情节摘要中使用了大约 10,000 个独特的词来描述我们的 5,000 部电影(注意,这个数字比 Ibtesam 的小,因为我用 min_df=3 将最小词频增加到了 3)。如果你有兴趣了解更多,我在这篇文章中也谈到了 TF-IDF。
计算相似性得分
现在我们有了一个单词矩阵,我们可以开始计算相似性得分。这个指标将帮助我们挑选出与用户提交的电影情节概要相似的电影。Ibtesam 选择了线性内核,但是我想尝试一下 sigmoid 内核,以获得乐趣。幸运的是,我得到了相似的结果:
既然我们已经构建了基于内容的过滤系统,让我们用永恒的最爱间谍小子来测试一下:
以下是我们对基于内容的过滤系统的建议:
因此,我们的推荐系统给了我们一些与间谍小子相关的精选,但也有一些失误,如《太深了中的和埃斯科瓦尔:失乐园。
限制
基于上述结果,我们可以看到我们的基于内容的过滤系统有一些局限性:
- 我们的推荐者挑选了一些可能被搜索与 Spy Kids 相关的标题的用户认为不合适的电影。为了改进我们的系统,我们可以考虑用字数来代替 TF-IDF,我们还可以探索其他相似性得分。
- 我们的系统只考虑每部电影的情节概要。如果我们像 Ibtesam 一样,考虑其他特征,如演员、导演和类型,我们可能会在找到相关电影方面有所改进。
- 我们目前的系统只根据特征的相似性来推荐电影。所以我们的推荐器遗漏了用户可能喜欢的其他类型的电影。我们需要尝试协同过滤来解决这个问题,但是我们的数据集不包括用户信息。
摘要
总而言之,我们涵盖了以下内容:
- 什么是推荐系统,它们如何工作,以及一些不同的类型
- 如何基于加权平均评分、受欢迎程度以及两者的混合来实现非常基本的推荐系统
- 如何创建基于内容的过滤系统,以及如何认识到基于内容的推荐的局限性
附录/进一步阅读
- TMDB 5000 部电影数据集
- 本教程归功于 Ibtesam Ahmed 的内核
- 我的 Colab 笔记本的要点(包含文章中引用的所有代码)
- 介绍 2019 年推荐系统
- 第九章:推荐系统
- TF-IDF scikit-learn 文档
- sci kit-了解 sigmoid-内核用户指南及更多内容
从零开始的机器学习
原文:https://towardsdatascience.com/beginning-machine-learning-650add627e79?source=collection_archive---------11-----------------------
我是如何学会不再担心反向传播的
Actor Peter Sellers in “Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb”
问题是
“我对机器学习真的很感兴趣,但我没有计算机科学或数学的背景。”
你可能以前遇到过这种情绪。如果你带着任何目的和意图阅读这篇文章,你很有可能经常遇到这种情绪。事实上,我猜测你有可能亲身体验过这种情绪。
我当然有。这是本文的缘起和基础。在相当长的一段时间里,我真的沮丧到了发狂的地步,因为我真的真诚地相信,像我这样的教育背景和经验的人很可能无法理解或使用机器学习技术。
一个“一般”的人能做机器学习吗?
简短的回答是是的。我们可以争论“平均”在这种情况下意味着什么,但我自己的个人经验(无可否认是相当有限的)向我表明,在那些被假定为必需的学科背景下(例如计算机科学、微积分和其他形式的更高层次的数学、统计学、编程等。),虽然肯定是有帮助的,但是或者根本不需要 (i) ,或者 (ii) (如果实际需要的话),典型地在比最初感觉到的显著更多的表面水平上。
成为机器学习初学者
概述
我不能告诉你如何成为一名机器学习专家,因为我自己也刚刚开始走上这条道路。但是,我确实可以放心地说,我已经开始的“机器学习初学者”之路是可以实现的,并且应该可以在具有各种背景的广泛人群中重复。
我是谁?
正如我上面提到的,我一直对机器学习、人工智能、自然语言处理和其他前沿计算领域感兴趣,但诚实而真实地感觉到,我缺乏“技术”教育背景正在阻碍我。
明确地说,按照社会将文凭等同于实际智力成就的奇怪标准,我被认为是受过良好教育的。我在达特茅斯学院获得俄罗斯语言文学本科学位,在哈佛大学获得硕士学位,在萨福克大学(位于马萨诸塞州波士顿)获得法律学位。
直到 2016 年,我一直在一家非常大、非常著名的国际律师事务所担任公司律师,在那里我非常专注于私募股权交易。2016 年年中,我做了一个完全符合年龄的决定(在 45 岁的时候),放弃了一份非常赚钱的职业,成为一名计算机程序员,这是一个我之前没有接受过正式培训,也没有真正实质性知识的学科。
为了透明起见,T2 并没有那么糟糕。我一直对计算机感兴趣,在进入法学院之前,我曾在几家软件公司工作过,但我的任何编程经验都是 (i) 非常少, (ii) 完全自学,并且 (iii) 是在 2001-2002 年获得的,这意味着这些知识实际上基本上是无用的。
经过大约一年的自学,我说服了一家公司给我一个机会。我利用那份工作学习 C#,提高我的 JavaScript,继续学习 web 应用程序架构等等。快进到今天,我在临床数据科学中心工作,但不是作为数据科学家。
因此,这是我在 2019 年下半年开始数据科学之旅时的立场:
- 我没有接受过任何计算机科学方面的正规教育,从 1989 年高中三年级开始,我就没有上过数学课。
- 我从 2016 年开始专业从事程序员工作,但我对 Python 的经验相当有限。
- 我的工作与数据科学家非常接近,但我不与他们中的任何人一起工作,当然也不知道从他们那里学到的任何东西,否则这些东西很难从谷歌那里收集到。**
如果你相信你和我一样,或者可能和我一样,我真诚地鼓励你继续读下去。
如何失败
教程和帮助文章很擅长告诉你应该肯定做什么,但是它们通常很少花时间解释什么不要做。我相信,为自己的成功做准备包括确保避免潜在的陷阱和失败,这个旅程对粗心的人来说有太多的好处。
在成为机器学习初学者的过程中,如果出现以下情况,你几乎肯定会失败:
你缺乏耐心和决心
作为一名程序员,如果不是作为一名机器学习实践者,我可以告诉你,学习编程是对耐心的锻炼。从一个非常重要(然而具有讽刺意味)的意义上来说,计算机是非常愚蠢的机器——它们只做你告诉它们的事情,除此之外别无其他。
如果你没有耐心坐在电脑前,参与编码、调试、研究的迭代过程,这可能不会让你感到愉快。
你缺乏好奇心
无论你最终选择哪种途径来获取机器学习知识,几乎可以肯定的是,你会得到这样的建议:“键入所有代码”或“按照练习进行工作”或“出去构建我们刚刚构建的东西,但略有不同”。这些都只是同一个想法的变体,即仅仅“修补”是有价值的——试验,当某些东西失败时阅读文档,查看其他人的源代码,等等。如果你没有从根本上被自己的好奇心和“建设”欲望所驱动和支撑,你几乎肯定会跟不上那些人。
你高估了学习曲线的难度
本质上,这是对最初关注的重新陈述,意味着这只是对具有非传统背景的人是否能在机器学习领域取得成功的关注。如果这篇文章有所成就的话,我希望它至少会打破机器学习完全不可接近的神话,或者只对碰巧拥有计算机科学和应用数学/统计双博士学位的少数幸运者而言。
你低估了学习曲线的难度
我认为这都是可以做到的,而不是简单的。如果很容易,只要说每个人都会这么做就够了,如果每个人都在这么做,按照逻辑,教育背景不可能是一个相关因素,这意味着本文试图解决的操作性问题将是没有实际意义的。
简单地说,在前进的道路上会有艰难的坎坷,你如何应对这些坎坷可能会成为你成功的决定性因素。你会开始搜索论坛、邮件列表、Twitter、媒体等吗?直到你得到满意的答案?还是面对不熟悉的素材会心神不定?见上面* 【你缺乏耐心和决心】。*
你打算下周、下个月、今年学习所有的机器学习/人工智能…
在刚刚成为机器学习初学者的过程中,可以学习的材料数量多得令人难以置信。更复杂的是,大量的学术和相关的工作成果正以如此快的速度增长,以至于我们倾向于用一个月或几年来衡量相关性,而不是几十年。
现在或在可预见的未来,技术的发展没有“尽头”,试图找出某个你将知道“关于机器学习的一切”的时间点,是在崇拜一个虚假神的圣坛。慢慢来,一遍又一遍地阅读相关材料,编写更多的代码,构建更多的东西,记录你的学习过程,享受和庆祝个人的小成就。
所以,是的,很明显失败是可能的,而且也不是特别难。但话说回来,避免这些问题也不是特别难。
如何在这方面取得成功
选择一个过程并坚持下去
有大量很好的资源提供了对机器学习概念的全面介绍。一个众所周知的选择是 T2 吴恩达在 Coursera 上的课程。另一种选择是由 fast.ai 提供的。决定没有对错之分——两者都有很好的声誉,每门课程提供的教学风格都与其他课程略有不同。
这里突出的一点是,你应该尽一切努力坚持单一的学习课程。当你面对你不理解的东西时,转换课程在统计学上有意义的一段时间内,一般情况下不太可能产生有意义的进步。解决方案不是“亚马逊的又一本书”或“一个不同的、不太技术性的教程”在某种程度上,你只需要全力以赴,咬紧牙关,努力向上到达学习曲线的右侧。
非常明确地说,我是而不是建议你不要用外部资源补充你自己的学习努力,或者当你有问题时参考第三方资料。我的意思是,在某个时候,随着你越来越深入,你会遇到一些难以理解的概念,因为它们实际上是很难理解的概念。拥抱困难,这是你推动自己超越舒适区的标志,舒适区是这个世界上所有值得讨论的事情发生的地方(根据我的经验)。改变课程、书籍或视频系列并不是一个可行的长期学习策略,而是一种寻找“银弹”的心态如上所述,没有灵丹妙药,没有捷径——有的只是努力工作。
选择一个框架并坚持下去
现在不是拿 TensorFlow 跟 PyTorch 跟 MXNet 等比较对比的时候。作为一个完全的初学者,你没有足够的知识或理解任何这些框架的实现的问题空间,因此任何这样的决定都不是另一个思维过程的回流。
选择一个拥有大型活跃开发社区的主流框架,并坚持下去。在这一点上,专注于学习总体概念,避免兔子洞,即一年后可能相关或不相关的给定框架的细节。
记住“这就像法语”
如果你曾经被要求学习一门外语,很可能你已经遇到了性别名词的概念。非常简单地说,在许多语言中(其中英语不是之一),某些名词不是阳性就是阴性。举例来说,从这篇文章(我的重点是增加的)中摘录。
有一些名词表示具有性别的实体,它们只有一种形式,使用时不考虑实体的实际性别,例如,**表示人的单词;personne;永远是女性化的,即使这个人是男性,而老师这个词;教授;即使老师是女的,也永远是男性**。
关键是,正如试图理解一个人无论性别为何总是女性化的逻辑是一项徒劳的工作(答案不可避免地是“它就是这样——接受它作为一篇真理并继续前进”),试图在第一遍中理解机器学习的一切根本不是一个合理的期望。有些事情你暂时只能相信。
这并不是说你没有注意到这个问题,以便在以后的某个时间点进行进一步的研究,但是每当你遇到你不理解的东西时,试图学习你不理解的所有东西只是上面讨论的“你打算学习所有的机器学习”的一个聪明的变体。
不管你更好的天使可能会告诉你什么,你试图钻研细节的动力是而不是帮助你学习。事实上,恰恰相反,因为这些兔子洞只是潜在地拖延时间,直到你对更大的图景有了坚实的理解和基础,为更有意义的探索提供了必要的背景。
建立工具集和可重复的工作流程
对于任何一个工具或工作流的细节,我没有什么特别有趣的(当然也没有什么原创的)可以补充,除了说拥有一套你熟悉的、舒适的、相当可靠的工具是很重要的。
从 Google Cloud 到 AWS 到 Azure 到 Jupyter 笔记本到 Vim、Emacs、VSCode 等的插件,有多种有据可查的解决方案。截至 2019 年下半年,为单个开发人员建立行业级机器学习管道是非常实惠的,也是有据可查的。
找一个像样的笔记软件
我认为这没有得到足够的重视。即使在这个旅程的最初阶段,你也会被信息轰炸,有些你能掌握,有些你不能。如上所述,鉴于我们的知识状况,有些事情你暂时必须相信。但是你绝对应该注意那些你不理解的概念,这样当你有更多的背景知识时,你最终可以做真正需要的深入研究。
我个人使用 Coggle ,但是冒着重复让你厌烦的风险,这并不是关于你选择的工具。文本文件、Markdown 文件、Jupyter 笔记本、OneNote、Evernote 等。都会管用。我个人的偏好源于我更喜欢“思维导图”风格的图表。相对于层次结构的格式(例如在大纲中),我经常发现这与我头脑中的材料的心智模型不一致。思维导图允许我以相当任意的模式将节点连接到其他节点,这允许我以一种对我的大脑更自然的方式记录事情。
学会接受失败是一种正常的休息状态
如果你正在从软件工程以外的东西过渡到机器学习,这可能看起来不直观。简单地说(不仅仅是开玩笑),这项工作的绝大部分可以通俗地描述为“让您的代码编译”,顾名思义,这意味着大部分时间,您的代码处于非工作、失败状态。
当然,作为人类,我们尽我们所能,通过确保错误以粗体、鲜红色显示,并伴有表明你从事不法行为的图标等,来加剧他人和自己的不足感。
事实上,这项工作的一个方面,就像软件工程(在观察了很多数据科学家的工作后,我觉得这样说很舒服),代表了一个有点乏味的实验、错误识别和修复,然后是进一步实验的循环。如果你没有坚韧不拔的精神、建设的动力和天生的好奇心来支撑你度过那些时刻,这可能不适合你。
结束语
成为一个机器学习初学者远不是一件简单的事情,但是,没有什么值得做的事情是简单的。
我给你们留下一个简单的思想实验——如果* (i) 数据科学是美国发展最快的工作 (ii) 只有拥有数据科学背景的人才能胜任那份工作,那么(I)*怎么可能是真的呢?它怎么可能是发展最快的工作呢?**
换句话说,如果第一个(我认为是虚假的)论断是真的,难道不会有很多人因为某种原因,恰好拥有一个十年前并不存在的行业所需的完美技能。这看起来可能吗?
或者更合理的解释是,像你们和我这样有能力的人在这个领域交叉培训和发展新技能,正是因为这些技能实际上是可以获得的?
我把它作为一个练习留给好奇的读者。
脚注
注意:除了我现在的雇主临床数据科学中心之外,我与本文中提到的任何组织都没有关联和/或附属关系。截至本文撰写之时,我没有从任何提及的公司(除了我的雇主)处获得任何折扣或其他优惠,而这些折扣或优惠是任何持有有效信用卡的人无法公开获得的。
[1]为了完全公开,我正在完成 fast.ai 课程。在简要评估了 fast.ai 课程和吴恩达的课程后,我决定 fast.ai 方法会更好地为我服务。我喜欢“自上而下”的方法,一般来说,你从“做”开始,然后到“理解”。
[2]我个人使用谷歌云平台和他们的人工智能笔记本服务,但我也使用过 AWS SageMaker,并对此感到满意。
开始实时复制自然对话
原文:https://towardsdatascience.com/beginning-to-replicate-natural-conversation-in-real-time-d4f6b7f62e08?source=collection_archive---------14-----------------------
进入文学的第一步
为了开始我的新项目,我首先要做的当然是浏览当前的研究和最先进的模型。
最近我接受了采访,在采访中我用 Wallscope 解释了这个新项目,但简而言之(非常短):我的目标是让对话代理人更自然地交谈。
我并没有穷尽这一领域的所有文献,我只是触及了皮毛(如果你知道我必须阅读的相关论文,请在下面链接)。这里是一些研究的概述和走向更自然的对话代理的旅程。在这方面,我将参考以下文件:
[1]
马修·罗迪、加布里埃尔·斯坎茨和娜奥米·哈特利用 LSTMs 研究连续话轮转换预测的语音特征
[2]
由 Divesh Lala、Koji Inoue、Pierrick Milhorat 和 Tatsuya Kawahara 开发的用于识别人机交互参与的社交信号检测
[3]
朱利安·霍夫(Julian Hough)和大卫·施朗根(David Schlangen)利用实时、真实世界的基础策略研究人机交互的流畅性
[4]
Angelika Maier、Julian Hough 和 David Schlangen 的走向情景口语对话系统的深层话轮结束预测
[5]
Gabriel skan tze 的《人机对话中的协调》( 2019 年 3 月 7 日在格拉斯哥的演讲)
内容
简介
转弯结束-转弯预测
接合
实施例
流体增量接地策略
结论
介绍
如果我们想到两个人进行流畅的对话,这与人类与 Siri、谷歌助手、Alexa 或 Cortana 之间的对话非常不同。
source
流量损失的一个原因是大量的暂停。对于一个会话代理(CA)来说,如果它检测到你已经说完了你正在说的话(完成了你的话轮),它会等待一段时间的静默。如果它检测到长时间的停顿,它会认为你已经完成了你的话轮,然后处理你的话语。
不同系统之间设置的静默持续时间略有不同。如果它设置得太低,CA 会在中途打断你,因为人类的对话充满了停顿。如果设置的太高,系统会更准确的检测到你的回合结束,但是 CA 会花费很长的时间来响应——扼杀了对话的流畅,让用户感到沮丧。
当两个人说话时,我们倾向于尽量缩小话轮之间的差距,这是跨文化的。在全球范围内,转弯之间的间隔大约为 200 毫秒,接近人类反应时间的极限[1]。因此,在听别人说话时,我们必须预测说话者的话轮结束。
转弯-转弯结束预测
要重现这种流畅的对话,在 CAs 中使用快速切换和轻微重叠,我们必须首先了解我们自己是如何做到的。
不要脸,但略有关联,自我推销。为了研究计算机视觉,我们必须先了解人类视觉
我们下意识地解读话轮转换的暗示来检测什么时候轮到我们说话,那么我们使用什么暗示呢?类似地,我们在听别人说话时不断地这样做,那么我们能重现这种递增的过程吗?
[4]使用声学和语言学特征训练 LSTM 来标记 10ms 窗口。他们的系统的任务是将这些窗口标记为语音、中途停顿(MTP)或 EOT,但主要焦点当然是标记为 EOT 的序列中的第一点。
LSTM 中使用的声学特征是:原始音高、平滑后的 F0、均方根信号能量、对数信号能量、强度、响度以及作为声学特征的每一帧的衍生特征。
除了这些声学特征之外,语言特征由单词和称为加权平均对数三字组概率(WML)的增量句法概率的近似值组成。
许多其他的信号被识别来指示说话者是要继续说话还是已经完成了他们的话轮[5]:
[5]
如前所述,等待 10 秒钟的响应就像 CA 不停地在你中途切入一样令人恼火[4]。因此,在 50 毫秒和 6000 毫秒之间定期考虑多个基线,以确保基线中包含多个权衡。
除了一个案例(只有语言特征,500 毫秒沉默阈值),每个模型都超过了基线。仅使用语言或声学特征不会产生太大的差异,但是当模型同时使用两组特征时,性能总是最佳的。最好的整体系统的延迟为 1195 毫秒,切入率仅为 18%。
[4]
[1]陈述了我们从多模态信号预测 EOT,多模态信号包括:韵律、语义、句法、手势和眼睛注视。
传统模型不是标记 10ms 窗口(如语音、MTPs 或 EOTs ),而是预测说话者是继续说话(保持)还是完成了他们的话轮(转换),但只有在检测到暂停时才会这样做。这种传统方法的一个主要问题是,反向信道既不是保持也不是转移,而是无论如何都要预测其中之一。
LSTMs 已经被用于以 50 毫秒的间隔连续进行预测,并且当应用于保持/移位预测时,这些模型优于传统的 EOT 模型,甚至优于人类。它们的隐藏层允许它们学习长期相关性,但是不知道哪些特征对性能影响最大。
在[1]中,新系统完成了三个不同的话轮转换预测任务:(1)停顿时的预测,(2)开始时的预测,(3)重叠时的预测。
暂停时的预测是在交互中的短暂暂停时发生的标准预测,用于预测是否会有暂停或转换。本质上,当暂停超过阈值时间时,具有最高平均输出概率(得分)的人被预测为下一个发言。这个分类模型用加权 F 分数进行评估。
开始时的预测对讲话过程中的话语进行分类,而不是在停顿时。然而,该模型略有不同,因为它预测当前正在进行的话语是短还是长。同样,作为一个分类器,这个模型使用加权 F 值进行评估。
首次引入重叠预测。这本质上又是一个保持/移位预测,但是当至少 100 毫秒的重叠周期出现时。当重叠是反向信道时,预测保持(继续讲话)的决定,并且当系统应该停止讲话时,进行转换。这再次使用加权 F 分数进行评估。
下面是一个预测话轮转换的例子:
如上所述,我们并不确切知道我们使用哪些特征来预测何时轮到我们发言。[1]在不同的排列中使用了许多特征来区分哪些是最有用的。所使用的特征如下:
声学特征是低级描述符,包括响度、摆振、音调、抖动、频谱通量和 MFCCs。这些是使用 OpenSmile 工具包提取的。
语言特征从词性(POS)和词两个层面进行考察。文献通常表明,POS 标签擅长预测转弯开关,但是需要单词(来自 ASR 系统)来提取 POS 标签,因此检查是否需要这种额外的处理是有用的。
对于需要实时运行的系统来说,使用单词而不是 POS 将是一个很大的优势。
语音特征从对语音进行分类的深度神经网络(DNN)中输出。
声音活动包含在他们的转录中,因此也被用作一个特征。
那么根据[1],什么特征对 EOT 预测最有用呢?
声学特征对于 EOT 预测非常有用,除了一个实验外,所有实验最佳结果都包括声学特征。对于重叠处的预测尤其如此。
除了开始时的预测,单词的表现大多优于词性标签,所以如果你想预测话语长度(如反向通道),请使用词性标签。
在所有情况下,包括声音活动在内的活动都提高了表现。
在声学特征方面,最重要的特征是响度、F0、低阶 MFCCs 和频谱斜率特征。
总体而言,通过使用声音活动、声学特征和单词获得了最佳性能。
如前所述,使用单词而不是 POS 标签会带来更好的性能,这一事实对于更快的处理来说是非常好的。这当然有利于实时增量预测——就像我们人类所做的那样。
所有这些特征不仅用于检测我们下一次说话的时间,甚至用于指导我们说什么。我们将根据对方对我们所说内容的参与程度,扩展我们所说的内容,跳过细节或改变话题。
因此,为了模拟自然的人类对话,CA 测量参与度是很重要的。
约会
参与度表示对对话的兴趣和关注,因为我们希望用户保持参与,所以会影响 CA 的对话策略。这种用户体验的优化必须实时完成,以保持流畅的对话。
[2]检测以下信号来衡量参与度:点头、笑声、口头暗道和眼睛凝视。这些信号显示注意力和兴趣的事实相对来说是常识,但却是从大量人机交互中习得的。
[2]
[2]不仅专注于识别社交信号,还致力于创建参与度识别模型。
这个实验是在日本进行的,在那里点头是非常普遍的。提取了七个特征来检测点头:(每帧)人头部的偏转、滚动和俯仰(每 15 帧)人头部的平均速度、平均速率、平均加速度和范围。
他们的 LSTM 模型在检测点头的所有指标方面都优于其他方法。
微笑经常被用来检测参与度,但为了避免使用相机(他们使用麦克风+ Kinect) 笑声反而被检测到。每个模型的任务是对声音的间歇期单位(IPU)是否包含笑声进行分类。使用韵律和语言特征来训练两层 DNN 执行得最好,但是使用其他频谱特征而不是语言特征(不一定可从 ASR 获得)可以用于改进模型。
与点头类似,口头暗语在日本更为频繁(称为会内)。此外,在日本,口头反馈通常伴随着头部运动,但只有声音提供给模特。类似于笑声检测,该模型对 IPU 是否是一个反向通道或该人是否开始轮到他们进行分类(当闯入时尤其困难)。发现表现最好的模型是随机森林,有 56 个估计器,使用韵律和语言特征。当只给定韵律特征时,该模型仍然合理地执行(再次因为语言特征可能无法从 ASR 获得)。
最后,的眼神俗称订婚的明确信号。根据注释者之间的协议,连续注视 Erica 的头部(本实验中的机器人实施例)10 秒钟被视为参与。因此,少于 10 秒是阴性病例。
Erica: source
来自 kinect 传感器的信息用于根据用户的头部方向计算一个向量,如果该向量与 Erica 的头部发生碰撞(加上 30cm 以适应误差),则用户被视为“在看 Erica”。这种基于几何的模型工作得相对较好,但 Erica 的头部位置是估计的,所以这将影响结果。预计当确切的数值已知时,该模型将得到显著改进。
本文的目的不是创建最佳的单个系统,而是假设这些模型结合起来会比单个模型在检测参与度方面表现得更好。
[2]
上述模型的集合被用作二元分类器(一个人是否参与)。特别是,他们建立了一个分层贝叶斯二元分类器,从上述 4 个模型的 16 种可能的输出组合中判断听者是否参与。
从注释器中,构建了一个模型来推断在检测参与时哪些特性更重要或更不重要。例如,一些注释者发现笑声是一个特别重要的因素,而其他人则不这么认为。他们发现输入一个包含三种不同字符类型的字符变量可以提高模型的性能。
此外,包括听众的先前参与也改进了模型。这是有道理的,因为目前不感兴趣的人在你下一轮更有可能保持不感兴趣。
衡量参与度只能在体现 CA 时才能真正做到(例如,与 Siri 的眼神交流是不存在的)。社交机器人越来越多地用于教学、公共场所、医疗保健和制造业等领域。这些都可以包含口语对话系统但是为什么一定要具体化呢?
[5]
典型,化身
当人们只需打个电话就能进行面对面的交流时,他们会走遍全球。我们不喜欢在看不到对方的情况下互动,因为我们错过了上面谈到的许多信号。在今天的世界里,我们也可以进行视频通话,但出于同样的原因,在可能的情况下还是要避免这样做。电话交谈或面对面交谈的区别类似于与 Siri 和嵌入式对话系统交谈的区别[5]。
目前的语音系统无法显示面部表情,通过眼神交流或移动嘴唇来表示注意。唇读对于听力受损的人来说显然非常有用,但我们在交谈时都会读唇(这就是我们如何知道人们在说什么,即使在非常嘈杂的环境中)。
一张脸不仅可以输出这些信号,它还允许系统检测谁在说话,谁在注意,真实的人是谁(Rory,Jenny 等),并识别他们的面部表情。
然而,机器人的脸有很多种形式,有些更适合在对话中使用。大多数机器人的脸,如 Nao 的脸,都是非常静态的,因此无法像我们一样通过表情来表达广泛的情感。
Nao: source
一些更抽象的机器人面部描述,如 Jibo,可以使用形状和颜色来表达情感,但有些表情必须学习。
Jibo: source
我们知道如何解读人脸,所以展示人脸是有意义的。超逼真的机器人脸是存在的,但有点令人毛骨悚然,像索菲亚,而且非常昂贵。
Sophia: source
他们非常现实,但不完全正确,这使得谈话非常不舒服。为了解决这个问题,虚拟人物被设计成可以在屏幕上对话。
source
这些机器人可以相对接近地模仿人类,而不会令人毛骨悚然,因为它不是一个物理机器人。这几乎和 Skype 一样,但是这种方法有“蒙娜丽莎效应”。在多方对话中,屏幕上的头像不可能只看一个人而不看另一个人。这个化身要么是在看所有的聚会,要么是不看任何人。
gabrial skan tze ([ 5]的演示者)是 Furhat robotics 的联合创始人,他认为 Furhat 是所有这些系统之间的最佳平衡。Furhat 已被开发用于对话应用,如接待员、社会培训师、治疗师、采访者等
source
Furhat 需要知道它应该看哪里,什么时候应该说话,应该说什么,应该展示什么面部表情[5]。
最后(就目前而言),一旦具体化,与机器人的对话需要与现实世界实时联系。在[3]中,给出的例子是在工业机器中实现的 CA ,[ 5]指出这变得越来越普遍。
source
流畅、渐进的接地策略
为了使对话自然,人机对话必须以流畅的方式为基础。
使用非增量接地,用户可以给出积极的反馈并进行修复,但只有在机器人完全理解请求之后。例如,如果你让一个机器人移动一个物体到某个地方,你必须等到这个物体被移动后,才能用类似“不,移动那个红色的”这样的话语来纠正它。没有重叠的语音是可能的,所以如果需要修复,动作必须完全颠倒。
使用增量接地,重叠仍然是不可能的,但是可以以更有规律的间隔给出反馈。反馈可以在子任务间隔给出,而不是在给出反馈之前完成整个任务。“不,移动红色的那个”可以在机器人捡起一个蓝色物体后说,快速修复。在前面的例子中,蓝色物体被放置在一个给定的位置,然后才能进行修复,这导致了整个任务的逆转!这更有效,但仍然不像人与人之间的互动那样流畅。
如果重叠被处理,流体增量接地是可能的。允许并发的言语和动作并进行推理要自然得多。继续我们的修复示例,“不,移动红色的”可以说是机器人一要拿起蓝色物体,就不必完成和反转任何任务,因为并发是允许的。拾取任务可以被中止,红色物体被流畅地拾取,就像你说的那样。
[2]
为了实现这种更加流畅的基础,需要进行实时处理。系统不仅需要一个字一个字地处理话语,还需要监控实时上下文,例如机器人的当前状态和计划的动作(这两者都可以在话语或单词的过程中动态变化)。
机器人必须知道什么时候它已经充分展示了它正在做什么来处理修理和确认。机器人需要知道用户在确认什么,更重要的是,需要修复什么。
结论
在这个简短的概述中,我只涉及了当前朝着更自然的对话系统发展的一小部分工作。
即使话轮转换预测、参与度测量、具体化和流体基础都很完善,CAs 也不会像我们人类一样进行对话。我计划在接下来的几年里写更多这样的综述,所以如果感兴趣的话,请留意它们。
与此同时,请对讨论点进行评论,批评我的理解,并提出我(以及任何阅读本文的人)可能会感兴趣的论文。
从 R 开始——未知的领域
原文:https://towardsdatascience.com/beginning-with-r-the-uncharted-territory-d35eaffff3f3?source=collection_archive---------29-----------------------
我来自非编程背景,并且 python 是第一次接触编程和数据分析,试图在 R 中动手似乎一开始就相当令人生畏。r 有时会感觉有点奇特和独特,因为它是基于进行数据分析和统计的前提,而不是像 python 那样的软件编程。但是,当我鞭策自己,努力学习 R 相对于 python 的许多特点和优势时,它在某种程度上提供了进行数据分析的不同视角。此外,与 python 相比,使用 R 有一个很强的优势——世界各地的统计学家都在用 R 实现各种统计方法的庞大而现代的库。
除了它的怪癖之外,迄今为止为 R 开发的最有趣的 IDE—R studio让数据分析看起来像是有趣的活动。Rstudio 中的各种其他东西,如使用 LaTex 和 HTML 制作报告,以及使用 HUGO 制作静态网站,都让生活变得非常简单。
但是为了能够做所有这些很酷的事情,我们需要首先掌握 R 的基础知识,这是任何复杂的数据分析管道的构建块。那么我们开始 r 的旅程吧。😃
目录
- R 简介
- r 数据类型
- 处理未定义的值
- 经营者
- 逻辑运算符
- 数据结构—列表、向量、矩阵、数组、因子、数据框
R 简介
r 是一种主要为统计计算和可视化而开发的动态语言。它包括各种统计和机器学习包,易于学习和用于数据分析。
r 数据类型
当在 R workspace 中创建一个变量时,R 会自动将数据类型赋给该变量。
**#***# [1] 4.2***#***# [1] "Hello!"*
要检查变量的类型,使用typeof()
**#***# [1] "double"***#***# [1] "character"*
基本数据类型有
- 字符串/字符
- 数字
整数
双精度
复数 - 布尔/逻辑
无论是整数还是浮点数,都总是用 double 表示。
**#***# [1] "double"*
对于整数的明确要求,添加后缀 L
**#***# [1] "integer"*
处理未定义的值
处理未定义/缺失的值与 python 略有不同。Python 只有NaN
值作为未定义/缺失值。在 R 中,未定义的值基本上用
- 空
- 钠
- 圆盘烤饼
三者的工作方式不同。
NULL 是一个空对象,在没有值时使用。如果向量或矩阵中存在某个值,并且该值不可用(fill_value),我们使用 NA 或 NaN。
NA 或 NaN 缺少值指示符。
**#***# [1] "NULL"***#***# [1] "logical"***#***# [1] "numeric"*
当没有真或假,即逻辑不确定性时,NA 出现。它也可能是丢失的值。
NaN 表示 0/0
经营者
- 乘法( ***** )
- 分部( / )
- 加法( + )
- 减法( - )
- 指数( ^ )
- 模数( %% )
- 整数除法( %/% )
逻辑运算符
- 不(!)
- 元素明智与( & )
- 还有( & & )
- 元素方面的 OR ( | )
- 或者( || )
- 在集合中(%在% )
数据结构
在 R 中有 6 种类型的数据结构
- 列表
- 向量(或原子向量)
- 矩阵
- 数组
- 因素
- 数据帧
列表
R 中的 List 可以保存不同类型的元素。没有强迫。列表可以包含数字、字符、布尔、矩阵、向量、数组、列表等。
要创建列表,请使用list()
参数。
**#***# [[1]]*
**#***# [1] "green"*
**#***#*
**#***# [[2]]*
**#***# [1] "yellow"*
**#***#*
**#***# [[3]]*
**#***# [1] 1*
**#***#*
**#***# [[4]]*
**#***# [1] 2*
**#***#*
**#***# [[5]]*
**#***# [1] 4 5 6*
要给列表中的每个条目命名,使用names()
参数。
使用$
访问列表中的特定条目
**#***# [1] "green"***#***# [1] "yellow"*
**#***# $A*
**#***# [1] "green"*
**#***# [1] "green"*
要合并两个或多个列表,使用c()
**#***# [[1]]*
**#***# [1] 1*
**#***#*
**#***# [[2]]*
**#***# [1] 2*
**#***#*
**#***# [[3]]*
**#***# [1] 3*
**#***#*
**#***# [[4]]*
**#***# [1] 4*
**#***#*
**#***# [[5]]*
**#***# [1] 5*
**#***#*
**#***# [[6]]*
**#***# [1] 6*
**#***#*
**#***# [[7]]*
**#***# [1] 7*
**#***#*
**#***# [[8]]*
**#***# [1] 8*
r 中的一些预定义列表。
**## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q"**
**## [18] "r" "s" "t" "u" "v" "w" "x" "y" "z"****## [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q"**
**## [18] "R" "S" "T" "U" "V" "W" "X" "Y" "Z"****## [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov"**
**## [12] "Dec"****## [1] "January" "February" "March" "April" "May"**
**## [6] "June" "July" "August" "September" "October"**
**## [11] "November" "December"**
向量
为了创建一个矢量,我们使用c()
函数。它基本上像 python 中的列表一样连接东西。
**## [1] "1" "2" "3" "4" "5.4" "hello" "TRUE" "FALSE"**
正如我们所见,向量可以有任何数据类型,可以是数字、字符或布尔值。但是我们注意到了一些事情。vector 中的所有元素都被强制为字符类型,因为 vector 包含一个字符串"hello"
。这就是隐性强制的效果。
对于严格意义上的数字向量,使用vector()
功能。
**#***# [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0*
我们可以使用这样一个向量来预分配一个向量,该向量可用于从一个for
循环中追加值,这比将值追加到一个空向量中要快,因为每次一个值被追加到一个空向量中时,R 都会复制它,从而减慢整个过程。
强制——矢量、数据帧等对象。可以使用as.class
功能强制到不同的类别。
**#***# [1] "numeric"***#***# [1] "character"***#***# [1] "logical"*
矩阵
矩阵与向量相同,只是它有一个额外的维度属性。它是一个二维数据结构。
**#***# [,1] [,2] [,3]*
**#***# [1,] 6 8 6*
**#***# [2,] 2 3 8*
**#***# [3,] 6 2 0***#***# $dim*
**#***# [1] 3 3*
矩阵开始按行填充。而在 python 中,矩阵开始逐列填充。
在 R 中,我们可以传递行和列的名称。
**#***# x y z*
**#***# a 6 8 6*
**#***# b 2 3 8*
**#***# c 6 2 0*
**## [1] "x" "y" "z"****## [1] "a" "b" "c"**
要访问矩阵的元素,请使用方括号。
**#***# [1] 3***#***# x y*
**#***# b 2 3*
**#***# c 6 2*
但是a[2,]
(第二行)或a[,2]
(第二列)给出了一个向量,即它试图返回最简单的数据结构。为了避免这种情况,即获得一个矩阵,使用drop = FALSE
**#***# x y z*
**#***# 2 3 8***#***# NULL*
**#***# x y z*
**#***# b 2 3 8***#***# [1] 1 3*
也可以进行特定的索引。
**#***# [1] 6 2 8 2*
你也可以使用逻辑向量做索引。
**#***# x y*
**#***# a 6 8*
**#***# c 6 2*
使用t(a)
转置矩阵
要组合矢量或矩阵,使用rbind
或cbind
矩阵维度也可以改变(整形)。
**#***# [1] 1 9*
数组
数组是一个可以保存多维数据的对象。矩阵是数组的子集,因为它们是二维数组。因此,除了维度属性dim
之外,数组还具有属性dimnames
。数组只是一个多维数据结构。
它的语法是a <- array(data, dim = c(x,y,z,t...))
**#***# , , 1*
**#***#*
**#***# [,1] [,2] [,3] [,4]*
**#***# [1,] 1 4 7 10*
**#***# [2,] 2 5 8 11*
**#***# [3,] 3 6 9 12*
**#***#*
**#***# , , 2*
**#***#*
**#***# [,1] [,2] [,3] [,4]*
**#***# [1,] 13 16 19 22*
**#***# [2,] 14 17 20 23*
**#***# [3,] 15 18 21 24*
**#***# , , 1*
**#***#*
**#***# [,1] [,2]*
**#***# [1,] 10 30*
**#***# [2,] 20 40*
**#***#*
**#***# , , 2*
**#***#*
**#***# [,1] [,2]*
**#***# [1,] 12 14*
**#***# [2,] 13 15*
要定义不同尺寸的标签,使用dimnames
**#***# , , g*
**#***#*
**#***# d e*
**#***# a 10 30*
**#***# b 20 40*
**#***#*
**#***# , , h*
**#***#*
**#***# d e*
**#***# a 12 14*
**#***# b 13 15*
**#***# , , 1*
**#***#*
**#***# [,1] [,2] [,3]*
**#***# [1,] 1 4 7*
**#***# [2,] 2 5 8*
**#***# [3,] 3 6 9*
**#***#*
**#***# , , 2*
**#***#*
**#***# [,1] [,2] [,3]*
**#***# [1,] 10 13 16*
**#***# [2,] 11 14 17*
**#***# [3,] 12 15 18*
**#***#*
**#***# , , 3*
**#***#*
**#***# [,1] [,2] [,3]*
**#***# [1,] 19 22 25*
**#***# [2,] 20 23 26*
**#***# [3,] 21 24 27*
**#***# $dim*
**#***# [1] 2 2 3***#***# , , 1*
**#***#*
**#***# [,1] [,2]*
**#***# [1,] 1 4*
**#***# [2,] 2 5*
**#***#*
**#***# , , 2*
**#***#*
**#***# [,1] [,2]*
**#***# [1,] 10 13*
**#***# [2,] 11 14*
**#***#*
**#***# , , 3*
**#***#*
**#***# [,1] [,2]*
**#***# [1,] 19 22*
**#***# [2,] 20 23*
因素
对于分类数据的表示,R 有称为因子的特定对象。因子基本上是整数,并且有与之相关联的标签。因此,特定数量的因素与特定的标签相关联。这些标签被称为级别。因子看起来像字符,但实际上是整数。因子的其他用途是根据一个分类数据集对所有分类数据集进行排序。
factor()
命令用来创建一个因子对象。
**#***# $levels*
**#***# [1] "apple" "banana" "orange"*
**#***#*
**#***# $class*
**#***# [1] "factor"*
默认情况下,这些级别是无序的。要订购它们,您可以定义级别。
**#***# $levels*
**#***# [1] "apple" "orange" "banana"*
**#***#*
**#***# $class*
**#***# [1] "factor*
数据帧
数据帧用于存储表格数据。长度相等的列表存储在数据帧中。
**#***# city rank*
**#***# 1 Jaipur 2*
**#***# 2 Jammu 3*
存储的数据可以是不同的类型。一列可能是字符,另一列可能是因子等等。但是每一列必须有相同类型的数据。