TowardsDataScience-博客中文翻译-2020-十九-
TowardsDataScience 博客中文翻译 2020(十九)
在 Python 中自动更新数据源
数据科学基本 Python 指南
以新冠肺炎数据集为例的分步指南
由 Chaeyun Kim 更新数据集 Python 插图
在 Data Sciences 中,很多时候,您会从开源网站或 git 存储库中为您的 Python 项目获得一个外部数据源,比如一个 csv 表。其中一些数据集可能会定期更新。然后,您可能会在运行 Python 脚本以获得最新结果之前,打开 web 浏览器下载数据集。本文将向您展示一个基本指南,告诉您如何自动化这个过程,以一种简单的方式保持您的数据是最新的。
从网站(URL)更新数据集
可以从 URL 中检索几个开源数据集。您可以使用urllib
模块直接在 Python 中打开并读取 URL 。它是大多数 Python 版本中预装的模块。所以你可以导入这个模块,使用下面的代码从任何 URL 下载数据。
**import urllib.request****url = '***<Your URL Here>***'
output = '***<Your output filename/location>***'
urllib.request.urlretrieve(url, output)**#.. Continue data analysis with updated output file
例如,下面的示例脚本显示了从罗伯特·科赫研究所(RKI,德国疾病控制和预防研究机构)更新德国新冠肺炎数据的示例。该数据为 csv 格式,可通过此 URL 获取。在实际操作中,一些URL可能会随着时间的推移而改变或贬值,这使得 Python 脚本运行出错,因此我们可以包含try/except
来检查 URL 是否仍然有效。假设你想保存下载文件的所有版本,你可以使用datetime
模块给输出文件名添加一个时间戳。
从 URL 下载文件的 Python 脚本示例(示例:来自 RKI 的新冠肺炎案例,使用 Python3.8)
*请注意,如果使用 macOS,应该先安装 Python 证书,然后才能使用urllib
库。你可以通过运行 Macintosh HD>Applications>python 3 . x 文件夹中的install certificates.command
文件轻松做到这一点。
从 Git 存储库更新数据集
如果您的 python 项目依赖于来自 git 存储库的数据。在您克隆存储库并将数据集获取到您的本地机器之后,您可能需要定期执行 git fetch 或 pull 来保持您的数据集是最新的。在这种情况下,您可以使用GitPython
模块自动更新您的项目数据集。要使用这个模块,你必须先安装它,你可以很容易地使用pip
这样做。
**pip install gitpython**
如果遇到错误,您可以查看完整的 GitPython 文档来检查您的操作系统环境可能没有的需求。安装完模块后,您可以轻松地按照这些代码在每次运行代码时自动执行 git pull。
**import git****repo = git.Repo('<your repository folder location>')
repo.remotes.origin.pull()**#... Continue with your Code.
例如,JHU·CSSEGithub 仓库提供了csv
格式的新冠肺炎时间序列数据集,这些数据集每天都在更新。将存储库克隆到您的机器上之后,您可以将上述代码添加到 Python 脚本的开头,以便每次都自动获取最新版本。这样,您可以确保您的结果是最新的。
一些提示
对于 git 认证,如果您使用ssh
,这将非常简单。如果您使用HTTPs
,将您的用户名和密码保存到您的环境中会更方便。在 Mac 和 Windows 中,首次输入后会自动存储鉴定信息。在 Linux 中,您可以通过更改凭证超时来强制机器记住您的凭证。例如,您可以使用以下命令让您的计算机记住您的凭据一年。(31536000 秒)
$ **git config --global credential.helper 'cache --timeout=31536000'**
作者单词
本文展示了在 Python 脚本的开头直接从任何 URL 或 git 存储库更新数据集的分步指南。这样,您可以确保基于最新的数据集运行脚本。
我希望你喜欢这篇文章,并发现它对你的日常工作或项目有用。如果您有任何问题或意*,请随时给我留言。
关于我&查看我所有的博客内容:链接
安全健康健康吗!💪
感谢您的阅读。📚
自动化类比:通过人工智能识别跨领域的意义
通过揭示类比联系促进科学发现
介绍
在最近的《自然》杂志文章中,研究人员使用单词嵌入来发现材料科学的候选化合物。其中一名作者 Vahe Tshitoyan 也发表了一篇关于介质的综述。具体来说,他们表明新的热电材料可以通过挖掘科学期刊来发现。
我认为这是著名的单词嵌入技术的一个有趣的应用。使用单词嵌入,我们希望为文档中的重要单词创建矢量表示。一旦矢量化,这些单词就可以用于线性代数中常*的向量运算。因此,我们可以通过加和减单词来找到符合我们直觉的结果。常*的例子是“king” minus “queen” approximately equals “man” minus “woman”
。
矢量化的单词还允许我们匹配在某种潜在意义上与相似的单词。例如,父亲和母亲会比鸡和钱彼此更亲近。这意味着单词向量可以用来捕获复杂的概念,而无需显式编码这些概念。
我认为这将是一个很好的应用。一个人们可以用来搜索与他们的研究相关的术语的工具。该工具将返回最近在各种领域发表的文章,这些文章包含与用户搜索词相似的词。
重要的是,相似性是“类比驱动”的,因为这种联系不是偶然观察就能明显看出的。这个词在其他文章中找不到,相反,其他文章只是在类似的背景下讨论一些事情。在上面提到的《自然》杂志的文章中,新的热电材料可能会被发现,因为其他论文正在以类似于人们讨论热电材料的方式讨论一些事情;但是其他文章里没有提到热电这个词。
为了理解单词嵌入在这个应用中做了什么,我们必须掌握它们如何与类比的概念相关联。我写过关于类比的力量的文章,before⁵,我强烈推荐 Douglas Hofstadter 的作品。
对于单词向量,我们看到线性行为,例如“woman is to queen as man is to king”
。这些已经被证明是类比 phenomenon⁴.的基础
在参考文献 4 中,他们表明逐点互信息 (PMI)矩阵的因式分解导致嵌入中的线性相似结构。从概率的角度来看,当词集在所谓的上下文词上引起等价分布时,它们会相互释义。作者通过表明“释义”对应于通过单词转换的类比,将这一点扩展到类比。
深入研究数学细节超出了本文的范围。请问我是否想更详细地讨论类比背后的数学。我鼓励在 Twitter 上进行这些对话,这样其他人也能受益。
“语境”是影响其含义的语句前后的词语。当我们在两个不同的领域之间进行类比时,我们认识到了一些潜在的相似性。
“从一个人和什么样的人交往,你就可以知道他是什么样的人”——弗斯
这就是一直以来的发现。人类通过意识到看似不同的领域之间的潜在联系,将它们联系起来。只有通过阅读其他作者的作品才能建立这种联系。
但是研究人员阅读自己领域之外的论文的可能性有多大呢?在阅读自己领域的论文、教学和撰写资助之间,不太可能。
研究人员多长时间审查一次他们领域之外的论文?
这意味着研究者的工作和其他出版物之间潜在联系的财富在很大程度上还没有被开发。如果人工智能可以提供一种方法来自动发现各种领域之间的类比联系,这将非常有用。将这种能力转化为产品可以帮助学术和独立研究人员做出他们可能会错过的发现。
以此为动机,让我们拼凑一个产品,帮助研究人员在他们的工作和许多不同的 STEM 领域之间建立联系。
注意:我并不声称本文中的应用程序是真正的发现。充其量,该应用程序可能会根据研究人员领域之外的上下文相似的领域,为他们指出一个有趣的方向。参*最后的错误叙述部分。
最终的应用程序如下所示:
我将介绍用于创建应用程序的高级方法。我使用 gensim 库提供的 Doc2Vec 和 Word2Vec。完整的应用程序可以在 Github 上获得。读者可以克隆项目来使用和/或修改。如果需要任何帮助,请联系我。
让我们开始吧。
应用
流程:第 1 部分
应用程序的后端使用 Node/Express web 服务来实现后端和前端之间的通信。图 1 显示了与后端处理相关的用户流。
图 1 前后端关系。Node 处理 arXiv 抓取,而 Python 处理所有其他与 Doc 和 Word 向量相关的函数。
用户首先从下拉框中选择 6 个域中的一个。这是 6 个常*的词干字段。一旦他们选择了他们的领域(和一个子领域),他们将被引导填写大量的搜索词。在参考文献 1 的例子中,这就是“热电”。
用户可以列出多个搜索词,用空格隔开。一旦他们列出了他们的术语,他们运行 DOC2VEC ,此时我们的后端检索所有 6 个域中最近发布的 arXiv 文章,为每篇文章创建文档向量,并根据与用户搜索术语的相关性返回前 5 篇文章。
此时,用户可以查看返回的文章,寻找有趣的对话。同样,这种想法是这些返回的文章可能在与用户的搜索词经常被讨论的相似的上下文中讨论工作(这些返回的文章中的词是“保持与用户的搜索词相同的公司”)。
让我们通过从 arXiv 获取主题来开始支持这个用户流。
获取主题
我们需要在arXiv.org获得所有主题。由于 arXiv 不太可能频繁添加新主题,我将在浏览器控制台中使用客户端 JavaScript,而不是设置后端抓取。
我们可以查看 arXiv 的分析页面并抓取那里的标题和命名代码。我写了下面的 JavaScript 来收集需要的内容:
我们在浏览器控制台中为 6 个域中的每一个运行这个。通过单击页面顶部的浅蓝色标题可以访问每个域:
为每个域这样做提供了 6 个 JSON 文件。下图显示了预期结构的一个片段:
我们可以使用这些来填充我们的下拉列表,并帮助我们抓取实际的文章。我将这些添加到应用程序中的数据文件夹:
├── **data** └── physics.json
└── mathematics.json
└── computer_science.json
└── quant_bio.json
└── quant_fin.json
└── stat.json
└── words.txt
我们可以通过过滤掉任何可能出现在 arXiv 论文中的非英语单词/符号来提高结果的质量。我将使用这个 50 个英语单词的列表:
http://www.mieliestronk.com/corncob_lowercase.txt
我会将这些文字复制并粘贴到一个名为 word.txt 的文件中,并将其放入数据文件夹。这些将在我们运行 Word2Vec 时使用。
刮擦 arXiv
当用户点击 RUN DOC2VEC 时,我们首先需要抓取 arXiv 上的文章。这意味着获取所选领域的每篇文章并创建文档向量。我们可以通过使用 Node.js 包 cheerio 得到每篇文章的链接。这个代码在scrape_arxiv.js
文件中。
我们以.list-identifier
类为目标,用href
来检索每个元素的 URL。这保存了一个名为 domain_1.json 的文件,其中保存了所有 25 个文档的所有单词,如图图 2 所示。
图 2 每个文档的(arXiv 文章)单词作为一个值保存在 domain_1.json 文件中。
这将由Doc2Vec
函数读取(并使用 words.txt 进行清理),以便创建文档向量并找到(推断出)与用户搜索词最匹配的文档。我们现在就写吧。
Doc2Vec
我们使用 gensim 的Doc2Vec
方法,该方法期望从我们读入的 JSON 中得到一个dict
对象作为 domain_1.json 。
您可以在 GitHub 上检查项目,看看我们的 API 如何将这些结果返回到前端。现在,用户已经返回了相关文档,我们可以支持用户流的第二部分。
流程:第 2 部分
在第 1 部分中,用户能够查看返回的文章。这使他们能够找到与自己的工作相关的潜在有用的讨论。然而,阅读整篇文章仍然很费时间,尤其是当所建立的“联系”可能在很大程度上是多余的时候。为了帮助确定这篇文章是否值得一读,我们可以尝试发现这篇文章中的哪些词与用户的搜索词最相似。如果这些返回的单词中有任何一个与用户相关,那么这篇文章可能值得进一步研究。
在第 2 部分中,我们抓取用户选择的文章(从返回的 5 篇文章中),使用 gensim 的 fastText (最初来自脸书)生成单词向量,并从第 1 部分中推断出与用户的搜索词最接近的单词。如图图 3 所示支持该流程。
图 3 用户可以运行 Word2Vec 来生成单词向量,并返回与搜索词最匹配的单词。这有助于用户决定所选文章是否值得进一步探索。
现在让我们创建 Word2Vec 函数。
Word2Vec
既然我们已经有了与用户搜索词最匹配的文档,我们想在一张纸上运行 Word2Vec。用户选择的任何论文都将通过 fastText 由 gensim 的 Word2Vec 方法进行处理,以找到最相关的单词。
与第 1 部分中返回的文档一样,您可以查看应用程序的代码库,看看这些结果是如何返回到前端的。
运行应用程序
让我们打开应用程序,运行几个实验,看看我们有什么发现。
从 GitHub 克隆应用程序:
git clone [https://github.com/sean-mcclure/word2vec_arxiv.git](https://github.com/sean-mcclure/word2vec_arxiv.git)
进入目录并启动 REST API :
node api/scrape_arxiv.js
从终端启动一个简单的 web 服务器:
python3 -m http.server
最后,将您的浏览器指向:
[**http://localhost:8000/app/**](http://localhost:8000/app/)
您应该会看到应用程序的启动状态:
结果
让我们做些试验。我们能从我们选择的一组搜索词中找到有趣的新研究思路吗?这个想法是为了看看单词嵌入是否与我们的直觉一致。
也许我想为我的分子动力学研究发现一种新的优化方法。我对量化金融或其子领域投资组合管理一无所知,但也许这一领域的人们正在尝试与我的工作类似的东西,尽管他们没有从事任何与物理或化学直接相关的工作。
让我们试试:
- 领域:量化金融>投资组合管理
- 搜索词:最优化、能源、量子、系统、动力学、绝热
我从量化金融下拉列表中选择投资组合管理,并填写我的 6 个搜索词。
用户可以列出任意数量的搜索词,甚至只有一个。
第篇论文 返回按相关程度排列:
- 带学*的鲁棒最优投资和再保险问题
- 具有路径依赖劳动收入的最优投资组合选择:无限地*线情形
- 半度量投资组合优化:一种减少同时资产冲击的新算法
- 使用自动编码器重建比率检测资产共同运动的变化
- 高维夏普比率:样本外最大值、约束最大值和最优投资组合选择的案例
我可以审核申请中显示的文件:
这些论文肯定是在谈论最优化,并且似乎提到了与动力学相关的东西。让我们在我们的顶级论文上运行 Word2Vec 来聚焦与我们的搜索词相关的具体讨论:
约简、顺序、策略和过滤这几个词或许值得一查。同样,这些是 Word2Vec 返回的单词,表明它们与我的搜索词相关的一些讨论有关联。让我们仔细检查一下这张纸,看看是否是这样。
简化一词是指论文使用了所谓的简化控制模型。这来自于控制理论,它是数学的一个子领域,研究影响动力系统的行为。动力系统与系统化学有联系,系统化学是研究相互作用分子网络及其涌现特性的科学。系统化学的一个主要目标是揭示复杂的反应网络,其中分子不断消耗能量来执行特定的功能。
经济模型处理多条业务线以及它们之间的依赖关系。他们试图通过创建一个通过优化学*到的参数模型来最大化财富的效用。这种优化是由汉密尔顿-雅可比-贝尔曼方程 (HJB)驱动的,其中导数由广义克拉克梯度代替。
HJB 方程已被用于研究“化学波”,即信息在整个反应扩散系统中快速传播,以同步和协调生物事件。
通过在网上做一些研究,我们已经能够在单词“ reduced ”和我们对分子动力学的兴趣之间建立联系。这是因为出现在我们最相关的文档中的单词 vector“reduced”与我们的搜索词“很接近”;优化、能量、量子、系统、动力学、绝热。深入研究后,我们很快意识到“减少”这个词确实是在优化的上下文中讨论的。这似乎是我们的词向量捕捉有用概念而没有显式编码这些概念的一个例子。
记住,我们最相关的文档也是通过使用嵌入发现的,通过文档向量。通过将 Doc2Vec 和 Word2Vec 放在一起,我们可以在不同的研究领域之间建立有趣和相关的联系。
这就是使用自动类比在我们可能永远不会想到的领域之间建立联系的力量。这是一个很好的例子,通过使用以类似方式运行的“智能”机器,增强了人们已经有的工作方式。
但是像一份经济学期刊的作者所使用的那样,探索使用与克拉克梯度相匹配的 HJB 方程来学*应用于复杂化学系统的优化参数,真的值得吗?也许吧。
或者也许我从一开始就知道(相信)这是不可行的。但是,在自动类比的鼓励下,沿着这种道路走下去不会有太大的害处。我只尝试了第一篇相关论文的第一个词,一个领域的第一个词,在我尝试的第一个词干领域。
至少这个应用程序让我重新考虑我目前的研究方法,看看其他人在做什么。这可能会引发新的*解,或者迫使我寻找不同的道路。它可能会让我想起我在另一本杂志上读过的东西,促使我重温某些概念。在领域之间建立松散的联系有助于我们远离短视的想法。
虚假叙述?
每当我们“发现”一些有趣的东西时,如果不提出一个困扰人类的基本问题,那将是我的失职。很容易看出我们想要什么,以为有联系,但实际上没有。我们必须小心,不要对看似有趣,但实际上不相关或不切实际的东西赋予太多的权重。
因此,当我们建立联系时,我们应该对任何相关的发现保持怀疑。科学的美妙之处在于(如果做得恰当的话),任何新的想法都必须经过严格的可证伪性检验,并证明它确实站得住脚。
愉快的探索。
参考
- 无监督单词嵌入从材料科学文献中捕获潜在知识
- 利用无监督机器学*揭开隐藏的科学知识
- Word2Vec 和 FastText Word 嵌入 Gensim
- 类比解释:理解单词嵌入
- 人类智能、计算和通用机器
Tableau 中的自动化分析— Python 和 Tabcmd
概述了如何使用 Python 来自动洞察 Tableau,并介绍了 Tableau 命令行实用程序 Tabcmd。
简介
Tableau 连续七年被 Gartner 评为分析和商业智能*台的领先工具。几乎每个行业中各种形状和规模的公司的 BI/数据团队都开发了仪表板,以便在整个组织中有效地交流关键业务指标。
使用 Tableau 的一个主要优点(这一点经常被忽略)是,它公开了一个公共 API 来以编程方式处理几乎所有可以在应用程序 GUI 上执行的任务,包括管理。
这就是 Python 的用武之地。大量库的脚本功能和支持使其成为在 BI 工作流中处理端到端流程自动化的流行选择。
来自 tableau.com/products/viewer的
在您继续之前…
为了有效地使用集成,Tableau 工作簿应在以下位置可用:
1.Tableau Server允许您在组织服务器上或使用云服务提供商托管内部工作簿和数据源。
2。Tableau OnlineTableau 管理服务器基础设施,您可以通过它们托管您的工作簿,只需支付一些额外费用。
通过上述方法之一将工作簿托管在 Tableau 服务器上通常是一种好的做法——尤其是如果您的仪表板经常被多方查看,并且涉及定期数据刷新(每天/每小时)。
Tableau Online 有一个 14 天的免费试用期,默认情况下会加载一些示例工作簿。您可以创建一个免费试用帐户来试用下面列出的一些测试集成和代码片段。
创建 tableau 在线账户后,保存用户名、密码、Tableau 服务器地址和网站名称的凭证。一台 tableau 服务器可以有多个站点,每个站点都承载一组工作簿和数据源。
条条大路通罗马
将 Python 与 Tableau Server 集成有多种方式,每种方式都基于不同的用例。
- Tableau 服务器客户端(TSC) 库
(Python 3.5 或更高版本)
这可能是从 Python 脚本执行服务器相关任务的最佳选择。这是一个由 Tableau 管理的开源项目,它包装了 Tableau 服务器 REST API。
pip install tableauserverclient
- TabPy 库
允许您在 Tableau 的表计算中嵌入和执行 Python 脚本。它本质上允许 Tableau 远程执行 Python 代码。
pip install tabpy
从这个tabby 博客——在 Tableau 计算中嵌入 Python
3.使用 请求 库直接消耗 Tableau 服务器 REST API 。一个更简单的方法,但是你可以让 Tableau 以任何你认为合适的方式工作,只要 API 允许。
其他整合路线和变体包括:
1.JupyTab
将 Jupyter 笔记本数据带入 Tableau 可视化。
pip install jupytab
- Tabcmd
从 Windows Shell 向 Tableau Server 发出命令——Mac/Linux 原生不支持,但有一个 hack 。
Tabcmd 的执行可以通过在计划任务下的批处理文件中进行设置来实现自动化。将 Tabcmd 添加到您的 windows PATH
变量中,或者切换到安装它的目录来运行它的命令。
您可以使用
***os***
或**subprocess**
模块在 Python 源代码中执行 tabcmd 命令。将 tabcmd 语句构造为字符串,并使用***os.system()***
或***subprocess.call()***
函数将它们传递给 shell
你可以在 Tableau 的 GitHub 页面找到更多支持其他语言(比如 JavaScript)的项目
这里我们重点讲 TSC 和 Tabcmd 的用法。
假设每个 TSC 片段都可以访问下面列出的虚拟变量。用你自己的凭证代替这些。
tableau_user = 'cricks@gmail.com'
tableau_passwd = '123'
tableau_server = 'http://172.16.22.2/'
tableau_server_site = 'my_site'
server_version = '3.7'
对于 Tableau Online,tableau_server
字段看起来会像这样:
prod-apnortheast-a.online.tableau.com
基于您的服务器位置。
以下各节详细介绍了如何使用 TSC 和 Tabcmd 在 Tableau 服务器上执行特定任务。
认证
贸易与供应链
使用 TableauServerClient 登录到 Tableau 服务器
Tabcmd
> tabcmd login -s http://172.16.22.2/ -t my_site -u cricks@gmail.com -p 123
凭证的每个参数都作为 shell 中的一个标志传递。
输出应该如下所示:
===== redirecting to http://172.16.22.2/auth
===== Signed out
===== Creating new session
===== Server: http://172.16.22.2/
===== Username: cricks@gmail.com
===== Site: my_site
===== Connecting to the server...
===== Signing in...
===== Succeeded
如果任一路由的身份验证失败,请向 Tableau 服务器管理员检查您的用户权限/用户授权。
获取并下载工作簿
“超市”工作簿可作为所有 Tableau 发行版的样本。它将是我们代码片段演示中的默认工作簿。
找到工作簿&将其下载为 **.twbx**
文件
TSCT30workbooks.get()
上带TSC.Filter()
的
— TSC.Pager()
— TSC.RequestOptions()
可以找到一个工作簿。
TSC 返回一个带有工作簿 ID、工作簿名称等属性的工作簿对象。这些选项中的每一个都在下面的要点中被详细描述为一个函数。
可以使用
TSC.Server().workbooks.download(workbook_id)
将工作簿下载为twbx
(Tableau 打包工作簿)
从服务器获取工作簿对象并作为 twbx 下载的两种不同方法
您可以通过引用 workbook 对象上的id
属性在服务器上检索工作簿的 ID。
超市工作簿的产品视图
Tabcmd
Tabcmd 保持简短:
tabcmd get “/workbooks/Superstore.twbx”
可能有几个警告,特别是对于 Tabcmd 中的
*get*
命令的权限。请务必在此 查看完整的清单 。您可以使用*get*
下载 PDF 或 PNG 格式的工作簿。
对视图应用过滤器并作为文件下载
我们可以查询工作簿中的特定视图,并对其应用过滤器。
工作原理:
我们发出一个以过滤器为参数的视图请求。API 将请求应用于视图,并将快照取回请求客户端。
过滤前:
超市——所有地区概览
后过滤为Region = West
:
超级商店-区域字段过滤为一个值的概览
TSC
假设workbook id
可以被获取,我们将使用它作为一个虚拟变量。
过滤视图并以 PDF 格式下载
view_items
包含一个view
对象列表。一个视图对象有id
、workbook_id
、name
、csv
等属性。个人最喜欢的是total_views
属性,它返回当前引用的视图在服务器上被用户查看的总次数。
我们需要"populate
" pdf 格式的视图,因为它允许 TSC 仅从网络上获取必要的属性。工作簿或视图对象包含对服务器上该对象的所有其他属性的引用。当需要填充其中一个对象时,TSC 让请求获取所需的属性以满足填充参数。
使用ImageRequestOptions()
可以将图像保存为 PNG,使用CSVRequestOptions()
可以保存 CSV。
关于的用法,请参*此处的文档。
Tabcmd
export 命令接受指定视图的 URL 和下载选项的可选参数。
tabcmd export -t my_site "Superstore/Overview?refresh=yes&Region=West" --pdf --pagesize a4 --pagelayout landscape -f "Overview.pdf"
视图也可以导出为 PNG 或 CSV 格式。
引号中指定的 URI 与用于通过浏览器访问 Tableau 服务器上的视图的 URL 的子字符串完全相同。
以下是相同命令在浏览器上的 URL:
http://172.16.22.2/#/site/my_site/views/Superstore/Overview?Region=West
这有助于在使用 Tabcmd 将视图导出到本地之前,在浏览器上试验视图的外观。
'refresh=yes'
强制服务器端刷新视图并获取最新结果。应用多个过滤器,在参数中用 '
&'
将它们分开日期可以过滤为:‘..
?report_date=2020–01–01
数据源和连接
Tableau 作为一个软件的核心特性之一是它允许用户处理数据源、提取和连接输入可视化的数据的能力。
贸易与供应链
获取服务器上的所有数据源作为对象,并打印每个数据源的名称。
与工作簿或视图对象类似,datasource
对象也可以被过滤或分页。
Tabcmd
tabcmd refreshextracts --datasource sales_ds
TSC 与 Tabcmd
TSC 和 Tabcmd 都允许您对数据源、连接、工作簿、视图、用户等执行重要的 CRUD 操作。
虽然 TSC 本身与操作系统无关,但是如果您有 windows 系统或者能够将其配置为在 Mac/Linux 上手动运行,Tabcmd 仍然足以在服务器上执行大多数日常任务。
TSC 胜过 Tabcmd 的一个特殊用例是它能够并行处理对服务器的大量请求。使用 Tabcmd,请求总是在每个 shell 会话中序列化。TSC 可以多线程处理数十或数百个工作线程,从而大幅提升其服务器请求的性能。在 Python 上,您可以在一个使用 TSC 的函数的列表上实现带有map()
的ThreadPoolExecutor()
,并让它为您所用。
这可能有助于启动快速高效的 BI 报告。将这些与Python for Google Sheets/Excel或 Python for SQL 结合在一起可以增强你的工作流程。
Tableau 有丰富的关于使用 TSC 和 Tabcmd 的文档。本文中的代码片段只是触及了它们在 Tableau 服务器上可以执行的大量操作的表面。下面详细检查一下。
其他参考文献
希望这是一个足够温和的介绍,可以让您站起来开始这些集成。
干杯。
自动化 AWS SageMaker 笔记本电脑
了解如何使用 CloudWatch、Lambda 和生命周期配置安排自动执行 AWS SageMaker 笔记本
简介
SageMaker 提供了多种工具和功能来大规模标记、构建、训练和部署机器学*模型。其中最流行的是笔记本实例,用于准备和处理数据,编写代码来训练模型,将模型部署到 Amazon SageMaker 主机,以及测试或验证模型。我最近在做一个项目,涉及自动化 SageMaker 笔记本。
使用 Amazon Glue 在 Sagemaker 中部署模型有多种方式,如这里的和这里的和所述。您还可以使用端点 API 来部署模型。如果您不部署模型,而是一次又一次地执行脚本,那该怎么办?SageMaker 目前还没有直接的方法来实现自动化。另外,如果您想在执行完脚本后立即关闭笔记本实例,该怎么办呢?这肯定会节省你的钱,因为 AWS 是按小时收费的。
我们如何实现这一点?
正在使用的其他 AWS 功能和服务
- 生命周期配置:生命周期配置提供了 shell 脚本,这些脚本仅在您创建 notebook 实例或启动一个实例时运行。它们可用于安装软件包或配置笔记本实例。
- AWS CloudWatch :亚马逊 CloudWatch 是一项监控和可观测性服务。它可用于检测您环境中的异常行为,设置警报,并排显示日志和指标,并采取自动化措施。
- AWS Lambda : AWS Lambda 允许您在不提供或管理服务器的情况下运行代码。您只需为您消耗的计算时间付费,当您的代码不运行时,则不收费。
用于自动化的主要步骤:
- 使用 CloudWatch 触发调用 lambda 函数的执行
- lambda 函数启动相应的笔记本实例。
- 笔记本实例一启动,生命周期配置就会被触发。
- 生命周期配置执行脚本,然后关闭笔记本实例。
详细步骤
λ函数
我们利用 lambda 函数来启动一个笔记本实例。假设 lambda 函数被称为‘测试-lambda-函数’。确保选择一个有权限访问 lambda 和 SageMaker 的执行角色。
这里‘test-notebook-instance’是我们想要自动化的笔记本实例的名称。
云观察
- 转到规则>创建规则。
- 输入刷新频率
- 选择 lambda 函数名:‘测试-lambda-函数’。这是我们在上面创建的同一个函数。
生命周期配置
我们现在将为我们的'测试笔记本实例''创建一个生命周期配置。让我们称这个生命周期配置为“测试-生命周期-配置”。
代码:
代码功能的简要说明:
- 启动 python 环境
- 执行 jupyter 笔记本
- 下载包含自动停止功能的 AWS 示例 python 脚本
- 等待 1 分钟。可以根据需要增加或降低。
- 创建一个 cron 作业来执行自动停止 python 脚本
之后,我们将生命周期配置连接到笔记本电脑。
我喜欢在 LinkedIn 上联系——https://www.linkedin.com/in/taufeeqrahmani/
查看我在 Data Sleek 的朋友的工作,寻找所有数据的解决方案。
自动关闭 AWS 服务器以进行深度学*
因为每个人都有忘记的时候,没关系。
最近,我一直在为一个机器学*项目使用 AWS EC2 服务器。我看到的每篇文章都在说同样的事情……“不要忘记关闭 EC2 实例”。看这个让我焦虑。只要一想到让 GPU 开着会在口袋里烧个洞,我就会莫名其妙地出汗。
所以我决定编写一个 Bash 脚本来启动服务器,SSH 进入,这样我就可以继续我的项目,然后当我退出时关闭服务器。我甚至在桌面上保存了一个脚本的快捷方式,这样我只需点击两下就可以开始工作了。
不幸的是,让脚本工作的过程并不简单,而且有点令人恼火。所以我决定写一个快速的帖子,这样社区也可以同样安心。
我的工作站是 Windows 10 PC,所以这些步骤对于 Mac 可能会有所不同。
先决条件 1:拥有一个 AWS 帐户并创建一个实例
您需要有一个 AWS 帐户,并实例化一个 AWS EC2 实例。FastAI 有一个关于如何做到这一点的教程在这里。如果这是您第一次创建 GPU 实例,您可能需要请求增加“p 型”实例的限制。对我来说,这花了大约两天时间才收到 AWS 的回复。
先决条件 2:设置 AWS CLI
您将需要 AWS CLI,这样 Bash 脚本就可以调用来启动/关闭服务器。你可以从这里下载 CLI。
AWS CLI 下载
在接下来的几个步骤中,我们将在 AWS IAM 中为您自己创建一个用户,然后生成并保存安全凭证,以便我们可以使用 AWS CLI。
IAM 控制台
如果 IAM 控制台中有用户,则不需要新用户。只需确保您拥有用户的“安全凭证”
如果您没有用户,请创建一个。
如果您创建了一个用户,请确保授予其“编程访问”权限。接下来,您将为用户生成安全密钥。
保存这些钥匙!
在 Windows 命令提示符下,您需要运行aws configure
并按照提示进行操作。用从 IAM 控制台获得的密钥填写访问密钥 ID 和秘密访问密钥。将默认区域设置为服务器所在的区域。
完成这些步骤后,您应该能够从命令行访问 AWS 实例了。尝试运行aws ec2 describe-instances
,您应该会看到 EC2 实例的列表。
先决条件 3:将 Git-Bash 连接到 AWS
如果您还没有安装 Git-Bash,请在这里安装 Git-Bash。您将需要它来运行 Bash 脚本。
Git-Bash 下载
下一步是将 Git-Bash 连接到 AWS CLI。为此,您需要在 bash 的根目录下创建一个. bashrc 文件。打开一个 Git-Bash 终端并执行以下操作。
cd ~vim .bashrc
这将打开一个文本编辑器。您可以在其中粘贴以下内容。
#!/bin/bashalias aws=”winpty -Xallow-non-tty -Xplain C://Program\ Files/Amazon/AWSCLI/bin/aws.exe”
现在 Git-Bash 终端将识别命令aws
。如果你跳过这一步,你将得到错误bash: aws: command not found
。确保上面插入的文件路径指向您的文件目录中的 aws.exe。
完成后,通过键入esc
和:wq
退出 vim 终端,然后按 enter 键。为了使更改生效,您需要关闭并重新打开 Git-Bash。这样做并执行aws
。您应该看到以下内容。
测试 AWS CLI 命令
创建脚本
这样,我们就非常接近我们的目标了。制作一个 Bash 脚本,自动启动、登录和关闭 EC2 服务器。
现在我们可以结束并编写脚本了。在您的 bash 终端中,导航到您想要脚本的任何地方(对我来说是cd C://Users/harrison/Desktop
),然后运行vim aws.sh
#!/bin/bashINSTANCE_ID=**<YOUR EC2 INSTANCE-ID HERE>** SSH_KEY=**<path/to/sshkey.pem>**echo "Starting AWS Server."
aws ec2 start-instances --instance-ids $INSTANCE_ID#Wait for server to come online
STARTED=False
while [ "$STARTED" != "True" ]; do
SERVER_STATUS=$(aws ec2 describe-instance-status --include-all-instances --instance-ids $INSTANCE_ID --output text --query 'InstanceStatuses[].InstanceState.Name')
if [ "$SERVER_STATUS" == "running" ]; then
STARTED=True
else
sleep 3
fi
doneSERVER_PUBLIC_DNS=$(aws ec2 describe-instances — instance-ids $INSTANCE_ID — output text — query ‘Reservations[].Instances[].PublicDnsName’)echo “Attempting to log into server.”
ssh -L localhost:8888:localhost:8888 -i $SSH_KEY ubuntu@$SERVER_PUBLIC_DNSecho “Shutting down server.”
aws ec2 stop-instances — instance-ids $INSTANCE_ID
echo "Sent shutdown command."
sleep 1echo "Querying instance status..."
aws ec2 describe-instance-status --include-all-instances --instance-ids $INSTANCE_ID --output text --query 'InstanceStatuses[]'
sleep 5
注意:我会定期对这个脚本进行改进。
用您的 EC2 实例的实例 id 填充INSTANCE_ID
。在SSH_KEY
中填入您的 SSH 密钥的路径。
现在,当您想开始在 EC2 服务器上工作时,只需运行 bash 脚本,您就可以连接到您的服务器了。从那里,您可以运行一个jupyter notebook
或者从 GitHub 加载 python 脚本。当您exit
退出实例时,脚本将继续运行并为您关闭服务器。
工作原理(可选)
aws ec2 start-instances — instance-ids $INSTANCE_ID
启动 EC2 实例。
您需要服务器的公共 DNS 才能登录。不幸的是,当您关闭服务器时,DNS 可能会改变。以下代码查询服务器的公共 DNS。
SERVER_PUBLIC_DNS=$(aws ec2 describe-instances — instance-ids $INSTANCE_ID — output text — query ‘Reservations[].Instances[].PublicDnsName’)
用ssh -L localhost:8888:localhost:8888 -i $SSH_KEYubuntu@$SERVER_PUBLIC_DNS
登录 EC2 实例
aws ec2 stop-instances — instance-ids $INSTANCE_ID
停止 EC2 实例。
用机器智能自动化代码
以及来自 OpenAI 的 GPT3 语言处理 API 的更多含义。
这是我的自由星期五关于机器人学& AI 的文章节选,请查阅。 看看这个视频,这是我*过的第一个引人注目的自动化软件生成演示。
来源。
这是什么
OpenAI 最新的语言处理模型 GPT-3(生成式预训练转换器)从两个示例片段创建了各种前端代码片段。(前端代码是在网站上呈现的代码,通常会大量重复以获得相同设计的变体,因此它是自动化的一个简单的初始目标)。
你可以在这里 (Twitter)与工具的作者进行交流。你可以在这里找到更多有创意的例子,或者在这里找到另一个代码生成例子。我特别喜欢的一个是写的创意小说或者是写的自动生成的游戏关于上一代的模型。
这是如何工作的
语言模型“生成式预训练转换器”使用了来自 OpenAI 的一个新的即插即用 API。下面是我的帖子中关于 NLP 和变形金刚的摘录( AI &仲裁真相——貌似每周都需要重温)。
科技—变形金刚& NLP
自然语言处理(NLP)是机器学*的子领域,涉及从文本中处理和提取信息。 用在智能助手、翻译器、搜索引擎、网店等等。 NLP(以及计算机视觉)是少数货币化的最先进的机器学*发展之一。是被用来诠释真理的候选人。
迄今为止最好的 NLP 工具是一个叫做 的神经网络架构,变压器 。长话短说,变形金刚使用一种 编码器和解码器结构 ,将单词编码到潜在空间,并解码为翻译、打字错误修复或分类(你可以认为编码器-解码器是通过神经网络将复杂的特征空间压缩到更简单的空间——非线性函数逼近)。NLP 领域的一个关键工具是一种叫做 注意力 的东西,它学*关注哪些单词以及关注多长时间(而不是硬编码到一个工程系统中)。
一个transformer结合了这些工具,以及一些其他的改进,允许模型被高效地并行训练。下图显示了数据如何流经转换器。
一个可视化来自一个 牛逼教程 我找到的。
为什么它很重要
这是我看到的第一个应用程序,人们可以用它来代替工程时间。前端设计人员可以借助这款工具大幅提高工作速度。这可能会被出售给许多现有的公司,新的企业将在未来使用它来创造有价值的服务。找到最好的应用程序需要一个有创造力的人,当然受到我们人类设计师的限制,很快就会被下一个最先进的模型所取代。
这是令人瞩目的,因为 OpenAI 著名的宪章。简而言之——我们将朝着 AGI 前进,如果另一家公司想抢先一步, 我们将加入他们的 。该产品背后的说法是,这些资金将帮助他们执行人工智能研究,但他们的领导层过去曾撤回模型,因为担心它们“太危险,无法分享”。这种 AI 危险的细线只会越来越尖锐。
书呆子角落:这个模型的训练量是 50[PETA](https://en.wikipedia.org/wiki/Peta-#:~:text=Peta (%2Fˈpɛt,πέντε%2C meaning "five".)翻牌/秒-天(这到底是什么意思?)仅培训费用就超过 1200 万美元[ 来源 ]。这是从费用中收回的一点成本。我喜欢思考这个模型如何与我用于回归任务的浅层神经网络相比较— 它的参数数量超过 1 亿倍。这是一个完全不同的函数逼近体系。对于书呆子来说,学术论文在这里是。
机器人和生成文本
我请求进入机器人研究的测试版。我有兴趣看看一个语言模型(大神经网络)的规划能达到什么水*,以游戏的形式给定上下文。 语言是否抓住了游戏中的基本意图和解决方案的结构?
从长远来看,我认为将语言整合到机器人奖励中是令人感兴趣的——它将允许与机器人一起工作的人类给机器下达口头任务(验证所述任务是另一个问题)。
示例:
- 给定一个游戏板的嵌入(书写、网格、其他方法),说“我应该移动到哪里。”
- 给出一个环境描述:“积木在椅子右边的球上,”问“球在椅子上面吗?”
这是一个非常初级的例子,但我认为来自商业化机器学*领域的链接,如视觉和语言的深度学*,是很有潜力的。
一个关于机器人和人工智能的博客,让它们对每个人都有益,以及即将到来的自动化浪潮…
robotic.substack.com](https://robotic.substack.com/)
与 Jenkins 一起自动化数据科学项目
了解如何使用 Jenkins 自动化数据科学代码
让我们描绘一个场景,您正在进行一个数据科学项目,起初,您有一个 80%的模型准确性,您使用 Flask 将该应用程序作为 API 部署到生产中。然后几天后,你决定继续这个项目,在调整了一些参数并增加了一些数据后,你有了比之前建立的模型更好的精确度。现在,您计划部署该模型,您必须经历构建、测试和再次将该模型部署到生产环境的麻烦,这是一项繁重的工作。在本文中,我将向您展示我们如何使用一个名为 Jenkins 的强大工具来自动化这个过程。
詹金斯是什么?
Jenkins 是一个免费的开源自动化服务器。它帮助自动化与构建、测试和部署相关的软件开发部分,促进持续集成和持续交付——维基百科
借助 Jenkins,您可以使用大量插件,在整个生命周期中自动化并加速软件交付过程。例如,您可以设置 Jenkins 自动检测存储库中的代码提交,并自动触发命令,从 Docker 文件构建 Docker 映像、运行单元测试、将映像推送到容器注册表或将其部署到生产服务器,而无需手动执行任何操作。我将解释一些我们需要知道的基本概念,以便在我们的数据科学项目中执行一些自动化。
詹金斯的优势
- 它是开源的
- 易于使用和安装
- 大量适合 DevOps 环境的插件
- 在代码上花更多时间,在部署上花更少时间
- 大型社区
詹金斯装置
Jenkins 支持跨*台安装,无论您是 Windows、Linux 还是 Mac 用户。您甚至可以将它安装在支持 PowerShell 或 Linux 实例的云服务器上。要安装 Jenkins,可以参考文档这里。
Jenkins 有很多惊人的特性,有些超出了本文的范围,要掌握 Jenkins 的窍门,你可以查看文档。
在我们开始实际操作之前,我想解释一些非常重要的术语,其中包括:
詹金斯工作
Jenkins 作业只是指由 Jenkins 控制的可运行任务。例如,你可以分配一个任务给 Jenkins 来执行一些特定的操作,比如运行“Hello World”,执行单元和集成测试等等。在 Jenkins 中创建工作非常容易,但是在软件环境中,你可能不会创建一个单独的工作,相反,你会做被称为管道的事情。
詹金斯管道
管道按照特定的顺序运行一组作业,让我用一个例子来解释。假设我正在 Jenkins 上开发一个应用程序,我想从代码库中提取代码,构建应用程序,测试并将其部署到服务器上。为此,我将创建四个作业来执行每个进程。因此,第一个作业(作业 1)将从存储库中提取代码,第二个作业(作业 2)将构建应用程序,第三个作业(作业 3)将执行单元和集成测试,第四个作业(作业 4)将代码部署到生产环境中。我可以使用 Jenkins 构建管道插件来执行这项任务。在创建作业并将它们按顺序链接起来之后,构建插件会将这些作业作为一个管道来运行。
詹金斯管道的类型:
- 声明性管道:这是一个支持管道作为代码概念的特性。它使管道代码更容易阅读和编写。这段代码写在一个 Jenkinsfile 中,它可以被签入一个源代码控制管理系统,比如 Git。
- 脚本管道:这是编写代码的老方法之一。使用这种方法,管道代码被写在 Jenkins 用户界面实例上,而不是写在文件中。尽管这两个管道执行相同的功能,并且使用相同的脚本语言(Groovy)。
在讨论了主要概念之后,让我们构建一个简单的迷你项目,并使用 Jenkins 实现自动化。
这个项目包含一个经过训练的机器学*模型,它可以检测来自 twitter 的与自杀相关的情绪,我使用 flask 将它部署为一个 API。我构建了我的 Jenkins 管道:
提交时从存储库中提取更改>>>构建 Docker 映像>>>将构建的映像推送到 DockerHub > > >删除未使用的 Docker 映像。
步伐
启动一个 Jenkins 服务器,安装 Git、Docker、Pipeline 和 build 插件,并在实例中安装 Git 和 Docker。对于本文,我在 AWS EC2 实例上使用了 Jenkins。
将代码推送到存储库,在本文中我使用了 Github。你可以在这里找到这篇文章的代码。
我的工作目录:
.
├── app.py
├── CustomCode
│ └── data_preprocessing.py
├── Dockerfile
├── Jenkinsfile
├── ML_model
│ └── model.pkl
└── requirements.txt
然后,我们需要告诉 Jenkins,每当代码库中发生更改时,就开始构建管道。为此,您需要将 Jenkins webhook 添加到 Github 存储库中,以便 GitHub 在代码发生变化时与 Jenkins 进行通信。为此:
点击代码库中的设置
然后导航到 webhooks,点击添加 Webhook
然后使用你的 Jenkins 服务器的公共 DNS 或公共 IP 并在末尾添加“/github-web hook/”,然后选择 application/json 作为内容类型。在“您希望哪个事件触发此网页挂钩?”,选择单个事件并选择仅推并点击添加 webhook。
现在,前往 Jenkins 并点击新项目
输入项目名称,选择管道,点击确定
从 General 向下滚动到 Build Triggers 并选择Github hook trigger for git SCM polling。它的简单作用是,每当代码中有提交时,帮助我们构建管道
然后滚动到管道,并在定义中从下拉列表中选择来自 SCM 的管道脚本。在 SCM(源代码管理)中,选择 Git 并输入存储库 URL,如果您的存储库是私有的,您需要使用您的用户名和密码创建一个凭证。在分支说明符中,您可以选择 master 或者您的代码存储库所在的任何分支,脚本路径选择 Jenkinsfile,Jenkins file 是我为项目编写管道的地方。然后选择保存。
现在让我们建立管道…
它贯穿了所有的阶段,构建是成功的
如果你查看你的 Docker Hub 库,你会在那里找到 Docker 图片。
现在让我们在代码库中做一点小小的改变
现在,如果你回到 Jenkins,你会看到它已经检测到已经做出的更改,并自动触发另一个构建。
这就是如何使用 Jenkins 来自动化这三个过程。
感谢阅读😃
深度 Q 学*的自动化毁灭:Tensorflow 中的一个实现。
强化学*的基础
介绍
在线学*方法是一个动态的强化学*算法家族,它是过去十年来人工智能领域许多成就的背后。在线学*方法属于基于样本的学*类强化学*方法,允许简单地通过重复观察来确定状态值,消除了对转换动态的需要。与它们的离线对应方式,不同,在线学*方法允许在环境事件期间对状态和动作的值进行增量更新,允许观察到持续的、增量的性能改进。
除了时间差异学*(TD ),我们还讨论了 Q-learning 的理论和实际实现,这是 TD 的一种发展,旨在允许增量估计和状态-动作值的改进。Q-learning 因成为模拟游戏环境的强化学*方法的支柱而闻名,如在 OpenAI 的健身房中观察到的那些。因为我们已经在过去的文章中涉及了 Q-learning 的理论方面,所以这里不再重复。
在线学*方法(如 TD)的快速情景内响应能力使其适用于高度动态的环境,在这种环境中,状态和动作的值通过多组估计值不断更新。也许最值得注意的是, TD 是 Q-learning 的基础,这是一种更先进的算法,用于训练代理处理游戏环境,如在 OpenAI Atari 健身房中观察到的环境,正如我们之前的实现中的一些所涵盖的。
在本文中,我们将探索如何通过使用开源的 OpenAI gym 包装库 Vizdoomgym ,将 Q-learning 应用于训练代理玩经典 FPS 游戏 Doom 。我们将指导您设置您的第一个代理,并为未来的工作奠定基础。
永恒经典的演变。我们将在这里关注 1993 年的版本。
超越 TD: SARSA & Q-learning
回想一下,在时间差异学*中,我们观察到一个主体在一个环境中通过一系列状态(S)、动作(A)和(奖励)循环地行为。
在 TD 期间,我们可以在到达下一个状态时更新前一个状态的值。我们可以进一步扩展我们的模型的范围,以包括状态-动作值,在一种称为 SARSA 的方法中,一种用于估计动作值的基于策略的 TD 控制算法。在 SARSA 期间,我们在给定的策略下连续地估计跨增量时间步长的动作值,同时使用这种知识来修改策略,使其趋向于动作值贪婪的替代方案。
让我们比较状态-动作和状态-值 TD 更新方程:
Q-learning 不同于 SARSA,它在更新期间强制选择具有当前最高动作值的动作,这与使用贝尔曼优化方程观察到的情况类似。我们可以检查贝尔曼和贝尔曼优化方程旁边的 SARSA 和 Q-learning,如下所示:
你可能想知道如何确保我们的状态-动作空间的完整探索,给定需要不断地为具有最高现有动作值的状态选择动作。从理论上讲,我们可能只是因为一开始就没有评估而避免了最佳行动。为了鼓励探索,我们可以使用一个衰减的 e-greedy 策略,本质上迫使代理以衰减的概率选择一个明显的次优行为,以便了解更多关于其价值的信息。通过使用衰减值,我们可以在评估完所有状态后限制探索,之后我们将为每个状态永久选择最佳操作。
有了我们的理论,让我们开始我们的实现。
履行
我们的 Google 协作实现是利用 Tensorflow Core 用 Python 编写的,可以在 GradientCrescent Github 上找到。关注我们出版物的读者会发现代码与我们之前在雅达利T4 环境中的实现相似。由于这种方法的实现非常复杂,让我们用总结一下所需动作的顺序:
1.我们定义我们的深度 Q 学*神经网络。这是一个 CNN,它拍摄游戏中的屏幕图像,并输出 Ms-Pacman gamespace 中每个动作的概率,或 Q 值。为了获得概率张量,我们在最后一层不包括任何激活函数。
2.由于 Q-learning 要求我们了解当前和下一个状态,我们需要从数据生成开始。我们将表示初始状态 s 的游戏空间的预处理输入图像输入到网络中,并获取动作的初始概率分布,或 Q 值。在训练之前,这些值将是随机的和次优的。
3.利用我们的概率张量,我们然后使用 argmax()函数选择具有当前最高概率的动作,并使用它来构建ε贪婪策略。
4.使用我们的策略,我们将选择动作 a ,并评估我们在健身房环境中的决定接收关于新状态s’、奖励 r 以及该集是否已结束的信息。
5.我们以列表形式将该信息组合存储在一个缓冲区中,并重复步骤 2-4 预设次数,以建立一个足够大的缓冲区数据集。
6.一旦步骤 5 完成,我们转到生成我们的目标y-值R’和A’,这是损失计算所需的。虽然前者只是从 R 中减去,但是我们通过将S’输入到我们的网络中来获得 A’。
7.有了所有的组件,我们就可以计算训练网络的损耗。
8.一旦训练结束,我们将评估我们的代理在新一集游戏中的表现,并记录表现。
让我们开始吧。随着 Tensorflow 2 在实验室环境中的使用,我们已经使用新的 compat 包将我们的代码转换为符合 TF2 标准。注意,这段代码不是 TF2 本地的。
让我们通过导入所有必需的包,包括 OpenAI 和 Vizdoomgym 环境以及 Tensorflow 核心:
import gym
import vizdoomgym
!pip install tensorflow==1.15
import numpy as np
import tensorflow as tf
from tensorflow.contrib.layers import flatten, conv2d, fully_connected
from collections import deque, Counter
import random
from datetime import datetime
接下来,我们定义一个预处理函数,对健身房环境中的观察结果进行标准化和调整大小,并将它们转换成一维张量。
from skimage.color import rgb2gray
from skimage import transform#prepro (240, 320, 3) uint8 frame into 30x40 1D float vector
color = np.array([240, 320, 74]).mean()
def preprocess_observation(obs):
img =obs/255.0
img[img==color] = 0 img_gray = rgb2gray(img)
preprocessed_frame = transform.resize(img_gray, [60,80])
return preprocessed_frame
接下来,让我们初始化健身房环境。我们将使用 Vizdoomgym 的健康收集场景,其中的目标是收集尽可能多的健康令牌,以便在通过一个具有破坏性酸性地板的方形房间时保持活着。
env = gym.make(‘VizdoomHealthGathering-v0’)
n_outputs = env.action_space.n
print(n_outputs)observation = env.reset()import tensorflow as tf
import matplotlib.pyplot as pltfor i in range(22):
if i > 20:
print(observation.shape)
plt.imshow(observation)
plt.show()observation, _, _, _ = env.step(1)
我们可以查看游戏画面,也可以查看游戏空间中的 3 个可用动作,即左转、右转或前进。当然,我们的代理人无法获得这些信息。
原始观察输入
我们可以借此机会比较我们的原始和预处理输入图像:
预处理图像输入
接下来,我们将输入帧堆叠和帧合成引入我们的预处理流水线,这是 Deepmind 在 2015 年推出的两项技术。这些方法分别为我们的输入提供时间和运动参考。
我们通过获取两个输入帧来应用帧合成,并返回这两个帧的元素式最大总和 maxframe 。然后,这些合成的帧被存储在一个队列或“堆栈”中,当引入新的条目时,它会自动删除旧的条目。
stack_size = 4 # We stack 4 composite frames in total stacked_frames = deque([np.zeros((60,80), dtype=np.int) for i in range(stack_size)], maxlen=4)def stack_frames(stacked_frames, state, is_new_episode):
# Preprocess frame
frame = preprocess_observation(state)
if is_new_episode:
# Clear our stacked_frames
stacked_frames = deque([np.zeros((60,80), dtype=np.int) for i in range(stack_size)], maxlen=4)
# Because we’re in a new episode, copy the same frame 4x, apply elementwise maxima
maxframe = np.maximum(frame,frame)
stacked_frames.append(maxframe)
stacked_frames.append(maxframe)
stacked_frames.append(maxframe)
stacked_frames.append(maxframe)
# Stack the frames
stacked_state = np.stack(stacked_frames, axis=2)
else:
#Since deque append adds t right, we can fetch rightmost element
maxframe=np.maximum(stacked_frames[-1],frame)
# Append frame to deque, automatically removes the oldest frame
stacked_frames.append(maxframe) # Build the stacked state (first dimension specifies different frames)
stacked_state = np.stack(stacked_frames, axis=2)
return stacked_state, stacked_frames
接下来,让我们定义我们的模型,一个深度 Q 网络。这基本上是一个三层卷积网络,它采用预处理的输入观察值,将生成的展*输出馈送到一个全连接层,生成将游戏空间中的每个动作作为输出的概率。请注意,这里没有激活层,因为激活层的存在会导致二进制输出分布。
tf.compat.v1.reset_default_graph() def q_network(X, name_scope):
# Initialize layers
initializer = tf.compat.v1.keras.initializers.VarianceScaling(scale=2.0) with tf.compat.v1.variable_scope(name_scope) as scope: # initialize the convolutional layers
layer_1 = conv2d(X, num_outputs=32, kernel_size=(8,8), stride=4, padding=’SAME’, weights_initializer=initializer)
tf.compat.v1.summary.histogram(‘layer_1’,layer_1)
layer_2 = conv2d(layer_1, num_outputs=64, kernel_size=(4,4), stride=2, padding=’SAME’, weights_initializer=initializer)
tf.compat.v1.summary.histogram(‘layer_2’,layer_2)
layer_3 = conv2d(layer_2, num_outputs=64, kernel_size=(3,3), stride=1, padding=’SAME’, weights_initializer=initializer)
tf.compat.v1.summary.histogram(‘layer_3’,layer_3)
# Flatten the result of layer_3 before feeding to the fully connected layer
flat = flatten(layer_3)
# Insert fully connected layer
fc = fully_connected(flat, num_outputs=128, weights_initializer=initializer)
tf.compat.v1.summary.histogram(‘fc’,fc)
#Add final output layer
output = fully_connected(fc, num_outputs=n_outputs, activation_fn=None, weights_initializer=initializer)
tf.compat.v1.summary.histogram(‘output’,output) # Vars will store the parameters of the network such as weights
vars = {v.name[len(scope.name):]: v for v in tf.compat.v1.get_collection(key=tf.compat.v1.GraphKeys.TRAINABLE_VARIABLES, scope=scope.name)}
#Return both variables and outputs together
return vars, output
让我们也借此机会为我们的模型和训练过程定义超参数。注意,由于我们的堆叠帧,X_shape 现在是(无,60,80,4) 。
num_episodes = 1000
batch_size = 48input_shape = (None, 60, 80, 1)learning_rate = 0.002
#Modified for composite stacked frames
X_shape = (None, 60, 80, 4)
discount_factor = 0.99global_step = 0
copy_steps = 100
steps_train = 4
start_steps = 2000
回想一下,Q-learning 要求我们选择具有最高行动价值的行动。为了确保我们仍然访问每一个可能的状态-行为组合,我们将让我们的代理遵循一个衰减的ε-贪婪策略,探索率为 5%。
epsilon = 0.5
eps_min = 0.05
eps_max = 1.0
eps_decay_steps = 500000def epsilon_greedy(action, step):
p = np.random.random(1).squeeze() #1D entries returned using squeeze
epsilon = max(eps_min, eps_max — (eps_max-eps_min) * step/eps_decay_steps) #Decaying policy with more steps
if p< epsilon:
return np.random.randint(n_outputs)
else:
return action
回想上面的等式,Q-learning 的更新函数要求如下:
- 当前状态 s
- 当前动作一个
- 当前动作后的奖励 r
- 下一个状态s’
- 下一个动作a’
为了以有意义的数量提供这些参数,我们需要按照一组参数评估我们当前的策略,并将所有变量存储在一个缓冲区中,我们将在训练期间从该缓冲区中提取迷你批次中的数据。让我们继续创建我们的缓冲区和一个简单的采样函数:
buffer_len = 20000
exp_buffer = deque(maxlen=buffer_len)def sample_memories(batch_size):
perm_batch = np.random.permutation(len(exp_buffer))[:batch_size]
mem = np.array(exp_buffer)[perm_batch]
return mem[:,0], mem[:,1], mem[:,2], mem[:,3], mem[:,4]
接下来,让我们将原始网络的权重参数复制到目标网络中。这种双网络方法允许我们在使用现有策略的训练过程中生成数据,同时仍然为下一个策略迭代优化我们的参数,减少损失振荡。
# we build our Q network, which takes the input X and generates Q values for all the actions in the state
mainQ, mainQ_outputs = q_network(X, ‘mainQ’)# similarly we build our target Q network, for policy evaluation
targetQ, targetQ_outputs = q_network(X, ‘targetQ’)copy_op = [tf.compat.v1.assign(main_name, targetQ[var_name]) for var_name, main_name in mainQ.items()]
copy_target_to_main = tf.group(*copy_op)
最后,我们还将定义我们的损失。这就是我们的目标动作(具有最高动作值)和我们的预测动作的*方差。我们将使用 ADAM 优化器来最大限度地减少我们在训练中的损失。
# define a placeholder for our output i.e action
y = tf.compat.v1.placeholder(tf.float32, shape=(None,1))# now we calculate the loss which is the difference between actual value and predicted value
loss = tf.reduce_mean(input_tensor=tf.square(y — Q_action))# we use adam optimizer for minimizing the loss
optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate)
training_op = optimizer.minimize(loss)init = tf.compat.v1.global_variables_initializer()
loss_summary = tf.compat.v1.summary.scalar(‘LOSS’, loss)
merge_summary = tf.compat.v1.summary.merge_all()
file_writer = tf.compat.v1.summary.FileWriter(logdir, tf.compat.v1.get_default_graph())
定义好所有代码后,让我们运行我们的网络并检查培训过程。我们已经在最初的总结中定义了大部分,但是让我们为后代回忆一下。
- 对于每个时期,在使用ε-贪婪策略选择下一个动作之前,我们将输入图像堆栈输入到我们的网络中,以生成可用动作的概率分布
- 然后,我们将它输入到网络中,获取下一个状态和相应奖励的信息,并将其存储到我们的缓冲区中。我们更新我们的堆栈,并通过一些预定义的步骤重复这一过程。
- 在我们的缓冲区足够大之后,我们将下一个状态输入到我们的网络中,以便获得下一个动作。我们还通过贴现当前的奖励来计算下一个奖励
- 我们通过 Q 学*更新函数生成我们的目标 y 值,并训练我们的网络。
- 通过最小化训练损失,我们更新网络权重参数,以便为下一个策略输出改进的状态-动作值。
with tf.compat.v1.Session() as sess:
init.run()
# for each episode
history = []
for i in range(num_episodes):
done = False
obs = env.reset()
epoch = 0
episodic_reward = 0
actions_counter = Counter()
episodic_loss = []
# First step, preprocess + initialize stack
obs,stacked_frames= stack_frames(stacked_frames,obs,True) # while the state is not the terminal state
while not done:
#Data generation using the untrained network
# feed the game screen and get the Q values for each action
actions = mainQ_outputs.eval(feed_dict={X:[obs], in_training_mode:False})
# get the action
action = np.argmax(actions, axis=-1)
actions_counter[str(action)] += 1
# select the action using epsilon greedy policy
action = epsilon_greedy(action, global_step)
# now perform the action and move to the next state, next_obs, receive reward
next_obs, reward, done, _ = env.step(action)
#Updated stacked frames with new episode
next_obs, stacked_frames = stack_frames(stacked_frames, next_obs, False)
# Store this transition as an experience in the replay buffer!
exp_buffer.append([obs, action, next_obs, reward, done]) # After certain steps, we train our Q network with samples from the experience replay buffer
if global_step % steps_train == 0 and global_step > start_steps:
o_obs, o_act, o_next_obs, o_rew, o_done = sample_memories(batch_size)
# states
o_obs = [x for x in o_obs]
# next states
o_next_obs = [x for x in o_next_obs]
# next actions
next_act = mainQ_outputs.eval(feed_dict={X:o_next_obs, in_training_mode:False})
# discounted reward: these are our Y-values
y_batch = o_rew + discount_factor * np.max(next_act, axis=-1) * (1-o_done) # merge all summaries and write to the file
mrg_summary = merge_summary.eval(feed_dict={X:o_obs, y:np.expand_dims(y_batch, axis=-1), X_action:o_act, in_training_mode:False})
file_writer.add_summary(mrg_summary, global_step)
# To calculate the loss, we run the previously defined functions mentioned while feeding inputs
train_loss, _ = sess.run([loss, training_op], feed_dict={X:o_obs, y:np.expand_dims(y_batch, axis=-1), X_action:o_act, in_training_mode:True})
episodic_loss.append(train_loss) # after some interval we copy our main Q network weights to target Q network
if (global_step+1) % copy_steps == 0 and global_step > start_steps:
copy_target_to_main.run() obs = next_obs
epoch += 1
global_step += 1
episodic_reward += reward
next_obs=np.zeros(obs.shape)
exp_buffer.append([obs, action, next_obs, reward, done])
obs= env.reset()
obs,stacked_frames= stack_frames(stacked_frames,obs,True)
history.append(episodic_reward)
print(‘Epochs per episode:’, epoch, ‘Episode Reward:’, episodic_reward,”Episode number:”, len(history))
一旦训练完成,我们就可以根据增量情节绘制奖励分布图。前 1000 集如下所示:
这一结果是可以接受的,改善的开始是可*的,考虑到最初的 Vizdoom 论文表明,要观察到更显著的改善,需要成千上万的情节。
img_array=[]
with tf.compat.v1.Session() as sess:
init.run()
observation, stacked_frames = stack_frames(stacked_frames, observation, True)
while True:# feed the game screen and get the Q values for each action
actions = mainQ_outputs.eval(feed_dict={X:[observation], in_training_mode:False})# get the action
action = np.argmax(actions, axis=-1)
actions_counter[str(action)] += 1# select the action using epsilon greedy policy
action = epsilon_greedy(action, global_step)
environment.render()
new_observation, stacked_frames = stack_frames(stacked_frames, new_observation, False)
observation = new_observation
# now perform the action and move to the next state, next_obs, receive reward
new_observation, reward, done, _ = environment.step(action)
img_array.append(new_observation)
if done:
#observation = env.reset()
break
environment.close()
最后,我们可以将我们的帧列表提供给 scikit-video 库,以生成视频序列输出供检查:
from random import choice
import cv2
from google.colab.patches import cv2_imshowimport numpy as np
import skvideo.ioout_video = np.empty([len(img_array), 240, 320, 3], dtype = np.uint8)
out_video = out_video.astype(np.uint8)for i in range(len(img_array)):
frame = img_array[i]
out_video[i] = frame
# Writes the the output image sequences in a video file
skvideo.io.vwrite(“/content/doom.mp4”, out_video)
让我们来看看我们的代理是如何工作的!
请注意代理在发现健康包时如何暂停,然后再继续向其移动。只是为了好玩,我们还为的基本场景训练了一个代理,目标是尽快击中怪物。而我们则取得了 ca 的最好成绩。1.3 秒,我们将在下面展示更早的一集。
这就结束了 Q-learning 的实现。在我们的下一篇文章中,我们将继续用更先进的 Q 学*方法处理更复杂的厄运场景,并将我们的代码切换到 Pytorch,这是人工智能研究中最流行的语言之一。
我们希望你喜欢这篇文章,并希望你查看 GradientCrescent 上的许多其他文章,涵盖人工智能的应用和理论方面。为了保持对 GradientCrescent 的最新更新,请考虑关注该出版物并关注我们的 Github 资源库。
参考文献
萨顿等人。强化学*
怀特等人。阿尔伯塔大学强化学*基础
席尔瓦等人。阿尔,强化学*,UCL
马卡洛夫等人。al,使用 VizDoom 第一人称射击游戏进行深度强化学*,HSE
肯普卡等人。al,ViZDoom:一个基于 Doom 的人工智能研究*台,用于视觉强化学*,PUT
Ravichandiran 等人。al,用 Python 实践强化学*
使用 AWS Lambda 自动化 ETL
使用 AWS Lambda 打包和部署无服务器 ETL 管道
哈桑·阿尔马西在 Unsplash 上的照片
介绍
我们周围的世界变化比以往任何时候都快。我们每天产生的数据量确实令人难以置信。每天会产生 2.5 万亿字节的数据,这意味着我们今天使用的数据明天可能就不再适用了。因此,我们需要一种方法来完全自动化我们的数据流流程,好消息是您不必担心需要昂贵的服务器和硬件来实现这一点,AWS 让您可以通过高性能和可扩展性的额外优势来实现这一点。
在本文中,我们将只使用 AWS 免费层产品。所以你可以跟着去。在我们开始这个过程之前,我们需要了解我们将要使用的 3 个 AWS 服务 EC2、AWS Lambda 和 Cloudwatch。
EC2
亚马逊弹性计算云 (EC2)是一项让你租用虚拟机的服务。我们可以用我们想要的任何配置(操作系统、存储等)启动一个虚拟机。)任何我们想要的时间。
λ
AWS Lambda 是一种无服务器计算服务,它运行我们的代码来响应事件,并自动为我们管理底层计算资源。我们可以使用 AWS Lambda 通过定制逻辑扩展其他 AWS 服务,或者创建我们的后端服务。 AWS Lambda 可以自动运行代码来响应多个事件,例如通过 Amazon API Gateway 的 HTTP 请求、对 Amazon S3 桶中对象的修改、Amazon DynamoDB 中的表更新。在我们的例子中,它将根据时间表运行代码。
云观察
顾名思义, CloudWatch 以日志、指标和事件的形式收集监控和运营数据,为我们提供运行在 AWS 和本地服务器上的 AWS 资源、应用程序和服务的统一视图。我们可以使用 CloudWatch 来检测我们环境中的异常行为,设置警报,并排显示日志和指标,采取自动操作,解决问题,并发现洞察力以保持我们的应用程序*稳运行。
AWS lambda 是我们进行编程以执行 ETL 的*台,但 AWS lambda 不包括大多数日常使用的包/库(Pandas,Requests ),标准的 pip install pandas 在 AWS Lambda 中无法工作。所以需要在本地或者 EC2 虚拟机上安装包/库,把它作为 zip 文件上传到 S3并作为层**附加到 Lambda 函数。**
这是我所说的工作流程的一个例子,
工作流程
创建并启动一个具有 S3 访问角色的 EC2 Linux 实例
登录 AWS 控制台。在服务下,选择 EC2,然后启动实例:
选择启动实例
第一步:为我们的 EC2 实例选择操作系统,我选择了Ubuntu Server 18.04 LTS(HVM),但是你也可以选择Amazon Linux 2 AMI(HVM)或者任何你喜欢的环境。****
选择 Ubuntu Server 18.04 LTS (HVM)
第二步:选择一个实例类型,选择 t2.micro(它包含在免费层中,我们每个月最多可以获得 750 小时的微实例)。
步骤 3:配置实例细节,除了 IAM 角色之外,其他都保留默认值。使用 S3 访问权限创建新角色。选择“创建新的 IAM 角色”。
创建新的 IAM 角色
我们将被重定向到“IAM 角色”页面,在这里我们可以选择创建角色,然后选择 EC2
选择创建角色
选择 EC2
附加“AmazonS3FullAccess”策略来读写 S3 存储桶,并为角色命名。点击创建角色。
附加 S3FullAccess 策略,以便我们拥有对 S3 的读写权限
给出角色名称
返回到“启动实例”页面,点击“IAM 角色”旁边的“刷新”,选择我们刚刚创建的角色,然后点击“查看并启动”。如果需要,我们还可以设置存储、标记和配置安全组,但目前,默认设置是好的。
选择 IAM 角色
我们将转到步骤 7:查看实例启动-点击启动。系统将提示我们创建或选择一个密钥对。选择 create a new pair 并给它一个名字,下载密钥对,并点击 launch instance。
创建新的密钥对并启动实例
创建实例后,选择 view instance。然后选择我们刚刚创建的实例并点击 connect。
选择实例并点击连接
复制“示例”代码,并在计算机上的命令提示符下连接到实例。
复制示例代码并将其粘贴到命令提示符下
如示例所示粘贴 ssh 命令,更改密钥(my_key.pem)的路径,然后按 enter 键。一旦我们连接到我们的命令提示符,它应该看起来像这样。
命令提示符
在虚拟环境中安装我们需要的所有依赖项(库),将依赖项打包成一个 zip 文件,并将其导出到 S3
安装、打包和导出依赖项
按照上面的代码,我们已经成功地将打包的 zip 文件导出到一个 S3 桶中。
创建并添加 Lambda 图层
选择 AWS 控制台左上角的服务,导航到 AWS lambda,然后导航到 层。 选择创建图层。******
选择创建层
复制我们上传到 S3 桶的 zip 文件的对象 URL ,并将其粘贴到“亚马逊 S3 链接 URL”文本框中。点击创建。
复制对象 URL
粘贴 S3 链接,选择兼容运行时
选择添加层,并选择我们创建的层和版本。点击添加。
添加层
选择你刚刚在最后一步创建的层,点击添加
创建 Lambda 函数
在 AWS lambda 控制台上,选择函数,然后点击创建函数。给函数起一个名字,并选择用来编写函数的语言。点击创建。
创建函数
给出函数名并选择运行时
更新 Lambda 函数来提取、转换和加载数据。在这里,我使用熊猫读取 CSV 文件,并将其存储在 S3 桶中。这是我们可以执行转换并决定将数据加载到哪里的地方,在我们的例子中,它是一个 S3 存储桶。
λ处理器
选择 test,为测试事件输入一个名称,其余的保持默认。点击保存。再次点击 test,代码执行我们的 ETL 过程。
选择屏幕右上角的测试,并添加测试名称
给测试事件起一个名字,剩下的保持默认
最后一步:计划你的 ETL 过程
选择 AWS 控制台左上角的服务,导航到 CloudWatch,然后依次导航到事件和规则。选择创建规则。
服务-云观察-事件-规则-创建规则
*步骤 1:选择 schedule 后跟 Cron 表达式,输入 Cron 表达式(4 * ? )在每天 4:00 GMT 运行 Lambda 函数。
点击了解更多关于 Cron 的表情。
第 2 步:输入名称和描述。选择创建规则。
创建规则
给规则命名和描述
恭喜👏!!我们的 ETL 过程是自动化的,将每 24 小时在格林威治时间 4:00 更新一次。
PS:确保终止 EC2 以及任何弹性块存储(EBS ),这样您就不会超出自由层的使用范围。
祝您的无服务器之旅好运!我希望这篇文章是有帮助的,如果你有任何问题,请随时联系我。
**** [## Ashwin Muthiah Murugappan -市场监督后数据分析师
我是一名充满热情的工业工程研究生,拥有学*先进技术的巨大潜力
www.linkedin.com](https://www.linkedin.com/in/ashwinmuthiah/)****
自动化 Python 项目的各个方面
每个 Python 项目都可以从使用 Makefile、优化的 Docker 映像、配置良好的 CI/CD、代码质量工具等自动化中受益…
每个项目——不管你是在做 web 应用、一些数据科学还是人工智能——都可以受益于配置良好的 CI/CD、Docker 映像,它们既可以在开发中调试,又可以针对生产环境进行优化,或者受益于一些额外的代码质量工具,如 CodeClimate 或 SonarCloud 。所有这些都是我们将在本文中讨论的内容,我们将看到如何将它们添加到您的 Python 项目中!
这是上一篇关于创建 【终极】Python 项目设置 的文章的后续,所以在阅读本文之前,您可能需要检查一下。
TL;DR:这是我的储存库,里面有完整的源代码和文档:https://github.com/MartinHeinz/python-project-blueprint
用于开发的可调试 Docker 容器
有些人不喜欢 Docker,因为容器可能很难调试,或者因为它们的映像需要很长时间来构建。因此,让我们从这里开始,构建开发的理想映像——构建速度快且易于调试。
为了使映像易于调试,我们将需要基本映像,它包括所有我们调试时可能需要的工具——比如bash
、vim
、netcat
、wget
、cat
、find
、grep
等。似乎是这项任务的理想人选。默认情况下,它包括许多工具,我们可以很容易地安装所有缺少的东西。这个基础图像很厚,但这并不重要,因为它将只用于开发。你可能也注意到了,我选择了非常特殊的镜像锁定 Python 和 Debian 的两个版本——这是有意的,因为我们想最小化由 Python 或 Debian 的更新的、可能不兼容的版本引起的“破损”的可能性。
作为替代方案,您可以使用基于阿尔卑斯山的图像。然而,这可能会导致一些问题,因为它使用了musl libc
而不是 Python 所依赖的glibc
。所以,只要记住这一点,如果决定选择这条路线。
至于构建的速度,我们将利用多阶段构建来允许我们缓存尽可能多的层。这样我们可以避免下载依赖项和工具,如gcc
,以及我们的应用程序所需的所有库(从requirements.txt
)。
为了进一步加快速度,我们将从前面提到的python:3.8.1-buster
创建自定义基础映像,这将包括我们需要的所有工具,因为我们无法缓存下载和安装这些工具到最终转轮映像所需的步骤。
说够了,让我们看看Dockerfile
:
上面你可以看到,在创建最终的流道图像之前,我们将通过 3 个中间图像。其中第一个被命名为builder
。它下载了构建最终应用程序所需的所有必要库,包括gcc
和 Python 虚拟环境。安装后,它还创建实际的虚拟环境,然后由下一个映像使用。
接下来是builder-venv
映像,它将我们的依赖项列表(requirements.txt
)复制到映像中,然后安装它。缓存需要这个中间映像,因为我们只希望在requirements.txt
改变时安装库,否则我们就使用缓存。
在创建最终图像之前,我们首先要对我们的应用程序进行测试。这就是在tester
图像中发生的情况。我们将源代码复制到映像中并运行测试。如果他们通过,我们将继续进行runner
。
对于跑步者图像,我们使用自定义图像,包括一些普通 Debian 图像中没有的额外图像,如vim
或netcat
。你可以在 Docker Hub 这里找到这张图片,你也可以在base.Dockerfile
这里查看非常简单的Dockerfile
。因此,我们在这个最终映像中要做的是——首先,我们从tester
映像中复制包含所有已安装依赖项的虚拟环境,接下来,我们复制已测试的应用程序。现在我们已经有了映像中的所有源代码,我们移动到应用程序所在的目录,然后设置ENTRYPOINT
以便它在映像启动时运行我们的应用程序。出于安全原因,我们还将USER
设置为 1001 ,因为最佳实践告诉我们永远不要在root
用户下运行容器。最后两行设置图像的标签。当使用make
目标运行构建时,这些将被替换/填充,稍后我们将看到。
用于生产的优化码头集装箱
对于生产级图像,我们希望确保它们小巧、安全、快速。我个人最喜欢的任务是来自distroles项目的 Python 图像。然而什么是distroles?
让我这么说吧——在一个理想的世界中,每个人都将使用FROM scratch
作为他们的基础图像来构建他们的图像(即空图像)。然而,这不是我们大多数人想做的,因为它需要你静态地链接你的二进制文件,等等。这就是distroles发挥作用的地方——这是大家的FROM scratch
。
好了,现在来实际描述一下发行版是什么。这是由谷歌制作的一组图像,包含你的应用程序所需的最少内容,这意味着没有外壳、包管理器或任何其他工具会使图像膨胀,并为安全扫描仪(如 CVE )产生信号噪声,从而更难建立合规性。
既然我们知道我们在处理什么,让我们看看生产...实际上,我们不会改变太多,只有两行:
我们需要改变的只是构建和运行应用程序的基础映像!但是差别是相当大的——我们的开发映像是 1.03GB,而这一个只有 103MB,这是相当大的差别!我知道,我已经能听到你了— “但是阿尔卑斯山可以更小!”是的,没错,但是大小没那么重要。你只会在下载/上传的时候注意到图片的大小,这并不常*。当图像运行时,大小根本不重要。比尺寸更重要的是安全,在这方面distroles肯定更胜一筹,因为 Alpine (这是一个很好的选择)有很多额外的包,增加了攻击面。**
在谈论发行版时,最后值得一提的是调试映像。考虑到发行版不包含任何外壳(甚至不包含sh
),当你需要调试和探索时,这变得相当棘手。为此,所有的发行版镜像都有debug
版本。因此,当便便遇到麻烦时,您可以使用debug
标记构建您的生产映像,并将其部署在您的正常映像旁边,执行到其中,并执行例如线程转储。你可以像这样使用python3
镜像的调试版本:
一切只需一个命令
所有的Dockerfiles
都准备好了,让我们用Makefile
来自动化它吧!我们要做的第一件事是用 Docker 构建我们的应用程序。因此,要构建开发映像,我们可以执行make build-dev
,它运行以下目标:
该目标通过首先用运行git describe
然后运行docker build
创建的图像名称和标签替换dev.Dockerfile
底部的标签来构建图像。
接下来—使用make build-prod VERSION=1.0.0
进行生产建设:
这一个与前面的目标非常相似,但是在上面的例子1.0.0
中,我们将使用版本作为参数传递,而不是使用git
标签作为版本。
当你在 Docker 中运行所有东西时,你将需要在 Docker 中调试它,为此,有以下目标:
从上面我们可以看到入口点被bash
覆盖,容器命令被参数覆盖。通过这种方式,我们可以直接进入容器,或者运行一个 off 命令,就像上面的例子一样。
当我们完成编码并希望将图像推送到 Docker 注册表时,我们可以使用make push VERSION=0.0.2
。让我们看看目标做了什么:
它首先运行我们之前看到的build-prod
目标,然后只运行docker push
。这假设你已经登录到 Docker 注册表,所以在运行之前你需要运行docker login
。
最后一个目标是清理码头工件。它使用被替换到Dockerfiles
中的name
标签来过滤并找到需要删除的工件:
你可以在我的知识库中找到这个Makefile
的完整代码清单:https://github . com/MartinHeinz/python-project-blue print/blob/master/Makefile
具有 GitHub 操作的 CI/CD
现在,让我们使用所有这些方便的make
目标来设置我们的 CI/CD。我们将使用 GitHub Actions 和 GitHub Package Registry 来构建我们的管道(作业)和存储我们的图像。这些到底是什么?
- **GitHub 动作是作业/管道帮助你自动化你的开发工作流程。您可以使用它们来创建单独的任务,然后将它们合并到定制的工作流中,然后在每次推送至存储库或创建发布时执行这些工作流。
- **GitHub 包注册表是一个包托管服务,与 GitHub 完全集成。它允许您存储各种类型的包,例如 Ruby gems 或 npm 包。我们将使用它来存储我们的 Docker 图像。如果你不熟悉 GitHub 包注册表并且想要更多关于它的信息,那么你可以在这里查看我的博客文章。
现在,要使用 GitHub 动作,我们需要创建工作流,这些工作流将基于我们选择的触发器(例如,推送至存储库)来执行。这些工作流是位于我们存储库中.github/workflows
目录下的 YAML 文件:
在那里,我们将创建两个文件build-test.yml
和push.yml
。首先,build-test.yml
将包含两个作业,每次推送至存储库时都会触发这两个作业,让我们来看看这些作业:
名为build
的第一个作业验证了我们的应用程序可以通过运行我们的make build-dev
目标来构建。在运行它之前,它首先通过执行发布在 GitHub 上的动作checkout
来检查我们的存储库。
第二项工作稍微复杂一些。它针对我们的应用程序以及 3 个 linters(代码质量检查器)运行测试。与之前的工作一样,我们使用checkout@v1
动作来获取源代码。之后,我们运行另一个名为setup-python@v1
的已发布操作,它为我们建立了 python 环境(你可以在这里找到关于它的详细信息)。现在我们有了 python 环境,我们还需要来自requirements.txt
的应用程序依赖项,我们用pip
安装它。此时,我们可以继续运行make test
目标,这将触发我们的 Pytest 套件。如果我们的测试套件通过,我们将继续安装前面提到的棉条- 皮林特、薄片 8 和土匪。最后,我们运行make lint
target,它触发每个 linters。
这就是构建/测试工作的全部内容,但是推送工作呢?让我们也回顾一下:
前 4 行定义了我们希望何时触发该作业。我们指定这个作业应该只在标签被推送到存储库的时候开始(*
指定标签名的模式——在这个例子中是——任何东西)。这样我们就不会在每次推送到存储库时都将 Docker 映像推送到 GitHub 包注册表中,而是只有在我们推送到指定应用程序新版本的标签时才会这样做。
现在是这项工作的主体——首先检查源代码,并将环境变量RELEASE_VERSION
设置为我们推送的git
标签。这是通过使用 GitHub 动作的内置::setenv
功能完成的(更多信息在此)。接下来,它使用存储在存储库中的REGISTRY_TOKEN
密码和启动工作流的用户的登录名(github.actor
)登录 Docker registry。最后,在最后一行运行push
target,它构建 prod image 并将其与之前作为 image 标记的git
标记一起放入注册表。
你可以在我的库中的文件里签出完整的代码清单。
使用 CodeClimate 进行代码质量检查
最后但同样重要的是,我们还将使用 CodeClimate 和 SonarCloud 添加代码质量检查。这些将与上面显示的我们的测试作业一起触发。所以,让我们给它添加几行:
我们从 CodeClimate 开始,首先导出GIT_BRANCH
变量,我们使用GITHUB_REF
环境变量检索该变量。接下来,我们下载code climatetest reporter 并使其可执行。接下来,我们使用它来格式化由我们的测试套件生成的覆盖率报告,在最后一行,我们将它发送给 CodeClimate ,它带有测试报告者 ID,我们将它存储在存储库 secrets 中。
至于 SonarCloud ,我们需要在我们的存储库中创建sonar-project.properties
文件,如下所示(该文件的值可以在右下角的 SonarCloud 仪表板上找到):
除此之外,我们可以使用现有的sonarcloud-github-action
,它为我们做了所有的工作。我们所要做的就是提供两个令牌- GitHub 一个是默认在存储库中的,另一个是 SonarCloud 令牌,我们可以从 SonarCloud 网站获得。
注意:关于如何获取和设置前面提到的所有令牌和秘密的步骤在资源库自述 这里 。
结论
就是这样!有了上面的工具、配置和代码,您就可以构建和自动化下一个 Python 项目的所有方面了!如果你需要更多关于这篇文章中所展示/讨论的主题的信息,那么就在这里查看我的资源库中的文档和代码:【https://github.com/MartinHeinz/python-project-blueprint如果你有任何建议/问题,请在资源库中提交问题,或者如果你喜欢我的这个小项目,就开始吧。🙂
资源
**本文最初发布于martinheinz . dev
使用开放式 python 库实现 GIS 和遥感工作流的自动化
实现空间 python 社区中一些最受欢迎的工具的实践指南
在我的职业生涯中,我使用 ArcGIS *台参与了许多地理空间相关的项目,我非常喜欢这个*台。这意味着我可以在具有尖端地理空间技术的项目中提供咨询,如多维栅格、深度学*和空间物联网自动化。考虑到这一点,我总是试图跟踪如何在没有 Esri 精美制作的系统的情况下执行我正在使用的 相同的操作。
在过去的几个周末,在异常乏味的隔离期间,我一直在编写这个小脚本,它将重现我一直在用 ESRI 的生活地图集开发的东西,以实现 NDVI 区域统计 ( 归一化差异植被指数,遥感中的经典)农村地块的。
这里的计划是在不借助任何 GIS 桌面软件的情况下执行整个地理处理和遥感例程。我们从一个包含我们感兴趣的一些宗地的图层和一个包含特殊立法适用的保护区的图层开始。python 之外什么都不允许!这是我们今天的计划:
- 检查 parcels geojson 图层中的无效几何并进行更正;
- 以公顷为单位计算每个地块的面积;
- 验证每个宗地是否与任何保护区相交;
- 计算每个宗地的相交面积,并在宗地属性中插入受保护区域的名称;
- 获得最新的五张没有云的 Sentinel-2 卫星图像;
- 计算每幅图像上的 NDVI;
- 计算分区统计数据(*均值、最小值、最大值和标准差)。戴夫。)为每个包裹上的 NDVI;
- 创建显示每个宗地中裁剪结果的地图。
我们开始吧
所以。重要的事情先来。我们必须导入存储有地块的 geojson 文件。为此,我们将使用 geopandas 库。如果你不熟悉它,我的建议是熟悉它。Geopandas 基本上用 python 模拟了我们在经典 GIS 桌面软件(GRASS、GDAL、ArcGIS、QGIS……)中使用的功能,其方式与数据科学家非常流行的工具 pandas 一致,允许对几何类型进行空间操作。
为了导入我们的 geojson,我们首先必须注意 geopandas 中的数据类型。基本上,当我们运行.read_file
方法时,我们给polygons
变量分配了一个geodataframe
类型。在每个geodataframe
内部总会有一个geoseries
,我们可以通过.geometry
方法访问它。一旦我们找到了geoseries
,我们就可以利用.isvalid
方法,为我们系列中的每条记录生成一个真/假值列表。
当然,我们的数据集中存在无效的几何图形。这并不奇怪,因为这些地块来自汽车登记处,巴西的每个农村土地所有者都必须自行申报他们自己的财产范围。
那么,我们如何解决这个问题呢?也许您*惯于运行 ArcGIS 或 QGIS 中的 excelent 无效几何检查工具,这些工具甚至会生成一份报告,说明表中每条记录的问题所在。但我们无法接触到地质公园里的那些东西。相反,我们将做一点小技巧来修正几何图形,对所有几何图形应用 0 米缓冲。
现在我们终于可以通过使用.plot
方法来看看我们的多边形了,这个方法实际上是从geopandas
中的matplotlib
组件继承来的。
这是快速了解我们的数据在空间上的样子的一种快速而有用的方法,但它与地图不同。
计算面积
因为我们想知道我们每块土地的公顷面积,我们需要确保我们的地理数据框架在投影坐标系中。如果您不熟悉坐标参考系统(CRS ),您至少需要知道的是地理坐标系统以度为单位(如纬度和经度),而投影坐标系统以距离为单位,使我们能够使用公制计算面积。从我们刚刚创建的绘图中,我们可以看到多边形可能是根据纬度和经度绘制的,大约在-15.7,-47.7 之间。如果我们运行print(polygons.crs)
,我们将得到epsg:4326
作为响应。有许多可用的坐标系统,因此 EPSG 系统是跟踪它们的一个非常好的方法; 4326 表示我们的地理数据框架在 WGS84 坐标系中——实际上是一个地理坐标系。
所以我们确实需要转换我们地理数据框架的坐标系。为此,我们必须首先决定我们将把它转换成哪个系统。在这一点上,我非常*惯于从一个系统转换到另一个系统,但如果你有点迷路,选择投影坐标系的一个好方法是使用 WGS84 系统的墨卡托通用横轴投影。所以你要做的就是找出你的数据在哪个 UTM 区域,这样你就知道那是你的数据面积失真最小的区域。一个很好的方法就是这个小小的网络应用。
我们知道我们的数据在[-15.7,-47.7 ]坐标附近的某个地方,所以现在我们知道这相当于 23 度 UTM 区,而且就在巴西利亚市旁边!
所以剩下的就是访问 EPSG 权威网站并检查我们选择的投影的 EPSG 代码。接下来,我们需要使用.to_crs
方法定义一个新的地理数据框架变量。
现在,我们可以在新的地理数据框架中创建一个新的列,我将其命名为area_ha
,并计算面积(单位为米,因为我们使用的是 UTM 投影),我们必须除以 10,000 才能得到公顷。
这是我们新的地理数据框架的头部。现在填充 area_ha 字段的值看起来比例正确。
检查覆盖
现在,我们可以导入提供给我们的第二个图层,该图层包含所有保护区(UCs,或Unidades de conservao),这些保护区可能代表我们正在分析的地块中农业用途的法律限制。我们将导入它,就像我们导入之前的 geojson 一样。这一次的主要区别在于,这段数据实际上有更多的字段,有保护区的名称、创建日期以及更多的法律信息。
一个更加丰富的数据集,用 geopanda 绘制。头法。
我们感兴趣的是将所有丰富的信息放入与给定保护区相交的地块的属性表中。使用叠加方法,Geopandas 实际上很容易做到这一点。它确实字面上的 正是我们要找的。在我们的示例中,它将创建一个新的地理数据框,其中每个地块的每个相交部分都有一条记录,并包含有关其相交的受保护区域的信息。这样,我们就可以像以前一样,以公顷为单位计算相交区域的新字段。
它看起来像以前的同一块地,但现在我们的土地被分成更小的部分,如果它们与任何保护区相交的话。另外,它们现在包含了更多有用的信息。
现在是遥感部分
我们已经完成了本文的 GIS 部分,现在事情变得有趣了。我们想很好地了解每个地块的植被状况,因此我们将尝试获取最新的(免费)卫星图像,并进行一些分析。有许多免费卫星图像的选项,如 [Landsat 系列](http://Landsat Sciencelandsat.gsfc.nasa.gov),但 ESA 的 Sentinel2 任务提供了体面的空间比例(20x20m 像素)的免费图像。
要访问它,我们可以使用不止一个库。哨兵枢纽是一个坚实的,ArcGIS 生活地图集是另一个。但我个人的选择是谷歌地球引擎,原因很简单:只需稍作改动,我们就可以用相同的代码访问来自 Landsat 和 Sentinel 的数据,而且它(仍然)可以免费使用——但让我们不要忘记谷歌地图 API 发生了什么。这里真正的缺点是 GEE 的 python API 没有很好的文档记录。
我们想做的事情相当简单。我们必须从 GEE 调用 Sentinel 2 图像集合,根据感兴趣的区域、日期和云百分比对其进行过滤,并获得集合中最新的五幅图像。为了获得感兴趣的区域,我们必须使用 geopandas 再运行一个命令,即.total_bounds
方法,这将为我们提供一个矩形的坐标,该矩形包含我们地块的全部范围。
我们已经获取了这五张最新的图片,并将它们存储在我们的collectionList
变量中。但是让我们看一看,以确保卫星图像确实符合我们的期望。为此,让我们使用地球引擎的.Image
,将其设置为 RGB 合成——在 Sentinel 2 中,这意味着使用波段 4、3 和 2——并使用 Ipython 的.display
绘制它。
看起来不错,巴西利亚。
计算 NDVI
这一点其实很简单。GEE 使得计算归一化差异变得非常容易,这正是 NDVI 的情况:
归一化差异植被指数 ( NDVI )是一个简单的图形指示器,用于评估被观测目标是否包含活的绿色植被。与其他波长相比,健康的植被(叶绿素)反射更多的近红外(NIR)和绿光。但是它吸收更多的红光和蓝光。
NDVI 通过测量近红外(植被强烈反射)和红光(植被吸收)之间的差来量化植被。像陆地卫星和 Sentinel-2 这样的卫星传感器都有必要的近红外和红光波段。
NDVI 公式,或近红外和红光之间的归一化差异。
在 GEE 中,我们只需要使用正确波段的.normalizedDifference
方法。在我们的例子中,是波段 8(近红外)和波段 4(红色)。通常情况下,就是这样,但我是一个老式的 GIS 极客,所以我需要在地图上查看我的数据,以确保一切正常。
为此,我将创建一个简单的树叶地图——一种使用 python 渲染传单地图的方法——并将 NDVI 栅格和地块 geojson 加载到其中。
区域统计很有趣
我们快完了。我们现在需要做的是恢复我们刚刚为每个地块中的五个哨兵 2 图像计算的 NDVI 数据。遥感领域的人们已经这样做了很多年,使用了一种叫做区域统计的东西。该工具存在于许多 GIS 桌面软件中,甚至在 GEE python API 中也是可行的-同样,文档记录很少。为了简单、易于访问和可靠,我的首选工具实际上是 rasterstats 。
问题是,到目前为止,我们一直在用自己的格式处理图像。并且 rasterstats 将需要那些老派。TIF 档案。所以我们要把图像导出到本地文件夹。
最后,这是奇迹发生的地方。让我们使用一个小 for 循环来打开每个本地 NDVI 栅格文件,计算每个地块的统计数据,然后将的*均值、最小值、最大值和标准偏差的结果附加到熊猫的数据帧中。
我们已经为每个图像的每个 stat 创建了一个字段,所以我们将为每种请求的统计类型(最小值、最大值、*均值和标准值)创建五个字段。戴夫。)
现在,我们可以像以前一样,通过绘制数据来可视化每个地块中的 NDVI 统计数据,只是这次我们可以告诉 matplotlib 使用哪一列和哪一种配色方案。由于结果看起来不错,我们可以将地理数据框架导出到 geojson 文件中,并与不太懂技术的同事共享。
这是我们最近的哨兵 2 图像的*均 NDVI 属性的可视化。
这是所有的乡亲
这一块就到此为止!我们已经成功实施了经典的地理处理和遥感工作流,无需使用 ArcGIS 或 QGIS 一次!你可以在我的 Github 页面找到整个工作流程。如果你有问题或建议,不要犹豫,随时给我写信!
如果你喜欢这篇文章,考虑给我买一杯咖啡,这样我就可以继续写更多的文章了!
嘿👋我刚刚在这里创建了一个页面。你现在可以给我买杯咖啡了!
www.buymeacoffee.com](https://www.buymeacoffee.com/guilhermeiablo) [## guillermeiablo/ndvistats
jupyter Notebook com flow to cálculo de statistics zones para poli gonos selectors utilizations to geo pandas,google…
github.com](https://github.com/guilhermeiablo/ndvistats)
使用 GitLab CI 自动部署 Lambda 模块
在 Unsplash 上 Sai Kiran Anagani 拍摄的照片
在使用 terraform lambda 模块时,我很难找到最佳的存储库架构来自动化我的 lambdas 部署。我找不到任何可以作为指南的文章,这就是我写这篇文章的原因。
在从事大型项目时,项目组织是必备的。在这个故事中,您将会看到一种组织您的存储库的方法,这样可以简化部署过程,使其更具可扩展性。
在本文中,我们将构建以下存储库架构:
- Lambda 模块:包含 Terraform Lambda 模块的存储库。
- Lambda-Infra :包含部署到 AWS 中的 Terraform 代码的存储库。
- Lambda 代码:包含使用 Gitlab-CI 进行部署的 Lambda 代码的存储库。
λ模块
由 HashiCorp: 定义
**模块是一起使用的多个资源的容器。
使用 terraform 模块解决了组织配置、封装配置、重用配置等问题,并且它提供了一致性并确保最佳实践。
我们将使用一个 AWS lambda 模块,可以在这里找到。我不会深入讨论如何构建 lambda 模块的细节,因为这不是本文的主要目标。
λ-Infra
一旦你准备好了你的模块,你就可以建立一个仓库来集中你所有的 lambdas 基础设施。在下面的例子中,每个。tf* 代表不同的λ。*
*.
├── README.md
├── lambda_alarm.tf
├── lambda_general.tf
├── lambda_sms.tf*
准备好 lambda 模块后,你可以用它来构建你的 lambda 基础设施。
从下面的代码中可以看出,我们将 lambda zip 文件存储在 s3 bucket 中,该 bucket 已经激活了版本控制。这是至关重要的一步,因为 s3 中 zip 文件的版本 id* 将触发 lambda 的重新部署,以防代码发生任何变化。*
在上面的例子中, lambda-sms.zip 是我们的 lambda 源代码,将在下面定义。
λ代码
为了自动化 lambda 部署,有必要压缩 lambda 代码并将其放入 s3 存储桶。
首先,让我们检查我们的 lambda 代码示例。
*.
├── README.md
└── .gitlab-ci.yml
└── lambda
├── config.py
├── database.py
├── handler.py
├── package
├── queries
│ └── save_data.sql
└── requirements.txt*
我们的 CI 将负责:
- 运行 Flake8 以检查语法错误和林挺惯例。
- 安装在 requirements.txt 中定义的 lambda 依赖项
- 压缩我们的代码
- 使用 AWS CLI 将其移动到 AWS s3 存储桶
遵循 AWS 中的最小特权原则,您应该创建一个只有 Put-Object 权限的 IAM 用户:
您将在 GitLab 项目的 CICD 设置中存储您的 AWS CLI 凭据:
GitLab CICD 设定截图
一切就绪后,当你将代码推送到主分支时,你的 lambda 代码将被压缩并存储在你的 S3 桶中。
结论
让我们看一下所有的部署程序:
- 创建您的 lambda 代码,并将其推送到您的 GitLab 库。
- 然后,您的代码将被压缩并存储在您的版本化 s3 存储桶中。
- 用 l ambda-infra 代码运行 terraform。
- Terraform 将检查您的 lambda 源代码的版本 id 的变化。
- 如果它检测到新的。zip 文件已经上传到 s3,它将重新部署您的 lambda。
这种架构让我的生活变得更加轻松,给了我的代码更多的可伸缩性。我希望它能像帮助我一样帮助你!
参考
当您使用 Terraform 管理基础设施时,您将创建越来越复杂的配置。没有…
learn.hashicorp.com](https://learn.hashicorp.com/tutorials/terraform/module?in=terraform/modules) [## 自动从 Gitlab 上传文件到 S3
更新于 2017 年 12 月 3 日。最近开始使用 GitLab 和他们的自动化管道(GitLab CI)来托管…
correctme.ifiamwrong.com](https://correctme.ifiamwrong.com/posts/gitlabcitos3/)*
使用 Amazon Glue、Amazon SageMaker 和 AWS Step 函数 Data Science SDK 实现机器学*工作流的自动化
使用 Amazon Glue、Amazon SageMaker 和 AWS Step 函数 Data Science SDK 实现机器学*工作流的自动化
自动化机器学*工作流有助于建立可重复和可再现的机器学*模型。这是将机器学*项目投入生产的关键一步,因为我们希望确保我们的模型是最新的,并且在新数据上表现良好。亚马逊胶水、亚马逊 SageMaker 和 AWS 步骤函数可以帮助在托管环境中自动执行从数据处理到模型部署的机器学*工作流。
在这篇文章中,我将使用上面提到的 AWS 服务来开发和自动化一个机器学*工作流,其中 PySpark on AWS Glue 用于数据准备和处理,Amazon SageMaker 用于模型训练和批量预测。这样做的目的是为了展示工程师和数据科学家如何快速轻松地创建自动化的机器学*工作流。
AWS 服务:
AWS Glue 是一项完全托管的提取、转换和加载(ETL)服务,使客户能够轻松准备和加载数据进行分析。
Amazon SageMaker 是一项完全托管的服务,使数据科学家能够构建、训练、调整和部署任何规模的机器学*模型。该服务提供了一个功能强大、可扩展且易于使用的计算环境。
Amazon Step Functions 让您可以将多个 AWS 服务协调到无服务器工作流中,以便您可以快速构建和更新应用。
AWS Step 函数 Data Science SDK 是一个开源库,允许数据科学家使用 Amazon SageMaker 和 Amazon Step 函数轻松创建处理和发布机器学*模型的工作流。
概观
编排机器学*工作流程是生产 ML 的关键。为此,我用 AWS Step 函数和 Amazon SageMaker 创建了一个简单的端到端教程,使用了 AWS Data Science Step 函数 SDK。你可以在Amazon sage maker Samples GitHub仓库中找到完整的例子。
步伐
在这篇文章中,我们将按照以下步骤创建一个机器学*工作流:
- 在 AWS Glue 上编写用于数据处理的 PySpark 脚本
- 训练一个模型,使用亚马逊 SageMaker XGboost 算法
- 部署模型
- 用亚马逊 SageMaker 批量转换进行批量预测
先决条件
为了完成这个例子,我建议您按照亚马逊 SageMaker workshop 网站上的步骤启动一个亚马逊 SageMaker 笔记本实例。我们还建议您阅读如何创建运行 Amazon Glue 作业所需的 IAM 角色和权限。
创建 PySpark 脚本在 Amazon Glue 上运行
我假设您已经熟悉编写 PySpark 作业。这个例子触及了 Glue 的基础,对于更复杂的数据转换,请仔细阅读亚马逊 Glue 和 PySpark。下面的代码片段展示了 AWS Glue 中简单的数据转换。
示例 Amazon Glue PySpark ETL 脚本
创建 PySpark 脚本后,该脚本必须上传到 S3 的一个位置,Amazon Glue 可以访问该位置:
$ aws s3 cp glue-etl-processing.py s3://my-code-bucket/glue/glue-etl-processing.py
一旦以上成功完成,我们将使用 AWS Python SDK 、 Boto3 来创建一个胶合作业。请参*下面的示例:
准备工作流程
在这篇文章中,我们将使用 Amazon SageMaker 内置的 XGBoost 算法来训练和托管一个回归模型。数据集来自视频游戏销售预测亚马逊 SageMaker Workshop 示例。然而,我们不会深入研究完整的细节,因为它们可以在亚马逊 SageMaker Workshop 网站上找到。
为了准备工作流,我将使用AWS Step Functions Data Science SDK,这使得在 AWS 上创建 step function 状态机变得更加容易和快速。在下面的步骤中,我将展示如何为数据处理、Amazon SageMaker 模型培训和部署步骤以及 Amazon SageMaker 批量转换步骤创建一个粘合步骤。最后,我们将把这些步骤链接在一起,创建一个工作流,然后用 AWS 步骤函数执行该工作流。
涂胶作业步骤
AWS 将作业步骤与 AWS 步骤函数 SDK 粘合在一起
亚马逊 SageMaker 估算器和训练步骤
AWS 步骤函数 SDK 训练和模型步骤
最后,让我们将这些步骤串联起来,创建一个工作流
AWS 步骤功能 SDK 链工作流步骤
使用 Amazon Glue、Amazon SageMaker 和 AWS Step 函数 Data Science SDK 实现机器学*工作流的自动化
通过批量预测实现工作流程自动化
在本教程中,我们演示了如何使用 AWS 步骤函数 SDK 运行 orchestrate 批处理推理机器学*学*管道,从使用Amazon Glueforpy spark进行数据处理开始,到在 Amazon SageMaker 上进行模型创建和批处理推理。
结论
在这个例子中,我演示了如何使用 Amazon Step 函数创建机器学*工作流。您可以使用 Amazon CloudWatch 预定事件自动进行模型再训练。因为您可以每天进行批量预测,所以您可以用 AWS Glue 准备数据,运行批量预测,并用 step 函数 SDK 将整个步骤链接在一起。您还可以添加一个 SNSStep ,这样您就可以通过电子邮件、 slack 或 SMS 获得关于您的 ML 工作流状态的通知。许多可能性…
使用 Amazon Glue、Amazon SageMaker 和 AWS Step Functions Data Science SDK 以及 SNS 通知实现机器学*工作流自动化
进一步阅读
请分享您的想法和意*,期待您的反馈。您可以通过电子邮件联系我,在 Twitter 上关注我,或者在 LinkedIn 上与我联系。等不及收到你的来信了!!
使用 Bash 脚本自动构建 MXNet
为发布软件而构建二进制文件是非常辛苦的。但是使用 Bash 脚本的自动化证明是非常值得的!
作为测试 Apache MXNet 的一部分,我被委托为 Apache MXNet 内部分支构建二进制文件。
在构建和测试 MXNet 二进制文件时,我必须运行无数步骤。此外,该管道必须复制 8 次,以符合 Apache MXNet 支持的各种风格,如 CPU/GPU、+/- MKL 和+/-大张量(2 =8)
这项工作时间紧迫,同时也是重复的。需要按顺序执行某一组步骤。此外,它必须在多台机器上通过微小的调整进行复制。所有这些都需要自动化。
任何写了两遍以上的东西都可以而且应该自动化。
Bash (shell 脚本)是完成这项任务的理想选择。由于之前没有什么经验,我热衷于实时应用它。这里尝试捕捉我在这个过程中遇到的与 shell 脚本相关的概念。
(哈希)+!(砰)= #!(舍邦)
从现有 shell 脚本中调用另一个 shell 脚本 拥有多个 shell 脚本来执行特定任务是一个非常常*的用例(考虑模块化,但在文件级而不是函数级)。由于需要调用另一个脚本,我很快意识到为什么我们需要shebang
。
有了 bash 的许多替代品(zsh,ksh,sh),在顶部添加一个 shebang 告诉操作系统(是的!OS ftw!)来使用提到的库。程序连同绝对路径(/usr/bin/env
)。如果未指定,操作系统将采用默认设置。
打印/记录
学*任何语言、测试任何代码、调试任何东西的第一步都是从打印语句开始的:控制台日志记录。打印到标准输出(标准输出)。
echo
向 shell 脚本传递参数
./pip_build_test.sh mkl
给定这个命令,mkl
是我们需要处理的参数。
在 bash 脚本中使用变量$1、$2 等访问参数
$1 是第一个参数(当然是在命令之后): mkl
另一种传递参数的方法叫做 Flags 方法,在这篇 livewire 文章中有很好的解释。
担心暴露凭据?
git 命令之一(针对托管在 AWS 代码提交上的存储库)需要用户名和密码。
git clone [https://username:password@server](https://username:)
虽然上面提到的方法在谷歌上的顶级搜索是存在的,但它肯定不是最好的方法。
公开 git(或任何)凭证从来都不是一个好主意。
又快又脏的变通方法?省略用户名和密码,让用户自己在机器上配置。具有讽刺意味的是,这是自动化过程中唯一的手工操作。
更好的解决方案?
- git-secrets
- AWS 秘密管理器 / SSH 密钥
- 环境变量!
将命令输出存储到变量中
有时,我们需要将命令的结果存储在一个变量中以备将来使用。可以使用var=$(command)
来实现
条件句
这让我们回到了阿尔戈尔!if
、else
得到其次是fi
、
镜像词的使用,得益于斯蒂芬伯恩、被从 Algol 移植到 Unix Shell 脚本语言。
if [[ condition ]]
then
echo "yes"
else
echo "no"
条件可以利用各种标志。例如,少数条件表达式-
-d
:搜索目录
-f
:搜索文件
-z
:如果字符串长度为零,则返回 True
关于进一步的细节man bash
命令。
旁注 : 测试 vs 扩展测试辩论。
[]
vs [[]]
:跟双[[
走。它有增强功能。为什么?改为。
将用户输入读入变量
此外,通过允许用户输入一个可以存储在变量中的值(也是为了将来使用),可以实现灵活性。
将可用性提高一个档次,我们可以允许用户使用
read -p “Continue? (Y/N): “ confirm && [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]] || exit 1
来确认
安全第一。终于。
感谢佩德罗·拉罗伊指出 2 个方便的细节。
首先要做的事情。为了使 bash 脚本安全,使用set -euxo pipefail
很重要。否则,bash 脚本中的错误将不会被发现,因为脚本将总是返回 true。其次,尽可能使用 Python 而不是 Bash。
为什么你会问?去阅读这篇关于编写安全 Shell 脚本的文章。
将脚本转换成可执行文件
说了这么多,做了这么多,还有最后一件事:将一个.sh
文件转换成一个可执行的.sh
脚本
chmod u+x <name of the file>.sh
现在,你可以选择其他权限来代替u
- u 代表用户。
- g 代表组。
- o 代表别人。
- a 代表全部。
最终外壳脚本
pip _ build _ 测试. sh
注意:aws-cli 一般可以使用
sudo apt install awscli
安装
上述使用 awscli-bundle 的过程是旧版本 Ubuntu 14.04 所必需的。(你能相信人们还在用 14.04 吗?老是金!)
这只是我典型的一天工作的一个例子。为 Apache MXNet 做贡献教会了我比在学校里学到的更多的东西。我们欢迎更多这样的贡献在我们的 Github 回购上:【https://github.com/apache/incubator-mxnet/
资源
感谢贡献一个堆栈溢出的答案!请务必回答问题。提供详细信息并分享…
stackoverflow.com](https://stackoverflow.com/questions/8967902/why-do-you-need-to-put-bin-bash-at-the-beginning-of-a-script-file) [## 如何将 grep 命令结果存储在 shell 中的某个变量中
感谢贡献一个堆栈溢出的答案!请务必回答问题。提供详细信息并分享…
stackoverflow.com](https://stackoverflow.com/questions/19951369/how-to-store-grep-command-result-in-some-variable-in-shell) [## 如何在 Bash 中将用户输入读入一个变量?
感谢贡献一个堆栈溢出的答案!请务必回答问题。提供详细信息并分享…
stackoverflow.com](https://stackoverflow.com/questions/18544359/how-to-read-user-input-into-a-variable-in-bash) [## 在 AWS 代码提交中使用用户名和密码进行 Git 拉/克隆
我需要使用 https url 作为一个命令行命令来执行 git pull。我需要将这个命令集成到 bash 脚本中。但是…
stackoverflow.com](https://stackoverflow.com/questions/46823193/git-pull-clone-with-username-and-password-in-aws-code-commit) [## 在线 Bash 编译器-在线 Bash 编辑器-在线 Bash IDE -在线 Bash 编码-练* Bash…
在线 Bash 编译器,在线 Bash 编辑器,在线 Bash IDE,在线 Bash 编码,在线练* Bash,执行 Bash…
www.tutorialspoint.com](https://www.tutorialspoint.com/execute_bash_online.php)
出于隐私和安全的考虑,剧本的内容有所改动。
用 Python 实现求职自动化
使用美素和硒
资料来源:unsplash.com
动机
我目前正在寻找一个新的数据科学职位,但我发现令人沮丧的是,有这么多不同的网站,在不同的时间列出不同的工作。不断检查每个网站以查看发布了哪些新角色变得很费力。
但后来我想起来了;我是一名数据科学家。一定有更简单的方法来自动化这个过程。因此,我决定创建一个管道,它包括以下步骤,并使用 Python 自动执行部分流程:
1。定期提取所有新的职位发布
我决定写一些 Python 代码来从我最常查看的网站上搜集信息。这是我将在这篇文章中概述的。
2。根据我的技能和兴趣查看新的招聘信息
我本来可以尝试自动化这一点,但我不想冒险忽略一个可能因为我放入代码的标准而感兴趣的工作。我决定手动检查我的网页抓取返回的帖子。
3。每周花一次时间申请符合条件的新工作。
我听说有人把这个舞台自动化了。然而,我相信如果你花时间和精力来定制应用程序,并且在原则上有点不同意这种方法,机会会更好。
注:本帖讨论的所有代码在 这里 都有。我也在底部分享了我最喜欢的学*资源。
我决定使用 BeautifulSoup 和 Selenium ,如果需要的话,我的进口声明如下:
来自 Indeed.co.uk 的工作信息—使用 BeautifulSoup
我寻找数据科学工作的主要网站之一是 Indeed.co.uk。
(1)提取初始 HTML 数据
我很高兴地看到,他们有一个标准化的网址格式,这将使网络抓取更容易。网址是“indeed.co.uk/jobs?”依次为【q =职位】&【l =位置】 — 如下:
在伦敦 Indeed.co.uk 寻找“数据科学家”的工作
这使得修改职位名称和位置变得相当容易。我决定创建一个函数,将职位和位置作为参数,这样任何人都可以定制搜索:
使用来自 urllib 的 urlencode 函数使我能够插入参数来创建完整的 url。我在 URL 中包含了“fromage=list”和“sort=date ”,这样就只显示了最近的工作。
然后,在 BeautifulSoup 的便捷帮助下,我可以提取 HTML 并适当地解析它。
最后,我想找到包含所有工作列表的适当的
。我通过打开 URL(indeed.co.uk/jobs?q=data+scientist&l =伦敦)并使用‘Inspect’元素找到了它。使用这个,我可以看到包含了所有的工作列表,所以我使用 soup . find(id = " results coll ")来选择所有这些工作。
截图:Indeed.co.uk 网站
(2)提取工作细节
现在我有了包含所有工作列表的 HTML“汤”,下一步是提取我想要的信息,它们是:
- 职位名称
- 这些公司
- 完整职务简介的链接
- 列出了日期
对于其中的每一个,我再次使用 Inspect 来识别适当的部分,并使用了。find() 函数来识别它们,如下:
(3)迭代每个工作列表
使用‘Inspect’我看到每个工作卡都包含在一个 div 中,该 div 的类为‘jobsearch-SerpJobCard ’,所以我使用了 BeautifulSoup 的。find_all 功能如下:
然后,对于每张卡,我想提取上面列出的 4 条关键信息,并将它们保存在一个列表中。
我想让我的函数通用化,这样人们可以选择他们想要搜索的特征(在列出的职位、公司、链接和日期之外),所以我创建了一个列表‘desired _ characts’来指定这一点。
对于每个特征,我循环并将其添加到列表中,如下所示:
最后,我将所有这些放入一个 jobs_list 中,然后可以导出为所选的格式 Excel、DataFrame 或其他格式:
使用“cols”使我能够根据提取的特征为 jobs_list 字典的每个键指定标题。
“extracted_info”是一个列表列表;例如,每个列表包含所有职位或所有公司。
使用这些数据结构使得编译最终的 jobs_list 字典更加容易。
(4)存储和保存作业
我将“jobs_list”字典转换为数据帧,然后将其导出到用户使用以下函数选择的文件名和文件类型:
(5)集成到单个函数调用中
最后,我希望用户可以通过一个函数调用来完成上述所有工作。我是这样做的:
令人满意的是,这产生了一个可以很容易地调用的最终结果,如下所示:
来自 CWjobs.co.uk 的工作刮擦——使用硒
下一步是概括我的脚本,也从其他网站的工作列表。另一个我经常搜索的网站是 CWjobs。然而,添加这一点被证明是一个更大的挑战。
当我检查 URL 时,我注意到关键字参数没有一致的模式。
因此,我决定使用 Selenium Webdriver 与网站进行交互——输入指定的职位和位置,并检索搜索结果。
(1)下载并启动驱动程序
我使用 Google Chrome,所以我从这里的下载了合适的 web 驱动程序,并将其添加到我的工作目录中。然后,我创建了一个函数来启动驱动程序,如下所示:
(如果使用替代浏览器,您需要下载相关驱动程序,并确保其名称和位置如上所述)
(2)使用驱动程序提取作业信息 HTML‘soup’
(3)提取工作信息
接下来的步骤与上面真正的 job scraping 中的步骤 2 和 3 相同,只是针对 CWjobs 的 DOM 结构进行了调整,所以我在这里不再赘述。
一旦我完成了代码,看到我的网络浏览器被控制,而我没有触摸鼠标或键盘,这是非常酷的:
屏幕录制:web 驱动程序的使用
包扎
我对我的功能代码非常满意,并决定就此打住(毕竟我确实不得不申请工作)。
在 GitHub 上快速搜索发现,人们已经为 LinkedIn 和其他一些*台制作了类似的工作抓取工具。
我将代码上传到了一个带有自述文件的 GitHub 库中,以防其他人想用这个代码完成工作。
然后我坐下来,对自己感到非常满意。现在,我只是每周运行一次脚本,然后挑选出我想申请的工作。
老实说,使用脚本比手工操作节省的时间和精力是微不足道的。然而,我从编写代码中获得了很多乐趣,并且在 BeautifulSoup 和 Selenium 上得到了更多的实践。
作为一个潜在的下一步,我可能会在 Amazon Lambda 上设置这个,这样它就可以每周自动搜索一次新的工作,而不需要我去做。所以如果我真的做了,将来可能会有一个关于这个的帖子。
我希望这是有帮助的/有趣的!
我在做这个项目时找到的最好的资源
https://realpython.com/beautiful-soup-web-scraper-python/——一个关于网页抓取的很好的概述/复*,还有漂亮的汤
https://towards data science . com/looking-a-house-build-a-web-scraper-to-help-you-5b ab 25 badc 83 e—web scraper 的另一个有趣的用例:识别潜在的可购买房屋
https://towards data science . com/controlling-the-web-with-python-6 fceb 22 C5 f 08—Selenium 的精彩介绍
https://www.youtube.com/watch?v=-vqRAkcWoM—硒在使用中的精彩演示
https://github.com/kirkhunter/linkedin-jobs-scraper——一个领英刮刀,既展示硒又美汤
我制作了一个关于这个的视频
使用人工智能实现在线监考自动化
基于视觉和音频的半自动监考功能,可防止在线考试中的作弊,并同时监控多名学生。
随着新冠肺炎的出现,远程学*蓬勃发展。学校和大学可能已经关闭,但他们转向像微软团队这样的应用程序来完成他们的学年。然而,没有解决考试的办法。有些人把它改成了作业形式,学生可以从网上复制粘贴,而有些人干脆取消了。如果我们的生活方式要成为新的标准,就需要一些解决方案。
ETS 组织托福和 GRE 等考试,允许学生在家考试,在整个考试过程中,监考老师会全程监督。由于所需的劳动力,大规模实施这一计划是不可行的。因此,让我们用 python 创建一个人工智能,它可以使用网络摄像头和笔记本电脑麦克风本身来监控学生,并使教师能够同时监控多个学生。完整的代码可以在我的 Github repo 上找到。
人工智能将具有四种基于视觉的功能,这些功能使用多线程技术结合起来,以便它们能够协同工作:
- 视线跟踪
- 嘴巴张开或闭上
- 人数统计
- 手机检测
除此之外,来自麦克风的语音将被记录,转换为文本,并且还将与试卷的文本进行比较,以报告考生说出的常用单词的数量。
要求
- OpenCV
- Dlib
- 张量流
- 语音识别
- PyAudio
- NLTK
基于视觉的技术
视线跟踪
照片由 S N Pattenden 在 Unsplash 上拍摄
我们的目标是跟踪考生的眼球,并报告他是否在向左、向右或向上看,他可能是在看笔记本或向某人发出信号。这可以通过使用 Dlib 的面部关键点检测器和 OpenCV 进行进一步的图像处理来完成。我已经写了一篇关于如何进行实时眼球追踪的文章,详细解释了后面将要用到的方法。
在本教程中,学*通过 python 中的网络摄像头创建一个实时凝视探测器。
towardsdatascience.com](/real-time-eye-tracking-using-opencv-and-dlib-b504ca724ac6)
嘴部检测
嘴部追踪结果
这和眼睛检测很像。Dlib 的面部关键点再次用于该任务,并且要求测试者坐直(如他在测试中所做的那样),并且记录 100 帧的嘴唇关键点(5 个外部对和 3 个内部对)之间的距离并取*均值。
如果用户张开他/她的嘴,点之间的距离增加,并且如果对于至少三个外部对和两个内部对,距离的增加大于某个值,则报告侵权。
人数统计和移动电话检测
我使用在 COCO 数据集上训练的 YOLOv3 的预训练权重来检测网络摄像头馈送中的人和手机。关于如何在 TensorFlow2 中使用 YOLOv3 并执行人数统计的深入解释,您可以参考这篇文章:
[## 使用预先训练的 YOLOv3 计算网络摄像头中的人数
学*使用实例分割(YOLOv3)来计算使用 TensorFlow 预训练权重的人数…
medium.com](https://medium.com/analytics-vidhya/count-people-in-webcam-using-yolov3-tensorflow-f407679967d5)
如果计数不等于,可以发出警报。COCO 数据集中手机的索引是 67,因此我们需要检查是否有任何类别索引等于该索引,然后我们也可以报告一部手机。
使用多线程合并
现在让我们深入研究代码。由于眼球跟踪和嘴巴检测是基于 dlib 的,我们可以为它们创建一个单独的线程,另一个线程可以用于 YOLOv3 任务:人数统计和移动检测。
首先,我们导入所有必要的库以及助手函数。然后加载 dlib 和 YOLO 模型。现在在eyes_mouth()
函数中,我们找出面部关键点并对其进行处理。对于嘴部检测,已经定义了外部点和内部点之间的原始距离,并且我们计算当前距离。如果某个数量大于预定义的数量,则通知监考人。对于眼睛部分,我们找出它们的质心,如链接的文章所示,然后我们检查它们最接近哪个面部关键点。如果两者都在边上,则相应地进行报告。
在count_people_and_phone()
功能中,YOLOv3 应用于网络摄像头馈送。然后,检查检测到的对象的类别,如果检测到不止一个人或者检测到移动电话,则采取适当的行动。
这些函数在不同的线程中传递,其中有无限的循环,proctor 可以通过按两次“q”来打破这些循环。
声音的
这个想法是从麦克风录制音频,并使用谷歌的语音识别 API 将其转换为文本。API 需要来自麦克风的连续语音,这是不合理的,因此音频是以块的形式记录的,因此在使用这种方法时没有强制的空间要求(十秒钟的 wave 文件的大小为 1.5 Mb,因此三个小时的考试应该有大约 1.6 Gb)。使用不同的线程来调用 API,以便可以不间断地进行连续记录,并且 API 处理最后存储的一个,将其数据附加到文本文件,然后删除它以节省空间。
之后使用 NLTK,我们从其中删除停用词。抽取问题纸(文本格式),其停用词也被移除,并且它们的内容被比较。我们假设如果有人想作弊,他们会从试卷上说些什么。最后,将常用词及其频率呈现给监考人。监考人也可以查看包含考生在考试中所说的所有单词的文本文件。
直到代码中的第 85 行,我们一直在记录、转换和存储文件中的文本数据。顾名思义,函数read_audio()
用于使用由stream_audio()
传递给它的流来记录音频。函数convert()
使用 API 将其转换为文本,并将其附加到文件 test.txt 中,同时添加一个空格。这一部分将贯穿整个考试过程。
在这之后,使用 NLTK,我们将存储的文本转换为标记,并删除停用词。对试卷的文本文件也进行同样的操作,然后找出常用词并报告给监考人。
这个系统可以和安全浏览器结合起来防止作弊。该项目并没有消除对监考人的需要,因为他需要执行某些操作。通过这个系统也有一些作弊的方法,比如一个人坐在笔记本电脑后面通过写作与考生交流。为了彻底杜绝作弊,我们需要像眼镜摄像头这样的外部硬件来覆盖考生的整个视野,并在图像上应用计算机视觉。但这将消除制造一个任何人都可以使用的人工智能的目标,而不需要使用除了标准笔记本电脑之外的任何额外东西,并且使用这个监考人还可以一次使用多个学生。
完整的代码请参考这里。
使用 Excel 和 Python 实现个人投资自动化
如你所愿,随时更新你自己的股票投资数据。
在 Unsplash 上由 Ishant Mishra 拍摄的照片
还入门 Python?
很长一段时间以来,我一直想知道如何开发 Python 项目,因为 Python 在我的日常工作中并没有被大量使用。所以,我在这里看到两种你可能适合的情况:
要么你的工作没有给你提供你正在寻找的编程技能,要么事实上根本没有给你提供任何使用它的机会。
无论你的情况如何(甚至是不包括在上面的情况),在这篇文章中,你可能会发现一个有趣的 Python 项目,现在就开始。那么,到底是什么?我设法开发了一种方法,你可以输入你所拥有的股票,并每天跟踪每只股票的表现。
首先,代码实际上是做什么的?简而言之,你必须在一个 Excel 文件中提供关于你所拥有的每一只股票的 3 个输入,然后,使用本文中分享的 Python 脚本,以便每天更新每一只股票的表现。
Excel 文件中需要输入哪些信息?股票交易代码(“股票行情”)、、、股票数量(“数量”)、和每只股票的总成本(“买入价格”)。很简单吧?除了这些输入非常简单这一事实之外,强调您只需要输入一次也很重要。
PS:我是巴西人,所以考虑了一个例子,我从巴西股市挑选了一些股票。
Excel 文件输入— Stock.xlsx
事不宜迟,我们最后来看看代码本身。
代码:
我的目标是分享我构建分析的方式,并强调我认为最重要的事情。还有一点很重要,我鼓励你搜索任何你不确定如何工作的库、方法、或属性。
第一部分:
每次您想要加载过去的数据时,都应该执行以下命令。
1.1:
你可能从未听说过的库是 yfinance。这是我们代码的核心,因为它通过 Yahoo Finance API 提供了您可能想要跟踪的股票价格(和其他一些信息)。
PS:你可能注意到了我在 Excel 文件输入图像中使用的语法,重要的是确保你写下了股票谈判的名称,因为它们在雅虎财经中是可用的。
1.2:
还记得我之前提到的 Excel 文件吗?在我的例子中,它保存为“Stock.xlsx ”,与我保存的目录相同。py 文件(这就是为什么您不必像在其他示例中看到的那样担心提供完整的文件位置,例如“C:/Documents/…”)
1.3:
除了逻辑结构之外,我强烈建议您花点时间去理解,我列出了最重要的事情:
- ^BVSP 是巴西主要的股票市场指数,类似于纳斯达克综合指数(^ixic);
- “收盘”是每只股票的市场收盘价,这是 yfinance 的一个属性。
1.4:
这是我称为“第 1 部分”的结尾。你在这之前都有什么?您创建了一个 Pandas DataFrame ,涵盖了您在 Excel 文件“Stock.xlsx”中考虑的过去一段时间(在本例中为 2 个月)内每天开市的股票价格。
为了避免创建多个 Excel 文件,您可能会注意到我覆盖了原始文件。您应该能够看到类似下面的内容(来自表的一部分的快照):
Excel 文件被股票信息覆盖
第二部分:
你应该在每天股市开盘时执行以下命令。
2.1:
我只添加了 matplotlib.pyplot 库(对我们要做什么有任何猜测吗?).
2.2:
这取决于你将如何保存你的。py 文件。按照我上面写的方法去做,“第 2 部分”会被认为是一个不同的。py 文件(有一部分 1。py 分隔文件,“StockHistory”,因为我只需要执行一次)。如果你想在一个地方拥有一切。py 文件,只需忽略这段代码,将它与所有其他代码行放在一起(但是,您需要注意,您将每天执行不必要的任务)。
2.3:
closePriceList 是由执行方法当天的每只股票价格组成的列表(注意到“[-1]”元素了吗?看看这行代码提供了什么)。
2.4:
这里的要点是向我们一直使用的 Excel 文件“追加”一个新列。这些列中的每一列都由最近股票价格的列表组成。
2.5:
这是最长的代码块,但是它的目标很简单:处理 df 以便它的每一行都作为列表提供。需要这些列表来生成以下内容:
股票每日余额[BRL 价值]
这个投资组合所有者应该考虑改变策略,对吗?
我希望你喜欢它。
这是我在 Medium 上的第一篇文章。这里重要的是分享一些有用的东西,这些东西可以用 Python 来完成,特别是对于那些不直接使用它,但希望学*更多的人。例如,您可以修改此代码来绘制累计余额,并区分您购买每只股票的日期。这取决于你自己的想象力和必要性。
使用 Python 自动化投资组合优化和分配
使用 Python 中的现代投资组合理论为您的投资组合计算优化的资产权重和分配
尼克·崇在 Unsplash 上的照片
现代投资组合理论——(MPT)
现代投资组合理论(MPT)或均值-方差分析是一种数学模型/研究,用于开发和创建投资组合,旨在使给定风险的回报最大化。这种数学很大程度上基于一种假设和经验,即普通人更喜欢风险较低的投资组合。降低风险可以通过投资于传统的安全港或多样化来实现,这是 MPT 倡导的一项事业。
这个理论是由亨利·马科维茨在 20 世纪 50 年代提出的,他因此获得了诺贝尔奖。虽然 MPT 受到了相当多的批评,部分原因是其向后看的倾向以及无法将商业和经济中的不可抗力/趋势考虑在内,但我发现,通过衡量波动率作为代理,这一工具对于衡量一个人投资组合的风险很有价值。
模型的基础知识
我将使用 Python 来自动优化投资组合。该理论的概念简述如下
- 投资组合预期收益-
投资组合的预期回报的计算方法是将资产的权重乘以其回报,然后将所有资产的价值相加。为了引入前瞻性估计,可以引入概率来生成和合并商业和经济中的特征。
投资组合预期收益
2。投资组合差异-
在该模型中,投资组合方差被用作风险的度量。较高的方差表明资产类别和投资组合的风险较高。该公式表示为
投资组合风险(方差)|ρ—资产 i/j 之间的相关系数
3。夏普比率
夏普比率衡量与无风险利率(国债利率)及其风险状况相关的投资回报。一般来说,夏普比率值越高,表明投资越好,利润越大。因此,如果比较两个具有相似风险特征的投资组合,在其他条件相同的情况下,最好投资具有较高夏普比率的投资组合。
夏普比率
4。有效前沿-
该图衡量风险与回报,用于在考虑风险状况和投资者特征后选择最佳投资组合。根据目标和投资者的能力/特征,有效边界是第一和第二象限曲线的重要部分。
资本配置线(CAL)本质上是有效边界的切线。切线和边界之间的交点被认为是最佳投资,在正常情况下,对于给定的风险状况,它具有最大的回报
在 Python 中自动化投资组合优化
- 导入库
我们将首先导入所有相关的库,以便随着我们的进展使我们的生活变得更容易。
#Importing all required libraries
#Created by Sanket Karve
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import pandas_datareader as web
from matplotlib.ticker import FuncFormatter
此外,一个重要的库是 PyPortfolioOpt,它包含了帮助我们优化投资组合的函数。我们将使用以下命令安装该库
!pip install PyPortfolioOpt#Installing the Portfolio Optimzation Library
导入将进一步需要的函数-
from pypfopt.efficient_frontier import EfficientFrontierfrom pypfopt import risk_modelsfrom pypfopt import expected_returnsfrom pypfopt.cla import CLAfrom pypfopt.plotting import Plottingfrom matplotlib.ticker import FuncFormatter
2。从网上删除股票和金融数据
我们将从雅虎获取数据!各种股票报价机的融资。我用过的代码有 Boston Scientific、Berkshire Hathway、Invesco Trust、S&P 指数基金、AES Corp .和 Sealed Air Corp .这些代码被选择用于分散各种行业的投资。
输入报价器后,我们需要创建一个空白的数据框架,用于通过循环捕捉所有股票的价格。出于本练*的目的,我进行了过滤,以捕捉我们正在研究的股票的调整后收盘价。
tickers = ['BSX','AES','BRK-B','SEE','QQQ','SPY']thelen = len(tickers)price_data = []for ticker in range(thelen):prices = web.DataReader(tickers[ticker], start='2015-01-01', end = '2020-06-06', data_source='yahoo')price_data.append(prices.assign(ticker=ticker)[['Adj Close']])df_stocks = pd.concat(price_data, axis=1)df_stocks.columns=tickersdf_stocks.head()
检查捕获的值是否为“NaN”。较不重要的是零值。如果有 NaN 值,好的做法是考虑不同的时间序列,或者用 D-1,D+1 的*均价格填充数据。如果出现大的空白,我宁愿不考虑和删除时间序列数据,也不愿插入零值。
#Checking if any NaN values in the datanullin_df = pd.DataFrame(df_stocks,columns=tickers)print(nullin_df.isnull().sum())
3。计算
我们将继续进行投资组合优化的计算。从获取所选投资组合的预期收益和方差开始。
#Annualized Returnmu = expected_returns.mean_historical_return(df_stocks)#Sample Variance of PortfolioSigma = risk_models.sample_cov(df_stocks)
接着分别计算并存储具有最大夏普比率和最小波动性的投资组合权重值。
#Max Sharpe Ratio - Tangent to the EFef = EfficientFrontier(mu, Sigma, weight_bounds=(-1,1)) #weight bounds in negative allows shorting of stockssharpe_pfolio=ef.max_sharpe() #May use add objective to ensure minimum zero weighting to individual stockssharpe_pwt=ef.clean_weights()print(sharpe_pwt)
这将为你提供不同持股的权重。如果你想最小化“零”持有或重量,请随意使用 L2 回归。此外,weight_bounds 被设置为从-1 到 1,以允许计算“做空”股票。最小方差投资组合也将进行同样的操作。
4。绘制有效边界并优化投资组合配置
最后一步是为了直观的目的绘制有效边界,并计算投资组合中给定美元金额的资产分配(即购买或卖空的股票数量)。出于本练*的目的,我考虑了 10,000 美元 investopedia 上的默认起始值。
latest_prices = discrete_allocation.get_latest_prices(df_stocks)# Allocate Portfolio Value in $ as required to show number of shares/stocks to buy, also bounds for shorting will affect allocation#Min Volatility Portfolio Allocation $10000allocation_minv, rem_minv = discrete_allocation.DiscreteAllocation(minvol_pwt, latest_prices, total_portfolio_value=10000).lp_portfolio()print(allocation_minv)print("Leftover Fund value in$ after building minimum volatility portfolio is ${:.2f}".format(rem_minv))
这将为您提供优化的投资组合,如下所示
对于计算具有最大夏普比率的投资组合,也可以这样做。
结论
据说投资既是艺术又是科学。Python 和它的库允许我们自动化优化,并在这个过程中节省宝贵的时间。然而,必须注意的是,这些孤立的技术不太可能是最好的投资方法。
接下来,我将发布关于我们如何通过机器学*选择股票来复制指数基金,以建立我们的投资组合和 Python 可以帮助我们的许多其他功能。最后,我还创建了一个程序,用蒙特卡洛模拟来计算股价的潜在损失或变动。这个工具可以和这个投资组合优化器一起使用。
自动计算风险价值(VaR ),使用 Monte 管理 Python 中的投资组合风险、股权和股票…
towardsdatascience.com](/var-calculation-using-monte-carlo-simulations-40b2bb417a67)
以上信息绝不是专业的投资建议或实践,而仅仅是我讨论如何通过现代投资组合理论(MPT)使用 Python 来自动化投资组合优化所做的努力。如需完整的源代码或任何讨论,请随时联系
自动化随机森林
建立你自己的自动机器学*系统的教程。
克里斯里德在 Unsplash 上的照片
我最近完成了一个网站的开发,它可以进行端到端的机器学*(作为一个 GUI ),也就是说,它可以自动完成以下步骤:
- 使用表单从用户处获取培训数据和测试数据。
- 清理数据并使其可用于机器学*模型(如填充缺失值、处理分类变量等。).
- 根据数据训练随机森林并调整其超参数。
- 对数据执行特征工程。
- 为最终模型绘制特征重要性图。
- 根据测试数据生成预测,并将结果和功能重要性图发送到用户提供的电子邮件地址。
所以在这篇博客中,我将带你浏览设置这样一个系统的代码。你可以在这里找到包含网站机器学*部分核心代码的 GitHub repo。
我们将使用旧的 fastai 库(v0.7)的一部分作为开始的初始基础(代码直到第 500 行包含来自库的片段和其他将被使用的必要导入)。您可以复制代码片段或安装库。我们将从这里开始编码!
我将一段一段地解释代码。所以让我们开始吧!
上面的代码定义了一些函数,随着我们的深入,这些函数将被重复使用。两个功能最为突出:
- “print_score”:它将用于评估我们的模型在训练和验证数据集上的性能。
- “auto_train”:它将用于使用给定的超参数来训练随机森林。
下一个函数“data_trainer”有点长,所以我将把它分成两部分来解释给你听。它将用于执行以下任务:
- 清理数据,处理分类变量,从日期(如果有的话)中提取信息,并填充缺失的值。
- 训练随机森林并调整其超参数。
- 特征工程。
- 删除多余的变量。
- 绘制特征重要性图。
所以,让我们开始吧!我已经添加了注释来划分与每个过程相对应的部分。
上述代码(“data_trainer”的第一部分)执行以下任务:
- 它从日期列(如果有的话)中提取数据,比如年、日、月、季度末与否、年末与否等等。
- 它将分类变量转换成机器学*模型可以使用的格式。它还会填充缺失的值。
- 它将数据分成训练和验证数据集。
- 如果数据集非常大,它将使用“RF _ sampling”(fastai 中的一种加速方法)。
- 然后,它将使用循环开始调整随机森林的超参数,即“min_samples_leaf”和“max_features ”,以获得最佳结果。
上面的代码(“data_trainer”的第二部分)将执行特征工程,并删除不影响我们的目标变量或多余的变量。
之后,该函数将返回最佳超参数和用于训练最终模型的特征列表。
上面的代码定义了一个函数来预测测试数据集,并生成和保存特征重要性图。它执行以下所有操作:
- 像我们对训练数据集所做的那样,从日期列(如果有)中提取信息。
- 在整个数据集(训练+验证)上训练随机森林(使用在先前函数中获得的超参数和特征工程信息),并将其应用于测试数据集以生成预测。
- 生成特征重要性图并保存。
现在剩下要做的就是将所有先前定义的函数捆绑在一起,通过适当的输入以适当的顺序调用它们,这就是下面要做的。
总结:
我们首先定义了一个函数来清理训练数据,找到最佳超参数,并执行特征工程(称为“data_trainer”)。然后,我们定义了一个函数,使用从上述函数获得的信息来训练模型,并使用它来生成测试数据集的功能重要性图和预测(称为“auto_applyer”)。然后,我们使用一个名为“auto_predictor”的函数将一切联系起来。此外,如果你想建立一个电子邮件系统来发送包含结果的电子邮件,你可以在这里找到代码。
瞧!我们建立了自己的自动化机器学*系统。
你可以查看网站(端到端 GUI) 这里这里是 GitHub repo 。
非常感谢你阅读这个博客!
附言
如有任何问题或建议,请随时通过 LinkedIn 与我联系。
自动化房地产投资分析:Python 网络抓取机器人
python 中的数据挖掘实现房地产交易筛选自动化。
房屋图片(来自 unsplash
摘要
目标是构建一个能够分析投资属性的 python web 工具。该工具将使用数据挖掘来查找房地产价格,然后分析回报率。
索引
摘要
索引
动机
该应用程序
这些功能
总结和展望
动机
机器人或自动化在交易和投资中的应用并不新鲜。多个例子包括股票交易机器人,其任务是根据不同的模型或指标来购买或出售资产。复兴科技因其通过算法投资获得的回报率而受到世界关注,该回报率在 30 年的时间跨度内*均达到 60%以上的年化回报率。
自动化的好处有可能改变不同规模的企业。单个重复性任务可通过内部开发的软件或第三方 SaaS *台实现自动化。
对于个人散户投资者来说,python 机器人为房地产投资的各种元素提供了一个有前途的解决方案。在本文中,我们将研究分析属性过程的自动化。其他可以自动化的流程包括:列出物业,向租户发送通知,筛选租户(机器学*或人工智能),甚至自动派遣维护人员。
该计划
输入和输出
该程序有三个输入:房源 URL、月租金价格和财产税税率。它返回每月现金流、上限利率和现金回报率。
- 现金流 —扣除所有费用(抵押贷款、物业管理、维修补贴、空置费用)后的每月利润
- —每年的净收入除以资产价格(百分比)
- —每年净收入除以用于资产的首付款(百分比)
包装
使用了以下软件包。注意对于那些在 Anacondas 环境中工作的人来说,streamlit 目前似乎不能通过这个包管理器使用。Streamlit 是和 pip 一起安装的,当 PIP 和 Anacondas 一起使用时可能会导致问题
- 请求 —这个包用于通过 HTTP 请求访问 python 中的网站。
- 美汤 4 —用于网页抓取和数据挖掘。我们能够使用这个包来检索描述网站内容和样式的 HTML 代码。一旦检索到 HTML 代码,就可以利用 beautiful soup 来隔离站点的特定部分。例如,在这个项目中,我们使用美丽的汤来获取房价。
- Streamlit —这个包让部署 web 应用程序变得超级简单。代码是在 Jupyter 笔记本上开发的,然后转换成。py 脚本一旦开始工作。Streamlit 允许无缝部署,并最大限度地减少用户界面上花费的时间。使用 streamlit,将 python 用于后端、flask 用于部署、react 用于动态内容的经典部署选项要简单得多。
编写代码
完成大部分繁重工作的函数是 price_mine 、 mortgage_monthly 和 net_operating 。
这些是分别执行以下职责的主要功能:
- 从 URL 中检索标价
- 计算每月抵押贷款成本
- 计算扣除所有费用后的每月净营业收入
- ***price _ mine***|该函数用于从房源中检索房价。可以使用 API,但是网络抓取更强大。web 抓取的缺点是站点结构的改变需要在代码中更新。在这里,网页刮包使用的是美丽的汤。这个过程相对简单,使用 f12 检查网页,然后在 HTML 代码中找到所需的元素。这段代码可以被隔离在 beautiful soup 中,以检索页面的特定部分。检索到代码后,内置的 python 函数 replace 用于删除逗号、美元符号和不必要的空格,以便建立一个浮点变量。
****def** price_mine(url):
*#Currently this function takes an input of a URL and returns the listing prices*
*#The site it mines is remax*
*#The input must be a string input, we can reformat the input to force this to work*
*#Next we use regex to remove space and commas and dollar signs*
headers = ({'User-Agent':
'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36'})
response = get(url)
response_text = response.text
html_soup = BeautifulSoup(response_text, 'html.parser')
prices = html_soup.find('h2',{'class': 'price'}).text
prices = prices.replace(",", "")
prices = prices.replace("$", "")
prices = prices.replace(" ", "")
prices = float(prices)
**return** prices**
- *mortgage _ monthly*|该函数将挂牌价格、抵押期限和利率作为输入,并返回每月抵押价格。有许多方法来计算每月抵押贷款价格,没有作出具体的决定,至于使用哪种方法和一个通用算法,是相当容易实现的使用。
****def** mortgage_monthly(price,years,percent):
*#This implements an approach to finding a monthly mortgage amount from the purchase price,*
*#years and percent.*
*#Sample input: (300000,20,4) = 2422*
*#*
percent = percent /100
down = down_payment(price,20)
loan = price - down
months = years*12
interest_monthly = percent/12
interest_plus = interest_monthly + 1
exponent = (interest_plus)**(-1*months)
subtract = 1 - exponent
division = interest_monthly / subtract
payment = division * loan
**return**(payment)**
- net_operating | 该函数以月租金、税率和价格作为输入,返回每月的净营业收入。净营业收入的金额分别代表支付抵押贷款(本金和利息)、财产税、支付管理费(每月 10%)、物业维修补贴和空置补贴后的现金。有人可能会说,只有每月支付的利息才构成费用,因为本金是建立在股本基础上的。虽然这是真的,但我们的模型想知道在支付所有费用后还剩多少现金。个人投资分析机器人可以改变像这样的元素,使个人投资者的计算个性化。
****def** net_operating(rent, tax_rate, price):
*#Takes input as monthly mortgage amount and monthly rental amount*
*#Uses managment expense, amount for repairs, vacancy ratio*
*#Example input: net_operating(1000,1,400,200)*
*#879.33*
*#1000 - 16.67 (tax) - 100 (managment) - 4 (repairs)*
mortgage_amt = mortgage_monthly(price,20,3)
prop_managment = rent * 0.10
prop_tax = (price * (tax_rate/100)/12)
prop_repairs = (price * 0.02)/12
vacancy = (rent*0.02)
*#These sections are a list of all the expenses used and formulas for each*
net_income = rent - prop_managment - prop_tax - prop_repairs - vacancy - mortgage_amt
*#Summing up expenses*
output = [prop_managment, prop_tax, prop_repairs, vacancy, net_income]
**return** output**
其他功能:
使用的其他函数,如 cap_rate,以百分比计算净收入与资产价格的比率。完整的函数列表可以在项目的 GitHub 资源库中找到,但是不包括在本文档中。
构建界面
早期概念化
想法是让输入在页面的左边,输出在页面的右边。输入被放置在侧边栏中,这样输入和输出在视觉上是不同的。
初始用户界面概念草图
介绍 streamlit
构建这个仪表板的一个常*方法是用 HTML 创建一个静态网站,用 flask 部署后端,在某种数据库中存储值,然后用 react 链接所有内容。一种比这种方法更具优势的新的替代部署途径被称为 streamlit。
Streamlit 允许从 python 脚本快速过渡到现代用户体验。它还提供了一种简单快速的部署途径。转换的第一步是替换内置的 python 输入函数,并用 streamlit 输入框替换它们。对输出进行了同样的替换。
一旦完成,就可以从控制台部署streamlit 应用程序,并通过外部 IP 地址进行访问。
streamlit 内置的初始用户界面
一旦在 streamlit 中构建了用户界面,就要修改代码,为输入添加一个侧栏,如上面草图中最初描述的那样。
带有输入侧边栏的用户界面
最终代码
最终代码可以在 GitHub 上找到。
项目的 GitHub 存储库
总结和未来方向
尽管复兴科技(renaissance technology)等集团能够从应用于投资的数学模型中获利,但个人散户投资者也能从中受益,而且实施起来要容易得多。
房地产投资者可以从自动化中受益,处理许多以前需要助理或占用大量时间的任务。这是一个使用自动化来减少过滤交易时间的例子。如果自动生成摘要报告,并且只将最好的资产呈现给人类,投资者可以审查更多的交易。夫妻店、房地产投资者和企业家可以从自动化中受益,而不仅仅是财富 500 强公司。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详*我们的 读者术语 。
R 中运行路线的自动化
实践教程
使用 Graphhopper API(在 rvest 和 PostcodesIO 的帮助下)运行伦敦的每个 Mews
冬天已经来到了英国,当其他人都在匆忙修理锅炉时,我最关心的是保持每周的运行里程,而温度却在相反的方向。
探索伦敦的新地方似乎是个好主意,而且不必考虑走哪条路似乎更好。所以计划是跑遍伦敦的每一条消息,让 R 决定怎么做。
本文中有一些代码片段,其余的在 fredwise/run_the_mews 上。
新闻
隐藏在伦敦一些大排屋后面的是 386 个原始的和幸存的消息。这些小街是真正的马动力的残余,虽然马厩和马车房现在大多是车库和底层厨房,但它们仍然是很好的观光景点。
找到他们
Everchanging Mews 在这里做了腿的工作,在过去的 10 年里,他们访问了 1200 多个 Mews,在他们的百科网站上对它们进行了分类。
原始/幸存的 mews 列表分为 8 页,每个列表都有一个包含更多详细信息的网页。Chrome Dev Tools 找到保存这个网址的元素,并对 R 包做了一些工作 rvest 列出了它们。
对它们进行地理编码
这些网页中的每一个都有一个邮政编码,邮政编码员将查询的邮政编码,io 以获得位置数据。当邮政编码不可靠或者在邮政编码. io 数据库(386 中的第 7 个)中不存在时,这里需要进行一些手工清理。之后,只需通过邮政编码 _ 查找运行它们。
映射它们
在这里,我们只需要将经度和纬度作为一个形状文件传递给活页。
一页上的 386 条原始/幸存的消息
路由它们
希望所有这些的真正价值来自于路线生成的自动化。最初的问题陈述是:
在 20 公里或更短的路线中,查找覆盖所有 386 家酒店的最短总路线。每条路线都从同一个地方开始。
GraphHopper 是这类路线优化的优秀免费资源。它允许所有种类的车辆(在这个例子中是脚)的路线,但是它的免费 API 只允许每个请求最多 5 个位置。
GraphHopper 甚至可以让你为一辆小型摩托车导航。
一个简单的解决方案是一次随机选择 5 个位置。这样做的代价是没有优化总距离,但是在这种情况下,这意味着完成了更多的运行,并且没有消息被访问两次(只要随机采样没有替换),所以应该这样做!
使用 GraphHopper API
GraphHopper 的文档非常棒,所需要的就是以正确的格式传递 5 个位置的纬度和经度。下面的代码片段显示了一个函数,它将这个请求构建为 R 列表,并使用 jsonlite 将其转换为 JSON。提醒一下,完整的脚本可以在 Github 上找到。
对我们的 5 个位置运行路线的 78 个查询使用 httr::POST 发送到 GraphHopper API
使用 sf 包将响应路径坐标转换成简单特征,并在活页中绘制成折线。
Graphopper 做了大量的工作来优化我们五个 mews 集合之间的路线
线串到 GPX
最后但并非最不重要的是,在设备上具有这些路线将是有用的,以便跟随该路线。只需将从每个 GraphHopper 响应路径创建的简单特性传递给 sf::st_write
哇,78 个 GPX 文件和 78 天的奔跑,不用考虑去哪里!
使用 SQLite 关系数据库和 Python 实现周日膳食准备自动化
创建和使用储物件,满足您所有的烹饪需求
成为一个真正的成年人(现在,被隔离)意味着加入 r/meal prep Sunday,重新创造所有的膳食准备食谱。然而,随着我的食谱越来越多,我对存储的需求也越来越大。
我现有的谷歌电子表格的快照,准备在未来几年成倍增长
我最初在一个电子表格中跟踪我所有尝试过的食谱,首先按照餐点,然后按照主料精心组织。我还包括了我想要跟踪的其他属性,包括烹饪、难度和食谱中的任何饮食限制。但是行数的增长也意味着组织和搜索时间的增长。我需要一个新的,更强大的存储单元。那时,我开始研究电子表格的轻量级(尽管在 UI 方面没有那么吸引人)表亲 SQLite 关系数据库的用途。
我想要这个新的食谱数据库来补救我的电子表格的困境。因此,我将它设计成:
- 最大化增长空间(我可能会在我的烹饪生涯中一直使用它
- 允许使用我现有的属性轻松存储和排序
- 通过汇总我为这一周选择的食谱中的所有材料来简化购物
最终,我的食谱数据库完成了所有这些目标。结果证明这是最用户友好/可行的选择吗?可能不会,而且我了解到 SQLite 可能不是这样一个项目的最佳选择。然而,我确实创建了食谱数据库的一些基本构件,并对现有的电子表格应用程序有了新的认识。如果您有兴趣了解 SQLite 和 python 的 pandas 如何用于食谱的上下文,那么让我们来看看实用性。
完整代码可以在我的 Github 这里 找到。为了方便查看,我用了一个 Jupyter 笔记本,但是你可以随意把它分成有标签的文件。
目录:
- 设置关系数据库模式
- Python for SQLite 入门
- Python 中的 SQLite 关系基础:配方版
- 用关键字参数和熊猫检索食谱
- 随时可用— Python 的 input()作为 UI
- 结论
设置关系数据库模式
我希望我的数据库满足的第一个标准是最大化增长空间,这直接受其结构的影响。随着数据库的扩展,最大限度地减少可能影响存储效率的冗余尤为重要。这个概念叫做规范化。
虽然不同的规范化形式包含它们自己特定的规则,但是作为一个整体,规范化通常需要将一个大表分解成多个小表,并维护这些部分之间的联系。这些小表的结构由底层数据的关系决定,有三种类型:一对一、一对多和多对多。
一个配方对应一套说明
最简单的数据库关系是一对一的。这是指表 A 中的一条记录与表 b 中的一条且仅有一条记录相关联。在配方数据库中,配方及其说明具有一对一的关系,因为两个配方几乎不可能具有完全相同的说明。因此,配方名称表和配方指令表将具有一行配方名称,对应于仅仅一行配方指令。
一对一的配方数据库模式
一个配方多种属性
对于大多数其他食谱属性(例如,难度、烹饪、课程和饮食类型),存在一对多的关系。表 A 中有一条记录链接到(你猜对了!)表 b 中的多个记录。例如,一个难度级别(例如“容易”)可以有许多与其相关联的食谱,因为可以有许多“容易”食谱。然而,反过来就不正确了——一个食谱不可能既“简单”又“困难”(除非我的烹饪能力一天比一天有很大的变化)。
一对多配方数据库模式
多种配料的多种食谱
表之间的最后一种关系是多对多关系。在配方数据库中,一个配方可以有许多配料,一种配料可以用于许多配方。
多对多关系的实现需要第三个连接表来符合规范化规则。在我的 Recipes 表和 Ingredient 表之间,我创建了一个名为 Recipe_Ingredient 的连接表。第三个表将多对多关系分解为两个一对多关系。
多对多配方数据库模式
在图的右侧,您可能已经注意到不只是一个成分表,而是四个独立的表,包括单位表、数量表和制备方法表。这种结构利用了配料的单位、数量和制备方法与食谱之间的多对多关系。虽然我可以利用配料及其各自的单位、数量和制备方法之间的一对多关系,但我更喜欢将所有与配料相关的信息集中在 Recipe_Ingredients 表中的一个地方。
主键和外键
既然表已经拆分,那么如何将它们链接起来的问题就出现了。所有以前的模式图都有箭头,从一个特定的表指向另一个表中与其等价的“id”列。箭头底部表示主键,或特定表中行的唯一标识符。箭头的尖端指向一个外键,或者指向一个主键的引用。
这些关键不仅有助于建立关系,还能减少冗余。在做改变的时候,如果有一天我想把“容易”变成“毫不费力”,我只需要在难度表上做一个改变。如果主外键关系不存在,我需要用“easy”遍历所有行,并单独进行更改。建立此链接还可以通过防止删除具有依赖外键的主键来保存孤立记录。有关 SQLite 外键的更多信息,请查看这里的文档。
Python for SQLite 入门
现在设置已经完成,是时候用 Python 实现了。
选择数据库管理系统
数据库管理系统,简称 DBMS,是帮助处理数据库的系统的总称。其中的一个子集可以处理关系,将它们分类到 RDBMS 下,用额外的 R 表示关系。因为我需要关系管理,所以我选择了 SQLite,一个 RDBMS,因为它的易于设置并且不需要服务器。
设置和关闭
# getting start with sqlite
import sqlite3# create database file by specifying location
cnn = sqlite3.connect(r"C:\file\path\here\mealpreprecipes.db")# initialize cursor object to interact with database
cur = cnn.cursor()
当我们希望 Python 与数据库交互并处理 SQL 查询时,Cursor 对象将会派上用场。更多信息可以在 Python 文档这里找到。
一旦进行了任何更改,您需要使用 Commit 语句进行保存。
cnn.commit()
完成连接后,使用以下命令关闭它:
cnn.close()
或者,您可以使用with
语句来确保在运行必要的代码后连接被关闭。
with cnn:
* insert code *
更多直接来自源代码的设置信息,请访问 Python 文档这里。
Python 中的 SQLite 关系基础:配方版
虽然我不会介绍简单的 SQL 语法,但我会解释在实现本文开头创建的数据库结构时我发现有用的技巧和诀窍。
创建具有主键和外键的表
前面建立的主键和外键现在可以在我们创建表时实现。以下是一个配方表示例:
cur.execute("""CREATE TABLE recipe
(recipe_id INTEGER PRIMARY KEY NOT NULL,
recipe_name TEXT,
recipe_notes TEXT,
difficulty_id INTEGER,
cuisine_id INTEGER,
course_id INTEGER,
diet_id INTEGER,
instructions_id INTEGER,
FOREIGN KEY (difficulty_id) REFERENCES difficulty(difficulty_id),
FOREIGN KEY (cuisine_id) REFERENCES difficulty(cuisine_id),
FOREIGN KEY (course_id) REFERENCES difficulty(course_id),
FOREIGN KEY (diet_id) REFERENCES difficulty(diet_id),
FOREIGN KEY (instructions_id) REFERENCES difficulty(instructions_id))""")
应用这些FOREIGN KEY
约束可以确保recipe
表的任何一行中的所有外键都将链接到另一个表的主键。例如,如果插入到recipe
表的difficulty_id
中的一行在difficulty
表中没有对应的主键,插入将会失败。
插入主键和外键的值
在设置了具有主键和外键的表之后,我们现在想要插入一些值。
感谢我们使用的INTEGER PRIMARY KEY NOT NULL
关键字,我们不必为表的主键插入显式值。只需为该行插入一个值,表就会自动生成一个唯一的整数对其进行编号。
diet_id 列表示稍后要引用的主键
为了插入外键,我喜欢使用下面的语法:
sql = """INSERT INTO recipe(recipe_name, recipe_notes, difficulty_id, cuisine_id, course_id, diet_id, instructions_id) VALUES (?, ?,
(SELECT difficulty_id FROM difficulty WHERE difficulty = ?),
(SELECT cuisine_id FROM cuisine WHERE cuisine = ?),
(SELECT course_id FROM course WHERE course = ?),
(SELECT diet_id FROM diet WHERE diet = ?),
(SELECT instruction_id FROM instructions WHERE instructions = ?))"""
以这种方式使用SELECT
语句可以确保我找到正确的对应主键,即使我不知道唯一的整数。
具有外键列的配方表条目
数据插入
我希望既不是主键也不是外键的行条目是用户给定的值。幸运的是,SQL 为我们提供了准备好的语句来插入我们事先不知道的值。有了准备好的语句,我们可以将参数指定为查询,使用问号作为语法。这些用来代替传统的 Python 字符串格式来保护我们免受 SQL 注入的影响。在下面的函数中,我使用了一条准备好的语句来插入食谱的指令。
def insert_instructions(self):
sql = "INSERT INTO instructions (instructions) VALUES (?)"
# insert values as tuples
# single item tuples need trailing comma to show tuple-ness
values = (self.instructions,)
cur.execute(sql, values)
cnn.commit()
检查是否存在
对于某些属性,比如 cuisine,我知道插入的值很可能是数据库中已经存在的值。为了与效率的主题保持一致,我想通过检查存在来防止重复。在 select 表中,我在一个准备好的语句中使用了一个SELECT
语句。
sql = "INSERT INTO cuisine (cuisine) SELECT (?) WHERE NOT EXISTS (SELECT 1 FROM cuisine WHERE cuisine = ?)"values = (self.cuisine, self.cuisine)cur.execute(sql, values)
cnn.commit()
插入已知的表格值
虽然我的大多数表都根据用户输入插入了行,但是我希望我的两个表course
和diet
只包含我预先选择的值。
# example in diet table
cur.execute("""CREATE TABLE diet
(diet_id INTEGER PRIMARY KEY NOT NULL,
diet TEXT)""")cur.execute("""INSERT INTO diet (diet) VALUES ("None", vegan", "vegetarian", "gluten-free")""")
虽然 SQLite 不支持 None 类型,如NULL
,但我添加了字符串“None”作为选项。我发现当我使用 select 方法插入外键时,SQLite 不认为NULL
是可搜索的值。因此,我选择将“None”作为一个值,这样食谱就可以被表示为没有饮食限制。
关于 execute()与 executemany()的补充说明
正如上面两个例子中所使用的,Cursor 对象有一个Cursor.execute()
方法,用于将 SQL 查询作为字符串传递。上面没有显示的是Cursor.executemany()
,方便一次插入多行。确保将您想要插入的行作为列表传入。
我如何处理配料
规划这个食谱数据库时最大的挑战是配料处理,因为一种配料有四个属性:名称、数量、单位和制备方法。我最终选择将这些属性按照每种成分组成一个字典。对于 Python 来说,这似乎是一个自然的电子表格,每一列都被转换成一个键。
pesto_tilapia = {'ingredient': ['butter', 'pesto', 'coconut milk'],
'unit': ['tbsp', 'cup', 'can'],
'quantity': [3, 1, 1],
'prepmethod': ['room temp', 'None', 'None']}
虽然手动输入这样的词典很麻烦,但一个好的用户界面有望使这变得易于管理。
用关键字参数和熊猫检索食谱
检索和查看食谱对使用至关重要。为了实现这个数据库的第二个和第三个目标,我在 view.py 中构建了两个函数:一个用于查看选择的食谱,另一个用于收集配料的汇总列表。
查看选定的配方
第一个函数我命名为【非常原本】print_recipes()
。我想根据我选择的标准过滤和选择食谱,并使用关键字参数实现这个“搜索”功能,然后格式化成一个 SQL SELECT
查询。关键字 arg 将 category 作为键,将 category selection 作为值。因为参数不是位置性的,所以我可以根据需要传入任意多的标准。
不幸的是,Python 中的 SQL 查询是麻烦的字符串,所以函数的其余部分专门用于格式化参数。在有多个参数的情况下,我决定用一个OR
而不是一个AND
来连接搜索标准。这是因为我知道我的大部分搜索会是前一周我想用完的成分。为了找到包含所有我想用的配料的食谱,我需要配料的联合,而不是交集。如果你要寻找的东西需要你的标准的交集,请随意将它改为AND
。如果你感觉更有野心,尝试在OR
和AND
搜索之间集成一个切换。
在所有的字符串格式化之后,您将会得到一个函数,它会显示出您用关键字参数选择的食谱的数据帧。现在是时候列出购物清单了。
带有 kwarg {'ingredients': 'fish'}的示例数据帧
收集成分的汇总列表
第二个函数在一个名为convert()
的函数中返回我的购物清单。它获取在前面的函数print_recipes()
中创建的食谱数据帧,并返回其配料的字典,其中包括所有重复的配料。
虽然具有相同单位的成分组合起来很简单,但是需要单位转换的成分就比较棘手了。使用 pandas 的groupby()
和nunique()
,该函数首先在数据帧中搜索独特的配料。基于该成分的单位是否可转换(字典conversion_chart
中硬编码的选项),该函数将该成分的多个实例聚合(在大量数据帧过滤之后)成用户在convert()
参数中指定的一个单位。
所有的食材都加入字典后,你就有了你的购物清单!
用户提示后的购物清单词典
随时可用— Python 的 Input()作为 UI
由于没有用户界面经验,我需要一种快速简单的方法来访问我的数据库。我使用 Python 的input()
函数来获得用户响应并实现基本的控制。然后,这些输入用于启动 main.py 文件中的数据库插入和检索。
使用 input()的用户提示
结论
现在你有了一个全功能的(有些易坏的)食谱数据库,它最大化了增长空间,允许简单的分类和搜索,并简化了你一周的购物。
如果你更愿意拥有一个充满来自互联网的食谱的数据库,尝试使用 Selenium 和 Beautiful Soup 从你最喜欢的网站上收集食谱。可以在这里找到这些工具不同用例的教程。
快乐的用餐准备!
完整代码可以在我的 Github 这里 找到。为了方便查看,我用了一个 Jupyter 笔记本,但是你可以随意把它分成有标签的文件。
自动化枯燥的东西:数据问题
一个懂 SQL 的机器人
加入 froma tob 10 天后,2019 年 9 月,当我还住在酒店的时候,我们决定重组我们的 Google DataStudio 仪表盘。目的是帮助人们理解哪些问题已经可以用图表来回答了。关于数据的简单、重复的问题不应该在每次被问到时都手动回答。在理想的情况下,人们应该能够通过快速访问仪表板来回答这些问题。
为了让我们的仪表板更加用户友好,我有了开发 Slack bot 的想法。一个友好的 Slack 机器人,将用户重定向到我们的仪表板。破折号就是这样诞生的:
来源:迪士尼粉丝维基
这个想法很简单:每次你问 Dash 一个问题,他都会给你一两个与可能答案最匹配的仪表盘链接。
我记得我花了一个晚上学* node.js,做了第一个 Dash 原型。最大的挑战实际上是让他能够与我们的 Slack 组织沟通。后来,定义内部逻辑是我最接近手动解决机器学*问题的一次。我定义了一个 dashboard 字典- >(关键字列表),以及一个 dashboard 评分系统,我必须手动调整它的权重,直到我的所有测试都通过,并且我认为我的工具足够健壮,可以使用。
Dash 使用下义词/上义词系统、拼写检查器、字符串相似性和单词嵌入的概念,还会讲笑话:
来源:作者
当被问到一个问题(“上周的皈依”)时,他是这样回答的:
来源:作者
与 Dash 的所有通信对其他用户来说是不可*的。这意味着你可以在任何频道或私人对话中使用 Dash,其他人不会注意到你使用了这个机器人。无数次,我在谈话中使用它来快速回答我关于数据的问题。
几个月前,我发现了谷歌的 DataQnA,并要求访问他们的私人 alpha。DataQnA 允许您将自然语言中的问题转换为 SQL 查询。
经过几次面试后,我获得了访问权限,并开始在 Dash 的新版本中工作。首先,2020 年的 Dash 现在有了一个面具:
来源:迪士尼粉丝维基
第二,Dash now 不仅仅会将你指向一个仪表盘— 它现在会尝试直接回答你的问题,因此你甚至不需要放松。DataQnA 的整合并不容易——但这是值得的。我们将不断集成越来越多的数据表到 Dash 中。这里有一个视频演示——当然是用假数据:
演示。来源:作者
我迫不及待地想看到 Dash 是如何不断成长的,直到我自动失业,然后他们解雇我。
原载于 2020 年 10 月 8 日https://fluent data . tech。
自动化 DCF 估价
使用蒙特卡罗模拟预测财务状况
DCF(贴现现金流)估值模型可能是金融专业人士拥有的最重要的金融工具。这种模型在理论和实践上都很棒,但是传统上在 excel 中执行,它有时在功能上相当繁琐。幸运的是,使用 Python,我们可以自动化这些评估步骤,然后更进一步,创建一个蒙特卡罗模拟函数,用于可视化潜在 DCF 结果的分布。
在 Unsplash 上由 Carlos Muza 拍摄的照片
**import** numpy **as** np
**import** pandas **as** pd
**import** matplotlib.pyplot **as** plt
%matplotlib inline
我们首先需要的是对我们年销售额的预测。我们将创建一个未来六年的数据框架,从理论上讲,它将从以前的财务报表中结转初始销售数据。
years = ['2020A', '2021B', '2022P', '2023P', '2024P', '2025P']
sales = pd.Series(index=years)
sales['2018A'] = 31.0
sales
我们现在已经构建了未来五年的销售增长(注:“A”=实际;“B”=预算;“P”=预计)。现在,我们将把预计的年度销售增长用于未来的预测。最终,我们可以用概率分布来代替这些估计,从而得到更真实的预测。
growth_rate = 0.1**for** year **in** range(1, 6):
sales[year] = sales[year - 1] * (1 + growth_rate)
sales
类似地,我们现在需要为 DCF 模型中的所有关键变量分配值或公式。这些变量将保持标准的财务定义。(注意:纳税将需要一个额外的 lambda 函数,以确保如果税前利润为负,我们就不会有正的纳税)。
ebitda_margin = 0.14
depr_percent = 0.032
ebitda = sales * ebitda_margin
depreciation = sales * depr_percent
ebit = ebitda - depreciation
nwc_percent = 0.24
nwc = sales * nwc_percent
change_in_nwc = nwc.shift(1) - nwc
capex_percent = depr_percent
capex = -(sales * capex_percent)
tax_rate = 0.25
tax_payment = -ebit * tax_rate
tax_payment = tax_payment.apply(**lambda** x: min(x, 0))
free_cash_flow = ebit + depreciation + tax_payment + capex + change_in_nwc free_cash_flow
我们现在有了预计的自由现金流(百万)。现在我们有了 FCF,我们可以开始实际的 DCF 估值模型。我们将计算终值,并将所有现金流贴现回现在。
cost_of_capital = 0.12
terminal_growth = 0.02terminal_value = ((free_cash_flow[-1] * (1 + terminal_growth)) /
(cost_of_capital - terminal_growth))discount_factors = [(1 / (1 + cost_of_capital)) ** i **for** i **in** range (1,6)]dcf_value = (sum(free_cash_flow[1:] * discount_factors) +
terminal_value * discount_factors[-1])
为了便于查看,让我们将这些变量打包成一个熊猫数据帧:
output = pd.DataFrame([sales, ebit, free_cash_flow],
index=['Sales', 'EBIT', 'Free Cash Flow']).round(1)output
创建蒙特卡洛模拟
因为我们对 DCF 模型变量使用了硬编码值,所以我们没有一个非常健壮的模型。幸运的是,我们可以通过引入蒙特卡罗模拟来改进这一点,该模拟将使用正态分布来随机生成和采样大量变量输入,然后将它们绘制成分布图。我们使用 numpy 来生成这些随机样本,然后迭代 10,000 次。
iterations = 10000**def** **run_mcs**():
*# Create probability distributions*
sales_growth_dist = np.random.normal(loc=0.1, scale=0.01, size=iterations)
ebitda_margin_dist = np.random.normal(loc=0.14, scale=0.02, size=iterations)
nwc_percent_dist = np.random.normal(loc=0.24, scale=0.01, size=iterations)
*# Calculate DCF value for each set of random inputs*
output_distribution = []
**for** i **in** range(iterations):
**for** year **in** range(1, 6):
sales[year] = sales[year - 1] * (1 + sales_growth_dist[0])
ebitda = sales * ebitda_margin_dist[i]
depreciation = (sales * depr_percent)
ebit = ebitda - depreciation
nwc = sales * nwc_percent_dist[i]
change_in_nwc = nwc.shift(1) - nwc
capex = -(sales * capex_percent)
tax_payment = -ebit * tax_rate
tax_payment = tax_payment.apply(**lambda** x: min(x, 0))
free_cash_flow = ebit + depreciation + tax_payment + capex + change_in_nwc
*# DCF valuation*
terminal_value = (free_cash_flow[-1] * 1.02) / (cost_of_capital - 0.02)
free_cash_flow[-1] += terminal_value
discount_factors = [(1 / (1 + cost_of_capital)) ** i **for** i **in** range (1,6)]
dcf_value = sum(free_cash_flow[1:] * discount_factors )
output_distribution.append(dcf_value)
**return** output_distribution
当我们绘制这个模拟图时:
这个输出图向我们显示,当迭代 10,000 个模型输入变量的潜在组合时,我们的贴现现金流值最常*的是在 2,300-2,500 万左右。
这是一个非常基本的介绍,介绍了 Python 在自动化金融操作方面的强大功能,但是蒙特卡洛模拟清楚地展示了这种强大的计算能力,它给了我们我们开始寻找的最终数字。请关注未来的帖子,这些帖子将进一步详细介绍如何使用 Python 实现日常财务任务的自动化。
利用卫星图像自动搜索土耳其的非法垃圾场
使用谷歌地球引擎为联合国进行图像分类
多年来,我作为地理信息系统和遥感专家的经历在人道主义领域的项目中留下了印记:联合国、世界银行、红十字会、WRI、无国界翻译组织;你说吧,我可能为他们做过一些工作。早在 2018 年,当我为 城市恢复*台——一家致力于为人道主义危机中的固体废物管理开发软件的法国初创公司——工作时,我们被赋予了一项非常简单但难以完成的任务:帮助 UNDP 和土耳其政府识别土耳其的每一个 非法垃圾场。
但是为什么呢?
土耳其独特的地理位置,与叙利亚和 T21 之间长达 911 公里的边境线,以及土耳其作为通往欧洲的陆路移民通道,导致土耳其接收了大量涌入的叙利亚难民。自 2016 年叙利亚危机开始以来,数百万人越境逃往土耳其东南部的安纳托利亚地区。2018 年 7 月安纳托利亚东南部登记在册的叙利亚人数量超过 350 万。
到 2016 年,移民将流入土耳其境内叙利亚人数最多的省份。东南部省份是难民营最多的省份,如桑尼乌尔法、加济安泰普和奥斯马尼耶。
这导致几个土耳其边境城市的人口结构发生了快速变化。例如,在基利斯,叙利亚难民的数量大于当地人口。
随着人口的流动,他们产生的垃圾也在增加。随着国内固体废物数量翻了一番,Analotia 东南部的省份开始面临越来越多的问题,如处理不足和收集和处理新人口产生的所有废物的能力不足。这导致了固体废物价值链的不*衡,导致了许多新的非法垃圾场的出现,以接收市政当局无法处理的废物。
Gaziantep 郊区的一个非法垃圾场,主要用于处理生活垃圾。
联合国开发计划署以其支持城市废物管理的明确任务为回应,推出了 东道社区有效城市废物管理方案,其中包括关键基础设施投资、如废物转运站和回收设施。
但是将垃圾从不受控制的垃圾场转移出去仅仅是升级整个垃圾收集系统的第一步。联合国开发计划署还想确保这些垃圾场正在进行重建。因此,需要一种方法来识别垃圾场。
你如何处理整个国家的图像?
因为我们没有办法走遍全国,希望能撞上隐藏得很好的垃圾场,所以我们求助于使用(滚筒…)卫星图像!
遥感领域的人们在机器学*技术成为现在的热点之前就已经在研究它了。主要的区别是他们一直在用一种几乎类似的方式做这件事,包括大量的点击按钮。该过程通常如下所示:
- 决定你将使用哪家卫星图像提供商,通常是在像 Maxar 的 Discover 这样的系统的帮助下;
- 通过从服务器上一张一张地下载或者购买(这通常需要两三次电子邮件交流)来获得你需要的每张图片;
- 训练像 ERDAS Imagine、eCognition 和 ArcMap 这样的桌面软件来识别您感兴趣的任何土地特征。
这就是 Maxar 的 Discover 的样子。这对于挑选一两张图像来说很好,但是如果你需要评估整个国家就不太好了。
嗯,在你不得不下载和分析像 T21 这么大的国家的图像之前,这都是有趣的游戏。
这需要你下载大量的图片,用它们建立一个马赛克,设置正确的参数,并指望你的机器能够在合理的时间内处理它。
幸运的是,我们现在可以用相当简单的脚本运行所有这些过程,而且更好的是,在云上运行。这就是谷歌提供的免费使用的 地球引擎 工具。
GEE 用户界面,文档、代码、控制台和地图都在同一个页面中。
正确物体的正确光谱带
如果你以前从事过图像分类工作,你会知道你应该总是对你正在看的任何东西的组成、形式和纹理有很好的理解。然而,废物的成分具有不同的密度、总体尺寸、化学成分,因此 光谱特征 。简而言之,也就是说,我们的目标以不同的强度反射不同的颜色(或光波波长),这使得很难将垃圾场检测为一种单一类型的物体。
Osmaniye 实地考察期间拍摄的建筑垃圾堆放场。
所以我们决定利用一个辅助分类模型。这个非常经典的模型包括用一组卫星图像中的训练样本“教”我们的代码垃圾场是什么样子,并告诉它搜索更多。这意味着为了开始,我们必须首先决定我们将使用哪个图像集合。由于我们没有任何获取图像的预算,我们将使用我们可以获得的最好的免费图像:哥白尼计划的 Sentinel-2 ,它提供了一个不错的空间分辨率(20 米像素,如果使用全景锐化,则为 10 米)和一个更好的光谱分辨率 (13 个波段,范围从 443 到 2190 纳米)。
哨兵 2 的光谱分辨率相当高。
为了用 GEE 实现这一点,我们声明一个我们称之为SENTINEL
的变量,然后使用ee.ImageCollection
方法声明我们正在寻找 哥白尼/S2 集合。然后,我们可以过滤这个集合,通过为云的百分比(< 10%)和采集日期(2018 年 1 月至 2018 年 8 月)设置阈值,找到实际上有用的图像。我们还使用 GEE 的 Assets 选项卡上传了一个压缩的 shapefile,其中包含我们感兴趣的区域,我们称之为southeasternturkey
,然后将它应用为边界过滤器。
这就是有趣的地方。即使我们刚刚过滤了集合,我们的SENTINEL
变量仍然保存了大量的图像,这些图像都是叠加的,有时是重叠的。我们要花很长时间来挑选最好的图像,并用它们构建一个马赛克。但是 GEE 提供了非常有用的median
方法,考虑到我们已经提供的过滤器,它提供了空间中任何给定点的中值像素值。所以我们把新的SENTINELMED
镶嵌图添加到地图上,看看它的自然色 RGB (B4,B3,B2)合成是什么样子。
我们的中间像素值马赛克的自然颜色 RGB 组成。
那是废物还是到处都是石头?
好的,太好了!那将是我们用来寻找弃尸点的拼图。我们接下来需要做的是建立一些训练样本,这样我们的代码就知道哪些像素是垃圾场,哪些不是:水、森林、庄稼、城市、裸露的土壤等等。对于垃圾场,我们将只导入由联合国提供的一些以前已知的垃圾场的 shapefile,对于其余的土地使用特征,我们将在 GEE 的地图上直接绘制这些。一旦在地图窗格中创建了一个新图层,它就会在导入窗格中显示为一个变量。重要的是,我们导入的数据和绘制的特征都有一个属性,我们称之为class
,以及一个唯一的值。例如,垃圾场将会是'class:1'
,水将会是'class:2'
,等等。
在 GEE 的导入窗格中设置训练样本。
一旦我们收集了足够多的样本,包括类别和范围,我们就可以将它们全部放入一个变量中。我们还需要确定哪些光谱带将用于执行分类。在我们的例子中,我们使用了所有这些。接下来,我们需要告诉 GEE 使用我们的几何图形并从选择的集合中提取像素,以便建立 样本区域 。这是我们的class
属性被使用的时刻。
现在我们可以使用Classifier
方法来训练一个算法。GEE 有许多不同的分类器,比如决策树和随机森林,举两个最流行的。这里我们将使用经典的推车** 分类器。我们将我们的样本区域和选择的波段输入它,它将返回我们自己的自定义分类器,我们可以使用我们想要的任何图像集合。**
最后,我们可以创建一个classification
变量,在这个变量中,我们将告诉我们的分类器用我们的SENTINELMED
马赛克施展魔法。然后我们可以将这个分类的结果添加到地图中,为我们创建的每个类指定颜色。
我们的分类镶嵌图是在云上计算的,并被添加到地图窗格中。
为了做更多的处理,我们需要将生成的光栅文件导出到本地机器上。GEE 提供了导出到 Google Drive 的功能,让这一切变得简单。
现在怎么办?
像素的分类是不防错的,尤其是考虑到不同的弃尸点可能彼此不同。为此,该模型需要最后一步,即通过视觉观察分析重新分类的像素群,如下所示。在进行分类之前,我们本可以使用一个分割程序——也就是说,将我们的镶嵌图转换成单色几何图形——但是我们觉得既然没有那么多垃圾倾倒点,人眼就能更准确地识别它们。
先前未知垃圾场的例子(1);重新分类的像素群集的形成(2);以及垃圾场的矢量化描述(3)
呈现暗色的潜在垃圾场
呈现浅色的潜在垃圾场
该模型在识别接收生活垃圾的垃圾场时最为有效,因为有机物呈现的深色是非常典型的。相反,当垃圾场接收来自建筑工地或拆除工地的碎石或废物时,识别集群的任务变得更加困难,因为这些很容易被误认为是采矿场。对于这些情况,视觉分析是最重要的,因为人眼比像素分类更容易识别这种垃圾场中观察到的模式。
通过这一过程总共描绘了 70 个多边形。这些多边形中的每一个都被怀疑是垃圾场。尽管如此,一些地点仍存在一些不确定性,仍需进一步核实。为此,我们使用 ArcGIS Online 应用程序模板 创建了一个 WebApp 用于数据编辑。该应用程序与联合国和土耳其政府官员共享,允许每个用户通过将每个划定的多边形分类为(1)建筑垃圾,(2)生活垃圾或(3)非垃圾场来提供输入。
开发地图注记工具是为了从了解具体环境的关键信息提供者那里收集*解。
根据关键线人的反馈,我们现在终于可以说我们成功识别了土耳其东南部的每一个垃圾场。该项目于 2018 年 8 月开展,是开发署为恢复该地区非法垃圾场而采取的第一步。接下来是一系列密集的实地行动,以确保废物价值链中的所有利益攸关方,从非正式收集者到回收者,都了解新的可用废物处理结构。土耳其政府采取的控制行动可以为垃圾场的有效恢复扫清道路。
由模型识别的所有七十个垃圾场
您可以通过下面的链接找到谷歌地球引擎图像分类模型。如果你愿意,不要犹豫,在这里或 Linkedin 上给我写信吧!
谷歌地球引擎上的古伊列梅·伊布洛诺夫斯基
code.earthengine.google.com](https://code.earthengine.google.com/2df85ba615c3223daaf2c72b85b31494) [## 古伊列梅·m·亚布洛诺夫斯基-产品经理| LinkedIn
我对如何重新利用专注于领域的学科的技术和论述充满热情…
www.linkedin.com](https://www.linkedin.com/in/guilherme-m-iablonovski-08013143/)**
使用假设在 Python 中自动化单元测试
凯文·Ku 在 Unsplash 上的照片
单元测试是产生高质量代码的关键。下面是如何实现自动化。
单元测试是开发高质量代码的关键。有许多可用的库和服务,你可以用它们来完善你的 Python 代码的测试。然而,“传统的”单元测试是时间密集型的,不太可能涵盖你的代码应该能够处理的所有情况。在这篇文章中,我将向你展示如何使用基于属性的测试和假设来自动测试你的 Python 代码。我还讨论了使用基于属性的测试框架的一些优点。
基于属性的自动化测试
单元测试包括测试代码的单个组件。典型的单元测试获取输入数据,通过一段代码运行它,并根据一些预定义的预期结果检查结果。
假设做了一些不同的事情。它是一个基于属性的(或:“生成的”)测试框架。基于属性的测试包括定义对代码的一般期望,而不是具体的例子。例如,如果您有一些代码来计算一些交易的总增值税,您可以定义一组假设的数字及其相应的增值税金额(100 美元交易→ $xx.xx 税),并对其进行测试。然而,如果你知道增值税是,比方说,20%,一个基于财产的测试将验证总增值税始终是总额的 20%。
假设是建立在这些原则之上的。它根据某个规范生成任意输入数据,并随后对该数据进行测试。更重要的是,当 Hypothesis 发现一个导致断言失败的例子时,它会试图简化这个例子,并找到最小的失败案例——这个过程称为“收缩”。假设实际上会试图“破坏”你的代码。因此,您的测试将用相同数量的代码覆盖更大的领域空间。而且,你一定会发现你甚至没有想到的边缘情况。
假设入门
让我们看看假设在实践中是如何工作的。假设有三个关键部分:你正在测试的代码,定义你的测试数据的策略,和一个使用策略测试你的代码的函数。
让我们假设我们有一段简单的(无意义的)Python 代码,它将浮点值转换为整数:
这段代码有一个明确的属性:结果应该总是整数类型。
策略
为了测试这段代码,我们将首先定义一个“策略”。策略定义了假设为测试生成的数据,以及如何“简化”示例。在我们的代码中,我们只定义数据的参数;简化(或:“缩小”)是假说的内在要求。
我们将从生成 0.0 到 10.0(包括 0.0 和 10.0)之间的浮点值的策略开始。我们在一个名为data_strategies.py
的单独文件中对此进行了定义。为此使用一个数据类可能看起来有点过头,但是当您处理带有一堆不同参数的更复杂的代码时,这是很有用的。
使用数据类和假设来定义数据策略
很多时间可以用来定义策略,事实上也应该如此。使用假设进行基于属性的测试的全部要点在于,您定义了生成数据的参数,以便您随后允许您的自动化测试发挥其魔力。你在这上面花的时间越多,你的测试必然越好(想想:“高投入;高奖励”)。
将代码和策略结合在一起:用假设运行测试
在我们定义了我们的策略之后,我们添加了一小段代码来将假设生成的示例传递给我们的函数,并断言我们想要测试的代码的所需结果(“属性”)。下面的代码从我们在上面的data_strategies.py
文件中定义的generated_data
dataclass 对象中提取一个浮点值,通过我们的convert_to_integer
函数传递该值,最后断言期望的属性保持不变。
使用假设定义您的测试模块
配置假设:有用的设置
在我们运行上面开发的测试模块之前,让我们回顾一下一些配置,我们可以使用这些配置来为我们的用例定制假设。假设自带一堆设定。这些设置可以使用settings()
装饰器传递到您的测试函数,或者通过在一个概要文件中注册设置,并使用装饰器传递概要文件(参*下面的示例代码)。一些有用的设置包括:
max_examples
:控制测试结束前需要多少个通过的例子。如果您对一段新代码通过评审所需的测试量有一些内部指导方针,这是很有用的。一般来说:你的代码越复杂,你想要运行的例子就越多(假设的作者注意到他们在测试 SymPy 的时候,在几百万个例子之后找到了新的 bugsdeadline
:指定单个例子允许用多长时间。如果您有非常复杂的代码,其中一个示例运行的时间可能会超过默认时间,您会希望增加这个值;suppress_health_check
:允许您指定忽略哪些“健康检查”。当您处理大型数据集(HealthCheck.data_too_large
)或需要很长时间才能生成的数据(HealthCheck.too_slow
)时非常有用。
让我们在测试模块中使用这些设置。有了这些简单的代码行,我们现在可以继续前进,在我们的函数中抛出 1000 个例子来验证它是否按预期工作。您可以从终端(python -m pytest test_my_function.py
)运行测试,或者如果您使用像 Pycharm 这样的 IDE,通过 s 为您的代码指定适当的 pytest 配置。
使用假设设置对 Python 代码进行基于属性的测试
升级你的游戏:使用复合策略
到目前为止,我使用的例子都很简单。Hypothesis 可以使用复合策略处理复杂得多的测试用例,顾名思义,复合策略允许您组合策略来生成测试用例。所以,让我们开始游戏,在更复杂的环境中使用假设。
假设您已经开发了一段计算数组百分比值的代码。有很多 Python 库可以为您完成这项工作,但是假设您对百分位特别感兴趣,并且只是想要一个自己的实现。在这个例子中,我们的目标是根据现有的实现对我们的解决方案进行基准测试。考虑到这一点,我们可以定义这段代码的两个简单属性来进行测试:
- 我们用来计算百分位数的数值数组的顺序对其结果并不重要;
- 该函数的输出需要与用另一个普遍接受的库计算的值一致(注意,将它定义为“属性”有点不典型——在本文的最后一节会有更多的介绍)。
让我们从百分位数函数开始。这里,我们实现了一个使用中点插值的版本。该函数接受整数值或浮点值(arr
)的数组,对其进行排序,根据指定的百分位(perc
)确定下限和上限,最后取两个值的中点。
简单的百分位数函数
现在,让我们继续我们的策略,也就是,我们为测试生成的数据的定义。这里,我们定义了一个名为generate_scenario
的函数,它基于随机选择的分布(dist
)产生一个随机长度的浮点值数组(n
)。我们还生成我们想要计算的百分比值(perc
)。我们将值和百分位数作为字典返回,因此我们可以轻松地访问测试所需的值。注意@st.composite
装饰器的使用,它将"一个返回一个例子的函数转换成一个返回产生这样的例子的策略的函数。
在假设中定义复合策略
最后,我们可以在测试模块中使用我们的复合策略。在这个模块中,我们指定我们的策略设置(SETTINGS
),并指定一个运行我们自己代码的函数。test_calc_percentile
函数测试反转数组顺序不会影响我们的 percentile 函数的输出,并将结果与 NumPy 实现进行比较。使用我们在这里设置的配置文件,我们运行 10,000 个示例,在我五年前的笔记本电脑上大约需要 30 秒来完成。
使用复合策略的测试模块示例
在你开始测试之前:关于你什么时候应该和不应该使用假设的说明
在你开始开发你自己的单元测试之前,有一些事情你需要知道。基于属性的测试在特定的环境下非常有效。当一段代码的属性被很好且容易地定义时,它是一个强大的框架,也就是说,“我的代码的 x 部分需要产生一个具有属性 y 的结果”。当定义“assert”语句的条件与您试图测试的代码一样复杂时,您将最终重新实现您现有的代码。
在某些情况下,拥有两个并行的实现可能是合适的,例如,当您创建了一段新的代码,或者用一个新的框架重新实现了一些东西,您需要针对现有的实现进行基准测试,如上面的示例所示。然而,在大多数情况下,事实并非如此:您将浪费时间和资源,最终不得不维护两段做完全相同事情的代码。
即使在自动化测试时,在“传统的”单元测试和基于属性的测试之间走一条中间路线也是明智的。您将希望避免让您的测试成为太多的“黑盒”,并确保您覆盖了明显的情况,尤其是在开发的早期阶段。总是建议至少创建几个很好理解的场景。并且,将你自己的“手动”测试用例与自动化测试结合起来,将会对提高你的测试覆盖率大有帮助,并且可以极大地改进你的代码。
感谢阅读!你喜欢用哪些 Python 工具来提高代码质量?请在评论中留下你的建议!
支持我的工作: 如果你喜欢这篇文章并愿意支持我的工作,请考虑通过我的推荐页面 成为付费媒介会员。如果你通过我的推荐页面 注册 ,订阅的价格是一样的,但是我会收取你每月的部分会员费。
如果你喜欢这篇文章,这里还有一些你可能喜欢的文章:
实施代码风格是简化开发过程的关键,下面是如何实现自动化。
medium.com](https://medium.com/python-in-plain-english/how-to-improve-your-python-code-style-with-pre-commit-hooks-e7fe3fd43bfa) [## 为您的 Python 项目自动化版本标签和变更日志
基于项目的提交历史,使用 commitizen 实现版本标签和变更日志自动化的实践指南
towardsdatascience.com](/automating-version-tags-and-changelogs-for-your-python-projects-6c46b68c7139) [## 简化您的 Python 代码:用 Wily 自动化代码复杂性分析
以下是如何让评估代码复杂性成为 Python 开发例程的一部分
towardsdatascience.com](/simplify-your-python-code-automating-code-complexity-analysis-with-wily-5c1e90c9a485)
请仔细阅读 本免责声明 中的任何内容后再依托 我的 Medium.com 文章 。
Py-Spark & SparkNLP 上的情感分析和主题建模自动化(使用 Twitter 大数据)
大数据*台 SparkNLP 上的高级 NLP
如何使用 spark 框架处理文本大数据并自动化 NLP 模型
马库斯·温克勒在 Unsplash 上的照片
“如今的选举不一样了,社交媒体已经大大改变了它们!”—哦,是的,我。
在过去的十年里,政治社交媒体(主要是推特)账户的使用量激增。许多政治领袖(有时是他们的家人)正在使用 Twitter 作为与他们的公民交流的一种卓越模式。然而,这导致了一些有趣的问题。不仅是美国的选举,最近世界上最大的民主国家印度的选举也因社交媒体的影响而被指责为''(查看此文由' 《华盛顿邮报》 ' 了解我这里的意思)。这种偏*,主要以 两极化的“公众情绪” 的形式,通过扭曲脆弱的社交媒体结构而注入。
想到美国政治和推特,你脑海中可能会浮现唐纳德·特朗普总统。自 2015 年特朗普发起政治竞选以来,他因所谓的负面、贬损&有些挑衅的推文而臭名昭著。给他 280 个字符的限制,他会把它翻译成一个由情感、情绪、事实和观点组成的包(通过' 《纽约时报》 ' 了解他玩的大部分推文)。甚至Vox(美国著名新闻与观点网站),在其一篇文章中,也证实了特朗普发很多,&量子真的在那里。
所有上述事实,结合我先进的分析知识,让我思考——我能开发一个能够跟踪 2020 年美国总统大选候选人社交媒体行为的直播应用吗?
我花了大约一个月的时间,用下面的话完整地回答了我上面的问题:
作者图片**
研究问题:
在进行这个项目时,我特别关注以下问题,同时牢记两位候选人(Donald j . Trump&Joe Biden):
- 两位候选人的【Twitter-holdings】(用户群)是否存在微小差异?(回答人:子话题 1.2 中的一般 Twitter 分析)**
- 候选人试图从他们的日常推文中获得什么样的?(回答人:使用子主题 2.2 中的 SparkNLP 对推文进行情感分析)
- 【用户行为】 (通过研究用户层面的推文情绪)对这些候选人的日常表现如何?(回答人:使用子主题 2.2 中的 SparkNLP 对推文进行情感分析)**
- 这些候选人在推特上谈论的(前 3 名)‘讨论最多的话题’是什么?(回答人:使用子主题 2.3 中的 SparkNLP 进行 LDA 主题建模)****
- 有没有一种方法可以让我每天的分析自动化?(回答:使用 windows cmd 的模型本地部署&将数据连接到子主题 3 中的实时开源 RDBMS PostgreSQL)****
1.数据管道:
回答上述问题的第一步是收集适当的数据&将它们存储在数据库中。为了理解候选人水*分析(问题 1、2 和 4),我需要与特定候选人相关的信息。对于用户层面的分析(用户观点——问题 3 ),我需要与接受调查的候选人相关的一般推文数据。
1.1 候选级别数据收集:
为了获取候选级别的数据,我决定使用官方的tweeper 的开发者 API ,而不是 python 原生的‘Tweepy Package’。在处理新获取的自然文本数据时,我还使用了一个清理函数(“clean_tweets”),如下面的代码片段所示:
1.2 用户级数据收集:
根据官方指南,Twitter API 每 3 小时只允许 3 00 条推文。因此,这么多的数据不允许我对用户级别的数据进行适当的情感分析。为了避开这个限制,在做了一些研究之后,我决定使用优化的 Get Old Tweets 3 包装器。它允许我获取与候选人相关的历史性推文。尽管如此,推特的最高点击率是 10,000 次。因此,我每次点击都附上 15 分钟的睡眠周期。
1.3 在 RDBMS PostgreSQL 中存储数据:
由于我计划自动化模型,并考虑到每天 20k+ tweet 数据读取量,我正在寻找一个开源 RDBMS 来存储我的数据。我使用 python 的【psycopg 2】库将我的数据连接到 PostgreSQL,在这里,我将候选人级别和用户级别的数据分别存储在不同的表中。
2.使用 SparkNLP 进行情感分析和主题建模:
由于我计划每天更新我的应用程序数据,我一直在寻找一个 NLP 解决方案,它可以让我获得最快且更准确的“情感分析”和“主题建模”框架。经过几天的研究,我发现了一个由 约翰斯诺实验室 开发的 大数据框架。 该框架被称为【Spark NLP】。 它是建立在 Apache Spark ML 之上的。它提供了 简单的表演的&精确的 NLP 标注,便于在分布式环境下为机器学*流水线中的进行缩放。Spark NLP 自带220+管道*** 和 型号 超过 46+ 语言。它支持最先进的变形金刚,如 伯特 ,XLNet,【ELMO, 艾伯特 , 通用它还提供了标记化、词性标注、命名实体识别、依存解析、拼写检查、多类文本分类、多类情感分析以及更多 NLP 任务。***********
2.1 设置 Spark NLP 环境:
那些使用过 py-spark 的人应该知道在我的本地机器上实现 py-spark 环境的挑战。经过多次修改安装&卸载各种版本的 py-spark,终于找到了正确的组合'py spark 2.4。4’&Java 版本’JDK v . 8.0’与 spark NLP 完美配合。一旦我安装了&并为我的 pyspark 设置了路径,我就安装了最新版本的“ sparkNLP ”。此外,在安装了 spark & sparkNLP 之后,我使用 sparkNLP 启动了一个 spark 会话(您也可以使用 spark 本身启动一个自定义会话)&导入了必要的 SQLContext,在模型构建的后续阶段,可能需要用到它来处理 spark 数据帧。
2.2 使用 SparkNLP 设置情感分析管道:
设置好环境后,我构建了一个主函数,它将我之前构建的 熊猫数据帧作为输入 &提供每条推文的 文本长度 以及 情感分数 。该函数是使用类似于许多其他机器学*库的 管道 概念构建的,它由两个主要组件组成,如估计器(估计数据和训练模型)和 转换器 (转换数据和应用模型),它们被定义为 注释器 。在构建管道时,注释格式保持非常特定,这与'注释指南'相匹配,因为它们以非常特定的格式获取输入和输出数据。因此,保持按特定顺序构建的管道的流动变得非常重要。例如,在标记器的 Spark NLP 的 文档 中,您可以看到这个注释器只接受注释器类型文档的输入数据,并输出标记类型的数据。因此,在 Spark NLP 管道中进出注释器的正确类型需要特别注意。**
以下是用于我的分析的管道元件的流程和基本功能:
I . 'document assembler' Transformer:为我们的第一个注释器格式化原始输入文本数据
二。标记器‘注释器:用标记化开放标准识别标记
三。规格化器注释器:清理数据并执行小写
四。 LemmatizerModel '注释器:将数据中的所有单词放到它的 lemma(基本形式)中
动词 (verb 的缩写)停用词清理器'注释器:删除不必要的(重复的)常用词集(如' a '、' the '、' in '、' is '、' to '、' at '等)。)
不及物动词注释器:将 n 元语法合并到我们的 NLP 管道中
七。感知器模型’注释器:使用一个预建的词性标注模型来避免我们的 n 元语法中不相关的词性(POS)标签组合
八。完成器转换器:将最终的注释器输出转换成可用的格式
一旦在输入数据上拟合了上述管道(代码行 1 : 78),我就利用一个 预训练管道‘analyze _ sentiment dl _ use _ Twitter’来确定我的完成器输出的情感分数(代码行 80 : 85)。**
最后,一旦安装了定制管道并计算了情感分数,所有的原始列都在‘id _ tmp’列上被连接到新的' sentscores '列(代码行 95: 98),并生成最终输出。一旦制作了 Spark 数据帧,它将再次转换为 pandas 数据帧,以供用户使用(代码行 107: 120)
上述函数的输出如下所示(对于每个传递的数据文件):
2.3 使用 SparkNLP & Py-Spark 进行主题建模:
因为 SparkNLP 本身不支持文本矢量化,所以我结合 SparkNLP 和 Py-spark ML 特性来构建 LDA 模型。我使用了从 SparkNLP 管道开发的干净的 n-grams & unigrams 作为对 pyspark ml 库 的“”模型(帮助我们计算 TF-IDF 词频-逆词频/词重要性)的输入。此外,TF-IDF 输出用于训练 pyspark ml 的 LDA 聚类模型(最流行的主题建模算法)。**
3.自动化:
为了实现上述所有步骤的自动化,我结合使用了 python 框架和 windows 命令提示符。我将所有的函数和它们的 python 脚本按顺序连接起来,产生了一个主函数。py 文件。这个 python 主脚本被本地 python.exe 使用 windows 批处理(.bat)文件。最后,使用 windows 任务计划程序将批处理文件置于自动执行模式。此外,使用 python 中适当的打印行文本命令,我设法在每天执行代码时在. txt 文件中获得' 执行报告 '。执行报告的一个片段如下:
为了利用我的开源 twitter (Election2020)数据&关于用 Python 中的 Spark 进行主题建模管道的更详细脚本,请查看我的 github 代码报告。
检查我的Live-App(Tableau-Public),在一个*台上展示所有上述分析。
在我的 LinkedIn 、电子邮件、&、个人作品集中找到更多我的信息。
自动机和超级智能
照片由 Maximalfocus 在 Unsplash 上拍摄
通过人工智能的两种潜在状态来理解它。
近十年来,人工智能一直是技术和媒体领域的新流行语。它(很快)未来的工作自动化是杨安泽的普遍基本收入的动机,它通过谷歌和脸书对我们的理解导致了隐私和道德方面的可疑行动——导致了两部著名的网飞纪录片 The Great Hack 和The Social Dilemma——其快速的改进速度让许多领域外的人感到恐惧。
一旦人工智能达到超级智能,没有人知道人类的未来将走向何方——就像普通公众如何忘记我们的数据将成为新的石油一样。未来人工智能将呈现两种状态:机器人和超级智能生物。自动机是一种能够准确有效地执行重复性程序任务的机器人,而超级智能生物是——你猜对了——一种超越我们目前所理解的智能的程序,为了方便起*,我现在在本文的其余部分将其称为 AGI(人工通用智能)。
现在,我必须指出显而易*的是,AI 的这两种状态产生了许多可能性。在这篇文章中,我的目标是分解我们应该从这些状态中期待什么,以及在处理它们时可能出现的伦理问题。
在自动机的情况下:
目前有许多不同模式的自动机在运行,但没有一种能与 AGI 的潜力相提并论。暂且忽略典型的人工智能程序,机械臂、爪子和其他自动化机械主导着工厂生产,因为它们与人类相比具有一致的生产率,而且随着时间的推移,这只会进一步增加。
我们已经*惯了生活中许多方面的自动化。越来越多的工作被机器人自动化只是时间问题。当与 AGI 的潜力相比时,我认为我们看到并与之交互的大多数——如果不是全部——人工智能程序在未来将被视为基本的自动机,因为它们很简单。
但是等等,谷歌和脸书利用我们的大量数据,可能比我们更了解我们。那不算超级聪明吗?
你完全可以说,与人类相比,谷歌和脸书的广告人工智能超级聪明。然而,我仍然认为它是一台自动机——是我们迄今为止最聪明的一台。这种考虑的主要原因很简单:它所做的一切都可以归结为一个目标:为我们提供它认为我们喜欢的帖子(无论是图片、视频、广告等等)。)它有一个目标,并不断优化以实现这个目标,而且做得很好。
快速切线:我想非常明确的说,它的知识库来自于不可逾越的数据量。对我来说,试图描述数据到底有多大是没有意义的,因为我们都不会真正理解它。把它想象成空间的大小,你知道它很大但是它到底有多大?随着这些数据而来的是智能,让我们与为我们量身定制的东西进行交互。然而,由于其唯一目标的“局限性”,它只是一个真正智能的自动机,给我们提供越来越多各种形式的帖子,而没有真正理解我们如何解释帖子——它只是(准确地)假设我们会与它互动。
那么,所有这些都摆在我们面前,我们该何去何从呢?
机器人将不可避免地在各自的应用领域变得更加智能,并取代人类完成这些任务。这些任务可以是在麦当劳卖汉堡,给我们送信,清扫街道,建造摩天大楼。任何物理任务都可以而且将会自动化。
作为一个集体,我们的工作是让技术进步改善我们的生活,而不是毁掉它。为机器以很小的价格(长期)夺走了你的工作而愤怒是一回事,但为机器抢走了你的工作而愤怒又是另一回事。这忽略了一个事实,那就是取代你的是人类的决定,而不是机器人。当谈到自动机时,它们不会决定一个濒临财务不稳定的努力工作的工人阶级家庭的未来。另一个人会。
就 AGI 而言:
把机器人和 AGI 混为一谈是愚蠢的。很多人都这样做。别犯傻了。
尽管 GPT-3 是目前写这篇文章时最好的自然语言模型,但与人类相比,它还是很笨。我相当节制地使用愚蠢;这是一个极其智能的程序,但这是因为用于训练它的数据量庞大,而不是因为它的实际智能。它在性能上的失败表明,要被认为与人类没有区别,它还有很长的路要走。就目前而言,这是一个记忆和反刍大量文本的优秀程序。
出于一个原因,很难对 AGI 做出假设。就像我们无法预测谷歌和脸书内部的技术-广告复合体一样,我们也无法准确预测 AGI 将如何形成。我不怀疑许多公司推动以人为中心的 AGI 背后的动机,例如 OpenAI 、 DeepMind 和 SingularityNET 。事实上,他们是我个人最信任的公司。然而,即使有了所有的制衡机制,我们仍然无法预测结果会是什么。
我们不知道 AGI 是否会从智力低下的起点开始,随着时间的推移慢慢提高,或者以超出人类理解的速度成倍提高。我们不知道它在运作时将如何或是否考虑人的价值。我们不知道它是否会爱我们,帮助我们更多地了解自己,是否会恨我们,杀死我们所有人,或者认为我们如此愚蠢,以至于人类对他们没有价值,让地球完全把我们带回到我们开始的地方。
无论是在面部识别中大量使用 POC技术,还是在招聘中歧视女性,以及如果你有很重的口音就无法识别你的声音,这些事件发生的一个主要原因是:偏*。假设 AGI 有能力学*人类的一切,当我们自己对彼此的看法有偏*时,它将永远达不到这种潜力。然而,创造无偏*的数字头脑是极其困难的,因为我们只能在这些机器已经为大众使用而训练和调整时才能看到它们的偏*。即使非常小心地确保一个系统是公正的,它也可能不可避免地在其他地方表现出偏*。一些偏差,像上面提到的那些,并不是微不足道的,并且显示了这些模型的当前和未来迭代的大量危险信号。
关于高维度偏*是什么样子,或者它如何影响 AGI 对人类的“态度”,没有固定的答案。然而,彻底消除偏*是伟大的第一步。然而,说起来容易做起来难。这个论点来自于一个人类物种不知道如何消除彼此之间的偏*。
总而言之,随着人工智能越来越多地与人类融为一体,人类生活将从根本上发生变化。这种转变对许多人来说是可怕的,对另一些人来说是令人兴奋的,但也有一些人对此视而不*。如果历史重演,我相信人工智能会让人类走向更高的生活水*和更好的生活质量。考虑到这一点,不*等必然会一直存在。我们只能希望这些超级聪明的人发现不*等是一个微不足道的人类问题,需要解决,而不是加剧。
感谢您的阅读。
大数据和自动化
或者如何对 40+ GB 的数据集使用 Google AutoML
Cloud AutoML 是谷歌云*台的一部分。AutoML 提供令人印象深刻的图像分类结果,无需任何数学或技术背景知识。对于 40 GB 以下的图像数据,图像可以直接加载到 AutoML 模块中。对于更大的数据集,必须首先将数据下载到一个虚拟机中,然后传输到存储桶,再从那里传输到 AutoML。
对于小于 40 GB 的数据,请考虑这个教程(它为你节省了一些开销)。
我使用的数据集由 112,120 张 X 射线图像组成,这些图像带有来自 30,805 名不同患者的疾病标签[1]。本教程的目标不是深入医学细节,而是展示大型数据集的 AutoML 工作流。您可以在以下位置找到本教程的数据:
来自 30,000 多名不同患者的 112,000 多张胸部 x 光图像
www.kaggle.com](https://www.kaggle.com/nih-chest-xrays/data)
新项目
在 Google 云*台中,首先创建一个新项目。
并建立一个新的帐户。有了 300 美元的免费积分,本教程对于了解 AutoML 工作流来说是完美的。
虚拟计算机
设置新的虚拟机实例。我用的是 50 GB 磁盘的 Debian GNU/Linux 9 (stretch)。
设置好 VM 后,打开云 Shell 并输入以下命令来下载 python 和 pip。
sudo apt update
sudo apt install python3 python3-dev
wget [https://bootstrap.pypa.io/get-pip.py](https://bootstrap.pypa.io/get-pip.py)
sudo python get-pip.py
pip –version
然后执行:
sudo pip3 install kaggle
能够通过 kaggle API 下载数据集。
将您的 kaggle API 令牌上传到环境中。你可以在你的卡格尔账户里找到它。
创建一个新文件夹,并将 API 令牌放入其中。
mkdir .kaggle
mv kaggle.json .kaggle/kaggle.json
然后下载数据集:
kaggle datasets download -d nih-chest-xrays/data
在不到 15 分钟的时间里,您已经下载了完整的 42 GB。最后,解压缩数据:
unzip data.zip
传输文件可能需要允许完全访问所有云 API。
查看这篇 StackOverflow 帖子以获得更多帮助。
存储桶
解压文件后,你将数据传输到谷歌云存储中。创建一个新的存储桶,并给它一个明确的名称。
执行
gsutil -m cp -r [DATA FOLDER] gs://[BUCKET NAME]
将所有数据复制到云存储中。为了加速这个过程,–m 标志确保使用所有的虚拟机内核。尽管如此,这需要一些时间。–r 标志复制完整的文件夹。
AutoML
在数据被完全复制后,转到 Google Cloud 中的 AutoML 并创建一个新的数据集。
在这种情况下,我们有一个多标签分类。这些图像将通过您必须提供给 AutoML 的 CSV 来选择。
AutoML 需要标签的 CSV 文件来指示图像是如何分类的。标签必须以字母开头,并且只能包含字母、数字和下划线。一张图片最多可以容纳 20 个标签。您还可以将标签留空,以便使用 UI 或人工标注服务进行手动标签定义。
有关详细信息,请查阅:
https://cloud.google.com/vision/automl/docs/prepare
培养
然后你看到你的图像的标签,你可以开始训练一个模型。我建议从 1 或 2 小时这样的低预算(训练时间)开始。完成训练后,你总是可以训练更长时间。
为了避免成本,请记住关闭您的虚拟机,或者在不再需要该项目时将其完全删除。
我希望这篇教程能帮助你用 Google Cloud AutoML 处理大型数据集!
[1] X. Wang,Y. Peng,L. Lu,Z. Lu,M. Bagheri 和 RM .Summers, ChestX-ray8:医院级胸部 X 射线数据库和常*胸部疾病弱监督分类和定位基准 (2017),IEEE CVPR
15 个人对 2 台机器。谁赢了?
15 名学生研究了 8 个数据集,试图超越 2 个领先数据科学*台的性能。找出谁赢了!
有很多关于自动机器学*(AutoML)工具的讨论,这些工具可以自动化数据科学流程,从而自动生成数据驱动的*解,而不需要数据科学专家。听起来很有希望,但他们在现实中表现如何?这样的*台能胜过人类吗,数据科学家会过时吗?还是人类能打败机器?
在这篇博客中,15 名学生使用机器学*模型研究了 8 个数据集,试图击败 2 个领先的数据科学*台(H2O 和 SparkBeyond)的性能。
选手们
机器
https://www.h2o.ai/products/h2o-driverless-ai/()H2O 无人驾驶人工智能使数据科学家能够更快、更有效地开展项目,通过自动化在几分钟或几小时内,而不是几个月内完成关键的机器学*任务。它提供自动特征工程、模型验证、模型调整、模型选择和部署、机器学*可解释性、自带配方、时间序列和模型评分的自动管道生成。
spark beyond(https://www.sparkbeyond.com/)是一个人工智能驱动的研究引擎,用于发现模式,预测结果,并利用网络上的数据仓库。SparkBeyond 的独特竞争优势在于其强大的特征发现引擎。专注于提高模型预测准确性的特征,SparkBeyond 能够在短时间内生成数十万个特征,并根据其重要性进行筛选。
学生们
来自 NYU 的 15 名金融工程硕士学生参与了这个项目。我们有相关的机器学*经验,并努力成为合格的数据科学家。我们深入研究了 AutoML,以加深我们对机器学*领域的理解。
数据集
我们在比赛中使用了 8 个著名的开源数据集。
分类:
泰坦尼克号(从 H2O 下载):利用乘客的信息预测泰坦尼克号上乘客的生存情况。
鸢尾:利用萼片和花瓣的长度和宽度预测鸢尾的种类。
心脏病:利用生理数据预测患者是否患有心脏病。
Lending Club(由 Spark Beyond 提供):使用财务指标预测贷款违约。
回归:
零售销售预测(由 H2O 提供):使用商店和区域数据预测销售量。
广告:利用不同媒体上的广告支出预测销售额。
波士顿房价:利用社区和房屋数据预测波士顿房价。
金县的房屋销售:利用房屋特征预测房屋销售价格。
实施
对于实现,我们使用最低接触(以避免给机器人类的优势!)H2O 和 SparkBeyond 的 AutoML 功能;我们还花了 1 周时间让学生建立模型和预测数据。
对于 H2O,用户可以使用它开箱即用,没有很多调整。对于 SparkBeyond,用户可以选择他们想要使用的算法和功能数量。对于人类,15 名学生在每个数据集上测试了几种算法,保留了最好的一种与 AutoML 进行比较。
超越界面的 H2O 和火花
结果
下图是机器对人类和 H2O 对 SparkBeyond 的赢家数量的饼状图。决定获胜者的标准是:如果该方法的 CV 和测试分数都获胜,则该方法为获胜者;如果该方法的 CV 或测试分数中只有一个获胜,则结果为“*局”。
中奖人数(详细数据*附录中的表 1 和表 2)
下面的条形图显示了标准化的指标—人与机器的百分比。需要注意的是,我们对前 3 个数据集使用了均方误差,包括金县的房屋销售、波士顿房价和广告。为了更容易与其他指标进行比较,我们选择使用这 3 个数据集的归一化指标的倒数。
如果标准化度量> 100%,则表明人类优于机器。我们可以看到,对于 CV 分数,人类只在一个数据集上对机器有细微的优势。然而,就考试成绩而言,一半的人打败了机器。
人%机器(人的结果占机器结果的百分比)
那么谁赢了,人还是机器?
“竞争”的结果是,在 8 个数据集里,AutoML 赢了 4 场,3 场*局,人类赢了 1 场。
对于我们测试的 8 个基本数据集,AutoML 模型相对于手工挑选的模型显示出明显的优势。然而,如果我们仔细观察预测分数,人类和 AutoML 之间的表现差距是微妙的。
只有一组在交叉验证分数上超过了机器。然而,有 4 组在测试分数上超过了机器。这个特殊的实验表明人类模型在测试集上比在训练集上有更好的机会击败 AutoML 模型。 AutoML 的特征工程和模型选择完全基于性能,这可能会在训练集上获得更高的分数。然而,这种方法也降低了模型的可解释性,并可能导致轻微的过度拟合问题。另一方面,学生更依赖于对数据集的理解,因此,人类模型可以生成有竞争力的样本外结果。但请注意,即使是样本外的分数,也只有一半的人类模型击败了机器模型。总体而言,AutoML 仍有不可忽视的优势。
关于 AutoML 的利与弊,你需要知道什么
总的来说,AutoML 可以成为数据科学家解决问题的一个很好的起点。它还可以帮助非数据科学家轻松获得最好的机器学*。
H2O 和斯帕克比谁更强?
总的来说,在我们测试的 8 个数据集(H2O 3 胜,spark beyond 2 胜,3 *)上,一个*台相对于另一个*台没有明显的优势。在这两个*台上的实验中,学生们发现 SparkBeyond 具有更好的特征工程功能,而 H2O 通过提供详细的报告和模型解释功能而更加用户友好。
下一步是什么?
在我们的实验中,一些团队通过将 SparkBeyond 生成的要素添加到数据集,然后在 H2O 上执行 AutoML,取得了出色的结果。结合每个数据科学解决方案提供商的最佳功能可能是未来探索的一个有趣方向。
我们在这个实验中使用的数据集既简单又普通。当处理更复杂的数据集时,数据科学*台可能会展现出更多的魅力。我们的团队将继续探索这些*台,在具有不同结构的更复杂的数据集上实现它们的功能,如时序数据、非结构化/文本数据、不*衡/倾斜数据等。请继续关注我们的下一篇文章。
如果您想了解我们项目的更多信息,请随时通过 LinkedIn 联系 15 名才华横溢、训练有素的 NYU 金融工程硕士学生。我们对与 AutoML、数据科学和量化金融相关的讨论持开放态度。
分类:
泰坦尼克号:,于
虹膜:,顾
回归:
广告:,杨
波士顿房价:刘贺静,
景县房屋销售:元泰谢,
附录
最佳机器和最佳人类的表现
H2O 和斯帕克的表现
标准化指标:人%机器
时间序列预测的 AutoML
《辛普森一家》第七季第 135 集(“特大号荷马”)
虽然我不是现在汽车的粉丝,但我喜欢参加汽车比赛。我相信这样的比赛是一个很好的学*机会,可以为未来的项目提供强大的管道。AutoML 竞赛介于 Kaggle 类竞赛和 LeetCode 任务之间:您的代码应该给出高分,并且应该稳定快速。
最近我参加了汽车系列——汽车时间序列数据竞赛,我在 40 名参赛者中获得了第一名(15 名进入决赛)。这篇文章概述了我的解决方案。
我在莫斯科 2020 年奥维托 ML 培训期间关于最终解决方案概述的讲话
竞争描述
AutoSeries 是网络搜索和数据挖掘( WSDM )大会的竞赛项目之一。该比赛是由 4Paradigm 和 ChaLearn 举办的第 10 届 AutoML 比赛。之前的目标是为表格数据、计算机视觉、自然语言处理和语音识别任务提供自动化的机器学*解决方案。过去挑战赛的完整列表可以在 AutoML 挑战赛的官方网站上找到。
这项挑战旨在为时间序列回归任务提出自动化解决方案。AutoSeries 仅限于多元回归问题,这些问题来自不同的时间序列领域,包括空气质量、销售、工作场所、城市交通等。挑战中的每个数据集都是表格数据,其特征主要有三种类型:Id(可能有多个特征,也可能没有)、时间戳(每个数据集只有一个时间戳)、其他特征(数字或分类)以及预测目标。Id 特征的组合识别一个变量(一个时间序列)。
给定数据集的示例。正如你所看到的,数据是混乱的,但是有一些时序模式
参与者要提交代码,代码将在 Docker 容器中运行(CPU: 4 核,16 Gb RAM,无 GPU)。首先,该模型是在完整数据上训练的,但是在推理过程中,它可以被更新或重新训练。公共排行榜是在五个数据集上计算的,私人——没有人为干预的五个新数据集。私有数据集的结果决定了最终的排名。
最终解决方案概述
最终解决方案的一般步骤
这一部分专门讨论最终解决方案的主要部分。它的代码公布在这里:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/DenisVorotyntsev/AutoSeries)
特征工程
该解决方案由几个步骤组成。首先,为时序任务生成公共特征。这些特征的数量和类型是管道的超参数,应该针对每个任务分别进行优化,但是由于缺乏计算时间,我决定为所有任务生成相同的特征,并在特征选择阶段删除无用的特征。
第一批特征是基于最关键的数字特征的特征。数字特征对的数字运算(加、减、乘、除)总是提高基于树的模型的得分,因为新特征可能揭示数据中的一些隐藏关系。
让我们以预测公寓的价格为例。关于公寓楼层( ap_floor )和建筑物中楼层总数( total_floors )的已知信息可以通过添加新特征来丰富,该新特征显示公寓楼层在建筑物中的相对位置:
*rel_floor* = *ap_floor / total_floors*
此功能可能有助于模型理解排屋中的第三层( rel_floor 更接近 1)与摩天大楼中的第三层( rel_floor 更接近 0)不同。
然而,如果我们执行所有可能对的数值运算,这种特征工程策略有两个重大问题:过拟合,这在时序任务中尤其重要,以及存储器问题(使用了 16 RAM docker)。为了减少负面影响,选择一小部分特征用于配对。这是通过将整个数据集拟合到浅层 LigtGBM 模型(10 棵树)来完成的。所有使用的特征按照“增益”重要性排序,即使用该特征的分裂的增益的总和。然后 top-n 最重要的数字特征被选择成对。
下一批特征基于数据的时间序列性质:以前的值和差异。我计算目标的滞后值、最重要的数字和分类特征、目标的最后值(滞后= 1)和目标的滞后值(滞后> 1)之间的差异。这些新特性是最重要的特性之一。
最后一批是时间序列特征:年、月、星期几、一年中的某一天和小时。我可以添加更多基于时间的特性,比如一天中的一分钟,一年中的四分之一,等等,但是我决定不这样做,所以我的解决方案是通用的。将这些新特征分类有时会提高分数,但在其他情况下,会显著降低分数。我在推理过程中没有足够的计算时间来优化这个超参数(即,作为数值或分类处理),所以它们都被作为数值处理。
验证和基线模型
在生成新特征之后,基线模型被训练。基线模型使用所有初始和创建的特征。它使用 CatBoost 编码器对类别进行编码,并按原样使用目标。该模型分两步训练:
- 首先,数据被分成训练和验证部分。通常,您希望您的培训/验证/测试分割能够模拟“生产设置”中模型的使用。在时间序列的情况下,这意味着模型不会频繁更新,您在验证部分采用 20–30%的数据(或使用相同比例的滚动窗口)。在这个竞赛中,模型的频繁更新是可能的,因此,验证部分应该更小:验证部分是全部训练数据的 10%。它用于早期停止,即优化 boosting 集成中的树的数量。在这一步之后,模型可以开始进行预测,接下来的所有步骤都是可选的(对于高分来说是至关重要的)。
- 使用最佳数量的树在全部数据上重新调整模型。
我使用 solo LigthGBM 模型进行预测。我测试了 CatBoost(没有 GPU 太慢)和 LinearModels(不够准确)。我还用不同的种子测试了打包和训练,以减少预测的方差,但这些方法花费了大量时间,并且没有将分数提高到足以包含在最终解决方案中。
超参数优化
超参数优化的步骤
我在超参数优化的推理过程中时间太少,所以我决定将所有可能的超参数组合缩小到最有希望的组合,即:
- 处理分类变量:将分类特征视为 pandas 类别类型,将难题留给 LightGBM,或者用 CatBoost 编码对每个类别进行编码(如果您还没有阅读,请查看我以前关于编码类别的文章)。
- 目标预处理:按原样使用目标或者通过微分计算一个新的目标进行回归:new _ target(t)= target(t)-target(t-1)。差分有助于克服时间序列数据的非*稳性。我还测试了 power transformation(对 target 和 Box-Cox 求根)来减少*稳性,但它没有将分数提高到足以包含在最终解决方案中。
通过选择最佳类别编码器来增加 ML 模型的分数
towardsdatascience.com](/benchmarking-categorical-encoders-9c322bd77ee8)
首先对每组参数进行验证,如果新的验证分数更高,则对模型进行改装。在选择了最佳的管线超参数集之后,模型开始特征选择:使用前 5、10、20 等来重新调整模型。最重要特性的百分比(“获得”重要性)。如果分数有所提高——一组新的特征被用于最后的可选步骤——优化超参数(随机网格)。
更新
更新很简单:用完整的数据(训练数据加上新的训练数据)改装最优模型。然而,频繁更新对高分至关重要。
结果
我在这个项目上投入了大量的精力,奋斗得到了回报。我在公共排行榜上获得第三名,在私人排行榜上获得第一名。
比赛的最终私人排行榜(已更新)
经验教训
在比赛期间,我面临了很多 bug,这些 bug 耗费了我的时间和提交材料。bug 是不可避免的,但是有注释,如果一开始就用的话对我帮助很大:
- 记录尽可能多的有用信息:数据框中的列(训练和测试数据中的列顺序可能不同)、数据类型(训练和测试数据框中的数据类型可能不同)、每次训练的时间、训练的剩余时间等。这将有助于理解为什么提交失败或得分低。例如,由于一个愚蠢的错误,我提交的一些模型没有更新,我没有注意到这一点。因此,我的分数远低于应有的水*。一条简单的消息打印出来("型号更新!")化险为夷,帮我找到了 bug。
- 在 AutoML 中,对未知数据的测试是必不可少的。您可能很容易使您的解决方案过度适应公共部分,并且它可能会在看不*的数据上崩溃。这就是我的情况——我提交的第一个任务失败了。尽量在比赛开始的时候收集更多的数据。新的数据集应该是多样化的,例如,在类别和其他因素中缺少值或字符串,这可能会使您的代码崩溃。用不同的时间预算来测试它们:当你时间紧迫时,试着输出甚至很差的模型。
- 以“即插即用”的方式组织代码:管道的每个部分都不应该依赖于其他部分。例如,我想拟合线性回归而不是 LightGBM,这样做容易吗?如果你的代码是组织良好的,它将是。在这次比赛中,我朝着更干净、更有条理的代码迈出了一大步。然而,有时我认为它仍然是垃圾,我看到了进步。
- 不要在熊猫身上使用代替操作,因为有问题。只要有可能,就不要使用它。
感谢
我要感谢汽车系列赛的组织者——4 个 Paradigm 和 ChaLearn 团队。他们做得很好:收集了数据,准备了提交评分引擎,编写了一个强大的基线解决方案,并回答了论坛和电子邮件中出现的问题。谢谢你的工作!
AutoML + Pentaho + Grafana 用于快速解决方案原型制作
TPOT 机器学*实验。
克里斯托弗·伯恩斯在 Unsplash 上拍摄的照片
在构建机器学*解决方案时,数据科学家通常会凭直觉选择适当的特征、建模技术和超参数来解决手头的问题。在实践中,这涉及到利用经验(和代码!)从以前的项目中,结合来自主题专家的领域知识,以及许多(许多、许多、许多、许多…!?!)迭代开发周期。
无论实验阶段是有趣的、极其乏味的还是介于两者之间的,有一点是肯定的;这个开发过程并不适合快速解决方案原型,尤其是对于新的或者不熟悉的问题领域。
在本帖中,我们将介绍使用自动化机器学*(AutoML)和 Pentaho(我们的数据集成*台选择)和 Grafana(可视化)快速设计、构建和评估大量建模方法,以预测重型斯堪尼亚卡车中的气压系统(APS)故障(2016 年工业挑战在第 15 届智能数据分析国际研讨会上举行)。我们想看看这种方法是否能够:
(1)加快充分执行模型的时间。
(2)帮助我们探索替代的建模/数据准备方法。
(3)为我们未来的项目提供一个可重复的、快速的开发模板。
数据集
我们决定在 UCI 机器学*库上使用 Scania CV AB 发布的数据集。它分为训练集和测试集,都有 171 个属性。由于专有原因,属性名称被匿名,但每个字段都对应于卡车上的传感器。训练集总共有 60,000 个样本,其中 59,000 个属于负面类别,1000 个属于正面类别。为了处理数据集中的许多缺失值,我们使用了中位数插补技术。数据集是高度不*衡的,为了对负类进行欠采样,我们使用了随机欠采样和压缩最近邻规则欠采样的组合,以便创建*衡的数据集。至于评分,我们使用了与本文中相同的成本指示值。在这种情况下,每个假阳性将花费 10 美元(不必要的检查),假阴性花费 500 美元进行相关的修复。基于这些价值,我们将计算总成本。
我们的 AutoML 工具包
AutoML 库旨在使特征工程和模型选择的过程自动化。我们决定使用 Python TPOT(基于树的流水线优化工具)库,该库使用进化算法来评估多种机器学*技术、特征工程步骤和超参数。换句话说,TPOT 尝试了一种特定的机器学*管道,评估其性能,并随机改变管道的部分内容,以寻求更好的整体预测能力。
除此之外,我们使用 Pentaho 为未来项目构建可重用的 AutoML 模板,管理实时模型目录和管理数据准备。 Grafana 用于显示搜索过程中各种管道/算法组合的性能。
入门
在 Pentaho 中,我们导入了 Scania APS 数据,采样以重新*衡类,并将所需的 Python 代码嵌入到数据流中以利用 TPOT 函数。
图 Pentaho 中的数据清理和欠采样
我们当前的任务是分类任务(APS 系统故障/无故障),所以我们将使用 TPOT 分类器。TPOT 的用法和语法类似于任何其他 sklearn 分类器。分类器参数的完整列表可在这里找到。出于开发目的,我们使用了:
世代:运行流水线优化过程的迭代次数。
population_size :每一代在遗传编程群体中保留的个体数量。
mutation_rate: 告诉进化算法每一代应用随机变化的管道数量。
评分:功能用于针对分类问题评估给定管道的质量。我们使用“召回”作为开始,因为由于较大的相关成本,最初优化识别所有真正的 APS 故障是有意义的,而不是最小化不必要的呼叫。
periodic _ check point _ folder:如果提供,这是一个文件夹,TPOT 将在优化时定期保存帕累托前沿的管道。我们希望在搜索过程中实时记录性能最佳的管道,以感受性能最佳的算法,并记录下来供以后比较。
详细程度:TPOT 在运行时传递了多少信息。随着搜索的进行,我们希望看到一切。
#example TPOT codeimport pandas as pd
import numpy as np
import pickle
import timefrom tpot import TPOTClassifier
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
from sklearn.externals import joblib#scaling training data and saving scalermin_max_scaler = preprocessing.MinMaxScaler()x_scaled = min_max_scaler.fit_transform(x)scaler_name=’/home/demouser/Desktop/Aldrin/scalers/scaler’+str(int(time.time()))+’.save’joblib.dump(min_max_scaler, scaler_name)X=np.asarray(x_scaled)#splitting train and CV setsX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=None)#Training TPOT classifiertpot = TPOTClassifier(generations=50, verbosity=3,population_size=100, periodic_checkpoint_folder=path_to_folder, scoring=’roc_auc’ , mutation_rate=0.9)tpot.fit(X_train, y_train)output_score=str(tpot.score(X_test, y_test))tpot.export(path_to_pipeline)pickle.dump(tpot.fitted_pipeline_, open(file_name, ‘wb’))
构建并可视化模型目录
我们还运行了一个 Pentaho 作业来收集 TPOT 生成的 ML 管道,并创建一个实时模型目录(图 2 & 3)。
图 2: Pentaho 收集 TPOT 管道并将结果传输到 Grafana 的工作。
图 3:用于数据摄取、争论和执行 TPOT 模型搜索算法的 Pentaho 转换。
我们在 Grafana(图 4)中可视化搜索性能最佳的管道,这使我们能够调整初始 TPOT 搜索参数,以获得运行时间与精度的正确*衡。
图 Grafana AutoML 仪表板的初始示例,用于跟踪 TPOT 搜索进度,包括一段时间内表现最佳的模型管道和召回分数。
快速成型?
我们的测试集由 16k 个样本组成,其中 375 个是 APS 系统中的类阳性故障。具体来说,对于斯堪尼亚来说,这些失败的成本是 375 * 500 美元= 187,500 美元。
我们能够在第一次通过时获得相当好的结果:在不到 30 分钟的时间内,使用我们的训练数据集,在测试集的肯定类上获得了 82%的召回率和 78%的准确率。然而,总的来说,成本相当高——33,400 美元。跑了 30 分钟后,TPOT 建议使用基于 XGBoost 的模型。你需要运行 TPOT 多长时间才能让它正常工作,这取决于数据的大小、维度、精度要求以及你必须投入的计算能力。通常用户运行 TPOT 算法几个小时甚至几天来得到最好的管道。我们的目标是获得总成本
模型可解释性
接下来,我们想了解 170 个特征(在这种情况下是传感器馈电)中的每一个对我们的 APS 故障预测有多大贡献。这将有助于我们了解哪些传感器反馈是重要的(鉴于我们缺乏斯堪尼亚重型卡车的专业知识!),以及那些积极阻碍我们成功的因素。使用SHAP(SHapley Additive exPlanations)库并将所需的 Python 代码嵌入到我们的 Pentaho 数据流中,我们能够从 170 个特征中识别出 30 个最重要的特征,并减少模型训练中使用的数量。
探索不同的建模方法
Grafana 中的 AutoML 仪表板允许我们看到哪些建模方法对我们的用例表现良好(图 4 中的示例视图)。除此之外,SHAP 值使我们能够探索哪些特征对模型预测最重要,每个特征的分布对正确分类的概率的贡献,以及不同特征之间的依赖关系(图 5)。
图 5:在 Grafana 中可视化 SHAP 值,探索哪些特征对模型预测最重要,以及不同特征之间的依赖关系。
初步结果
在运行了 8 个小时的优化数据流后,TPOT 提出了一个随机森林模型,这与之前的工作【1】是一致的,随机森林也产生了最好的结果。就*衡假阳性和假阴性而言,我们确定 0.2 的阈值是最有希望的。我们的阳性类别概率阈值为 0.2 的最终模型识别出 357 个真阳性、639 个假阳性、14986 个真阴性、18 个假阴性或 95.2%的召回率和 35.8%的精确度。这相当于不必要的维护呼叫的总成本为 6390 美元,错过的 APS 故障的总成本为 9000 美元,与最初挑战期间先前工作和中报告的成本相当。总成本为 15390 美元,比最初运行时提高了两倍多。
进一步改进
我们能够显著提高模型性能,但它仍远未达到[1] 中所示的最佳模型性能。我们决定用超参数调谐来获得 TPOT 输出的最佳管道。在对随机森林模型(最佳参数 n_estimators=200,max_depth=10)执行超参数网格搜索后,我们能够得到 12320 美元的总成本,其中有 13 个假阴性和 582 个假阳性,38.3%的精确度和 96.5%的召回率。这让我们更接近于车型在【1】和原挑战赛【2】中产生的最佳成本。
总结
TPOT 图书馆与 SHAP 合作,为探索各种模型提供了一个很好的工具集,同时更好地理解了哪些功能正在影响模型的行为。这种方法的优点包括相对容易使用和需要配置的参数最少。另一方面,TPOT 能够找到最佳的模型配置,但无法在 10 小时的运行周期内优化超参数。从我们的角度来看,这突出了两种方法(TPOT 和 SHAP)的计算复杂性。人们需要等待相当长的时间(例如 10 个小时)才能得到结果,但正如 TPOT 的创造者所说,AutoML 算法并不意味着运行半个小时。总之,考虑到我们对数据集的不熟悉,我们认为 AutoML 方法减少了我们的实验时间或“获得合适的原型解决方案的时间”。当使用熟悉的数据源时,在减少开发时间方面可能没有什么好处,但是 TPOT 可以以辅助方式用于寻找替代的建模方法,或证明当前使用的建模技术。
参考文献
[1]Mr unal sawant 在 https://link.medium.com/zrKQJkThv6 T2 @ the startup _ 的斯堪尼亚卡车上的 APS 故障
[2]费雷拉·科斯塔,卡蜜拉和纳西门托,马里奥。(2016).IDA 2016 工业挑战:使用机器学*预测故障。381–386.10.1007/978–3–319–46349–0_33.【https://archive.ics.uci.edu/ml/datasets/IDA2016Challenge
自动归零
我们花了 60 年才发现一个可以自我发现的东西。
我们人类设计模型,模型有参数。可以把参数想象成稍微向左或向右旋转的旋钮,改变模型的行为。近年来,神经网络在各种各样的任务上表现出显著的成功,并且已经看到了巨大的普及增长。考虑到技能、计算资源和 ML 研究的难度等因素,它催生了一个名为 AutoML 的新领域,,旨在用机器计算的时间代替人类的研究时间。
什么导致了自动归零?
AutoML 研究已经通过使用人类专家预先描述的构建块来限制搜索空间(算法可以从中提取操作的项目池),如ReLU 层、卷积层、批处理规范化层,这往往会使搜索结果偏向于人类设计的算法。一个常*的例子是神经结构搜索,它使用复杂的人为设计的层作为构建块,并遵循反向传播的规则来搜索新的结构和最佳超参数。
AutoML 的其他变体通过预定义某些他们认为至关重要的超参数来限制他们的搜索空间,但该算法无法像反向传播期间的学*速率那样实现它。一些研究建议使用固定的预处理管道将处理后的输入馈送到算法,如图像情况下的数据扩充。因此,许多这些方面仍然是手工设计的。这些方法可能会节省计算时间,但可能会降低 AutoML 的创新潜力。
AutoML-Zero 背后的概念很简单,为什么我们不假设我们没有花哨的运算(像反向传播或梯度下降)并让算法通过使用基本的数学运算从零开始设计一切,这就是为什么它被称为机器学*从零开始。 把它想象成没有 TensorFlow,没有 PyTorch,只是用 NumPy 来进化机器学*的概念。令人惊讶的是,它可以发现非线性模型、学*率、梯度等概念。所以基本上在你眼前持续了 30 年的神经网络进化。
高级工作概述
AutoML-Zero 框架背后的想法是,它们初始化大量的程序,每个程序包括三个在启动时为空的函数。这三个功能是
- setup() - >该函数用于初始化变量。
- predict() - >该函数用于对给定的数据点进行预测。
- learn() - >此函数用于更新变量,以便预测函数随着时间的推移执行得更好。
给定这三个函数,AutoML-Zero 必须在这些通用函数中填充程序的其余部分。
来源:https://github . com/Google-research/Google-research/tree/master/automl _ zero
以上是 AutoML-Zero 发现的一个线性回归问题的算法片段。如您所*,设置函数初始化了一个名为“s2”的变量,该变量后来被用作学*函数中的学*速率,预测函数通过应用输入特征和学*权重“v1”之间的点积进行预测,学*函数首先计算实际标注和预测标注之间的误差,应用学*速率,计算梯度并更新权重。让我们看另一个片段
以上是自动发现的 CIFAR-10 分类算法的片段。设置函数初始化学*速率,预测函数将噪声引入特征(它发现引入噪声可以提高其预测精度),学*函数是计算误差、估计梯度、归一化梯度、归一化误差等等。
记住,程序开始时是空函数。事实上,这些程序可以学*像点积、梯度和归一化这样的东西,这是令人惊讶的,因为它必须搜索这个巨大的搜索空间,这个空间非常稀疏,而你在这种空间中发现的大多数程序都是完全无用的。
内部工作
在这一部分,我们将回答两个问题。如前所述,AutoML-Zero 框架初始化了大量的程序。为什么?(请记住,每个程序都包含这三个功能——设置、预测和学*)第二个问题是,它如何准确地填写功能中的指令?。
AutoML-Zero 设置使得搜索空间非常稀疏,因此,一个好的学*算法,即使是一个琐碎的任务,也可能是十分之一。在这种环境下,随机搜索无法在合理的时间内找到解决方案。为了克服这个问题,通过使用正则化进化搜索在搜索空间中发现这些机器学*程序。
正则化进化搜索
在正则化进化搜索中,大量程序被初始化(称为种群),它们的函数为空。然后,算法从总体中选择一个样本(两个或更多),对它们进行评估,并选择表现最好的一个作为父代。然后父母克隆自己创造一个孩子,孩子变异了。这种突变是从三个选项中随机选择的
- 在随机位置随机插入或删除指令。
- 随机替换组件函数中的所有指令
- 修改指令的一个参数,将其替换为随机选项。
跟随动画可能会让你对进化搜索有更深的理解
演进实施加速
机器学*算法的自动零搜索空间是非常稀疏和通用的。这意味着这些程序中的大部分是完全无用的。例如,在第二种类型的变异中,预测函数接受标量“s0 ”,并将其分配给某个矩阵的*均值,该矩阵在设置中根本没有定义,在学*函数中也根本没有学*,然后它将另一个随机标量值“s3”分配为另一个随机标量值“s7”的余弦。所以你可以观察到,这些函数完全没有用,没有做任何有助于将指针移向机器学*算法的事情。
来源:https://github . com/Google-research/Google-research/tree/master/automl _ zero
为了让这种算法发挥作用,他们需要用他们的进化搜索策略评估大量不同的模型。因此,研究人员特别描述了通过 5000–10000 个模型/秒/cpu 核心的搜索。他们这样做的一些方法是通过实现迁移,这是一种在不同的 CPU 之间混合这些不同模型的方法,以确保在这个分布式系统中不同工作人员的多样性。然后是 FEC(功能等价检查),这是一种确保两个程序对于给定的输入特性没有相同输出的方法。还有一些数据集多样性,其中算法必须从多标签分类数据集(如 MNIST ( [0 对 8]或[6 对 9])中执行二元分类任务。一组更加多样化的任务进一步有助于提高这些程序的实用性。然后是渐进式动态跨栏,在那里他们有一个中级健康评估,以截断表现不太好的模型。
算法进化
投射的双星 CIFAR-10 上的一个演化实验的进展。
来源:https://storage . Google APIs . com/gresearch/automl _ zero/progress . gif
结论
这是对 AutoML 新版本的一瞥。在 AutoML-Zero 中,我们还没有达到最先进的水*。但令人兴奋的是,它仅仅从矩阵向量乘法中生成一个程序来进行机器学*,这是非常令人兴奋的。目标是减少搜索空间中的人为偏差。我希望这种方法将发现机器学*概念的新的基本构件。
自回归模型— PixelCNN
深度学*/生成模型
使用深度生成模型创建数字!
编剧沃尔特·雨果·洛佩兹·皮纳亚、佩德罗·f·达·科斯塔和杰西卡·达弗伦
大家好!这是我们关于现代自回归模型系列的第一篇文章。以下是我们将在本系列中涉及的主题:
总结
- 自回归模型— PixelCNN
- 模拟彩色图像
- PixelCNN 的盲点及如何修复——门控 PixelCNN
- 使用门控像素 CNN 的条件生成
- 带裁剪卷积的门控像素 CNN
- 提高性能— PixelCNN++
- 缩短采样时间—快速 PixelCNN++
- 使用注意机制——pixels nail
- 生成多样化的高保真图像——VQ-VAE 2
每个主题的实现都可以在这个库中找到
开始吧!
介绍
生成模型是来自无监督学*的一类重要的模型,在过去的几年中受到了很多关注。这些可以被定义为一类模型,其目标是学*如何生成看起来来自与训练数据相同的数据集的新样本。在训练阶段,生成模型试图解决密度估计的核心任务。在密度估计中,我们的模型学*构造一个估计量——p model(x)——尽可能的类似于不可观测的概率密度函数——pdata(x)。值得一提的是,创成式模型应该能够从分布中构造新的样本,而不仅仅是复制和粘贴现有的样本。一旦我们成功地训练了我们的模型,它就可以用于各种各样的应用,从图像修复、着色和超分辨率等重建形式到艺术作品的生成。
有几种不同的方法可以用来进行这种概率密度估计,例如:
- 生成敌对网络(GANs) 使用一种方法,其中模型执行 隐式密度估计 。在这种情况下,我们训练一个模型,它可以从p model(x)创建样本,而无需显式定义p model(x);该模型学*产生数据的随机程序,但不提供观察概率的知识或指定条件对数似然函数;
- 变分自动编码器(VAE) 使用一个 显式密度估计 但是定义了一个难以处理的密度函数,其潜在变量不能被直接优化。所以,为了训练模型,我们改为推导并优化似然的下界( 近似密度);我们通过最大化证据下限(ELBO)来优化数据的对数似然性(更多细节可在此处的和此处的中找到);
- 自回归(AR)模型创建一个 显式密度 模型,该模型易于处理以最大化训练数据的可能性( 易于处理的密度 )。为此,使用这些方法,很容易计算数据观察的可能性,并获得生成模型的评估度量。
正如我们提到的,自回归是一种实用的方法,它提供了似然函数的显式建模。然而,为了对具有多个维度/特征的数据进行建模,自回归模型需要施加一些条件。首先,输入空间 X 需要有一个来决定其特征的 排序。这就是为什么自回归模型通常用于具有内在时间步长序列的时间序列。然而,它们可以用于图像,例如,通过定义左边的像素在右边的像素之前,顶部的像素在底部的像素之前。第二,为了对数据观察中的特征的联合分布进行易处理的建模(p(x),自回归方法将p(x)作为条件分布的产物。自回归模型在给定先前特征的值的情况下,对每个特征使用条件来定义联合分布。例如,来自图像的像素具有特定强度值的概率取决于所有先前像素的值;而一幅图像的概率(所有像素的联合分布)就是它所有像素的概率的组合。因此,自回归模型使用链式法则将数据样本 x 的可能性分解为一维分布的乘积(下面的等式)。因式分解将联合建模问题转化为序列问题,在序列问题中,人们学*在给定所有先前生成的像素的情况下预测下一个像素。
这些条件(即确定排序和条件分布的乘积)是自回归模型的主要定义。
现在,大挑战是计算这些条件可能性 p(x ᵢ| x₁,…,x ᵢ ₋ ₁) 。我们如何在一个易于处理和扩展的表达模型中定义这些复杂的分布呢?一种解决方案是使用通用近似器,如深度神经网络。
像素 CNN
DeepMind 在 2016 年推出了 pixel CNN(Oord et al .,2016 ),这个模型开启了自回归生成模型最有前途的家族之一。从那时起,它就被用于生成语音、视频和高分辨率图片。
使用 VQ-VAE-2 生成图像(链接)
PixelCNN 是一个深度神经网络,可以捕捉其参数中像素之间的依赖关系分布。它沿着两个空间维度在图像中一次一个像素地顺序生成。
感兴趣的像素 I(红色)由所有先前的像素(蓝色)定义。PixelCNN 可以沿着深度神经网络使用卷积层对它们的关联进行建模。
使用卷积运算,PixelCNN 可以并行学*图像中所有像素的分布。然而,在确定特定像素的概率时,标准卷积层的感受野违反了自回归模型的顺序预测。在处理一个中心像素的信息时,卷积滤波器考虑其周围的所有像素来计算输出特征图,而不仅仅是前面的像素。然后采用掩模来阻挡来自尚未预测的像素的信息流。
屏蔽卷积层
可以通过将不应考虑的所有像素置零来进行掩蔽。在我们的实现中,创建了一个与卷积滤波器大小相同、值为 1 和 0 的掩码。在进行卷积运算之前,该遮罩与权重张量相乘。在 PixelCNN 中,有两种类型的遮罩:
- 掩码类型 A :该掩码仅适用于第一个卷积层。它通过将遮罩中的中心像素置零来限制对感兴趣像素的访问。这样,我们保证模型不会访问它将要预测的像素(下图中的红色)。
- 屏蔽类型 B :该屏蔽应用于所有后续卷积层,并通过允许从一个像素到其自身的连接来放松屏蔽 A 的限制。为了说明第一层的像素预测,这是很重要的。
掩码 A 仅用于第一卷积层。在所有其他层中使用掩码 B,以允许以感兴趣的像素为中心的卷积运算的信息沿着网络传播。
在这里,我们展示了一个片段,展示了使用 Tensorflow 2.0 框架实现的掩码。
体系结构
在 Oord et al. 2016 中,PixelCNN 使用了以下架构:第一层是带有 7x7 滤波器的掩蔽卷积(A 型)。然后,使用 15 个残差块。每个模块使用掩码类型为 B 的 3×3 卷积层和标准 1×1 卷积层的组合来处理数据。在每个卷积层之间,有一个非线性 ReLU。最后,残余块还包括残余连接。
像素 CNN 的架构。
在块序列之后,网络具有 RELU-CONV-RELU-CONV 层链,使用具有 1x1 滤波器的标准卷积层。然后,输出层是预测像素的所有可能值中的值的 softmax 层。模型的输出具有与输入图像相同的空间格式(因为我们需要每个像素的输出值)乘以可能值的数量(例如,256 个强度级别)。
在这里,我们展示了使用 Tensorflow 2.0 框架实现网络架构的一个片段。
预处理
像素 CNN 的输入值被缩放到[0,1]的范围内。在这个预处理过程中,有可能以较低数量的强度等级量化像素值。在我们的实现中,我们首先呈现用两个强度级别训练的模型,然后用所有 256 个级别。我们注意到,由于问题复杂性较低(在像素的概率分布中要考虑的可能值较少),该模型在具有较少级别的数据中表现更好。
目标数据对应于指示像素强度的分类(整数)值。
模型评估
PixelCNN 有一个简单的训练方法。该模型通过最大化训练数据的可能性来学*其参数。
由于大多数优化问题被定义为最小化问题,一个常用的技巧是将训练目标转化为最小化负对数似然 (NLL)。
由于 p(xᵢ|θ) 对应于 softmax 层输出的概率,NLL 等价于交叉熵损失函数——监督学*中常用的损失函数。此外,NLL 是一种用于比较生成方法之间性能的指标(使用 nats 单位或每像素位数)。
推论
由于 PixelCNN 是一个自回归模型,推理恰好是顺序的——我们必须逐个像素地生成。首先,我们通过向模型传递零来生成图像。它不应该影响第一个像素,因为它的值被建模为独立于所有其他像素。因此,我们执行向前传递并获得它的分布。给定分布,我们从多项式概率分布中抽取一个值。然后,我们用采样的像素值更新我们的图像,并且我们重复这个过程,直到我们产生所有的像素值。这里使用 PixelCNN 使用 MNIST 数据集在 150 个时期后生成样本。每张生成的图像都有四级像素强度。
相同的采样过程可以用于部分遮挡的图像作为起点。
现在,我们还尝试训练或建模以产生具有 256 个像素强度级别的图像。
生成了 256 个强度级别的数字。
部分遮挡的图像。
与其他生成模型(VAE 和甘斯)相比,这种采样过程相对较慢,在其他模型中,所有像素都是一次性生成的。然而,最近的进展已经使用缓存值来减少采样时间(快速 PixelCNN++,在接下来的帖子中解决)
结论
PixelCNN 模型的优点是联合概率学*技术是易处理的,并且可以使用梯度下降来学*。没有近似值;我们只是试图在给定所有先前像素值的情况下预测每个像素值。由于 PixelCNN 是通过最小化负对数似然来训练的,因此与替代方法(例如 GANs 需要找到纳什均衡)相比,它的训练更加稳定。然而,由于样本的生成是连续的(逐个像素),原始的 PixelCNN 在可扩展性方面存在问题。在下一篇文章中,我们将在具有 RGB 通道的数据集中训练 PixelCNN 模型。
参考
- http://sergeiturukin.com/2017/02/22/pixelcnn.html
- https://towards data science . com/auto-regressive-generative-models-pixel rnn-pixel CNN-32d 192911173
- 【https://deepgenerativemodels.github.io/
- https://eigenfoo.xyz/deep-autoregressive-models/
- https://wiki.math.uwaterloo.ca/statwiki/index.php?title = stat 946 f17/Conditional _ Image _ Generation _ with _ pixel CNN _ Decoders
- https://www . code project . com/Articles/5061271/pixel CNN-in-auto regressive-Models
- https://towards data science . com/blind-spot-problem-in-pixel CNN-8c 71592 a 14 a
- https://www.youtube.com/watch?v=5WoItGTWV54&t = 1165s
- https://www.youtube.com/watch?v=R8fx2b8Asg0
- https://arxiv.org/pdf/1804.00779v1.pdf
- https://blog.evjang.com/2019/07/likelihood-model-tips.html
- https://arxiv.org/abs/1810.01392
- http://bjlkeng.github.io/posts/pixelcnn/
- https://jrbtaylor.github.io/conditional-pixelcnn/
- http://www.gatsby.ucl.ac.uk/~balaji/Understanding-GANs.pdf
- https://www.cs.ubc.ca/~lsigal/532S_2018W2/Lecture13b.pdf
- https://tinyclouds.org/residency/
- https://tensor flow . blog/2016/11/29/pixel CNN-1601-06759-summary/
- https://web . cs . hacettepe . edu . tr/~ ay Kut/classes/spring 2018/CMP 784/slides/le C10-deep _ generative _ models-part-I _ 2 . pdf
AutoVIML:自动化机器学*
为任何给定的数据集自动选择最佳的机器学*模型
法托斯 Bytyqi 在 Unsplash 上的照片
机器学*提供了学*算法的优势,该算法随着经验自动改进。有“n”种机器学*算法和技术,通常,我们需要测试其中的大多数,以便为我们的数据集找到具有最高准确性的最佳预测模型。
大多数机器学*方法,如回归技术、分类技术和其他模型都是在 Sklearn 中定义的,但为了选择哪种技术最适合我们的问题陈述或数据集,我们需要尝试所有这些模型以及超参数调整,并找出性能最佳的模型。这需要花费大量的时间和精力,使用名为 AutoVIML 的 python 包可以减少这些时间和精力。
AutoVIML 是一个开源的 python 包,使机器学*变得容易。它所做的是,通过不同的机器学*模型呈现你的数据,并为给定的数据集找出精确度最高的最佳模型。无需对数据集进行预处理即可将其传递给 AutoVIML。它会自动清理您的数据,帮助您对变量进行分类,执行特征约简,可以在单个模型中处理不同类型变量的数据,如文本、数字、日期等。
在本文中,我们将了解如何使用 AutoVIML 来减少创建机器学*模型的时间和精力。我们将看到我们在 AutoVIML 中使用的不同参数,以及它们对我们的预测有什么变化。
安装 AutoVIML
像任何其他 python 库一样,我们将使用 pip 来安装 autoviml。
pip install autoviml
导入 AutoVIML
from autoviml.Auto_ViML import Auto_ViML
加载数据集
为了探索 AutoVIML,您可以使用任何数据集,这里我将使用一个与心脏病相关的数据集,您可以从 Kaggle 下载。这个数据集包含不同的属性和目标变量。
import pandas as pd
df = pd.read_csv('heart_d.csv')
df
使用的数据集(来源:作者)
现在让我们了解一下如何使用 autoviml 来使用这个数据集制作预测模型,以及 AutoVIML 中有哪些参数。
#Basic Example with all parameters
model, features, trainm, testm = Auto_ViML(
train,
target,
test,
sample_submission,
hyper_param="GS",
feature_reduction=True,
scoring_parameter="weighted-f1",
KMeans_Featurizer=False,
Boosting_Flag=False,
Binning_Flag=False,
Add_Poly=False,
Stacking_Flag=False,
Imbalanced_Flag=False,
verbose=0,
)
在上面的代码中,我们可以清楚地看到如何使用 AutoVIML 创建模型,以及我们可以使用哪些参数。现在让我们详细讨论这些参数是什么。
- train:它应该包含数据集的位置,或者如果您已经将数据集加载到数据帧中,则应该包含数据帧的名称。在本文中,我们将它加载到名为“df”的数据帧中,因此我们将它设置为“df”。
- target:它包含目标变量的名称。在我们的例子中,目标变量名是“TenYearCHD”。
- test:它包含测试数据集。如果我们没有任何测试数据集,我们也可以像这样将其留空,以便将训练数据集拆分为训练和测试。
- sample_submission:我们将把它留空,这样它将在我们的本地目录中自动创建提交。
- hyper_param:我们将随机搜索 cv,因为它比网格搜索 CV 快 3 倍。我们需要将此设置为“RS”。
- feature_reduction:我们将把它设置为 true,这样它将考虑到模型创建中最重要的预测变量。
- scoring_parameter:您可以给出自己的评分参数,否则它将根据模型假设合适的参数。我们将在这里使用“加权 f1”。
- KMeans_featurizer:这对于线性分类器应该为真,对于 XGboost 或随机分类器应该为假,因为它会导致过度拟合。
- boosting_flag:用于升压。这里我们将保持它为假。
- 宁滨 _ 标志:默认情况下,它是假的,当我们想把顶部的数字变量转换成装箱的变量时,它可以被设置为真。
- add_poly:我们将它设置为 false。
- stacking_flag:默认为 False。如果设置为 True,将添加从另一个模型的预测中派生的附加要素。我们将保持它为假。
- Imbalanced _ flag:如果设置为 TRUE,它将检查数据不*衡,并将使用 SMOTING 技术消除数据不*衡。
- Verbose:通常用于打印所执行的步骤。我们将它设置为 3。
现在让我们将所有这些参数用于我们的数据集,并使用 AutoVIML 创建具有最高精度的最佳性能模型。
model, features, trainm, testm = Auto_ViML(
train=df,
target="TenYearCHD",
test="",
sample_submission="",
hyper_param="RS",
feature_reduction=True,
scoring_parameter="weighted-f1",
KMeans_Featurizer=False,
Boosting_Flag=True,
Binning_Flag=False,
Add_Poly=False,
Stacking_Flag=True,
Imbalanced_Flag=True,
verbose=3
)
让我们分析一下我们得到的输出。
- 数据分析部分
数据分析(来源:作者)
2.数据清理和特征选择
数据清理(来源:作者)
3.数据*衡和模型创建
数据*衡(来源:作者)
4.分类报告和混淆矩阵
困惑矩阵(来源:作者)
5.模型可视化
模型可视化(来源:作者)
6.特征重要性和预测概率
来源:作者
在上面的集合中,我们看到了 AutoVIML 如何处理数据,清理数据,*衡结果变量,以及创建最佳模型和可视化以获得更好的理解。
同样,您可以使用不同的数据集探索 AutoVIML,并在对本文的回复中分享您的经验。AutoVIML 是一种根据数据集创建最佳性能机器学*模型的简单方法。
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。
如何测量分布式系统中的可用性
可用性是分布式系统的一个关键特征。
图片作者作者
可用性是分布式系统的一个重要方面。在当今时代,大多数系统都需要保证可用性。我们可以说,可用性是一个系统在一个特定的时期内保持功能以执行其所需任务的时间。
根据维基百科,可用性通常被定义为正常运行时间除以总时间(正常运行时间加上停机时间)
我们有时会互换使用可靠性和可用性这两个术语,但它们并不相同。如果我们考虑可能发生的所有可能的真实世界情况,可靠性是随着时间推移的可用性。如果一个系统是可靠的,你可以说它是可用的。但是,如果有,也不一定可靠。
★为什么可用性至关重要?
假设我们正在推出一个教程网站。我们必须确保教程、编码和阅读材料的视频的可用性。每当客户访问教程或学*材料的网站时,他们都希望该系统能够完全运行和可用。该系统可能会失去客户,也很难获得新的客户。一个破碎的系统会给你带来不好的名声。
如果系统经常不可用,用户会不满意。他们甚至可能转向提供相同服务的其他竞争对手的系统。因此,对于系统设计师来说,确保可用性非常重要。
现在,这些 web 服务如果不可用,可能会对其宣传、财务安全等造成危害。但这不会是世界末日。没有这样的系统不会有时变得不可用。
让我们以支持一个飞机软件为例。帮助飞机在空中正常运行的软件。现在,这种系统变得不可用甚至几分钟都是不可接受的。因此,一架可以飞行许多小时的飞机可以说具有极高的可用性。如你所*,这可能会影响到生死存亡。
但是我们不需要在我们的想象中走那么远来寻找高可用性场景的生死状况。
即使是 youtube 这样的*台,试想一下,如果 youtube 一旦宕机,会对多少用户造成多大的影响。每天有数亿人使用 youtube,他们中的许多人也依靠 youtube 谋生。AWS 或谷歌云*台等云提供商也是如此。你能想象有多少服务会因此被封锁吗?你现在可能无法阅读这篇文章!!是..那种不好的效果。
此类云提供商的一次宕机可能会产生巨大而深远的影响。所有这些例子都告诉我们,可用性对于系统设计非常重要。
★如何衡量可用性?
好了,我们明白了,可用性是必不可少的,但是我们如何衡量可用性呢?它可以计算为系统或服务在正常条件下保持运行的时间百分比。
假设我们根据一年中系统正常运行时间的百分比来衡量系统的可用性。因此,如果一个系统一年中有六个月处于运行状态,它将有 50%的可用性。现在,想象一下,如果脸书或优步一年下跌 50%!!!那真的很糟糕;这是不可接受的。没人会用它们,对吧?
在可用性方面,我们需要处理非常高的百分比。老实说,即使 90%的可用性也不够好。按照这个速度,脸书每天会停机 2.5 小时。一年有 35 或 36 天。那你会用它吗?如果发生这种情况,我怀疑扎克伯格是否会使用它。只有 90%的可用性,任何产品都不可能在今天的市场上生存。
★可用性中的 9 是什么
如果一个系统的可用性为 99%,那么它就被称为“两个九”可用性,因为数字“九”会出现两次。即使是 99%可用的系统,一年也有将近四天的停机时间,这对于脸书、谷歌这样的服务来说是不可接受的。
可用性的百分比有时用数字中的“9”的数量“T1”或“9 的类别”来表示。
照片由🇨🇭·克劳迪奥·施瓦茨| @purzlbaum 在 Unsplash 上拍摄
对于 99.9%的可用性称为“三个九”,99.99%的可用性称为“四个九”。“五个九”的可用性(99.999%)给出了一年中 6 分钟的停机时间,可以说这是高可用性的黄金标准。
高可用性(HA)是系统的一个特征,旨在确保一个约定级别的操作性能,通常是正常运行时间,比正常时间长。
高可用性伴随着更高的延迟或更低的吞吐量等代价。当您是系统设计人员时,您的工作就是考虑这些权衡,并决定您需要多高的可用系统。也许您的系统的一部分需要高度可用,而不是整个系统。
比如说,我们以 Medium 为例;它有系统的许多部分。我们需要在配置文件中有 stat 页面的高可用性吗?不完全是。另一方面,文章写作、阅读、主页加载部分需要高可用。如果您在一段时间内看不到统计页面,比如说 5-10 分钟,这有关系吗?我不这么认为。因此,系统的这一部分可能不太可用(当然,不是 50%的可用性)。
★高可用性的解决方案是什么?
现在,我们需要知道如何提高系统的可用性。第一个简单的解决方案是您的系统不应该有单点故障。因此,如果系统中的某个组件出现故障,整个系统都会崩溃。
图:服务器的单点故障(图片由作者提供)
冗余是单点故障的解决方案。冗余是复制或倍增系统组件的行为。
现在让我们假设一个系统有一个服务器来处理客户端的请求。这是一个单点故障。
因此,我们需要添加更多的服务器来处理请求。但是我们需要一个负载*衡器来*衡服务器之间的负载。现在,如果负载*衡器失效,系统将不可用。
图:添加更多的服务器以实现冗余,但是负载*衡器现在是单点故障(图片由作者提供)
因此,我们需要多个负载*衡器来消除系统的单点故障。现在,如果其中一个服务器出现故障,其他服务器可以处理客户端请求。如果一个负载*衡器关闭,其他负载*衡器可以接收请求并将其发送到服务器。
图:负载*衡器和服务器消除单点故障的冗余(图片由作者提供)
结论:
可用性是分布式系统的一个关键属性。如果您想使系统可用,您需要消除系统中的任何单点故障。你可以通过使系统的这一部分冗余来做到这一点。此外,您需要在系统中有一个处理系统故障的流程。在系统出现故障的情况下,可能需要人工干预来恢复系统;然后,您需要在系统中建立流程,确保人们在一定时间内收到系统故障的通知。
可用的超参数优化技术
我们在分类模型集上应用三种不同的超参数优化技术来比较它们的准确性。
背景
我经常收到关于自动搜索超参数优化的文章。一旦我理解了这些技术的意图和范围,我就想知道通过这种优化一个模型可以改进多少。
本文的目的是调查不同的可用优化技术,并在一个简单的例子上测试它们,比较它们并查看所获得的改进的概述。
超参数是模型可调参数,必须对其进行调整以获得具有最佳性能的模型。然后,优化模型的超参数是提高所选算法性能的关键任务。
在某种程度上,我们需要知道每个超参数在每个算法中的含义及其可能的值。深入理解不同算法中每个超参数的含义是必要的,也是一项艰巨的任务,有时意味着了解算法内部的工作方式及其背后的数学原理。这篇文章的内容没有达到那个深度,虽然我们会在每一个里面选取一些超参数,用不同的算法来分析。
使用过任何算法的人可能已经对缺省值集进行了一些手动优化尝试。这种手动调整通常需要很长时间,并不总是严格地进行,并且很难将结果系统化
第二,我们可以应用可用的自动化和相当简单的技术,例如网格搜索和随机搜索,它们通常给出更好的结果,但是时间和机器计算的成本很高。我们将应用这两种技术来比较它们的结果
最后,我们将应用贝叶斯优化,这是一种找到函数最小值的方法,在测试的最佳算法上使用 Python 的 hyperopt 库。这种技术的实现可能不那么容易,但它可以在性能或时间上给我们比以前更好的结果。
数据集
我们将在练*中使用的数据集是 Kaggle 的泰坦尼克号乘客数据集,这是一个二元分类练*,用于预测哪些乘客幸存,哪些乘客没有。
import os
import numpy as np # linear algebra
import pandas as pd #
from datetime import datetime
from sklearn.model_selection import train_test_split
from sklearn.linear_model import SGDClassifier
from sklearn.linear_model import RidgeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.ensemble import BaggingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
import lightgbm as lgb
from sklearn.metrics import confusion_matrix
import scikitplot as skplt%matplotlib inlinenp.random.seed(7)
train = pd.read_csv('./data/train.csv', index_col=0)
y = train.Survived #.reset_index(drop=True)
features = train.drop(['Survived'], axis=1)
features.head()
选择的指标是准确性:正确预测的乘客百分比。
准确率= (TP+TN) /(合计)
特征工程和结果数据框架
我们将应用数据工程的基本技术,这将使我们能够无误地使用算法(记住,本文的目的不是获得好的结果,而只是比较应用优化技术时的性能)。
我们选择了八种算法来完成这项工作;这个决定是基于重用杰森·布朗利和 T2·威尔·科尔森的部分工作,他们开发了这里使用的大部分代码。
这些模型中的每一个都将是我们结果表中的不同列:
- 随机梯度推进
2.脊线分类器
3.k-最近邻(KNN)
4.支持向量机(SVM)
5.袋装决策树
6.随机森林
7.逻辑回归
8.LGBM
对于这些列中的每一列,我们将尝试应用以下优化技术:
- 默认超参数
- Sklearn GridSearchCV
- Sklearn 随机搜索 CV
- Python 的远视
features = features.drop(['Cabin'], axis=1)
features = features.drop(['Name'], axis=1)
objects = [col for col in features.columns if features[col].dtype == "object"]features.update(features[objects].fillna('None'))
numeric_dtypes = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
numerics = [col for col in features.columns if features[col].dtype in numeric_dtypes]
features.update(features[numerics].fillna(0))
features.info()
# dummies and split
X = pd.get_dummies(features)
X_train, X_valid, y_train, y_valid = train_test_split(X,y,train_size=0.70,test_size=0.30,random_state=0)#Results dataframe
cols = ['Case','SGD','Ridge','KNN','SVM','Bagging','RndForest','LogReg','LGB']resul = pd.DataFrame(columns=cols)
resul.set_index("Case",inplace=True)
resul.loc['Standard'] = [0,0,0,0,0,0,0,0]
resul.loc['GridSearch'] = [0,0,0,0,0,0,0,0]
resul.loc['RandomSearch'] = [0,0,0,0,0,0,0,0]
resul.loc['Hyperopt'] = [0,0,0,0,0,0,0,0]resul.head()
结果的空数据框架
第 1 行—每个算法的默认超参数
如上所述,我们的结果表的第一行是分析的起点,采用每个算法的超参数的默认值:
#Models creation
sgd = SGDClassifier()
ridge = RidgeClassifier()
knn = KNeighborsClassifier()
svc = SVC(gamma='auto')
bag = BaggingClassifier()
rf = RandomForestClassifier(n_estimators=10)
lr = LogisticRegression(solver='liblinear')
lgg = lgb.LGBMClassifier()models = [sgd,ridge,knn,svc,bag,rf,lr,lgg]col = 0
for model in models:
model.fit(X_train,y_train.values.ravel())
resul.iloc[0,col] = model.score(X_valid,y_valid)
col += 1resul.head()
第 2 行—应用 GridSearchCV
“网格搜索通过尝试您想要在模型中尝试的每个可能的参数组合来工作。这些参数中的每一个都在一系列交叉验证过程中被尝试。在过去的几年里,这种技术作为一种调整你的模型的方法已经流行起来了,“⁴.
现在,我们必须为每个算法定义一个包含不同参数及其值的字典
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import RepeatedStratifiedKFold#SGD
loss = ['hinge', 'modified_huber', 'log']
penalty = ['l1','l2']
alpha= [0.0001,0.001,0.01,0.1]
l1_ratio= [0.15,0.05,.025]
max_iter = [1,5,10,100,1000,10000]
sgd_grid = dict(loss=loss,penalty=penalty,max_iter=max_iter,alpha=alpha,l1_ratio=l1_ratio)#Ridge
alpha = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
ridge_grid = dict(alpha=alpha)#K-Nearest - Neighborg
n_neighbors = range(1, 21, 2)
weights = ['uniform', 'distance']
metric = ['euclidean', 'manhattan', 'minkowski']
knn_grid = dict(n_neighbors=n_neighbors,weights=weights,metric=metric)#Support Vector Classifier
kernel = ['poly', 'rbf', 'sigmoid']
C = [50, 10, 1.0, 0.1, 0.01]
gamma = ['scale']
svc_grid = dict(kernel=kernel,C=C,gamma=gamma)#Bagging Classifier
n_estimators = [10, 100, 1000]
bag_grid = dict(n_estimators=n_estimators)#Random Forest
n_estimators = [10, 100, 1000,10000]
max_features = ['sqrt', 'log2']
rf_grid = dict(n_estimators=n_estimators,max_features=max_features)#Logistic Regrresion
solvers = ['newton-cg', 'lbfgs', 'liblinear']
penalty = ['l2']
c_values = [100, 10, 1.0, 0.1, 0.01]
lr_grid = dict(solver=solvers,penalty=penalty,C=c_values)#LGB
class_weight = [None,'balanced']
boosting_type = ['gbdt', 'goss', 'dart']
num_leaves = [30,50,100,150] #list(range(30, 150)),
learning_rate = list(np.logspace(np.log(0.005), np.log(0.2), base = np.exp(1), num = 10)) #1000
lgg_grid = dict(class_weight=class_weight, boosting_type=boosting_type, num_leaves=num_leaves, learning_rate =learning_rate)
然后,对每个应用 GridSearchCV:
models = [sgd,ridge,knn,svc,bag,rf,lr,lgg]
grids = [sgd_grid,ridge_grid,knn_grid,svc_grid,bag_grid,rf_grid,lr_grid,lgg_grid]col = 0
for ind in range(0,len(models)):
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3,
random_state=1) grid_search = GridSearchCV(estimator=models[col],
param_grid=grids[col], n_jobs=-1, cv=cv,
scoring='accuracy',error_score=0) grid_clf_acc = grid_search.fit(X_train, y_train)
resul.iloc[1,col] = grid_clf_acc.score(X_valid,y_valid)
col += 1resul.head()
不同的算法有更多的参数,这里没有特意包括,您可以在每个超参数中强制搜索更多的值。
这个缩减是根据我们愿意投入的时间和计算能力来发展的。
第 3 行—应用 RandomSearchCV
“进入随机搜索。考虑尝试每一种可能的组合需要大量的蛮力计算。数据科学家是一群没有耐心的人,所以他们采用了一种更快的技术:从一系列参数中随机取样。这个想法是,你会比网格搜索更快地覆盖接近最优的参数集。然而,这种技术是幼稚的。它不知道也不记得以前运行过的任何东西。”⁴
出于实用目的,代码与 GridSearchCV 相同,只是修改了:
random_search = RandomizedSearchCV(models[col],
param_distributions=grids[col],n_iter=n_iter_search,
cv=cv)
代替
grid_search = GridSearchCV(estimator=lr, param_grid=lr_grid,
n_jobs=-1, cv=cv, scoring='accuracy',error_score=0)
完整的代码如下:
from scipy.stats import randint as sp_randint
from sklearn.model_selection import RandomizedSearchCVcol = 0
for ind in range(0,len(models)):
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3,
random_state=1)
n_iter_search = 3
random_search = RandomizedSearchCV(models[col],
param_distributions=grids[col],n_iter=n_iter_search, cv=cv) random_search.fit(X_train,y_train)
resul.iloc[2,col] = random_search.score(X_valid,y_valid)
col += 1resul.head()
分析结果
到目前为止,如果我们检查结果网格,我们发现自动搜索技术的应用已经给出了良好的结果。
在某些情况下,像 SGD 或 SVM 算法已经有了很大的改进,从 67–69%的下限提高到 78–76%。
总的趋势是提高 1、2 或 3 个百分点,GridSearchCV 比 RandomSearchCV 获得更好的结果,随机应用时间比网格应用时间好。
我们来分析一下他版本的 GridSearchCV 中的获胜算法(光照渐变提升):
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3,
random_state=1)
n_iter_search = 3
grid_search = GridSearchCV(estimator=lgg, param_grid=lgg_grid,
n_jobs=-1, cv=cv, scoring='accuracy',error_score=0)
grid_win = grid_search.fit(X_train, y_train)#Predict values based on new parameters
yv_pred = grid_win.predict(X_valid)print(confusion_matrix(y_valid, yv_pred))
skplt.metrics.plot_confusion_matrix(y_valid, yv_pred,figsize=(8,8))
要了解我们使用的算法版本中的超参数:
print("Best: %f using %s" % (grid_win.best_score_, grid_win.best_params_))
第 4 行——使用 hyperopt 库应用贝叶斯超优化
我必须承认,在我理解如何应用贝叶斯优化技术之前,我感到非常失落和困惑,几乎要放弃了。我可以参考的来自图书馆和其他文章的文档和例子都很模糊,或者太枯燥,或者非常过时。
所有这一切,直到我发现这个优秀的图图利亚 l⁵和它的代号 ⁶由威尔·科尔森所作,我建议你一步一步地回顾和尝试,因为它是清晰和详尽的。跟着他,我们要做的第一件事是定义我们的目标函数,它必须返回一个至少带有标签‘loss’和‘status’的字典。
import csv
from hyperopt import STATUS_OK
from timeit import default_timer as timerMAX_EVALS = 500
N_FOLDS = 10def objective(params, n_folds = N_FOLDS): """Objective function for Gradient Boosting Machine Hyperparameter Optimization""" # Keep track of evals
global ITERATION
ITERATION += 1 # Retrieve the subsample if present otherwise set to 1.0
subsample = params['boosting_type'].get('subsample', 1.0) # Extract the boosting type
params['boosting_type'] = params['boosting_type']
['boosting_type']
params['subsample'] = subsample # Make sure parameters that need to be integers are integers
for parameter_name in ['num_leaves', 'subsample_for_bin',
'min_child_samples']:
params[parameter_name] = int(params[parameter_name]) start = timer()
# Perform n_folds cross validation
cv_results = lgb.cv(params, train_set, num_boost_round = 10000,
nfold = n_folds, early_stopping_rounds = 100,
metrics = 'auc', seed = 50)
run_time = timer() - start # Extract the best score
best_score = np.max(cv_results['auc-mean']) # Loss must be minimized
loss = 1 - best_score # Boosting rounds that returned the highest cv score
n_estimators = int(np.argmax(cv_results['auc-mean']) + 1) # Write to the csv file ('a' means append)
of_connection = open(out_file, 'a')
writer = csv.writer(of_connection)
writer.writerow([loss, params, ITERATION, n_estimators,
run_time]) # Dictionary with information for evaluation
return {'loss': loss, 'params': params, 'iteration': ITERATION,
'estimators': n_estimators, 'train_time': run_time,
'status': STATUS_OK}
域空间:域空间表示我们想要为每个超参数评估的值的范围。每次搜索迭代,贝叶斯优化算法将从域空间中为每个超参数选择一个值。当我们进行随机或网格搜索时,域空间是一个网格。在贝叶斯优化中,想法是相同的,除了这个空间对于每个超参数具有概率分布而不是离散值。
space = {
'class_weight': hp.choice('class_weight', [None, 'balanced']),
'boosting_type': hp.choice('boosting_type', [
{'boosting_type': 'gbdt', 'subsample': hp.uniform('gdbt_subsample', 0.5, 1)},
{'boosting_type': 'dart', 'subsample': hp.uniform('dart_subsample', 0.5, 1)},
{'boosting_type': 'goss', 'subsample': 1.0}]),'num_leaves': hp.quniform('num_leaves', 30, 150, 1),
'learning_rate': hp.loguniform('learning_rate', np.log(0.01),
np.log(0.2)),
'subsample_for_bin': hp.quniform('subsample_for_bin', 20000,
300000),
'min_child_samples': hp.quniform('min_child_samples', 20, 500, 5),
'reg_alpha': hp.uniform('reg_alpha', 0.0, 1.0),
'reg_lambda': hp.uniform('reg_lambda', 0.0, 1.0),
'colsample_bytree': hp.uniform('colsample_by_tree', 0.6, 1.0)}
这里使用不同的域分发类型(在hyperopt 文档中寻找完整的分发列表):
choice
:分类变量quniform
:离散均匀(间隔均匀的整数)uniform
:连续均匀(浮动间隔均匀)loguniform
:连续的均匀圆木(在圆木刻度上均匀分布的浮子)
from hyperopt import tpe
from hyperopt import Trials# optimization algorithm
tpe_algorithm = tpe.suggest# Keep track of results
**bayes_trials = Trials()**# File to save first results
out_file = './gbm_trials.csv'
of_connection = open(out_file, 'w')
writer = csv.writer(of_connection)# Write the headers to the file
writer.writerow(['loss', 'params', 'iteration', 'estimators', 'train_time'])
of_connection.close()
最后,准备好所有代码后,我们通过 fmin 函数寻找参数的最佳组合:
from hyperopt import fmin# Global variable
global ITERATION
ITERATION = 0
MAX_EVALS = 100# Create a lgb dataset
train_set = lgb.Dataset(X_train, label = y_train)# Run optimization
best = fmin(fn = objective, space = space, algo = tpe.suggest,
max_evals = MAX_EVALS, trials = bayes_trials,
rstate =np.random.RandomState(50))
它触发了寻找最佳组合的过程。在最初的例子中,变量 MAX_EVALS 被设置为 500;由于本练*的性能问题,它被减少到 100,这可能会影响最终结果。
一旦流程结束,我们就可以获取 Trials 对象(在我们的例子中是 bayes_trials)并分析其结果:
# Sort the trials with lowest loss (highest AUC) first
bayes_trials_results = sorted(bayes_trials.results, key = lambda x: x['loss'])
bayes_trials_results[:2]
我们还可以从 CSV 加载数据帧,并使用“ast”库将文本转换为字典,并为我们的最终模型提供最佳结果。
results = pd.read_csv('./gbm_trials.csv')# Sort with best scores on top and reset index for slicing
results.sort_values('loss', ascending = True, inplace = True)
results.reset_index(inplace = True, drop = True)
results.head()
import ast# Convert from a string to a dictionary
ast.literal_eval(results.loc[0, 'params'])
# Extract the ideal number of estimators and hyperparameters
best_bayes_estimators = int(results.loc[0, 'estimators'])
best_bayes_params = ast.literal_eval(results.loc[0, 'params']).copy()# Re-create the best model and train on the training data
best_bayes_model = lgb.LGBMClassifier(n_estimators=best_bayes_estimators, n_jobs = -1,
objective = 'binary', random_state = 7,
**best_bayes_params)
best_bayes_model.fit(X_train, y_train)# Evaluate on the testing data
preds = best_bayes_model.predict(X_valid)
print(confusion_matrix(y_valid, preds))
print (best_bayes_model.score(X_valid,y_valid))
skplt.metrics.plot_confusion_matrix(y_valid, preds,figsize=(8,8))resul.iloc[3,7] = best_bayes_model.score(X_valid,y_valid)
resul.head()
远视在 LGB 模型中的应用
摘要
我们开发了完整的代码来应用三种可用的优化技术,八种不同的分类算法。应用这些技术所需的时间和计算能力是一个需要考虑的问题;当所选模型的技术水*足够高时,似乎有必要执行这种优化。
参数优化并不一定意味着训练模型的结果相对于测试数据的持续改进,因为参数的选择可能会产生过度拟合。
最后,应该指出的是,在不同模型上观察到的改进通常具有相当大的幅度,这至少为通过这些技术中的任何一种来提高算法性能的可能性留下了余地。
来源和参考
[1]https://en.wikipedia.org/w/index.php?title = Accuracy _ and _ precision&action =编辑& section=4
在二进制分类中,准确度也用作一种统计度量,用于衡量 二进制分类 测试正确识别或排除某个条件的程度。即准确率是真实结果(既有 真阳性 又有 真阴性 )占检查病例总数的比例……量化二进制准确率的公式为:
准确度= (TP+TN)/(TP+TN+FP+FN)
其中:TP =真阳性;FP =假阳性;TN =真阴性;FN =假阴性
[4]https://medium . com/apprentice-journal/hyper-parameter-optimization-c9b 78372447 b
法国的雪崩危险
使用 GeoPandas 和 Bokeh 库在 Python 中可视化地理空间数据
从布兰克湖看布兰克山,图片来源:卡米拉·哈马尔奇科瓦
对徒步旅行者和登山运动员来说,法国哪些山脉最危险?这是我的主要问题,因为我最近搬到了格勒诺布尔,那里基本上是法国徒步旅行的天堂。
不幸的是,我只从ANENA(法国雪和雪崩研究组织)按公社(法国的小行政单位)划分的报道中找到了关于每年雪崩事故的地区性数据。这是除了按山脉分组的山区事故之外第二好的事情,因为我找不到,所以在扑克或俄罗斯方块中,我玩了我拿到的那手牌,并搜索了法国公社的【shape file】(幸运的是,法国政府的官方消息来源没有让我失望)。这只是我的可视化“拼图”的两块,我需要在 Jupyter 笔记本上开始编码,以创建过去 10 年法国雪崩事故的互动地图。****
不说话,只管码
Jupyter 笔记本中所有带源码数据和代码的文件都可以在我在法国的 GitHub repo 雪崩危险中找到。
1)安装
假设您已经安装了像 Pandas 和 Numpy 这样的标准 Python 库,为了处理地理空间数据和 shapefiles,我需要添加 GeoPandas 和 Bokeh。
在我的例子中(带有 Anaconda 的 Windows ),我的命令行的神奇单词是; conda install geopandas 和 conda install bokeh,如 GeoPandas 和 Bokeh 库文档中所述。
最终可视化预览,用彩色描绘了法国过去 10 年中发生 1 - 30 次雪崩的公社,用灰色描绘了没有雪崩的公社
2)熟悉 Geopandas 数据框架
之前,我用了两次术语 shapefile 而没有进一步解释,这有点刻薄,我不想成为刻薄的女孩,所以…
Shapefile 格式是指点、线或多边形形式的地理空间数据,通常用于 GIS(地理信息系统)。shapefile 的扩展名是。shp,但是为了显示数据,你实际上需要一个文件夹中的 3 个文件。shp,。shx 和。dbf** 。**
如果 polygon 听起来更像是 Jean-Luc Piccard 在修理他的企业时必须飞行的宇宙飞船的名字,你会从下面的例子中有更好的想法。这是法国阿斯奈尔斯-苏尔-瓦兹公社的多边形(在几次随机试验后,我能找到的最接近宇宙飞船的多边形)。
用 iloc()方法显示某个多边形
在这里,我们可以看到,使用 iloc 方法,地理数据框中的多边形或地理空间数据通常可以以与传统 Pandas 数据框中的行相同的方式显示。对于多边形的图像,我们需要寻找具有活动的 几何图形的列, 数据以 GPS 坐标的形式存储在哪里。(具有活动几何图形的柱最有可能被命名为几何图形。)**
带坐标系(几何)的列将 GeoPandas 中的地理数据框与 Pandas 中的其他数据框区分开来。
读取和查看地理数据框与简单的数据框非常相似(除了已经提到的需要。shp,。shx 和。一个文件夹中的 dbf 文件,以便加载 shapefile)😗*
Jupyter 笔记本中带有活动几何图形的地理数据框架
我的两个可视化拼图(shape file with all communities and avalanche incidents report)都需要有一个连接列。就是公社( gdf 地理数据框架中的 NOM_COM 和雪崩数据框架中的公社)。
不幸的是,地理数据框架和数据框架中的社区名称是使用不同的大写/小写字母、特殊法语字符(é、à、等)编写的。)有时甚至混合使用连字符和空格。
3)法语的数据清洗和陷阱
因此,我用 str.lower( ) 方法将所有的公社名称改为小写,并替换特殊的法语字符,以避免相同公社名称的两个版本。
理想情况下,avalanche 数据框架中的所有社区名称也应包含在 gdf 地理数据框架中,但由于以下几个原因,情况并非如此:
- 雪崩报告中的社区名称是由人插入的,因此包括一些拼写错误,有时记录中提到的不是滑雪站的社区名称
- 随着时间的推移,一些公社合并成不同的公社或改变了名称,因此一些公社的名称今天已经过时
- 不同地区的公社很少有名字完全相同的
- shapefile 中的多边形不是从公社派生出来的,而是从更小的单元派生出来的,这些单元在大多数情况下与公社相同,但不是所有的都是如此
我通过简单更改 gdf 地理数据框架或雪崩数据框架的名称解决了前三个问题。这很费时间,但是因为它只对我的情况非常具体,并且与地理空间数据没有特别的联系,所以我不会在这里详细讨论它(无论如何,更多的细节可以在我的 GitHub repo 中找到)。
多边形的最后一个问题并不总是来源于你需要的形状,这也是你在处理地理空间数据时可能遇到的问题。这里我们可以看到夏蒙尼勃朗峰社区由 4 个不同的多边形组成。
在这里,夏蒙尼勃朗峰公社由四个不同的多边形组成,我们可以在几何栏的四个不同条目中看到。
它可以通过使用溶解函数来解决,该函数基于所选的列创建新的多边形(例如:dissolve(by="column_x "))。社区边界被定义为仅保留我们想要保留的列的地理数据框架。创建缓冲区以避免新多边形相交。
徒步旅行者在法国格勒诺布尔附近的山脉没有探测到雪崩的危险。资料来源:Kamila Hamalcikova
4)创建最终的地理数据框架,以便在散景中进一步使用
现在,我终于有了源自公社的完美多边形。但是我也需要每个公社雪崩事故的总数。简单的 groupby()函数和创建新的数据帧就可以达到这个目的:
当然,丑陋的列名 0 需要一点修饰。
最后,我可以将 gdf 地理数据框架中的数据与 aval_final 数据框架中的累积雪崩报告合并。
NaN 值是指在过去 10 年中没有发生雪崩的社区。稍后,当使用散景时,我们需要将此地理数据框架转换为 GeoJSON 格式。这将触发错误,因为 NaN 值不被识别为 JSON 对象。因此,我将用 fillna()函数*将所有 NaN 替换为字符串“No avalanche ”,并验证之后地理数据帧中没有出现 NaN。*
如果你坚持这么长时间阅读这篇文章,我认为在攻击在散景图书馆创建可视化的最后一步之前,你应该得到一张更酷的法国阿尔卑斯山的照片。
右侧为勃朗峰的麂皮,来源:卡米拉·哈马尔契科娃
Bokeh 雪崩事故互动地图
Bokeh 库使用 GeoJSON 格式进行数据可视化,因此我需要将最终的地理数据框架转换为 GeoJSON 格式。
与大多数 Python 库不同,散景库中的元素需要单独成组导入。在下面的代码中,我导入了我将使用的所有元素,但是还有更多选项。
接下来,我将选择颜色设置。在散景文档中有大量的调色板。在 color_mapper 中,选择 vis 值的最小值和最大值以及所选调色板外的颜色(nan_color) 来表示 nan 值,或者更准确地说是 GeoJSON 中的字符串“No avalanche”。
我还使用了 major_label_overrides 来突出显示只有至少发生过一次雪崩事故的公社 才会出现在调色板中。如果不使用此功能,所有 0 到 4 次雪崩的社区将会以相同的颜色结束在一个组中,这在视觉上是非常不清楚和混乱的。
为了最终的可视化,我们需要创建图形对象。
方法 patches() 用于绘制图形中公社的形状。除了定义 x 和 y 坐标,我们还需要指定 fill_color 。我们的颜色必须在每个多边形上改变,因此我使用带有关键字字段和变换的字典。字段值是我们想要绘制的变量,转换值是该变量的颜色组。
在 hovertool 的工具提示中,我们选择了在地图上移动光标时显示给用户的数据(在我的例子中是社区名称和雪崩事故总数,所以列社区和雪崩事故计数)。
如果您仍然发现上面的代码中有不清楚的地方,我建议检查具有非常相似的可视化的散景库。
最后,我将最终的可视化保存为单独的 html 文件,但是如果你想在 Jupyter 笔记本中直接显示图形,你可以使用 save()函数 show()。只是别忘了从 bokeh.io 导入之前的功能。
任何人都可能会猜测,大多数雪崩事故发生在法国的阿尔卑斯山,在勃朗峰和比利牛斯山脉附近,靠近西班牙边境。对我来说,很惊讶地发现雪崩也出现在阿尔萨斯地区或中央高原,甚至在科西嘉岛也有一例发生。
用户指出夏蒙尼勃朗峰公社是过去 10 年里雪崩事故发生最多的地方。ANENA 组织报告了从 2010/11 年冬季到 2019/20 年冬季的 30 起病例。
有这么多多边形的地图可视化的一个缺点是缩放非常慢,并且需要 GitHub 上的额外存储,以防你想把它发布在那里。另一方面,地图非常详细和精确。
参考文献:
- ANENA:全国雪崩和雪崩研究协会,事故报告* (2020),Anena.org*
- *Data.gouv.fr (2020),【Data.gouv.org *
- 南 PATEL,使用 Python 制作交互式地理地图的完整指南* (2019),TowardsDataScience.com*
- 地球实验室,第六课。如何使用 Geopandas 融合多边形:python 空间数据开源 Python 工作坊中的 GIS(2019)EarthDataScience.org
- 地理信息系统,在 geopandas* (2018),gis.stackexchange.com中,溶解原因“不能从空值创建有形状的几何图形”*
- Stackoverflow,在 geopandas* (2020) ,Stackoverflow.com*
用最后的气宗化身实现 Python 中的数据可视化
学*使用 Plotly、Seaborn 和 Matplotlib 库制作令人惊叹的可视化效果。
《最后的气宗》是那种你迫不及待想知道下一集会发生什么的剧集。它有一个伟大的故事情节,强大的人物和一些好的战斗。看了第二遍《阿凡达》后,我决定寻找比我们大多数人年轻时看的更多的关于这部电视剧的东西。为此,我将使用 Plotly、Seaborn 和 Matplotlib 来用很酷的图表支持我们的分析。
注意:你可以在 Kaggle 上找到我用于此分析的头像数据集(或者从我的Github下载,我也将此分析的完整代码留在那里)
人物
阿凡达团队的成员(安昂、卡塔拉、索卡、托弗和祖寇)在所有角色中拥有最多的台词。然而,前 10 名中的一些角色可能会让你大吃一惊。例如,指挥官赵只在第一部(水)中出现,但他在那一季中有很多屏幕时间,这反映在他进入前 10 的大量台词中。
另一个没有出现在所有剧集中的角色是杰特,他只在第一部和第二部(地球)中出现过。此外,它引起了我对第三部(火)中 Iroh 叔叔的几句台词的注意。我记得他被抓了,只在几个场景里出现过,所以说得通。
作者图片
像上面这样的交互式可视化很容易用 Plotly 实现。一旦数据准备就绪,您只需要几行代码:
谁跟谁说话?
我们已经知道在 61 集阿凡达中谁说的话最多。然而,前 10 个角色之间有很多对话,所以我很好奇他们之间的互动频率。我们可以通过使用 Seaborn 库中的热图来发现角色之间的交互细节。
行与列对话。每个方块的颜色代表每行中的字符对每列中的字符说的行数。较亮的方块意味着说出了更多的台词——图片由作者提供
热图揭示了人物之间的一些关系。自然有很多团队头像成员之间的对话。然而,也有许多团队成员之间的对话头像和休息,例如,索卡-淑熙和艾罗-祖寇。最后,我不禁注意到前 10 个角色之间从未在屏幕上发生过的一些对话。意料之中的是赵从来没有和像阿祖拉这样后来在节目中介绍的角色说过话,但是当我发现 Jet 在节目中从来没有面对过阿祖拉或者的时候,我有点惊讶。
他们在说什么?
有很多方法可以窥*顶级人物在说什么。在这种情况下,我将使用其中的两个:情感分析和词云。
情感分析
我们可以使用自然语言处理技术(VADER 情感分析)来量化角色所说的每一行的情感。有了这个工具,获得情感分数非常简单。关于处理情感分析数据的细节在我的 GitHub 上。一旦我们获得分数,我们就可以使用 Matplolib 用柱状图展示它。
作者图片
上面的图表揭示了按照积极程度排序的前 10 位人物。显然,艾罗和安昂是剧中最积极的角色。一个是开茶叶店的快乐大叔,另一个是当事情出错时喜欢跳舞的和*主义僧侣,所以结果是合理的,对吗?
另一方面,赵是该剧中迄今为止最消极的角色。事实上,我期待阿祖拉在这个位置上,但它仍然有意义。还有,祖寇的前两个赛季足以让他们被认为是一个消极的家伙,数据也证明了这一点。
词汇云
让我们来看看水、土、火这三本书里所有角色说的话。我去掉了角色名以获得更有意义的单词。
水、土、火……—作者图片
为了创建这个单词云,我同时使用了stylecloud
和wordcloud
。第一个给出了时尚的文字云,包括惊人的颜色和图标,而第二个你可以使用自己的图片,就像我在右边使用的“火国符号”。这是我用styleloud
做文字云的代码。其余的可以在 GitHub 上找到。
额外收获:我的卷心菜!
记得白菜商的大车被砸的时候笑了很多次。我发现这个短语他在 61 集里重复了 5 次。他第一次说这句话是在第一集奥玛舒王(第一集),而最后一次是在第二集大蛇的通行证
IMDb 评分与口语
我们可以用散点图找到两个变量之间的关系,并使之与 Plotly 交互。
有趣的是,口语数量最少的剧集(索金的短号第 3 和第 4 部分)获得了最高的 IMDb 评分,而口语数量最多的剧集之一(大分裂)获得了最低的 IMDb 评分。似乎粉丝们更喜欢有更多动作和精彩打斗的剧集,而不是冗长的对话。
作者图片
这是我用 Plotly 做上面散点图用的代码:
结论
在这篇文章中,我们发现了一些关于《最后的气宗阿凡达》的*解,这些*解可能是你和我从未想过的。我们已经知道谁用柱状图说话最多,谁用热图和谁说话,以及这些角色通过情感分析和文字云在说什么。
最重要的是,我们发现我们可以从学*数据科学工具中获得乐趣。请随意在 Github 上查看该分析背后的代码。
可解释性很重要——这就是证据
通过可解释性避免算法厌恶
科尔·凯斯特在 Unsplash 上的照片
想象一下,你正在申请研究生院,而你梦想中的大学的招生委员会决定今年的录取决定将由机器学*(ML)算法而不是人类评审员做出。你会对 ML 算法评估你并做出决定感到舒服吗?我们中的一些人可能不希望这样。但是为什么呢?
研究表明,基于证据的算法(ML 算法)比人类预测者更准确地预测未来。在一系列应用中,算法预测被认为优于人类预测,无论是股市预测还是游戏预测(在 AlphaGo 中)。录取决定也可以被视为一项预测任务,因为它们只不过是对候选人是否适合某个特定项目的预测,或者对候选人将有多成功的预测。然而,为什么我们中的一些人想要一个人来评价我们呢?
如果算法是比人类更好的预测者,那么人们应该选择算法预测而不是人类预测。然而,他们往往不会。这种现象,我们称之为算法厌恶,是有代价的,了解其原因很重要(Dietvorst,Simmons,and Massey,2014)。
我们对人们何时以及为何表现出算法厌恶知之甚少。关于人们何时使用人类预测者而不是高级算法,或者为什么人们不能使用算法进行预测,没有一致同意的机制。由于我们每天产生的数据量现在已经达到了几乎所有预测任务都需要某种算法参与的程度,因此解决算法厌恶问题非常重要,这样我们大多数人就可以依靠性能更好的算法来预测我们的未来。
Dietvorst、Simmons 和 Massey ( 2014 和 2016 )进行了几项研究,寻找算法厌恶的原因。他们发现:
- 在看到算法预测者犯同样的错误后,人们往往会比人类预测者更快地对算法预测者失去信心。
- 如果人们可以(甚至轻微地)修改结果,他们就会使用不完美的算法。因此,给予控制权是克服算法厌恶的一种方式。
然而,我们知道在许多情况下提供控制是不可能的。因此,我们需要寻找其他方法来克服或避免算法厌恶。
什么是黑盒算法?(来源)
现代预测算法大多被大多数人视为黑盒,因为它涉及复杂的机器学*模型,很少有人理解。除此之外,算法的复杂性和性能与其可解释性成反比。例如,线性回归模型可能很容易解释,但性能可能很差。另一方面,神经网络可以有很好的性能,但同时也很难解释。那么,解释模型的预测或者理解模型学到了什么,有助于克服算法厌恶吗?让我们来了解一下!
我进行了一项在线实验,将模型可解释性和算法厌恶这两个领域结合起来,以回答算法厌恶的可能机制这一更广泛的问题。特别是,我想探索这个问题:模型可解释性在算法厌恶中扮演什么角色,解释能帮助克服对算法的厌恶吗?我通过观察如果有解释,人们是否会比人类预测者(他们自己)更频繁地选择相同的算法(或给予更高的评价),来操作这个问题。
资料组
在开始我的实验之前,我需要选择一个机器学*算法,作为我的预测器/预测器。为了训练任何机器学*算法,我们需要数据,在我们的情况下,需要标记数据。为此,我使用了一个来自 Kaggle 的开放数据集,它类似于上面讨论的招生场景。
为了确保参与者不会被数字淹没,我特别强调在数据集选择过程中将特征/预测器的数量保持在 10 个以下。研究生招生数据集为每个学生档案提供了一个从 0 到 1 的“录取机会”衡量标准,以及以下 7 个参数:
- GRE 成绩(满分 340 分)
- 托福成绩(满分 120 分)
- 申请人完成本科学业的大学评级(满分 5 分)。1 是最低等级,5 是最高等级。
- 目标陈述优势(满分 5 分):1 分最低,5 分最高。
- 推荐信强度(满分 5 分):1 分最低,5 分最高。
- 本科 GPA(满分 10 分)
- 研究经验(0 或 1 ) : 0 表示以前没有研究经验,1 表示至少有一些研究经验。
我将“录取机会”指标乘以 100,转换为“录取分数”,以便参与者更容易处理,即他们可以输入整数作为预测值。“录取分数”可以被认为是对学生成功与否或个人实力的预测。分数范围从 0 到 100,分数越高表明录取/个人资料优势的机会越大。数据集总共有 500 个条目。数据集是干净的,不需要任何其他主要的数据预处理或数据争论步骤。
模型和解释者
我在数据集上训练了几个模型,XGBoost 是表现最好的模型之一。我决定坚持使用 XGBoost 作为研究生入学预测器,因为即使使用最小的参数调整和预处理,我也获得了足够好的结果。准备好机器学*模型后,我必须选择一个库来为算法的预测生成解释。令人欣慰的是,机器学*社区已经接受了模型可解释性的问题,并开发了几种新的方法来解释机器学*模型。
一个这样的解释者是 SHAP (沙普利附加解释),一种解释任何机器学*模型输出的博弈论方法。SHAP 可以为单个行提供解释,说明每个要素都有助于将模型输出推离基准值。使用 SHAP 库也可以生成指示总体模型解释的摘要图和贡献依赖图。以下资源对使用 SHAP 理解模型可解释性非常有帮助,我推荐你去看看:
[## 学*机器学*可解释教程
从任何机器学*模型中提取人类可以理解的*解。
www.kaggle.com](https://www.kaggle.com/learn/machine-learning-explainability) [## 一种特征归属方法(假定)可以统治所有这些特征:Shapley 值
在 NIPS 上引起我注意的论文中,有一篇文章声称已经发现了一个框架…
towardsdatascience.com](/one-feature-attribution-method-to-supposedly-rule-them-all-shapley-values-f3e04534983d)
试验设计
该实验是一个简单的随机控制实验,旨在检查添加解释是否对人们做出的选择或他们如何感知/评价该算法有任何影响。它建立在 Qualtrics 调查*台上,参与者通过朋友和关系在亚马逊 MTurk 和众包*台之外招募。参加者总数为 445 人,其中 350 人来自土耳其电信公司,其余 95 人来自不同来源。参与者的*均年龄为 30.76 岁,其中约 43%为女性,57%为男性。
调查 (请看一看以更好地了解流程)从询问参与者的年龄、性别以及对概率、计算机科学和机器学*的熟悉程度(1-4)开始。这是为了在实验完成后探索治疗效果的异质性。然后,所有参与者都熟悉一所加拿大大学在其招生委员会中利用机器学*算法的想象场景。接下来,参与者会看到 10 名申请者的特征值,并被要求预测他们的录取分数。在参与者给每个申请人打分后,如果参与者属于对照组,参与者的预测会显示在算法预测的旁边。然而,对于治疗组,除了参与者和算法的预测之外,还显示了对影响模型的特征的解释。
向参与者提出问题(左侧),并给出申请人概况特征的值。控制组(右上):预测分数后,控制组中的参与者会看到他/她的预测以及实际分数和算法的预测分数。向治疗组(右下)参与者展示对申请人的算法预测分数的解释,以及对照组所看到的一切。
此外,处理组中的参与者具有解释在 10 个问题之前显示的 Shapley 值的页面,以及具有特征重要性和贡献依赖图的页面,即,在 10 个问题之后显示的整体模型解释。
对照组(无解释)和治疗组(有解释)分别有 227 和 218 名参与者,他们在调查开始时被随机分组。一旦这些问题完成,参与者会被问一系列关于他们所看到的后续问题。本节特别关注三个问题:
- 你今年申请了同一个理学硕士/工商管理硕士项目,招生委员会正在试验你在前面 10 个问题中看到的算法。你支持哪种复*方法?
- 现在想象一下,你被任命为 MBA 项目的招生委员会主任。你会用算法代表你做决定吗?请注意,你必须应对大量的申请人和有限的劳动力,但你也要对自己做出的决定负责!
- 你认为机器学*算法做得有多好?在 0-100 的范围内给算法打分。
调查结束时向所有参与者提出的问题
这些问题代表了算法的结果(I)对参与者有直接影响,(ii)参与者对算法的结果负责,以及(iii)分别与它们没有任何联系的一般评级。
结果
对于实验设计部分提到的三个后续问题,观察到以下结果:
1.当申请入院时,即当算法的预测对他们产生影响时,在没有解释的对照组中,参与者选择 ML 算法的百分比为 48.13%,在有解释的治疗组中,为 49.78%。
2.当出席招生委员会时,即当算法减轻了他们的工作但让他们负责时,在没有解释的对照组中,参与者选择 ML 算法的百分比为 47.95%,在有解释的治疗组中,为 49.50%。
3.当被要求对该算法进行总体评分时,对照组的参与者*均给它打了 70.81 分(满分为 100 分),而治疗组的参与者*均给了 71.07 分。两组的 Cohen d 值为 0.016。
从上面的结果,我们可以看到两组之间有一个非常明显的差异。在问题 1 和 2 中,当算法与 SHAP 解释一起出现时,更高比例的参与者选择使用该算法。还有,在问题 3 中, Cohen 的 d 值 0.016 说明均值之间的差异是正的,有利于具有可解释性的群体,但效果大小很小。总的来说,更大的样本量会使结论和效果更清晰。
治疗效果的异质性:与任何其他实验一样,我从三个方面探索了参与者之间治疗效果的异质性:年龄、性别以及对概率、计算机科学和机器学*的熟悉程度。所有年龄组的治疗效果都一样。性别在决定算法分数时也没有发挥作用。
当我们看算法得分或参与者对算法的感知方式时,总体差异并不大。然而,当我们根据他们对概率、计算机科学和机器学*的熟悉程度来看分组时,结果如下。
一个重要的观察结果是,与没有解释的对照组相比,没有技术背景(即从未听说过概率、计算机科学和机器学*)的参与者给出的算法分数在有解释的治疗组中总是更高。Cohen 的 d 值在这个小组中也显著增加,这表明与呈现给他们的纯粹数字相比,人们如何评价带有解释的算法有很大的积极影响。
通过这个实验,我试图找到算法厌恶可以通过可解释性来克服的经验证据。它适用于参与者受到算法预测影响的情况,也适用于参与者对算法准确性负责的情况。在进一步的实验中,治疗效果的异质性应该是主要关注点。我们可以特别关注非 STEM(科学、技术、工程和数学)参与者,提出额外的问题来了解他们选择这种方式的原因。如果我们可以在一个更大的数据集上证明这个实验的外部有效性,像 SHAP 这样的简单方法可以被纳入我们日常的机器学*预测器中,以帮助人们避免算法厌恶!
结论
世界正在走向“可解释的人工智能”,许多人认为这是深度学*算法的必要条件。这个实验仅仅证明了这些步骤对于建立对算法的信任是必要的。
尽管算法厌恶不是一个大问题,但就目前而言,这是一个我们需要严肃对待的问题。虽然我们可能认为今天的预测任务只是一个简单的研究生入学问题或房价估算任务;这将是明天自动驾驶汽车上预测你前面卡车速度的任务。无论是医疗保健还是太空探索,在人类生命受到威胁的情况下,算法不可避免地要接管这些任务。无论在什么情况下,我们都需要找到一种方法来建立对这些算法的信任。因此,看到机器学*社区通过在我们的创新道路上像对待复杂性一样认真对待可解释性来解决这个问题,这是非常令人鼓舞的。
参考
[1] Dietvorst,Berkeley 和 Simmons,Joseph P .和 Massey,Cade,算法厌恶:人们在看到算法出错后错误地避免算法(2014 年 7 月 6 日)。即将在《实验心理学杂志:总论》上发表。在 http://dx.doi.org/10.2139/ssrn.2466040 的 SSRN 有售:
[2] Dietvorst,Berkeley 和 Simmons,Joseph P .和 Massey,Cade,克服算法厌恶:人们会使用不完美的算法,如果他们能够(即使是轻微地)修改它们(2016 年 4 月 5 日)。可在 http://dx.doi.org/10.2139/ssrn.2616787SSRN买到
[3] Lundberg,S.M .,Erion,g .,Chen,h .等从局部解释到全球理解用可解释的人工智能对树木进行研究。自然机器智能 2,56–67(2020)。https://doi.org/10.1038/s42256-019-0138-9。
请随时在帖子上发表您的反馈和建议,或者通过 LinkedIn 与我联系。
避免这些 Python 新手的错误
他们可能会工作,但他们可以工作得更好。
(python 徽标由 http://python.org/提供)
随着大量的实践,编程将逐渐变得容易,但底线是
编程很难。
假设和自己解决问题的不幸组合会使事情变得更加困难。尤其是在没有导师的情况下,甚至很难知道你做事的方式是否是错的。我们当然都为以后进入代码和重构而感到内疚,因为我们都在不断学*如何以更好的方式做事。幸运的是,如果有足够的意识,纠正这些错误可以让你成为一个更好的程序员。
成为伟大程序员的最好方法是克服错误和问题。做事情总有更好的方法,找到更好的方法才是有挑战性的。*惯做这样或那样的事情很容易,但有时需要一点改变,才能真正成为一名伟大的工程师。
未实施
虽然“未实现”错误可能是这个列表中最不常*的错误之一,但我认为发布一个提醒是很重要的。在 Python 中引发 NotImplemented 不会引发 NotImplemented 错误,但会引发类型错误。我写了一个函数来说明这一点:
def implementtest(num):
if num == 5:
raise(NotImplemented)
每当我们试图运行“num”等于 5 的函数时,看看会发生什么:
引发正确异常的解决方案是引发 NotImplementedError,而不是引发 NotImplemented。为此,我修改了我们的函数:
def implementtest(num):
if num == 5:
raise(NotImplemented)
if num == 10:
raise(NotImplementedError('This is the right way!'))
运行这个会给我们正确的输出:
可变默认值
(这是我犯的错)
Python 中的默认参数被求值一次,,求值发生在执行函数定义的时。假设这些参数只计算一次,那么每个 inbound 元素都会在每个调用中使用,这意味着每次在函数中访问变量时,变量中包含的数据都是可变的。
**def** **add**(item, items**=**[]):
items**.**append(item)
我们应该做的是将参数的值设置为 nothing,并添加一个条件来修改列表,如果它不存在的话
**def** **add**(item, items**=**None):
**if** items **is** None:
items **=** []
items**.**append(item)
尽管这主要适用于 Python 用户的统计/DS/ML 方面,但根据具体情况,拥有不可变的数据是普遍重要的。
全局变量
在面向对象的编程语言中,全局变量应该保持在最低限度。然而,我认为,通过解释全局变量当然是必要的,并且在某些情况下很好,给这种说法加上副标题是很重要的。这方面的一个很好的例子是数据科学,这是实际上正在进行的有限数量的面向对象编程,Python 的功能性比通常情况下更强。
当多个函数调用并依赖同一个值时,全局变量会导致命名和隐私问题。我认为全局变量的一个很好的例子是类似于文件路径的东西,特别是要和 Python 文件打包在一起的。即使在编写 Gtk 类和移动图形用户界面构建器时,也应该私下进行,而不是全局进行。
收到。
使用 copy 在客观上可以比使用 normal 赋值更好。正常的赋值操作只是将新变量指向现有对象,而不是创建一个新对象。
d = 5
h = d
使用 Python 的复制模块可以执行两种主要类型的复制,
浅层复制和深层复制。
这两种类型的副本之间的区别在于您希望通过函数传递的变量的类型。当对包含在单字节数据中的变量(如整数、浮点、布尔或字符串)使用深度复制时,浅复制和深复制之间的差异是感觉不到的。然而,当处理列表、元组和字典时,我建议总是进行深度复制。
浅层拷贝构造一个新的复合对象,然后(尽可能地)向其中插入对原始对象的引用。深度拷贝构造一个新的复合对象,然后递归地将原始对象的拷贝插入其中。有了这些定义,就很容易理解为什么要对给定的数据类型使用其中的一种。
import copy
l = [10,15,20]
h = 5
hcopy = copy.copy(h)
z = copy.deepcopy(l)
为了测试我们的结果,我们可以简单地检查它们的变量 id 是否与条件语句相同:
print id(h) == id(hcopy)
False
最后
成为一名伟大的程序员需要不断提高,希望随着时间的推移,一些错误的观念能够被消除。这是一个渐进而痛苦的过程,但是通过大量的练*和更多的信息,遵循这样简单的指导和建议肯定会有所收获。像这样分享“不要做的事情”通常会成为很好的话题,让每个人都成为伟大的程序员,所以我认为讨论这个肯定是有益的,不管你在你的无尽的编程之旅中走了多远。
如果你想快速学*编程,避免这个错误
意*
你通过做项目学得很快,但不是这种方式
安东尼·托里在 Unsplash 上的照片
一位程序员创建了一个 Slack 频道,并邀请感兴趣的人加入。精通 Python 的程序员为那些想学*编程的人创造了通过做项目来学*的渠道。
频道主上传任务到频道,会员在上面一试身手;然后一起头脑风暴。
我也加入了频道,但我总是迷路。通过评论,我发现频道上的许多人对编程都有一定程度的精通。我对 Python 的熟练程度为零。我知道这个频道不会像我希望的那样快速提高我的知识。我退出了频道。
频道所有者的目标是好的。但是作为一个初学者,我能感觉到这种学*方法对初学者来说并不好。
以下是我认为初学者应该警惕这个陷阱的原因。
为什么不应该跳过项目的基础
编程需要你了解基础知识。这就是让你精通一门语言的原因。你会很好地掌握你正在学*的语言。
如果你有一门语言的基础知识,并且用它来构建项目,那就太好了。太完美了。这意味着你正在运用你所获得的知识。
我看过几次类似“在这个 5 小时的视频里用 Node.js 搭建一个 Twitter app”的文章。这些类型的文章对于那些已经了解 Node.js 的人来说非常好,初学者不应该学*如何用这样的文章编码。
首先,大多数时候你会发现自己迷失了。你将很难理解如何从 A 点到达 b 点。如果这是你将面临的唯一问题,那就更好了。还有一个问题。这可能会永远阻碍你学*如何编码。以这种方式学*编码会让你对编程失去兴趣,并怀疑自己的学*能力。
第二,你浪费了很多时间。因为你没有项目语言的基础知识,这意味着你要做大量的研究和询问。有人可以向你解释 A 点是如何通向 B 点的,想想在你能够理解它之前要花多少时间。
第三,你只精通你做的项目,而不精通这门语言。你只擅长你做的项目。你不会成为语言大师。作为一名成功的程序员,你需要解决问题。有些问题不会是你已经知道如何解决的。它们是一种新的球类运动,你需要把它放在你的最佳比赛中。
我正在浏览一个社交媒体*台上的帖子,一名开发人员在他的页面上写道,他从事的大多数项目都不是他所知道的。他必须研究和研究项目。
一个没有良好语言基础知识的程序员会有什么样的命运?
第四,你不会成为一门语言的专家。专业化是在编程领域取得成功的关键。如果作为一个初学者,你*惯于通过“在 4 小时内完成这个”的视频来学*,你会一直想要尝试用不同的语言来完成不同的项目,这样的视频会让你大吃一惊。长此以往,这让你成为了一个没有语言的高手。
外卖
根据经验,要学会快速编码并成为一名成功的程序员,掌握一门语言的基础知识是关键。有了这些基础知识,在此基础上培养你的技能就变得容易了。当你面临一个问题时,你会知道如何寻找解决问题的方法。
像“在这个 3 小时的视频中如此构建”这样的文章并不是学*如何编码的最好方法——对于初学者来说。这是浪费时间和分心。
不要跳过语言的基础,直接通过构建项目来学*。当你熟悉了基础知识,就开始根据你选择的职业道路来构建项目。如果你现在跟随一个视频或一篇文章,教你如何基于你正在学*或已经学*的东西来构建一个项目,这没有什么不好。
感谢您的阅读。
对于长时间运行的 API 请求,避免在 AWS Lambda 上冷启动
布拉登·科拉姆在 Unsplash 拍摄的照片
如果你和我一样,你会认为无服务器很棒。可忽略不计的运行成本,无需占用您时间的服务器配置,默认自动扩展等。等等。当然,根据“没有免费的午餐”的说法,这种便利和成本节约是有代价的,虽然无服务器有许多实际成本(内存限制、包大小、运行时间限制、开发人员学*曲线),但本文将假设您已经解决了这些问题(或者不关心它们),而是专注于特定的性能成本—冷启动。
冷启动为什么会伤害数据科学应用?
冷启动很慢。这就是问题所在,到底有多慢取决于各种因素,比如你的运行时(python 实际上是启动更快的 lambda 容器之一),以及你在 Lambda 的设置阶段做了什么(源)。
作为数据科学家和开发人员,我们*惯了缓慢的节奏。开始下载 200 GBs 的文本数据(放上水壶),加载模型(可怜的茶),运行聚类算法(去散步)……听起来熟悉吗?虽然这种缓慢的速度对于实验(以及运行在持久服务器上的生产系统)来说是好的,但是对于无服务器模式来说却是致命的。AWS Lambda 只允许在函数超时和容器死亡之前最多运行 15 分钟,将所有未持久化的工作(和运行的计算)限制在死亡容器的墓地中,永远不会重新启动。
当您的 lambda 函数实际上是一个 API 端点,客户端可以临时调用它来触发一些实时数据科学/分析过程(在我们的示例中,NLP 基于任意长度的单个短语)时,这个问题就变得复杂了,因为 15 分钟的 Lambda 运行时间窗口突然缩减为 30 秒的窗口,以向客户端返回 HTTP 响应。
本文并不是试图让您停止在 lambda 中运行特定的 NLP 管道,相反,它希望帮助您了解这些约束以及克服它们的一些方法(或者,从理解的角度选择忽略,帮助您生活在边缘)。
什么是冷启动?
冷启动发生在容器关闭时,然后在调用 lambda 函数时必须重新启动,通常这发生在大约 5 分钟的不活动之后。
已经有很多关于冷启动的文章,所以这篇文章不会提供详细的指导(我建议你查看这篇文章)。但是简单来说…
当容器从冷态启动时,该功能需要:
- 从外部永久存储器(例如 S3)获取并加载包含 lambda 代码的包;
- 旋转容器;
- 将包代码加载到内存中;
- 运行函数的处理程序方法/函数。
(https://dash bird . io/blog/can-we-solve-server less-cold-starts/)
注意:每当你调用一个 lambda 函数(这是你的代码)时,第 4 步总是发生。),但步骤 1-3 仅适用于冷启动。由于设置阶段完全发生在 AWS 中,它们不在我们的控制范围内。我们可以在步骤 4 中优化我们内心的内容,但是步骤 1-3 仍然会随意地给我们带来大约 10 秒以上的延迟。这显然是同步 API 的问题。
我们的具体问题
现在开始讨论我们的具体问题。我们有一个同步 API,它:
- 从 HTTP 请求中获取任意文本输入
- 从 S3 下载了一个 NLP 模型(大约 220mb)
- 使用模型对输入执行 NLP
- 将序列化的结果返回给调用者。
这里的问题是第二步。每次调用时从 s3 下载模型可能需要 15-20 秒。这在大多数情况下对我们的用例来说是好的,因为尽管我们提供了一个长时间运行的同步端点,但我们并不期望它很快(我们讨论的是动态 NLP,而不是简单的 GET 请求)。
然而,在冷启动期间,我们经常看到请求超时。这完全说得通,就好像 lambda 需要 10 秒启动,而下载模型需要 20 秒,我们没有太多时间来运行 NLP 并在 30 秒的 HTTP 窗口中返回结果!
图 1(作者截图):3 个月窗口中各种 API 调用的*均延迟。当线路在 29k 毫秒处中断时,将会发生超时,并引发 504 错误。
可能的解决方案:
有各种方法可以解决这个问题,例如:
a.供应的并发
b.无服务器插件预热
c.EC2
d.定制的解决方案
下面将逐一讨论:
A.供应的并发
如果您知道一个确切的窗口,知道您的 lambda 流量的预期时间,那么供应并发是一个很好的解决方案。它基本上预先分配了一定数量的容器来运行您的 lambda,这些容器将在指定窗口的持续时间内保持运行。
这种解决方案的主要优势之一是,它可以改善上述 lambda 流程的设置(1–3)和运行时(4)阶段的延迟。显而易*,由于容器已经在运行(即没有冷启动),设置阶段在提供的时隙中被消除了,但这种方法如何加快运行时间可能不太明显。答案在于,通过保持容器温暖,避免了后续调用中不必要的初始化(例如,建立数据库连接、初始化对象、下载参考数据或加载沉重的框架等任务)(源)。
对于我们的用例,供应并发的问题是,由于我们的 API 必须支持全球不同时区的集成器,供应窗口将变得非常大,这对我们来说将成为无效的解决方案。此外,我们不知道这些窗口的确切时间。
B.无服务器插件预热
我们使用(强烈推荐的)无服务器框架,采用该框架的最大好处之一是可用的开源插件的社区和范围。一个解决这个问题的插件是无服务器插件预热。
这个插件采取了一种类似的方法来提供并发性,因为它试图防止 lambda 容器变冷,但它是通过在指定的时间窗口内用虚拟请求撞击它们来实现的。该插件有很好的文档记录,高度可配置,但最终我们认为它不是我们的最佳途径,原因与提供并发选项相同——我们不一定能准确预测何时需要并发,将其配置为宽窗口将是浪费/过度。
让我们简单关注最后一点——浪费。Lambdas 像芯片一样便宜,但对我们来说,真正的成本是下载 NLP 模型。一个烟盒计算表明,如果我们试图在整个月的正常英国办公时间内保持 10 个集装箱运行,我们一个月就会下载 1.89TB 的数据。虽然这在 S3 还不是一笔大开销,但比我们目前的支出高出了几个数量级。在扩展您的 lambda 时,请记住真正的成本——通常不仅仅是 lambda 本身的运行时间!
C.EC2
每次都从 S3 下载模型听起来效率很低——难道我们就不能启动几个自动缩放的网络服务器,然后在上面加载模型,这样就可以开始了吗?问题解决了,不是吗?
是的,但是 A)这需要大量投资来重构我们当前完全无服务器的 API 后端,B)另一个烟盒成本计算显示,这将比实现 A 或 B 的成本高几个数量级,而 A 或 B 本身比我们当前所做的要贵几个数量级。
D.定制的解决方案
排除上述解决方案后,我们决定采用定制解决方案。
现在,这里的警告是,当选择推出自己的解决方案时,不要忘记开发的成本。我喜欢 Yevgeniy Brikman 的规则,即如果你是一家初创公司,除非你正在构建的是你的核心价值主张,否则不要构建它——使用开源库,否则使用专有解决方案。
然而,在这种情况下,我决定打破这条规则,因为替代方案的持续成本会使该特性的一次性开发成本相形*绌。
那么解决方案是什么呢?
我们的解决方案基于这样一个认识:虽然我们无法准确预测何时需要预热服务,但我们知道,为了使用服务,客户端必须首先使用 OAuth 验证自己。如果发送了一个获取 OAuth 令牌的身份验证请求,很可能会接着发送一个对该令牌执行某些操作的请求。
因此,模式如下:
- 当生成 OAuth 令牌时,也异步预热 lambda 容器。
- 当发出后续客户端请求时,会命中 warmed lambda。
这是一个序列图:
图 2(图片由作者提供):在认证请求期间处理 NLP 模型 lambda 预热的序列图。
注意:这个解决方案有一个小问题,如果客户端在 lambda 完全预热之前发送后续请求,它会引入一个竞争条件。在我们的例子中,只要我们向我们的 API 集成者明确表示,在认证后发送第一个请求之前,给 lambda 留出预热时间,这就可以了。
结论
无服务器很酷。在无服务器上做 NLP 很酷。API 请求超时并不酷(讽刺的是,冷启动并不酷)。如果你想变得冷静,通过考虑上面强调的方法之一来解决如何避免冷启动的问题。
根据您的具体使用情况,像提供的并发这样的现成解决方案可能是您的正确选择,或者,如果这些解决方案都不理想,那么就像我们一样考虑简单的定制方法。始终考虑运行和扩展服务的全部成本(不仅仅是 lambda 调用运行时)。最后,在避免过早优化的同时,如果您的 API 开始遇到超时问题,那么您知道现在是优化的时候了!
脚注
关于这一点:“每次都从 S3 下载模型听起来非常低效”。的确如此。这里的解决方案是利用 AWS lambdas 附带的“/tmp”存储,并且只有在模型还没有保存在那里的情况下才重新下载模型(即冷启动)。
使用混淆矩阵度量避免混淆
从混淆矩阵中理解 17 个指标
一个混淆矩阵是一个度量工具,用于评估分类机器学*模型的结果。它是一个正方形矩阵,其大小取决于模型中的类的数量。尽管我经常对可以推导出的度量标准感到困惑,因为它们代表了什么以及它们是如何计算的。
在这篇文章中,我将在混淆矩阵上为我们所有人创建一个参考,它的 17 个相应的度量及其公式(根据上面链接的维基百科文章),一些帮助我们最终不再需要这个参考的解释,以及如何从头开始编码它们。让我们加载我们需要的库并开始吧!
注意:所有配方都是稍加修改或取自上述维基百科文章,并使用此 在线乳胶生成器 创建。
由于本文的重点是度量,我将使用 NumPy 的均匀分布生成器创建一些假数据,为y_actual
和y_pred
获得 500 个 0 和 1 的随机值。
混淆矩阵结构和提供的信息
首先,我们需要讨论混淆矩阵的组成部分。为此,让我们创建一个带有二进制分类情况的样本混淆矩阵。
用 Python 代码自制的混淆矩阵
如标签所示,矩阵有两面。“真实标签”在左侧垂直方向,“预测标签”在底部。这决定了 4 个小方框中的数字所代表的预测类型。这些值是以下各项的数量:
- 真底片(左上)缩写 TN
- 真阳性(右下)缩写 TP
- 假阴性(左下角)缩写 FN
- 误报(右上)缩写 FP
你怎么记得哪条对角线有正确的匹配?沿着从上到下的对角线走。你也可以用短语“自上而下”作为记忆工具,因为你是沿着对角线从上往下走的。
快速提示,如果你设置了参数normalize=True
,你会水*归一化结果。回想一下,规范化值意味着将所有值相加,然后将每个值除以该总和。混淆矩阵的每一行中的所有值都会再次发生这种情况。
上述混淆矩阵的标准化版本。
在这种情况下,真 0 标签行的总和是 239。用 128 和 111 除以 239 得到的百分比分别是小数 0.54 和 0.46。在继续下一步之前,现在尝试使用 true 1 标签行。
从混淆矩阵计算出的度量
在我们开始之前,让我们通过scikit-learn
创建混淆矩阵。
你可以像对任何其他数组一样对矩阵的每个部分进行切片,从而得到它们的值。这是因为该函数的输出是一个 2x2 数组。为了获得每个值,我们使用以下公式:
- 真底片(左上)=
cm[0, 0]
- 真阳性(右下角)=
cm[1, 1]
- 假阴性(左下)=
cm[1,0]
- 误报(右上)=
cm[0,1]
在我们开始之前还有一件事。我将在解释和代码之前给出度量的公式。我鼓励你先尝试自己编写公式。然后你可以对照你自己的版本检查我的版本。这将让你练*自己编写公式。现在来看指标(这次是真的)!
准确(性)
准确性是最简单的,也可能是你最熟悉的。这是告诉我们有多少数据被正确分类的量度。该值越接近 1,精确度越高。
回忆=真实阳性率
你可以认为这是积极的准确性。这个指标告诉我们“1”值被归类为“1”值的准确程度。
特异性=真阴性率
你可以认为这是负面的准确性。这个指标告诉我们“0”值被归类为“0”值的准确程度。
精确度=阳性预测值
这就是事情开始变得棘手的地方。你可能会问这和召回有什么不同。该指标的目的是确定预测值“1】实际为真实“1”值的百分比。再次回忆只是告诉我们在所有真“1”值中,有百分之多少的真“1”值被正确预测为“1”值。
阴性预测值
这是上面精度的否定版本。同样,这和特异性之间的主要区别是分母。分母包含所有预测为“0”的值。特异性将所有真正的“0”值作为其分母。因此,这告诉我们预测的“0”值实际上是真实的“0”值的百分比。
假阳性率
也被称为落幕。除了错误分类的值之外,您可以将此视为要回忆的对应物。该指标越接近 1,您将“0”值错误分类为“1”值的百分比就越大。该指标越接近零,被错误分类为“1”值的“0”值的百分比就越低。
假阴性率
也被称为失败率。除了错误分类的值之外,您可以将此视为特异性的对应项。该指标越接近 1,您将“1”值错误分类为“0”值的百分比就越大。该指标越接近零,被错误分类为“0”值的“1”值的百分比就越低。
错误发现率
这又是事情变得棘手的地方。但是这个度量也是精度的对应物。这里的分母是被归类为“1”值的值。由于分子是 FP 而不是 TP,我们使用这个度量来确定实际上是假 "1 "值的预测 "1 "值的百分比。
错误遗漏率
该指标也是阴性预测值的对应指标。这里的分母是被归类为“0”值的值。由于分子是 FN 而不是 TN,我们使用这个度量来确定实际上是假“0】值的预测“0”值的百分比。
关键成功指数
这也被称为威胁率。关键成功指数显然用于预测,它提供了一种衡量“1”值相对于错误分类值(FN 和 FP)的准确性的方法。一些文章将该指数描述为命中与未命中。如果你对一个用例更感兴趣,这里有这篇论文是关于深度 CNN 的一个应用,它使用索引作为结果的度量。
马修斯相关系数
Matthews 相关系数是实际值和预测值之间的相关性,例如我们的二进制情况。像相关性一样,它的范围可以从-1 到 1。这个度量提供的好处是,不管两个类之间的数量差异如何,模型都有一个“*衡的度量”来解释它的质量。除了这里提到的内容之外,请查看本段中链接的文章以了解更多细节。
关于上述指标,您注意到了什么?
关于这些指标的组成部分,您注意到了什么?
如果你注意到所有的指标都是由混淆矩阵本身的各个部分构成的,那你就对了!从这一点开始,剩下的 6 个指标(是的,我们已经完成了 11 个)将由上面的指标组成。所以如果你准备好了,我们走吧!
阿曼德·库利在 Unsplash 上拍摄的照片
*衡精度
*衡精度是一种精度度量,用作原始精度度量的替代。只有当您的目标达到*衡时,原始的精度指标才是最佳的。这是当你有几乎相等数量的“0”值和“1”值来训练模型的时候。当您的数据严重不*衡时(比如说 97%的数据是“0”值,其余的是“1”值),最初的准确性指标就失效了。*衡准确度对真阳性率和真阴性率(也称为召回率和特异性)进行*均,以获得更能代表不*衡数据的模型结果的准确度度量。看看这个例子的对比。
F1 分数
F1 得分是精确度和召回率的调和*均值(又名阳性预测值和阳性准确率)。这是原始准确性的另一个衡量标准。根据本文中的,当您的数据有大量负值(在本例中为“0”值)时,您可能希望使用这一指标来衡量原始精度。
信息
根据 Venkatesh-Prasad Ranganath 的文章,知情是回忆的另一种选择。Venkatesh-Prasad 解释说,回忆的缺点是,当情况需要时,它不考虑模型的负类值(“0”值)的任何变化。包括特异性的真实阴性率有助于解决这个问题。我建议阅读本段中链接的文章,了解对这一指标的详细解释。
显著
Venkatesh-Prasad Ranganath 在的同一篇文章中也提到了标记性。他解释说,标记性是精确性的一种替代。预测值的精度与 recall 有类似的问题,它不考虑负的真“0”值。精确地包括负预测值有助于处理这个问题。我再次建议阅读本段中链接的文章,以进一步了解这一指标。
流行阈值
正如你所看到的,流行阈值仅仅基于回忆和特异性(也就是真正的阳性率和真正的阴性率)。这是一个衡量标准,为模型的良好表现设置了一个标准。请注意,流行阈值的分母是上面的信息度量。
福尔克斯-马洛指数
Fowlkes-Mallows 指数用于确定两组数据之间的相似性。在我们使用二元分类的情况下,它可以是一组实际值和一组预测值。它的范围从 0 到 1,越接近 1 表示相似性越强。
最后的想法
令人惊讶的是,存在如此多的评估机器学*模型的指标。更别说这些只和分类有关!为了帮助您进一步理解这些指标,请尝试将它们相互比较。例如,回忆和特异性关心负值(“0”值)和正值(“1”值)的预测率。然后你也有他们的假阳性率和假阴性率。还要记住,前几个指标的意义取决于分子和分母的选择。
感谢阅读!这封推荐信对你有多大帮助?你会如何修改它?
欢迎您在 Linkedin 和 Twitter 上关注或联系我。对 Twitter 上的 DM 开放。
直到下一次,
约翰·德杰苏斯
用敌对的 t 恤避免被发现
了解新 t 恤图案背后的新研究,它愚弄了最先进的人体检测系统
仅仅穿一件特定类型的 t 恤怎么能让你不被人发现和监视系统发现呢?好吧,研究人员已经发现并利用了深度神经网络的致命弱点——一些最佳物体探测器背后的框架(YOLOv2,fast R-CNN,HRNetv2,仅举几例)。
早期方法:
在[1]中,作者设法在真实世界的用例中得到欺骗的基准准确度 57% 。然而,这并不是第一次试图欺骗物体探测器。在[2]中,作者为他们的模型设计了一种方法来学*和生成可以欺骗检测器的补丁。这种贴片戴在纸板(或任何*面)上时,可以躲过人体探测器,尽管准确率只有 18%
出自[2]。左图:成功检测到没有贴片的人。右图:拿着补丁的人被忽略。
像这样“迷惑”或“愚弄”神经网络被称为做出 物理对抗性攻击 或现实世界对抗性攻击。这些攻击最初基于错综复杂的像素值,使网络(基于其训练数据)混淆,将对象标记为“未知”或简单地忽略它。
作者在[2]中转换其训练数据中的图像,应用初始补丁,并将结果图像馈入检测器。获得的对象损失用于改变补片中的像素值,旨在最小化对象性分数。
出自[2]。生成补丁并获取对象丢失。
然而,除了 18%的低准确性之外,这种方法仅限于像纸板这样的刚性载体,并且当捕获的帧具有扭曲或歪斜的补丁时,性能不佳。而且印在 t 恤上肯定效果不好。
“一个人的运动可以导致他们衣服上明显和不断变化的褶皱(也称为变形)”[1]。从而使得开发通用对抗性补丁的任务更加困难。
新方法:
[1]中的新方法采用薄板样条映射来模拟布料变形。这些变形模拟了以前尝试使用对抗模式所面临的现实问题。考虑不同的变形将极大地提高系统的性能,因为它将能够在更多数量的帧中 不检测 图案。
理解样条本身就足以大致了解他们试图用这种方法做什么。
样条:
对于一个更正式的数学定义,你可以看看这篇文章,对于一个更简单的理解,我认为这篇文章做得最好。
从直觉上来说,样条有助于*滑地绘制任意函数——尤其是那些需要插值的函数。样条有助于对这些缺失的数据进行建模:在对布料变形进行建模时,可以在连续的帧中看到面片形状的变形,我们可以使用一种高级形式的多项式样条,称为 薄板样条 (TPS)。
查看哥伦比亚的这篇文章,这篇文章很好地解释了 TPS 回归。
这些变化,或位移,在补丁帧随时间的推移,然后简单地建模为一个回归问题(因为我们只需要预测未来帧的 TPS 参数)。
生成 t 恤图案:
上述模式只是一个对立的例子——一个违背对象检测器目的的补丁。作者使用 对转换的期望(EOT)算法 ,该算法有助于在给定的转换分布上生成这种对立的例子。
这里,变换分布由 TPS 变换组成,因为我们想要复制实时起皱、轻微扭曲和织物轮廓的变化。
来自[1]:模拟布料变形的效果。
除了 TPS 变换,他们还在人的边界框内使用物理颜色变换和传统的物理变换。因此,这产生了对扰动图像的像素值进行建模的方程。
基于所有这些复杂公式的 EOT 公式可以最终计算出攻击损失,并欺骗目标探测器。
到目前为止,以其最简化的形式对该过程的解释是针对单个物体检测器的。作者还提出了一种针对多目标探测器的策略,该策略涉及将最小-最大优化应用于单目标探测器方程。
最后:
在他们自己的数据集上训练和测试后的结果令人印象深刻。
来自[1]。在作者的数据集上生成自定义对抗性补丁后的结果
TPS 的使用也显示出巨大的进步:
来自[1]。比较使用 TPS(第二行)和不使用 TPS(第一行)的不同姿势的结果
未来会怎样:
- 在东北大学的一篇文章中,【1】的作者之一林雪澄清说,他们的目标不是为了偷偷摸摸地不被探测器发现而创造一件 t 恤。
“我们研究的最终目标是设计安全的深度学*系统,……但第一步是对它们的漏洞进行基准测试。”—林雪
- 当然,作者们意识到他们的结果有很大的改进余地,并提到将做进一步的研究来实现它。
由塞巴斯蒂安·莫利纳·福托格拉夫在 Unsplash 拍摄的照片
感谢您从头到尾的阅读!您可以通过 LinkedIn联系我,获取任何信息、想法或建议。
参考资料:
[1]:徐,,等.对抗性 t 恤!在物理世界中躲避人探测器(2019), arXiv 预印本。 arXiv-1910.11099
[2]: Thys,Simen,Wiebe Van Ranst 和 Toon Goedemé,愚弄自动监控摄像机:攻击人员检测的对抗性补丁(2019),IEEE 计算机视觉和模式识别研讨会会议录。
[3]: Athalye,Anish,和 Ilya Sutskever,综合稳健的对抗性例子(2017), arXiv 预印本 arXiv:1707.07397。
避免代价高昂的最后一英里数据科学失败
一种更具触觉的方法,确保我们解决了客户关心的问题
“他一生都在看别处”——便利贴上的塔图因
每当我们读到关于数据科学的成功或失败时,人们常常会提到“最后一英里”。通常与“这是项目进行到 s***!”相提并论。
这是非常重要的一步,您可以将通过分析/机器学*获得的*解提供给客户。你相信这些*解可以帮助他们做出更好的决策…这些决策最终会带来真正的商业利益。
内心深处,有一丝怀疑。如果你对客户不太关心的问题提供了*解会怎样?
回忆之旅
回到土木工程的第一年,我们*过一切的教授会给新生一个挑战。两个城镇,被一条湍急的河流分开,我们需要一座桥…一座牙签桥。
“任何一种牙签桥。桁架?悬臂?拱门?你决定……”
“做假设!”面对几乎没有任何信息的抗议,他会咆哮回应。当年没有谷歌!
在接下来的一周里,学生们带来的模型从糟糕到差强人意,从无聊到完全古怪。教授苦笑着,首先会问“你们相信这些设计吗?”。
然后他拿出一个钢珠轴承,把它放在正确的位置,果然,每个人的结构都会一个接一个地倒塌。
《公民 101》中没有人能接近这位拉斯·埃里克森笔下的尤物(转载请注明出处:http://www.pisymphony.com/toothpick/toothpick13.jpg)
他们为什么不信任我们?
从工程师的角度来看,最后一英里的成功是一座结构稳定的桥梁。但是土木工程也是一门成熟的学科。它有明确定义的流程,会让你得到一个输出…除非事情变得非常糟糕。
数据科学在很大程度上是概率性的。就预测而言,我们从数据中提取知识,然后拼命对未来做出更有根据的猜测。
我们倾向于说“顾客先生,你可能会得到一座桥——我们只是不知道是哪一种,也不知道它会有多坚固。但是我们认为你应该越过它,因为我们已经……完成了工作!”
对许多客户来说,这是一个黑匣子。魔法发生了,但是是什么样的炼金术呢?这是花招吗?没有人确定。
而没说出口的问题通常是“我们信任那个黑盒吗?而前面的人呢?”。
问题陈述中的信任和不确定性
“商界有句老话:如果不提出正确的问题,你怎么能指望得到正确的答案?对于任何给定的产品或服务,客户的期望、愿望和要求往往被禁锢在客户的头脑中。”~Forbes ~ '为什么企业无法走完分析的“最后一英里”
信任的问题可以追溯到最初。在客户看来,数据科学类型的业务问题可以采取多种形式,并经过多次迭代。
客户通常告诉你的是他们认为他们在特定时间点想要的。但是如果他们不了解你,他们可能一开始不会告诉你足够的信息…或者给你理解问题本质所需的背景。
所以实际上,你听到的问题的第一个版本不太可能是你需要解决的问题。
例如看看这个是如何变形的。
- 第一周:你的系统能预测硬件何时会失效吗? 好吧。
- 第三周:你的系统能在 30 分钟内完成预测吗? 好吧,但为什么是 30 分钟?
- 第 6 周:当硬件出现故障时,有多少网络流量受到影响?那是一件有点多但可行的工作。
- 第 9 周:事实上,我们知道高网络流量会导致硬件故障。您能预测流量何时会激增到足以导致故障吗? 为什么一开始不告诉我们包含流量?
- 第 14 周:我们已经有了一个硬件更新计划。如果我们用你的预测,会不会更便宜?对自己思考>我们到底如何收回成本??
最终,我们与客户(内部或外部)相处的每一天,都离了解真正的问题更近了一步。
找到一种尽可能快速和亲密地接触到那个肮脏的下腹部的方法意味着一项艰巨的任务,即总是试着站在顾客的立场上想象……然后问供应商一些问题,目的是从内心感受。
- 供应商在做什么?
- 他们真的了解我们的问题吗?
- 这些都管用吗??
这也是故事板在数据科学中派上用场的地方,它能够以一种邀请对话的方式来组织问题和答案。
故事板对我们意味着什么
几年前,受到沟通不畅和结果不佳的困扰,数据科学抓住了用数据讲故事的概念。
看到我们的第一手观众被数据驱动的对话淹没,我们不得不寻找替代方案。我们发现 Brent Dykes 在他的“基本数据科学技能”文章中描述的使用视觉和叙事的原因实在太引人注目而不能忽视。
挤出时间学*一项新技能是一回事,但如何找到动力呢?为此,我们去了电影业…可能是真正的视觉故事大师。
所以我们阅读了 Studio Binder 的故事板指南,然后浏览了故事板形式的电影收藏库。老实说,首先尝试在画板上解决客户的问题的想法更加鼓舞人心!
当然,这仍然给我们留下了如何有效地将数据整合到故事板中的问题,以供高层、工程师、经理和其他人使用。谢天谢地,我们找到了南希·杜阿尔特,并欣然接受了她关于人性化数据的想法。
对我们来说,故事板现在已经成为我们和我们的客户需要走的路的路标。
数据科学中故事板的五个好处
这不是一部电影,但故事板可以帮助您和您的客户了解事情的发展方向
1.故事板帮助你确认存在问题
我们犯的早期错误之一是在数据分析期间开始我们的故事板过程。太晚了…除非你确信你理解了客户所看到的问题。
现在我们从确保我们可以首先通过数据看到问题的目标开始,这并不总是像听起来那么容易。但它给了我们信心,让我们相信问题是切实存在的。
2.故事板有助于您与客户达成对常*问题的理解
通过用你的话向客户复述问题,他们可以理解你的过程,你也可以理解他们的过程。
你也有机会改进问题,客户可能会感觉到你真诚地试图理解和承认他们的痛苦。
3.故事板向他们展示了你正在做的事情
客户通常想知道发生了什么事情。一次一张图,一点点进步,就能创造奇迹。
更重要的是,当他们看到你在做什么时,那个黑盒就不再是黑盒了。
4.早期财务的故事板将会给你一个如何最终得到一个合理的商业案例的感觉
我们需要快速找出是什么让客户心动,最好是离终点线越远越好。
引入成本估算是一个确定无疑的方法,可以提前了解问题有多严重,客户有多关心它,以及您可能会偏离轨道有多远!
5.故事板可以针对不同的利益相关者进行定制
就像课程中的马一样,相同的故事板不一定适用于您客户领域中不同层次的受众。这就是为什么使用允许多个故事板从相同的底层数据出发的工具是至关重要的。
这需要多少能量?
很多。
毫无疑问,这是一项耗时耗力的工作。我们实际上是在进行前期投资,希望未来能有更多的收益。广泛澄清问题从来不意味着数据清理、转换、模型构建和机器学*应用程序的所有其他工作都要停止。
但它确实给了我们在最后一英里之前自我修正的机会,而不会造成太多的附带损害。
并帮助我们与客户一起一砖一瓦地构建至关重要的叙述和业务案例。
所以,也许现在先把洞察力放在一边,先揭开黑匣子
“他一生都在向远处看……向未来,向地*线。他从不关心他在哪里…他在做什么”——尤达
现实是,即使业务问题被充分定义,如果决策者不相信我们如何到达那里的过程,任何有用的洞察力都不可能工作。如果他们一开始就不是旅程的一部分,这通常会发生。
但是如果我们参与客户版本的流程,我们就给了自己一个机会。我们可能最终会花足够的时间和他们在一起,让信任和尊重自然而然地建立起来。
当然,我们的工作质量最好是体面的,数字必须工作。
然后,他们可能会在你的允许下过桥…
(2020 年 2 月)瑞士巴登一个冬日下午的最后一英里回家
真棒朱莉娅机器学*包每个人都应该尝试!
一些我最喜欢的 Julia ML 包,我想其他开发者也会喜欢!
尽管 Julia 仍然是一门相对年轻和温顺的编程语言,但有时生态系统变得如此成熟会令人非常惊讶。我认为在机器学*领域更是如此。虽然 Python 等其他语言当然有更多的机器学*包,但 Julia 的机器学*包绝对值得一试。它们不仅具有用像 Julia 这样的快速高级语言编写的额外好处,而且它们是很棒的软件,无论使用何种语言,都易于使用。
这些包中的许多都利用了 Julia 富于表现力的语法。此外,它们都使用 Julia 库中可用的函数,使用 Julia 的多态分派在不同类型上完成类似的任务。这使得包跳转比在另一种语言中更容易。关于许多 Julia ML 包的另一个很酷的事情是,它们不会很庞大,因为通常你不需要为了做统计而写过多的 Julia 代码。
流量
开始列表是朱利安机器学*的主要内容,
Flux.jl。
在 Julia 中,Flux.jl 通常用作创建神经网络的抽象层。Flux.jl 是我在 Julia 语言中最喜欢使用的包之一,也是我开始使用 Julia 时最先使用的包之一。Flux 的一大优势是它非常小。它在 Julia 已经很棒的 AD 和 GPU 计算代码基础上提供了轻量级的抽象。哦,我有没有提到,Flux 有很棒的 CUDA 支持?并行计算始终是一个巨大的优势,但除了已经投入 JuliaGPU 的出色工作,Nvidea 显卡和 Flux 的结合使机器学*工程师的梦想成为现实。
Flux 的重量也使它非常适合在服务器上使用,因为它不会占用太多空间,并且可以非常容易地放入带有 Pkg 的微型虚拟环境中。总而言之,Flux 是可移植的。Flux 也是用百分之百纯 Julia 代码编写的,这是一个额外的好处,因为你不必处理外来的语法,也不需要使用 CSyntax 这样的包来完成 Flux 的工作。如果您想更熟悉 Flux.jl,我在本文中为您写了一个简短的介绍:
[## Julia 对 Flux 的快速介绍(使用 CUDA)
用 Flux 在 Julia 中建立你的第一个渐变模型
towardsdatascience.com](/a-swift-introduction-to-flux-for-julia-with-cuda-9d87c535312c)
梅林. jl
Merlin 是另一个在 Julia 中创建神经网络的深度学*框架。Merlin.jl 是许多开发人员可能会忽略的一个包。然而,这将是一个错误,因为 Merlin 是一个不可思议的工具,在许多不同的场合下节省了我很多时间。像 Flux.jl 一样,Merlin 是相对轻量级的,并且是用百分之百纯 Julia 代码编写的。Merlin 在许多操作中往往超过 Flux,尽管这并不一定意味着它总是更快。
同样类似于 Flux,Merlin 内置了对 CUDA 的 GPU 支持。不仅如此,Merlin 模型通常比 Flux 模型更易于部署。虽然这并不是说部署 Flux 特别困难,但也不是特别容易。所以我会说,如果你计划部署一个 API,使用一个带有 Genie 和 Julia 的神经网络,我可能会选择 Merlin。除了所有这些很酷的特性,Merlin 还包括一个小的发行库。
KNet.jl
Knet 是 Julia 的另一个深度学*框架,有一点扭曲。Knet 实际上是为 kou 大学开发的。因此,这个包似乎比这个列表中的大多数其他包维护得更好,这些包通常只由少数出于热情而工作的人来管理。与 Flux 和 Merlin 不同,Knet 是一个更重的包。Knet 也不是用纯 Julia 编写的,而是用各种语言编写的,比如运行在 Julia 代码下的 C 和 MATLAB。
但是,需要注意的是,Knet 中有很小一部分是用 C 和 MATLAB 编写的,总共只有大约 1.8%。我想说 Knet 是这个列表中初学者的最佳选择之一,因为它非常简单。
我犹豫要不要把车床加入这个列表,因为我对它有点偏*,因为
我是创造者。
然而,我觉得不在这里添加它是没有意义的,因为车床提供了大量的特性。首先,Lathe 附带了一个相当大的统计库,其中包括 chi 测试、贝叶斯统计、t-测试、f 检验,甚至还有一些不太为人所知的统计,如 signs 测试。最重要的是,stats 模块中还包含了验证,它具有连续和分类预测的准确性指标。作为本模块中统计数据的精华,Lathe.jl 还包含了一个不错的发行版库。
为了增加 DS/ML 的乐趣,Lathe 还提供了大量的预处理工具,这些工具可能是你从这个不成熟的包中没有想到的。这方面的好例子是特征定标器、训练测试分割和分类编码。最重要的是,车床有一个短而甜的模块加载数据到朱莉娅。如果您想将任何类型的图像或类似数据加载到 Julia 中,这些工具非常有用。
最后,车床有一个不断扩大的机器学*模块库,甚至支持构建卷积神经网络。车床也有一个管道框架,使得部署一个具有 JLD2 序列化的车床模型变得非常容易。Lathe 也是用纯 Julia 编写的,并且在文档方面相对稳定(尽管在 0.1.2 中有一个很大的文档更新,文档字符串被修改。)我会说,如果说 Flux 是 Julia 的 Tenserflow,那么 Lathe 就是 Julia 的 Sklearn。这意味着车床是包容的,提供了你需要的所有工具,并且它对初学者来说也是非常友好和容易的。
如果你想通过检查车床来支持我,你可以在这里这样做:
[## 车床
车床使用更快的方法和简单的方法。使得包装快速、简单且轻便。许多工具和模型…
车床. ai](http://lathe.ai)
MLBase.jl
MLBase.jl 是另一个 Julia 模块,它遵循与 Python 中的 Sklearn 类似的方法。MLBase.jl 包括用于通用数据处理的工具,如特征缩放器和编码器,以及基于分数的分类和验证。这个包还有一个非常独特和有用的特性,
模型调整。
MLBase 的模型调整将使你的超参数优化变得非常容易。MLBase,你可能已经猜到了,MLBase.jl 完全是用 Julia 写的。它也是这个列表中最轻的包。它也非常容易使用,所以对初学者来说是另一个很好的选择。
你有它;这些是 Julia 开发人员拥有的一些最好的机器学*模块。虽然它们中的一些肯定服务于不同的目的,但是从所有的特性中挑选特性往往是最佳的行动计划。至于开始的最佳方案,我会说它介于
- MLBase.jl
- 车床. jl
- Knet.jl
从那里,我会问“你想做什么?”因为这些模块中的每一个都有自己独特的才能,根据您的情况,这些才能可能有用,也可能没用。总的来说,尽管 Julia 的生态系统不像 Python 的怪物生态系统那样成熟,但这也是 Julia 有趣的一部分。很多人对这门语言做出了巨大的贡献,更重要的是,对整个数据科学做出了巨大的贡献。总之,虽然 Julia 可能没有你在其他语言中看到的那么多令人惊叹的模块,但它所拥有的包通常都是开发良好的,并且只是刚刚开始它们的旅程。
可怕的 JupyterLab 扩展
一些有用的 JupyterLab 扩展之旅
作者图片
Jupyter Lab 是数据科学界使用最广泛的 ide 之一。当涉及到快速原型和探索性分析时,它们是许多数据科学家的工具选择。JupyterLab 巧妙地将许多功能捆绑在一起,实现了协作、可扩展和可伸缩的数据科学。然而,这篇文章不是关于 Jupyter 实验室的各种优势。我相信有很多关于这个主题的资源。相反,这里的重点是 JupyterLab 的一个有用的组件,叫做扩展。这些扩展非常有用,可以提高一个人在单独工作或团队工作时的效率。让我们从理解什么是扩展开始,然后我们将快速浏览 Github 上目前可用的一些有用的 JupyterLab 扩展。
扩展ˌ扩张
JupyterLab 被设计成一个可扩展的模块化环境。因此,人们可以轻松地在现有环境中添加和集成新组件。扩展正是基于这一核心思想。JupyterLab 可以很容易地通过第三方扩展进行扩展。这些扩展由 Jupyter 社区的开发人员编写,本质上是 npm 包(Javascript 开发中的标准包格式)。那么是什么让这些扩展如此有用呢?这里有一段摘自官方文档的摘录,回答了这个问题:
"扩展可以向菜单或命令调色板、键盘快捷键或设置系统中的设置添加项目。扩展可以提供 API 供其他扩展使用,并且可以依赖于其他扩展。事实上,整个 JupyterLab 本身只是一个扩展的集合,并不比任何自定义扩展更强大或更有特权。”
装置
在本文中,我们将看看一些有用的扩展,以及它们如何增强我们使用 jupyter 实验室的体验。但是在我们开始之前,让我们快速地看一下如何安装这些扩展。要安装 JupyterLab 扩展,您需要安装 Node.js ,要么直接从 Node.js 网站安装,要么如下所示。
conda install -c conda-forge nodejs
or# For Mac OSX users
brew install node
安装后,它会作为一个新图标出现在 JupyterLab 侧边栏中。
扩展经理
为了管理各种扩展,我们可以使用扩展管理器。默认情况下,管理器是禁用的,但可以通过单击“enable”按钮来启用。
启用扩展管理器|作者图片
或者,您可以在命令面板中搜索扩展管理器,并在那里启用它。
通过在命令面板|作者图片中搜索来启用扩展管理器
有用的 JupyterLab 扩展
现在让我们浏览一下 JupyterLab 中目前可用的一些有用的扩展。请记住这些是第三方扩展,未经审核。一些扩展可能会带来安全风险或包含在您的机器上运行的恶意代码。
您可以在扩展管理器中搜索所需的扩展。搜索时,您会注意到其中一些扩展的名称旁边有一个 Jupyter 图标。这些扩展由 Jupyter 组织发布,并且总是放在最前面。
可用的 Jupyter 实验室扩展|作者图片
1️⃣ .Jupyterlab Google Drive
顾名思义,jupyterlab-Google-drive 扩展 通过 google drive 为 JupyterLab 提供云存储。安装完成后,这个扩展会在 JupyterLab 的左侧面板添加一个 Google Drive 文件浏览器。您需要登录您的 google 帐户,才能通过 JupyterLab 访问存储在 google drive 中的文件。
安装:通过扩展管理器
您可以通过扩展管理器安装扩展。在搜索栏中搜索扩展的名称并安装它。
安装 jupyterlab-google-drive 扩展|作者图片
然后,您需要重新启动环境。一旦您这样做了,您将看到以下提示:
安装扩展时提示 JupyterLab 构建|作者图片
点击**Build**
来合并任何更改,你会立即在侧边栏看到一个 google drive 图标。除了安装扩展之外,您还需要通过 Google 验证您的 JupyterLab 部署。通过 设置 文件或此处 链接 进行处理。填写凭据后,您就可以从 jupyter 实验室访问您的驱动器。
Jupyterlab Google Drive 扩展|作者图片
安装:通过命令行接口
或者,您可以通过 CLI 安装该扩展,如下所示:
#Install the jupyterlab-google-drive extension
jupyter labextension install @jupyterlab/google-drive#Set up your credentials using [this](https://github.com/jupyterlab/jupyterlab-google-drive/blob/master/docs/setup.md) guide.# Start JupyterLab
jupyter lab
现在,如果有人与你共享一个笔记本或 markdown 文件,它将反映在 Jupyter 实验室的shared with me
文件夹中。您可以在 Jupyter 环境中无缝地打开并编辑它。
2️⃣.JupyterLab GitHub
JupyterLab Github 是用于访问 Github 库的 JupyterLab 扩展。使用这个扩展,您可以选择 GitHub 组织,浏览它们的存储库,并打开这些存储库中的文件。如果存储库包含一个 jupyter 笔记本,您将能够在您的 JupyterLab 环境中直接访问它们。
装置
同样,您可以通过扩展管理器或 CLI 安装这个扩展。请注意,这个软件包已经表明它需要一个相应的服务器扩展,在使用该扩展之前,系统会提示您安装该扩展。
l:通过扩展管理器安装|| R:通过命令行界面安装|作者图片
安装后需要从 GitHub 获取 凭证。
使用
一旦输入了凭证和权限,您就可以访问 JupyterLab 环境中的所有存储库,而无需在不同的界面之间切换。
JupyterLab Github 扩展|作者图片
3️⃣.Jupyterlab Git
Jupyterlab-git 是另一个有用的 Jupyterlab 扩展,用于使用 git 进行版本控制。
安装
要安装扩展,您可以执行以下步骤:
l:通过扩展管理器安装|| R:通过命令行界面安装|作者图片
安装后,可以从左侧面板的 Git 选项卡访问 Git 扩展
Jupyterlab-git 扩展|作者图片
4️⃣.Jupyterlab-TOC
Jupyterlab-TOC扩展填充 Jupyterlab 界面左侧的目录。如果有一个笔记本或 markdown 文件打开,其相应的目录将在侧边栏上生成。这些条目可以滚动和点击。
装置
****
l:通过扩展管理器安装|| R:通过命令行界面安装|作者图片
使用
一旦安装了扩展,您可以通过 JupyterLab 的高级设置编辑器修改它的一些属性。例如,您可以通过将*collapsibleNotebooks*
参数设置为 *True*
来从目录中折叠笔记本的各个部分。
Jupyterlab-TOC 扩展|作者图片
5️⃣.Jupyterlab-drawio
Drawio 插件 是一个 Jupyterlab 扩展,用于将 drawio/ mxgraph 独立集成到 JupyterLab 中。画画。 io 是一款免费的在线图表软件,用于制作流程图、过程图、组织图、UML、ER、网络图。
装置
****
l:通过扩展管理器安装|| R:通过命令行界面安装|作者图片
使用
Jupyterlab-drawio 扩展|作者图片
6️⃣.jupyterlab-顶部栏
J 顶部栏可用于放置一些有用的指示器,如:
Jupyter 实验室环境中顶部栏上的指示器|图片由作者提供
装置
****
l:通过扩展管理器安装|| R:通过命令行界面安装|作者图片
使用
一旦安装并启用了扩展,您将在顶部栏上看到一些指示器。将有一个注销按钮,黑暗和光明的主题开关,自定义消息,和内存指示器。
Jupyterlab-Topbar 扩展|作者图片
7️⃣.Jupyterlab 代码格式化程序
Jupyterlab 代码格式化程序 是一个小插件,支持 Jupyterlab 中的各种代码格式化程序。这是我最喜欢的扩展之一,因为它消除了代码格式化的许多痛苦。
装置
第一步是安装插件。
****
l:通过扩展管理器安装|| R:通过命令行界面安装|作者图片
下一步是安装代码格式化程序。Jupyterlab 代码格式化程序目前支持 Python 和 r 中的以下格式化程序。
在 Python 和 R. | Image by Author 中, Jupyterlab 代码格式化程序目前支持以下格式化程序
# Install your favourite code formatters from the list abovepip install black isort#orconda install black isort
然后你可以重启 JupyterLab 并配置插件,正如这里提到的和。下面显示了一个快速演示,但详细用法请遵循 文档 。下面演示的代码取自扩展的 Github 库。
Jupyterlab 代码格式化程序扩展|作者图片
8️⃣.jupyterlab-图表编辑器
jupyterlab-chart-editor扩展用于编辑 Plotly 图表,基于https://github.com/plotly/react-chart-editor。该扩展支持通过用户友好的点击式界面编辑 Plotly 图表。
装置
****
l:通过扩展管理器安装|| R:通过命令行界面安装|作者图片
使用
以下示例摘自官方文档。首先使用 plotly 创建图形,然后将其写入 JSON 文件。然后使用新安装的 plotly 编辑器打开保存的文件,并在 jupyterLab 环境中对其进行一些更改。
Jupyterlab-chart-editor 演示:Source — 官方文档
结论
在本文中,我们研究了一些有用的 JupyterLab 扩展,这些扩展使 JupyterLab 脱颖而出。在一个工作场所中拥有不同的工具非常有用,因为人们不必在不同的环境之间切换来完成工作。这些插件肯定会让你的数据分析过程更加顺畅和高效。
7 个强大的 Rust 驱动的命令行工具
适合每个开发人员的现代 Linux 命令
**Table of Contents**[**Introduction**](#072d)🦀 [Starship](#461e)
🦀 [ripgrep](#a547)
🦀 [bat](#1a8c)
🦀 [tokei](#5e9b)
🦀 [exa](#0ac4)
🦀 [fd](#ed5f)
🦀 [procs](#d4f9)
🦀 [How I found them](#0776)[**Conclusion**](#ee40)
介绍
Rust 编程语言已经连续四年成为 Stack Overflow 最受欢迎的语言。
Rust 在很大程度上被视为 C 或 C++等其他系统编程语言的替代品。
这就是为什么包括 Benjamin Sago 和 Andrew Gallant 在内的许多天才开发人员创造了优秀的 Rust 驱动的命令行工具。
在本文中,您将找到现在可以开始使用的七大命令行实用程序。
星际飞船
对于任何 shell 来说,Starship 是最小的、极快的、可无限定制的提示符。
要安装 homebrew run:
brew install starship
关于如何安装星舰的更多细节,请阅读 这篇文章 中关于星舰的内容。
并将 init 脚本添加到 shell 的配置文件中:
# ~/.zshrc
eval "$(starship init zsh)"
你可以在这里找到来自的其他装置。
图片来自星际飞船
里格雷普
一个超快的搜索工具,递归地在目录中搜索正则表达式模式。ripgrep
支持 Windows、macOS 和 Linux ,是grep
的现代替代品。
可以安装ripgrep
:
# macOS Homebrew/Linuxbrew
$ brew install ripgrep
# MacPorts
$ sudo port install ripgrep
# Windows Chocolatey
$ choco install ripgrep
# Windows Scoop
$ scoop install ripgrep
你可以在这里找到其他装置。
MS 的 VS 代码使用一个由 ripgre 驱动的搜索。默认情况下,它还会忽略隐藏的二进制文件。
行动中的超快速 ripgrep
蝙蝠
[bat](https://github.com/sharkdp/bat)
是一个cat
克隆,具有语法高亮和 Git 集成。bat
是用 Rust 和 woks 在 Windows/macOS/Linux 上写的。
# for macOS
brew install bat
bat
支持大量编程和标记语言的语法高亮显示:
带 md 文件的 bat
bat
集成了git
,并显示了对索引的修改(*上图左侧栏)。
时惠
是一个显示代码统计数据的程序。是cloc
的超快速替代。
tokei
显示文件数量、这些文件中的总行数以及按语言分组的代码、注释和空白。
tokei
可在 Mac、Linux 和 Windows 上使用。参*安装说明。
时惠。/输出
穰(等于 10 的 18 次方)
[exa](https://github.com/ogham/exa)
是 Unix 和 Linux 操作系统附带的命令行程序ls
的现代替代品。
要安装 homebrew run:
brew install exa
你可以在这个链接中找到其他装置。
示例输出
exa -T 输出
作者的 exa 快速参考
软驱
[fd](https://github.com/sharkdp/fd)
是find
的简单、快速且用户友好的替代品。[fd](https://github.com/sharkdp/fd)
在 Windows/macOS/Linux 上工作。
要安装 homebrew run:
brew install fd
对于其他安装,请参*此链接。
图片来自https://github.com/sharkdp/fd
procs
[procs](https://github.com/dalance/procs)
是用 Rust 写的ps
的替代。它创建树形视图,其输出是人类可读的格式。
你可以对多栏进行关键字搜索。procs
在 Windows(实验)/macOS/Linux 上工作。
请在此找到您的系统的其他安装。
按n
可以循环浏览标题,按a
可以升序排序,按d
可以降序排序。
# for macOS
brew install procs
procs 输出
procs -w 然后使用 n 代表下一个,d 代表降序
如何保持最新的最热门的 rust 命令行实用程序
网站不允许你按下载次数排序,所以你可以运行这段代码来保持更新。
我用 BeautifulSoup 抓取了网站,用熊猫在 Jupyter 笔记本上创建了一个数据框。
即使 lib.rs 有自己的排名算法,我还是按下载号排序的。
import requests
from bs4 import BeautifulSoup
import pandas as pd
URL = 'https://lib.rs/command-line-utilities'
page = requests.get(URL)
soup = BeautifulSoup(page.content, 'html.parser')
# find all package names
divs = soup.select('.h > h4')
names=[]
for div in divs:
names.append(div.text.strip())
# find all package downloads
metas = soup.select('.meta')
downloads=[]
for meta in metas:
if(mytitle:=meta.find(class_='downloads')):
parts = str(mytitle).split()[2].split('="')[1]
downloads.append(int(parts))
else:
# some libraries do not have downloads class
downloads.append(0)
# create a dataframe using pandas
data_tuples = list(zip(names,downloads))
df=pd.DataFrame(data_tuples, columns=['Name','Downloads'])
# sort by number of downloads
df = df.sort_values(by='Downloads', ascending=False)
df.head(20)
结果(截至 2020 年 5 月 5 日)
作者图片
有些包是针对 Rust 环境的,所以我选择了每个人都可以用于终端的包。
结论
还有更多 Rust 驱动的命令行实用程序不在这个列表中。我希望这些实用程序对您有用。
你最喜欢的是什么?或者你很受启发,想在 Rust 中开始构建自己的命令行应用程序。
通过 成为 会员,可以完全访问媒体上的每一个故事。
[## 通过将 Python 转换成 Rust 来学* Rust
Rust 基础入门教程
towardsdatascience.com](/learning-rust-by-converting-python-to-rust-259e735591c6) [## 你想学 Rust 但是不知道从哪里开始
Rust 初学者的完整资源
towardsdatascience.com](/you-want-to-learn-rust-but-you-dont-know-where-to-start-fc826402d5ba) [## Rust-Powered 命令行实用程序可提高您的工作效率
您腰带下的现代快速工具
towardsdatascience.com](/rust-powered-command-line-utilities-to-increase-your-productivity-eea03a4cf83a) [## 终端改造的终极指南
今天你将度过的最好的 11 分钟:程序员的终端提示
towardsdatascience.com](/the-ultimate-guide-to-your-terminal-makeover-e11f9b87ac99) [## 为您的数据科学项目安排任务的分步指南
macOS/Linux 中 cron 和 launchd 的完整指南
towardsdatascience.com](/a-step-by-step-guide-to-scheduling-tasks-for-your-data-science-project-d7df4531fc41)
AWS 和虚拟云计算
什么是云计算和 AWS 的初学者指南。
图片由 Unsplash.com 的伊恩·巴塔格利亚拍摄
这将是我关于 AWS 服务系列文章的第一篇。这将是一篇介绍性的文章,适合没有任何 AWS 或云服务知识的初学者。这篇文章旨在帮助那些刚接触云计算领域的人加深理解。本文将涵盖以下内容:
- 传统 IT 基础设施。
- 什么是云计算?
- 传统 IT 与云基础架构。
- 亚马逊网络服务介绍。
传统 IT 基础设施
当我们登录电脑,通过谷歌 Chrome 等网络浏览器浏览互联网,访问我们最喜欢的网站,如 YouTube.com 或 Facebook.com 时,很多事情都在幕后发生。许多不同的物理和虚拟、人类和非人类组件协同工作,使用户能够访问他们喜爱的网站或服务。
对于任何组织来说,无论规模大小,当他们必须通过 internet 向用户提供对任何服务的访问时,他们需要不同的组件来完成这项工作。基于 web 的服务的传统 IT 基础架构包括以下核心组件:
- 服务器。
- 存储和数据库。
- 网络和路由。
- 操作和监控整个基础架构所需的人力和空间。
- 维护、安全和灾难恢复。
如果某个特定服务的用户数量不是很大,这种安排非常有效。但是,随着这项服务越来越受欢迎,组织不断壮大,扩展物理基础设施并始终为用户提供即时、不间断的访问成为一项艰巨的任务。以脸书为例。大约有 26 亿用户在使用这个*台。他们拥有非常大的定制数据中心,2019 年全球有 15 个,超过 180,000 台服务器,使这 26 亿用户能够稳定、不间断地访问 Facebook.com。这些数据中心的核心是上述组件,即服务器、存储、网络和劳动力。
因此,我们可以看到,并不是所有的组织都能够负担得起这么多的物理硬件、人力和运营空间来开展日常活动。
什么是云计算
简而言之,云计算就像任何其他数据中心一样,拥有服务器、存储、网络、劳动力和空间,以及数据中心的所有其他必需品,只是不由您管理。一个受信任的独立方通过互联网将其整个基础架构借给客户,这些客户是那些负担不起内部基础架构或认为没有必要拥有内部基础架构的其他组织。
云计算是计算能力、数据库存储、应用程序和其他 IT 资源的按需交付,价格随用随付。根据您的需要访问任意多的资源,并几乎即时地调配正确类型和大小的计算资源。
云服务提供商为其客户提供传统内部 IT 基础架构中涉及的所有核心服务,以及在定价、服务可用性、扩展或缩减、安全性、维护等方面的附加服务和优势。客户通常以非常合理的成本支付他们所使用的东西,并且只需担心他们想要的基础架构类型及其虚拟部署。一切都可以通过云服务提供商提供的一些接口在互联网上访问,用户登录后只需部署他们想要的基础设施。
云服务提供商
这些年来,随着越来越多的组织放弃物理数据中心,转向云计算,云计算经历了巨大的增长。到 2020 年,前三大云服务提供商将是:
- 亚马逊(Amazon)将在 2020 年占据 60%的市场份额
- 微软(Azure)在 2020 年拥有 31%的市场份额
- 谷歌(GCP)在 2020 年占 9%
云*台的客户
在这些云服务上运行的一些受欢迎的服务是网飞、Airbnb、麦当劳、Activision、NASA、沃尔玛、福特、T-Mobile、迪士尼、高露洁、易贝、Spotify 等等。
云服务在组织中越来越受欢迎,新的创业公司围绕云服务构建他们的产品,而旧的组织迁移到云。云计算已经成为一个 10 亿美元的产业,仅 AWS 在 2019 年就赚了大约350 亿美元,并拥有超过100 万活跃用户。
云服务的类型
让我们来看看不同的提供商正在提供什么样的云服务:
- 基础设施即服务(IaaS): 它是云计算 It 的构建模块。允许您选择所需的网络、服务器、数据库和存储空间的类型。这是构建基于云的服务的最灵活的选择,并且可以很容易地与本地 It 并行。底层基础设施仍然必须由您来管理(尽管是虚拟的)。
- *台即服务(PaaS): 允许用户构建、管理和部署应用程序,而无需管理网络、服务器、数据库等底层基础设施。例如 AWS 弹性豆茎,Windows Azure,Heroku。
- 软件即服务(SaaS): 它是完全由所提供的服务提供和管理的完整服务。用户只需创建账户,配置和使用服务。例子包括谷歌应用程序(Gmail),Dropbox,Zoom。
下图有助于理解每种云服务向用户提供的抽象级别。
图片来自 azure.microsoft.com
传统 IT 与云基础架构
现在我们知道了传统 IT 和云的组成,我们可以很容易地对两者进行比较。与建立内部数据中心相比,云*台有几个额外的好处。下表可以帮助我们理解为什么云成为大多数人的首选:
传统 IT 与云基础架构
云基础架构的优势
拥有基于云的基础架构有以下优势:
- 按需付费:无需筹集大量资金购买基础设施。仅在需要时为您使用的内容付费。降低总体拥有成本和运营开支。
- 调配合适类型的资源:云让客户有机会在电力、存储、速度、网络等方面选择合适类型的资源,以满足其业务需求。
- 计量和自助服务:所有的资源使用都是计量的,只对用户使用的资源付费。此外,用户可以在任何时候自己使用服务提供商提供的任何服务,而无需依赖任何第三方。
- 灵活性和可扩展性:云环境非常灵活和有弹性。用户可以轻松地在不同种类的资源之间切换,以获得更高的处理能力,并根据他们面临的工作负载类型增加或减少节点数量。
- 高可用性和容错:由于云是基于全球基础设施的,因此资源会在多个数据中心之间自动调配,以便在发生灾难时提供高可用性和容错能力。
- 全球部署:客户可以在几分钟内轻松地在全球范围内部署其整个基础架构,并拥有全球业务。
- 无运营或维护成本:客户不必担心与员工、维护、租金、电力、冷却、硬件、许可等相关的任何成本。就这些费用而言,云对客户来说是经济高效的。
亚马逊网络服务简介
当我们谈论云计算时,亚马逊网络服务(AWS) 是第一个想到的名字。AWS 是云行业云计算的开创者。在 2004 年推出只有一项服务(SQS)的时候,他们已经走过了漫长的道路。毫无疑问,AWS 是最成熟的云服务提供商,也是目前云行业的市场领导者。
拥有超过 212 项服务,包括计算、存储、网络、数据库、分析、应用服务、部署、管理、移动、开发人员工具和物联网工具。AWS 在全球运营,在 42 个国家的 84 个城市拥有 216 个存在点 (205 个边缘位置& 11 个区域缓存)。
AWS 存在点。
AWS 允许客户以非常低的成本为各种各样的行业构建高度可伸缩、健壮和复杂的应用程序。他们的按需付费定价模式大幅降低了成本,随着用户群越来越大,AWS 通过其巨大的规模经济定价策略进一步降低了成本。
AWS 允许通过构建良好的基于 web 的控制台访问所有资源。其他方法包括通过 CLI、SDK 和 API 进行访问。
AWS 使用案例
AWS 提供所有三种类型的云服务,即 IaaS、PaaS 和 SaaS。AWS 的常*使用案例包括:
- 企业 IT、备份和存储。
- 大数据分析。
- 网站托管。
- 移动和社交应用。
- 游戏。
AWS 产品
AWS 拥有 200 多种服务,至少有一种产品符合您的需求
AWS 解决方案
AWS 还提供特定于领域的解决方案,您可以利用已经实现的解决方案,构建您的架构良好的应用程序
AWS 自由层:
如果你是一个初学者,刚刚开始使用云计算,AWS 提供一年的免费层(访问以下链接)。
获得免费的 AWS *台、产品和服务实践经验探索 60 多种产品并开始…
总结:
在本文中,我们了解了传统 IT 基础架构和云服务之间的区别。什么是云计算,它相对于传统 IT 的优势和附加好处,什么是 AWS?
如有任何疑问,请随时联系我。如果你喜欢这篇文章,请关注我,获取更多令人惊叹的内容(帮助我达到我的目标 500 名追随者)。链接到我的个人资料。
在介质上阅读 Furqan Butt 的文字。大数据工程师,Python 开发者。让我们连接…
medium.com](https://medium.com/@furqan.butt)
谢谢,继续看:)
AWS 和 Python:boto 3 包
Domo Arigato,AWS Boto
现在是 2020 年,云存储和计算世界很可能是未来几十年大多数企业的发展方向。拥有可扩展的存储和计算能力而无需购买物理设备的前景非常诱人。云的三大巨头是亚马逊网络服务(AWS)、微软 Azure 和谷歌云服务。
由于 Python 是最受欢迎的语言之一(在撰写本文时),所以无论您选择哪种服务,查看允许使用 Python 的工作数据工程师、数据科学家和机器学*科学家利用云的能力的包都是有意义的。微软 azure 有 Azure 包,谷歌有谷歌云包,AWS 有 boto3。本文将重点介绍 boto3。
设置它
首先,我们需要设置一些东西。AWS 确实提供免费服务,你可以免费注册。你需要一个用户名和令牌来通过后台登录 boto3,所以去 https://aws.amazon.com 注册一个免费账户吧。您还需要在您的 IDE、笔记本电脑等中安装 boto3。只需使用 pip 或 conda 安装 boto3 即可。
接下来,您需要通过 Amazon 的身份和访问管理控制台( IAM )创建一个用户。在这里,您可以添加用户、组和任何与访问相关的内容。您需要为自己创建一个角色,这样您就可以拥有一个用于凭证目的的永久授权令牌。
步骤 1:设置用户名和访问类型
第二步:设置权限(对于这篇文章,你只需要 SNS,S3,理解和 Rekognition)。确保为每个选项选择完全访问权限。如果这是一个个人帐户,你可以给自己所有亚马逊服务的完全访问权限,只需在搜索中输入 FullAccess 并选中 all。
步骤 3:添加标记(可选)—这些是键:值对,它们是用于更好控制的附加标识符
完成上述步骤后,只需确认设置,用户就会收到访问密钥 id 和秘密访问密钥。在您的本地计算机上启动 AWS 会话将需要这些。
开始会话
这是你节省时间的地方。启动会话就像打开您的 IDE 或笔记本一样简单,只需使用以下命令:
import boto3
s3 = boto3.client(‘service_name’, region_name=’region_name’,
aws_access_key_id=key,
aws_secret_access_key=password)
对于上下文:“服务名称”是您正在连接的 AWS 服务(S3、SNS、理解、Rekognition 等),区域是您正在连接的计算服务的区域。该地区很重要,因为这将决定成本。请访问 AWS 网站获取服务列表,并访问https://how to . lintel . in/list-of-AWS-regions-and-avail ability-zones/获取地区列表。只有用户拥有权限的服务才可以访问。抱歉,到目前为止,它不需要服务列表,所以你需要一次加载一个。
服务和功能示例。
S3 。AWS 的简单存储解决方案。这是创建和存储文件夹和文件的地方。这是一个非关系型的存储空间,所以它需要许多不同类型的文件。AWS 对文件夹的术语是“桶”,文件被称为“对象”。以下是 S3 的几个函数:
import boto3, login into ‘s3’ via boto.client#### create bucketbucket = s3.create_bucket(Bucket=’bucket_name’)
#### list bucketbucket_response=s3.list_buckets() #requests a list of buckets
buckets = bucket_response[‘Buckets’] #sets bucket list from Buckets key
print(buckets)
#### delete bucketresponse = s3.delete_bucket(Bucket=‘bucket_to_be_deleted’)
#### upload objects3.upload_file(Filename=’local_file_path’,
Bucket = ‘bucket_name’,
Key = ‘object_name’,
ExtraArgs={‘ACL’:’acl_type’, #sets access control limit type
‘ContentType’:’content_type’} #to specify type of content (html, jpg, etc.)
#### list objects#obtain many files
response =s3.list_objects(Bucket=’bucket_name’,
MaxKeys=2 #maximum number of files to list
Prefix=’prefix_of_file_for_search’)
print(response)
#obtain single file
response =s3.head_object(Bucket=’bucket_name’, Key=’file_name’)
print(response)#### download filess3.download_file(Filename=’local_path_to_save_file’,Bucket=’bucket_name’,Key=’file_name’)
#### delete file
s3.delete_object(Bucket=’bucket_name’,Key=’file_name’)
SNS。AWS 的简单通知系统。该服务将根据管理员设置的条件向组和用户发送通知。以下是社交网络的一些功能:
import boto3, login into ‘sns’ via boto.client#### create topicresponse=sns.create_topic(Name=’topic_name’)[‘TopicArn’] #sets topic and grabs response
#### list topicsresponse=sns.list_topics()
#### delete topicssns.delete_topic(TopicArn=’full_topic_arn_value’)
#### create subscriptionresp_sms = sns.subscribe(TopicArn = topic_name,
Protocol='delivery_method,
Endpoint=’phone_email_etc’)
#### list subscriptionsresponse = sns.list_subscriptions_by_topic(TopicArn = topic_name)
subs = pd.DataFrame(response['Subscriptions']) #converts list to a df#### delete subscriptionsns.unsubscribe(SubscriptionArn=’full_sub_arn’)
#### send messages##### publish to a topicresponse = sns.publish(TopicArn = topic_arn,
Message = ‘body of message’ #can use string formatting,
Subject = ‘Subject line’)
##### sending single smsresponse = sns.publish(PhoneNumber = ‘phone_number’,Message = ‘body of message’) #can use string formatting
领悟。理解是 AWS 的自然语言处理服务。它可以确定文件是用什么语言编写、翻译和执行情感分析。这些功能如下:
#### text translatetranslate = ‘translate’ via boto.client
response=translate.translate_text(Text=variable,’string’,etc.,
SourceLanguageCode = ‘auto’,
TargetLanguageCode = ’language_to_translate_to’)
#### detecting languagecomprehend = ‘comprehend’ via boto.client
response=comprehend.detect_dominant_language(Text=variable,’string’,etc.,)
#### sentiment analysiscomprehend = ‘comprehend’ via boto.client
response=comprehend.detect_sentiment(Text=variable,’string’,etc.,LanguageCode=’language’)
重新认识。这是 AWS 的图像识别服务。它实际上在检测物体和从图像中提取文本方面做得非常好。以下是一些函数:
#### object detectionimport boto3, login into ‘s3’ via boto.client
#upload file where images are located
rekog = ‘rekognition’ via boto.client
response=rekog.detect_labels(Image=’image_name’:
{‘Bucket: ’bucket_name’, ’Name’: ’file_name’},
MaxLabels = maximum # of objects to detect
MinConfidence = set confidence level of classification)
#### text detectionimport boto3, login into ‘s3’ via boto.client
#upload file where images are locatedrekog = ‘rekognition’ via boto.clientresponse = rekog.detect_text(Image=’image_name’:
{‘Bucket: ’bucket_name’, ’Name’: ’file_name’},
MinConfidence = set confidence level of classification)
显然,有许多服务和更多的功能需要花相当长的时间来总结。这将给您一个良好的开端,并让您有机会通过 Python 探索 AWS 服务。像往常一样,这些项目的回购可以通过我的 Github 在https://github.com/Jason-M-Richards/Data-Science-Toolkit获得。
AWS Athena 和 Glue:查询 S3 数据
AWS Glue 是一个 ETL 服务,允许数据操作和数据管道管理。
在这个特定的例子中,让我们看看如何使用 AWS Glue 将 csv 文件从 S3 存储桶加载到 Glue 中,然后在 Athena 中对这些数据运行 SQL 查询。
下面是 S3 存储桶中的 CSV 文件,如下图所示——数据集本身可以从本文末尾引用的 GitHub 存储库中获得。
来源:亚马逊网络服务
在 AWS Glue 中设置爬虫
爬行器用于从源中提取数据,分析数据,然后确保数据符合特定的模式——或定义表中每个变量的数据类型的结构。
定义了 crawler,并设置了数据存储、IAM 角色和调度。
来源:亚马逊网络服务
crawler 将需要一点时间来提取表,这取决于数据的大小。在这里,爬虫被安排按需运行。
来源:亚马逊网络服务
但是,也可以将 crawler 设置为按特定的时间表运行。
来源:亚马逊网络服务
当 S3 存储桶中的数据定期更新或更改时,这一点尤其重要——必须确保 Glue 中的数据保持最新。
该表现在显示在 AWS 胶中。这里,模式被自动检测。
来源:亚马逊网络服务。
但是,也可以通过选择编辑模式,然后手动定义每个变量的数据类型来编辑模式:
来源:亚马逊网络服务。
雅典娜中的查询
现在这个表是用 AWS Glue 表示的,让我们试着运行一些查询!
Athena 是一项 AWS 服务,允许在 S3 对数据运行标准 SQL 查询。因为已经在 Glue 中建立了模式,并且表已经加载到数据库中,所以我们现在只需要查询我们的数据。
正在分析的特定数据集是酒店预订数据集。
让我们使用一些 SQL 查询来执行以下操作:
- 从表中选择所有列,其中 Country 列下的所有条目都以字母 p 开头。
- 计算*均提前期,其中国家= 'PRT '(葡萄牙)。
- 计算*均 ADR 值,其中 Country = 'GBR '(英国),且细分市场属于直接类别。
- 最后,让我们根据国家、预订的房间类型和客户类型来订购桌子。
查询 1
select * from table where country like ‘P%’;
来源:亚马逊网络服务
查询 2
select avg(leadtime) from table where country=’PRT’;
来源:亚马逊网络服务
查询 3
select avg(adr) from table where country=’GBR’ and marketsegment=’Direct’;
来源:亚马逊网络服务
查询 4
select * from table order by country, reservedroomtype, customertype;
来源:亚马逊网络服务
这些查询也可以保存起来供以后使用。让我们保存查询 3 作为一个例子。
来源:亚马逊网络服务。
来源:亚马逊网络服务
结论
在本例中,您看到了:
- 如何用胶水在 S3 桶中抓取数据
- 在 Glue 中编辑表模式
- 使用 Athena 运行 SQL 查询
非常感谢您的参与,相关的数据集可以在 MGCodesandStats GitHub 存储库中找到。
您还可以在 michael-grogan.com 的找到我的数据科学内容。
免责声明:本文是在“原样”的基础上编写的,没有担保。本文旨在提供数据科学概念的概述,不应以任何方式解释为专业建议。
AWS DataBrew —一款全新、经济的数据准备工具
入门
数据分析和转换工具的演练
2020 年 11 月 11 日,AWS 宣布发布 Glue DataBrew。专注于数据准备,它提供了 250 多个函数来帮助。我喜欢所有的数据,所以我检查了一下。有两种主要类型的功能,数据配置文件和转换。我将介绍设置和使用这两个特性的步骤。
[## 介绍 AWS Glue DataBrew:可视化数据准备工具,用于清理和标准化高达 80%的数据…
AWS Glue DataBrew 提供了 250 多种预构建的转换来自动化数据准备任务(例如,过滤…
定价
总要考虑成本。每节互动课 1 美元。转换作业每节点小时 0.48 美元。最好的部分是,它完全是随用随付。这使得该工具对每个人来说都非常容易使用和负担得起,甚至是休闲爱好者。
加载您的数据
从 AWS 控制台,假设您已经设置了一个帐户,您可以直接进入 AWS DataBrew。有一个很好的界面来分析和转换数据。第一步是创建数据集。为了这个演示,我从纽约加载了一个开放的崩溃数据集到 S3。
从这里开始—作者截图
当我把我的数据加载到 S3 时,我很高兴看到了红移和 RDS 的直接联系。我希望很快看到更多的连接。
连接到您的数据—作者截图
运行数据配置文件作业
创建数据集后,您可以选择运行分析作业。它有一个简单的设置。您需要确定输出的位置。
数据集已创建—作者截图。
概要职务参数—作者截图
我必须创建一个新的数据 Brew IAM 策略和角色。你得到了完成这个过程所需的信息,所以还不算太糟。如果能够在同一个屏幕中创建策略和角色,那就太好了。
输入信息后,点击创建并运行作业。
数据配置文件结果
数据配置文件在数据集中的前 20,000 行上运行。这花了 2 分 2 秒的时间。如果您的数据恰好在第 20k 行之后变得疯狂,它不会显示在此报告中。这是一个基本只看一眼,不能全面分析。
对于您的数字数据,将为您提供相关性。我有大部分的字符串,所以这不是那么令人印象深刻。
点击放大—作者截图。
对于每一列,都提供了基本的数据分析。这是其他工具集的典型,可能有点偏轻。
点击放大—作者截图
提供了数据沿袭视觉,其被理解为:
作者截图
现在我们可以创建一个数据转换项目。
数据集屏幕中的一个选项是从数据集创建一个项目。一个项目由一个“配方”组成,它是数据转换工作中的一系列步骤。这确保了更新多个数据集时的一致性。权限与您的数据集相同。
该界面允许您以网格或模式格式查看数据。我更喜欢模式显示。
格子
网格布局—作者截图
(计划或理论的)纲要
模式布局—作者截图
向配方添加步骤
你可以给你的“食谱”添加不同的步骤我在下面的列表中注意到一些有趣的。能够一键处理、区分大小写、删除特殊字符和输入缺失值非常有用。这比在 python 中设置相同的逻辑要快得多。
大写 _ 大小写,格式 _ 日期,小写 _ 大写,大写 _ 大小写,句子 _ 大小写,ADD _ 双引号,ADD _ 前缀ADD _ 单引号ADD _ 后缀,EXTRACT _ BETWEEN _ 分隔符,EXTRACT _ BETWEEN _ 位置 REPLACE_WITH_EMPTY ,REPLACE _ WITH _ LAST _ VALID, REPLACE_WITH_MEDIAN , FLAG_COLUMN_FROM_NULL ,REPLACE _ WITH _ MOST _ frequency,数学函数,,文本函数,日期和时间函数,
提供建议
一个很好的特性是推荐标签。对于突出显示的列,详细介绍了建议的转换。
“推荐”选项卡—作者截图
示例—一个热门分类列
为多类别列设置一次性列是为机器学*准备数据时的一项常*任务。有几个 Python 库可以用来完成这项任务。使用这个界面更加容易。这个工具似乎有一些不适用的限制。(样本数据集超过 10 个类别)。
一键编码—作者截图
点击应用。Boom —新列。就这么简单。
点击放大—作者截图。
公布你的食谱
发布你的食谱供再次使用。好东西。
作者截图
结论
虽然我怀疑我是否需要数据分析功能,但我肯定会使用转换“配方”作业。“随用随付”选项真正将 AWS 与市场上一些常*的大型企业数据准备工具区分开来。该工具中提供了一些样本数据集,请立即试用!
AWS DeepRacer:强化学*的有趣方式
欢迎来到 AWS DeepRacer 之旅
最近,我参加了一个训练营,将开始我学*强化学*(RL)的旅程。这个训练营是由亚马逊网络服务(AWS)和雅加达机器学*(JML)举办的。在接下来的三个月里,我们将接受 AWS 经验丰富的代表的指导,学*和应用强化学*理念。
这将是一个令人兴奋的旅程,因为我们将使用 AWS DeepRacer 以有趣的方式学*强化学*,并带上您!
尼古拉斯·佩罗尔在 Unsplash 上拍摄的照片
了解 AWS DeepRacer
我们先从了解什么是 AWS DeepRacer 开始。DeepRacer 是 AWS 将强化学*带到每个开发者手中的举措之一。这项倡议带来了一种有趣的学*机器学*的方法,特别是 RL,使用自动驾驶赛车,3D 在线赛车模拟器来建立你的模型,以及比赛。
AWS 深赛车
AWS DeepRacer Evo 是一辆 1/18 比例的自动驾驶赛车,由强化学*驱动。这辆车配有左右前置摄像头,组成立体摄像头。立体摄像机可以帮助车辆学*图像中的深度信息,这些信息可用于感知和避免轨道上的物体被接近。这辆车还有一个向后的激光雷达传感器,用于检测车辆后面和旁边的物体。立体相机和激光雷达传感器的结合实现了物体回避和短兵相接的比赛。
AWS DeepRacer Evo 汽车。图片由 AWS DeepRacer 提供
AWS DeepRacer 控制台
作为开发人员,我们可以在 3D 在线赛车模拟器中训练、评估和调整 RL 模型。这个旅程可以从学* RL 的基础开始。AWS 提供了易于理解的学*材料来掌握基础知识。
模型创建流程。作者图片
然后,我们可以开始在 AWS 控制台中构建、训练和评估我们的模型。为了使它更容易,我们还可以开始使用预构建模型示例。AWS DeepRacer 控制台也为我们提供了执行此类任务的能力:
- 创建 RL 训练作业,以创建具有特定奖励函数、优化算法、超参数和环境的模型。
- 选择一个轨道来训练和评估一个模型。
- 克隆一个训练模型,通过调整超参数来优化模型的性能。
- 下载部署到 AWS DeepRacer 车辆的模型,以便它可以驾驶。
- 提交一个模型到一个虚拟的比赛中,并与其他模型进行比较。
AWS 深度赛车联盟
一旦我们的模型准备好了,我们就可以将模型部署到 AWS DeepRacer 的在线或离线 AWS DeepRacer 联赛中,从而有机会赢得 AWS DeepRacer 冠军杯。
约书亚·戈尔德在 Unsplash 上拍摄的照片
2020 年 AWS DeepRacer 联赛有两种比赛方式。首先是在线虚拟电路,它允许你在世界任何地方进行比赛。AWS 还提供免费等级,使您能够进行 10 小时的培训。所以你可以免费进入联盟。第二个是顶峰赛道,在这里你可以和其他车手在顶峰比赛。
今年,联盟提供了三种比赛形式。它们是头对头,物体回避和计时赛。
AWS 深赛车联盟比赛格式。作者图片
- 在面对面排位赛中,我们需要完成几圈,同时避免 AWS 机器人赛车在赛道上移动。月底,前 32 名选手将被列入淘汰名单,我们需要与其他选手展开正面交锋。
- 在物体躲避比赛中,我们需要完成赛道,同时躲避路上指定数量的障碍物。最快的赛车手将晋级争夺冠军奖杯。
- 在计时赛比赛中,我们需要在赛道上完成规定的圈数。谁跑得最快,谁就能晋级争夺冠军奖杯。
强化学*
现在,让我们看看车轮后面,了解强化学*的基本概念。RL 是一种先进的机器学*(ML)技术,采用与其他机器学*方法非常不同的方法来训练模型。它的超级能力是,它可以在不需要任何标记训练数据的情况下学*非常复杂的行为,并可以在为长期目标优化的同时做出短期决策。
RL 基础
在强化学*中,一个代理将探索一个环境来执行任务,采取行动并产生好的结果,避免坏的结果。该模型将从经验中学*,随着时间的推移,它将能够识别哪些活动会带来最佳的回报。
这里有一个有趣的例子来解释强化学*。在实验中,给鸡的任务是只钉粉红色的纸。当小鸡钉住正确的纸时,小鸡会被奖励食物。当桌子上引入其他颜色时,挑战变得更加有趣。有趣的是,这只鸡仍然设法只盯住粉红色。
AWS DeepRacer 中的重要 RL 术语
AWS DeepRacer 中的重要术语。作者图片
有几个重要术语可用于探索这些想法,并理解它们与 AWS DeepRacer 的关系:
- 代理人。代理由需要培训的 AWS DeepRacer 车辆代表。更具体地说,它体现了控制车辆、接受输入和决定行动的神经网络。
- 环境。该环境包含一条定义车辆行驶路线的轨道。代理探索环境以收集数据来训练底层神经网络。
- 状态。状态表示代理在某个时间点所处环境的快照。前置摄像头捕捉车辆上的这种状态。
- 动作。动作是代理在当前状态下做出的决定。对于 AWS DeepRacer,动作对应于车辆以特定速度和转向角度移动。
- 奖励。奖励是当代理在给定的状态下采取行动时作为反馈给代理的分数。在训练 AWS DeepRacer 模型时,奖励由一个奖励函数返回。一般来说,您定义或提供一个奖励函数来指定在给定的状态下代理应该采取什么样的行动。
- 剧集。一集是代理终止之前的一组过程。
如何训练车辆
在这一点上,我们将在高层次上探索如何培训 AWS DeepRacer。训练过程是一个迭代的 tass。在模拟器中,代理将探索环境并获得经验。收集的经验用于更新模型,更新的模型用于获得更多的经验。
我们将在一个简化的环境中看到这些示例,以便真正了解培训过程是如何进行的。
简化的学*过程。作者图片
在这个例子中,我们希望车辆以最短的路径从起点到终点,而不离开赛道。然后我们可以将环境简化为一个正方形网格。每个方块代表一个单独的状态,我们将允许车辆在面向目标的方向上上下移动。
我们可以给网格中的每个方块分配一个分数,以决定激励什么行为。这里,我们将轨道边缘的方块指定为“停止状态”,这将告诉车辆它已经偏离了轨道并且失败了。因为我们想让车辆学会沿着轨道中心行驶,所以我们为中心线上的方块提供高奖励,而在其他地方提供低奖励。
在强化训练中,车辆将从探索网格开始,直到它移动出界或到达目的地。当它四处行驶时,车辆从我们定义的分数中累积奖励。这个过程被称为插曲。学*将需要一些迭代,以使车辆能够获取知识。
代理人需要探索,看看在哪里可以获得最高的回报,然后才能使用或利用这些知识。随着代理获得越来越多的经验,它学会留在中央广场,以获得更高的奖励。
随着更多的经验,代理变得更好,最终可以可靠地到达目的地,并找到最高的奖励。
结论
到目前为止,你应该已经知道什么是 AWS DeepRacer,以及 AWS DeepRacer 车辆、训练控制台和 AWS DeepRacer League 等每个组件。您还将了解强化学*的基础知识及其在 AWS DeepRacer 中的应用,包括重要术语和培训的执行方式。
文献学
- https://aws.amazon.com/deepracer/
- https://docs . AWS . Amazon . com/deep racer/latest/developer guide/what-is-deep racer . html?ICM PID = docs _ deep racer _ console
- AWS 强化学*简介
关于作者
Bima 是一名数据科学家,他总是渴望扩展自己的知识和技能。他毕业于万隆技术学院和新南威尔士大学,分别是采矿工程师。然后他通过 HardvardX、IBM、Udacity 等的各种在线课程开始了他的数据科学之旅。目前,他正与 DANA Indonesia 一起在印度尼西亚建立一个无现金社会。
如果您有任何疑问或任何要讨论的话题,请通过 LinkedIn 联系 Bima。
AWS Glue 101:您需要了解的全部内容
什么是胶水?解释了完整的 ETL 管道
有没有想过大型科技公司是如何设计他们的生产 ETL 管道的?有兴趣了解如何无缝抓取数据的 TB、ZB 并高效解析到数据库或其他存储,以便于数据科学家和数据分析师使用吗?
在本帖中,我将详细解释(用图形表示!)使用 AWS 服务(Glue、S3、红移)的 ETL 过程的设计与实现。任何没有 AWS Glue 或 AWS 堆栈经验或接触过 AWS Glue 或 AWS 堆栈(甚至没有深入的开发经验)的人都应该很容易理解。对于那些对使用 AWS Glue 感兴趣的人来说,这篇文章可以作为一个很好的入门指南。
在开始本演练之前,让我们简要回答三(3)个常*问题:
AWS 胶水到底是什么?
使用胶水有什么特点和优势?
真实世界的场景是什么?
什么是 AWS 胶水?
那么什么是胶水呢?AWS Glue 只是一个无服务器的 ETL 工具。ETL 指的是大多数数据分析/机器学*过程中通常需要的三(3)个过程:提取、转换、加载。从源中提取数据,将数据转换成适合应用程序的方式,然后将数据加载回数据仓库。AWS 帮助我们创造奇迹。AWS 控制台 UI 为我们提供了将整个任务执行到底的简单方法。不需要额外的代码脚本。
AWS 胶水的成分
- 数据目录:数据目录保存元数据和数据的结构。
- 数据库:用于创建或访问源和目标的数据库。
- 表:在数据库中创建一个或多个表,供源和目标使用。
- 爬虫和分类器:爬虫用于使用内置或定制的分类器从源中检索数据。它创建/使用在数据目录中预定义的元数据表。
- 作业:作业是执行 ETL 任务的业务逻辑。在内部,Apache Spark 用 python 或 scala 语言编写了这个业务逻辑。
- 触发器:触发器按需或在特定时间启动 ETL 作业执行。
- 开发端点:它创建了一个可以测试、开发和调试 ETL 作业脚本的开发环境。
为什么要用 AWS 胶水?
胶水对我们有什么好处?以下是在你自己的工作场所或组织中使用它的一些优势
- AWS 使用爬虫扫描所有可用的数据
- 最终处理的数据可以存储在许多不同的地方(亚马逊 RDS、亚马逊红移、亚马逊 S3 等)
- 是云服务。内部基础设施不需要资金。
- 这是一个划算的选择,因为它是一个无服务器的 ETL 服务
- 它很快。它马上给你 Python/Scala ETL 代码。
AWS 胶水的生产用例
这里有一个使用 AWS 胶水的实际例子。
一个游戏软件每天会产生几 MB 或几 GB 的用户游戏数据。从软件中收集用户生成数据的服务器每 6 小时将数据推送到 AWS S3 一次(JDBC 连接使用亚马逊 S3、亚马逊 RDS、亚马逊红移或任何外部数据库连接数据源和目标)。
我们公司希望根据用户资料预测该剧的时长。为了执行这项任务,数据工程团队应该确保获得所有的原始数据,并以正确的方式对其进行预处理。Glue 提供了 Python SDK,我们可以在其中创建一个新的 Glue Job Python 脚本来简化 ETL。代码运行在 Spark(一个分布式系统,可以使过程更快)之上,它是在 AWS Glue 中自动配置的。由于 spark,数据将被分成小块,并在多台机器上同时并行处理。
提取— 该脚本将把 S3 存储桶中的所有使用数据读取到一个数据帧中(您可以把它想象成 Pandas 中的一个数据帧)
转换— 假设原始数据*均每秒包含 10 个不同的日志。分析团队希望以特定的逻辑每 1 分钟汇总一次数据。
加载— 将处理后的数据写回到另一个 S3 存储桶,供分析团队使用。
项目演练
对于项目的范围,我们将使用来自电信流失数据集的样本 CSV 文件(数据包含 20 个不同的列。数据集的目标是二元分类,并且目标是基于每个人的信息来预测每个人是否会继续订阅电信。我在这个演示中使用的数据和数据集的描述可以通过点击这个 Kaggle 链接下载。
1.创建一个 IAM 角色来访问 AWS Glue + EC2 + CloudWatch + S3
作者照片
您需要一个适当的角色来访问您将在此过程中使用的不同服务。IAM 角色类似于 IAM 用户,因为它是一个 AWS 身份,权限策略决定该身份在 AWS 中可以做什么和不可以做什么。当您获得一个角色时,它为您的角色会话提供临时安全凭证。你可以在这里找到更多关于我的角色的信息
- 打开亚马逊 IAM 控制台
- 点击角色 → 创建角色。
- 从“选择将使用此角色的服务”中选择粘合服务
- 从“选择您的用例部分选择胶水
- 从附加权限策略部分选择“AWSGlueServiceRole”。
- 点击下一步:标签。将添加标签部分留空。创建角色。
- 您的角色现在可以完全访问 AWS Glue 和其他服务
2.上传源文件到亚马逊 S3
作者照片
- 在亚马逊 S3 控制台上,点击创建一个可以存储文件和文件夹的存储桶。
作者照片
- 输入一个桶名,选择一个区域,点击下一个
- 剩余的配置设置现在可以保持为空。点击下一个的来创建你的 S3 桶。
- 在您的存储桶中创建一个新文件夹,并上传源文件
- (可选)在将数据加载到 bucket 之前,您可以尝试使用 python 中的几个库将数据的大小压缩成不同的格式(例如 Parquet)
3.启动 AWS 胶水数据库
作者照片
为了将数据添加到粘合数据目录中,这有助于保存元数据和数据结构,我们需要将粘合数据库定义为逻辑容器。
所以我们需要初始化胶水数据库
4.创建并运行胶水爬虫
由于我们已经准备好了胶水数据库,我们需要将我们的数据输入到模型中。因此,我们正在尝试这样做:我们将创建爬行器,基本上扫描指定 S3 桶中的所有可用数据。爬虫自动识别最常*的分类器,包括 CSV、JSON 和 Parquet。
作者照片
- 在 AWS 胶水控制台的左窗格中,点击爬虫- >添加爬虫
- 点击蓝色的添加爬虫按钮。
- 将爬虫命名为、并保留不变,用于“指定爬虫类型”
作者照片
- 在数据存储中,选择 S3 并选择您创建的存储桶。向下钻取选择读取文件夹
作者照片
- 在我的角色中,选择您在上面创建的角色
- 现在将频率设置为“按需运行”。您可以随时根据自己的兴趣更改爬虫计划。
- 在输出中,指定您在上面创建的胶水数据库( sampledb )
作者照片
- 然后,生成一个胶水爬行器,它读取指定 S3 桶中的所有文件
- 点击复选框,点击运行爬虫运行爬虫
- 完成后,您应该会看到它的状态为“停止”。并且指定了“上次运行时间”和“添加的表”。
作者照片
- 然后,左侧窗格中的数据库 → 表让您验证这些表是否是由爬虫自动创建的。
5。定义涂胶作业
有了最终的表,我们知道创建粘合作业,它可以按计划、按触发或按需运行。创建 Glue jobs 的有趣之处在于,它实际上可以是一个几乎完全基于 GUI 的活动,只需点击几下按钮就可以自动生成必要的 python 代码。但是,我将做一些编辑,以便综合多个源文件并执行就地数据质量验证。默认情况下,Glue 使用 DynamicFrame 对象来包含关系数据表,并且它们可以很容易地来回转换为 PySpark 数据帧以进行自定义转换。
请注意,在这一步,如果来自爬行器的数据变大,您可以选择启动另一个数据库(即 AWS RedShift)来保存最终数据表。对于项目范围,我们跳过这一步,将处理后的数据表直接放回另一个 S3 存储桶
作者照片
- 在左侧窗格中,点击工作,然后点击添加工作
作者照片
- 给起个名字,然后选择之前为 AWS Glue 创建的 IAM 角色
- 选择类型的 Spark 选择 Spark 2.4,胶版的 Python 3
- 您可以在安全配置、脚本库和作业参数的最大容量字段中编辑 DPU(数据处理单元)值的数量(可选)。
- 剩余的配置是可选的
- 从选择数据源部分选择一个数据源表。您只能选择一个数据源。
作者照片
- 给 AWS 红移增加一个 JDBC 连接。我们需要选择一个位置来存储最终处理后的数据。如果您有数据库,可以选择现有的数据库。或者你可以写回 S3 集群。对于本教程,我们将继续使用默认映射。业务逻辑也可以在以后对此进行修改。
作者照片
- 通过选择最近创建的作业名称打开 Python 脚本。点击动作- >编辑脚本。
- 左窗格显示了 ETL 过程的可视化表示。右侧窗格显示脚本代码,在它的正下方,您可以看到正在运行的作业的日志。
- 通过单击运行作业保存并执行作业。
作者照片
- 我们在运行脚本后获得历史记录,并在 S3 中填充最终数据(或者,如果我们将红移作为最终数据存储,则为 SQL 准备好数据)
结论
总而言之,我们已经构建了一个完整的 ETL 过程:我们创建了一个 S3 桶,将我们的原始数据上传到桶中,启动 glue 数据库,添加一个 crawler 来浏览上述 S3 桶中的数据,创建一个 GlueJobs,它可以按计划、按触发或按需运行,最后将数据更新回 S3 桶。
可以做的额外工作是根据业务需求修改 GlueJob 阶段提供的 Python 脚本。
(即改进预处理以缩放数值变量)
总的来说,上面的结构将让您开始在任何业务生产环境中设置 ETL 管道。
额外资源
有关学*其他数据科学主题的更多详细信息,下面的 Github 存储库也会有所帮助。它包含易于遵循的代码,让你开始解释。
- 生产中的 AWS sage maker
展示如何使用 Amazon SageMaker 及其 ML/DL 算法解决业务问题的端到端示例。 - PySpark
函数和实用程序,带有真实世界的数据示例。可以用来构建一个完整的数据建模的 ETL 过程 - 推荐系统
py torch 中推荐系统的生产级实现。克隆 repo 并通过运行“main.py”开始训练 - 自然语言处理(NLP)
Python 中几种自然语言处理方法的完整实现示例。按照学*的复杂程度排序
关于作者
贤俊是一名拥有统计学学位的数据极客。他喜欢分享数据科学/分析知识。在 LinkedIn 上给他发消息联系。
参考: 【1】杰西·弗雷德里克森,https://towardsdatascience . com/AWS-Glue-and-you-e2e 4322 f 0805
【2】Synerzip,https://www . Synerzip . com/blog/A-Practical-Guide-to-AWS-Glue/《AWS 胶水实用指南》
【3】肖恩·奈特,https://towards
AWS Glue:亚马逊的新 ETL 工具
什么是 AWS 胶水,需要吗?
Amazon AWS Glue 是一个完全托管的基于云的 ETL 服务,在 AWS 生态系统中可用。它是由亚马逊 AWS 于 2017 年 8 月推出的,大约在同一时间,由于公司无法成功实施大数据项目,大数据的宣传逐渐消失。2015 年, Gartner 曾做出一个著名的预测,到 2017 年将有 60%的大数据项目失败,尽管其分析师后来声称这个数字是保守的,实际失败率可能高达 85%。
在同一份报告中,在失败背后的许多因素中,Gartner 强调,缺乏正确的 IT 和基础架构技能将是此类大数据分析项目失败背后的一个关键因素。如果我们详细阐述这一点,任何大数据项目的主要挑战之一是将来自多个来源的各种数据纳入中央数据湖或数据仓库。这通常需要实现和管理复杂的 ETL 过程,这不是一件容易的事情,并且可能成为一个失败点。因此,亚马逊 AWS Glue 在 2017 年推出不仅仅是一个巧合,而是试图通过在其云上提供 ETL 服务来利用脆弱的 ETL 市场。
在我们深入探讨 Amazon AWS Glue 之前,让我们首先了解 ETL 到底是什么,以及与之相关的挑战是什么。然后我们来看看 AWS Glue 及其特性。最后,我们将讨论构建 ETL 管道的另一种解决方案:数据虚拟化。
什么是 ETL 过程?
ETL 代表提取、转换和加载,在这个过程中,从各种来源收集数据并加载到数据仓库或数据湖的目标数据库中。整个过程的三个主要步骤是:
提取
在此过程中,来自各种来源的数据被提取出来并放入一个临时区域。数据既可以从同类来源提取,也可以从异类来源提取。例如,您很有可能从 SQL 数据库中提取一些数据,从 NoSQL 数据库中提取一些数据用于您的数据湖。
改变
在第一步中提取的数据通常保存在一个临时区域中,以对其进行清理和预处理,从而使来自不同来源的数据保持一致,并确保它们符合我们的目标数据库的设计。例如,在从不同国家提取销售数据时,在将数据插入目标数据库之前,将不同的货币转换成一种通用货币(如美元)是有意义的。
负荷
在这个最后的步骤中,经过清理和预处理的数据最终被加载到数据湖或数据仓库的目标数据库中。现在,您可以使用这些数据来执行分析并从中获得*解。
ETL 流程的主要挑战
- ETL 已经以某种形式存在了很多年。在大数据爆炸之前,ETL 被认为是一个批处理过程,通常只需要处理同质数据。那时候事情很简单,但是现在时代变了,数据量大、速度快、种类多,而且人们越来越期望执行接近实时的 ETL。所有这些都需要非常复杂的 ETL 设计,这对 ETL 开发人员来说是一种新的挑战。
- ETL 日益增长的复杂性要求更复杂的基础设施、服务器和资源。一个大企业仍然能够负担得起投资于内部强大的服务器,但是较小的公司可能并不总是发现花费来构建强大的 ETL 服务器是容易的。
- ETL 不是奖励,而是开销。这是因为最终目标是提取报告、有意义的*解、对数据执行分析,而 ETL 只是先决条件。这份 2015 年的旧调查提到,三分之一的受访者表示,他们将 50%-90%的时间用于数据准备,以使其“为分析做好准备”。因此,矛盾的是,主要目标是执行分析的公司最终会花费更多的时间和金钱将数据提供给分析师和数据科学家。
该图显示了 AWS Glue ETL 工具的通用工作流(图片由作者创建)
亚马逊 AWS 胶水简介
正如我们在介绍中所讨论的,Amazon AWS Glue 是一个完全托管的、无服务器的 ETL 服务,可以在 AWS cloud 上使用。这里的“托管和无服务器”是指 AWS Glue 将根据需要自行处理 AWS 云上的服务器和资源供应。所以作为用户,你不需要担心基础设施部分。
让我们借助它的架构来更深入地看看 AWS Glue。
AWS Glue 架构由三个主要部分组成
- AWS 胶水数据目录
- ETL 引擎
- 调度程序
AWS 粘合数据目录
AWS Glue 在爬虫的帮助下自动浏览所有可用的数据存储,并将它们的元数据保存在一个名为 Data Catalog 的中央元数据存储库中。在实际的 ETL 过程中会用到这些元数据信息,除此之外,目录还保存了与 ETL 作业相关的元数据。
可以有一个或多个数据存储,如 Amazon RDS、Amazon Redshift、Amazon S3 和其他运行在 EC2 实例上的数据库。爬行完成后,它会创建一个来自各种来源的数据目录,并呈现一个统一的视图,可以使用 Amazon Athena 或 Amazon Redshift Spectrum 进行查询。
如果您在 Amazon EMR 上处理大数据,这个目录也可以用作 Hive Metastore。不用说,它支持所有流行的数据类型和格式,比如 CSV、JSON、Parquet 等等。
ETL 引擎
AWS Glue 利用目录信息,可以根据您的选择自动生成 Scala 或 Python 格式的 ETL 脚本。这个 ETL 脚本负责将数据从源数据源加载到目标数据源,通常是数据仓库或数据湖。您还可以根据自己的需求灵活地进一步定制。
调度程序
ETL 作业可以手动调用,但是对于重复的 ETL 作业,AWS Glue 提供了调度程序,以预定的频率执行 ETL 过程。您还可以灵活地将多个 ETL 作业按执行顺序连接起来,或者在预定义的事件时触发作业。更有用的是,这些调度程序也可以从 AWS Lambda 等外部服务中调用。
AWS 亚马逊胶水的优势
在本文的开始,我们向您展示了 ETL 的挑战,所以让我们看看 AWS Glue 如何使 ETL 过程变得更加容易。
- 由于 AWS Glue 是一种云 ETL 服务,组织不必担心投资本地 ETL 基础设施。
- 即使在 AWS 云上,AWS Glue 也是完全托管的,没有服务器,一切都在后台自行处理。对于 ETL 过程,您不必在 AWS 上显式地启动任何服务器或服务。
- 作为一个云 ETL 服务,AWS Glue 对于大公司和小公司都是一个划算的选择。
- 你不需要在 ETL 过程中花费太多时间,AWS Glue 会将 ETL 代码直接提供给你。这意味着您可以更专注于直接对数据执行分析。请记住,进行分析一直是实际的目标,ETL 只是以可能的格式获取数据的必要手段。
使用 AWS 胶水的公司
以下是一些使用 AWS 胶水的知名公司
- 德勤
- 布鲁特
- 21 世纪福克斯
- 西门子
- 金融公司
- Woot
- 罗宾汉
- Creditvidya
亚马逊 AWS 胶水适合你吗?
如果您是一家已经在使用 AWS cloud 运行应用程序的公司,并且正在寻找 ETL 解决方案,那么您肯定应该考虑 AWS Glue,因为您已经在该生态系统中了。
然而,如果你的公司根本没有使用 AWS 云,这就不那么明确了。如果您的公司愿意投入时间和金钱从头开始构建数据湖,那么迁移到 AWS 云并在 AWS Glue 和 AWS 生态系统中的其他服务的帮助下构建您的数据湖可能是有意义的。但是这肯定不会适合所有的用例。
尽管 Amazon Glue 已经减少了 ETL 过程中所需的工作,但是让我们花一点时间退一步问另一个问题——“我们真的需要 ETL 吗?”在本文中,这个问题听起来可能有些违反直觉,但是最近市场上出现了一些新的非 ETL 解决方案。
数据虚拟化—无 ETL 解决方案
数据虚拟化是一种从一个或多个数据源检索或查询数据的技术,而不必担心数据的底层格式。由于数据虚拟化层,这是可能的。因为您是直接从数据源实时查询数据,所以不需要执行 ETL 来将数据加载到数据仓库或数据湖中。
数据虚拟化绝对是一个游戏规则改变者,因为它消除了对 ETL 过程的需求,甚至使 AWS Glue 对于许多用例来说都是不必要的。
结论
对于任何数据分析项目来说,ETL 都是最具挑战性的方面,如果不是失败的原因,它通常会成为一个复杂的开销。Amazon AWS Glue 通过其完全托管的 ETL 服务来帮助简化 ETL 过程。然而,对于某些用例来说,使用 Knowi 这样的 BI 工具可能更实用,它消除了使用数据虚拟化进行 ETL 的需要。
AWS 胶水和你
在这篇文章中,我将利用 AWS (Amazon Web Service) S3、Redshift 和 Glue,介绍云 ETL(提取、转换、加载)过程中涉及的架构和实现。我的目标是从我的家用计算机中获取源数据文件,并将其中包含的数据处理成云中可用的真实关系 SQL 表。我将使用 S3 来存放源数据,红移到从该源数据派生的主机表,并将数据从 S3 文件转换和加载到红移表。首先,让我们浏览一下项目数据上下文。
数据和问题背景:
我喜欢把我感兴趣的话题作为我项目的基础,这个也不例外。为了这个项目,我从 OpenDoTA API 下载了 10gb 的数据样本,其中包括超过一百万场真实 DoTA 比赛的记录。(对于那些不了解内情的人来说,DoTA 是一种流行的在线视频游戏,两队 5 人在一个战场上比赛)。我的数据由 3 大块组成。csv 文件,分别包含整体比赛数据,球员特定的比赛数据,以及由 Valve (DoTA 开发者)分配的比赛技能等级。这些信息都非常有趣,可能会用于各种统计分析,甚至可能用于一些机器学*,如果你想给一个强化学*模型添加功能,学*实际玩 DoTA。但是把它放在我硬盘上的几个本地文件里并没有太大的好处——所以让我们把它移到一个云 SQL 数据库,在那里它可以被正确地共享和查询。
我将在这项工作中使用的 AWS 服务简述如下:
S3: 亚马逊的简单存储服务(S3)是一种云存储服务,类似于微软的 Azure Blob 存储。出于几个原因,我将把 S3 作为我的数据的中转区:
- S3 根据我的需求动态扩展。虽然我的数据现在只有 10gb,但如果它是 500gb,我将需要一个新的硬盘来本地容纳它,然后我将需要迁移所有这些数据。S3 可以在几乎没有我监督的情况下存储 PETA/EB 规模的数据。
- S3 设计用于冗余和数据损坏自检。如果我所有的真实来源的原始数据都存在我的硬盘上,而我的硬盘出了故障,我就会丢失它们。S3 降低了这种风险。
- 虽然我可以把它从我的硬盘加载到 Redshift 中,但 AWS 服务开箱后就能很好地协同工作。这意味着很容易设置可伸缩的服务来加载我的数据,同时在后台维护安全性、日志和维护。
- 这模拟了现实世界的生产场景,我们可以想象一个计划的抓取作业可能会定期将新数据转储到一个公共的网络位置(S3)。我们的 ETL 作业可以根据新的或更改的文件的出现而被触发运行。
Redshift: AWS Redshift 是一个 Pb 级的数据存储服务,我将使用它来托管由我的 S3 文件中的数据填充的 SQL 表。它的很多特性(巨大的容量,机器学*优化的查询队列,等等。)目前对我来说当然有些过了,但是 Redshift 在 AWS 生态系统中起着重要的作用,并且已经成为行业标准的关系数据存储解决方案,绝对值得这个项目去研究。和 S3 一样,作为云存储服务,Redshift 在备份和维护方面提供了低开销的便利,因为这一切都是由亚马逊在幕后提供的。
Glue: AWS Glue 是这个架构的主力。它表示数据目录中我的源 S3 文件中包含的数据,并包含负责将这些数据移动到红移表中的 ETL 作业。我不仅可以使用 Glue 来定义过滤、转换和验证我的数据的作业,还可以使用类似于气流的相互依赖的作业来协调整个调度/触发的 ETL 工作流。Glue 甚至提供开箱即用的机器学*来识别数据中的重复记录。此外,Glue 是完全无服务器的——我可以使用 Glue 来运行基于 pyspark 的 ETL 作业,而不必担心如何支持 Spark EMR EC2 集群,Glue 将为我做到这一点。
项目演练
1。加载 S3: 我首先将从本地硬盘上抓取的数据文件加载到 S3。这 3 个文件中最大的一个大约是整个数据集大小的 50%,所以我将首先使用 python 中的 dask 和 pandas 库来压缩它。Pandas 可以将 csv 读入数据帧,然后将该数据帧转换为 parquet,这是一种压缩文件存储系统,其中保存了内容上易于阅读的元数据。Dask 可以并行化和批处理 pandas 功能,一旦 RAM 成为一个限制,这对大型数据集来说是非常关键的。这样做可以将这个特定 csv 的大小从 4gb 减少到 800mb。
将文件插入 S3 就像创建一个存储桶、定义访问规则和用 AWS 控制台上传我的文件一样简单。由于文件读写请求将来自我自己的 AWS 帐户和同一个虚拟私有云(VPC),我不需要编辑默认访问权限。
2。初始化胶水数据库:为了向胶水数据目录添加数据,我首先需要将胶水数据库定义为一个逻辑容器。我把我的命名为“gluedb”。
3。创建粘合爬虫来构建数据目录:接下来,我需要将我的数据“摄取”到模型中。我实际上并没有在这里移动任何数据,我只是要创建几个 Glue crawlers 来扫描我的 S3 桶,并从它们找到的文件中推断出我的数据的自然格式。我将为包含我的两个 csv 文件的文件夹定义一个,为保存我的所有 parquet 分区和元数据的子文件夹定义一个。这里很重要的一点是,每个爬虫都拥有对我的 S3 存储桶的读取和列表访问权限,我可以通过附加一个正确定义的 IAM 角色来授予它这种权限。
在运行每一个之后,我的 gluedb 数据库目录被填充:
4。为 S3 配置 VPC 端点:因为我要将数据移出 S3,所以我需要创建一个 VPC 端点,这是一个允许传输文件的网关。我可以从 AWS 控制台 VPC 页面执行此操作,并确保与正确的子网相关联。
5。竖起红移星团:现在我们准备竖起一个红移星团来容纳我们的最终表。亚马逊通过控制台简化了这个过程——只要确保它和 S3 在同一个子网中。对于这个项目,我知道我的表相对来说很小,所以我将选择在 1 dc2.large 节点上托管它们,该节点带有 160gb 的 SSD。重要的是要确保我在这里附加了一个 IAM 角色,它授予适当的红移安全性和访问控制。
6。定义 SQL 模式,创建表:现在架构已经就绪,我可以编写实际的 ETL 过程,将数据从源文件传输到目标表中。首先,我将定义我的最终模式,并通过基于控制台的编辑器在我的 Redshift 集群上执行 SQL 查询来创建我的最终表。
你会注意到我从‘matches’和‘player _ matches’中删除了大量字段。这有两个原因。“聊天”等一些字段包含大量非结构化文本,不适合存储在 SQL 表中;如果我想让它可供查询,我需要建立一个适当的数据存储。此外,我删除的大多数字段实际上都是 json 对象的字符串表示。例如,聊天字段是 json,遵循 OpenDoTA 文档中的结构:
一个合适的解决方案是使用 pyspark 从这些字段中推断出 json 模式,然后使用它们填充一个完整的星型模式,该模式由少量维度表组成,这些维度表通过自然键和派生键连接到一组事实表。然而,对于这个项目的目的,我只是对 AWS 工作流的概念证明感兴趣,不会费心解析这些字段。
7 .。定义粘合作业:准备好最终的表格后,我就可以开始移动数据了。我可以通过创建胶合作业来实现这一点,胶合作业可以按计划、按触发或按需运行。创建 Glue jobs 的有趣之处在于,它实际上可以是一个几乎完全基于 GUI 的活动,只需点击几下按钮就可以自动生成必要的 python 代码。但是,我将做一些编辑,以便综合多个源文件并执行就地数据质量验证。默认情况下,Glue 使用 DynamicFrame 对象来包含关系数据表,并且它们可以很容易地来回转换为 pyspark 数据帧以进行自定义转换。我所有的 ETL 脚本都可以在这个项目的 GitHub 资源库中找到,链接在本文末尾。
运行后:
两个表都已完全填充并准备好进行 SQL 查询:
重申一下,我现在已经建立了一个过程,通过这个过程,我从自己的硬盘上加载数据,将它存放在云中,并将其转换成一对目的地事实来源表。基础云架构现在已经就绪,我可以发展和定制我的 ETL 流程,我在这里可以做的额外工作是真正生产这个数据流,这取决于我特定的分析需求。例如,通过对我的 ETL 作业进行一些修改,我可以改进这个过程,以便在我向 S3 上传额外文件时自动合并我的数据表,我还可以规范化我的目标表并包含我选择删除的字段。为了这个概念验证项目的目的,我的工作已经完成了!
我想特别感谢我的朋友兼同事斯图尔特·明舒尔,他是亚马逊网络服务的高级云架构师,他就我在这个项目中采用的总体架构和最佳实践向我提供了咨询!
Github:https://github.com/jfreds91/DEND_Capstone
AWS Glue Studio——没有火花技能——没问题
使用 AWS Glue Studio 轻松创建 Spark ETL 作业——不需要 Spark 经验
图片由皮克斯拜的 Gerd Altmann 提供
AWS 胶水工作室近日上线。有了 AWS Glue Studio,您可以使用 GUI 来创建、管理和监控 ETL 作业,而不需要 Spark 编程技能。用户可以通过可视地定义 ETL 作业的源/转换/目的节点来可视地创建 ETL 作业,该 ETL 作业可以执行诸如获取/保存数据、连接数据集、选择字段、过滤等操作。一旦用户组装了 ETL 作业的各个节点,AWS Glue Studio 就会自动为您生成 Spark 代码。
AWS Glue Studio 支持许多不同类型的数据源,包括:
- S3
- 无线电数据系统
- 由外界刺激引起的不随意运动
- 卡夫卡
让我们尝试创建一个简单的 ETL 作业。这个 ETL 作业将使用 3 个数据集- 订单、订单细节和产品。目标是连接这三个数据集,选择几个字段,最后过滤产品 MRSP 大于 100 美元的订单。最后,我们希望将结果保存到 S3。
当我们完成时,ETL 工作应该看起来像这样。
作者图片
让我们从下载本教程所需的数据集开始。将数据集保存在 S3。
$ git clone [https://github.com/mkukreja1/blogs](https://github.com/mkukreja1/blogs)$ aws s3 mb s3://glue-studio
make_bucket: glue-studio$ aws s3 cp blogs/glue-studio/orders.csv s3://glue-studio/data/orders/orders.csv
upload: blogs/glue-studio/orders.csv to s3://glue-studio/data/orders/orders.csv$ aws s3 cp blogs/glue-studio/orderdetails.csv s3://glue-studio/data/orderdetails/orderdetails.csv
upload: blogs/glue-studio/orderdetails.csv to s3://glue-studio/data/orderdetails/orderdetails.csv$ aws s3 cp blogs/glue-studio/products.csv s3://glue-studio/data/products/products.csv
upload: blogs/glue-studio/products.csv to s3://glue-studio/data/products/products.csv
我们将把这些文件保存到 S3,并使用 Glue Crawler 将它们编入订单数据库。
$ aws glue create-database --database-input '{"Name":"orders"}'$ aws glue create-crawler --cli-input-json '{"Name": "orders","Role": "arn:aws:iam::175908995626:role/glue-role","DatabaseName": "orders","Targets": {"S3Targets": [{"Path": "s3://glue-studio/data/orders/"},{"Path": "s3://glue-studio/data/orders/"}]}}'$ aws glue start-crawler --name orders$ aws glue delete-crawler --name orders$ aws glue create-crawler --cli-input-json '{"Name": "orderdetails","Role": "arn:aws:iam::175908995626:role/glue-role","DatabaseName": "orders","Targets": {"S3Targets": [{"Path": "s3://glue-studio/data/orderdetails/"},{"Path": "s3://glue-studio/data/orderdetails/"}]}}'$ aws glue start-crawler --name orderdetails$ aws glue delete-crawler --name orderdetails$ aws glue create-crawler --cli-input-json '{"Name": "products","Role": "arn:aws:iam::175908995626:role/glue-role","DatabaseName": "orders","Targets": {"S3Targets": [{"Path": "s3://glue-studio/data/products/"},{"Path": "s3://glue-studio/data/products/"}]}}'$ aws glue start-crawler --name products$ aws glue delete-crawler --name products
使用 AWS 控制台打开 AWS Glue service,并使用左侧菜单点击 AWS Glue Studio 。确保您选择了空白图表。点击创建。
作者图片
首先创建第一个转换节点- 获取订单数据
作者图片
确保获取订单数据指向之前在 Glue 中分类的订单表。
作者图片
使用与上述相同的原则创建转换节点- 获取订单明细数据以及获取产品数据
现在我们将创建一个转换节点,它将把提取订单数据连接到提取订单详细信息数据。
作者图片
请注意两个表之间的连接条件是如何定义的,如下所示。
使用相同的原理创建一个转换节点,该节点将连接连接订单到获取产品数据。
作者图片
因为我们想从三个表中选择一个列的子集,所以我们可以使用选择字段节点
作者图片
请注意如何为应该包含在最终结果集中的字段选择复选框。
作者图片
现在我们要过滤 MRSP 大于 100 美元的产品。这可以通过创建如下的过滤器产品 MRSP > 100 节点来实现。
作者图片
请注意如何定义一个或多个过滤条件。
作者图片
最后,我们希望将结果表以拼花格式保存到 S3。对于 tis,我们创建一个目的节点- 保存结果
作者图片
作者图片
使用“保存”按钮保存您的 ETL 作业。这时你应该可以看到 AWS Glue Studio 已经自动为你生成了 Spark 代码。点击脚本菜单查看生成的代码。
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
import re## [@params](http://twitter.com/params): [JOB_NAME]
args = getResolvedOptions(sys.argv, ['JOB_NAME'])sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)
## [@type](http://twitter.com/type): DataSource
## [@args](http://twitter.com/args): [database = "orders", table_name = "orders", transformation_ctx = "DataSource0"]
## [@return](http://twitter.com/return): DataSource0
## [@inputs](http://twitter.com/inputs): []
DataSource0 = glueContext.create_dynamic_frame.from_catalog(database = "orders", table_name = "orders", transformation_ctx = "DataSource0")
## [@type](http://twitter.com/type): DataSource
## [@args](http://twitter.com/args): [database = "orders", table_name = "products", transformation_ctx = "DataSource2"]
## [@return](http://twitter.com/return): DataSource2
## [@inputs](http://twitter.com/inputs): []
DataSource2 = glueContext.create_dynamic_frame.from_catalog(database = "orders", table_name = "products", transformation_ctx = "DataSource2")
## [@type](http://twitter.com/type): DataSource
## [@args](http://twitter.com/args): [database = "orders", table_name = "orderdetails", transformation_ctx = "DataSource1"]
## [@return](http://twitter.com/return): DataSource1
## [@inputs](http://twitter.com/inputs): []
DataSource1 = glueContext.create_dynamic_frame.from_catalog(database = "orders", table_name = "orderdetails", transformation_ctx = "DataSource1")
## [@type](http://twitter.com/type): Join
## [@args](http://twitter.com/args): [keys2 = ["ordernumber"], keys1 = ["ordernumber"], transformation_ctx = "Transform2"]
## [@return](http://twitter.com/return): Transform2
## [@inputs](http://twitter.com/inputs): [frame1 = DataSource0, frame2 = DataSource1]
Transform2 = Join.apply(frame1 = DataSource0, frame2 = DataSource1, keys2 = ["ordernumber"], keys1 = ["ordernumber"], transformation_ctx = "Transform2")
## [@type](http://twitter.com/type): Join
## [@args](http://twitter.com/args): [keys2 = ["productcode"], keys1 = ["productcode"], transformation_ctx = "Transform3"]
## [@return](http://twitter.com/return): Transform3
## [@inputs](http://twitter.com/inputs): [frame1 = Transform2, frame2 = DataSource2]
Transform3 = Join.apply(frame1 = Transform2, frame2 = DataSource2, keys2 = ["productcode"], keys1 = ["productcode"], transformation_ctx = "Transform3")
## [@type](http://twitter.com/type): SelectFields
## [@args](http://twitter.com/args): [paths = ["ordernumber", "orderdate", "requireddate", "shippeddate", "status", "productname", "msrp"], transformation_ctx = "Transform1"]
## [@return](http://twitter.com/return): Transform1
## [@inputs](http://twitter.com/inputs): [frame = Transform3]
Transform1 = SelectFields.apply(frame = Transform3, paths = ["ordernumber", "orderdate", "requireddate", "shippeddate", "status", "productname", "msrp"], transformation_ctx = "Transform1")
## [@type](http://twitter.com/type): Filter
## [@args](http://twitter.com/args): [f = lambda row : (row["msrp"] > 100), transformation_ctx = "Transform0"]
## [@return](http://twitter.com/return): Transform0
## [@inputs](http://twitter.com/inputs): [frame = Transform1]
Transform0 = Filter.apply(frame = Transform1, f = lambda row : (row["msrp"] > 100), transformation_ctx = "Transform0")
## [@type](http://twitter.com/type): DataSink
## [@args](http://twitter.com/args): [connection_type = "s3", format = "parquet", connection_options = {"path": "s3://glue-studio/results/", "partitionKeys": []}, transformation_ctx = "DataSink0"]
## [@return](http://twitter.com/return): DataSink0
## [@inputs](http://twitter.com/inputs): [frame = Transform0]
DataSink0 = glueContext.write_dynamic_frame.from_options(frame = Transform0, connection_type = "s3", format = "parquet", connection_options = {"path": "s3://glue-studio/results/", "partitionKeys": []}, transformation_ctx = "DataSink0")
job.commit()
我们都准备好了。让我们使用右上角的运行按钮运行作业。点击运行详细信息会显示正在运行的作业的状态。一旦作业状态变为成功,您就可以去 S3 查看作业的最终结果。
作者图片
此时,结果文件夹中应该会生成许多拼花文件。
作者图片
您可以使用 Apache Parquet 查看器检查文件的上下文。
作者图片
我希望这篇文章是有帮助的。 AWS Glue Studio 是由 Datafence Cloud Academy 提供的 AWS 大数据分析课程的一部分。课程是周末自己在网上教的。
AWS honey code—没有代码
打造自己的 AWS re: Invent 2020 日程应用
图片由皮克斯拜的 Gerd Altmann 提供
AWS Honeycode 最近在发布,作为 AWS 提供的“无代码应用构建器”。对于熟悉微软 Power 应用的人来说,Honeycode 非常类似。该服务的重点是为团队协作设置工具。我没有看到在工具外部共享应用程序的选项。要想和朋友分享应用,看看 AppSheet 。我把它用于非盈利活动,给数百名儿童分发节日礼物。它在这方面做得很好。
我决定做一个演示来创建一个简单的 AWS re: Invent 2020 会话调度器。今年的会议为期三周(并且是免费和虚拟的)。为我不想错过的会议做计划;我需要有条理!
在某种程度上是免费的
Honeycode 界面仍处于测试模式。我没有被要求提供任何付款信息来设置这个演示。您可以免费添加多达 20 个成员或多达 2500 个数据行。还不错。
入门指南
登录蜜码:
这是而不是你的 AWS 账户,有趣点。我想象这个工具将在某个时候集成到 AWS 控制台中。
一切从你的数据开始。
我还没有会议时间表,所以我创建了一些感兴趣的话题。
我还设置了一个空白表来存放日程数据。我增加了一些额外的领域,在那里我可以思考好的和坏的。几天后,会议往往会变得模糊不清。
是时候“构建”应用程序了
Amazon Honeycode 包含基本模板,帮助您启动和运行。你总是可以从基本模板开始,然后在此基础上进行个性化和趣味化。
样本模板—作者截屏
我使用定制构建,而不是使用任何向导或模板。有一些试错的成分。如果你以前用过 Power Apps,那就非常类似了。
我的应用程序将有两个屏幕。主屏幕是我的个性化时间表。我想显示我的日程安排。第二个屏幕将列出我可以查看并添加到我的时间表中的所有会议。
我添加了两个带动作的按钮。一个是从我的日程表上删除一个时段。一个是在我的日程表上增加一节课。相当直接。
结果呢
嗯,它不会赢得任何设计奖。考虑到我只花了大约一个小时创建一个帐户和这个应用程序,这是足够体面的。
我的简历:发明日程表应用主页——作者截图
会话详细信息和选取器屏幕—作者截屏
我可以下载应用程序并在手机上使用。
作者手机截图
结论
如果你需要建立一个团队协作应用程序,并且不想乱搞代码,它与微软 PowerApps 兼容。它创造有用的结果。
如果你想开发一个供公众使用的无代码应用,你可能需要看看市场上的其他产品。
AWS IAM 简介
AWS 身份和访问管理服务概述
IAM 的关键元素是用户、角色和策略。除了任何相关的背景,我们将在本帖中逐一讨论。用 Draw.io 创建
让许多迁移到基于云的环境的人感到震惊(和沮丧)的第一件事是权限可以有多复杂。通常,在多年*惯于成为您之前编写的任何代码的神之后,您会被引入一个几乎所有东西都被默认锁定的环境。
这篇文章将通过教你 IAM 最重要的部分 Amazon Web Services 的身份和访问管理服务——以及介绍一些众所周知的最佳实践来减轻你的痛苦。在以后的文章中,我计划以这个为基础。
如果你有兴趣看到我在这篇文章中讨论的所有 IAM 元素,请务必阅读这篇后续文章。
帐户和资源
AWS 的世界始于帐户和这些帐户中的资源。IAM 的存在主要是为了保护您帐户中的资源,防止出现以下问题:
- 恶意行为者试图对你的 AWS 帐户做不必要的事情(例如,从你的 S3 桶中窃取你的数据)。
- 您公司内的用户/应用程序意外删除了资源,或者执行了他们原本不应该执行的操作。
账户:
AWS 用户之间的逻辑障碍。非常简单:
- 与 12 位账户 id 一一对应,如
123456789012
。 - 作为最佳实践,一个组织将拥有多个 AWS 帐户[1]。IAM 通常用于处理组织内 AWS 帐户之间的权限。
- 与电子邮件地址、信用卡绑定;账户就是你的账单。
资源:
资源是您的帐户中您想要使用的持久对象,如负载*衡器或 EC2 实例。
- 资源总是有一个ARN——亚马逊资源名称——来唯一地标识它们。例如,对于 IAM 用户,ARN 可能如下所示:
arn:aws:iam::123456789012:user/Development/product_1234/*
注意帐户 id 123456789012
是如何出现在 ARN 中的,以及资源的类型(这个资源是一个 IAM user
)。
身份
IAM 的核心特性是身份,这是一种 AWS 资源。AWS 服务总是公开可以使用某种身份调用的 APIs 这告诉 AWS 你是谁(认证)以及你是否被允许做你正在做的事情(授权)。
IAM 中有两种主要的身份形式:用户和角色。
用户
IAM 中用户的意图类似于脸书等其他网站中的用户。当你第一次创建一个 AWS 账户时,你会得到一个根用户,可以完全访问你的账户【2】。然后,您可以选择——强烈建议——创建更多的用户和角色。
关于用户的一些说明:
- 与角色不同,用户有用户名和密码。这些是长期有效的凭证,可以保存很长一段时间,用于登录 AWS 控制台。
- 通常旨在为个人提供对 AWS 控制台或 API 的访问。然而,作为一个 最佳实践 ,你应该尽可能使用角色而不是用户。这是为了限制长期凭据被放错位置并让攻击者访问您的 AWS 帐户的风险。
- 用户被给予访问密钥。访问密钥可用于通过 CLI 或 SDK 调用 AWS 服务。像用户名/密码一样,访问密钥是长期有效的。它们看起来更加随机,并且可以通过创建一个名为
~/.aws/credentials
的文件与 CLI 一起使用,该文件的内容如下所示:
[personal]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
您可以通过 CLI 上的--profile
选项在 CLI 中使用凭据配置文件:
> aws s3 ls --profile personal2017-11-30 16:20:55 some-s3-bucket
2017-10-31 20:05:17 some-other-s3-bucket
...
角色
像用户一样,角色是用于访问 AWS APIs 和资源的身份。然而,角色通常用于向 AWS 帐户授予临时凭证。此外,可以将这些临时凭证配置为信任第三方或其他 AWS 服务。
角色在 AWS 中无处不在:
- 需要访问 AWS 资源的 EC2 实例将使用实例角色根据您的应用程序逻辑来命令其他 AWS 服务/资源。
- 需要访问您帐户中的资源的其他 AWS 帐户有时会在您的帐户中扮演角色,以通过 STS 扮演角色 API 获得访问权限。为了允许他们这样做,您可以通过信任策略为另一个帐户中的某个身份授予角色权限(稍后将详细介绍)。
- AWS 的一个重要特性是它能够代表您采取行动。然而,AWS 服务通常被实现为 AWS 帐户;这意味着默认情况下,他们无权访问您帐户中的资源。因此,他们通常会要求您在您的帐户中创建并授予他们访问“服务角色”的权限,以便他们可以代表您采取行动。例如,EC2 上的自动伸缩将需要权限来为您上下旋转 EC2 实例。
- 像 JumpCloud 这样的第三方将使用角色来授予在 AWS 之外管理的用户对 AWS 资源的访问权。这个过程称为联合。
政策
最后,当您(以某种身份运行)调用 AWS API 时,IAM 将通过评估一个或多个策略来确定调用是否有效。有两种主要的策略:身份策略和资源策略。
身份策略
身份策略确定允许给定身份(角色/用户)做什么。身份策略可以由 AWS 管理(这些受管策略将在您的帐户中预先创建),也可以由您管理。
下面是一个更简单的身份策略示例:
- 可以被调用的 API 在 IAM 中被称为
Actions
。多个 API 可以命中一个动作,但是,通常情况下,动作只对应于一个 API。 - 该策略是白名单;这意味着,默认情况下,不允许动作。对于两个动作:
CreateRole
和CreateUser
,给出了明确的Allow
。有关如何在 AWS 帐户中评估策略逻辑的完整分类,请参*本文档。 - AWS 中的大多数 API 调用都可以缩小范围,只允许在特定的资源上调用,如上所述。您可以看出发生了这种情况,因为
Resources
部分不是*
。这意味着使用该标识的请求只能针对具有这些特定 arn 的资源成功。例如,您只能使用此策略创建 ARNarn:aws:iam::123456789012:role/some-role
的角色。将范围缩小到单个资源是防止许多安全漏洞的最佳实践。以 2019 年的 Capital One hack 为例。Capital One 给了他们的防火墙过多的 S3 权限,一旦它被 SSRF 欺骗,就允许攻击者窃取超过 1 亿个人的数据。 - 没有资源策略的身份策略只能在同一个 AWS 帐户中工作。
- 支持通配符。该策略中的第二个声明与 Cloudwatch 日志有关,并给予对 Cloudwatch 日志的完全访问权(他们开放的任何 API,以及任何资源)。
任何给定的身份都可以附加多个策略;在这种情况下,身份获得应用于它的策略的逻辑或,其中显式的Deny
将覆盖显式的Allow
。
我认为语法很简单,但是,要更深入地了解策略语法,请阅读文档。
这里还有一个 EMR 策略生成器,我推荐你用它来更快地构建这些:https://awspolicygen.s3.amazonaws.com/policygen.html
资源政策
当某个主体对某个资源执行* 操作时,无论该资源是从其获取对象的 S3 桶,还是某人试图承担的 IAM 角色,其资源策略都将生效。这些乍一看似乎是多余的,因为您可以将身份策略的范围扩大到特定的资源,但通常在您的资源而不是调用它的身份上设置策略是有用的。*
这些资源策略在支持跨帐户访问资源方面也起着关键作用。单独的身份策略无法实现跨帐户访问,因为 AWS 帐户之间的权限界限比单个帐户内部的权限界限要严格得多。
让我们检查一个角色的资源策略。请注意,角色上的资源策略也称为信任策略,因为它们使其他人能够承担角色。
- 委托人 是试图访问资源的调用者的名字。该策略将服务 EC2 以及帐户
123456789012
中的两个其他角色列入白名单,以承担该角色。主体是普通身份的超级集合,可以包括 AWS 服务或来自其他应用程序的用户。 - 您会注意到,当您为某个规则指定一个主体时,您需要指定它是哪种主体。委托人有几种类型,但最常*的两种是
Service
和AWS
。前者允许 AWS 服务(如 EC2)访问该角色,后者允许特定 AWS 帐户的身份访问该角色。 - 根据服务的不同,资源策略会有很大的不同。有些资源策略比其他资源策略更严格,或者启用不同的功能。例如,在密钥管理服务中,您必须在密钥的资源策略中授予您帐户的根用户权限,然后身份策略才能授予对该密钥的访问权限。S3 桶有额外的安全控制,像访问控制列表。始终致力于理解您正在使用的资源如何单独管理权限:不要假设两种类型的资源以相同的方式管理权限。
在大多数资源上,资源策略是可选的。如果它们不存在,它们将被忽略,如下所示。
简化的策略评估逻辑
最后,我想提供一个简单的图表来形象化地说明我们讨论的策略是按照什么顺序进行评估的。
为了简单起*,我省略了完整的评估逻辑,只包括下面的通用策略。我建议您阅读公共文档以获得更详细的策略评估视图,包括更深奥的策略,如会话策略和权限边界。
委托人提出请求时评估的典型策略的流程图。这里的允许/拒绝对应于您在上面看到的 JSON 策略文档中指定的允许/拒绝。用 Draw.io 创建
IAM 是 AWS 的主要构件之一。我希望这已经向您介绍了使用它时会遇到的主要问题。
如果你想更深入地了解我,一定要看看我的后续文章!
如果您还有任何问题或者只是想聊天,您可以通过我的 evankozliner@gmail.com 联系我,或者在 Twitter 上给我发消息。
笔记
[1]构建多账户组织超出了本文的范围,但是,如果您感兴趣,我推荐下面的视频和简介。
[2]根用户实际上不同于 IAM 用户。有些任务只有根用户才能执行。
AWS Lambda & Amazon API Gateway——不像听起来那么令人生畏
在这篇博客中,我们将创建一个简单的 OpenCV + Tesseract 算法,并使用 lambda 函数和 API 网关将其作为 API 部署在 AWS 上
“牛逼。你创造了一个伟大的机器学*算法。我对它的准确性印象深刻,也喜欢它的技术。如何在我们的系统中实现?”—这是你在客户或业务会议中多次听到但从未能如实回答的事情吗?别担心,这可能是 90% ( 保守点说)的数据科学家同事面临的问题。AWS 有许多解决方案。其中之一就是——集成亚马逊 API 网关 的 AWS lambda 功能。
什么是 AWS Lambda?
AWS Lambda 是一个事件驱动、 无服务器 计算*台,由亚马逊提供,作为亚马逊网络服务的一部分。它是一种计算服务,运行代码以响应事件,并自动管理该代码所需的计算资源。 无服务器 计算的概念是指你不需要维护自己的服务器来运行这些功能的想法。这意味着你可以上传你的代码 (Python,Node.js,Go,。NET、Java、Ruby) 和 Lambda 将管理其他事情,如运行时、缩放、负载*衡等。
什么是亚马逊 API 网关?
Amazon API Gateway 是一个完全托管的服务,使开发人员可以轻松地创建、发布、维护、监控和保护任何规模的 API。API 充当应用程序从后端服务访问数据、业务逻辑或功能的前门。使用 API Gateway,我们可以创建 RESTful APIs 和 WebSocket APIs,实现实时双向通信应用程序。API Gateway 支持容器化和无服务器的工作负载,以及 web 应用程序。
我们的博客行动计划
索引
- 登录 AWSLambda
- 理解并创建一个λ_ function
- 使用 Docker 下载并定义 层 (又名依赖关系)
- 测试我们的功能
- 配置 亚马逊 API 网关
- 部署 API 并使用 Postman 进行测试
让我们从简单的开始
对于所有没有 AWS 账户的人,请前往
→在“https://signin.aws.amazon.com/”
创建新账户→记住添加账单详情,因为没有它,一些 AWS 功能将无法工作。(别担心,AWS 提供免费等级&因此你不会被收费,除非你超过那个等级,这是一个很大的数目!)
有关限额的更多信息,您可以查看以下内容:aws.amazon.com/free
登录 AWSλ
→登录 AWS 控制台,在搜索栏中搜索 Lambda
Lambda 登陆页面,有函数、层等多个对象。
→点击 创建功能→
分配函数名称、运行时和执行角色如:
→函数名称:→ml Function →运行时:Python 3.7* →执行角色: 新建一个具有基本 Lambda 权限的角色*
理解并创建一个λ_ function**
什么是 lambda_function?
运行在 AWS Lambda 上的代码(这里:python)* 作为 Lambda 函数上传。它可以包括库,甚至是本地库。*
它有两个参数——事件和上下文。
Event
表示导致 lambda 调用的事件或触发器。这就像函数的输入。例如:Lambda 函数可以通过上传到 S3 或通过 API 网关传递一些输入/数据来触发。(我们将主要关注事件)**Context
提供关于 lambda 的调用、函数和执行环境的信息。可用于检查内存分配或检索执行超时前剩余的毫秒数。这就像 AWS 提供的 extra 或 meta 信息来理解函数的运行时。
创建一个λ函数
让我们创建一个执行以下操作的代码:
→输入:图像文件(。jpg,。png 等)
→ OpenCV:读取图像
→镶嵌:对图像进行 OCR&打印出文本
*import base64
import pytesseract
import json
import io
import cv2def write_to_file(save_path, data):
with open(save_path, "wb") as f:
f.write(base64.b64decode(data))def ocr(img):
ocr_text = pytesseract.image_to_string(img, config = "eng")
return ocr_textdef lambda_handler(event, context=None):
write_to_file("/tmp/photo.jpg", event["body"])
im = cv2.imread("/tmp/photo.jpg")
ocr_text = ocr(im)
# Return the result data in json format
return {
"statusCode": 200,
"body": ocr_text
}*
记得“保存”该功能
使用 Docker 下载&定义层(又名依赖)
虽然我们已经创建了 lambda 函数,但它不会立即执行或运行。原因是我们没有下载或安装代码运行所需的库(依赖关系)。像在正常环境中,我们需要 pip 或 conda 安装库,我们需要为 AWS lambda 做同样的事情。我们通过向 AWS lambda 添加层来做到这一点。它被定义为:
包含库、自定义运行时或其他依赖项的 ZIP 存档。使用层,您可以在函数中使用库,而无需将它们包含在您的部署包中。
使用 Docker 下载依赖项
如果我们中的任何人以前使用过宇宙魔方,我们就知道安装这个库有多困难。
Benjamin Genz 在简化整个流程方面做了大量工作。
→转到您的终端并克隆回购
*git clone [https://github.com/amtam0/lambda-tesseract-api.git](https://github.com/amtam0/lambda-tesseract-api.git)
cd [lambda-tesseract-api/](https://github.com/hazimora33d/lambda-tesseract-api.git)*
文件夹结构将如下所示
重要:
1。将使用 docker 来安装所有的库,所以请确保您已经下载了
2。不要详细检查 Docker 文件,而是进行必要的修改
转到命令和运行
*bash build_tesseract4.sh*
这将为函数下载宇宙魔方层
→ build_py37_pkgs.sh
包含需要安装的附加库的列表。移除“枕头”,因为我们不需要它。
*declare -a arr=(“opencv-python” “pytesseract” “Pillow”)*
到
*declare -a arr=(“opencv-python” “pytesseract”)*
→转到命令和运行
*bash build_py37_pkgs.sh*
需要一些时间,你会看到所有相关的库已经下载到一个 zip 文件中。
向 AWS Lambda 添加层
→返回 AWS lambda 控制台,点击创建图层**
→添加 名称,兼容运行时&上传zip 文件**
→ 瞧,你已经成功添加了立方体层
→重复同样的过程,通过 zip 文件上传OpenCV&tesse ract库。
定义图层的目录
在我们开始使用上传的依赖项之前,还有最后一件事。
→回到你的 功能 ,点击 图层
→添加 立方体 作为兼容层
→重复同样的过程添加OpenCV&宇宙魔方 作为该功能的另一层。最后,你应该看到两个图层都被添加到 图层功能
现在我们已经添加了层,我们只需要确保这些库可以被 MLFunction 读取。
→转到 环境变量
→添加以下路径,以便上传的 图层 可以通过 lambda 函数访问
PYTHONPATH = /opt/
您可能想要添加超时会话,因为图像可能需要一些时间来加载并使用 tesseract 进行处理
→转到基本设置,超时 1 分钟
让我们测试我们的 lambda 函数
测试我们的功能
→转到测试
→创建一个新事件,添加以下内容
这是下图的 base64 编码版本:
提示:Lambda 函数将所有图像(事件)转换为 base64。因此,在您的代码中进一步使用它们之前,请确保对它们进行解码
→点击 测试 ,您应该会看到以下内容:
您不仅成功地创建了一个新的 lambda 函数,还测试了它。拍拍背!**
配置 Amazon API 网关
→登录 AWS 控制台,在搜索栏中搜索 API
→点击 创建 API
→选择 Rest API (非私有)
→为您的 API 命名。 (此处:OCR API)
现在你在你的 API 控制台中。我们需要执行几个操作来配置我们的应用程序。
创建帖子资源
我们需要创建一个 POST 方法,以便用户可以上传图像,并通过我们的 lambda 函数传递它。
→转到 资源→ 动作→创建方法→ 选择 发布
→选择使用 Lambda 代理集成选择 **lambda 函数(此处:ml function)****&点击保存**
点击 确定 到 添加权限给 Lambda 函数
→转到 方法响应
→在 HTTP 状态下进行以下更改:
- 响应头: 内容类型
- 回复正文:将内容编辑为 图片/jpeg
注意:这意味着 API 要以图像的形式发送 lambda 函数内容*。这是一个非常重要的步骤,除非我们做出这个改变,否则 API 将无法理解什么类型的文件需要流向 lambda 函数。
—如果是 HTML 或 XML 等其他类型,我们应该将响应体改为 application/html 或 application/xml***
再做一次改变,然后我们就可以开始了。
添加二进制选项
我们希望用户上传文件,为此我们需要启用二进制选项。
→转到 API 部分下的 设置
在二进制媒体类型&中添加*/*
点击保存更改。(这意味着用户可以上传任何类型的文件——虽然它会根据 内容发送到 lambda 函数——我们前面定义的)**
您已经准备好部署和测试您的 API 了。
部署 API 并使用 Postman 或 curl 测试它
→转到 资源→操作→部署 API
→命名为 部署阶段(这里:测试)→部署
哇——您已经部署了您的 API。现在您应该会看到您的 API 的 URL。
测试 API
我们将使用 Postman 来测试我们的 API。你可以从https://www.postman.com/downloads/下载
→打开 Postman,您应该能够看到一个仪表板
→新建一个标签页→选择 POST 选项→在输入请求 URL 中添加 API URL
→选择 二进制正文& 上传 Hello World 镜像文件**
****
输出— 您应该得到以下输出
瞧 —您已经成功地创建、部署并测试了您 API。与你的朋友和家人分享你的网址。
另外,如果你有兴趣在 AWS EC2 实例或 Heroku 上托管 OpenCV &宇宙魔方,那么请阅读以下博客。
** [## 使用 AWS EC2 实例部署 Python + Tesseract + OpenCV 快速 API
关于如何创建 AWS EC2 实例并为…部署代码的分步方法(包括截图和代码)
towardsdatascience.com](/deploy-python-tesseract-opencv-fast-api-using-aws-ec2-instance-ed3c0e3f2888) [## 在 Heroku 上部署 Python Tesseract OCR
如何在 Heroku 上创建 OpenCV + Tesseract OCR 的一步一步的方法(包括截图和代码)
towardsdatascience.com](/deploy-python-tesseract-ocr-on-heroku-bbcc39391a8d)
暂时结束了。有什么想法来改善这一点或希望我尝试任何新的想法?请在评论中给出你的建议。再*。**
AWS Lambda 性能:专业提示和技巧
如何诊断和优化您的功能
Lambda 是亚马逊网络服务(AWS)提供的无服务器云计算服务。该服务使您能够在 AWS 服务上运行后端代码,而无需管理基础设施。你在 AWS Lambda 上运行的代码叫做函数。可以使用自己的函数,也可以使用预制的函数。一旦您的函数被加载,您就选择了一个 AWS 事件源。你可以根据需要设置事件,然后让 Lambda 自动运行。
如果您不想处理供应、资源和其他计算任务,Lambda 是一个很好的解决方案。但是,您仍然需要以确保性能的方式设置您的函数和触发器。本文解释了 AWS Lambda 性能如何受到冷启动时间、执行时间和并发性的影响。您还将学*如何诊断和优化 Lambda 性能问题。
什么导致了 AWS Lambda 性能问题?
当用 AWS Lambda 设置功能时,几个问题破坏了无服务器应有的速度和灵活性。当函数没有按预期执行时,以下三个原因是最常*的原因。
冷启动时间
调用后,函数会在一段未声明的时间内保持热度。一般 30 分钟左右。之后,函数实例被终止,下一次调用需要创建并初始化一个新的实例。这种冷启动增加了操作的时间和成本。冷启动的等待时间最长可达 10 秒,您需要为该功能预热的时间付费。
执行时间
Lambda 函数每次调用最多可以运行 15 分钟。这是你无法改变的硬性限制。函数运行时间为什么长,函数是否在等待响应,或者它是否需要大量的计算,这些都无关紧要。由于这个限制,对于任何运行时间接近 15 分钟的函数,您应该考虑另一种方法。
并发
使用 Lamba,每个函数实例一次只能调用一个。如果您在运行时再次调用它,则会创建一个新实例,直到达到您的并发限制。美国(东西)和欧洲(爱尔兰)的并发量最高可达 3k,亚太(东京)和欧洲(法兰克福)最高可达 1k,其他地区最高可达 500。对于更多的并发实例,您必须请求 AWS 增加数量。如果不这样做,任何超出限制的调用都会被抑制。
诊断性能问题
诊断 Lambda 中的性能问题可能很棘手。功能的短暂性要求动态监控,而无服务器架构的分布式特性使得调试变得困难。
监控、记录和追踪
除了您提供给 Lambda 的函数和资源需求之外,您几乎无法控制函数实例如何操作。这意味着您不能使用守护程序进行监控,也不能轻松地将日志导出到外部*台。然而,AWS 确实提供了一些解决方案来帮助您克服这个障碍。
- 监控 — AWS CloudWatch 自动从您的函数中收集运行时和基本性能指标。您可以将这些指标导出到第三方监控解决方案,或者通过 CloudWatch 控制台或 AWS CLI 访问它们。但是,请记住,每次您访问指标时,都会收取少量费用。
- 日志 —可以在代码中插入日志语句,将数据发送到 CloudWatch 日志中。然后,您可以通过控制台、AWS CLI 或使用 API 导出来查看这些日志。
- 跟踪 — AWS X-Ray 是一种服务,通常可用于对 Lambda 函数和微服务架构进行端到端跟踪。它支持 Java、Node.js 和。NET 并跨 AWS 帐户、区域和可用性区域工作。
调试
在调试函数时,可以很容易地结合 CloudWatch 和 X-Ray 信息来识别性能瓶颈,并为单次调用请求问题。然而,将这些服务用于多次调用可能是一个挑战,因为来自所有调用的日志记录混合在 CloudWatch 日志中。这使得很难按时间顺序查看数据。
如果您试图调试跨多个函数或服务的错误,上述工具提供的帮助就更少了。这意味着为了有效地调试,您需要将数据导出到第三方*台。
如何优化 AWS Lambda 性能
除了监控和调试之外,您还可以采用一些最佳实践来帮助减少或防止性能问题。下面是一些需要考虑的实践。
提高冷启动性能
减少冷启动的影响是提高功能表现最有效的方法之一。有几种方法可以减少冷起动时间,但是你也可以消除许多冷起动。
为了避免冷启动,你可以使用更热的逻辑。这个逻辑包含在一个处理函数中,用于与 Lambda 函数和事件触发器接口。较热的逻辑以 5 到 10 分钟的增量调用主函数中的少量逻辑,以确保实例在实际需要调用它时保持活动状态。您可以使用 cron 作业来完成这些调用,也可以使用一些模块来批量预热。
内存和 CPU
在定义函数的资源需求时,您只能指定 RAM,最大为 3GB。无论您指定多少,都会按比例分配 CPU 能力。您每分配 1,792 MB,就会向您的资源中添加一个虚拟 CPU。
要优化,你需要找到功能性能和成本的*衡点。对于单线程应用程序,这通常意味着 1.8GB 或更少的 RAM。对于 CPU 绑定代码的多线程应用,任何低于 1.8GB 的东西都可能是无效的。
错误
捕捉函数中异常的最佳方式是嵌入导出到 CloudWatch 日志的日志记录语句。这可以通过普通的 stdout 或 stderr 语句或者特定于语言的日志方法来完成。
无论哪种方式,您都需要确保分配给您的功能的身份和访问管理(IAM)角色拥有将日志发布到 CloudWatch 的权限。否则,您的日志将只显示没有帮助的权限被拒绝错误。
喉咙
一旦达到并发限制,调用请求就会受到限制并返回一个错误。对于保留和非保留并发都是如此。这个限制的一个警告是,它取决于函数是如何被调用的。对于基于流的事件,限制由并行化因子决定。这个因素决定了使用多少并发调用来处理数据流的每个片段。
对于非基于流的事件,计算的调用请求数是实际调用数乘以函数持续时间。这意味着即使在给定时间内没有新调用那么多函数实例,您也可以很快达到极限。
要解决这个问题并避免返回错误,您可以:
- 异步调用 —适用于非基于流的事件。这种方法需要排队服务,像 SQS 。这使得调用能够按顺序处理,并确保每个调用都得到响应。
- 减少并行化 —适用于基于流的事件。这种方法包括减少你的批量和减少一次处理的碎片数量。这样做时,请记住,当映射单个源时,最大调用数等于碎片数。
结论
有三个主要因素会极大地影响 AWS Lambda 性能——冷启动时间、执行时间和并发性。这三个问题直接关系到每个函数的寿命,以及你如何利用函数。因为您是按使用计费的,并且您使用的是函数,所以冷启动时间、执行时间和并发性问题不仅会影响延迟,还会影响计费。
为了确保您的功能正常执行,您应该不断地监视、记录、跟踪和调试。您可以使用 AWS CloudWatch 来设置基于度量的自动化监控。对于日志记录,在代码中插入语句可以帮助您将数据发送到 CloudWatch。您可以使用 AWS X-Ray 对 Lambda 函数进行端到端跟踪。然后,您将能够识别问题并进行调试。
一个月后 AWS 机器学*专业认证
我在一个月内决定参加、准备和通过 AWS 机器学*专业考试的经历
AWS 机器学*专业认证一个月通过迪皮卡巴德
上周,我通过了 AWS 机器学*专业考试。我认为这将是我日常工作中值得学*和有用的东西。我提前一个月预定了日期,并相应地计划去实现它。如果你在这个领域,你的工作与 AWS 相关,我怎么推荐都不为过。在本帖中,我将分享我的备考经验和考试经验本身。
为什么我决定追求这个?
在攻读数据科学硕士学位之前和期间,我一直在数据科学领域工作。在我目前的工作中,我想专注于数据工程相关的工作,在 AWS 中为数据*台创建数据管道。在参加考试之前,我参加过数据科学项目,涉及生产中机器学*部署的项目和使用 AWS 服务的项目。我个人想通过 AWS 了解更多关于生产中的机器学*。我认为这将有助于我在 AWS 中交付端到端的机器学*产品。如今,大多数公司都在寻找这些技能,知道只有数据科学可能是不够的。
在 AWS 网站上有不同级别的认证。我没有从助理级别证书开始,因为我已经有相关的经验来展示这一点,但人们可以通过这些来了解 AWS 提供的大多数服务。我正在寻找机器学*的具体和这个专业证书击中了现场非常好。这也是我直接瞄准机器学*专业考试的原因。就在那时,我决定去约会。我知道,如果我觉得我没有准备好,我可以在考试前 24 小时推迟考试。但是给自己更少的时间促使我坚持这个计划。
评估我是否准备好了
我做的第一件事就是检查他们机器学*专业认证页面上的样题,看看我是否能做到这一点。我不能马上知道答案,但是我知道哪些部分我可以通过学*掌握,哪些部分我已经知道了。机器学*相关的东西,比如 NLP,优化和我熟悉的模型。我认为 AWS 特定的解决方案和内置算法需要我做一些工作。这给了我一个想法,是否有可能在一个月内通过考试。
在同一页上,AWS 给出了考试指南,涵盖了考试将涉及的主要领域。这也能让你更好地了解你已经知道了多少,哪些需要更多的准备。对我来说,在我的一些项目中,我以这样或那样的方式接触过这些领域,所以这是一个很好的指标,表明我能够理解那些主题和用例。
用于准备的材料
以下是我准备时使用的主要资源:
- 关于 AWS 机器学*专业 2020 的 Udemy 课程——动手!
- 关于 AWS 机器学*专业实践考试的 Udemy 课程
- 面向合作伙伴的 AWS 解决方案培训:AWS 上的机器学*—技术(数字)
- 亚马逊 SageMaker:使用标记有地面真相的图像建立一个对象检测模型
- AWS SageMaker 开发者指南
我完全可以推荐前两个备考资源,因为我觉得模拟考试对试题的设计有更好的了解,而且它还涵盖了考试领域的大部分类型和内容。第一门课程涵盖了考试的必要材料和提到的所有领域。这是很好的结构和考试的要点材料。他们没有涵盖 ML 的基础知识和 ML 模型的细节,因为假设如果你参加这次考试,你应该有在实践中使用数据科学的经验。
例如,作为一名经验丰富的机器学*实践者,你应该知道如何优化模型,需要调整哪些参数,以及如何清理数据以改进模型。包括深度学*内置算法何时何地使用。基于用例,您是否应该选择定制模型或在内置模型本身的基础上转移学*等等。但课程不会深入细节。根据考试的先决条件,这是有道理的。
对我来说,课程和考试对解决考试中的实际问题很有帮助。AWS 本身也提供很多数字课程和课堂课程。我发现上面第 3 点和第 4 点提到的一些课程很有用。课程 3 深入探讨了 Udemy 课程中没有的解决方案和各种用例。我喜欢它有几个实验室,这有利于获得一些实践,并对所使用的工具感到舒适。课程 4 是我出于兴趣观看的,如果你感兴趣并且有时间,你也可以浏览一下。
AWS SageMaker 开发人员指南是 SageMaker 的一个很好的参考资料,我发现除了这些课程之外阅读它也很有用。很难在一门课程中涵盖所有内容,所以如果时间允许的话,浏览一下文档是很有用的。特别是我深入研究了内置算法的细节。
规划和准备
在最初的一周半时间里,我浏览了 Udemy 课程和一些与这些主题相关的阅读材料。我进行了第一次模拟考试,我很清楚有什么类型的问题,我需要在课程中注意什么。
在接下来的两个星期里,我一边复*课程,一边记下我发现需要明确记住的要点。除此之外,我还浏览了上面提到的一些 AWS 课程以及它们的文档。
在过去的 5 天里,我进行了多次测试。我还浏览了 AWS 的样题。那时我知道我完全可以参加这次考试,没有必要推迟。
考试经历
说实话,我觉得实际考试比我预想的或准备的要难。我真的很满意难度水*,因为他们认为你有关于实际实现的知识和一般的机器学*知识。我能够在一个半小时内完成考试,而不用回去复*问题。许多人喜欢标记几个问题来复*,你可以在最后不确定的地方回到那些问题上。
我以前从项目中学到的一些知识和我在机器学*方面的数学背景对解决这些问题很有用。这不是我前一个月准备的东西的一部分。人们应该根据基础数据知道选择哪个模型,以及背后的原因是什么。同样,您应该能够为给定的用例以及资源限制等选择正确的内置模型或服务。我觉得我在考试前练*的这个考试为我朝那个方向思考做好了准备,但也准备好发现一些与 ML 主题相关的问题,这些问题可能在上面提到的课程中没有涉及。
希望这份素材和策划经验对你有帮助如果你志在必得的话:)
一如既往——愉快的实验和探索!
AWS SageMaker 更新 2019
2019 年 12 月 re:Invent 发布的新功能
AWS SageMaker 正迅速成为构建和部署机器学*模型的最受欢迎的工具之一。它以易于使用的 AWS 预制模型和一个将定制模型放在 web 端点后面的框架吸引了开发人员和数据科学家。
去年 12 月在 re:Invent 2019 上公布了许多更新。我总结了一些重要的,整理了链接,如果你想了解更多。
希望你觉得有用!
注意:如果你是 SageMaker 的新手,有大量关于 Medium 的文章向你介绍它。( 从这里开始 )
1.多型号集装箱
在发布多型号容器之前,每个 SageMaker 型号都将放在一个单独的 docker 容器中。这是低效的,原因有两个:1)有时你的应用程序有不止一个模型,你想把所有的模型组合成一个单元。2)许多 ML 应用程序将具有相同/相似的依赖关系,这可能没有意义旋转 4 个不同的 docker 容器,它们都具有相同的requirements.txt
文件。
我提到成本节约了吗?(了解更多)
2.部署监控
所以你建立了一个机器学*模型。然后你挣扎了几个月,试图找出如何让它在商业用户手中。在你最终想出如何将它整合到现有的软件和业务流程中之后…现在你就完成了,对吗?
不对。世界在不断变化。您不希望您的模型变得过时,或者意外地对错误的数据做出推论或建议。
队列 SageMaker 模型监视器。这将查看您的训练数据,并自动生成关于每个变量应该是什么样子的规则和统计数据(您也可以自己输入这些数据),然后监控进入模型的输入数据。
来源:https://docs . AWS . Amazon . com/sage maker/latest/DG/model-monitor . html
如果有异常数据,它会给你发消息。如果变量开始偏离模型的训练目标,您可以让它自动触发一个重新训练任务。(了解更多
3.萨格马克实验
已经有一些工具可以帮助跟踪 ML 实验(* Domino 和 Cloudera ),但是开源的并不多。许多数据科学家只是在(在此插入您最喜欢的 ML 框架)中编写他们自己的实验脚本或模块。
AWS 发布了 SageMaker 实验,以及一个 Python SDK 来帮助数据科学家建立和跟踪 ML 实验。下面是该框架中的一些主要概念,可以帮助您入门。(了解更多)
试验:您希望比较的相关试验的集合
试验:多步骤 ML 工作流程的描述。每个步骤都由一个 TrialComponent 描述
TrailComponent :对 ML 工作流中单个步骤的描述
Tracker :用于记录单个 TrialComponent 信息的 python 上下文管理器
4.SageMaker 自动驾驶仪
一旦你使建立模型、运行实验、部署端点和监控生产 ML 应用变得容易;你也可以将整个过程自动化。AutoPilot 和其他 AutoML 软件最大的区别就是透明。曾经有一种二分法,一种是易于使用但难以信任的黑盒 AutoML,另一种是由数据科学家从零开始构建的模型,这种模型更容易信任但更难构建。
AutoPilot 对它正在做的算法、实验、参数和其他一切都是完全透明的。这应该有助于启动数据科学家的工作流程,而不是取代它。数据科学家现在将花更多的时间来解释结果,理解潜在的业务问题,并进行特征工程以改善结果;同时花费更少的时间来确定在随机森林中使用哪个分裂标准或者在支持向量机中使用哪个核。
5.SageMaker 工作室
最后,数据科学家的 IDE。SageMaker Studio 与其他 IDE 的区别在于它专注于可视化数据和跟踪 ML 实验。它利用了其他流行的工具,如 Jupyter 笔记本和与 git 的集成。数据科学家需要了解的一切都可以在单一控制台中获得。它似乎还能与其他 SageMaker 工具很好地配合,用于实验、部署和监控。(了解更多
6.SageMaker 算子
在引擎盖下,SageMaker 是一个 docker 容器。当你从头开始构建一个 SageMaker 模型时,你只是让你的 ML 应用程序结构符合 SageMaker 期望的容器结构。这使得它非常适合 Kubernetes,这是一个非常流行的编排容器化应用程序的工具。
SageMaker 运营商为公司和个人提供了一种将 SageMaker 完成的工作与他们的 K8 系统集成的方式。现在,您可以通过 Kubernetes API 或 kubectl 命令与 ML 训练、调优和推理容器进行交互。(了解更多)
7.从 SQL 命令调用 SageMaker
现在,您可以直接从 AWS (Athena 或 Aurora)中的 SQL 查询调用 SageMaker 模型。这意味着整个组织中的分析师、开发人员和商业利益相关者更容易访问 ML 模型。
文档示例:https://docs . AWS . Amazon . com/Athena/latest/ug/query-ml model . html
对于某些用例来说,这似乎很好。但是说实话,如果您的数据视图以 ML 模型可以接受的方式进行了清理,那么运行批处理预测作业更有意义,然后将预测值保存到另一列的表中。这样,每个记录只调用一次模型,而不是每次对每个记录运行查询时调用。(了解更多
结论
当 SageMaker 在 2017 年推出时,它落后于其他一些早期的 MLops 数据科学家工具。从那以后,它在新特性和新功能方面取得了突飞猛进的进步。随着这些工具变得更加强大,人们只能期待事情以更快的速度变化。
感谢阅读!
AWS 转录总统辩论
如何在 AWS 中设置多说话者声音转录
无论你的政治倾向如何,第一场 2020 年总统选举辩论都是一场垃圾大战。对于一个人来说,很难理解彼此在喊些什么。AWS 转录会怎么做?我们来设置一下,看一看。
数据
一个基本的谷歌搜索找到了音频剪辑。我不得不试了几个,直到我找到一个没有新闻评论的。
https://wgnradio . com/news/audio-first-2020-总统-辩论-总统-唐纳德-特朗普-前副总统-乔-拜登/
设置
我已经有一个 AWS 账户,并在一个月前订阅了亚马逊转录。我所要做的就是点击创建工作。我选的是一般型号,要求多扬声器细分,一共三个扬声器。
转录作业设置-由作者截图一些可选设置,然后点击创建-由作者截图。
音频分割作业比常规作业运行时间长。有道理。考虑到文件长达 90 分钟,20 分钟的运行时间是合理的。
结果呢
我运行了两个任务,一个是多说话人识别,一个是无故障。你可以得到一个翻译预览,你可以下载整个脚本。
文字记录保存在一个 JSON 文件中。我把它转换成文本,并把两套都加载到 Kaggle 上,这样你就可以自己查看了。
https://www . ka ggle . com/silverfoxdss/20-总统辩论-9 月 29 日-音频-文字稿
抄本
好吧,亚马逊直接从盒子里转录也不能解决这个问题!我强调了辩论中我记得有重叠对话的两个地方。是的,我不严谨地使用了“对话”这个词。
“呃,副总统先生,如果参议院共和党人,我们最初在这里谈论的是最高法院,如果参议院共和党人继续下去并确认 Barrett 法官,呃,已经有人谈论结束阻挠议事或甚至打包法院,增加那里的 9 名法官。你称之为总统的干扰。但事实上,并不是总统提出来的。这是你的一些民主党同事在了解国会时提出来的。所以我的问题是你过去拒绝谈论它。今晚你是否愿意告诉美国人民,你是否会支持结束阻挠议事或打包我采取的任何立场,这将成为问题?
问题是美国人民应该发言。你应该出去投票。你现在在投票。投票,让你的参议员知道你的感受有多强烈。让我们现在投票,确保你,事实上,让人们知道在哪里。
参议员们,我不会回答这个问题,因为答案,因为这个问题是激进左派。你能闭嘴吗,伙计?谁在你的名单上?乔,这是你的先生们的。我认为这是不可印刷的。挤满了球场。我们没有付出。
我们已经结束了这一部分。我们将进入第二部分。
那真的很有成效。段亦琛不住地瞎扯,伙计。人民理解,乔。47 年了,你什么都没做。他们明白。好吧。
第二个主题是秘密 19,这是一个非常严肃的主题,所以让我们认真对待它。
这是 JSON 上的一个小片段,它试图将对话分开。它似乎试图通过声音打断对话,但似乎无法识别是哪个说话者。这个 JSON 需要额外的代码来使它可读和有用。
{“transcript”:”gentleman. I think this is unprintable. Pack the court. We have not given. We have ended the segment. We’re gonna move on to the second segment. That was really productive. Segment wasn’t. Yeah.”,”items”:[{“start_time”:”1013.97",”confidence”:”0.368",”end_time”:”1014.8",”type”:”pronunciation”,”content”:”gentleman”},{“confidence”:”0.0",”type”:”punctuation”,”content”:”.”},{“start_time”:”1014.81",”confidence”:”1.0",”end_time”:”1014.93",”type”:”pronunciation”,”content”:”I”},{“start_time”:”1014.93",”confidence”:”1.0",”end_time”:”1015.38",”type”:”pronunciation”,”content”:”think”},{“start_time”:”1015.39",”confidence”:”0.998",”end_time”:”1015.57",”type”:”pronunciation”,”content”:”this”},{“start_time”:”1015.57",”confidence”:”0.998",”end_time”:”1015.75",”type”:”pronunciation”,”content”:”is”},{“start_time”:”1015.76",”confidence”:”0.861",”end_time”:”1016.76",”type”:”pronunciation”,”content”:”unprintable”},{“confidence”:”0.0",”type”:”punctuation”,”content”:”.”},{“start_time”:”1016.76",”confidence”:”0.5",”end_time”:”1017.01",”type”:”pronunciation”,”content”:”Pack”},{“start_time”:”1017.01",”confidence”:”0.782",”end_time”:”1017.11",”type”:”pronunciation”,”content”:”the”},{“start_time”:”1017.11",”confidence”:”0.907",”end_time”:”1017.5",”type”:”pronunciation”,”content”:”court”},{“confidence”:”0.0",”type”:”punctuation”,”content”:”.”},{“start_time”:”1017.51",”confidence”:”0.586",”end_time”:”1017.64",”type”:”pronunciation”,”content”:”We”},{“start_time”:”1017.64",”confidence”:”0.647",”end_time”:”1017.87",”type”:”pronunciation”,”content”:”have”},{“start_time”:”1017.88",”confidence”:”0.976",”end_time”:”1018.27",”type”:”pronunciation”,”content”:”not”},{“start_time”:”1018.27",”confidence”:”0.188",”end_time”:”1018.73",”type”:”pronunciation”,”content”:”given”},{“confidence”:”0.0",”type”:”punctuation”,”content”:”.”},{“start_time”:”1018.74",”confidence”:”0.456",”end_time”:”1018.93",”type”:”pronunciation”,”content”:”We”},{“start_time”:”1018.93",”confidence”:”0.978",”end_time”:”1019.09",”type”:”pronunciation”,”content”:”have”},{“start_time”:”1019.09",”confidence”:”1.0",”end_time”:”1019.56",”type”:”pronunciation”,”content”:”ended”},{“start_time”:”1019.57",”confidence”:”0.693",”end_time”:”1019.73",”type”:”pronunciation”,”content”:”the”},{“start_time”:”1019.73",”confidence”:”1.0",”end_time”:”1020.19",”type”:”pronunciation”,”content”:”segment”},{“confidence”:”0.0",”type”:”punctuation”,”content”:”.”},{“start_time”:”1020.19",”confidence”:”0.981",”end_time”:”1020.28",”type”:”pronunciation”,”content”:”We’re”},{“start_time”:”1020.28",”confidence”:”0.938",”end_time”:”1020.44",”type”:”pronunciation”,”content”:”gonna”},{“start_time”:”1020.44",”confidence”:”1.0",”end_time”:”1020.62",”type”:”pronunciation”,”content”:”move”},{“start_time”:”1020.62",”confidence”:”0.779",”end_time”:”1020.76",”type”:”pronunciation”,”content”:”on”},{“start_time”:”1020.76",”confidence”:”0.779",”end_time”:”1020.84",”type”:”pronunciation”,”content”:”to”},{“start_time”:”1020.84",”confidence”:”1.0",”end_time”:”1020.95",”type”:”pronunciation”,”content”:”the”},{“start_time”:”1020.95",”confidence”:”1.0",”end_time”:”1021.32",”type”:”pronunciation”,”content”:”second”},{“start_time”:”1021.32",”confidence”:”0.998",”end_time”:”1021.83",”type”:”pronunciation”,”content”:”segment”},{“confidence”:”0.0",”type”:”punctuation”,”content”:”.”},{“start_time”:”1021.84",”confidence”:”0.908",”end_time”:”1021.97",”type”:”pronunciation”,”content”:”That”},{“start_time”:”1021.97",”confidence”:”1.0",”end_time”:”1022.1",”type”:”pronunciation”,”content”:”was”},{“start_time”:”1022.1",”confidence”:”0.998",”end_time”:”1022.4",”type”:”pronunciation”,”content”:”really”},{“start_time”:”1022.41",”confidence”:”1.0",”end_time”:”1023.15",”type”:”pronunciation”,”content”:”productive”},{“confidence”:”0.0",”type”:”punctuation”,”content”:”.”},{“start_time”:”1023.15",”confidence”:”0.998",”end_time”:”1023.53",”type”:”pronunciation”,”content”:”Segment”},{“start_time”:”1023.53",”confidence”:”0.72",”end_time”:”1023.97",”type”:”pronunciation”,”content”:”wasn’t”},{“confidence”:”0.0",”type”:”punctuation”,”content”:”.”},{“start_time”:”1024.44",”confidence”:”0.024",”end_time”:”1024.5",”type”:”pronunciation”,”content”:”Yeah”},{“confidence”:”0.0",”type”:”punctuation”,”content”:”.”}]}]},{“start_time”:”1021.97",”end_time”:”1023.97",”alternatives”:
结论
唷!转录和 JSON 就像在电视直播中一样令人困惑。我给你们留下了辩论文本的文字云。在不同的辩论中比较它们会很有趣。在市政厅会议上,气氛变得更加乐观和乐观了吗?
辩论词云—作者截图
AWS 和 Udacity 为高级机器学*工程师纳米学位提供奖学金
偶尔,伟大的公司会与 Udacity 合作,提供奖学金,帮助学生建立数据科学领域非常受欢迎的技能。
这一次,亚马逊网络服务赞助了 AWS 机器学*奖学金计划,在该计划中,我们将有机会学*基础知识以及更高级的技能,成为专业的机器学*工程师,同时学*使用 AWS 生态系统中一些最受欢迎的工具和技术。
要求
- 申请人必须年满 18 岁🔞
谁应该申请
该计划面向所有技能集的开发者,从初级和中级机器学*专业人员。
它是如何工作的
该计划 100%在线进行,分为两个阶段:
- 第一阶段:奖学金基础课程
- 第二阶段:优达城纳米学位项目的全额奖学金
第一阶段:奖学金基础课程
在基础课程中,学生将学*如何编写生产级代码和练*面向对象编程,以及在现实世界场景中应用的深度学*技术。
“该课程将帮助学生发展面向对象的编程技能,包括编写干净的模块化代码,并介绍关键的 AWS 机器学*技术,即亚马逊人工智能服务和亚马逊人工智能设备,并在 AWS 实验室环境中应用他们的技能。”
从 2020 年 5 月 19 日起,您可以免费注册基础课程,并在 2020 年 7 月 31 日前完成。
如果你从 5 月份开始学*,这门课程每周将花费你大约 3-5 个小时,但是你可以按照自己的进度学*。一旦你完成了课程,你会收到一份完成课程的证书。最后,您将收到参加在线评估测验(在上述期限内)的说明,以便有资格参加第 2 阶段。
第二阶段:Udacity 纳米学位项目的全额奖学金
前 325 名得分者将获得 Udacity 热门纳米学位项目的全额奖学金: AWS 机器学*工程师。
这些纳米学位的价格通常在 400 美元/月左右,所以这绝对是一个你不想错过的机会!
在这个纳米学位中,你将有机会学*先进的机器学*技术和算法。
“该计划将提供世界一流的课程、突破性的课堂体验、行业领先的教师、全面的项目审查和全套职业服务。”
完成整个纳米学位项目的第二阶段学生将被授予纳米学位证书。
在为期两个月的项目中,纳米学位的学生应该每周投入大约 10 个小时。
如何注册
报名于 2020 年 5 月 19 日开始。然而,你可以现在就注册在课程开启(虚拟)大门时得到通知。
一些个人想法
即使你没有进入第二阶段,我认为完成基础课程也是值得的,因为这是一个很好的机会来强化 ML 的所有基础知识,并了解 AWS 生态系统中这些高度按需的技术。
你可以和同一个社区的其他学生互动,互相帮助。此外,如果你正在寻找开始学* ML 的动力,这是一个巨大的挑战,要养成每周学*一点的*惯,同时有一种鼓励你继续进步的社区意识。
我一定会报名参加这个课程,如果你想加入,请告诉我!✨
感谢你的时间,我真的希望这篇文章是有益的😊
下一集再*!🚀
概率公理——理解基础
概率论基础&几个证明
这篇文章将会很简短。关于技术知识,我通常支持对正在使用的方法有坚实的基础和扎实的理解。我通常不喜欢记忆任何东西,并尽可能避免这样做。相反,我专注于发展概念的坚实基础,从这些基础中我可以用数学方法推导出我可能需要的任何东西。
下面是 Andrew Kolmogorov 在 1933 年提出的 Kolmogorov 公理。这三个公理构成了概率论的基础,概率中的其他定理或结果都可以从概率论中推导出来。我一直觉得有趣的是,不管一个概率定理或结果变得多么复杂,它都可以来源于这三个基本公理。我觉得简单迷人。下面是从这三个公理推导出的几个简单的概率定理。对 Medium 的快速搜索显示,这些证据和关系(据我所知)还没有被简单地组织在一篇文章中。这些都是值得了解的概念。
所以让我们开始吧:
三个概率公理:
示例定理和证明:
如上所述,这三个公理构成了概率论的基础,从这个基础上可以推导出概率中的其他定理或结果。下面是五个简单的定理来说明这一点:
*注意,在下面的证明中,M.E .代表“互斥”
最后的想法
希望以上有*地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练*。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在 LinkedIn 上与我联系,并在 Medium 上 关注我的更新!
Azure Automated ML 倾听他们的设计师
本 autoML 系列的第 3 部分,微软,绝地大师
图片由皮克斯拜的 Gerd Altmann 提供
在这个 autoML 系列的第三部分中,我将继续测试各种 autoML 工具的易用性。专注于基本的开箱即用产品和寻找免费试用,我进入了微软的世界。我将我们的“沃森”训练文件发送到微软的 autoML 产品 Azure Automated ML 中。总的来说,Azure autoML 的用户体验比 AWS AutoPilot 和 Google autoML Tables 都要好得多。这种体验感觉更加完美,尽管它仍处于预览模式。你几乎可以感觉到设计师对屏幕的布局和导航有发言权。干得好!
为什么选择 Azure 自动化 ML?
微软是绝地大师!最近关于五角大楼云计算合同的裁决已经把投资和开发放回了首要位置。这种资金注入只能意味着机器学*/人工智能将获得一些高质量的关注。当 ML studio 处于“预览”状态时,它似乎可以正常工作。
预告——作者截图
设置
如果您还没有帐户,您可以注册 Azure 免费订阅。这笔交易将给你 200 美元的信用额度,你可以在 30 天内使用。
我遵循了本教程中的设置。当它引导你完成各个步骤时,我发现屏幕非常直观。刚开始在门户—https://portal.azure.com/#home。
自动化 ML 可通过机器学*服务访问。自动化 ML 需要一个企业版,所以当你遇到它的时候选择那个选项。
作者截图
一旦服务为你准备好了,工作室就可以使用了。主页上有明显的自动 ML 选项。
作者截图
数据
为了保持本系列中各种工具的*等性,我将坚持使用 Kaggle 培训文件。矛盾,我亲爱的华生。使用 TPUs 检测多语言文本中的矛盾和蕴涵。在这个入门竞赛中,我们将句子对(由一个前提和一个假设组成)分为三类——蕴涵、矛盾或中性。
6 列 x 13k+行— Stanford NLP 文档
- 身份证明(identification)
- 前提
- 假设
- 朗 abv
- 语言
- 标签
模型培训成本
当谷歌挥舞着“免费”的 200 美元时,我没有对集群的成本进行太多研究。与此同时,定价也不像 AWS 和谷歌那样对我有利。好奇。我确实找到了一个 doc,但是并不简单。
我在控制台上查看账单!检查您的账单!不,这是在更险恶的成本管理之下。训练这个例子让我的谷歌雄鹿总数减少了 50 美分。还不错。
作者截图
加载数据
这个工具的一个很好的特性是,您可以将数据作为当前工作流的一部分进行加载。不需要走出工作室去谷歌存储。不要在屏幕上跳来跳去。
作者截图
训练您的模型
接下来,我必须配置训练运行。我使用低优先级设置而不是专用资源创建了一个新的计算集群。使用低优先级一般更便宜。我想尽可能地使用我的 200 美元。
作者截图
在下一个屏幕上,分类被选中,我启用了深度学*。我应该仔细阅读一下附加的配置设置,因为我意识到我的最大运行时间是 24 小时。不用了,谢谢。
作者截图
有一个状态让您知道进程在哪里。我最喜欢的状态是生成数据集功能。什么样的特征?
作者 gif
培训的时候,我在界面上戳来戳去。我能够看到输入文件的数据配置文件。
作者截图
评估培训结果
当模特们完成训练后,领队会被挑选出来并显示在仪表盘上。令我失望的是,算法名称并没有链接到那些算法的细节。他们只是把我带到一个类似的详细信息页面。我将不得不假设他们是[sklearn.preprocessing](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.preprocessing)
。MaxAbsScaler 和随机森林集合。
作者截图
有一个标签叫做数据护栏。概念不错,很高兴看到它被收录。我希望在这个页面上有更多信息的工具提示。我尝试搜索数据护栏,但很难找到细节。即使信息很少,我也喜欢。它会重新出现在我的幻想 autoML 工具。
作者截图
点击 Go,看看会发生什么。
开箱即用的实际结果?这些模型的表现不如谷歌模型。我喜欢提供的图表,很明显,它的表现比机会好不了多少。据我和下一位数据科学家所知,即使对于 autoML,也需要进行超参数调优,但我并没有过多关注实际的指标结果。因此,我想坚持基本原则,以保持它跨*台。
作者截图
我很喜欢他们列出了挑战者,而不仅仅是获胜的模特。挑战者的可用性是至关重要的,因为在某些情况下,您可能不得不放弃最准确的模型,而选择一个具有更好解释能力的模型。
作者截图
说到可解释性,我很欣赏这个想法,但结果是缺乏的。
作者截图
结论
我可以看到自己再次使用 Azure 机器学*工作室。总的来说,我对这个工作流程非常满意。这种体验是无缝的,尽管 autoML 输出还有改进的余地。有用的可视化是必不可少的,特别是当我们试图说服我们的商业赞助商,我们有足够的东西来推进一个项目。
伟大的可视化的价值将在我的下一篇关于 DataRobot 的文章中强调。但是你为好东西付钱。这个工具对于没有企业预算的人来说是遥不可及的。H2O 自动驾驶仪也一样。但是它们很漂亮。
如果您错过了本系列的前两篇文章:
[## AWS Sagemaker Studio 自动驾驶仪准备好迎接黄金时段了吗?
带有一些评论的自动驾驶界面演示
towardsdatascience.com](/is-aws-sagemaker-studio-autopilot-ready-for-prime-time-dcbca718bae7) [## 免费体验 Google autoML 表格
autoML 工具用户体验评论系列之二。
towardsdatascience.com](/experience-google-automl-tables-for-free-d5648ae3d0e5)
Azure Data Studio 和 SSMS——我应该使用哪个?
Azure 数据工作室还是 SSMS?为什么不是 Azure Data Studio 和 SSMS?看看你如何能从两个世界中取长补短
题目中的问题已经变得非常流行,而且会变得越来越久而久之化。由于微软在 2018 年 9 月推出了 Azure Data Studio 并在此期间大力投资于该工具的改进,看起来旧的 SQL Server Management Studio 注定要退休了(当之无愧)……
但是,是那样的吗?
作为一名 SQL 开发人员,他每天都在编写查询,我将尝试根据我迄今为止的发现给出一些观察结果,特别强调 Azure Data Studio ,因为我相信我们大多数人已经非常熟悉 SSMS 。
Azure 数据工作室
在我深入了解“新街区小子”的一些很酷的功能之前,先做个简短的介绍。当我听到新工具的名字时,我并不打算深入测试它,因为“Azure”部分并没有引起我的特别兴趣。然而,在我听到 Ben Weissman 今年 1 月在 SQL Saturday Vienna 上的发言后,他解释说“Azure”word 并不一定意味着你需要将该工具与 Azure palette of products 结合使用,我决定尝试一下。
所以,我的第一印象是:微软给这个 IDE 命名相当误导!为什么称之为“ Azure Data Studio ”,连接 Azure 只是其中一个选项?您还可以连接到本地 SQL Server 数据库,就像之前的 SSMS、一样,但您也可以连接到大数据集群(SQL Server 的最新功能,在 2019 年版中推出)。
Azure Data Studio 的主要优势在于其可移植性——虽然 SSMS 只能在 Windows *台上运行,但广告也可以在 Linux 和 macOS 上运行。这是一个巨大的进步,符合微软向非 Windows 世界的全面扩张。
与 SSMS 的另一个巨大区别是,你可以使用笔记本,并在其中编写 SQL、Python、Spark 或 Scala 脚本。我不能详细说明,因为我还没有使用这个特性(我是一个传统的 SQL 家伙),但与 SSMS 相比,它无疑为更复杂的用法提供了更多的灵活性。
好了,关于 ADS 和 SSMS 的特征和区别的一般性描述已经足够了。我将尝试加粗一些 Azure Data Studio 提供的简洁功能:
#1 对象定义
当我编写查询时,我经常需要检查数据库对象定义。例如,查看基础数据类型是日期时间还是日期时间 2 。当然,这可以在 SSMS 使用一些第三方插件来实现(顺便说一下,我喜欢 SSMS 升压),但在广告中这很简单:
只需标记要检查的对象,右键单击,然后在“查看”下选择“查看定义”。您将立即看到所选对象的定义:
#2 黑暗主题
据我所知,SSMS 仍然缺乏黑暗模式,我知道很多开发者都渴望这一点。在广告中,黑暗模式就在那里!
进入 文件- >首选项- >颜色主题 ,选择您想要的布局:
看起来很酷,哈?
#3 快速可视化查询结果
这真的很有用,我在使用 Azure Data Studio 时广泛使用了它。它可以让您对查询返回的数据有一个简要的了解,这样您就可以直接执行快速的数据分析,并检查有多少个空值,是否有一些异常值,等等。
运行该查询后,我可以选择右侧的图表图标,并立即可视化我的结果:
此外,正如您在上面的图片中所注意到的,我可以定义整套参数并调整结果的视觉外观。
#4 源代码控制
Azure Data Studio 附带了 Git 源代码管理器(SCM ),因此与 SSMS 相比,源代码管理成为最大的优势之一!关于如何执行代码源代码控制的更多细节可以在官方的 Azure Data Studio 文档中找到。
#5 轻松导出到 Excel/CSV/JSON
在许多情况下,您需要为用户提供快速的查询结果。现在,不需要复制/粘贴查询结果或使用一些外部插件来处理这些简单的请求。只需点击一下,你就可以开始了!
在右侧,您只需选择是将结果导出为 CSV、Excel、JSON、XML,还是将其可视化(如前一篇技巧文章)。
#6 定制洞察/仪表板
这一个可以很容易地拿第一,但是我故意把它留到最后。想象一下,您可以在一个地方拥有所有相关的度量,比如当前运行的查询、死锁、索引碎片等的数量。!
我将演示如何为索引碎片检查创建一个仪表板,但是您可以使用与您的监视相关的查询轻松地扩展您的仪表板。
SELECT st.index_id
,name AS indexName
,avg_fragmentation_in_percent AS frgPrct
,fragment_count AS frgCnt
, avg_fragment_size_in_pages AS frgPages
FROM sys.dm_db_index_physical_stats (DB_ID('StackOverflow2013'), NULL, NULL, NULL, NULL) AS st
INNER JOIN sys.indexes AS i ON st.object_id = i.object_id AND st.index_id = i.index_id
ORDER BY avg_fragmentation_in_percent DESC
一旦我执行了这个查询,我选择右边的图表图标:
我将把这个查询保存在桌面上(你可以把它保存在任何你喜欢的文件夹中)。然后,我选择表格图表类型,并单击结果集上方的 Create Insight:
一旦我这样做了,JSON 代码就会生成。然后,转到视图选项卡,选择命令调板,然后选择首选项:打开用户设置。
搜索仪表板。Database.Widgets 并在 settings.json 中选择编辑。
在“dashboard.database.widgets”键中,粘贴在前面某个步骤中创建的 JSON 代码。
保存 settings.json 文件,导航到 StackOverflow2013 数据库,右键单击它并选择“管理”。如您所*,我们新创建的小部件被固定在一个仪表板上,我们可以轻松地监视索引碎片的情况。
您可以创建多个不同的小部件,并将它们固定在一个仪表板上,这样您就可以快速了解数据库的关键指标。
定论
尽管 Azure Data Studio 确实是一个令人敬畏的工具,但它仍然缺乏一些关键功能,因此不能被视为 SSMS 的直接替代品。对于 DBA 任务来说尤其如此,SSMS 作为一个成熟的工具提供了更多的选择。
在我看来, 这两个工具都将留在 这里,至少在未来一段时间内!
微软不断升级 Azure Data Studio,我将专门撰写单独的文章来介绍一些最近添加的功能,如 SQL 代理作业,或更常*的任务,如使用估计和实际的查询执行计划来优化您的查询。
老实说,我仍然比 ADS 更频繁地使用 SSMS(可能只是因为我更*惯它),但我相信每个开发者都应该至少尝试一下 Azure Data Studio。
成为会员,阅读媒体上的每一个故事!
订阅这里获取更多有*地的数据文章!
Azure 机器学*服务:第 1 部分—简介
在微软 Azure 公共云*台上开发和部署端到端人工智能解决方案的入门系列。
图文鸣谢:微软为 Azure 机器学*
前言
自从我成功通过了微软的 DP-100 考试认证,即“ 在 Azure 上设计和实现数据科学解决方案”。我很想以 KT 的形式写点东西,这样将来有一天它可以帮助别人。因此,在牢记这句格言的同时,我在此发表了关于 Azure 机器学*服务(Azure ML Service)的第一篇文章。因为这是第一篇文章,所以我将对这个完全由云管理的服务做一个非常基本的介绍。稍后,我会发表更多关于高级主题的文章,因此这将是一个系列。
请注意,对于那些对 Azure 和基础知识有所了解的人来说,这篇文章和接下来的一系列文章会非常直观,对于其他对 Azure 了解有限的人来说,这篇文章是一个知识来源,对 AI/ML 开发和部署的云方面有非常高的概述。此外,微软官方文档页面上有一些资源可以帮助开始使用这项服务。
[## Pankaj Jainani -云解决方案架构师- LinkedIn
我是云解决方案架构师、人工智能工程师、DevOps 顾问、Scrum Master、技术经理……
www.linkedin.com](https://www.linkedin.com/in/p-jainani/)
介绍
Azure Machine Learning(Azure ML)是一个基于云的服务,用于创建和管理机器学*解决方案。它旨在帮助数据科学家和机器学*工程师利用他们现有的数据处理和模型开发技能&框架。此外,帮助他们将工作负载扩展、分发和部署到云中。用于 Python 的 Azure ML SDK 提供了一些类,我们可以在 Azure 订阅中使用它们来处理 Azure ML。
图形致谢:Microsoft Azure ML 服务文档
入门指南
Azure ML 资源的工作区
Workspace 是所有 AML 资产的逻辑容器:计算、存储、数据、脚本、笔记本、实验(他们的版本)、指标、管道和模型(他们的版本)。
Azure ML 的下图描述了逻辑工作区:
图形致谢:Microsoft Azure ML 服务文档
从 Azure Portal 或 AML SDK 创建工作空间后,我们必须连接到工作空间来执行我们的机器学*操作。因此,我们需要从从 SDK 导入以下包开始—
导入包和库
将所有包加载到笔记本后,我们必须通过传递 AML 服务名称、Azure 资源组名称和 AML 服务的 Azure 订阅 ID 的值,使用Workspace.get()
方法实例化工作区对象ws
。
还有一种方法可以使用 config.json 文件实例化 Workspace 对象。这个方法在笔记本里有解释。
实验
AML 服务实验是一个命名的过程,通常运行一个脚本或管道,它可以生成指标和输出,并在 Azure 机器学*工作区中被跟踪。我们可以用不同的数据、代码或设置多次运行相同的实验。该实验定义如下:
定义并开始实验
一旦提交了实验,run context
用于初始化、跟踪和完成实验。在run context
中,我们可以从实验的执行中捕获各种度量,这些度量与其run
对象相关联。
使用运行上下文从实验运行中获取指标。
在上面的代码中,我们可以使用run.log()
捕获一个单值,使用run.log_image()
捕获一个度量图像的图形表示,类似地,使用run.log_list()
方法捕获一个值列表。
实验细节
实验完成后,run 对象用于获取实验实例的信息和细节:
抓住实验的细节
这些语句将产生与实验、元数据、指标和日志相关的输出。
实验仪表板
以下是 Azure Portal 中为每个实验运行提供的仪表盘:
- 实验的名称是“简单实验”
- 给出了每次实验的细节
实验仪表板
实验的细节
接下来呢?
这是一系列博客帖子,包含各种 Azure 机器学*功能的详细概述,其他帖子的 URL 如下:
- 岗位 1 (本) : 蔚蓝机器学*服务:第一部分——简介
- 帖子 2: Azure 机器学*服务——运行一个简单的实验
- 帖子 3: Azure 机器学*服务——训练一个模型
- 帖子 4: Azure 机器学*服务——我的数据在哪里?
- 帖子 5: Azure 机器学*服务——目标环境是什么?
接我上LinkedIn进一步讨论**
** [## Pankaj Jainani -云解决方案架构师- LinkedIn
我是云解决方案架构师、人工智能工程师、DevOps 顾问、Scrum Master、技术经理……
www.linkedin.com](https://www.linkedin.com/in/p-jainani/)
参考
[1]代码笔记本— Azure 机器学*—简介,Kaggle。
【2】Azure 机器学*服务官方文档,微软 Azure。**
Azure 机器学*服务——运行一个简单的实验
第 2 部分:如何使用 Azure 机器学*服务编写一个 ML 模型并执行实验。
摘要
在本系列的 第一部分 中,我主要介绍了关于 Azure 机器学*(AML)服务的概述和介绍,在那篇文章中,我介绍了设置、配置和这种云管理服务提供的各种 OOB 功能。我还详细讨论了反洗钱工作区、反洗钱实验和反洗钱服务实验的仪表板。
在第 2 部分中,我将讨论如何创建一个独立的实验脚本来封装云上 ML 模型的核心实现,即通过重复实验运行进行训练和跟踪。此外,我将演示如何设置执行实验脚本所需的先决环境和配置。
这篇特别的帖子摘自 Kaggle 笔记本托管— 此处。使用链接来设置和执行实验
机器学*实验脚本
一旦连接到 Azure 机器学*工作空间,下一步是定义一个模型实验脚本,这是一个非常通用的 python 脚本,它从实验的“工作空间”计算上下文中加载和执行。这还要求数据文件的根目录(文件夹)必须与加载该脚本的位置相同,如下所示
图 1: 实验脚本快照——必须导入 azureml.core.Run 类并执行其 get_context() 方法
实验输出文件夹— 大多数情况下,运行一个实验会生成一些输出文件,例如保存的模型,这些文件保存在工作区的输出文件夹中,如下图所示—
os.makedirs("outputs", exist_ok=True)
joblib.dump(value=model, filename='outputs/iris_simple_model.pkl')
*# Complete the run*
run.complete()
也可以在如下所示的实验文件代码中使用 Run 对象的 upload_file 方法,这使得在计算上下文中写入 outputs 文件夹的任何文件都可以在运行完成时自动上传到运行的 outputs 文件夹,例如
run.upload_file(name='outputs/IRIS.csv', path_or_stream='./sample.csv') # upload from local
进行实验
运行配置和脚本运行配置
在实现 ML 模型的脚本准备好之后,下一步是定义*RunConfiguration*
对象——它定义脚本将在其中运行的 Python 环境,以及*ScriptRunConfig*
对象——,它将运行环境与脚本相关联。下面的代码片段通过调用RunConfiguration()
方法实例化了 Python 环境,并且ScriptRunConfig()
封装了相同的脚本执行环境:
from azureml.core import Experiment, **RunConfiguration, ScriptRunConfig***# create a new RunConfig object*
experiment_run_config = **RunConfiguration()**
experiment_run_config.environment.python.user_managed_dependencies = True*# Create a script config*
src = **ScriptRunConfig**(source_directory=experiment_folder,
script='iris_simple_experiment.py',
run_config=experiment_run_config)
*RunConfig*
对象还允许额外包含脚本执行所必需的 Python 包。
仪表板结果
访问Azure Machine Learning Studio来导航样本实验运行,并在仪表板上的结果中验证结果。在这里,显示了实验的运行历史的全部细节,如下所示——运行的统计、历史、结果、度量、日志、输出、错误、诊断等的细节..可从仪表板上轻松获得:
图 2:Iris-sample-experiment 的仪表板结果视图,观察运行统计和其他可用指标。
图 3: 更详细的结果也可用于任何选定的实验,例如试验# 20
图 4: Outputs 文件夹中有一个使用实验脚本上传的模型文件
结论
在系列的这一部分,我试图涵盖 Azure 机器学*服务的最基本概念,即准备和执行机器学*实验并生成模型二进制文件。在下一篇文章中,我将介绍一种稍微高级一点的方法来设置和控制脚本的执行环境,安装或更新所需的依赖项和包。所以请保持关注!
接下来呢?
这是一系列博客帖子,包含各种 Azure 机器学*功能的详细概述,其他帖子的 URL 如下:
- 帖子 1: Azure 机器学*服务:第一部分——简介
- 岗位 2 (这个) : Azure 机器学*服务——运行一个简单的实验
- 帖子 3: Azure 机器学*服务——训练一个模型
- 帖子 4: Azure 机器学*服务——我的数据在哪里?
- 帖子 5: Azure 机器学*服务——目标环境是什么?
与我连线LinkedIn进一步讨论
参考
[1]笔记本&代码— Azure 机器学*—简介,Kaggle。
【2】Azure 机器学*服务官方文档,微软 Azure。
Azure 机器学*服务—训练模型
第 3 部分:学*如何使用估计器训练模型的高级概念
摘要
到目前为止,在这一系列文章中,我已经能够简单介绍 Azure 机器学*服务(AML)的,并且能够运行一个简单的实验。在这篇文章中,我将介绍实验脚本的参数化,配置脚本环境、框架和依赖关系的不同方法。此外,如何在培训结束后向 AML 服务注册模型。
这篇特别的帖子摘自 Kaggle 笔记本托管— 此处。使用设置的链接来执行实验。
即兴创作——简单的实验
在开始讨论 AML 中的数据存储和数据集管道之前,我将简要介绍一些高级配置选项,以运行前面描述的简单实验。
脚本参数
在文章# 2,中,我讨论了使用定制 Python 脚本实现一个简单的 ML 实验,但是那个脚本文件有一个问题,它是简单的和静态的,所以我们如何改进实验的脚本,以便它可以接受一系列值并有效地训练模型?是的,答案是参数化脚本——因此在 AML 服务环境中,任何实验脚本的参数值都可以按如下方式实现:
*****### .... ###*run = Run.get_context()**##Adding the parameter: regularization rate
parser = argparse.ArgumentParser()
parser.add_argument('--reg_rate', type=float, dest='reg', default=0.01)
args=parser.parse_args()
r = args.reg**run.log("model regularization", np.float(r))*# load the data from a local file*
data = pd.read_csv('IRIS.csv')
X = data[['sepal_length', 'sepal_width','petal_length','petal_width']].values
X=StandardScaler().fit_transform(X)
Y= (data['species']).map(lambda x: 0 if x=='Iris-setosa' else (1 if x=='Iris-versicolor' else 2))*#Split data into train and test set*
X_train, X_test, Y_train, Y_test = train_test_split(X,Y, test_size=0.25, random_state=1234)*# fit the model:* ***with extra parameter***
model = LogisticRegression(***C=1/r,*** solver='lbfgs', multi_class='multinomial').fit(X_train,Y_train)Y_pred = model.predict(X_test)
accuracy = np.average(Y_test == Y_pred)
print("accuracy: " + str(accuracy))
run.log("Accuracy", np.float(accuracy))*###....###*****
评估者 API
虽然运行配置和脚本运行配置允许开发人员运行基于脚本的实验来训练机器学*模型,但 AML 服务也提供了更好的抽象,将它们的功能封装到单个对象中,称为估计器。典型的用例是当运行配置变得太复杂而无法为某些依赖项和框架进行配置时。它可用于最常用的机器学*框架,即 Scikit-Learn、PyTorch 和 Tensorflow。****
下面的代码实现了通用估计器类的对象来运行训练实验。Estimator()
构造器通过使用compute_target
参数来参数化实验执行的计算资源的引用,例如容器、VM 或本地计算。通用估计器不包括 scikit-learn 包,因此,我们需要传递参数conda_packages
的值。另外,我们可以通过使用构造函数方法Estimator()
的script_params
参数来传递脚本的参数集合。
**from azureml.train.estimator import Estimator
from azureml.core import Experiment
from azureml.widgets import RunDetails*# Create an estimator*
estimator = Estimator(source_directory=experiment_folder,
entry_script='iris_simple_experiment.py',
compute_target='local',
use_docker=False,
**script_params = {'--reg_rate': 0.07},**
conda_packages=['scikit-learn']
)***# COMMENTED - SKLearn as an estimator***
*#estimator = SKLearn(source_directory=experiment_folder, entry_script='iris_simple_experiment.py', compute_target='local', use_docker=False)**# Create an experiment*
experiment_name = 'iris-estimator-experiment'
experiment = Experiment(workspace = ws, name = experiment_name)*# Run the experiment based on the estimator*
run = experiment.submit(config=estimator)*# Get Run Details*
RunDetails(run).show()*# Wait to complete the experiment. In the Azure Portal we will find the experiment state as preparing --> finished.*
run.wait_for_completion(show_output=True)**
AML SDK 包括特定于框架的 estmators 类,它允许开发人员轻松配置框架依赖关系,例如,用于 SKLearn 或 Tensorflow 或 PyTorch。代码中还有一个 SKLearn 估计器的例子(注释)。
注册模型
完成 ML 模型的训练后,我们必须使用它进行推理,因此,通过 AML 服务,我们可以注册模型,并在需要时使用它进行推理。
下载模式:运行对象的download_file()
或download_files()
方法用于将输出文件下载到本地文件系统。
**# List the files generated by the experimentfor file in run.get_file_names():
print(file)# Download a named filerun.download_file(name='outputs/model.pkl', output_file_path='model.pkl')**
为了注册模型和相关的元数据——名称、版本、标签,我们可以编写以下内容:
**from azureml.core import Modelrun.**register_model**(model_path='outputs/iris_simple_model.pkl', model_name='iris_estimator_model', tags={"Training Context":"Estimator", "Script Context":"Parameters"},
properties={"Accuracy":run.get_metrics()["Accuracy"]})**
最后,要查看在反洗钱服务中注册的模型,可以使用以下信息
**for model **in** Model.list(ws):
print(model.name, ":", model.version)
print("**\n**Tag List")
for tag_name **in** model.tags:
tag = model.tags[tag_name]
print(tag_name, tag)
print("**\n**Properties List")
for prop_name **in** model.properties:
prop = model.properties[prop_name]
print(prop_name,prop)**Output** iris_estimator_model : 4Tag List
Training Context Estimator
Script Context ParametersProperties List
Accuracy 0.9736842105263158
IRIS_model : 1Tag List
Training context Pipeline**
结论
随着这篇文章的结束,到目前为止,我们能够涵盖反洗钱服务的最基本的方面。我们能够运行一个简单的实验并训练一个 ML 模型。此外,使用 API(如运行配置、脚本运行配置和估算器)允许我们创建一个具有相关依赖关系的环境来动态运行实验,而不考虑计算环境。
接下来呢?
这是一系列博客帖子,包含各种 Azure 机器学*功能的详细概述,其他帖子的 URL 如下:
- 帖子 1: Azure 机器学*服务:第一部分——简介
- 帖子 2: Azure 机器学*服务——运行一个简单的实验
- 岗位 3 (这个) : 蔚蓝机器学*服务——训练一个模型
- 帖子 4: Azure 机器学*服务——我的数据在哪里?
- 帖子 5: Azure 机器学*服务——目标环境是什么?
与我连线LinkedIn进一步讨论
参考
[1]笔记本&代码— Azure 机器学*—模型训练,Kaggle。[2]Azure Machine Learning—Estimator API,URL
【3】Azure 机器学*服务官方文档,微软 Azure。
Azure 机器学*服务—我的数据在哪里?
第 4 部分:数据集和数据存储简介
摘要
或许这就是云机器学**台的重要方面之一。每个机器学*问题的迫切需要是它的数据。这些数据大多来自各种不同的来源,然后经过提炼、修剪和处理,用于各种分析,并用于 ML 模型。由于这个原因,云机器学*定义了数据管理 SDK,它可以定义、保护和管理云*台中的数据源。
这篇特别的文章摘自 Kaggle 笔记本,这里是这里是。使用设置的链接来执行实验。
数据存储和数据集
数据存储
数据存储是一种数据管理功能,是由 Azure 机器学*服务(AML)提供的 SDK。它使我们能够连接到各种数据源,然后这些数据源可以用于将它们摄取到 ML 实验中,或者写入来自相同实验的输出。Azure 提供各种*台服务,这些服务可以作为数据源,例如 blob store、data lake、SQL database、Databricks 等等。
Azure ML workspace 与 Azure 中定义的数据存储有着天然的集成,比如 Blob 存储和文件存储。但是,执行 ML 模型可能需要来自其他外部来源的数据及其依赖性。因此,AML SDK 为我们提供了将这些外部资源注册为模型实验数据源的方法。定义数据存储的能力使我们能够跨多个实验重用数据,而不管实验运行的计算环境如何。
注册数据存储
如前所述,数据存储有两种类型——默认和用户调配,如存储 Blobs 容器或文件存储。要获取工作区的默认数据存储列表,请执行以下操作:
***# get the name of defult Datastore associated with the workspace.***
default_dsname = ws.get_default_datastore().name
default_ds = ws.get_default_datastore()
print('default Datastore = ', default_dsname)
使用 AML SDK 注册数据库—
from azureml.core import Workspace, Datastore
ws = Workspace.from_config()**# Register a new datastore**
blob_ds = Datastore.register_azure_blob_container(workspace=ws,
datastore_name='blob_data',
container_name='data_container',
account_name='az_store_acct',
account_key='11223312345cadas6abcde789…')
要设置或更改默认数据存储—
ws.set_default_datastore('blob_data')
从 Azure ML 查看—数据存储
将文件上传到数据存储
将本地文件从本地系统上传到远程数据存储。这允许使用远程数据位置直接运行实验。目标路径是文件在远程数据存储位置的路径。一旦文件上传到数据存储,就会返回‘引用路径’。当您想要在实验脚本中使用数据存储时,我们必须向脚本传递一个数据引用
default_ds.upload_files(files=['../input/iris-flower-dataset/IRIS.csv'],**target_path**='flower_data/',overwrite=True, show_progress=True)**flower_data_ref** = default_ds.path('flower_data').as_download('ex_flower_data')
print('**reference_path** = ',flower_data_ref)
尝试数据存储
如上所述,一旦我们有了对数据存储的引用,我们需要将这个引用传递给一个实验脚本,作为来自估计器的脚本参数。此后,可以检索该参数的值,然后将其用作本地文件夹—
####run = Run.get_context()*#define the regularization parameter for the logistic regression.*
parser = argparse.ArgumentParser()
parser.add_argument('--reg_rate', type=float, dest='reg', default=0.01)***#define the data_folder parameter for referencing the path of the registerd datafolder.***
parser.add_argument('--data_folder', type=str, dest='data_folder', help='Data folder reference', default=0.01)
args=parser.parse_args()
r = args.reg
ex_data_folder = **args.data_folder**####
将估计值定义为—
####run = Run.get_context()estimator = SKLearn(source_directory=experiment_folder,
entry_script='iris_simple_experiment.py',
compute_target='local',
use_docker=False,
script_params = {'--reg_rate': 0.07,
'--**data_folder':flower_data_ref**}
*# a****ssigned reference path value as defined above.***
)####
' —数据文件夹'接受数据存储文件夹引用;上传文件的路径。该脚本将从作为参数传递给它的数据引用中加载训练数据,因此我们需要设置脚本参数来传递文件引用以运行实验。
数据集
数据集是打包的数据对象,易于机器学*管道使用。这是处理数据的推荐方式。帮助启用数据标注、版本控制和漂移监控(将在后续帖子中讨论)。数据集是根据已经存储在“数据存储”中的数据的位置定义的
数据集类型 —我们可以创建两种数据集
- 表格:一种结构化的数据形式,主要从数据存储中导入的表、CSV、RDBMS 等中读取。示例—回归问题的数据框架。
- File: 这是针对非结构化数据类型的,文件路径列表可以通过数据存储使用。一个示例用例是读取图像来训练 CNN。
创建数据集
数据集首先从数据存储区创建,并且需要注册。以下示例显示了表格和文件数据集的创建。
*#* ***Creating tabular dataset*** *from files in datastore.*
tab_dataset = Dataset.Tabular.from_delimited_files(path=(default_ds,'flower_data/*.csv'))tab_dataset.take(10).to_pandas_dataframe()*# similarly,* ***creating files dataset from the files*** *already in the datastore. Useful in scenarios like image processing in deeplearning.*file_dataset = Dataset.File.from_files(path=(default_ds,'flower_data/*.csv'))for fp **in** file_dataset.to_path():
print(fp)
注册数据集
定义数据集后,需要将其附加到 AML 工作区。此外,还附加了元数据,如数据集的名称、描述、标签和版本。数据集的版本化允许我们跟踪实验所基于的数据集。如果我们想要在任何特定的版本上训练模型,版本控制也是有用的。以下是注册表格和文件数据集的方法:
***# register tabular dataset***
tab_dataset = tab_dataset.register(workspace=ws, name='flower tab ds', description='Iris flower Dataset in tabular format', tags={'format':'CSV'}, create_new_version=True)
***#register File Dataset***
file_dataset = file_dataset.register(workspace=ws, name='flower Files ds', description='Iris flower Dataset in Files format', tags={'format':'CSV'}, create_new_version=True)
Azure 机器学*服务中注册的数据集
print("Datasets Versions:")
for dataset_name **in** list(ws.datasets.keys()):
dataset = Dataset.get_by_name(ws, dataset_name)
print("**\t**", dataset.name, 'version', dataset.version)**Output >>**
Datasets Versions:
flower Files ds version 1
flower tab ds version 1
用数据集做实验
- 在训练分类模型的训练脚本中,表格数据集作为输入传递给分类模型,方法是将数据集读取为熊猫数据帧
data = run.input_datasets['flower_ds'].to_pandas_dataframe()
- 使用 SKLearn 估算器的输入参数传递注册的数据集,该数据集将由训练脚本使用。
inputs=[tab_dataset.as_named_input(‘flower_ds’)]
- 此外,使用 pip_packages 附加参数使运行时环境能够提供支持 AML pandas 操作所需的包。由于脚本将需要使用一个数据集对象,你必须在脚本的计算环境中包含完整的 azureml-sdk 包或 azureml-dataprep 包以及 P 和 as 额外的库。
pip_packages=[‘azureml-dataprep[pandas]’]
结论
在此,我们介绍了 AML 服务的一个最重要的方面,即模型和实验的数据管理。数据是任何机器学*工作负载中的基本元素,因此,在这里我们学*了如何在 Azure 机器学*工作区中创建和管理数据存储库和数据集,以及如何在模型训练实验中使用它们。
接下来呢?
这是一系列博客帖子,包含各种 Azure 机器学*功能的详细概述,其他帖子的 URL 如下:
- 帖子 1: Azure 机器学*服务:第一部分——简介
- 帖子 2: Azure 机器学*服务——运行一个简单的实验
- 帖子 3: Azure 机器学*服务——训练一个模型
- 岗位 4 (这个) : Azure 机器学*服务——我的数据在哪里?
- 帖子 5: Azure 机器学*服务——目标环境是什么?
参考
[1]笔记本&代码— Azure 机器学*—处理数据,Kaggle。
【2】Azure ML 服务,数据参考指南,官方文档,微软 Azure。
【3】Azure 机器学*服务官方文档,微软 Azure。
Azure 解决方案和客户案例浏览器
直观地搜索和探索 Azure 云解决方案、参考架构、已发布的客户案例…
C loud 提供了多种技术选项,旨在以经济高效的方式解决业务挑战,并最大限度地减轻维护硬件和软件的负担。然而,在云世界中,技术的选择是巨大的,并且发展迅速。这就为解决方案或架构使用相关技术带来了挑战(可以说是好事)。可以做什么以及如何改变的可能性,因此迫切需要一个一站式存储库来找到已建立的体系结构和开发以及客户故事的指导原则。让我在解决方案探索空间中介绍一个全新的工具,它可以用来查找架构和客户参考,这可以增强信心并产生可以在您的业务用例中应用的想法。
在 Azure(微软领先的公共云服务)世界中,我们可以使用名为 Azure Solution Explorer 的工具来利用和查找您感兴趣的服务的已发布参考架构、解决方案想法和示例工作负载。该网站由微软云解决方案架构师阿列克谢·波尔科夫尼科夫开发。荣誉和特别感谢阿列克谢,使这个可怕的工具。
Azure Solution Explorer 的 UI 发布在这里:【https://azurecharts.com/solutions
图一。Azure 解决方案浏览器
让我们进一步探索选择宇宙数据库和蔚蓝 IOT 枢纽。Azure Cosmos DB 是微软的全球分布式多模型数据库服务。只需点击一个按钮,Cosmos DB 就能让您在全球任意数量的 Azure 区域灵活、独立地扩展吞吐量和存储。您可以灵活地扩展吞吐量和存储,并使用您喜欢的 API(包括 SQL、MongoDB、Cassandra、Tables 或 Gremlin)来利用快速的个位数毫秒级数据访问。Cosmos DB 为吞吐量、延迟、可用性和一致性保证提供了全面的服务水*协议(SLA ),这是其他数据库服务无法提供的[1]。物联网中心是托管在云中的托管服务,充当物联网应用程序及其管理的设备之间双向通信的中央消息中心。您可以使用 Azure IoT Hub 来构建物联网解决方案,在数百万个物联网设备和云托管的解决方案后端之间进行可靠和安全的通信。您几乎可以将任何设备连接到物联网中心[2]。
第一步 :在 Azure Solution Explorer UI 中选择 Cosmos DB 和 IoT Hb。
图二。在 Azure Solution Explorer UI 中选择 Cosmos DB 和 IoT Hb
第二步 :点击下拉查看当前结果
图三。探索结果
第三步 :使用 Cosmos DB 点击物联网
图 4。使用 Comsos DB 的物联网
步骤 4 :它会将你重定向到使用 Comsos DB 架构的官方物联网,供你参考,你可以从那里开始钻取。
图五。使用 Cosmos DB 的物联网
第五步 :您可以点击远程患者监控解决方案,查看一个实际使用案例,您可以通过结合物联网和智能来优化治疗,使用 Azure 远程监控患者并分析医疗设备生成的海量数据,从而预测和预防未来的事件[3]。
图六。选择远程患者监护解决方案
图 7。远程患者监护解决方案
第 6 步 :如果您计划探索更多内容,请点击 Azure 物联网参考架构,该架构展示了使用 PaaS(*台即服务)组件的 Azure 物联网应用程序的推荐架构。
图 8。选择物联网参考架构
图九。物联网参考架构
如果您正在搜索已发布的客户参考资料,Azure Customer Story Explorer 是一个很棒的一站式存储库,可以发现您感兴趣的服务的已发布客户成功案例和案例研究。查看其他客户构建的内容。
Azure Customer Story Explorer 的用户界面发布在这里:https://azurecharts.com/stories
让我们进一步探索这个选择 Azure 数据浏览器。Azure Data Explorer 是一个用于日志和遥测数据的快速且高度可扩展的数据探索服务。它帮助您处理现代软件发出的许多数据流,因此您可以收集、存储和分析数据。Azure Data Explorer 是分析来自任何数据源(如网站、应用程序、物联网设备等)的大量不同数据的理想选择。这些数据用于诊断、监控、报告、机器学*和其他分析功能。Azure Data Explorer 使获取这些数据变得简单,并使您能够在几秒钟内对数据执行复杂的即席查询[4]。
第一步: 在 Azure 客户故事浏览器中选择 Azure 数据浏览器
图 10。Azure 客户案例浏览器
第二步: 点击下拉查看当前结果
图 11。客户案例结果
第三步: 点击其中一个用例。在这里,我深入研究了 Screenzilla used 案例,Screenzilla Entertainment 是 Hyper Hippo Productions 的一个部门,它正在使用微软游戏堆栈来获得成功所需的洞察力。借助微软 PlayFab、Azure 和 Power BI 的组合,该公司可以将其游戏呈现在合适的人面前,基于反馈数据提高游戏性能,并为每个玩家个性化其游戏[5]。
图 12。选择 Screenzilla 用例
第四步: 它会将你重定向到已发布的 ScreenZilla 用例供你参考,你可以从那里开始钻取。
图 13。Screenzilla 使用案例
感谢您花时间阅读本文,希望 Azure Solution 和 Customer Story Explorer 对您有所帮助。请让我知道任何问题和建议,以改善工具总是受欢迎的。
参考
[1]
" https://docs . Microsoft . com/en-us/azure/cosmos-db/introduction,"[Online]。
[2]
" https://docs . Microsoft . com/en-us/azure/IOT-hub/about-IOT-hub,"https://docs . Microsoft . com/en-us/azure/IOT-hub/about-IOT-hub。【在线】。
[3]
“https://docs . Microsoft . com/en-us/azure/architecture/solution-ideas/articles/remote-patient-monitoring,”https://docs . Microsoft . com/en-us/azure/architecture/solution-ideas/articles/remote-patient-monitoring。【在线】。
[4]
" https://docs . Microsoft . com/en-us/azure/data-explorer/data-explorer-overview,"https://docs . Microsoft . com/en-us/azure/data-explorer/data-explorer-overview。【在线】。
[5]
" https://customers . Microsoft . com/en-us/story/724204-screenzilla-entertainment-hyper-hippo-productions-gaming-azure,"https://customers . Microsoft . com/en-us/story/724204-screenzilla-entertainment-hyper-hippo-productions-gaming-azure。【在线】。
Azure Synapse Analytics 作为云湖边小屋:一种新的数据管理范式
企业数据湖&企业数据仓库(EDW)会共存吗?
在数据仓库的早期,一个数据仓库 ( DW 或 DWH ),也被称为企业数据仓库 ( EDW ),是一个常*的用于报表和数据分析的系统,被认为是商业智能的核心组件。提取、转换、加载 (ETL)和提取、加载、转换 (E-LT)是构建数据仓库系统的两种主要方法。数据仓库是来自一个或多个不同来源的集成数据的中央存储库。它们将当前和历史数据存储在一个地方。这听起来可能非常类似于数据湖的定义。特别是,data lake 可以存储数据源提供的任何形式的结构化和非结构化数据。请参*数据湖与数据仓库的比较——两种不同的方法 (AWS ),了解两者的详细特征。
与数据仓库相比,数据湖是两种不同的方法 (AWS)
许多云解决方案提供商经常将这两种产品捆绑在他们提议的大数据架构中,将数据湖定位为存储层,将数据仓库定位为模型和服务层。
现在的问题变成了数据湖&企业数据仓库(EDW)会共存吗?答案是肯定的!我们将这种新出现的模式称为云湖库,它将数据仓库和数据湖的优势结合在一起,简化了大数据架构。一些突出的优势包括:
- AI + BI 支持。
- 支持结构化和非结构化。
- 端到端流式传输。
- 模式实施和治理。
- 提高生产力和效率。
- 降低数据仓库和数据湖整合及现代化的风险和成本。
Cloud Lakehouse 启用云中的分析、人工智能和数据科学,来源:云数据仓库和数据湖现代化 2020 年 4 月 P.3 (Informatica)
与 AWS Redshift 或 GCP BigQuery 不同, Azure Synapse Analytics 被认为是云湖边小屋的一个例子。“Azure Synapse 使用工作空间的概念来组织数据和代码或查询工件。工作空间可以作为业务分析师的低代码/无代码工具,或者作为数据工程师和数据科学家在 Spark 中工作或应用机器学*模型的类似 Jupyter 的笔记本。在演示中,微软展示了如何使用两种途径开发相同的数据转换任务。体验上会有一些不同——例如,Synapse 继承了 Azure SQL 数据仓库功能来支持高并发性,而 Spark 环境通常涉及独狼数据科学家或数据工程师。在数据安全性级别上也有差异——在关系数据库方面,表、列和原生行级安全性的实践要成熟得多,但在数据湖方面却不那么成熟。这是 Cloudera 与 SDX 的不同之处,后者是其*台产品的一部分。”(细看微软 Azure Synapse Analytics ,托尼·贝尔(dbInsight) 对于大数据,2020 年 4 月 14 日)。“ Databricks *台具有湖边小屋的建筑特征”。由于微软正朝着集成单一数据*台的方向发展,其他托管服务在未来很可能会以类似的模式发展。
点击了解更多详情。
参考文献
免责声明:以下内容并非本人雇主官方背书。本文表达的观点和意*仅代表作者的观点和意*,不一定反映当前或以前的雇主、组织、委员会、其他团体或个人的官方政策或立场。本文中进行的分析是基于有限日期的开源信息。分析中所做的假设并不反映任何前任或现任雇主的立场。
贝塞尔曲线
理解贝塞尔曲线的数学
贝塞尔曲线在计算机图形学中被大量使用,经常用来产生*滑的曲线,然而它们是一个非常简单的工具。如果你曾经使用过 Photoshop,你可能会偶然发现一个叫做“锚点”的工具,在那里你可以放置锚点并用它们画一些曲线…是的,这些是贝塞尔曲线。或者,如果您使用基于矢量的图形,SVG,这些也使用贝塞尔曲线。让我们看看它是如何工作的。
定义
给定 n+1 个 点【P0,…,Pn】称为 控制点由这些点定义的贝塞尔曲线定义为:
情商。一
其中 B(t) 是伯恩斯坦多项式,并且:
情商。2
你会注意到这个伯恩斯坦多项式看起来很像牛顿二项式公式中的 k(th) 项,即:
情商。3
其实伯恩斯坦多项式不过是 (t + (1 - t))^n = 1)展开式中的【k(th)项。* 这就是为什么如果你把所有的到相加,你会得到 1 。任何方式。***
二次贝塞尔曲线
二次贝塞尔曲线就是我们所说的具有 3 个控制点的贝塞尔曲线,因为 P(t)的次数将是 2。让我们计算给定 3 控制点的贝塞尔曲线,并探索我们可能找到的一些属性!记住,eq. 1
为 n+1 分,所以在我们的例子中 n=2。
情商。四
注意 P(t) 返回的不是一个数字,而是曲线上的一个点。现在我们只需选择三个控制点,并评估范围[0, 1]
上的曲线。我们可以很容易地在 Python 中做到这一点。
您会注意到曲线在第一个和最后一个控制点开始和结束。这个结果对任何数量的点都成立。由于 t 的范围是从 0 到 1 ,我们可以通过在t=0
和t=1
处对 P(t) 求值来证明这一点。使用eq. 1
:
情商。四
情商。5
因为曲线从 P0 到,在这种情况下,完全由决定曲线的形状。移动P1你周围的人可能会注意到一些东西:******
贝塞尔曲线总是包含在由控制点形成的多边形中。该多边形因此被称为 控制多边形 、或贝塞尔多边形。这一特性也适用于任意数量的控制点,这使得在使用软件时它们的操作非常直观。
矩阵表示
我们实际上可以使用矩阵乘法来表示贝塞尔公式,这在其他情况下可能很有用,例如分割贝塞尔曲线。如果我们回到我们的例子,我们可以重写 P(t)如下:
情商。6
因此,关于二次贝塞尔曲线的所有信息被压缩到一个矩阵中, M 。现在,我们可能想要找到该矩阵的系数,而不必执行所有这些步骤,并且以一种易于编程的方式。由于矩阵的系数只是每个 Pi 前面多项式的系数,所以我们要找的是伯恩斯坦多项式eq. 2
的展开形式。
还有一点:如果展开 Bi(t) 我们会得到 Pi 前面的多项式,对应矩阵中的 i(th)列。然而,这并不方便,如果我们能得到行,编程会更容易。也就是说,你可能会注意到矩阵的 i(th)行与反转(n-i)(th)** 列完全相同,和反转(n-i)(th)列的系数只不过是按照**的递减幂取的 B(n-i)(t) 的系数。****
情商。七
如果你遇到麻烦,你可能想参考eq. 2
和eq. 3
。
所以矩阵的系数无非就是 t 前面的系数,意思是:
情商。8
插入文字
贝塞尔曲线的一个有趣的应用是绘制一条通过一组预定义的点的*滑曲线。之所以有趣,是因为 P(t) 的公式产生点,并且不是 y=f(x) 的形式,所以一个 x 可以有多个 y (基本上是一个可以“后退”的函数)。例如,我们可以画出这样的东西:
然而,产生这个结果的数学方法并不简单,所以我为此专门写了一篇文章:
使用贝塞尔曲线创建*滑形状。
towardsdatascience.com](/bézier-interpolation-8033e9a262c2)**
与此同时,以下是如何使用eq. 1
为任意数量的控制点编写贝塞尔曲线的通用版本。
运行这个程序,你将得到显示在标题中的图表。
这就是贝塞尔曲线的介绍。我希望你学到了一些东西,不要犹豫地评论任何你可能有的问题!
贝塞尔插值
使用贝塞尔曲线创建*滑形状。
在本文中,我们将看到如何使用三次贝塞尔曲线来创建一条通过预定义的点集的*滑线。如果你不知道什么是贝塞尔曲线,你可能想看看我写的这篇文章,它可以作为一个介绍,或者只是浏览维基百科!
理解贝塞尔曲线的数学
towardsdatascience.com](/bézier-curve-bfffdadea212)
三次贝塞尔曲线
目标是拟合 n+1 给定点 (P0,…,Pn) 。为了拟合这些点,我们将在每对连续的点之间使用一条三次贝塞尔曲线(4 个控制点)。
图一
所以在这个图中,【G0】、【G1】、 和 G2 是三条不同的三次贝塞尔曲线,起点和终点分别是 (P0,P1) 、 (P1,P2) 和 (P2,P3) 因为任何贝塞尔曲线总是在第一个和最后一个控制点开始和结束,所以我们为每条曲线留下 2 个控制点,我们必须找到它们以使结果线看起来*滑。
在本文中,您可能想回头参考 *fig. 1*
来理解我们将使用的指数。
三次贝塞尔曲线的一般方程如下:
其中 K 为 4 个控制点。在我们的例子中, K0 和 K3 将是我们想要拟合的两个连续点(例如 P0-P1 ,或者 P1-P2 等等)。),而 K1 和 K2 是我们要找的剩下的 2 个控制点。
问题设置
假设我们有 n+1 个点要拟合,我们将使用三次贝塞尔曲线来拟合每个连续的点。我们将符合 Pi 到 Pi+1 的贝塞尔曲线称为γI:
情商。2
哪里的 ai 和 bi 都是左找。注意这里有 n 条曲线。**
如果想要最终的曲线*滑,就需要保证γI和γI+1在 Pi+1 周围*滑。换句话说,γI的曲率与γI+1围绕 Pi+1 的曲率相匹配。 数学上,这意味着尊重以下条件:******
情商。3, 4
我们需要找到所有的 ai 和 bi 。由于我们在每条贝塞尔曲线中有一对这样的变量,并且由于我们有 n 条曲线,我们需要找到 2n 个变量。但是,这里我们有【2(n-1)】的方程式。我们缺少两个方程来解这个系统。因此,我们施加以下(任意)边界条件:
情商。5, 6
编写系统
在解方程组之前,我们需要计算γI的一阶和二阶导数,把方程组写下来。
情商。七
而且,
情商。8
注入方程式
将eq. 7
注入eq. 3
:
情商。9
将eq. 8
注入eq. 4
:
情商。10
将eq. 8
注入eq. 5
:
情商。11
最后,将eq.8
注入eq. 6
:
情商。12
求解系统
综上所述,我们有以下 2n 等式:
情商。9, 10, 11, 12
为了解决这个系统打算通过将eq. 9
注入eq. 10, 11, 12
来消除所有的。使用eq. 9
:
情商。13
将eq. 13
注入eq. 10
:
情商。13, 14
将eq. 13
注入eq. 11
:
情商。15
快到了!我们现在需要将eq. 13
代入第四个方程eq. 12
。然而,eq. 12
有 bn-1 但eq. 13
保持到 bn-2 。好消息,我们可以用eq. 14
去掉 bn-1 然后注入 bn-2 。
情商。16
好吧!总结一下,我们按照这个顺序eq. 15, 13, 16
:
情商。15, 13, 16
我们可以把这个系统写成一个矩阵乘法来求解。坚持住,我们到了!
情商。17
如你所*,第一个矩阵只有 3 个对角线填充了值,其他都是零。这种矩阵被合理地称为三对角矩阵。存在有效解决这种类型系统的算法,例如在时间上线性运行的托马斯算法。为了简单起*,我们不会进一步优化,我们将简单地使用 Python 中 Numpy 的内置函数来解决这个系统。
但是,我们仍然缺少了 bi 点。为了找到这些,我们简单地使用eq. 13
来计算所有的直到 bn-2 ,然后使用eq. 12
给出最后一项, bn-1 。
情商。13, 12
我们终于完成了!让我们看看如何用 Python 来编程。
Python 代码
我尽了最大努力让代码尽可能清晰,我还添加了注释。如果你不能理解某事,不要犹豫发表评论!
最后,我们将这样使用这段代码:
对我来说,我得到了这个:
图 2
这篇文章到此为止!我希望你喜欢它,并且不要犹豫评论你可能有的任何问题!
数据科学学士…值得主修它吗?(英尺。我的 DS 课程作业)
意*
我对你是否应该考虑主修 B.S .数据科学的想法。
瓦西里·科洛达在 Unsplash 上的照片
视频版本
介绍
数据科学是一个新兴领域,现在许多学院和大学都在提供本科数据科学课程。
作为一名最近获得数据科学学士学位并在数据科学领域找到工作的毕业生,我想谈谈我们学校的数据科学课程,以及它们是否让我受益。我还想分享一下我对本科是否值得主修数据科学的看法。
我在大学的故事
我是大学里首批获得数据科学学士学位的两个人之一(实际上只有我和我的朋友),我对这个项目有一段非常有趣的经历。
直到大三第一学期(2018 年秋季),我都是 CS 专业的学生。在那一学期,我开始从事股票交易,并偶然发现建立股票价格的预测模型。使用数据来预测股票价格的想法很吸引我,我发现了数据科学领域。
有趣的是,我的大学宣布他们将在下学期开设数据科学课程,他们列出的课程让我兴奋不已。
2019 年春天,我正式从 CS 转专业到 DS。然而,我当时的处境非常有趣。一些高年级的班级还没有准备好上课,我的学校也没有想到会有一个即将毕业的学生转专业。这些课程是大数据和深度学*课程。
我记得我的导师联系了计算机系的系主任,向他解释了我所处的情况,而要找到一个能教这两个班的教授是一件非常麻烦的事情。他们最终找到了一位教授,可以在下学期(2019 年秋季)教他们。
2019 年秋天,我们发现教授患有严重的慢性疾病,他无法在那个学期教学(在那个学期我们听说他去世了。安息吧,森伯博士)。所以,我们必须找到其他可以教授这两门课的教授。长话短说,我被安排到大数据管理研究生班(该行业的专业人士正在攻读硕士学位),我必须在他的办公室会*一位教授,以参加深度学*课程。
2019 年秋季将是最难忘的学期之一。一开始有很多小问题,但在那个学期,我参加了所有对我的数据科学之旅有帮助的有用课程——机器学*、深度学*、统计学*、大数据和概率。
特别感谢我的导师里克,他不辞辛苦地帮助我走过大学旅程。你的豚鼠将继续成长!
我大学的数据科学课程
我大学的数据科学项目是计算机科学、统计学和数学的混合体。
- 计算机科学课程
- CS 编程基础(C++) :这门课程教给学生基本的软件开发方法、数据类型、控制结构、函数、数组以及运行、测试和调试的机制。
- 计算机科学 I(c++):这门课程是 CS 编程基础的延续,我们在这里深入研究了面向对象编程(OOP)。我记得创建了一个“石头、剪子、布程序”,你可以在这个程序中玩石头、剪子、布的游戏。
- 计算机科学 II(Java 语言):这门课程涵盖的主题包括递归、基本数据结构(包括堆栈、队列、链表、哈希表、树和图)、算法分析和面向对象编程。作为最后一个项目,我们要创建一个程序,你可以从中买卖书籍、有声读物和 DVD。
- 离散数学:这门课程涵盖了计数原理、布尔运算、逻辑和证明方法、递归关系、集合、关系、函数、初等图论&数论。
- 数据结构和算法(Java 语言):我记得这门课是我大学生涯中最难学的课程之一。由于这门课,很多学生最终转了专业。幸运的是,我活了下来。课程涵盖了算法分析,包括时间复杂度和 Big-O 符号,堆栈、队列和树的分析,包括 B 树、堆、散列和高级排序技术。不相交的集合和图。
- 数据库系统:这个课程是一个非常轻松愉快的课程。它讲述了如何用 SQL 设计关系数据库系统。对于小组项目,我们创建了一个电视&电影系列数据库系统。
- 大数据管理和分析:这是我和高管研究生一起上的课。令人难忘的一件事是,由于课程是提供给专业人士的,它发生在周五下午 6 时至 10 时。课程涵盖了 Hadoop MapReduce 和 Spark。
- 数据科学家的计算方法(Python 语言):这是一门深度学*课程,涵盖了 CNN 和 RNN。我在教授的办公室*了他,和我的另一个朋友一起学*。我很喜欢,因为这基本上是与教授一对一的课程,所以我学到了很多东西。
- 机器学*(Python 语言):课程名称很好地解释了一切。它涵盖了机器学*算法,我很喜欢。
- 顶点工程:这是一学期的团体项目课。有一个赞助公司的名单,你可以从中选择项目,一旦这个小组与该公司匹配,你就可以参与他们的项目。我们小组最终使用深度学*完成了 OCR(光学字符识别)项目。
2.统计课程
- 统计学家和精算师数据分析(在 R) :这门课程涵盖了抽样、拟合和测试模型、回归和人口比较。
- 概率:涵盖了所有的统计基础理论。
- 数理统计(in R) :概率的延续。它涵盖了所有的统计检验——T 检验、f 检验、卡方检验、假设检验等。
- 数值和统计计算(R 版):本课程涵盖了蒙特卡罗方法、最优化、随机数生成等。在这门课上学会了如何使用 R Markdown。
- 应用线性模型(R 中):本课程涵盖了线性统计模型及其对经验数据的应用。主题包括线性和逻辑回归;多元回归;诊断措施;异常值和有影响的观察值的检测;变量选择;一元和二元方差分析。
- 统计学*(in R) :这门课和机器学*课是一样的,除了我们用了 R,我和机器学*一起上了这门课,所以它非常有帮助,因为两门课涵盖了相同的主题。机器学*和统计学*课程在我找到工作的过程中发挥了至关重要的作用。
3.数学课程
- 微积分(一、二、三、多变量微积分),线性代数,还有一些数学专业的学生上的我觉得没啥用的高阶证明式数学课。
结论和要点
总的来说,我对学校开设的课程非常满意。所有的编程课程都是基于项目的,而不是基于理论的,所以我觉得我学到了很多。做动手项目对获得实践技能更有帮助。此外,我从统计学课程中学到的知识对找工作绝对有帮助。
因此,我会检查你的课程大纲,看看它们是否是基于项目的。在我的面试过程中,我了解到雇主并不在乎你是如何获得这些知识的。他们关心你是否能解决现实世界的问题。你做的项目越多,你解决问题的能力就越强。
那么……攻读数据科学学士学位值得吗?这真的取决于你的学校提供什么。正如我上面提到的,我会检查学位计划,检查课程和教学大纲的描述,并确保你是否真的能从课程中学到东西(也就是基于项目的课程)。以下是一些要点:
- 如果你学校的 DS 项目提供了 CS 和 stats 课程的良好结合,你可以在其中学*基础编程、统计学、机器学*、统计学*和/或深度学*,那么我强烈建议你主修 it。
- 如果你是一名试图进入数据科学领域的计算机科学专业的学生,我强烈建议你学*基础统计学课程和线性代数(如果线性代数不是必修课的话)。此外,如果你的学校提供机器学*、深度学*或大数据,我会选择它们作为上层选修课。
- 如果你是统计学/数学专业的,我强烈推荐你上基础编程课(不管是 Python,Java,还是 C++,但最好是 Python),机器学*,和/或统计学*作为上层选修课。
我相信你的知识和技能比你的学位更重要。如果你是一名想要进入数据科学领域的本科生,请关注你能从课程中获得什么!
希望这篇文章对你有用。感谢您的阅读!
宝宝很牛逼…人类就是 OG 神经网。
即使人工智能和神经科学在许多方面相似,但它们并不完全相同。
“婴儿太棒了……人类就是 OG 神经网络。”—埃隆·马斯克,在最近的一次乔·罗根采访中,他们在讨论他的新生儿 xa-12。
事实上,我们的大脑如何连接和神经网络如何工作有许多相似之处。人工智能神经网络的本质类似于人脑,模拟大脑在学*过程中的行为。即使人工智能和神经科学在许多方面相似,但它们并不完全相同。
就像,我们建造潜艇不是为了像鱼一样游泳;而是借用了流体力学的原理,应用于建造潜艇。在莱特兄弟之前,人们设计翅膀像鸟一样扇动。但是莱特兄弟解决了飞行的问题,他们不再试图制造完美的鸟类翅膀。相反,他们研究了翅膀的模式和产生升力的翅膀上下流动的空气动力学。
同样,我们可以从人脑中寻找灵感,并借用有价值的概念。人工智能研究人员致力于通过理解生物大脑来模拟人脑的内部过程,这可能在构建智能机器方面发挥重要作用。
情景记忆
构建智能系统的关键在于记忆系统记住过去的经历。在大脑中,这是海马,它在巩固信息、学*和记忆中起着至关重要的作用。
在强化学*中,这允许动作的值通过重复的经验被增量地学*并存储在记忆中,被称为情景记忆。 Deep Q-network (DQN)的一个关键要素是“经验重放”,网络通过经验存储行动的价值,然后“重放”它。DQN 存储了与每个雅达利游戏屏幕或星际争霸场景相关的行动和奖励结果等经验。它根据当前情况和存储在记忆中的先前经历之间的相似性来选择行动,采取能产生最高回报的行动。
经验重放允许强化学*从过去发生的成功或失败中学*,由此导致奖励或惩罚的行动序列在内部重新制定。存储在 DQN 重放缓冲器中的经验就像原始的海马体一样实现,允许巩固、学*和记忆发生。
内存储器
人类不是每秒钟都从零开始思考;相反,我们的思想具有持久性。当你读这句话的时候,你对句子的理解是基于一系列的单词。你利用现有的知识并产生新的信息。
人类智慧的定义是我们在活跃的商店中保持和操纵信息的非凡能力,这种能力被称为工作记忆。与回忆过去的情景记忆不同,工作记忆使认知成为可能,这是一个通过思想、经验和感官获取知识和理解的心理过程。
随着时间的推移,我们维护和处理信息的能力导致人工智能研究人员开发了递归神经网络架构。这些网络中有环路,允许信息持续存在。它已经在多种应用中得到应用,比如自然语言处理和语音识别。它还被用于创建描述图像的标题,通过选择图像的一部分来查看它输出的每个单词。这些网络在各种各样的问题上工作得非常好,特别是长短期记忆网络,它在各个领域都取得了最先进的表现。
注意力
不像大多数 CNN 模型直接在整个图像上工作来确定猫是否存在,我们的视觉注意力战略性地转移到物体上。我们不是处理整个图像,而是集中我们的处理资源,分离出在任何给定时刻相关的信息。
这种注意力机制一直是人工智能架构的灵感来源,旨在忽略图像中不相关的对象,专注于相关的内容。这也使得人工智能从业者可以根据输入图像的大小来调整计算成本。注意力机制已经导致在混乱的情况下在困难的多物体识别任务中产生令人印象深刻的表现。它还支持图像到字幕的生成。
虽然注意力最初被认为是感知的定向机制,但它已经导致了机器翻译和谷歌翻译的艺术表现。它的成功归功于它在翻译过程中通过有选择地关注句子的子部分来很好地概括长句的能力。
迁移学*
人类有一种与生俱来的能力,可以将从一个环境中获得的知识应用到新的环境中。我们在学*一项任务时获得的知识,我们可以用同样的方法来概括解决相关任务的经验。当我们试图学*新的东西时,我们不会从头开始学*所有的东西。相反,我们利用过去学到的知识。
例如,我们认为汽车是一种有轮子和门的物体,它们有特定的形状和大小。我们可以在试图识别卡车时使用这些知识,而无需重新学*车轮的外观。同样,在学*法语之后,我们可以有效地学*意大利语,因为我们可以概括共同的语法特征和单词相似性。
尽管是人类的第二天性,迁移学*是机器学*中的一个研究难题。人工智能研究人员专注于利用从一个应用程序中获得的存储知识,并将其应用于一个不同但相关的问题。在深度学*的背景下,迁移学*的关键动机是缺乏不同领域的注释数据。由于机器学*方法依赖于足够数量的带注释的训练数据的可用性,所以获得足够的带标签的训练数据通常是昂贵的。
在计算机视觉领域,迁移学*的一个成功应用是在 ImageNet 挑战赛中,参与者被提供了包含 1000 个类别和 120 万张图像的 ImageNet 训练数据子集。
对于自然语言处理,单词嵌入,如 Word2vec ,其中单词的语义是从维基百科这样的源数据中训练出来的,并将其应用于情感分析和文档分类。
在语音识别中,为英语开发的模型已成功用于提高其他语言的语音识别能力。
他们如何相互激励、共同进步、相互受益
towardsdatascience.com](/the-fascinating-relationship-between-ai-and-neuroscience-89189218bb05)
乔·罗根采访埃隆·马斯克
迈向数据科学的一小步:Python 中的决策树回归
理解决策树回归背后的直觉,并用 python 实现。提供源代码和数据集。
埃里克·马塞利诺在 Unsplash 上的照片
什么是决策树回归?
决策树主要用于分类问题,但是,让我们试着理解它在回归中的含义,并且试着理解为什么在回归中使用它不是一个好主意。
决策树回归可以将数据分成多个部分。这些拆分通常回答一个简单的 if-else 条件。该算法决定数据中的最佳分割数。由于这种拆分数据的方法非常类似于树的分支,因此这种方法可能被称为决策树。事实上,最后一层(即适合、不适合)被称为叶子。
例如,看上面的图片,有关于顾客的数据,他们的年龄,他们是否吃比萨饼和他们是否锻炼。通过执行决策树回归,数据按照年龄被分成两类,即年龄< 30 and age> 30。年龄内< 30 category, the data is again split into 2 categories by their eating habits i.e., people eating pizza and people not eating pizza. The same goes for exercise as well. By doing these splits, we can simply account for the behavior of the customers based on their choices and we end up deciding whether they are fit or unfit.
Implementation in Python
Let us deep dive into python and build a polynomial regression model and try to predict the salary of an employee of 6.5 level(hypothetical).
Before you move forward, please download the CSV data file from my GitHub Gist.
[https://gist.github.com/tharunpeddisetty/433e5fe5af0e6b6cdd9d7df3339931a5](https://gist.github.com/tharunpeddisetty/433e5fe5af0e6b6cdd9d7df3339931a5)
Once you open the link, you can find "Download Zip" button on the top right corner of the window. Go ahead and download the files.
You can download 1) python file 2)data file (.csv)
Rename the folder accordingly and store it in desired location and you are all set.If you are a beginner I highly recommend you to open your python IDE and follow the steps below because here, I write detailed comments(statements after #.., these do not compile when our run the code) on the working of code. You can use the actual python as your backup file or for your future reference.
导入库
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
导入数据并定义 X 和 Y 变量
dataset = pd.read_csv(‘/Users/tharunpeddisetty/Desktop/Position_Salaries.csv’) #add your file path
X = dataset.iloc[:,1:-1].values
y = dataset.iloc[:, -1].values#iloc takes the values from the specified index locations and stores them in the assigned variable as an array
让我们看看我们的数据,了解变量:
该数据描述了员工的职位/级别及其工资。这与我在多项式回归文章中使用的数据集相同。
可视化数据
plt.scatter(X, y, color = ‘red’)
plt.plot(X,regressor.predict(X), color = ‘blue’)
plt.title(‘Decision Tree’)
plt.xlabel(‘Position level’)
plt.ylabel(‘Salary’)
plt.show()
作者图片
训练模特
from sklearn.tree import DecisionTreeRegressor
regressor = DecisionTreeRegressor(random_state=0)
regressor.fit(X,y)#random_state is the seed value, just to make sure we both get same results.
我们将使用模型中的全部数据,因此您不需要将数据分成训练和测试数据。
可视化决策树回归的结果
X_grid = np.arange(min(X), max(X), 0.1)
X_grid = X_grid.reshape((len(X_grid), 1))
plt.scatter(X, y, color = 'red')
plt.plot(X_grid,regressor.predict(X_grid), color = 'blue')
plt.title('Decision Tree')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()
作者图片
您可以看到我们的模型如何预测与数据点相同的精确数据水*。这种可视化仅用于说明目的。实际上,我们几乎没有任何只有 X 和 Y 变量的数据集(X=职位级别,Y =薪水)。因为这个数据是二维的,我们能够绘制它。如果数据是多维的,我们就不会绘制它。这显然是有道理的。
使用决策树回归预测 6.5 级结果
print(regressor.predict([[6.5]]))
# predict method expects a 2D array thats the reason you see [[6.5]]
结果
决策树回归:150000
结论
我们可以看到,我们的模型预测了与 6 级员工相同的工资。这是由决策树算法的本质决定的。它的工作假设是,如果一个雇员有某些特征(在这种情况下是水*),那么另一个具有相似特征的雇员也获得相同的工资。
我把这个留给你的智慧去理解这个模型有多好。开个玩笑!你可以清楚地看到这是不公*的,对吗?同样,我们可以得出结论,这种模式表现不佳。正如我在本文开始时已经提到的,这个模型更适合于分类问题,我将在以后的文章中处理这个问题。我将确保在我的下一篇文章中使用相同的数据集来实现不同的回归技术。通过这样做,您可以比较结果,并决定哪个模型是最好的。
我希望这对你来说是有趣的。恭喜你!您已经用最少的代码行实现了决策树回归。当我说婴儿迈向数据科学时,我是认真的。现在您有了代码的模板,您可以在其他数据集上实现它并观察结果。机器学*快乐!
迈向数据科学的一小步:Python 中的多元线性回归
如何实施多元线性回归并解释结果?源代码和有趣的篮球运动员数据集已经提供。
图像来源:交叉验证—堆栈交换
什么是多元线性回归?
让我直接进入主题。你上图看到的是多元线性回归的数学表示。图像中给出了所有必要的解释。
顾名思义,MLR(多元线性回归)是定义因变量*均行为的多个特征/变量的线性组合。
考虑 x1,x2,..xp 为自变量,Y 为因变量。所有β值对应于各自独立变量的系数。另一方面,β0 是截距值,类似于简单的线性回归。
错误术语是什么?
这是自然界存在的错误。还记得在我之前的文章中,我指出一个人永远无法预测准确的未来值吗?这是因为存在这个错误。误差包括我们的模型中没有记录/使用的所有数据。例如情绪、感觉等,它们不容易量化,或者仅仅是缺少数据/记录数据时的人为错误。
但是不用担心。一旦我们使用这种回归方法,我们只能得到 Y 变量的*均行为。与实际数据相比,这种*均行为可能大于、小于或等于 Y 的原始预测值。由于我们只处理 Y 的*均值,误差项相互抵消,最终我们得到一个没有误差项的估计回归函数。
如何减少误差?简单,多投点钱,多找数据。
举例:
让我们考虑公司的利润作为因变量(Y ),它的研发支出(x1 ),广告支出(x2)和营销支出(x3)作为自变量。假设在做了所有的数学计算后,我们得出了下面的回归方程或函数[任何回归的数学表示的另一个名称]。请记住下面的函数是假设的。
Profit = 10000 + 5(RnD) - 2(Advertising) + 1(Marketing)
释义:
- 如果公司不投资研发、广告和营销,那么他们的*均利润将是 10,000 美元
- 如果公司增加 10 万美元的研发支出,*均利润增加 50 万美元/5 个单位[这里变量的单位非常重要。基于单位,你可以正确地做出解释[所有变量都以 10 万美元为单位],这是有意义的,因为更多的研发投资和更好的产品进入市场,从而更好的销售。
- 如果公司增加 10 万美元的广告支出,那么*均利润减少 20 万美元/2 个单位。更多的广告支出可能会降低整体利润。
- 如果公司增加 10 万美元的营销支出,那么每单位产品的*均利润增加 10 万美元。更多的营销支出可能会增加它的受欢迎程度,从而增加利润。
这些估计值是如何计算出来的?
有一种数学方法叫做 OLS(普通最小二乘法)。使用某些矩阵变换,你可以找到估计的系数值。解释 OLS 不在本文的范围之内。你可以很容易地在网上找到同样的教程,如果你真的想知道它是如何工作的,请浏览它们。然而,现代编程语言将帮助你计算这些估计。
用 Python 实现
让我们深入研究 python,构建一个 MLR 模型,并尝试预测篮球运动员的得分。
由安德烈·克拉西尔尼科夫在 Unsplash 上拍摄的照片
在您继续之前,请从我的 GitHub Gist 下载 csv 数据文件。
[https://gist.github.com/tharunpeddisetty/bc2508ab97c7c8460852f87ba4ad4efb](https://gist.github.com/tharunpeddisetty/bc2508ab97c7c8460852f87ba4ad4efb)
Once you open the link, you can find "Download Zip" button on the top right corner of the window. Go ahead and download the files.
You can download 1) python file 2)data file (.csv)
Rename the folder accordingly and store it in desired location and you are all set.If you are a beginner I highly recommend you to open your python IDE and follow the steps below because here, I write detailed comments(statements after #.., these do not compile when our run the code) on the working of code. You can use the actual python as your backup file or for your future reference.
导入库
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
导入数据并定义 X 和 Y 变量
dataset = pd.read_csv('/Users/tharunpeddisetty/Desktop/PlayerStatsBasketball.csv') #paste your path inside the quatations #iloc takes the values from the specified index locations and stores them in the assigned variable as an arrayX = dataset.iloc[:,:-1].values
Y = dataset.iloc[:,-1].values
让我们看看我们的数据,了解一下变量:
作者图片
所有变量名都是不言自明的。在这个程序中,我们的任务是根据一个球员的身高、体重、投篮命中率和罚球命中率来预测他的*均得分。因此,您可以看到,我使用 python 中的 iloc 函数和一些独立切片,将最后一列隔离为我们的 Y 变量,并将所有其他变量隔离到 X 中作为特征数组。
将数据拆分成训练集和测试集
from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X,Y,test_size=0.2,random_state=0)# test_size =0.2 tells the class that we are trying to split 80% of the data into train data and 20% into the test data. random_state=1 serves as a seed, this basically makes sure that same random process is chosen when splitting the data in different evironments. To be specific, you and I running this code in 2 different computers get same rows in both test and train data sets
ScikitLearn 是一个著名的 python 库,广泛用于机器学*。你可以检查出所有它的牛逼 API 供你参考。我们会经常用到它们。点击下面的链接
https://scikit-learn.org/stable/modules/classes.html
训练模型
from sklearn.linear_model import LinearRegression
regressor = LinearRegression()
regressor.fit(X_train,Y_train)#regressor is the object for class LinearRegression
对测试集 进行预测
# Predicting new data i.e., test data resuls using the model that is trained on our train datay_pred = regressor.predict(X_test)np.set_printoptions(precision=2)print(np.concatenate((y_pred.reshape(len(y_pred),1),Y_test.reshape(len(y_pred),1)),1))
#.reshape is to display the vector vertical instead of default horizontal. Second parameter axis =0 is vertical concatenation, axis =1 is horizontal concatenation
结果
作者图片
这些结果与我们上次发表的声明一致。第一列值是我们的模型预测的*均进球,第二列显示了球员的实际进球。
打印系数和截距值
print(regressor.coef_)
print(regressor.intercept_)
我相信你可以把这些打印出来,然后根据我之前举的例子做你的解释。
结论
嗯,正如你所看到的,我们的模型没有预期的那么好。只有一个值,即 7.55,与实际值 7.9 非常接近。我选择这个数据集来解释多元线性回归是有原因的,也就是说没有一个模型是完美的,没有人能够建立一个完美的模型。你必须知道它性能不达标背后的原因。我们的数据可能存在某些问题,例如:
- 数据集可能存在潜在问题。
- 很可能,我们没有足够的训练数据供模型处理和预测。
- 数据中可能存在不一致,例如输入了错误的值(由于人为或计算机错误)。
- 考虑的独立变量可能不是解释玩家在游戏中*均进球的显著变量。
以上几点都重合在一点:误差。我们可以说我们的数据有很多错误。我们可能需要更多关于球员在比赛中的体能、动机、情绪等方面的数据。
那么这是否意味着我们未能实现多元线性回归呢?当然不是,因为作为一名数据科学家,你必须明白编写代码和实现模型的能力并不是主要目标。他/她必须深入了解数据。你是怎么做到的?只需与提供数据的人交谈,也可能与数据来源领域的行业专家交谈(在我们的案例中是篮球),并尝试找出数据中是否有任何潜在的错误。
除非你理解数据,否则建立模型并不那么简单。人们必须知道他们的目标是什么。没有一个完美的模型可以用不同的数据集一直预测 95%的准确率。如果有人声称他们的模型是最好的,那个人是个傻瓜。
嗯,我的目的达到了。我已经展示了如何对多元线性回归建模,还展示了在开始回归建模之前需要仔细考虑的问题。人们必须改变必要的参数,以便该模型最佳地为企业/个人的特定目的而工作。尝试相同的方法,用不同的数据集编码,识别 X 和 Y 变量,检查结果,你可以得到大量的在线数据集。相同的代码在各种其他数据集上运行得非常好,所以它毕竟不是真的没用。机器学*快乐!
迈向数据科学的一小步:Python 中的多项式回归
理解多项式回归背后的直觉,并用 python 实现。提供源代码和数据集。
图片来源 Animoid
什么是多项式回归?
在上图中,你可以看到多项式曲线的例子。大多数实时数据实际上并不是线性的,而是非线性的。上图中所有蓝色的点代表数据点,绿线是线性回归线,而红线是多项式回归线。你可以立即看到哪条线是完美的。它是红线,即代表给定范围内数据的总体趋势。
现在,让我们理解什么是多项式回归:你可以从初等数学中联系你对多项式的理解。它是一个正整数幂的变量。因此,多项式回归归结为使用多项式函数来对数据建模。如何知道何时使用这种类型的回归?简单地看一下数据分布,如果它与你在上图中看到的接近,你可以尝试使用多项式回归。数据科学是关于在真实世界场景中使用数学和统计知识,而不是像我们在学校里学到的那样,是一个假设的作业问题。
多项式回归函数的表示
Y = b0+ b1x +b2 x²+b3 x³ + ….+bn x^n
你可以看到它不同于线性函数,线性函数的形式是:
Y = b0 + b1 x1 + …+ bn xn
用 Python 实现
让我们深入研究 python,建立一个多项式回归模型,并尝试预测一个 6.5 级别的员工的工资(假设)。
在您继续之前,请从我的 GitHub Gist 下载 csv 数据文件。
[https://gist.github.com/tharunpeddisetty/22447d5446928f864b55e096b4aac995](https://gist.github.com/tharunpeddisetty/22447d5446928f864b55e096b4aac995)
Once you open the link, you can find "Download Zip" button on the top right corner of the window. Go ahead and download the files.
You can download 1) python file 2)data file (.csv)
Rename the folder accordingly and store it in desired location and you are all set.If you are a beginner I highly recommend you to open your python IDE and follow the steps below because here, I write detailed comments(statements after #.., these do not compile when our run the code) on the working of code. You can use the actual python as your backup file or for your future reference.
导入库
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
导入数据并定义 X 和 Y 变量
dataset = pd.read_csv(‘/Users/tharunpeddisetty/Desktop/Position_Salaries.csv’) #add your file path#iloc takes the values from the specified index locations and stores them in the assigned variable as an array
X = dataset.iloc[:,1:-1].values
y = dataset.iloc[:, -1].values
让我们看看我们的数据,了解一下变量:
作者图片
该数据描述了员工的职位/级别及其工资。你可以看到,随着工作级别的提高,工资的增长是非线性的。
可视化数据
作者图片
你可以看到绘制的数据是非线性增长的,因此,我们可以尝试多项式回归方法。请注意,我是说我们可以“尝试”,但不是说这是最好的模式。你会在我以后的文章中看到其中的道理。
训练模特
from sklearn.preprocessing import PolynomialFeatures
poly_reg = PolynomialFeatures(degree=4)
X_poly=poly_reg.fit_transform(X) #regressor is the object for class PolynomialFeatures
#degree=4 defines that the function must have x, x^2 , x^3 and x^4 terms
#fit_transform() returns a new data set with x, x^2 , x^3 and x^4 terms as the input data set
我们将使用模型中的全部数据,因此您不需要将数据分成训练和测试数据。
可视化多项式回归的结果
plt.scatter(X,y,c=’red’)
plt.plot(X,lin_reg2.predict(X_poly), c=’blue’)
plt.title(‘Polynomial Linear Regression’)
plt.xlabel(“Position Level”)
plt.ylabel(‘Salary’)
plt.show()
作者图片
你可以看到 4 次多项式函数给了我们合适的回归线。
可视化线性回归的结果
作者图片
您可以通过阅读我的线性回归文章来实现线性回归并将其可视化。以上图片已添加供您参考。不过你在我的要点文件里有它的代码。你可以立即看到回归线的巨大差异。
使用多项式线性回归预测 6.5 级结果
print(lin_reg2.predict(poly_reg.fit_transform([[6.5]])))
# we need to enter x1,x2,x3,x4 and this is the efficient model
# predict method expects a 2D array thats the reason you see [[6.5]]
# we use poly_reg.fit_transform because we want to transform our value 6.5 into a 3 other columns values with degree 4\. We need to enter the input exactly how we transformed it for using in the model
结果
多项式线性回归:158862.45
线性回归预测:330378.79(请自行尝试)
结论
我们可以看到,我们的多项式模型预测的实际工资介于 6 级和 7 级工资之间。看看线性回归的表现有多差。现在你可能会想,为什么我只考虑了这个问题的 4 度。好吧,我鼓励你尝试不同的程度,看看你的结果。尝试度=2、3、4、5、6 等
我希望这对你来说是有趣的。恭喜你!您已经用最少的代码行实现了多项式回归。当我说婴儿迈向数据科学时,我是认真的。现在您有了代码模板,可以在其他数据集上实现它,并通过更改想要使用的多项式函数的次数来观察结果。机器学*快乐!
迈向数据科学的一小步:Python 中的随机森林回归
理解随机森林回归背后的直觉,并用 python 实现。提供源代码和数据集。
基思·琼森在 Unsplash 上的照片
什么是随机森林回归?
随机森林算法是我的最爱之一。它可用于分类和回归。用更简单的语言来说,随机森林收集来自各种决策树的预测,并给出这些预测的*均值。这样,预测就有可能实际上收敛到真实值。每个决策树仅在数据子集上实现。该子集由算法随机选择,其中随机选取一个观察值并替换回数据集中,随机选择另一个观察值,添加到数据子集;这就是通常所说的自举。因此,您可以理解,单个观察可以多次成为决策树的一部分,因为我们替换了数据集中的观察并进行随机选择。对于多个决策树,这个过程重复多次。所有这些决策树统称为随机森林,现在,你确切地知道为什么使用随机和森林这两个词了。
这里的基本思想是在不同的数据样本上训练每棵树,并使用它们预测的*均值作为最终输出。这个输出的方差很小,很容易理解。
我可以强烈地说,随机森林比单一决策树更好。为什么?这是因为结果更加稳健。每一棵决策树都有自己的信息,并做出相应的预测。当我们组合所有这样的树时,结果预计会更加准确,并且接近*均真实值。
我将使用我在决策树文章中使用的相同数据集,这样您可以看到预测中的差异。
用 Python 实现
让我们深入研究 python,建立一个随机森林回归模型,并尝试预测一个 6.5 级别的员工的工资(假设)。
在您继续之前,请从我的 GitHub Gist 下载 CSV 数据文件。
[https://gist.github.com/tharunpeddisetty/8c3213de90fdc50c5814dbadcba181ac](https://gist.github.com/tharunpeddisetty/8c3213de90fdc50c5814dbadcba181ac)
Once you open the link, you can find "Download Zip" button on the top right corner of the window. Go ahead and download the files.
You can download 1) python file 2)data file (.csv)
Rename the folder accordingly and store it in desired location and you are all set.If you are a beginner I highly recommend you to open your python IDE and follow the steps below because here, I write detailed comments(statements after #.., these do not compile when our run the code) on the working of code. You can use the actual python as your backup file or for your future reference.
导入库
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
导入数据并定义 X 和 Y 变量
dataset = pd.read_csv(‘/Users/tharunpeddisetty/Desktop/Position_Salaries.csv’) #add your file pathX = dataset.iloc[:,1:-1].values
y = dataset.iloc[:, -1].values#iloc takes the values from the specified index locations and stores them in the assigned variable as an array
让我们看看我们的数据,了解变量:
该数据描述了员工的职位/级别及其工资。这与我在决策树回归文章中使用的数据集相同。
训练模型
from sklearn.ensemble import RandomForestRegressor
regressor = RandomForestRegressor(random_state=0,n_estimators=10)
regressor.fit(X,y)#random_state is the seed value, just to make sure we both get same results.
#n_estimators defines the number of trees you want to implement
可视化决策树回归的结果
X_grid = np.arange(min(X), max(X), 0.1)
X_grid = X_grid.reshape((len(X_grid), 1))
plt.scatter(X, y, color = 'red')
plt.plot(X_grid,regressor.predict(X_grid), color = 'blue')
plt.title('Random Forest Tree')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()
作者图片
作者图片(不包括代码)
这个可视化没有太多需要解释的。为了让你更好的理解和比较,我已经把我上一篇文章中决策树的可视化和预测结果包括进来了。
使用决策树回归预测 6.5 级结果
print(regressor.predict([[6.5]]))
# predict method expects a 2D array thats the reason you see [[6.5]]
结果
随机森林回归:167000
决策树回归:150000(不属于代码的输出)
结论
你可以亲眼看到随机森林回归比决策树预测的结果更真实。决策树对一个 6.5 级的员工预测了同样的工资,这似乎不太公*。当您查看随机森林预测时,它预测了 16.7 万美元,介于第 6 级和第 7 级之间,只要查看它,您就会发现它是有道理的。记住一件事,回归是所有关于*均行为和因素如何*均影响解释变量。
恭喜你!您已经用最少的代码行实现了随机森林回归。这很简单,对吗?。现在您有了代码的模板,您可以在其他数据集上实现它并观察结果。机器学*快乐!
迈向数据科学的一小步:Python 中的支持向量回归
理解支持向量回归背后的直觉,并用 python 实现。提供源代码和数据集。
什么是支持向量回归?
支持向量回归是一种特殊的回归,它为您提供了某种缓冲或误差灵活性。它是怎么做到的?我将通过展示两张不同的图表,用简单的术语向你解释。
作者图片
以上是假设的线性回归图。你可以看到回归线画在一个最小*方误差的位置。误差基本上是原始数据点(黑色点)和回归线(预测值)之间距离差的*方。
作者图片
以上与 SVR(支持向量回归)的设置相同。您可以观察到回归线周围有两条边界。这是回归线上下垂直距离为ε的管。实际上,它被称为ε不敏感管。这个管子的作用是为误差创造一个缓冲。具体来说,该管内的所有数据点被认为与回归线的误差为零。计算误差时,只考虑该管外的点。误差计算为数据点到管边界的距离,而不是数据点到回归线的距离(如线性回归所示)
为什么选择支持向量?
管外的所有点都称为松弛点,它们本质上是二维空间中的向量。想象一下,画出从原点到各个松弛点的向量,你就可以看到图中所有的向量。这些向量支持该管的结构或形成,因此它被称为支持向量回归。你可以从下面的图表中理解它。
用 Python 实现
让我们深入研究 python,建立一个随机森林回归模型,并尝试预测一个 6.5 级别的员工的工资(假设)。
在您继续之前,请从我的 GitHub Gist 下载 CSV 数据文件。
[https://gist.github.com/tharunpeddisetty/3fe7c29e9e56c3e17eb41a376e666083](https://gist.github.com/tharunpeddisetty/3fe7c29e9e56c3e17eb41a376e666083)
Once you open the link, you can find "Download Zip" button on the top right corner of the window. Go ahead and download the files.
You can download 1) python file 2)data file (.csv)
Rename the folder accordingly and store it in desired location and you are all set.If you are a beginner I highly recommend you to open your python IDE and follow the steps below because here, I write detailed comments(statements after #.., these do not compile when our run the code) on the working of code. You can use the actual python as your backup file or for your future reference.
导入库
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
导入数据并定义 X 和 Y 变量
dataset = pd.read_csv(‘/Users/tharunpeddisetty/Desktop/Position_Salaries.csv’) #add your file pathX = dataset.iloc[:,1:-1].values
y = dataset.iloc[:, -1].values#iloc takes the values from the specified index locations and stores them in the assigned variable as an array
让我们看看我们的数据,了解变量:
该数据描述了员工的职位/级别及其工资。这与我在决策树回归文章中使用的数据集相同。
特征缩放
#Feature Scaling. Required for SVR. Since there’s no concept of coefficients
print(y)
#we need to reshape y because standard scaler class expects a 2D array
y=y.reshape(len(y),1)from sklearn.preprocessing import StandardScaler
sc_X = StandardScaler()
sc_y = StandardScaler()
X= sc_X.fit_transform(X)
# create a new sc object because the first one calcualtes the mean and standard deviation of X. We need different values of mean and standard deviation for Y
y= sc_y.fit_transform(y) print(y)
SVR 中没有类似线性回归的系数概念,因此为了减少高值特征的影响,我们需要对特征进行缩放,或者换句话说,在一个缩放比例下获取所有值。我们通过标准化价值观来实现这一目标。因为在这个例子中我们只有一个特性,所以无论如何我们都要应用它。我们使用 sklearn 的 StandardScaler()函数来实现。但是,对于其他数据集,不要忘记缩放所有要素和因变量。此外,请记住对 Y(因变量即薪水)进行整形,这纯粹是为了通过 python 中的标准缩放器来传递它。
训练 SVR 模型
from sklearn.svm import SVR
regressor = SVR(kernel = 'rbf')
regressor.fit(X, y)
很简单,不是吗?我们将使用径向基函数作为支持向量回归算法的核心。这意味着我们使用一个叫做“rbf”的函数来将数据从一个空间映射到另一个空间。解释这是如何工作的超出了本文的范围。但是,你可以在网上研究一下。核函数的选择随着数据的分布而变化。我建议你在用 python 实现这个基本程序后研究一下它们。
可视化 SVR 回归的结果
X_grid = np.arange(min(sc_X.inverse_transform(X)), max(sc_X.inverse_transform(X)), 0.1)
X_grid = X_grid.reshape((len(X_grid), 1))
plt.scatter(sc_X.inverse_transform(X), sc_y.inverse_transform(y), color = 'red')
plt.plot(X_grid, sc_y.inverse_transform(regressor.predict(sc_X.transform(X_grid))), color = 'blue')
plt.title('Support Vector Regression')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()
作者图片
你可以看到这个模型是如何符合数据的。你认为它做得很好吗?将这一结果与我以前文章中对相同数据进行的其他回归进行比较,您就可以看到差异,或者等到本文结束时再看。
使用决策树回归预测 6.5 级结果
print(sc_y.inverse_transform(regressor.predict(sc_X.transform([[6.5]])))
)
#We also need to inverse transform in order to get the final result
确保将所有转换应用为初始数据的转换,以便模型更容易识别数据并生成相关结果。
结果
让我总结一下各种回归模型的所有结果,以便于我们进行比较。
支持向量回归机:17560 . 486868686686
随机森林回归:167000(输出不是代码的一部分)
决策树回归:150000(输出不是代码的一部分)
多项式线性回归:158862.45(输出不是代码的一部分)
线性回归预测:330378.79(输出不是代码的一部分)
结论
你面前有数据。现在,作为一名经理,自己做决定。你会给一个 6.5 级的员工多少薪水(把级别看作是工作经验的年限)?你看,在数据科学中没有绝对的答案。我不能说 SVR 比其他模型表现得更好,所以它是预测工资的最佳模型。如果你问我的想法,我觉得随机森林回归的预测结果比 SVR 更真实。但是,这也是我的感觉。请记住,很多因素都会发挥作用,如员工的职位、该职位在该地区的*均工资以及员工以前的工资等。所以,如果我说随机森林结果是最好的,你也不要相信我。我只说比别人更现实。最终的决定取决于组织的商业案例,而且没有一个完美的模型可以完美地预测员工的工资。
恭喜你!您已经用最少的代码行实现了支持向量回归。现在您有了代码的模板,您可以在其他数据集上实现它并观察结果。这标志着我关于回归的文章的结束。下一站是分类模型。感谢阅读。机器学*快乐!
巴赫最喜欢的音符
斯蒂芬尼·安德拉德在 Unsplash 上的照片
我一直喜欢古典音乐。小时候,我花了大约 10 年时间学*乐理,拉小提琴。当然,我最大的爱好是科学和数据。我总是试图找到结合两者的方法,用数据科学来分析古典音乐。我不想分析古典作品的声音,我想把我的分析集中在音乐理论上。我想研究音乐作曲家是如何创作音乐的,而不是音乐是如何演奏的。本质上,我在寻找一种将乐谱转换成结构化数据的方法。
我选择巴赫的音乐有几个原因。首先,巴赫被认为是音乐天才,是最伟大的古典音乐作曲家之一,所以分析他的音乐总是很有趣。其次,巴赫写了 1000 多首曲子,所以有大量的数据需要分析。第三,巴赫的音乐是非常严格地遵循调性体系和对位法的规则来创作的,这使得音乐更加结构化,也更容易从和弦分析的角度来分析。最后,我真的很喜欢巴赫的音乐,所以也有一些个人偏好。
在本文中,我不深入分析背后的代码的技术细节,但如果感兴趣,读者可以在这里找到完整的代码。
数据
如上所述,我的第一个问题是获得能让我分析音乐理论的数据。音频文件如.wav
、.aiff
或压缩音频文件如.wma
、.mp3
等。不适合这种分析。从整个管弦乐队的原始音频到特定的音符、和弦、音乐调等。这将是一个更加困难的项目,一个我不知道如何在合理的时间内完成的项目。
不过,有一种格式可以用于我的分析。。midi 格式,用于控制电子或数字乐器。使用.midi
,音符(音高)的演奏、音符的持续时间以及演奏音符的乐器(通道)都是直接指定的。此外,我有一个简单的方法来转换。midi 文件到.csv
文件,即结构化数据,此时我可以用熟悉的方式分析它,就像任何其他结构化数据一样。
我发现了muto pia 项目,它收集了大量的古典音乐作品,全部都在公共领域。我在网站上搜寻 J.S .巴赫的作品。网站上有 417 首巴赫的作品,但有些有多个文件,所以文件总数是 529。我使用我在这里找到的代码将所有的.midi
文件转换为.csv
文件。在我拿到.csv
的文件后,我可以开始我的分析。分析是用 Python 完成的,我的代码可以在这里找到。
数音符
关于一首音乐作品,我想回答的第一个问题是,它是由哪些音符组成的。哪一个音符用得最多?哪张纸币用得最少?音符的分布或多或少是均匀的,还是有些音符比其他音符用得多?
换句话说,计算一个音符出现的次数,一个新音符出现的事件可以给我们这样的分布。另一方面,一些音符可能持续一个完整的小节,而另一些音符在快速段落中仅作为十六分音符出现。我认为音符的持续时间应该作为分布中的一个权重,这样较长的音符比持续时间较短的音符更重要。
在.midi
文件中,乐器在特定时间内演奏一个或多个音符。记录音符开始播放的时间和音符停止播放的时间。这给了我们音符的持续时间,这是用时钟滴答来衡量的。它可以通过转换因子(一个四分音符中的节拍数)转换为常规音符长度,该转换因子也包含在文件中。因此,我们可以提取传统乐谱中音符的持续时间,即四分音符、八分音符等。
将一个音符在音乐作品中的所有持续时间相加,将得出该音符的总持续时间。我们可以对每个音符都这样做,所以最后,我们可以比较所有音符的总持续时间,看看哪个音符被演奏得最多。
作为一个例子,我们来看看巴赫的《c 大调第一发明》(BWV 772) 。在这里可以找到的活页乐谱。我们可以看到这首曲子是用 c 大调写的,没有升半音,所以自然音符都有更高的持续时间。此外,C 键的主音,是使用最多的音符,不出所料,第五个(G)和第三个(E),分别位于第二和第三位。尽管这首曲子只有 22 小节长,但 G 大调、A 小调、F 大调都有调式,这也是降 B 调、升 F 调和升 C 调的由来。
这可以扩展到我们数据集中所有巴赫的作品。将每首乐曲中每个音符的值相加,我们得到所有音符持续时间的总和。结果可以在下图中看到。音符 D 是巴赫使用最多的音符,使用频率比 A 稍高,A 排在第二位,其余的自然音符紧随其后。
在图表中,我们分别标出了自然音符、降半音和升半音。这样做是为了证明一个惊人的观察。自然音符确实显示出一些可变性,演奏最多的音符(D)的持续时间几乎是演奏最少的音符(F)的两倍。然而,该分布类似于均匀分布。另一方面,高音符的持续时间变化很大,演奏最多的音符(升 F)的持续时间是演奏最少的音符(升 B)的 46.5 倍。这同样适用于公寓。
然而更有趣的是,从第一场到最后一场比赛的升半音的顺序确切地说是升半音在调号符号中的顺序:F♯、C♯、G♯、D♯、A♯、E♯、B♯.同样,降半音的顺序与调号符号中的降半音顺序完全一致:B♭、E♭、A♭、D♭、G♭、C♭、F♭.最后,双升半音的持续时间比自然音低几百倍。
从第一个到最后一个升半音的顺序与调号符号中升半音的顺序完全匹配
计算和弦
到目前为止,我们一直在数单个的音符。然而在音乐中,几个音符可以同时发出声音,形成和弦。如果各种乐器或声部同时演奏不同的音符,或者同一种乐器同时演奏多个音符,就会出现这种情况。
这里,我们将和弦定义为一起演奏的任意数量的音符。因此,三个音符一起演奏,例如 C、E、G,是一个和弦,但是仅仅两个音符一起演奏(例如 G)或者甚至一个音符单独演奏(E)也被认为是一个和弦。还有,我们会把不同八度的音符当做同一个音符,在和弦中只算一次。例如,如果 C4、E4、C5 和 E5 一起发音,我们将把它视为(C,E)和弦。此外,和弦中音符的顺序并不重要。例如,和弦 C4、E4、G4 会被认为与 E3、G3、C4 相同。更正式地说,我们对和弦的定义是音乐理论中的一组和弦。
我们希望将我们用于音符的相同方法应用于和弦。但是我们如何测量和弦的持续时间呢?为了做到这一点,我们将乐曲拆分为最小的节奏值,即第六十四个音符。对于每个第 64 个音符音程,我们收集在该音程弹奏的所有音符,形成一个和弦。我们将每个和弦的第 64 个音符音程的所有实例相加,得出每个和弦在第 64 个音符中的总持续时间。最后,我们将持续时间转换为四分音符。
有成千上万种方法可以将音符组合成一个和弦,但大多数在实践中使用起来都很不和谐。此外,许多作品只为一种乐器创作,如小提琴、大提琴或鲁特琴,所以它们的完整乐谱通常只有单个音符,没有和弦出现。这使得数据偏向单个音符。因此,这里我们只展示两个或两个以上音符的和弦。尽管如此,巴赫的作品中仍然使用了数千种音符组合,即使其中一些只使用了一次,或者只使用了很短的时间。在下面的情节中,我们展示了巴赫作品中最常用的 30 个和弦。
我们注意到,音程(B,G)占第一位,后面是音程(E,G)和(A,C)。第一个全和弦,即包含主音、第三和第五音的和声三和弦,是(B、D、G)或 G 大调,出现在第四个位置。接下来的和声三和弦是 D 大调,C 大调,A 大调,D 小调和 A 小调。
和弦排名
如前所述,我们在巴赫的作品中发现了数以千计的音符组合,但其中大多数很少使用,而另一些则一直在使用。这类似于自然语言中单词的使用。Zipf 定律描述了这种排列数据的行为。具体来说,Zipf–Mandelbrot 定律是 Zipf 定律的扩展,描述了排名数据的分布。我们拟合了 Zipf–Mandelbrot 定律形式的函数,得到了相对较好的拟合。我们应该强调的是,与上一张图表不同,这张图表中包含了单音符和弦。
有一篇由胡安·伊格纳西奥·佩罗蒂和奥兰多·维托·比罗尼撰写的论文,他们描述了当齐夫定律应用于音乐作品中的音符和和弦时的类似发现。
和弦类型
另一个有趣的发现是所有第一位置的全和弦不是大调就是小调和弦。我们想进一步探索这个想法,并确定巴赫使用的所有和弦类型。为了做到这一点,我们需要将和弦从音符的常规和弦转换成音高等级集。音高类别集是一组数字,表示组成和弦的音符与第一个音高的相对差异,第一个音高被赋予数字 0。差异是用半音来衡量的。例如,大和弦三和弦对应于集合(0,4,7),因为第一个和第二个音符相隔 4 个半音(大三度),第一个和第三个音符相隔 7 个半音(完全五度)。
这样,我们可以将和弦的类型分组在一起,因为所有的主和弦都对应于同一个集合。同样,所有小和弦都对应于集合(0,3,7)。其他常*的集合也有传统的名称,例如,集合(0,2,7)被称为悬弦,集合(0,1,4,7)被称为减大七和弦。
一组音符通常对应于一个以上的音高标准组。例如,集合(C,E,G)可以对应于集合(0,4,7),也可以对应于集合(0,3,8),这取决于音符的顺序。我们总是采用集合的最紧凑形式,即第一个和最后一个音高之间的距离最小的形式,作为音高类集合。此外,可能存在一个以上的最紧密集合。在这种情况下,我们选择按缩短顺序排在第一位的集合。例如,在集合(0,1,5)和(0,4,5)之间,我们选择第一个。
我们在下图中展示了结果。只要有可能,我们就用传统的和弦名称来代替数字集合。
很快,我们注意到所有的第一位置都对应众所周知的音程和和弦。在这里,我们用现代术语识别了大七和弦、悬和弦和其他类型。当然,在巴洛克音乐中,作曲家们并不这样想。除了大和弦、小和弦、减和弦和增和弦之外,其余都是一个声部用“非和弦”音符演奏旋律,然后将其余声部加入到一个辅音和弦中。
此外,我们注意到单音符和双音符音程比全和弦更常*。这也是因为一些作品是为独奏乐器创作的,所以它们包含了更多的单音符。另一个有趣的观察是,大和弦的使用率几乎是小和弦的 1.5 倍。
和弦进行
我们现在开始和弦进行。从音乐理论的角度来看,一段音乐可以被认为是一系列的和弦,一个接一个。这被称为和弦进行,是音乐理论中的一个主要话题。我们需要澄清的是,巴洛克时代的作曲家并没有按照和弦进行来思考,这是一种现代的解释。然而,从现代音乐理论的角度来看巴赫作品中的和弦进行是很有趣的。
这一次,和弦的持续时间并不重要。我们只关心接下来的和弦。如前所述,我们将和弦转换为音高等级集合。对于每首曲子,我们都按照和弦的顺序创建一个列表,从第一个和弦到最后一个和弦。然后我们按两个或更多和弦的顺序将和弦分组。这个过程相当于一段文本的 n-grams ,其中和弦可以被认为是文本的单词,音乐片段可以被认为是文档。实际上,在代码中,我们使用了与自然语言处理完全相同的方法。
在这一点上,我们将搜索限制在至少有一个三和弦的和弦进行上。这样做是因为,正如我们之前注意到的,数据偏向于单音符和双音符和弦,但为了更好地理解音乐作品的和声,我们需要研究完整的和弦。如果我们不使用这个限制,第一个位置都是单音符和双音符的级数。在下图中,我们展示了前 30 个双弦序列(二元模型)。
我们注意到巴赫通常是从大调和弦转到小调和弦,然后回到大调和弦,或者从一个大调和弦转到另一个。我们也注意到悬弦的使用。对位法中一个常*的技巧是将一个音符从前一个和弦带到下一个和弦,最后分解到第三个或主音。我们可以概括所有不和谐的和弦——至少根据巴洛克的标准——比如悬和弦、七和弦等等。我们可以看到,这些和弦总是解析为一个协和和弦(比如大调或小调和弦)。
接下来,我们绘制三和弦序列(三元组)。这一次,我们注意到进展变得更加具体。我们不太可能找到三个和弦的特定顺序。例如,级数(大调->小调->大调)与(小调->大调->小调)不同。尽管很明显,在这两个进行中,我们只是从大调和弦到小调和弦,然后再回到大调和弦,我们可以有几种进行顺序的排列,都会导致不同的进行。如果我们把它扩展到更长的序列(n-gram ),这种进展会变得更加具体和不那么频繁。因此,我们在这里停止分析。也许以后,我们可以尝试对排列进行分组,以获得更有趣的长序列结果。
结论
在这篇文章中,我试图用数据科学的方法来分析巴赫的音乐。这些发现,结合巴赫创作音乐时期的历史知识,从音乐理论的角度来看,符合众所周知的事实。
首先,巴赫使用的音符频率几乎完美地契合了良好的调律和惯例调性。巴赫在展示调和调音的可能性方面发挥了重要作用,这种调音后来演变为所有西方音乐中使用的标准*均律系统。此外,巴赫对和弦的使用,主要是大调和小调和弦以及这些和弦的相关音程,与巴洛克音乐形式相一致。更复杂的和弦,如第七和弦,被认为是不和谐的,在巴洛克时期被避免使用。在巴赫的作品中,这种不和谐的和弦大多发生在其中一个声部在大调或小调和弦上演奏一段旋律时。这段的音符与主和弦相结合可能会产生更不和谐的和弦,但在巴赫的时代,这甚至不会被认为是和弦。最后,和弦进行分析与通常的和弦进行是一致的。我们观察到,最常*的进行方式是从大调到小调和弦,然后再转回来,甚至偶尔用一些附加音符来维持大调和弦。我们还注意到,大多数不和谐和弦会立即分解为大调或小调和弦。
如果有足够的数据,这种分析可以扩展到古典时期任何其他作曲家的作品,甚至可以扩展到同一时期几个作曲家的作品集合。也可以探索其他想法,例如将作品分组以揭示有趣的模式,或者使用这种分析来识别音乐作品的作曲家。
这个分析的完整代码可以在这里找到。
信封背面快速数据分析
内部 AI
“一个眼神胜过千言万语。”这些快速数据分析有可能提高模型预测精度和集中数据预处理
基于本文讨论的代码的数据可视化——图片来自作者
数据分析是任何机器学*工作流的重要元素。任何机器学*模型预测的性能和准确性都取决于数据分析和后续的适当数据预处理。每个机器学*专业人员都应该擅长数据分析。
在这篇文章中,我将讨论四种非常快速的数据可视化技术,它们可以用几行代码实现,并且可以帮助规划所需的数据预处理。
我们将使用来自 open ML 的印度肝病患者数据集来学*快速有效的数据可视化技术。
该数据集包含分类和数字独立特征的混合,以及肝脏和非肝脏状况的诊断结果。
from sklearn.datasets import fetch_openml
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
我觉得使用 Pandas dataframe 比默认的 bunch 对象更容易和高效。参数“as_frame=True”确保数据是 pandas 数据帧,包括具有适当数据类型的列。
X,y= fetch_openml(name="ilpd",return_X_y=True,as_frame=True)
print(X.info())
由于独立数据在 Pandas 中,我们可以通过“info”查看特性的数量、具有空值的记录的数量以及每个特性的数据类型。
独立的特性、计数和数据类型—基于上面讨论的代码(图片由作者提供)
它只用一行代码就立即提供了大量关于自变量的信息。
考虑到我们有几个数字特征,理解这些变量之间的相关性是谨慎的。在下面的代码中,我们创建了一个没有分类变量“V2”的新数据帧 X_Numerical。
X_Numerical=X.drop(["V2"], axis=1)
很少有机器学*算法在处理高度线性相关的独立变量时表现不佳。此外,目标始终是用最少的所需变量/维度构建一个机器学*模型。
我们可以使用熊猫的“corr”函数来获得所有数值特征之间的相关性。
使用 seaborn 软件包,我们可以绘制相关性的热图,从而快速直观地了解独立变量之间的相关性。
relation=X_Numerical.corr(method='pearson')
sns.heatmap(relation, annot=True,cmap="Spectral")
plt.show()
粗略地看,我们可以得出结论,自变量 V4 和 V3 具有密切的关系,并且像 V1 和 V10 这样的特征很少是松散负相关的。
基于上述代码讨论的独立特征的相关矩阵(图片由作者提供)
接下来了解特性之间的相关性后,快速了解数值特性的值分布将会非常有用。
就像相关函数一样,Pandas 有一个本地函数“hist”来获得特征的分布。
X_Numerical.hist(color="Lightgreen")
plt.show()
基于上面讨论的代码的独立特性的分布(图片由作者提供)
直到现在,熊猫的力量和多才多艺才被清楚地展示出来。我们只需要两行代码就可以得到数字特征之间的关系和特征的分布。
接下来,通过所有数值变量组合之间的散点图来更好地理解数值自变量将会很有趣。
sns.pairplot(X_Numerical)
plt.show()
借助于观想,我们可以识别出正相关或负相关的变量。此外,只要看一眼,就可以识别出彼此之间没有关系的特征。
基于上述代码的独立特征散点图(图片由作者提供)
最后,我们可以通过计数图了解分类特征的分布。
sns.countplot(x="V2", data=X)
plt.show()
我们知道,与女性相比,男性在数据集中的比例过高。了解我们是否有不*衡的数据集并采取适当的措施是至关重要的。
你可以阅读更多关于 4 种管理不*衡分类情况的独特方法
基于上述代码的分类特征计数(图片由作者提供)
关键要点和结论
我们可以用不到 15 行代码快速获得许多信息,如不同特征之间的相关性、它们的分布和散点图。
这些快速可视化有助于在开始任何复杂的建模练*之前,将注意力集中在数据预处理区域。
在这些可视化的帮助下,即使没有正式的建模或高级统计分析,我们也可以了解大量的数据并做出推断。
您可以了解更多关于 5 用于探索性数据分析(EDA)的高级可视化和 5 用于数据预处理的熊猫强大可视化
**"""Full Code"""****from sklearn.datasets import fetch_openml
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns****X,y= fetch_openml(name="ilpd",return_X_y=True,as_frame=True)
print(X.info())****X_Numerical=X.drop(["V2"], axis=1)****relation=X_Numerical.corr(method='pearson')
sns.heatmap(relation, annot=True,cmap="Spectral")
plt.show()****X_Numerical.hist(color="Lightgreen")
plt.show(****sns.pairplot(X_Numerical)
plt.show()****sns.countplot(x="V2", data=X)
plt.show()**
是的,你应该听安德烈·卡帕西的,并且理解反向传播
不是穿着闪亮盔甲的骑士,但绝对是我们人工智能战斗卡中的无名英雄
罗马法师在 Unsplash 上拍摄的照片
如果你问周围的任何人,他们会告诉你人工智能是最热门和发展最快的领域。我们在监督学*方面取得了巨大的进步——自然语言处理和计算机视觉。这两个领域解决非常不同的问题,并且没有很多共同的文献。在一个方面表现出色的模型在另一个方面表现不佳。但在内心深处,它们确实有一些共同点,那就是反向传播——这种机制有助于我们从输出到输入反向传播损失——在模型的训练阶段发挥着非常关键的作用。
但是首先让我们看看每一个监督学*模型将会有什么:
- 一个架构 :可以是 CNN/RNN/NN。此外,层数、每层的激活函数和维数、学*速率等。
- 一个损失/成本函数 :当一个 ML 模型做一个预测的时候,我们需要一个方法来计算我们离地面真相有多远。
- 一个优化器 :一旦我们有了损失,我们需要更新我们的模型的权重,以便最小化我们的损失。
那么反向传播在这幅图中处于什么位置呢?它连接了损失函数和优化器。损耗在输出层计算,然后我们使用反向传播将损耗以其梯度的形式传播回去,一直传播回输入层的输入(因此称为反向传播)。一旦 back prop 完成,我们知道每个节点的损失梯度,然后我们使用优化器来更新权重,试图在下一次迭代中最小化损失。Back prop 是本地的
如何计算渐变?
计算 F=XYZ 的梯度
设 F= XYZ 并要求你计算 ∂F/ ∂X,∂f/ ∂z。
我们很容易弄清楚,
∂f/ ∂x=y * z=-2 -3 = 6,
∂f/ ∂y=x * z= 6 -3 =-18,
和 ∂F/ ∂Z = XY = 6-2。
但是我们如何使用上面的计算图来计算呢?
- 从最终输出开始, F 。∂F/ ∂F 是 1。所以回流到乘法节点( AZ* )的上游梯度为 1。
- 计算节点输入的局部梯度 F=AZ,∂F/∂A* = Z 和 ∂F/∂Z = A. 将为输入回流的上游梯度将是来自特定节点输出 的 局部梯度上游梯度。因此,a 的上游梯度将为 ∂F/∂A * ∂F/∂F = Z1 = -3 ,而 z 的上游梯度将为 ∂F/∂Z * ∂F/∂F = A1 = -12。***
- 对节点 A = XZ.* 上游坡度= -3 重复步骤 2。
x 的局部梯度: ∂A/∂X = Y = -2。 y 的局部梯度: ∂A/∂Y = X= 6。 上游梯度回流 x:localgradientx * upstreamgradientfromputput=∂a/∂x * ∂f/∂a = ∂f/∂x =-2 -3 = 6。 上游梯度回流 y:localgradienty * upstreamgradientfromputput=∂a/∂y * ∂f/∂a = ∂f/∂y = 6 -3 =-18。
神经网络中的反向传播
这里唯一改变的是每个节点上发生的计算。不是简单的乘法运算,每个节点都有一个激活 函数,Y =H(X1,X2,…,Xi)。 在正向传递本身中——当我们计算 Y 时——我们还会计算并存储当地的梯度 ∂Y/∂X1、∂Y/∂X2、∂Y/∂X?和 ∂Y/∂Xi.
神经网络中梯度流和计算的示例。红色箭头显示渐变的流向。绿色箭头显示了向前传递的值的流向。
当我们得到反向传播中的上游梯度时,我们可以简单地将其与对应于每个输入的局部梯度相乘,并将其传回。在上面的例子中,我们从 2 个节点获得上游梯度,因此绿色节点接收的总梯度只是所有上游梯度的相加——在这种情况下是两个上游梯度。然后,我们将每个局部梯度乘以总的上游梯度,并将其向后传递给相应的输入。
雅可比矩阵。每一列都是某个输入向量的局部梯度。来源。
在神经网络中,节点的输入 X 和输出是向量。函数 H 是一个矩阵乘法运算。 Y =H(X) = WX,其中 W* 是我们的权重矩阵。局部梯度为雅可比矩阵—YwrtX各元素的微分。
实际上,输入向量 Xi 只影响输出向量中的 Fi 。
RNN 的反向支持——递归神经网络
在 RNNs 中事情变得有点棘手,因为与 NNs 不同,在 NNs 中,节点的输出和输入彼此独立,当前步骤的输出作为输入被馈送到下一步骤中的相同节点。理论上,它对我们的反向传播流没有任何影响,但在实践中,它导致了臭名昭著的消失梯度和爆炸梯度问题。
未卷起的 RNN 中的梯度流。注意,每个时间步长的 Fw 保持不变。由于相互依赖,每个时间步的输出和输入都是变化的。
考虑上面的普通 RNN,在每个时间步的向前传递中, F(xi) = Wxi,其中 xi* 是第 i 时间步的输入, W 是权重矩阵,W 对于每个步骤保持不变。在反向传播期间,每个节点的局部梯度被称为 h(xi)。到达输入节点的梯度将是 L* h(xt)h(xt-1)..h(x1)。如果所有的 h(xi) 大于 k ,那么输入处的梯度大于 Lk^t. 对于深度 RNNs t 可能很大,在这种情况下,如果 k > 1,梯度继续呈指数增加,导致梯度变得太大的爆炸性梯度问题。
类似地,在输入节点处的所有 h(xi) < k,梯度将小于 LK^t* 的情况下,如果 k < 1,梯度在到达输入层时将几乎变为 0——消失梯度问题,其中梯度变得太小而无法引起任何有意义的更新。
由于 F(xi) 本质上是一个矩阵乘法,h(Xi)= F’(Xi)也就是~ W 。对于具有 t 时间步长的 RNN,在反向传播期间,局部梯度将是 h(xi),即权重矩阵——或其一部分——并且在每一步,当我们计算local gradient * upstream gradient时,它将一次又一次地与自身相乘,因为上游梯度是某个局部梯度(本质上是 W 或其一部分)及其在每个先前时间步长的相应上游梯度的递归乘积。根据 W 中元素的值,我们将面临两种梯度问题中的任何一种,大于 1 的元素会爆炸,更小的元素会消失。
CNN —卷积神经网络中的反向传播
CNN 的情况与其他案例略有不同,但基本概念保持不变。我们仍将通过乘以上游和局部梯度来计算梯度,但在这种情况下事情有点复杂。在前向传递中,这里的输入不像在 NN 中那样贡献给所有的输出,同时,它们也不像在 RNN 中那样只贡献给单个输出。在正向传递中,如下图所示,每个输出总是接受四个不同输入的贡献,而一个输入可以贡献的输出数量取决于其位置。
CNN 中的向前传递:一个 2x2 内核(显示为黄色)以步长 1 覆盖输入层(3x3 ),以给出一个 2x2 输出——具有四种不同的颜色,每种颜色突出显示在其计算中起作用的输入。
在回柱过程中,我们将知道上游的坡度: ∂L/ ∂y1、∂L/ ∂y2、∂L/ ∂y3 和 ∂L/ ∂y4 。当地梯度: ∂y1/ ∂x1 、∂y1/ ∂x2、∂y1/ ∂x3、∂y1/ ∂x4、∂y1/ ∂x5、∂y1/ ∂x6、∂y1/ ∂x7、∂y1/ ∂x8 和∂y1/ ∂x9。
我们知道 y1 = w1x1 +w2x2 +w3x4 +w4x5。因此,
∂y1/ ∂x1 = w1。从上图可以看出 x1 只对 y1 有贡献,所以∂l/ ∂x1 = ∂l/ ∂y1∂y1/ ∂x1 = ∂l/ ∂y1 * w1。*
对于 ∂L/ ∂x5 ,由于 x5 对四路输出都有贡献,
∂l/ ∂x5 = ∂l/ ∂y1∂l/ ∂y1+∂l/ ∂y2∂y2/ ∂x5+∂l/ ∂y3∂y3/ ∂x5+∂l/ ∂y4∂y4/ ∂x5,* ∂y1/ ∂x5 = w4,
∂y2/ ∂x5 = w3,
≈y1/≈X5 = w1
≈y1/≈X5 = w2。
实际上,我们可以通过将核旋转 180 度并使用旋转后的核对输出矩阵执行完全卷积来计算梯度。
执行全卷积以计算梯度。参考。
在他关于反向传播的文章中,Andrej Karpathy 描述如下:
反向传播是一种有漏洞的抽象;这是一个具有重要后果的信用分配方案。如果你因为“TensorFlow 自动让我的网络学*”而试图忽略它在幕后是如何工作的,你将没有准备好应对它所带来的危险,你在构建和调试神经网络方面的效率将会低得多。
虽然您可能在不了解反向传播的情况下训练一个 ML 模型并获得良好的结果,但是理解它将使您在训练神经网络时占上风,这将使您能够更好地理解工作,从而提高其性能。
参考资料:
- deep grid——阅读更多关于 CNN 的信息。
- 了解全卷积:https://medium . com/@ 2017 CSM 1006/卷积神经网络中的前向和后向传播-4dfa96d7b37e
- 安德鲁·卡帕西的斯坦福笔记
- 在斯坦福大学的讲座中,点击查看更多关于计算图的信息。
我很高兴你坚持到了这篇文章的结尾。👏我希望你的阅读体验和我写这篇文章时一样丰富。💖**
请点击这里查看我的其他文章。
如果你想联系我,我会选择推特。
使用 CPPI 策略对 NIFTY 50 股票进行回测分析:一种数据科学方法
介绍
本文试图通过分析新冠肺炎疫情对 NIFTY-50 股票的影响,使用数据科学方法来解决现实世界的投资管理问题。
像新冠肺炎这样的疫情事件是“黑天鹅”事件,因为它们无法预测,而且没有任何分散投资策略可以保护投资免受这种系统性风险的影响。正如专家所说,“多样化会在你最需要的时候让你失望”。在 2008 年金融危机或我们现在面临的新冠肺炎疫情等事件中,即使是非常多元化的投资组合也会亏损。那么,当市场在此类事件中崩盘时,你如何保护自己的财富,同时又能参与上涨,在不失去你的财务目标的情况下,两全其美呢?答案是,在建立投资组合时,要有一个“保险”或“安全网”之类的策略。曾经这样的“安全网”策略就是固定比例投资组合保险(CPPI)。
尽管这类策略在行业中以多种形式和技术使用,但在这里,我们尝试通过一步一步的数据科学方法,从相关来源提取足够的数据,对其进行清理、转换和建模,实施动态 CPPI 算法,获得回溯测试结果,并使用高级数据可视化方法对策略进行交互分析。在接下来的几节中,我们将更多地讨论用户交互性、直观性和 CPPI 计算的算法复杂性之间的*衡,而不是 CPPI 作为投资组合策略的本质。关于 CPPI 如何运作的更多细节和它是什么的一个外行例子,看一看 https://www.investopedia.com/terms/c/cppi.asp。我们使用 Python/Anaconda 实现数据工程&算法,使用 Tableau 实现数据可视化,使用分析扩展库 TabPy 作为解决方案的技术工具。
确定数据源和数据准备步骤
我们研究的主要数据来源是 NSE 印度网站,我们试图使用网络抓取来提取 NIFTY-50 股票的历史价格。然后我们发现了一个非常有用的库/API‘NSEPY ’,它以一种更优雅的方式提取给定股票代码的历史价格。因此,我们首先创建了 50 只股票的列表,并调用 NSEpy 库/API(【https://github.com/swapniljariwala/nsepy/tree/master/nsepy】)来提取 2018 年 1 月至 2020 年 6 月的数据。
从 NSE 提取的原始数据如下所示:
这些数据点基本上是股票在某一天的各种价格点。为投资组合分析处理每日频率数据可能有些过分,为了简单起*,我们将每周汇总数据。从每日价格中,我们会发现周价格点,如开盘价、收盘价、最高价和最低价。我们还应该注意列标题,确保它们看起来干净,中间没有任何空格或特殊字符。一旦你转换成每周时间序列数据,数据框架应该像下面这样:
在每周分组后,计算每周收益,这是相对于前一周的价格变化百分比。
上述数据框的可视化表示应类似于 Tableau 中的下图或任何数据可视化工具。正如我们所*,在 2020 年 2 月至 5 月期间,每周回报非常繁忙,导致波动很大。
CPPI 的逻辑
在这一节中,我们将看到如何用 Python 实现 CPPI 算法的伪代码。实现它的步骤基本上不多,用 python 实现也不复杂。
对于给定的一组周收益时间序列数据,我们需要遍历尽可能多的步骤来计算和存储每个时间点的各种指标。
初始化并设置 CPPI 参数
#设置 CPPI 参数
n_steps = len(每周回报数据集)
account_value = start(你投资的起始值)
floor _ value = start * floor(floor 是一个输入参数,通常在 0.1-1.0 之间)
peak = account_value
然后,对于每周回报时间序列中的每一步,计算以下步骤
第一步:缓冲=(账户值-下限值)/账户值
第二步:计算风险重量和安全重量:
risky_weight = m * cushion (m 是一个输入参数,它是一个乘数,基本上表示投资者的风险状况,是一个标准化值,介于 0-1 之间)
safe _ weight = 1—risky _ weight
risky _ allocation = account _ value * risky _ weight
安全分配=账户价值*安全重量
第三步:重新计算账户值
*account _ value = risky _ allocation *(1+risky _ week _ return)+safe _ allocation (1+safe _ week _ return)
其中 risky_weekly_return 是作为输入接收的股票的时间序列每周回报,safe_weekly_return 通常使用安全净产品(如国债)的假定无风险利率计算。
第四步:使用累计乘积法计算风险财富,因为每个时间段的回报都需要复合。
risky _ wealth = start (1+risky _ r[step]) risky _ wealth _ prev
risky _ wealth _ prev =(1+risky _ r[step]) risky _ wealth _ prev*
第五步:将每个时间段的所有指标存储在后验容器中。
年化回报率与年化波动率
现在我们已经有了 CPPI 算法,让我们挑选一些回报率较高的股票和一些波动性较大的股票,观察 CPPI 策略的回溯测试结果。
雀巢印度公司表现最好,盖尔表现最差
印度斯坦联合利华的年波动率最低,而印度银行的年波动率最高
我们可以很容易地观察到,波动性对业绩不利,很明显,高绩效股票(高年回报率)的波动性低,反之亦然。
为什么 CPPI 是一个安全网战略
雀巢印度公司是 2018 年 1 月至 2020 年 6 月期间表现最好的股票,使用 CPPI 策略,1000 卢比的初始投资回报了 1522.36 英镑的最终财富。如果我们在没有任何策略的情况下投资所有的 1000 卢比,我们最终会得到 2119 卢比。很明显,在形势大好的时候,我们遵循 CPPI 的策略是在吃亏。
但 CPPI 策略的优势在于,当黑天鹅出现时,当情况不妙时。当我们观察盖尔,这是表现最差的股票,我们将能够体会到这一战略的好处。
正如我们所看到的,如果我们没有实施 CPPI 策略,把所有的钱都投资到高风险账户,我们最初的投资 1000 卢比,最终的价值是 210.4 卢比。这会粉碎投资者的财务目标,不是吗?。相反,如果我们遵循 CPPI 策略,我们的损失不会低于我们之前设定的最低价值,我们最终会获得 807.62 卢比,从而保护我们的财务目标,在很大程度上减少损失,保护资本。
由于我们必须进行再*衡,CPPI 战略还有其他局限性,这反过来会增加交易成本,这是必须考虑的因素。
与 Tableau 整合
Tableau 为 python 提供了一个名为 Tabpy 的分析扩展,这是一个有用的工具,可以将 Python 中的数据工程和算法任务与 Tableau 中的高级可视化功能集成在一起。在 Jupyter 中可以很容易地部署 python CPPI 算法,如下所示
client.deploy('run_cppi ',run_cppi,'运行 CPPIstrategy 的回溯测试,给定风险资产的一组回报',override = True)
在 Tableau 中,端点的返回值以计算字段的形式接收,如下所示:
SCRIPT _ STR(" Return tabpy . query(' run _ cppi ',_arg1,_arg2,_arg3,_arg4,_arg5)['response']",SUM([Weekly_Return]),cppi_m,cppi_start,cppi_floor,cppi_rfrate)
##def run_cppi(risky_r,m=3,start=1000,floor=0.8,riskfree_rate=0.03):
结论
尽管 Tableau 和 Python 在金融服务公司中被广泛使用,但是集成它们并利用它们各自优势的能力提供了“思维速度”的分析能力,这是仅使用其中一种工具所无法实现的。分析扩展为数据科学家提供了设计和实施解决方案的机会,这些解决方案对于为投资策略(如 CPPI)提供建议非常有用。尽管这个解决方案的实现并非没有技巧和变通方法,但我们将把它留到以后讨论。
信用
Coursera 和 EDHEC Business School 提供了 Python 和机器学*在投资管理专业课程中的知识
回归基础:常*机器学*模型的假设
暂时忘记深度学*和神经网络。
随着越来越多的人开始进入数据科学领域,我认为重要的是不要忘记这一切的基础。
统计。
如果你是分析领域的新手,没关系!我们都是从某处开始的!
但重要的是 意识到 我将在这篇文章中分享的机器学*模型假设的存在。
我很幸运在我的大学时代就已经研究了所有这些概念,所以我认为回到基础上写一些关于它们的东西会令人耳目一新。
关心就是分享。😃
我们开始吧!
线性回归又称普通最小二乘(OLS)回归
OLS 回归试图解释自变量(预测值)和因变量(目标值)之间是否存在关系。
它通过最小化残差的*方和来拟合你的数据。
残差是观察值和预测值之间的差值。残差用于指示模型与数据的拟合程度。
然而,为了能够信任和对结果有信心,在建模之前必须满足一些假设。
满足所有这些假设将允许您为您的模型创建可能的最佳估计。
OLS 回归模型中有 5 个关键假设。
假设 1:自变量和因变量之间存在线性关系。
当我第一次在统计课上听到这个假设时,我措手不及。
我记得当我回顾我的考试成绩时,我感到如此的被欺骗和被欺骗,这已经深深地刻在了我的记忆中。
精神食粮。
这些等式中的哪一个符合这个假设?
Y = β₀ + β₁X₁+ β₂X₂
Y = β₀ + β₁X₁+ β₂X₂²
原来两者都是线性的。
对于被认为是线性方程的东西,经常会有的曲解。
线性方程组=直线
非线性方程组=曲线
这是错误的。
当统计学家说一个方程是线性的时,他们指的是参数的线性,并且这个方程有一定的格式。
这是格式:
**Y = Constant + Parameter1 * Variable1 + Parameter2 * Variable2 …**
注意:
- 必须有一个常数
- 其他项遵循“参数变量*”的模式,所有项都加在一起。
变量 是否非线性(即*方)并不重要,只要 方程 遵循这种指定格式,就是线性方程。任何其他不遵循这种格式的方程都是非线性的。
这也意味着一些线性方程线在拟合时是弯曲的。
所以从技术上来说…单独使用散点图并不能真正告诉你你看到的拟合曲线是否是线性的。你可能需要看看曲线的方程式。
假设 2:没有多重共线性
多重共线性是指自变量之间的高度相关性。
多重共线性是一个问题,因为它会产生冗余信息,导致回归模型的结果不可靠。
为了避免这个问题,您可以部署两种技术:
- 对你所有的自变量进行相关性分析。
- 删除具有高方差通货膨胀系数的独立变量(VIF)*。作为一般的经验法则,a
VIF > 10
是多重共线性的强烈指示。
*VIF = 1 ÷ (1-R²)
假设 3:没有自相关
自相关是指残差不是相互独立的。即先前的观测残差导致当前观测残差的系统增加/减少。
因此,它会导致你低估你的方差,这将影响你的置信区间或假设检验的结果。
为了检查自相关性,您可以使用 Durbin-Watson 'D '测试。1.5 < d < 2.5
之间的任何值都满足这个假设。
否则,要修正自相关,您应该在计算标准差时应用“自相关-稳健标准差(HAC) ”公式来修正自相关。
注意:你可能会遇到“HAC”作为“纽维-韦斯特估值器”。
假设 4:残差应该是同方差的
同质性是指你的残差图应该在所有观察值上显示一个 甚至 和 随机模式 。
换句话说,残差的方差在所有观测中应该是一致的,不应该遵循某种形式的系统模式。
在下图中,第一个图显示了残差图中的系统模式。这也被称为异方差;推翻了这个假设。
下图显示了同方差残差图应该是什么样子。
2010 年 7 月 29 日,由 Protonk ( CC3.0 ) ( 来源)提供的同质性示例
那么异方差到底有什么问题呢?
- 你的无偏估计将不再是最好的。
- 它会影响标准误差的计算,而标准误差会无意中影响任何假设检验的结果。
要解决异方差的第一个问题,一个好方法是增加样本量。
对于第二个问题,你应该应用“稳健标准误差”公式来解释异方差对你的误差的影响。
注:“稳健标准误差”也称为“异方差一致性标准误差”(HC)。编程的时候可能会遇到“HC”。
假设 5:所有自变量都是正态分布的
就产生最佳无偏估计而言,这个假设是可选的。
但是,如果您想要执行假设检验以产生置信区间或预测区间,则需要使用它。
注:你可以在这里回顾一下两个的区别。
检查正常性有两种方法:
- 为每个独立变量创建直方图。
直方图示例,Gbdivers 于 2009 年 3 月 16 日( CC2.0 ) ( 来源)
2.在残差上运行 Q-Q 图。如果残差是正态的,所有的观测值都应该遵循一条直线。
QQ 图示例,2009 年 10 月 19 日,作者Skbkekas(cc 3.0)(来源)
如果你需要满足这个假设,但是你的变量不是正态分布的,你可以转换你的变量。
逻辑回归
逻辑回归假设与 OLS 回归的不同之处在于:
- 自变量和因变量之间不需要线性关系。
- 残差不需要是正态的。
- 不需要满足同伦假设
那么逻辑回归需要满足哪些假设呢?
以下是逻辑回归的 5 个关键假设。
假设 1:适当的因变量结构
这个假设简单地说明了二元逻辑回归要求因变量是二分的,而有序逻辑回归要求它是有序的。
此外,因变量既不能是区间,也不能是比例。
假设 2:结果的 logit 与各个自变量之间存在线性关系。
logit 函数由下式给出:
logit(p) = log(p/(1-p)), where p is the probability of an outcome
为了检验这一假设,您可以通过在散点图上绘制每个独立变量和 logit 值来直观地进行检验。
检验逻辑回归的线性假设
在上图中,Y 轴是独立变量,而 X 轴显示的是 logit 值。然后看曲线的方程,看是否满足线性假设。
请记住,线性存在于参数中。只要方程满足上述线性方程形式,就满足线性假设。
注意:我在 x 轴标签上犯了一个错误,应该是“Logit”而不是“Logit Probability”
假设 3:没有多重共线性
与 OLS 回归的假设一样,这里也可以这么说。
(详* OLS 回归部分。)
假设 4:没有有影响的异常值
有影响的异常值是影响逻辑回归模型质量的极端数据点。
并非所有的离群值都有影响力。
在移除或变换点以进行分析之前,您需要检查哪些点是有影响的点。
要检查异常值,可以对数据值运行 Cook 距离。高库克距离值表示异常值。
标记出有影响力的异常值的经验法则是Cook’s Distance > 1.
假设 5:观察独立性
这种假设要求逻辑回归观测值相互独立。
也就是说,观察结果不应来自重复测量设计。
重复测量设计是指在不同的实验条件下或跨时间对同一个人进行的同一变量的多次测量。
重复测量的一个很好的例子是纵向研究——跟踪一个主题多年的进展。
支持向量机(SVM)
SVM 没有需要验证的模型假设。
基于树的模型
对于基于树的模型,如决策树、随机森林、&、梯度推进,没有模型假设需要验证。
与 OLS 回归或逻辑回归不同,基于树的模型对异常值是稳健的,并且不需要因变量满足任何正态假设。
为什么基于树的模型对异常值具有鲁棒性?
点击这里查看来自 Quora 的详细解释。
结尾注释
嗯,就是这样!
我认为这里的关键要点是,你计划使用回归或任何广义线性模型(GLM) ,在建立你的模型之前,你必须验证一些模型假设。
对于 SVM 或基于树的模型,没有任何模型假设需要验证。
希望这篇帖子有所帮助!
下期帖子再*!
안녕히 계세요!
领英简介:谭震东
参考
- https://www.lexjansen.com/wuss/2018/130_Final_Paper_PDF.pdf
- https://www . statistics solutions . com/assumptions-of-logistic-regression/
- http://www . sth da . com/English/articles/36-class ification-methods-essentials/148-logistic-regression-assumptions-and-diagnostics-in-r/# logistic-regression-assumptions
- http://SPH web . bumc . bu . edu/otlt/MPH-Modules/BS/R/R5 _ Correlation-Regression/R5 _ Correlation-Regression 4 . html
- https://www . statistics solutions . com/assumptions-of-linear-regression/
- https://www . quora . com/Why-are-tree-based-models-robust to-outliers
回到学校,回归正常?
在疫情之后重新发明我们的教育系统
本·怀特在 Unsplash 上的照片
在过去的几个月里,世界各地的教育系统在全球疫情的威力下颤抖。孩子们和教育工作者一夜之间被从教室里带走。一些人在技术的帮助下很快适应了,而另一些人则拼命挣扎。但最重要的是,疫情令人大开眼界,认为一旦它过去,我们就会恢复正常的想法是错误的。
我们需要大胆地驾驭人工智能(AI)在教育中赋予我们的力量。人工智能可以帮助我们解决各个领域专业人员短缺的问题,并帮助我们的教育工作者利用他们有限的资源实现更多的目标。它还将通过确保我们的孩子从我们的教育系统中获得最大收益来优化我们的人力资本。最重要的是,这将鼓励每个孩子继续学*。我们不能失去任何人!
尽管多年来实施了多项教育计划来摆脱一刀切的方法,但我们仍需要为学生做更多的事情。每个孩子都是不同的,孩子不应该经历相同的教育经历。如果我们想让他们从教育系统中获得最大收益,我们就应该考虑他们独特的能力、技能和素质。混合能力班的引入,加上差异化的教学,是朝着正确方向迈出的一步,并带来了更个性化的方法,但代价是增加了教育者的工作量(他们已经超负荷工作)。
为了解决这些问题,我们需要一个教育人工智能系统的帮助,该系统可以自动个性化和优化儿童的学*:从学*困难的儿童到有天赋的儿童。
众所周知,有时候,老师们会很纠结,因为他们不得不处理不时出现的不同的班级动态。因此,给学生的教育质量可能会受到影响。教育人工智能系统将充当最佳实践的存储库,从而确保每个孩子的体验始终保持高水*。它将保证每个孩子都能得到最好的学*,自动定制并适应他或她的能力。这也确保了在不增加无用压力的情况下,期望他们完成的任务是可以实现的。该系统抓住了较弱的学生,帮助他们脱颖而出,同时也对有天赋的学生提出了挑战。此外,由于系统实时处理批改,教师将有更多的时间专注于其他任务;比如帮助那些有需要的学生,提升自己或者创造新的资源。
在许多学校,我们很幸运地部署了*板电脑。孩子们已经对这样的系统非常有信心,教育人工智能系统在*板电脑上运行,我们不需要投资其他资源,而是使用我们已经拥有的资源。
该系统还将在放学后(当没有老师的帮助时)为儿童提供上下文支持,从而帮助他们自己解决最具挑战性的问题。不时出现的一个争论是给孩子们布置多少家庭作业合适。是五分钟吗?三十分钟?两个小时?事实上,没有神奇的数字。但是教育人工智能系统可以通过给每个孩子适量的工作来解决这个问题,从而避免压倒性的工作量。
此外,根据学生提供的答案,布置的家庭作业是动态变化的。与标准化测试相比,这种自下而上、井然有序的学*环境将随着学生个人的表现和对内容的掌握而扩展,从而提供适应性更强、更顺畅、更愉快的教育体验。
另一方面,由于该系统是高度自治的,因此不会给教育者增加额外的负担。它将为他们配备适当的工具和统计数据,帮助他们监控整个班级,并使他们专注于那些需要他们帮助的学生。该系统还将提供实时反馈,教师和学生都可以据此采取行动,以改善未来的学*。它将预测学生未来的成绩,从而让教育者在为时已晚之前进行干预。本质上,教育人工智能系统可以帮助教师更有效地管理班级和支持所有学生。
在 Unsplash 上由 Oluwakemi Solaja 拍摄的照片
数百名学生已经通过他们的*板电脑尝试了这个系统。他们中的许多人超级兴奋,可能是因为它说着他们理解的相同的技术语言。他们中的大多数人恳求我们在试验后继续使用它。
最让我们吃惊的是我们获得的初步结果。在使用该系统一段时间后,与对照组(不使用该系统)相比,大多数学生表现出了改善。令人惊讶的是,较弱的学生从这种方法中受益最多。当然,这些结果不是结论性的,应该持保留态度,尽管我们计划进一步的纵向研究。
然而,它们非常令人鼓舞,并清楚地表明,教育的未来在人工智能。考虑到我们生活在一个唯一资源是人力资本的国家,我们相信教育人工智能系统将帮助我们的国家培养未来一代高技能专业人员,准备好面对今天的挑战,同时设计明天的世界。
如果你喜欢这篇文章,并想与我联系,请这样做🐦推特,🔗领英,📷 Instagram 或者😊脸书。
Alexiei Dingli 教授是马耳他大学人工智能教授。他一直在进行研究并在……
www.udemy.com](https://www.udemy.com/course/artificial-intelligence-in-the-classroom) [## 向孩子们解释人工智能
如何让我们的年轻一代为明天的挑战做好准备!
towardsdatascience.com](/explaining-ai-to-children-c9b2ecab1ffc) [## 使用人工智能提升我们的教育系统和劳动力
在任何国家,最重要的资源是人力资本。熟练的劳动力和运转良好的教育系统…
towardsdatascience.com](/boosting-our-educational-system-and-our-workforce-using-ai-a676afacb9cd)
阿列克谢·丁力教授 是马耳他大学的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他已经出版了几本同行评审的出版物,并成为马耳他的一员。由马耳他政府成立的人工智能特别工作组,旨在使马耳他成为世界上人工智能水*最高的国家之一。
回到数据分析的未来:Tukey 真空的整洁实现
约翰·图基的一篇里程碑式的论文“数据分析的未来”包含了一套很大程度上被忽视的分析技术,就好像它们藏在众目睽睽之下一样。
多种来源认为 Tukey 的论文是数据科学史上的一个开创性时刻。《福布斯》(《数据科学简史》)和《史丹福》(《数据科学 50 年》)都发表过以论文为起点的历史。斯普林格将其收录在他们的作品集 统计学的突破 。我自己也在微软关于数据科学的文章中引用过 Tukey 的话(“用 Azure 去理解 Azure ”)。
独立于论文,Tukey 对数据科学的影响是巨大的:他是《探索性数据分析》的作者。他开发了快速傅立叶变换(FFT)算法、箱线图和多种以他的名字命名的统计技术。他甚至创造了“比特”这个术语
但是直到我真正阅读了《数据分析的未来》之后,我才发现了 Tukey 被遗忘的技术。当然,我已经知道这篇论文很重要。但我也知道,如果我想理解为什么——理解图基思想的突破——我必须亲自阅读。
Tukey 没有让人失望。他以一个强有力的宣言开始:“很长一段时间以来,我一直认为自己是一名统计学家,对从特殊到普遍的推论感兴趣。但是当我看到数理统计的发展时,我有理由感到惊奇和怀疑”(第 2 页)。就像贝多芬第五交响曲的开头一样,这个声明是直接而大胆的。“总而言之,”他说,“我开始觉得我的主要兴趣在数据分析……”(第 2 页)。
尽管图基使用了第一人称,但他的开场陈述是而不是关于他自己。他将个人和职业兴趣放在一边,做出更大胆的断言,即统计学和数据分析是不同的学科。他承认这两者是相关的:“统计学为数据分析做出了很大贡献。在未来,它能够而且我认为应该做出更大的贡献”(第 2 页)。
此外,Tukey 认为统计学是纯粹的数学。并且,用他的话说,“……数学不是一门科学,因为其有效性的最终标准是一种公认的逻辑一致性和可证明性”(第 6 页)。然而,是一门科学,以其“依赖经验测试作为有效性的最终标准”(第 5 页)而著称。
没有克兰的消息
然而,在报纸上没走多远,我就被绊倒了。在(第 22 页)大约三分之一的地方,图基介绍了 FUNOP,一种自动解释情节的技术。我向前翻了一页,发现了一些方程式。我担心——在我能理解这些方程式之前——我可能需要对 FUNOP 有一个直观的理解。我向前翻页,发现了第二种技术,FUNOR-FUNOM。我很快意识到,这两种技术,加上我还没有意识到的第三种技术,占了论文的将近一半。
为了理解“数据分析的未来”,我肯定需要学*更多关于 FUNOP 和 FUNOR-FUNOM 的知识。不过,我很快就意识到了这一点,因为我很久以前就知道,数据科学充满了我还不知道的术语和技术,而且将永远如此。我会做我的研究,然后回到图基的论文。
但是我在网上搜 FUNOP 的时候,发现几乎什么都没有。更令人惊讶的是,克兰什么也没有。考虑到 CRAN 中数以千计的软件包和 Tukey 技术的广泛采用,我期望如此重要的论文中的技术会有多个实现。反而什么都没有。(直到现在…)
FUNOP
幸运的是,Tukey 详细描述了 FUNOP 和 FUNOR-FUNOM 的工作原理。幸运的是,他提供了它们如何工作的例子。不幸的是,他只提供了这些过程及其对示例数据的影响的书面描述。因此,为了理解这些过程,我在 r 中实现了它们。)为了进一步阐明他们做了什么,我生成了一系列图表,以便更容易地可视化正在发生的事情。
以下是 Tukey 对 FUNOP(全正常情节)的定义:
- (b1)设 aᵢ₍ₙ₎ 为来自单位正态分布的 n 样本中第 i 次有序观察的典型值。
- (b2)设y₁≤y₂≤…t5≤yₙ为待检查的有序值。设 y̍ 为他们的中值(或者设 ӯ ,读作“ y 修剪”,为 yᵢ 与⅓nI≤⅓(2n的*均值)。
- (b3)仅对于 i ≤ ⅓ n 或> ⅓(2 n ),让zᵢ=(yᵢ-y̍)/aᵢ₍ₙ₎(或让
zᵢ=(yᵢ-か/) - (b4)设 z̍ 为这样得到的 z 的中间值(关于⅓(2 n 的个数)。
- (b5)特别注意zs 其中既|yᵢ-y̍|≥a**z̍和zᵢ≥b**z̍其中 A 和b
- (b5)特别是对于小 n , zⱼ 与 j 比一个 i 更极端,其中(b5)选择 zᵢ 也值得特别关注……(p23)。*
基本思想非常类似于 Q-Q 图。
Tukey 给了我们一个 14 个数据点的例子。在正常的 Q-Q 图上,如果数据呈正态分布,它们会形成一条直线。但是在下面的图表中,根据示例数据,我们可以清楚地看到一些点距离直线相对较远。他们是局外人。
FUNOP 的目标是通过自动化解释来消除目视检查的需要。
FUNOP 过程中的第一个变量( aᵢ₍ₙ₎ )简单地给出了理论分布,其中 i 是范围 1 中的序数值.. n 和 Gau⁻是正态分布的分位数函数(即 Q-Q 图中的“q”):
FUNOP 的关键创新是计算每个点相对于中位数的斜率。
如果 y̍ 是样本的中间值,我们假设它位于分布的中点(其中 a ( y ) = 0),那么每个点的斜率可以计算为:
上图说明了一个点(1.2,454)相对于中值(0,33.5)的斜率是如何计算的。
任何一个点的斜率比其他点的斜率要陡得多,则该点必然离直线更远。为此,FUNOP 简单地将每个斜率( zᵢ )与所有计算的斜率( z̍ )的中间值进行比较。
但是,请注意,FUNOP 只计算排序后人口的顶部和底部三分之一的斜率,部分原因是因为 zᵢ 在人口的内部三分之一不会有太大变化,还因为内部三分之一的 aᵢ₍ₙ₎ 的值将接近 0,并且在计算 zᵢ 时除以≈0 可能会导致不稳定。
重要性 Tukey 称之为“特别注意”——部分由两个预定值(或超参数)之一 B 决定。对于他的例子,Tukey 推荐一个介于 1.5 和 2.0 之间的值,这意味着 FUNOP 简单地检查任意点相对于中点的斜率是否比中值大 1.5 或 2.0 倍。
另一个预定值是 A ,它大致等于 yᵢ 与 y̍ 的标准偏差数,并作为显著性的第二个标准。
下图显示了 FUNOP 的工作原理。
我们的原始值沿着 x 轴绘制。绿色的点构成了我们样本的内三分之一,我们用它们来计算 y̍ ,这些点的中间值,用绿色垂直线表示。
绿色的点而非构成了我们样本的外三分之一(即顶部和底部三分之一),我们用它们来计算 z̍ ,即这些点的中值斜率,用黑色水*线表示。**
我们的第一选择标准是zᵢ≥bt30】z̍。在他的例子中,Tukey 设置 B = 1.5,所以我们的兴趣阈值是 1.5 z̍ ,用蓝色水*线表示。我们会认为这条线以上的任何一点(蓝色阴影区域)都值得“特别关注”。我们只有一个这样的点,红色的。
我们的第二个标准是|yᵢ-y̍|≥az̍。在他的例子中,Tukey 设置了 A = 0,所以我们的兴趣阈值是| yᵢ - y̍ | ≥ 0 或者(更简单一点)yᵢ≦y̍。基本上,绿线上的任何一点不是。蓝色阴影区域中的一点不在绿线上,所以我们还有一点。
我们最后的标准是任何比迄今为止选择的任何一个 i 更极端的 zⱼ 。基本上,这是任何比已经确定的值更极端的值。在这种情况下,我们有一个比我们的红点大的值(在x-轴的更右边)。那个点是橙色的,我们把它添加到我们的列表中。
FUNOP 确定的两个点与我们在图表 1 中直观确定的点相同。
技术
FUNOP 代表了论文中的一个转折点。
在第一部分中,Tukey 从更加哲学的角度探索了各种主题:判断在数据分析中的作用,教学分析中的问题,实践该学科的重要性,面对不确定性,等等。
在第二部分,土耳其将他的注意力转向“参差不齐的数据”及其挑战。小节变得越来越专业,许多方程式中的第一个出现了。就在他介绍 FUNOP 之前,Tukey 探索了“自动化考试”,在那里他讨论了技术的作用。
尽管图基在近 60 年前就写了他的论文,但他预计技术将继续发挥双重作用:它将使分析民主化,使普通用户更容易获得分析,但它也将推动该领域的进步:
“(1)大多数数据分析将由非高级数据分析师完成。对于拥有计算机的人来说,完全自动化的工具是最容易使用的。
“(2)……[成熟的数据分析师]必须有时间和动力去尝试新的分析程序;因此已知的程序必须尽可能让他们容易申请。再次要求自动化。
"(3)如果我们要研究和比较程序,如果程序已经被充分规定,那就容易得多,因为在使程序常规化和自动化的过程中必然会发生这种情况"(第 22 页)。
“自动化考试”和“FUNOP”的并列让我想知道 Tukey 在他的论文中包含该技术的原因。他开发 FUNOP 仅仅是为了证明他关于技术的观点吗?它有效地识别异常值,但是它足够复杂,可以从自动化中受益。
如果您对代码不感兴趣,请随意跳过:
FUNOR-FUNOM
识别异常值的一个常*原因是对它们做些什么,通常是通过修剪或 Winsorizing 数据集。前者只是从排序数据集的上端和下端删除相同数量的值。Winsorizing 类似,但不删除值。相反,它用最接近的原始值而不是受过程影响的来代替它们。
Tukey 的 FUNOR-FUNOM(完全正常拒绝-完全正常修改)提供了一种替代方法。该过程的名字反映了它的目的:FUNOR-FUNOM 使用 FUNOP 来识别异常值,然后使用单独的拒绝和修改过程来处理它们。
这项技术提供了许多创新。首先,与影响排序数据集顶端和底端所有值的修剪和 Winsorizing 不同,FUNOR-FUNOM 使用 FUNOP 来识别要处理的个别异常值。第二,FUNOR-FUNOM 利用数据集的统计属性来确定那些离群值的个体修改。
FUNOR-FUNOM 是专门为在双向(或应急)表上操作而设计的。类似于在列联表上操作的其他技术,它使用表的大*均值( x..)和行列的意思( xⱼ.)和 x.ₖ ,分别计算表格中条目的期望值。
下面的等式显示了这些效应是如何组合的。因为期望值不太可能与表中的实际值完全匹配,所以该等式包含一个残差项( yⱼₖ )来解释任何偏差。
FUNOR-FUNOM 主要感兴趣的是偏离期望值最大的值,即具有最大残差的值。因此,要计算残差,只需将上面的等式互换一下:
FUNOR-FUNOM 从重复应用 FUNOP 开始,寻找异常残差。当找到它们时,它通过应用以下修改来修改具有最大偏差的异常值:
在哪里
回忆斜率的定义(来自 FUNOP)
δxⱼₖ方程的第一部分简化为仅仅是 yⱼₖ - y̍ ,残差与中值的差。等式的第二部分是一个因子,仅基于表的大小,意在补偿异常值对表的总计、行和列*均值的影响。
当δxⱼₖ应用于原始值时, yⱼₖ 项相互抵消,有效地将异常值设置为其期望值(基于列联表的综合影响)加上中值残差的一个因子(~ xⱼ.) + x.ₖ + x.. + y̍ )。
FUNOR-FUNOM 重复同样的过程,直到它不再找到“值得特别关注”的值。
在最后一个阶段,FUNOM 阶段,该程序使用较低的感兴趣阈值(FUNOP 具有较低的 A )来识别最终的异常值组进行治疗。调整变成了
这里有一些变化。首先,包含(–bₘz̍)有效地将异常值的残差设置为 FUNOP 的感兴趣阈值,很像 Winsorizing 将受影响的值设置为相同的截止阈值的方式。不过,FUNOM 只将受影响值的剩余值 T33 设置为该阈值:该值的大部分是由 grand、row 和 column *均值的综合影响决定的。
其次,因为我们已经处理了最大的异常值(其调整会对表的*均值产生更大的影响),所以我们不再需要补偿因子。
下图显示了将 FUNOR-FUNOM 应用于 Tukey 论文表 2 中的数据的结果。
黑点代表受程序影响的原始值。它们的处理值的颜色取决于它们是否由程序的功能或功能部分确定。灰点代表不受程序影响的值。
FUNOR 处理最大的调整,Tukey 通过设置 Aᵣ = 10 和 Bᵣ = 1.5 来完成这部分过程,FUNOM 通过设置 Aₘ = 0 和 Bₘ = 1.5 来处理更精细的调整。
同样,由于该过程利用了数据的统计特性,因此每个调整结果都是唯一的。
代码如下:
“不使用它是愚蠢的!”
在描述了 FUNOR-FUNOM 之后,Tukey 断言它服务于一个真正的需求——一个以前没有解决的需求——他邀请人们开始使用它,探索它的特性,甚至开发竞争对手。与此同时,他说,人们会“……不使用它是愚蠢的”(第 32 页)。
在他的论文中,Tukey 使用斜体来强调重点。在这里,他重复了早先关于反对采用新技术的论点。他让同事们建议,在给出新技术的功能之前,不要发表新技术,更不要说使用新技术了。图基意识到了讽刺,因为许多应用统计学依赖于学生的测试。他在论文中指出:
“当然,建议的知识量也不足以让任何人保证
"(c1)当该程序应用于实际数据时,出错的可能性正好相当于显著性或置信度的名义水*,或
“(c2)当应用于真实数据时,该程序在任何特定意义上都是最优的。
“但是我们从来没有能够对学生的“t”(第 20 页)做出这两种说法。
这是 Tukey 唯一一句全大写的句子。显然,他想抓住要点。
而且,很明显,FUNOR-FUNOM 并不是作为理论上可能的技术的例子。Tukey 打算用它。
真空吸尘器
FUNOR-FUNOM 通过识别和最小化过大的残差来处理列联表的异常值,这是基于大、行和列的*均值。
Tukey 在他的真空吸尘器中进一步发展了这些概念,其输出是一组残差,可用于更好地了解数据中的差异来源,并进行更明智的分析。
为了分离残差,Tukey 的真空吸尘器使用回归将列联表中的值分解为其组成成分(第 51 页):
这个想法与基于宏大、行和列的方法非常相似。事实上,真空吸尘器的第一级产生的结果与从原始值中减去*均值的组合效果相同。
要做到这一点,真空吸尘器需要根据我们表中的值( yᵣₖ )以及行( aᵣ )和列( bₖ )的载体(或回归量)来计算每一行和每一列的回归系数。[很抱歉对列使用“k ”,但 Medium 有其局限性。]
下面是用于计算列的回归系数的公式。
方便的是,当我们设置
aᵣ ≡ 1:
其中 nᵣ 是行数。实际上,该方程遍历每一行(σᵣ),对同一列中的单个值求和( c )并除以行数,与计算*均值( y.ₖ )相同。
然而,请注意, aᵣ 是一个向量。所以要设置 aᵣ ≡ 1,我们需要我们的向量来满足这个等式:
对于长度为 nᵣ 的向量,我们可以简单地赋予每个成员相同的值:
我们最初的回归变量是两组向量,一组用于行,一组用于列,包含行的√(1/ nₖ )或列的√(1/ nᵣ )。
最后,与所有行*均值或所有列*均值的*均值可用于计算总体*均值的方式相同,行系数或列系数可用于计算双重回归(或“总体”)系数:
计算所有这些系数的原因,而不是简单地从我们的表的原始值中减去总计、行和列的*均值,是因为 Tukey 的真空吸尘器在下一个过程中重用了这个阶段的系数作为回归量。(为了确保下一阶段的 aᵣ ≡ 1 和 aₖ ≡ 1,我们对两组新回归变量进行归一化处理。)**
第二阶段是真正的创新。它采用了 Tukey 的早期思想,一个非可加性的自由度,并将其分别应用于每一行和每一列。Tukey 告诉我们,“……提取‘列*均值减去大*均值’的逐行回归和‘行*均值减去大*均值’的逐列回归”(第 53 页)。
结果是一组残留,真空清除系统的影响。
以下是整个过程的代码:
外卖食品
当我开始这个练*时,我真的以为这是一次考古努力:我以为我会挖掘一件 1962 年的文物。相反,我发现了一些令人惊讶的创新技术。
然而,这三种程序都没有以其原始形式保存下来。甚至图基在 15 年后出版的《探索性数据分析》中也没有提到它们。也就是说,这本书关于双向桌子的章节包含了 FUNOR_FUNOM 和吸尘器的明显继承者。
也许它们已经淡出使用的一个原因是基础过程 FUNOP 需要定义两个参数, A 和 B 。图基自己承认“选择 Bₐ将是一个判断的问题”(第 47 页)。当我尝试在其他数据集上应用 FUNOR_FUNOM 时,很明显使用该技术需要调优。
另一种可能性是,这些程序有一个盲点,这篇论文本身就证明了这一点。Tukey 的目标之一是避免“……将错误的符号归因于产生的相关或回归系数的严重错误”(第 58 页)。因此,具有讽刺意味的是,图基的系数示例表(表 8,第 54 页)中有一个值的符号相反。
我测试了 Tukey 的每一个程序,没有一个程序能发现错别字:误差(-0.100)和修正值(0.100)都太接近相关的中间值和*均值,所以不容易被注意到。我发现它只是因为打印的行和列的意思与我计算的不一致。
这个缺陷不是致命的。最终,这些程序的效用是无关紧要的。我写这篇文章的真正目的只是鼓励人们阅读 Tukey 的论文,并通过提供我自己想要的直观解释来使这项任务变得简单一些。
明确地说,任何人都不应该把我的解释和我对 Tukey 技术的实现误解为阅读他的论文的替代品。“数据分析的未来”包含了比我在这里讲述的更多的内容,Tukey 的许多观点今天仍然是新鲜的,也是相关的,包括他的著名格言:“对经常模糊的正确问题的近似答案,远比对错误问题的精确答案好得多”(第 14-15 页)。
回到金字塔
数据分析师/科学家对数据工程的思考。
建造金字塔的第一步是选择一个合适的地点——西蒙·伯杰在 Unsplash 上的照片
前言
耗尽权力的他意识到他有多不能没有权力。
电工建造系统所基于的金字塔的基石。这个电力基础已经变得如此普遍,以至于它不再是一个竞争优势;就像它第一次出现时一样。由于这个原因,今天每个人都认为电是理所当然的。在这种程度上,可以说没有人质疑它是如何工作的,或者它从何而来。然而,有史以来所有最伟大的建筑师都是通过学*电气服务开始他们的教育的。
数据爱好者喜欢从事各种与数据相关的活动。如今,网上有无限量的免费资料,学*变得前所未有的容易和容易。然而,尽管尝试所有这些狂热的新技术可能很诱人,但踩下刹车、温*基础知识无疑是无害的。事实上,虽然时间会证明所有当前流行的数据科学包是否会持续下去,但可以肯定的是,从 20 世纪 70 年代开始流行的 ETL 作业(提取、转换和加载)将在 50 年后仍然存在——根据林迪效应理论。这就是为什么我决定建立使数据金字塔项目长期存在的基础。
让有数据
这一切都是从我的一个朋友开始的,他希望运用他新学到的财务分析技能,来评估一家公司是否得到了公*的评估。为此,他需要综合运用众所周知的指标和一些工程指标。为了收集他的数据,人们浏览了金融媒体和新闻渠道,寻找有助于公司发展的历史数据。
这些数据集可以免费(合法)下载,任何人都可以很容易地阅读 Excel 文件。尽管这些网站大多数都是可靠的,但它们不提供进行大规模下载的可能性。API 本质上提供实时市场数据(相对于公开填写的财务报表)。
结果,我的朋友一个接一个地手工整理这些公司的文件。对这些 excel 文件应用一些常规程序,在最终分析之前一起计算出度量标准。
换句话说,所采用的方法是乏味的(至少可以说是无聊的)和耗时的(至少可以这么说)。
因此有了这个问题:
如何自动化这一过程并设计可扩展的解决方案?
提取、转换和加载
“在计算、提取、转换、加载 ( ETL )是将数据从一个或多个源复制到目标系统的一般过程,目标系统以不同于源的方式表示数据[…]。ETL 过程在 20 世纪 70 年代成为一个流行的概念,并且经常用于数据仓库。— 维基百科
最简单的解决方案是构建一个 ETL 管道。该程序将从源网站抓取数据,处理数据,并将它们加载到关系数据库中。我不打算详述如何做,因为已经有无数的资源在讨论这个问题。相反,我将分享一些我在处理不同的阻碍时的想法,这些阻碍使你离最终目标更远。除此之外,我将包括我从该过程中获得的跨学科知识。
使用的 Python 库和服务:
基本 ETL 流程的表示
当心黑天鹅
“黑天鹅是一种不可预测的事件,超出了正常情况下的预期,可能会产生严重的后果。黑天鹅事件的特点是极其罕*,影响严重,而且人们普遍坚持认为事后才明白。— 纳西姆·尼古拉斯·塔勒布
简单地说,黑天鹅被视为不太可能发生的事情。从统计学上来说,不太可能发生的是发生概率低的事情。所以,某个时刻最终会发生的事情!因此,问题并不是预测什么或者什么时候会发生,而是如何为此做好准备?
在我们的例子中,黑天鹅是指会阻止程序正确执行任务的东西,因此可能会损害进程。因此,我们的想法是识别并列出最终的威胁,并使第一个支柱稳固。在商业战略中,这种方法也被称为事后分析。接下来的两点假设你对你处理的数据有信心,并且知道如何处理坏的/丢失的数据。
A .关于数据源的重要性
Jonathan Zittrain 在推特上的照片
数据源将为项目提供燃料;因此,使用最可靠的方法至关重要。除了确保它是否是合法来源,最基本的健康检查将是确保您处理的是原始数据源(而不是第三方从其他地方获取的数据)。
还有,你肯定不想破坏目标网站。这就是为什么您应该避免同时发送太多 GET 请求的原因。或者,你可以设置一个睡眠功能来延迟你的请求。有人可能会说使用代理会更快,但是你猜怎么着:代理不安全。你不仅会暴露自己的数据被盗和被非法使用,而且,大多数免费代理会修改目标 HTML 以插入恶意广告或其他一些废话。
b .理论上,一切正常
正常的做法是连续运行代码,看看它是否工作。一旦你的产品发布了,你就永远无法避免以后会出现的事情。万一发生什么事情,您需要尽快识别和理解错误并修复它。为了确保这个过程是快速的,请确保您的代码足够自我解释。谁也不知道下一个需要你阅读的人是谁。
当您持续测试您的程序时,您会理解您的程序如何对外部事物(源代码、包依赖、SQL 客户端等等)做出反应,并对未来可能发生的灾难保持警惕。尝试/除功能对它有很大的帮助。除了让程序运行之外,它还可以列出并记录现有的错误。
下面是 Try/Except 的一个片段,它返回关于就绪错误的信息
剥猫皮有许多方法
有趣的是,我们都知道一个事实,关于堆栈溢出的问题总是由一个伟大的社区来回答。如此多的答案,以至于对于每一个问题,都有许多有效的可能性。
没有真理。尽管有无数种方法可以算出 2,但什么会让 1+1 比 2 x1 更合理呢?越不复杂越好。最升级的答案提出最有效的代码来优化处理能力。然而,解决你的问题的另外 10 个答案当然也有效。所有这些贴出的答案展示了初学者和专家之间的巨大差异。这是新手不应该回避破解的原因。质量代码将伴随多年的实践而来。
所以因为没有冒名顶替者,你的主要目标应该是让它工作,然后你会改进它。首先,你交付,然后你迭代。不要让完美成为生产力的敌人。
即使在高级数据科学级别,这种能力也是一项很强的技能。事实上,许多数据科学家抵制了为他们的 ML 模型获取更多精确点的渴望,而不是现在部署它,以后再迭代。
也就是说,人们应该一路学*并尊重 python 的约定、风格指南和指导原则。
自动化枯燥的东西
一切都可以(或者应该)自动化。时间是最昂贵的资源。考虑到这一点,我很容易想象出一种符合“如果不能自动化,就不要做/外包”的企业价值观。
正是带着这个目的,VBA 复活了。尽管如此,事实证明这对大多数 excel 用户来说很难。从这个意义上说,我只能鼓励人们学*一些编程的基础知识,尤其是在科技公司。除了教育员工一个好的流程应该是什么样子,这将节省分析师做同样的日常工作的时间。
不要把鸡蛋都放在一个篮子里
我们已经看到了易变性是如何危及项目的。有趣的是,观察到在更高的水*上,这也是真的。无论你是项目经理还是企业领导,你都应该考虑运营是否无懈可击,这样才能有几个投资回报流。例如,新冠肺炎证明了大多数商业计划是多么脆弱,而几乎每家公司都有能力利用其数据来获得一些收入。
同理心很重要
昨天我读了一篇文章,解释了像其他领域一样,数据管理走向全栈配置文件。一言以蔽之,数据科学家应该更像数据工程师,数据工程师应该更像数据科学家。所以,因为两个领域重叠,这意味着两个功能是同一个硬币的两面。因此,这两种技能的完美组合需要对它们以及这个角色需要什么有一个坚实的理解。
欣赏你的队友的工作会带来更好的同理心。
西蒙·西内克在他的书《领导者最后吃》中强调了同理心是如何通过化合物在同事关系中发挥作用的,以及这些化合物是如何增强协作的。基本上,我们大脑中的化学物质(多巴胺、内啡肽、催产素、血清素)有许多方法发挥作用。成就感和爱是这些分子的两个主要触发因素。当人们喜欢一起工作时,他们自然会愿意付出更多的努力,并停留更长的时间来互相帮助。这通常突出了那些齐心协力并获得最佳结果的团队。
除了扩大人们的视野之外,将同事放在彼此的位置上只会提高同理心和团队合作。同理心是关系金字塔的基础,团队合作是巨大成功的基础。
吉萨的大金字塔充满了有待发现的财富
知识矩阵。一个好的项目有助于解决已知的未知问题;一个伟大的项目揭示未知-未知。
原本应该是一个基本的练*,最终变成了一个*稳的旅程,并帮助我发现了一堆未知的未知。它也揭示了许多现实生活中的问题,这些问题甚至在一开始都没有被怀疑。
ETL 活动从未被证明是有用的,因此总是值得一次又一次地引用。另一方面,新的数据技术每天都在涌现,并将数据科学提升到另一个水*。坚实的数据管道是任何使用开源软件库的项目成功背后的重复分母。基础工程不仅经得起时间的考验,而且由于更复杂和非结构化数据的增加而不断发展。
"好书不会一下子泄露所有的秘密。"—斯蒂芬·金
参考
[1] Sangeet Moy Das,像我这样的傻瓜的数据工程 101(2019),towardsdatascience.com
[2]塔奈·杰普瑞亚,《林迪效应和赌永远不变的东西》 (2018),medium.com
[3]【wikipedia.com】提取、转换、加载(最后编辑于 2020 年 5 月 14 日,)
[4]纳西姆·尼古拉斯·塔勒布,黑天鹅 (2007)
[5] 预验和后验(2018)redbooth.com
[6]towardsdatascience.com,伯颜·安杰洛夫,在机器学*中处理缺失数据
[7] 代理服务不安全。尝试这些替代品 (2015),Wired.com
[8] 蟒试除,w3schools.com
[9]爱丽丝·博耶斯,《哈佛商业评论》,不要让完美成为生产力的敌人
[10]阿尔·斯威加特,用 Python 自动化枯燥的东西 (2015)
[11]西蒙·西内克,领导者吃最后的 (2014)
[12]杰西·安德森数据工程师与数据科学家 (2018),奥赖利
回到一切开始的地方
我将如何重新开始学*机器学*(3 年后)
由丹尼尔·伯克 — 10 分钟阅读
我在地下,回到一切开始的地方。坐在我第一次遇*迈克的隐蔽咖啡馆里。在过去的 9 个月里,我一直在我的卧室里学*,并决定走出洞穴。我一半担心早餐要付 19 美元(除非是圣诞节,周末开车去优步不是很赚钱),另一半担心我在网上做的这项研究是否有意义。
Hannah Wright 在 Unsplash 上拍摄的照片
自然语言处理中的标记化算法概述
本文是对标记化算法的概述,从词级、字符级和子词级标记化,重点是 BPE、单字 LM、词块和句子块。这意味着专家和初学者都可以阅读。如果有任何概念或解释不清楚,请与我联系,我很乐意澄清任何需要。
pixabay.com/杰拉尔特
是什么让数据分析师变得优秀?
凯西·科济尔科夫(Cassie Kozyrkov)—6 分钟阅读
在剖析卓越分析的本质之前,让我们先快速总结一下第 1 部分中关于分析的三个常*误解:
- 分析就是统计。(编号)
- 分析是数据新闻/营销/讲故事。(编号)
- 分析就是决策。(不!)
数据清理终于实现自动化
杰瑞米·哈里斯(Jeremie Harris)——听 40 分钟🎧
说数据清理占数据科学家工作的 80%是老生常谈,但这在方向上是正确的。
这太糟糕了,因为像数据探索、可视化和建模这样有趣的事情是大多数人进入数据科学的原因。因此,行业内正在大力推动尽可能自动化数据清理,这是一件好事。
我们的每日精选将于周一回归!如果你想在周五收到我们的 每周文摘 ,很简单!跟随 我们的出版物 ,然后进入你的设置,打开“接收信件”您可以在此 了解有关如何充分利用数据科学 的更多信息。
旧足迹的背景估计
有时候没有人看镜头也一样好看!
巴黎圣母院。来自盖伊·琼斯通过 T2 的 youtube 上传的视频
这种拍摄于上个世纪的镜头并不少*,镜头是静止的,记录着人们的日常生活,给我们展示了这个时代生活的美丽景象,一个永远存在的景象!。
由于相机是静止的,它为我们提供了包含两个元素的帧;静止的背景(例如建筑物)和移动的物体。这个特性使得它非常适合于背景估计算法。
在本文的其余部分,我将探索这个用例,旨在看看如果场景是空的,没有任何存在,这些镜头会是什么样子。
幸运的是,有简单而直观的方法来执行这项任务,只需使用 意味着 和 中值 的力量就足以交付足够好的结果。
请注意,为了便于说明,本文中的所有例子都是从这个伟大的频道盖伊·琼斯的这个镜头中摘录的。
比方说,如果我们从某些片段中随机选取三帧。
三个随机帧。
你可以看到在所有的里面,持久的是背景,移动的是人和马车(或者更抽象一点,物)。因此,通过计算所有帧的*均值来估计背景听起来是合理的。
三个随机帧*均值。
如您所*,这种均值变换的幸存者是具有相似值的像素。此外,应用中间值也有类似的效果:
三个随机帧的中间值。
均值方法具有在图像上产生鬼影状伪像的趋势,另一方面,中值更加修剪,以在像素之间提供非*滑过渡。
*均值和中间值对左下方男人的影响。
中位数通常比*均值更受欢迎,主要是因为它对异常值更稳健,这可以通过观察左下方的人来看出。对于矩形内的像素(上图),这个人是一个离群值,因为他只出现在一帧中,所以他无法通过中值方法生存。而在中庸的方法中,尽管他相对来说是一个局外人,但他将一直存在(但强度不大)。
正如您可能已经猜到的,从几帧移动到整个视频更有可能产生更好的结果,因为随着时间的推移,假设非背景对象将持续移动,每个像素成为背景像素的机会将更高。
以下是将同样的方法应用于一些不到一分钟的场景后的一些结果。在顶部,您可以看到原始场景,在左侧,您可以看到它的运行*均值(到当前帧为止的所有帧的*均值),在右侧,您可以看到它的运行中值(到当前帧为止的所有帧的中值)。
上面这一个突出了使用中间值的主要缺陷,因为在如此短的视频中,马车在场景中一致地在同一位置移动,这给了它们被预测为背景的高机会。然而,在这种情况下,*均似乎更好。
这是迄今为止对均值和中值最具挑战性的一个,因为有人会说有些区域的实际背景根本没有出现在场景中。如果你仔细看,你几乎看不到楼梯的前几级。
方法
中位数
我希望这能让你对背景估计的潜在应用有所了解,如果你想进一步了解这个主题,我建议从这些幻灯片开始。
背景抠图:世界是你的绿屏
使用深度学*和 GANs 在您自己的家中实现专业质量的背景替换
你希望没有完整的工作室也能制作专业质量的视频吗?或者 Zoom 的虚拟背景功能在视频会议中表现更好?
我们最近在 CVPR 2020 上发表的论文【1】提供了一种新的简单的方法来为各种各样的应用替换你的背景。你可以在家里的日常环境中,用一个固定的或手持的相机来做这件事。我们的方法也是最先进的,其输出可与专业结果相媲美。在本文中,我们将介绍我们方法的动机、技术细节和使用技巧。
什么是抠图?
抠图是将图像分为前景和背景的过程,以便您可以将前景合成到新的背景上。这是绿屏效果背后的关键技术,它被广泛用于视频制作、图形和消费应用程序。为了模拟这个问题,我们将捕获图像中的每个像素表示为前景和背景的组合:
抠图方程式
我们的问题是给定一幅捕获的图像(C ),求解每个像素的前景(F)、背景(B)和透明度(alpha)。显然,这是高度不确定的,并且由于图像具有 RGB 通道,这需要从 3 个观察值中求解 7 个未知数。
分割的问题是
一种可能的方法是使用分割来分离前景以便合成。尽管分割在最近几年取得了巨大的进步,但它并没有解决全部的抠图问题。分割为每个像素分配一个二进制(0,1)标签,以表示前景和背景,而不是求解连续的 alpha 值。这种简化的效果在以下示例中显而易*:
这个例子说明了为什么分段不能解决合成问题。使用 DeepLab v3+ [2]进行分割。
边缘周围的区域,尤其是头发中的区域,具有介于 0 和 1 之间的真实 alpha 值。因此,分割的二进制性质在前景周围产生了粗糙的边界,留下了可*的伪像。解决部分透明度和前景色允许在第二帧更好的合成。
使用随意捕捉的背景
因为抠图是一个比分割更难的问题,所以经常使用附加信息来解决这个无约束的问题,即使在使用深度学*时也是如此。
许多现有的方法[3][4][5]使用三分图,或已知前景、背景和未知区域的手绘地图。虽然这对于图像是可能的,但是注释视频是非常耗时的,并且对于这个问题来说不是一个可行的研究方向。
我们选择使用捕获的背景作为真实背景的估计。这使得它更容易解决前景和阿尔法值。我们称之为“随意捕捉”的背景,因为它可以包含轻微的运动、颜色差异、轻微的阴影或与前景相似的颜色。
我们的抓捕过程。当对象离开场景时,我们捕捉他们背后的背景以帮助算法。
上图显示了我们如何轻松地提供真实背景的粗略估计。当这个人离开场景时,我们捕捉他们背后的背景。下图显示了这种情况:
捕获的输入、捕获的背景和在新背景上合成的示例。
注意这张图片是多么具有挑战性,因为它有非常相似的背景和前景色(特别是在头发周围)。它也是用手持电话录制的,包含轻微的背景运动。
我们称之为随意捕捉的背景,因为它可以包含轻微的运动、颜色差异、轻微的阴影或与前景相似的颜色
捕捉提示
尽管我们的方法在一些背景扰动下也能工作,但是当背景恒定时,它仍然是更好的,并且在室内环境中是最好的。例如,在存在由对象投射的非常明显的阴影、移动的背景(例如,水、汽车、树)或大的曝光变化的情况下,它不起作用。
失败案例。这个人是在一个移动的喷泉前拍摄的。
我们还建议在视频结束时,通过让这个人离开场景来捕捉背景,并从连续的视频中提取该帧。当您从视频模式切换到照片模式时,许多手机都有不同的变焦和曝光设置。用手机拍摄时还应该启用自动曝光锁定。
理想的捕捉场景。背景在室内,不动,主体不投阴影
捕获提示的摘要:
- 选择你能找到的最稳定的背景。
- 不要站得离背景太近,这样你就不会投下阴影。
- 在手机上启用自动曝光和自动对焦锁定。
这种方法像不像背景减法?
另一个自然的问题是,这是否像背景减法。首先,如果很容易使用任何背景进行合成,电影业就不会这么多年来花费数千美元在绿色屏幕上。
背景减法对于随意捕捉的背景效果不佳
此外,背景减法不解决部分 alpha 值,给出与分割相同的硬边缘。当有相似的前景和背景颜色或背景中有任何运动时,它也不能很好地工作。
网络详细信息
该网络由监督步骤和非监督细化步骤组成。我们将在这里简要地总结一下,但是要了解全部的细节,你可以随时查阅这篇文章。
监督学*
为了首先训练网络,我们使用 Adobe Composition-1k 数据集,该数据集包含 450 个仔细注释的地面真相 alpha mattes。我们以完全监督的方式训练网络,输出上有每像素的损失。
我们网络中受监管的部分。我们使用几个输入线索,然后输出一个阿尔法遮罩和预测的前景色。我们在 Adobe 1k 数据集上进行训练,并提供地面实况结果。
注意,我们有几个输入,包括图像、背景、软分割和时间运动信息。我们新颖的上下文切换模块也确保了对不良输入的鲁棒性。
使用 GANs 的无监督细化
监督学*的问题是 adobe 数据集只包含 450 个地面真实输出,这远远不足以训练一个好的网络。获取更多的数据是极其困难的,因为它涉及到手工注释图像的 alpha 遮片。
为了解决这个问题,我们使用 GAN 细化步骤。我们从受监督的网络中获取输出阿尔法遮罩,并将其合成在新的背景上。然后鉴别器试图辨别这是真的还是假的图像。作为响应,发生器学*更新 alpha 遮罩,以使合成结果尽可能真实,从而欺骗鉴别器。
我们的无监督 GAN 细化步骤。我们把前景放到一个新的背景上,然后阿甘试着分辨它是真是假。
这里重要的一点是,我们不需要任何带标签的训练数据。该鉴别器用数千幅很容易获得的真实图像进行训练。
根据您的数据训练 GAN
GAN 的另一个用处是,您可以根据自己的映像训练生成器,以提高测试时的结果。假设你跑网络,输出不是很好。你可以根据确切的数据更新生成器的权重,以便更好地欺骗鉴别器。这将使您的数据过拟合,但会改善您提供的图像的结果。
未来的工作
虽然我们看到的结果相当不错,但我们仍在继续使这种方法更准确、更易于使用。
特别是,我们希望使这种方法对背景运动、摄像机运动、阴影等环境更加鲁棒。我们也在寻找方法使这种方法实时工作,并且使用更少的计算资源。这可以在视频流或移动应用程序等领域实现各种各样的用例。
如果您有任何问题,欢迎联系我,Vivek Jayaram,或 Soumyadip Sengupta
参考
[1] S .森古普塔、v .贾亚拉姆、b .柯尔斯、s .塞茨和 I .凯梅尔马赫-什利泽曼,背景铺垫:世界是你的绿幕 (2020),CVPR 2020
[2]陈立春,朱,帕潘德里欧,施若夫,亚当,【2018】,ECCV 2018
[3]庄玉英、柯尔斯、塞勒斯和塞利斯基,(2001),CVPR,2001
[4]侯庆林和刘福林。用于同步前景和阿尔法估计的上下文感知图像抠图 (2019),ICCV 2019
[5] H. Lu,Y. Dai,C. Shen,和 S. Xu,索引很重要:学*索引用于深度图像抠图 (2019),2019
用 U -Net 去除背景
去除图像的背景是许多应用程序的老问题。在我的使用中,我需要在各种环境下擦除一张居中家具照片的背景,同时保持物体本身完整。
在这里,我们想保留两把椅子,同时删除灰色背景。
虽然在大多数情况下,这项任务可以通过经典的计算机视觉算法来实现,如图像阈值处理(例如使用****【1】),但如果没有特定的预处理或后处理,一些图像可能会非常困难。如果对象具有与背景非常相似的颜色,那么由于边缘或阴影较弱,要找到一个清晰的轮廓会非常困难。
边缘和阴影较弱的图像示例。
相反,如果背景是不同于对象的特征颜色,则很容易构造遮罩来去除背景。这就是色度键控背后的原理,使用绿色和蓝色屏幕擦除背景,并用另一个场景替换,这是娱乐业广泛使用的效果。
我没有使用绿色屏幕的奢侈,但对我来说幸运的是,由于过去十年深度学*的最新进展,这个问题正在被专门为这项任务设计的新模型再次探索。
与这个问题相关的具体子任务叫做显著性物体检测。****
听起来不错,但是显著性到底是什么意思呢?
这里是维基百科对显著图的定义:****
在计算机视觉中,显著图是显示每个像素的独特质量的图像。显著图的目标是简化和/或改变图像的表示,使其更有意义和更易于分析。
通俗地说,显著性就是从图像的其余部分中脱颖而出的能力。显著图允许将图像的重要部分(通常是前景中的对象)与其余部分(背景)区分开来。
非常适合我们的使用案例!
因为我想快速解决这个问题,因此制作自己的数据集是毫无疑问的,所以我寻找一个预训练的模型,它无需进一步微调就能满足我的需要。
最近针对这项任务发布了许多不同的模型,我选择了U-Net【2】,因为根据基准测试,它表现很好,并且代码很容易修改,可以根据我自己的图像进行推断。
这个名字来源于众所周知的 Unet[3] ,它借用了这个名字的一般架构。我不会深入探讨这个问题,但这两个网络都是“U 形”,具有一系列卷积和下采样层,向下到一个低点,在该点开始一系列卷积和上采样层,直到原始输入形状。
U -Net 的主要区别在于“层”本身就是带有向下和向上采样层的“U-结构。
Unet(左)与 U -Net(右)的网络架构
现在,在对原始代码做了一些轻微的修改后,我们可以直接从模型中可视化显著性图:
unet2 预测的掩码
每个单独的像素是一个介于 0 和 1 之间的浮点数,这意味着这个显著图处理透明度!
没有任何进一步的修改,我们可以通过使用 numpy 的简单矩阵乘法,将显著图作为遮罩应用于我们的图像。
在应用显著图作为掩模之后
模型表现很好。我们仍然可以透过椅子看到一点地板,但在我们的情况下这不是问题。总的来说,效果非常好,但可能会留下一些伪像,尤其是像这把椅子这样有“空隙”的物体。
这个结果是在没有对图像进行任何预处理或后处理的情况下获得的。例如,您可以将较高的值向上舍入为 1,将较低的值向下舍入以避免图像周围的“模糊”,或者只是锐化图像。
该型号还配备了另一种更小的架构( u2netp ),与原始的 176 mb 相比,重量仅为 4.7 mb 以获得类似的结果!
当我们想要将我们的模型部署到一些基于云的*台上,而这些*台可能对模型大小有一些限制时,这就变得很方便了。例如 Amazon Lambda,它允许你运行一个无限可扩展的 API,而不需要建立你自己的服务器,它对内存使用和磁盘空间有很大的限制。
以下是不同设置下的图像样本的结果:
****
来源:
[1]https://docs . opencv . org/master/D7/d4d/tutorial _ py _ thresholding . html
[2] U2-Net:使用嵌套的 U 结构进行更深入的显著对象检测
在小批量上从头开始反向传播
逐步执行方程的小批量反向传播算法的实现。
约翰·福斯特在 Unsplash 上的照片
你一定在想,又一个从头开始的博客?是的,但我想通了,想出了一些东西,你可以用它来修改,还有一些容易理解的方程,你通常会写下来理解算法。
本博客将重点关注在小批量数据集上逐步实现反向传播算法。有大量的教程和博客来详细演示反向传播算法以及微积分和代数背后的所有逻辑。所以我将跳过这一部分,直接讨论数学中的方程和使用 Python 的实现(为什么不呢)。
为什么从零开始?
这是一个很长时间的社区问题,为什么我们要从头实现一个算法,即使它已经可以被几乎所有的框架使用。显然,在使用某些高级框架时,你甚至不会注意到反向传播的神奇之处。为了彻底理解它,你应该试着用这个东西弄脏你的手。反向传播是可以边玩边做实验的东西。
为什么是小批量?
小批量背后的原因很简单。它通过将数据分成小批来节省内存和处理时间,并在训练循环的每次迭代中向算法提供数据集的一部分。一次进给一个 10000x10000 的矩阵不仅会耗尽内存,而且需要很长时间来运行。相反,将它降低到每次迭代 50 次不仅会减少内存使用,而且您可以跟踪进度。
注- 这与随机方法不同,在随机方法中,我们从每个类别的数据中抽取分层样本,并在此基础上假设模型可以推广。
实施时间!
这是我将在这个实现中使用的数据的头部。
这里的目标变量是占有率,它是一个分类变量(0/1)。这将是我们将要编码的架构。
算法:
对于 i:=1 至 i:=m:
- 执行前向传播或前向传递,以计算每层神经元的激活值。
2.反向传播步骤:
- 使用数据中的标签计算误差项(MSE 或 LogLoss 或您的愿望):
- 隐藏层中的误差项计算如下:
- 设置渐变:
初始化δ= 0
3.梯度下降和重量更新步骤:
现在实现:
如前所述,这将是一个三层网络。我们保持层数简洁,以便以更好和更容易的方式识别梯度和误差方程。之后,我们将定义一个函数,它将被用作网络中的转发传播器。
这里需要注意的一点是,我认为输入层是我的第 0 层。可能有其他博客/教程认为它是第一。所以怎么索引完全是你自己的选择。
现在,在初始化权重和偏差并定义前向传播函数后,我们将定义小批量的后向传播函数,大小=数据集大小/N。您可以调整 N 来调整所需的批量大小。
让我们一环一环地分解它
- 如上所述,Ist 循环迭代你想要让模型遍历你的数据的次数,简单地把它放在神经网络术语“时期”中。
- 第二次循环:在指定批次数量后,该循环对每个时期“I”的每个小批次进行迭代
- 第三个循环遍历该小批量中的每个训练示例,并计算梯度和误差值
- 最后,对于每个批次,执行梯度下降步骤,并对重量矩阵进行更改。
就是这个!!你终于自己完成了小批量反向传播的实现。这里需要注意的一点是,我对网络中的每一层都使用了一个矩阵变量,当你的网络规模增长时,这是一个愚蠢的举动,但同样,这样做只是为了了解事情实际上是如何工作的。
如果您想增加隐藏层的数量,您可以简单地使用 3d 矩阵进行误差和梯度计算,其中第三维度将保存层值。例如,dim(δ)=(2,3,2),这表示您正在计算第二个隐藏层中 W(2,3)的梯度。
另外,我正在开发一个带有贝叶斯初始化的博客,希望很快会有这样的博客。
感谢阅读!继续实验!
编辑:在这里 可以在 Github repo 中找到使用过的数据集以及 ipython 笔记本。
反向传播变得容易
反向传播在机器学*中是如此基础,却又如此令人生畏。但实际上,这比看起来容易。
学*机器学*(ML)并不需要数学天才。基本上,你所需要的只是大学一年级水*的微积分、线性代数和概率论,你已经准备好了。但是在 ML 看似良性的第一印象背后,有大量与 ML 相关的数学理论。对于许多人来说,学* ML 的第一个真正障碍是反向传播(BP)。这是我们用来推导神经网络(NN)中参数梯度的方法。训练模型是梯度下降算法中的一个必要步骤。
BP 是任何 NN 训练中非常基础的一步。它涉及链规则和矩阵乘法。但很多 ML 课程或教程中 BP 的引入方式并不尽如人意。当我第一次在 Coursera 的机器学*课上学* BP 时,我对它的计算过程非常困惑,以至于暂停了几个月。同时,我搜索了更多关于 BP 的解释。我设法通过了这门课程。我完成了编码作业。但是英国石油公司在我的脑海中仍然是一个非常混乱和令人困惑的模糊形象。
如果你完全不了解 BP,简单地把它当成一个黑箱,其实也没什么坏处,因为 Tensorflow 或者 Pytorch 可以自动为你执行 BP。但是最近我在复*关于 ML 的笔记,我开始正确理解 BP。我的方法是建立一个简单的神经网络,明确地写下每个参数和变量矩阵/向量,并通过链式法则逐步写下每个参数矩阵/向量的梯度计算。最终,BP 比我最初想象的要容易得多。
使用两层 NN 和单个输入样本作为例子
我的内涵是基于 Coursera 的深度学*规范课程 1。我将用一个两层神经网络作为例子。两层刚好“足够深”,因为计算层 1 中的梯度的技术可以重复用于任何附加层。让我们看到关于每层神经元数量的参数的维数也是有帮助的,例如,注意输入是一个 2 维向量,第 1 层中有三个神经元,因此 w[1]是一个 3*2 矩阵。第 2 层或输出层有两个神经元。如果神经网络用于二值分类,输出层是一个神经元;如果神经网络用于多重分类,输出层的神经元数量与类别相同。为了概括我们的分析,我们只考虑一个双神经元输出层作为例子。
简单的两层神经网络(图片由作者提供)
在输入层,即第 0 层,我们有一个 21 的输入向量 x,现在我们只关注单个样本输入。如果我们想把输入看作一批 m 个样本,那么输入的维数实际上是 2m .但是我们这里只考虑一个输入实例。
在第一层,我们有三个神经元,矩阵 w[1]是一个 32 的矩阵。在这个 NN 中,每层也有一个偏置向量 b[1]和 b[2]。b[1]是一个 31 向量,b[2]是一个 2*1 向量。在正向传递中,我们有以下关系(以矩阵形式和矢量化形式书写):
第一层运算的矩阵乘法
第一层操作的矢量化表达
类似地,第 2 层的矢量化运算可以写成:
第二层操作的矢量化表达。请注意,a[1]作为这一层的输入。
暂且忽略激活功能和损耗功能的细节。
对于每一层,我们将使用非线性激活函数 g(z),例如 sigmoid 函数或 ReLU。为了简单起*,我们省略了 g(z)的细节,只是继续使用 g(z)。
a[1]和 z[1]之间的关系
请注意,一旦我们决定使用哪个 g(z ), g(z)对 z 的导数是已知的。
g'(z)是我们已知的。
在神经网络的输出端,我们有一个损失函数 J(),我们将努力使其最小化。通常是交叉熵。为了简单起*,我们暂时不讨论 J()的细节。同样,它是 a[2]和 y 的函数,所以我们可以直接计算它对 a[2]的导数。
损失函数
从最后一层开始,得到部分方向的 dz[2]。
要执行 BP,我们需要从最后一层向后到第一层。在最后一层,我们可以直接从损失函数 J 得到 da[2]的偏导数,因为 J 是 a[2]的函数。假定我们知道导数 g'(z),通过下面的函数从 da[2]获得偏导数 dz[2]也是直接的。请注意,最后一个等式中的运算符(圆圈中的点)表示元素级乘法。
一旦我们获得了 dz[2],我们将试图找到 dw[2]和 db[2]。
以 w[2]中的 w7 为例,这个参数乘以 a1,然后加到 z4。根据链式法则,dw7 等于:
因此,w[2]和 dz[2]之间的关系如下:
可以看到 dw[2]无非是 dz[2]的向量相乘和 a[1]的转置。db[2]就是 dz[2]本身。
然后,我们可以进入第 1 层,计算 da[1]和 dz[1]。
以 a[1]中的 a1 为例。请注意,a1 乘以 w7 和 w8,并分别与 z4 和 z5 相加。根据链式法则,da1 也将由这两部分组成。da[1]和 dz[1]的细节如下所示:
请注意,da[1]是用第 2 层的参数 w[2]和 dz[2]计算的。
使用 dz[1],我们可以获得 dw[1]和 db[1],就像在第 2 层中一样。
我们可以看到 dw[1]的计算是 dz[1]向量和 x 的转置相乘,你也可以把 x 想象成“0”层的输出向量 a[0]。因此得到 dw[l]=dz[l]*a[l-1]的一致表达式。t(。t 表示转置,l 是随机层数)。
通过以上步骤,我们获得了 dw[2]、db[2]、dw[1]和 db[1]。对于超过 2 层的 NN,可以对每一层重复上述步骤:对于任何一层,我们只需要获得 dz[l](或者直接从 J 获得,或者从上一层获得),用它来计算 dw[l]和 db[l];得到 da[l-1]和 dz[l-1],进行到 l-1 层。
对于具有 L 层的 NN,BP 归结为以下四个主要步骤:
- 从最后一层,从损失函数 J 计算 da[L];然后从 da[L]得到 dz[L];设 l= L,
- 用 dz[l] 计算当前层参数的梯度:计算 dw[l]=dz[l]a[l-1]。t;db[l]= dz[l];
- 用 dz[l] 计算上一层输出的梯度:用 da[l-1] = w[l]计算 da[l-1]。T * dz[l],从 da[l-1]得到 dz[l-1]。
- 设置 l=l-1,从第二步开始重复,直到到达第一层。
总之,在每一层,我们都想找出 dz[l],一切都从那里开始。
然后我们来看 J()和 g()的细节。我们假设 g(z)是 sigmoid 函数,J()是交叉熵。它们的格式和渐变如下所示。
在我们 NN 的情况下,J 是 a[2]和 y 的函数,我们可以从下面的函数得到 dz[2]。一旦我们有了 dz[2]的显式表达式,我们就可以用上面的步骤执行 BP。
最后,我们来看看多个输入实例的情况。如果输入包含 m 个实例,那么输出和中间矩阵 A[1],A[2],Z[1]和 Z[2]都有 m 列。
x,Y,A[1],A[2],Z[1],Z[2]有 m 列
如果损失函数 J 是预期的交叉熵,则 dw 和 db 的计算需要包括 1/m 项,但其他一切基本上仍然相同:
就是这样。我们使用简单明了的两层神经网络作为例子,并对单个输入和多个输入执行 BP。希望这个简单的教程能帮助你更好地了解 BP。
参考:
[1] Coursera 深度学*规范课程 1:神经网络和深度学*
[2]https://www.youtube.com/watch?v=ibJpTrp5mcE&feature = youtu . be
[3]http://speech . ee . NTU . edu . tw/~ tlkagk/courses/ML _ 2016/Lecture/BP . pdf
从头开始反向传播纸张
实践教程
理解深度学*的基本基础,通过演练脚本传播错误
由 Mirko Blicke 在 Unsplash 上拍摄的照片
神经网络结构依靠反向传播来获得梯度以减少误差,然后通过在隐藏层中形成内部表示来学*输入/输出模式的映射。反向传播的概念对于理解神经网络如何学*的基础知识至关重要。
这个想法是在著名的(1986) 通过错误传播 学*内部表征中以广义 Delta 规则的名义引入的,这是来自 David Rumelhart 、 Geoffrey Hinton 和 Ronald Williams 的经典。今天,我将为这篇文章提供一个简单的代码脚本和笔记本。论文本身讨论了在问题部分结尾的两个类似的概念表述,其中之一是大卫·帕克的 学*逻辑:在硅中铸造人脑的皮层 (1985)和杨乐存的 不对称阈值网络的学*方案 (1985)。虽然这不是唯一一篇引入这一概念的论文,但这篇论文获得了更大的关注,并在深度学*研究中掀起了热潮。可能正是因为这个原因,这是当时深度学*领域取得的最大里程碑。如今,我们当然可以讨论更大的里程碑。
本文不仅给出了广义 delta 规则,而且给出了合理数量问题的模拟结果,最后还有一个递归网部分。这里,我们只涉及反向传播概念和前馈神经网络结构。
项目回购:https://github . com/devrimcavusoglu/learning _ internal _ presentations
目标是什么?
我在这里提供的是一个基本前馈神经网络架构的 Python 实现,以及对广义 delta 规则的解释。或许这个(Jupyter)笔记本和脚本的一个独特之处在于,我把它们设计成可以在任何地方传达原始符号的形式。因此,我们的主要目标是通过实现来浏览本文,而不要让读者因不同的符号和等式而感到困惑。我知道,概念本身对于一个初学者来说已经很难理解了,或者最近有人跳到了深度学*领域。然而,我认为,反向传播概念对于理解神经网络的基础是必须的。我相信这个笔记本让人们更容易理解纸上的符号。在这一点上,让我说纸符号不是目前常用的符号。然而,我提供了一个简单的字典来使转换到通用符号变得更容易。
已经有一篇关于论文的反向传播算法从杰夫·辛顿学*反向传播的好文章,作者是瑞安·戈特斯曼,有更简单的解释、图表和方程。因此,如果你想检查一个快速写作和一些没有实现,但进一步解释的概念,请参考该职位。当然,笔记本包括大量的信息和解释。
这个项目是为了谁?
我知道你对基本前馈神经网络的代码实现有什么想法。是的,有几百甚至几千个。我非常肯定,任何人都开始学*深度学*,神经网络可能已经完成了他/她的实现。然而,正如我在上一节中提到的,我们的目标是直接使用论文中的符号和方程来提供一个合适的实现。
基本上任何人都想了解神经网络的基础,并从谁至少有一个像样的微积分和线性代数的理解。该项目是为任何人谁没有阅读论文,但愿意阅读,或目前正在阅读,或已经阅读论文。在阅读的任何阶段,你都可以看一下这个演练代码。
让我们进入回购和代码。
法托斯 Bytyqi 在 Unsplash 上的照片
项目内容
虽然这是原论文的一个实现,但是实现上略有不同。例如,神经网络的笔记本实现是以矢量化的方式设计的。网络组件对本文中介绍的方程使用矢量化。要理解矢量化,请参考这篇讨论,或者查看 Jalal Mansoori 的这篇帖子。
资源库:https://github . com/devrimcavusoglu/learning _ internal _ presentations
该项目的组成部分是:
- learning _ internal _ presentations . ipynb
- nnet.py
- example_datasets.ipynb
- nb_utils.py(侧面组件)
建造
到目前为止,我们已经讨论了内容和方法。让我们继续学*实现前馈神经网络的基础知识。下面,你可以看到一个伪代码式的代码片段和神经网络基本训练的步骤。
反向传播部分是我们使用输出和层网络以及激活函数来获得梯度的部分,然后我们使用该梯度来更新权重以降低成本。让我们快速浏览一下反向传播过程的方程式和步骤。本文提出的广义 delta 规则如下:
广义德尔塔法则
权重和偏差的更新规则为
我自己为 t_j (偏置向量)添加了更新规则(不要与代表目标的第 j 分量的 t_pj 混淆),这篇文章没有单独写。上述规则可以转换成矢量化形式,
GDR 的矢量化版本
利用矢量化更新规则,
其中上标代表层 l ,而 L 是总层数减 1,这是由于索引从 0 开始。注意,对于 f 素数,为了方便起*,我们使用下标 l 而不是上标。
记住这些,您可以在下面的代码片段中看到一个反向传播过程,其中 backward_pass 是从层 l+1 到层 l 的反向传播的一个步骤。
我希望这些组件能让读者更容易理解神经网络基础的概念。你可以更进一步,尝试自己去完善这些,或者只是为项目回购做点贡献。
最后的话
实现一篇论文或者一个众所周知的方法的概念,并不是一件找不到的事情。事实上,有一个优雅的项目论文,代码为,旨在用机器学*论文、代码和模拟结果创建完全免费和开放的资源。该项目为许多论文提供了代码,您可能还想查看不同论文的不同实现。这里实现的文件也存在(提交于 2020 年 11 月 9 日),具有相同的实现。
在那之前,我希望笔记本可以带你了解这篇论文的主要概念,反向传播算法。在回顾了这个项目之后,我强烈建议初学者实现自己的项目,对于有经验的人,我建议实现一篇论文来贡献开源。有几点需要考虑,
- 用你自己的话写/重写主要过程 这确实有助于实现过程更能适应不期望的构建部分,并且有助于计划的设计。
- 改进/即兴发挥你实现的方法
例如,实现一个矢量化版本是一个很好的即兴发挥,适合最近的条件,或者添加一个单独的偏差向量。对于方程,LaTeX 永远是好朋友。 - 首先实现一个演练笔记本,然后继续执行脚本 一步一步地实现一个演练笔记本/脚本使概念更容易被吸收。此外,本演练是针对您的反复试验的,就像操场笔记本/脚本,它直接改进您的最终版本的实现。
顺便说一下,不要犹豫分享你的想法,任何反馈都是值得赞赏的。此外,因为这是开源的,所以请随意公开问题,或者创建 pull-request 来贡献代码、文档等。
熊猫交易策略的回溯测试——向量化回溯测试
一种快速有效的交易策略评估方法
啊哈!你在市场上发现了一种模式,这种模式有可能让你成为下一个沃伦巴菲特……现在该怎么办?在设计了一个新的交易策略,可以系统地从这个模式中获利后,现在是时候问自己:“如果五年前我有这个策略会怎么样?”。
今天,我将讨论矢量化回溯测试如何帮助您“回答”这个问题,如何使用 Pandas 实现它,以及您应该注意哪些微妙之处。对于在这方面有一些经验的人,可以直接跳到第 5 部分。
1.什么是回溯测试?
B acktesting 用于模拟交易策略的过去表现。
回溯测试的核心概念是通过回到过去来模拟给定的交易策略,并像在过去一样执行交易。产生的利润通常通过一些指标(如最大提款、夏普比率、年化回报等)与基准业绩进行比较。).根据策略的性质,应该使用不同的基准和度量标准,但这本身就是一个完整的主题,所以我在这里不会详细讨论。
2。什么回测不是
B acktesting 不是过去绩效的准确指标,不应作为研究工具,尤其是对没有经验的人而言。
有趣的是,回溯测试并不能很好地表明如果你能回到过去,你今天会有多富有。除了时间旅行,几乎不可能精确复制过去的表现,因为有很多因素太复杂了,无法精确建模(滑点,交易的市场影响等)。).此外,对于没有经验的人来说,回溯测试可能充满偏差(例如,前瞻偏差、幸存者偏差等)。)可以使战略看起来比实际情况好得多(* 5.3 节)。
最后,回溯测试不是一个研究工具。不要仅仅因为在回溯测试中看起来更好就随意改变你的策略参数。你应该将市场的历史表现视为随机变量的多种可能实现之一。在没有合理的经济逻辑的情况下,将你的参数用于回溯测试将不可避免地导致过度拟合。
3。事件驱动与矢量化回溯测试
V 结构化回测比事件驱动回测快得多,应该用于策略研究的探索阶段。
对策略进行回溯测试有两种主要方法:(I)事件驱动和(ii)矢量化。事件驱动的回溯测试通常涉及到使用一个随时间迭代的循环,模拟一个根据市场信号发送订单的代理。这种基于循环的方法非常灵活,允许您模拟订单执行中的潜在延迟、滑动成本等。
相反,矢量化回溯测试收集与策略相关的数据,并将它们组织成向量和矩阵,然后通过线性代数方法(计算机非常擅长的方法)进行处理,以模拟过去的表现。
由于线性代数的表达能力,矢量化回溯测试比事件驱动的回溯测试快得多,尽管它缺乏灵活性。通常,向量化的回溯测试更适合于初始的探索性策略分析,而事件驱动的回溯测试更适合于更深入的分析。
4。关于日志返回的注释
可以使用对数收益的累积和来计算策略绩效。
在深入研究 python 代码之前,理解对数回报的概念很重要,对数回报被定义为时间间隔( t-1,t )内资产的对数价值的差异:
由于许多原因(*稳性、对数正态性等),对数收益在定量金融中非常有用。),但出于回溯测试的目的,我们将使用它的时间累加属性来计算累积回报(即过去的表现)。
例如,考虑一项资产在几天内的对数收益 (t=3,2,1 )。为了计算该资产在整个期间的总收益,我们简单地将所有日收益相加( r[3]+r[2]+r[1] )。这是因为日志价格信息被取消,如下所示:
因此,如果我想知道资产增长了多少,我只需要用指数函数去掉最终的自然对数。在上面的例子中,资产价值增加了一个系数( p[3]/p[0] )。
上述论点也适用于你的策略。例如,如果您的策略在 T 天内产生了对数回报( r[0],r[1],…,r[T] ,那么策略的回溯测试可以通过对数回报的简单累积和以及指数函数来计算。
5。熊猫的矢量化回溯测试
5.1.单一资产回溯测试
假设我们想对价格移动*均线交叉策略的表现进行回溯测试,如果短期价格*均线高于长期价格*均线,则您做多标的资产,反之亦然。我们可以用 6 个步骤来计算策略绩效:
(1)计算标的资产的对数收益。在这个例子中,我们正在查看 AAPL 股票的对数价格差异,该股票存储在按时间索引的 Pandas 系列中。
rs = prices.apply(np.log).diff(1)
(2)计算信号
w1 = 5 # short-term moving average window
w2 = 22 # long-term moving average window
ma_x = prices.rolling(w1).mean() - prices.rolling(w2).mean()
(3)将信号转化为实际交易头寸(多头或空头)
pos = ma_x.apply(np.sign) # +1 if long, -1 if shortfig, ax = plt.subplots(2,1)
ma_x.plot(ax=ax[0], title='Moving Average Cross-Over')
pos.plot(ax=ax[1], title='Position')
作者图片
(4)通过根据头寸调整基础资产的对数回报来计算策略回报(策略回报的计算并不精确,但在实际水*上通常是足够好的近似值)。此外,请注意,位置已经移动了 1 个时间步长,这样做是为了避免前瞻偏差(参*第 5.3 节)。)
my_rs = pos.shift(1)*rs
(5)通过使用累积和并应用指数函数来计算回测。
my_rs.cumsum().apply(np.exp).plot(title=’Strategy Performance’)
作者图片
5.2.多资产回溯测试
类似于单个资产的情况,我们可以使用 Pandas 计算资产组合的回测。这里唯一的不同是我们正在处理一个熊猫数据框架,而不是熊猫系列。
让我们首先计算每个资产的信号和位置,如下面的代码所示。请注意,我们已经调整了头寸,因此在任何给定时间,投资组合头寸的总和都不超过 100%(即假设没有使用杠杆)。
rs = prices.apply(np.log).diff(1)w1 = 5
w2 = 22
ma_x = prices.rolling(w1).mean() - prices.rolling(w2).mean()pos = ma_x.apply(np.sign)
pos /= pos.abs().sum(1).values.reshape(-1,1)fig, ax = plt.subplots(2,1)
ma_x.plot(ax=ax[0], title='Moving Average Cross-Overs')
ax[0].legend(bbox_to_anchor=(1.1, 1.05))
pos.plot(ax=ax[1], title='Position')
ax[1].legend(bbox_to_anchor=(1.1, 1.05))
作者图片
我们可以从单个资产的角度来看该策略的表现:
my_rs = (pos.shift(1)*rs)my_rs.cumsum().apply(np.exp).plot(title=’Strategy Performance’)
作者图片
我们还可以看看该策略在投资组合层面的总体表现:
作者图片
5.3。关于前瞻偏差的快速注释
在上面的例子中,位置向量/矩阵总是移动 1 个时间步长。这样做是为了避免前瞻性偏*,这种偏*会使战略看起来比实际情况好得多。
这个想法是:在时间 t ,你有一个信号,它包含的信息直到并包括 t ,但是你实际上只能在 t+1 交易那个信号(例如,如果你的信号包含一家公司在周一晚上发布的收益信息,那么你只能在周二早上交易那个信息)。
如下所示,前瞻偏*会使战略看起来比实际更有希望(尤其是对于“动量”战略)。
my_rs1 = (pos*rs).sum(1)
my_rs2 = (pos.shift(1)*rs).sum(1)my_rs1.cumsum().apply(np.exp).plot(title='Look-Ahead Bias Performance')
my_rs2.cumsum().apply(np.exp).plot()
plt.legend(['With Look-Ahead Bias', 'Without Look-Ahead Bias'])
作者图片
5.4.评估对延迟的鲁棒性
有了向量化回溯测试,评估策略对延迟的稳健性就容易多了(即在信号发出后 T 个时间点开始交易)。然而,这种分析在高频交易级别更有用,因为延迟会严重影响业绩。
lags = range(1, 11)
lagged_rs = pd.Series(dtype=float, index=lags)for lag in lags:
my_rs = (pos.shift(lag)*rs).sum(1)
my_rs.cumsum().apply(np.exp).plot()
lagged_rs[lag] = my_rs.sum()plt.title(‘Strategy Performance with Lags’)
plt.legend(lags, bbox_to_anchor=(1.1, 0.95))
作者图片
5.5.模拟交易成本
交易成本通常以固定百分比报价。为了将这些纳入回测,我们可以简单地计算出投资组合在连续时间步之间的变化,然后直接从我们的策略回报中减去相关的交易成本。
tc_pct = 0.01 # assume transaction cost of 1% delta_pos = pos.diff(1).abs().sum(1) # compute portfolio changes
my_tcs = tc_pct*delta_pos # compute transaction costsmy_rs1 = (pos.shift(1)*rs).sum(1) # don't include costs
my_rs2 = (pos.shift(1)*rs).sum(1) - my_tcs # include costsmy_rs1.cumsum().apply(np.exp).plot()
my_rs2.cumsum().apply(np.exp).plot()
plt.legend(['without transaction costs', 'with transaction costs'])
作者图片
我希望你喜欢这篇文章!如果你想看更多这样的内容,请关注我。
此外,查看我的网站的完整代码和其他资源。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详*我们的 读者术语 。
用三行代码优化你的交易策略
使用 fastquant 自动轻松优化您的交易策略参数!
回溯测试的目标是了解空间中的哪些区域会产生更好的结果
如果你想通过投资持续赚钱,回溯测试是评估交易策略有效性的最好方法之一——当然,前提是你要正确实施。这个想法是,你可以为你选择的策略试验不同的参数,看看哪个组合能给你的投资带来最好的回报。
然而,这很容易变得乏味,因为您必须手动运行数百甚至数千个参数组合。
为了解决这个问题,我们可以使用 fastquant 来实现一种称为“网格搜索”的技术,它基本上允许您对您想要为您的策略运行的每个参数组合运行回溯测试。
在本文的其余部分,我将演示如何在回溯测试您的交易策略时应用自动网格搜索。
注意:如果你还不熟悉如何用 fastquant 做基本的回溯测试,你可能想看看我以前的 文章 中关于如何用 3 行代码做这件事。
顺便说一句,如果你对执行这种类型的分析感兴趣,甚至不需要编码,请注册我正在构建的这个新工具以使高级投资分析更容易使用!
好的,让我们从通过 pip 安装 fastquant 开始。
# Run this on your terminal
pip install fastquant
# Alternatively, you can run this from jupyter this way
!pip install fastquant
例如,让我们使用 Jollibee Food corp .(JFC)2018 年 1 月 1 日至 2019 年 12 月 31 日的股票作为我们的样本数据。
注: *get_stock_data*
支持从 雅虎财经 和 PSE 访问的所有公司。
from fastquant import get_stock_data
df = get_stock_data("JFC", "2018-01-01", "2019-12-31")
df.head()# dt close
# 2018-01-03 255.4
# 2018-01-04 255.0
# 2018-01-05 255.0
# 2018-01-08 256.0
# 2018-01-09 255.8
假设你想在 JFC 股票上用 15 天的快速周期和 40 天的慢速周期来回溯测试一个简单的移动*均交叉(SMAC)策略。
from fastquant import backtest
backtest("smac", df, fast_period=15, slow_period=40)# Starting Portfolio Value: 100000.00
# Final Portfolio Value: 68742.36
你会注意到,你的最终投资组合价值下降了很多(~31%),通过查看下面的图表,你会发现这是因为当股票处于整体下降趋势时,该策略仍在推荐交易(绿色和红色箭头)。
即使股票整体下跌,你也会看到交易发生(绿色和红色箭头)
所以现在,我们想看看是否有一个“慢速期”和“快速期”的组合会导致 SMAC 策略知道不要在整体下降趋势中交易。
一种方法是尝试大量可能的快速周期和慢速周期组合。在这个例子中,我们将慢速周期设置为取 20 到 241 范围内的值(每隔 5 秒跳过一次),而快速周期可以取 1 到 20 范围内的值。
这意味着快速周期可以取 20 个可能值,而慢速周期可以取 45 个可能值。总的来说,这意味着 900 (20 x 45)种可能的组合!想象一下这样一个一个做对。
幸运的是,我们可以通过使用迭代器(例如list
、range
)而不是单个数字作为输入,使用 fastquant 的内置网格搜索功能来轻松实现这一点。
results = backtest("smac", df, fast_period=range(1, 21), slow_period=range(20, 241, 5))
results[["fast_period", "slow_period", "final_value"]].head()# fast_period slow_period final_value
#0 3 105 107042.02
#1 8 205 103774.66
#2 11 170 103774.66
#3 8 200 103774.66
#4 9 95 103388.12
注意“backtest”返回一个 pandas data frame(“results”),其中包含每行上每次迭代的结果。数据帧的每一列对应于所使用的一个参数(如fast_period
)或策略的一个性能指标(如final_value
)。
方便的是,这些行根据每次迭代的投资组合回报按降序排列,因此“最佳”参数组合是在数据框顶部的那些。
在这种情况下,似乎最上面的参数组合是:fast_period=3,slow_period=105,投资组合收益为 7,042.02。这表明,当我们在 JFC 股票上使用 SMAC 策略时,我们可能要使用这个参数组合。
注意:很有可能该参数组合仍然过度适合所选的周期。参*之前 文章 中回测的注意事项和保障措施。
现在,让我们运行我们的最优策略!
from fastquant import backtest
backtest("smac", df, fast_period=3, slow_period=105)# Starting Portfolio Value: 100000.00
# Final Portfolio Value: 107042.02
如下图所示,上面的参数组合会建议我们在整体下跌趋势之前卖出我们的股票——看到下跌之前的红色向下箭头。这解释了它如何能够避免我们在本文开始时看到的在我们最初实施 SMAC 战略时的损失。
有了结果数据框架,您甚至可以用如下热图来直观显示每个参数组合的有效性!
查看本技术教程以了解如何绘制该热图
恭喜你!现在,您应该熟悉如何使用 fastquant 内置的网格搜索功能自动优化您的交易策略。下次您发现自己手动插入参数组合到backtest
时,请考虑使用这种自动化方法!
同样重要的是要注意,这是一个改编自 backtrader 包的功能,fastquant 就是建立在这个包之上的。不同之处在于 fastquant 允许您用更少的代码行(少至 3 行)来完成这项工作,这样您就可以花更多的时间来测试您的假设,而不是设置代码。
要查看以上示例的更详细版本和完整代码,包括没有“内置网格搜索”时的代码演示,请查看 Jerome de Leon 的技术教程。
如果你对这份材料有任何问题,请随时在下面发表评论,或者在 Twitter 或 Linkedin 上给我发消息。
最后,如果你想对这个软件包有所贡献,或者想了解更多关于其他人如何使用 fastquant 的信息,请加入我们的社区 Slack workspace ,在这里我们每两周与其他 quant 成员会面一次!
想完全不用编码就做到这一点?
如果你想让这种分析变得更加简单,而根本不需要编码(或者想避免做所有必需的设置的痛苦),你可以订阅这个我正在构建的新的无代码工具来使数据驱动的投资大众化。
希望让更多的人能够接触到这些强大的分析!
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详*我们的 读者术语 。
仅用 3 行 Python 代码回溯测试你的交易策略
介绍 fastquant ,一个面向数据驱动型投资者的简单回溯测试框架
自从我在大学开始投资以来,我接触到了不同的股票分析方法——技术分析和基本面分析。我甚至读过关于这些技术的书籍和无数文章。
简而言之,技术分析认为,你可以利用基于股票历史价格和成交量变动的技术指标来确定买卖股票的正确时机。另一方面,基本面分析认为,你可以根据公司财务报表中的基本面信息来衡量股票的实际内在价值。
这两种分析对我都有意义,我渴望用它们来指导我的交易;然而,我总是对一件主要的事情感到沮丧:
有许多可能的策略,但没有系统的方法来选择一个。在实践中,大多数交易仍然以“直觉”决定告终,而不是由数据驱动。
那么我们如何评估这些策略呢?我们可以通过比较每种方法的预期投资回报(ROI)来做到这一点。最好的方法是使用一种叫做回溯测试的方法,这种方法是通过模拟你过去使用策略时的表现来评估策略。
现在,已经有相当多的回溯测试框架,但是大多数都需要高级的编码知识。一个简单的 hello world 实现通常需要大约 30 行代码。
为了填补这一空白,我决定创建 fastquant ,目标是通过尽可能简化回溯测试,使其成为主流。用fast quant,我们可以用少至 3 行的代码回测交易策略!
fastquant 本质上是流行的 backtrader 框架的包装器,它允许我们大大简化回溯测试的过程,从 backtrader 上至少需要 30 行代码,到 fastquant 上只有 3 行代码。
在本文的其余部分,我将带您了解如何通过 Jollibee Food Corp .的历史数据对简单的移动*均交叉(SMAC)策略进行回溯测试。
此外,如果你有兴趣在无需编码的情况下进行这种类型的分析,一定要尝试一下鹰眼,这是我最近开发的一个新工具,它让高级投资分析变得更容易使用——即使对于非编码人员来说也是如此!
我们开始吧!
回溯测试我们的第一个策略
安装 fastquant
就像使用 pip install 一样简单!
# Run this on your terminal
pip install fastquant
# Alternatively, you can run this from jupyter this way
!pip install fastquant
获取股票数据
从 fastquant 导入 get_stock_data 函数,用它拉取 Jollibee Food corp .(JFC)2018 年 1 月 1 日到 2019 年 1 月 1 日的股票数据。注意,我们有对应于日期(dt)和收盘价(close)的列。
from fastquant import get_stock_data
jfc = get_stock_data("JFC", "2018-01-01", "2019-01-01")
print(jfc.head())
# dt close
# 2019-01-01 293.0
# 2019-01-02 292.0
# 2019-01-03 309.0
# 2019-01-06 323.0
# 2019-01-07 321.0
回溯测试你的交易策略
使用 fastquant 的回溯测试功能,通过 Jollibee Food Corp. (JFC)的历史股票数据对简单的移动*均交叉(SMAC)策略进行回溯测试。
在 SMAC 策略中,快速周期(fast_period)是指用于快速移动*均线的周期,而慢速周期(slow_period)是指用于慢速移动*均线的周期。当快速移动*均线从下方穿过慢速移动*均线到上方时,这被认为是“买入”信号,而如果它从上方穿过到下方,这被认为是“卖出”信号。关于如何工作的更多信息,请查看我以前的文章中的解释。
首先,让我们将 fast_period 和 slow_period 分别初始化为 15 和 40。
您应该会在日志底部看到最终的投资组合价值。这个价值可以被解释为你的投资组合在回溯测试期结束时(在这种情况下是 2019 年 1 月 1 日)的价值。如果你得到了“最终投资组合价值”和“初始投资组合价值”之间的差额,这将是你基于回溯测试的同期预期收益(在本例中为 PHP 411.83)。
from fastquant import backtest
backtest('smac', jfc, fast_period=15, slow_period=40)# Starting Portfolio Value: 100000.00
# Final Portfolio Value: 100411.83
将所有这些放在一起——用 3 行 Python 代码进行回溯测试
下面的代码展示了我们如何只用 3 行 python 代码就能执行上述所有步骤:
**from** **fastquant** **import** backtest, get_stock_data
jfc = get_stock_data("JFC", "2018-01-01", "2019-01-01")
backtest('smac', jfc, fast_period=15, slow_period=40)# Starting Portfolio Value: 100000.00
# Final Portfolio Value: 100411.83
简单移动*均线交叉(15 日均线对 40 日均线)
改进我们的 SMAC 战略
增加快周期和慢周期
这显示了微小的变化是如何迅速将一个成功的策略变成一个失败的策略的。在将 fast_period 和 slow_period 分别增加到 30 和 50 之后,我们的最终投资组合价值从 100,412 菲律宾比索下降到 83,947 菲律宾比索(下降了 16,465 菲律宾比索)。
backtest('smac', jfc, fast_period=30, slow_period=50)# Starting Portfolio Value: 100000.00
# Final Portfolio Value: 83946.83
缩短慢周期,同时保持快周期不变
在这种情况下,我们的策略的性能实际上提高了!我们的最终投资组合价值从 100,412 菲律宾比索上升到 102,273 菲律宾比索(增加了 1,861 菲律宾比索),在此之前,将慢速期减少到 35,快速期保持在 15。
backtest('smac', jfc, fast_period=15, slow_period=35)# Starting Portfolio Value: 100000.00
# Final Portfolio Value: 102272.90
简单移动*均线交叉(15 日均线对 35 日均线)
下表比较了我们 3 种 SMAC 战略的绩效:
基于我们的回溯测试,策略 3(用黄色突出显示)是最准确的 SMAC 策略!
克服回溯测试的局限性
现在,这是不是意味着我们应该继续用最好的 SMAC 策略交易 JFC?也许还不是时候。
回溯测试有相当多的限制,克服这些限制通常需要额外的步骤来增加我们对回溯测试结果和建议可靠性的信心。
下面是回溯测试的两个局限性,以及克服这些局限性的安全措施:
过拟合
这是指这样一种情况,即您得出的“最佳参数”与前一个时间段的模式过于吻合。这意味着当你决定使用你的策略时,你的策略的预期盈利能力不会转化为实际盈利能力。
对此的一个保障是在样本外测试你的策略,这类似于在机器学*中使用“测试集”。这个想法是,你拿出一些数据,当你想评估你的交易策略的盈利能力时,你只使用一次。这样,你就很难过度调整你的参数,因为你没有根据数据集来优化你的策略。
前瞻偏差
这是由于在回溯测试中利用了在测试期间不可用的信息而产生的偏差。例如,您可以在 JFC 上测试一个策略的有效性,该策略假设您在它实际公开之前一个月就已经知道它的财务表现(例如净收入)。这会让你对自己的策略产生不可靠的信心,这可能会让你以后损失很多钱。
在这种情况下,避免这种偏*的最好方法之一就是彻底验证你在回溯测试策略时所做的假设。严格评估你的策略和正确执行策略所需的信息是值得的。
这些只是回溯测试带来的众多限制中的两个。我确实计划在将来写一篇文章来更详细地讨论这些,所以请继续关注!
在解决了上述限制之后,我们应该对我们选择的策略更有信心;然而,请记住,虽然我们可以对我们的策略更有信心,但它在未知的真实世界中的表现永远不会是 100%确定的。
我建议,一旦你在现实世界中采用了一个策略,开始时投入相对较少的资金,只有当这个策略显示出更加持续的成功时,才增加投入;否则,如果它在现实世界中被证明效果不佳,就要做好消灭它的准备。
记下 fastquant 的默认参数
“获取股票数据”功能
为了使“get_stock_data”函数尽可能简单易用,我们将它设计为只返回股票的收盘价(用于大多数交易策略),它遵循格式“c”(c =收盘价)。但是,如果您想要更多的定价数据点(例如,OHLCV 表示“开盘价”、“最高价”、“最低价”、“收盘价”、“成交量”),只需将“get_stock_data”中的“格式”参数设置为您想要的数据格式。
下面是 Tesla 股票的格式(OHLCV)示例:
tsla = get_stock_data("TSLA", "2018-01-01", "2019-01-01", format="ohlcv")
注:对于在 雅虎金融 e 上市的国际股票,这种格式特征应该是稳定的。对于来自【PSE的符号,我们建议坚持默认的“c”格式。
“回溯测试”功能
对于“回溯测试”函数,我们还假设您买入时使用的现金比例(buy_prop)为 1 (100%),您卖出时持有的股票比例(sell_prop)为 1 (100%),每笔交易的佣金(commission)为 0.75%。您可以通过设置括号中参数的值来编辑这些默认值。
下面的例子中,我回测特斯拉,假设 buy_prop = 50%,sell_prop = 50%,commission_per_transaction = 1%。
backtest("smac", tsla, buy_prop=0.50, sell_prop=0.50, commission=0.01)
为 fastquant 贡献更多策略
记住 fastquant 的策略和它现有的策略库中的策略一样多。到目前为止,有 8 种策略可供选择,包括简单的移动*均交叉(SMAC),相对强弱指数(RSI),甚至还有基于情绪分析的策略!
正如我在这篇文章的引言中提到的,有很多不同的策略可以用于交易。有了这个,fastquant 开发团队和我真的可以利用一些帮助来将更多这些策略添加到 fastquant 中。如果你有兴趣投稿,请务必查看 fastquant 包中的 策略模块 。
如果你不熟悉财务概念或正在使用的低级回溯测试框架,不要担心!我们有一个强大的贡献者社区,一旦你发送了你的第一份 PR,他们就可以帮助你。只要遵循这些关于投稿的文档,你应该会很顺利!
如果你想直接与我们互动,你也可以通过鹰眼不和联系我们。欢迎在#反馈建议和#错误报告频道中询问有关 fastquant 的问题。
在 fastquant 系列的下一篇文章中,我将讨论如何应用网格搜索来自动优化您的交易策略,超过数百个参数组合!
感谢您阅读这篇文章,如果您对*fast quant*或任何与将数据科学应用于金融相关的问题有任何进一步的疑问,请随时在下面评论或通过电子邮件( lorenzo.ampil@gmail.com)、 twitter 或 linkedin 与我联系!
想完全不用编码就做到这一点?
如果你想让这种分析变得更简单,而根本不需要编码(或者想避免做所有必要的设置的痛苦),你可以尝试一下hawk sight——这是我最近为民主化数据驱动投资而开发的新的无代码工具。
我们刚刚推出了开放测试版,所以任何人都可以注册,并免费使用该工具。希望让更多的人能够接触到这些强大的分析!
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详*我们的 读者术语 。
使用 Quantopian 对苹果股票的布林线进行回溯测试
我们将创建一个使用双布林线策略交易 APPL 股票的机器人,并用 5 年的数据进行回溯测试,将其与买入并持有进行比较。
尼古拉·切尔尼琴科在 Unsplash 上拍摄的照片
学*技术分析的最大挑战之一(如果不是最大的话)是把你的钱押在一个策略上,而你并不知道这个策略是否有效。互联网上有很多好的和坏的信息,但通过经济损失找出什么有效什么无效是一个难以下咽的药丸。幸运的是,我们不再需要拿我们辛苦赚来的钱去测试我们在网上学到的东西了。我们可以在开始操作前用量子力学进行回溯测试。
我想提出一个简单的练*:用一个最著名的指标来交易 2015 年到 2020 年的苹果股票。是双布林线策略。这是我们要做的:
1-计算 2 组布林线。
一组距离 20 天简单移动*均线(SMA 20)1 个标准差,另一组距离 SMA 20 2 个标准差。
https://www . pro real code . com/pro real time-indicators/blai 5-b b-double/
2-定义操作区域
两个上部带之间的区域将是‘购买区’(上图中的红色区域)。两个较低带之间的区域将是‘销售区’(绿色区域)。以及中央区域,即‘中性区域’。
3-实施战略
- 如果当前价格在买入区,我们在 APPL 上做多。
- 如果当前价格处于“中性区”,我们就按兵不动。**
- 如果当前价格在“卖出区”内,我们做空 APPL。
除此之外,我们还将测试该算法的不同参数。但是首先我们需要一个基准。让我们看看购买 APPL 并持有 5 年的表现。
在 APPL (sid=24)上,每天重新*衡投资组合,使其为 100%多头
APPL 买入并持有业绩
不算太坏,5 年内 194.63%的回报率或每年大约 15%。然而,贝塔系数和下降幅度非常高。同样,希望增加α和夏普比率。让我们编写一个机器人来执行双布林线策略,并在相同的时间内对其进行回测:
**# Original Double BB strategyimport numpy as npdef initialize(context):
context.stock = sid(24)
schedule_function(buy_and_hold, date_rules.every_day())
context.sell = False
context.buy = Falsedef bollinger_bands(context, data):
period = 20
current_price = data.current(context.stock, 'price')
prices = data.history(context.stock, 'price', period, '1d')
avg_20 = prices.mean()
std = prices.std()
upper_band1 = avg_20 + std
upper_band2 = avg_20 + 2*std
lower_band1 = avg_20 - std
lower_band2 = avg_20 - 2*std
stop_loss = 0.0
if ((current_price > upper_band1) and (current_price < upper_band2)) and not context.buy:
order_target_percent(context.stock, 1.0)
context.buy = True
context.sell = False
print('Long position')
elif ((current_price < lower_band1) and (current_price > lower_band2)) and not context.sell:
order_target_percent(context.stock, -1.0)
context.buy = False
context.sell = True
print('Short position')
elif (current_price < (1 - stop_loss) * lower_band1) and context.buy:
order_target_percent(context.stock, 0)
context.buy = False
context.sell = False
print('Stop loss on long')
elif (current_price > (1 + stop_loss) * upper_band1) and context.sell:
order_target_percent(context.stock, 0)
context.buy = False
context.sell = False
print('Stop loss short')
record(upper = upper_band2, lower = lower_band2, price = current_price)**
在这个代码中,使用了 SMA20 和 0%的止损。除此之外,一旦当前价格脱离买入或卖出区域,算法就会*仓。让我们看看这段代码将如何执行:
原创双 BB 性能
回报率大幅下降,但所有其他基本面都有所改善。让我们看看是否可以通过稍微调整我们的算法来做得更好。我提议 3 个改变:
1-不要用 SMA20,我们试试 SMA13。互联网会告诉你在 8 到 12 之间选择一个 SMA,但我认为最好对它进行回溯测试,选择一个最适合你想要使用的安全性的。我测试了几个,13 是最好的。
2-允许当前价格有更多的空间来“T2”呼吸“T3”。让价格在简单移动*均线(上下带)的 2 个标准差内反弹。
3-设置 2%的止损。
**# Modified Double BB strategyimport numpy as npdef initialize(context):
context.stock = sid(24)
schedule_function(bollinger_bands, date_rules.every_day())
context.sell = False
context.buy = False
def buy_and_hold(context, data):
order_target_percent(context.stock, 1.0)
print('Buy APPL')def bollinger_bands(context, data):
period = 13
current_price = data.current(context.stock, 'price')
prices = data.history(context.stock, 'price', period, '1d')
avg_20 = prices.mean()
std = prices.std()
upper_band1 = avg_20 + std
upper_band2 = avg_20 + 2*std
lower_band1 = avg_20 - std
lower_band2 = avg_20 - 2*std
stop_loss = 0.02
if ((current_price > upper_band1) and (current_price < upper_band2)) and not context.buy:
order_target_percent(context.stock, 1.0)
context.buy = True
context.sell = False
print('Long position')
elif ((current_price < lower_band1) and (current_price > lower_band2)) and not context.sell:
order_target_percent(context.stock, -1.0)
context.buy = False
context.sell = True
print('Short position')
elif (current_price < (1 - stop_loss) * lower_band2) and context.buy:
order_target_percent(context.stock, 0)
context.buy = False
context.sell = False
print('Stop loss on long')
elif (current_price > (1 + stop_loss) * upper_band2) and context.sell:
order_target_percent(context.stock, 0)
context.buy = False
context.sell = False
print('Stop loss short')
record(upper = upper_band2, lower = lower_band2, price = current_price)**
让我们回测一下这段代码:
改进的双 BB 性能
很好!我们能够提高回报率、阿尔法和夏普比率,同时降低贝塔和下降。
结论
在本文中,我们研究了苹果股票的双 BB 策略与买入并持有策略的绩效。
与买入并持有相比,自动双 BB 的回报率增加了 100%以上,同时降低了市场风险β和提款。此外,机器人增加了阿尔法和夏普比率。
我很想在评论区听到你关于如何改进这个算法的想法。
谢谢!
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详*我们的 读者术语 。
使用 Python 进行回溯测试
回溯测试移动*均线
在本帖中,我们将使用 Python 对简单的移动*均(MA)策略进行回溯测试。在我最近的一篇文章中,我展示了如何使用 Python 计算和绘制移动*均策略。现在,我们将学*通过回溯测试我们的算法来模拟移动*均线策略在过去几个月的表现。
重述移动*均线策略
让我们首先快速回顾一下我们在上一篇文章中构建的内容。我们的模型很简单,我们构建了一个脚本来计算和绘制短期移动*均线(20 天)和长期移动*均线(250 天)。
我推荐你看一下这篇文章,了解更多关于移动*均线和如何构建 Python 脚本的细节。在这篇文章中,我将只发布获取所选股票的移动*均线和股价的代码:
import requests
import pandas as pd
import matplotlib.pyplot as plt
def stockpriceanalysis(stock):
stockprices = requests.get(f"https://financialmodelingprep.com/api/v3/historical-price-full/{stock}?serietype=line")
stockprices = stockprices.json()
#Parse the API response and select only last 1200 days of prices
stockprices = stockprices['historical'][-1200:]
#Convert from dict to pandas datafram
stockprices = pd.DataFrame.from_dict(stockprices)
stockprices = stockprices.set_index('date')
#20 days to represent the 22 trading days in a month
stockprices['20d'] = stockprices['close'].rolling(20).mean()
stockprices['250d'] = stockprices['close'].rolling(250).mean()
stockpriceanalysis('aapl')
回溯测试策略
为了执行回溯测试,我们将:
- 当短期移动*均线穿越长期移动*均线上方时,做多 100 只股票(即买入 100 只股票)。这就是所谓的黄金交叉。
- 几天后卖出股票。例如,我们会保留库存 20 天,然后出售。
- 计算利润
这是一个非常简单的策略。我们将有所选股票的每日收盘价。该策略也可以用于分钟或小时数据,但我将保持简单,并基于每日数据执行回溯测试。
因为我不期望有很多进入点,也就是当我们购买股票时,为了简单起*,我将忽略交易成本。
还记得我们之前的帖子吗,如果我们通过将股票名称作为参数传递给 analyse 来运行脚本,我们将获得一个名为 stockprices 的 Pandas 数据帧,其中包含最近 1200 天的收盘价和移动*均线。
stockpriceanalysis('aapl')
#Outcome stored in a DataFrame call stockprices
close 20d 250d
date
2020-02-07 320.03 316.7825 224.76192
2020-02-10 321.55 317.3435 225.36456
2020-02-11 319.61 317.4760 225.96228
2020-02-12 327.20 318.2020 226.58788
Python 中的回溯测试策略
为了建立我们的回溯测试策略,我们将首先创建一个包含我们每个多头头寸利润的列表。
首先(1),我们创建一个新列,它将包含数据帧中所有数据点的 True ,在该数据帧中,20 天移动*均线与 250 天移动*均线相交。
当然,我们只对交叉发生的第一天或第二天感兴趣(即 20 日均线越过 250 日均线)。因此,我们定位交叉发生的第一个或第二个日期(行)( 2)。
正如在这篇文章中所述,我们将使用两天规则(,即只有在被多一天的收盘确认后,我们才开始交易,并且只有当连续两天 20 日均线高于 250 日均线时,我们才会保留该日期作为进场点。
这种方法将帮助我们避免日常交易噪音波动。当这种情况发生时,我们将在列 firstbuy 中设置入口点,其中值等于 True:
#Start longposiiton list
longpositions = []
# (1)
stockprices['buy'] =(stockprices['20d'] > stockprices['250d'])
# (2)
stockprices['firstbuy'] = ((stockprices['buy'] == True) & (stockprices['buy'].shift(2) == False)& (stockprices['buy'].shift(1) == True))
# (3) identify the buying points
buyingpoints = np.where(stockprices['firstbuy'] == True)
print(buyingpoints)
#Outcome
(array([ 307, 970, 1026]),)
规则(股票价格【买入】。shift(2) == False) ,帮助我们找出交叉发生后的第一个日期。
现在我们有了变量买入点 (3),我们应该用我们的长期策略进入市场的日期。
数组 buyingpoints 中的每个元素代表我们需要做多的行。因此,我们可以通过它们循环得到接近的价格,并购买 100 只股票(4)。
然后,我们保留这些股票 20 天(5),并以+20 天收盘价卖出这 100 只股票。
#(4)
for item in buyingpoints[0]:
#close price of the stock when 20MA crosses 250 MA
close_price = stockprices.iloc[item].close
#Enter long position by buying 100 stocks
long = close_price*100
# (5) sell the stock 20 days days later:
sellday = item + 20
close_price = stockprices.iloc[sellday].close
#Sell 20 days later:
sell = close_price*100
# (6) Calculate profit
profit = sell - long
longpositionsprofit.append(profit)
最后,我们计算利润,并将策略的结果添加到 longpositionprofit 数组(6)中。
我们战略的结果
要了解我们的策略执行得如何,我们可以打印出多头头寸利润列表并计算总额:
print(longpositionsprofit)
#outcome
(array([ 307, 970, 1026]),)
print(sum(longpositionsprofit))
#outcome
2100.0
太好了,我们对苹果的回溯测试策略显示,在 1200 多天里,我们进入了一个多头头寸,并在 20 天后总共卖出了三次。
第一次,我们获得了 307 美元的利润,第二次,970 美元,最后一个多头头寸,我们获得了 1026 美元的利润。总共是 2100 美元。
一点也不差。但是如果我们在 1200 天前买了这只股票并一直持有到今天会怎么样呢?通过在我们的股票价格数据框架中获得最后一个可用价格和第一个可用价格,我们可以很容易地计算出买入和持有的利润。
firstdayprice = stockprices.iloc[0].close
lastdayprice = stockprices.iloc[-1].close
profit = 100*(lastdayprice - firstdayprice)
profit
#Outcome
15906.999999999996
有趣的是,只要持有股票 1,200 天,我们的利润就是 15,906 美元加上年度股息。比我们采用移动*均线策略要高得多。
包扎
我们使用了一个简单的策略,当 20 日均线穿过 250 日均线时买入股票。然后,我们把股票保留了 20 天,然后才卖出。
我们可能还遵循了其他策略。例如,我们可以在移动*均线交叉时买入股票,并持有到最后。或者,如果 250 天移动*均线低于 20 天移动*均线,我们可以卖掉股票。
我会让你知道如何试验和测试这些其他的策略。很高兴在我的 Twitter 账户上收到您的反馈。
查看下面的 Python 脚本,对任何公司的移动*均线策略进行回溯测试。只要把苹果的 换成其他公司的 就行了
#Moving Averages and backtesting
import requests
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
def stockpriceanalysis(stock):
stockprices = requests.get(f"https://financialmodelingprep.com/api/v3/historical-price-full/{stock}?serietype=line")
stockprices = stockprices.json()
#Parse the API response and select only last 1200 days of prices
stockprices = stockprices['historical'][-1200:]
#Convert from dict to pandas datafram
stockprices = pd.DataFrame.from_dict(stockprices)
stockprices = stockprices.set_index('date')
#20 days to represent the 22 trading days in a month
stockprices['20d'] = stockprices['close'].rolling(20).mean()
stockprices['250d'] = stockprices['close'].rolling(250).mean()
###STARTING BACKTESTING STRATEGY
#Start longposiiton list
longpositionsprofit = []
shortpositions = []
stockprices['buy'] =(stockprices['20d'] > stockprices['250d'])
#We find the first True since it is first day when the line has crossed. Also, ensure that we have at least two days where sticoprices
stockprices['firstbuy'] = ((stockprices['buy'] == True) & (stockprices['buy'].shift(2) == False)& (stockprices['buy'].shift(1) == True))
buyingpoints = np.where(stockprices['firstbuy'] == True)
for item in buyingpoints[0]:
#close price of the stock when MA crosses
close_price = stockprices.iloc[item].close
#Enter long position
long = close_price*100
sellday = item + 20
close_price = stockprices.iloc[sellday].close
#Sell 20 days later:
sell = close_price*100
#Calculate profti
profit = sell - long
longpositionsprofit.append(profit)
#Result of Moving Average Strategy of going long
print(longpositionsprofit )
print(str(sum(longpositionsprofit)) + ' is the profit of Moving Averag Strategy')
#Result of just holding the stock over 1200 days
firstdayprice = stockprices.iloc[0].close
lastdayprice = stockprices.iloc[-1].close
profit = 100*(lastdayprice - firstdayprice)
print(str(profit) + ' is the profit of holding over the selected period of 1200 days')
#Change apple for the ticker of any company you want to backtest
stockpriceanalysis('AAPL')
原载于 2020 年 3 月 8 日 https://codingandfun.com**。
回溯:如何处理搜索编程面试问题
用三个例子直观地解释:N 皇后、飞行路线和数独
图片来源:作者
回溯是解决常*编程面试算法问题的有效方法。回溯深度——搜索解决方案,然后一到达终点就回溯到最近的有效路径(也就是说,我们不能再前进了)。这种方法减少了搜索空间,因为我们知道的无效路径都从解空间中排除了。
然而,使用回溯需要测试部分解决方案的能力——如果没有进度指标表明我们当前的解决方案路径是否通向一个解决方案,该方法就不能找到全局最优。然而,像数独这样的事情可以用回溯来解决——比方说,如果在一行、一列或一个正方形中有两个相同的数字,那么当前的解决路径是否无效就一目了然了。
回溯由三部分组成:一个递归函数,它接受一个解集(可能是不完整的 n ),一个对 n 的变异或添加,它添加到集合 n ,以及一个完成和有效性检查,它检查一个解集变异的完成(解是完整的吗?)和有效性(是否符合有效性的要求?对于当前填写的值,这是一个可接受的解决方案吗?).
图片来源:作者
回溯基于非常简单的元素自动创建一个干净且计算高效的搜索树。
在本文中,我将通过视觉演示回溯如何被用来解决三个经典的编程面试式搜索问题。
n 皇后问题
N-皇后问题是一个经典的回溯问题:给定一个 N 乘 N 大小的棋盘,你可以用多少种方式排列 N 个皇后棋子,使它们不会互相威胁(一个不在一个皇后的列、行或对角线上)?
举例来说,这个格子是一个无效的移动,因为八个皇后中至少有两个在另一个的行、列或对角线上,用红色方块标记。
这个问题的强力解决方案是尝试在每个 N 乘 N 地点中的 N 个皇后的每一个组合— N 选择 N 种可能性。
画出来,其中 x 代表 N 和 y 代表搜索的可能性的数量,它扶摇直上。
图片来源:作者
仅仅对于一个标准的 8 乘 8 网格,就有 4,426,165,368 种组合,慢得令人痛苦。这可以通过不将两个皇后放在同一行或列中得到部分改善,但我们仍然需要迭代每一行和每一行中的每个单元格——运行时间为 O ( N ),不够快。
现在,让我们通过一个问题清单来确定回溯是否有帮助。
可以构造部分解吗?
是的,可以构建部分解决方案。通过在棋盘上放置一定数量的皇后,我们可以部分地构建一个解。
那些部分解决方案可以被验证为有效或无效吗?
是的,我们可以通过检查任意两个皇后是否相互威胁来验证部分解决方案是否有效。这可以通过承认原来的女王不互相威胁来加速,并且只检查新增加的女王是否威胁任何其他女王。
可以验证解决方案是否完整吗?
是的,当所有的 N 皇后都被放到棋盘上时,解决方案就完成了。回溯的伟大之处在于,当解决方案完成时,它也是正确的,因为所有不正确的解决方案路径都已被事先排除。
让我们构造一个回溯方法来更快地解决 N 皇后问题。
功能n_queens
:
- 摄入
N
和board
,一串数字。 - 如果没有指定,将
board
初始化为空列表,并将count
初始化为 0。 - 对于
*N*
中的每列*X*
, -
将列
*X*
' 的索引添加到board
。 -
如果
board
有效,将n_queens
的输出与输入N
和board
相加到count
(这将初始化函数的另一个循环,是回溯的隧道或树构建过程。由于在这种情况下部分解决方案被认为是有效的,它启动了函数n_queens
的另一个实例。 -
否则,删除列
*X*
。 - 返回
count
。
伸缩式树型建筑
评估电路板是否有效的函数如下:
- 入口
board
,一个数字列表,其中每个数字对应一列。 - 最近添加的皇后行是棋盘的当前长度减一(因为索引从 0 开始),当前皇后列是棋盘的最后一个元素。
- 对于棋盘中的每一行
R
和每一列C
(仅由放置的皇后组成), -
找出新添加的皇后列和当前列的区别
C
。如果等于 0(两列相同),返回False
并从函数中中断。 -
找出新添加的女王排和当前排
R
的区别。如果等于 0(两行相同),返回False
并从函数中中断。 - 否则,返回
True
。
通过在一个构建函数中递归迭代一个构建函数的新实例,回溯能够构建一个智能树,在情况无望时不再继续:它是基于过程而不是基于结果的。
结果,其中索引指示 N 的值:
1, 1, 0, 0, 2, 10, 4, 40, 92, 352
航班路线问题
给定某人的航班的无序列表,每一个都用(起点、目的地)对和起始机场表示,计算此人的行程。如果不存在,返回 na-必须在旅程中使用所有航班。
让我们以这些航班为例:
- HNL ➔ AKL
- 尤尔·➔订单
- SFO ➔ HNL
- 订单➔ SFO
这个问题的强力解决方案是尝试航班的每一种排列,并验证它是否是一个有效的旅程,使它成为 O ( n !)时间。
让我们再问一下使用回溯的三个问题清单。
可以构造部分解吗?
是的,部分解决方案可以通过列出一个不完整的行程来构建,比如 SFO ➔ HNL ➔奥德➔?。
那些部分解决方案可以被验证为有效或无效吗?
如果没有从旅程中的最后目的地出发的航班,并且仍然有剩余的航班可以乘坐,则该解决方案可以被验证为无效。因为必须使用所有航班,所以我们到达了终点。
可以验证解决方案是否完整吗?
是的,当旅程使用所有航班时,解决方案就完成了。
构建解决方案的逻辑:
一个功能get_itinerary
:
- 获取一个无序列表
flights
,其元素形式为(origin, destination)
和current_itinerary
,即一个旅程列表(其中第一个元素是起始机场,第二个元素是第一个航班的目的地和第二个航班的出发地,依此类推)。 - 如果
flights
已经用完,返回current_itinerary
。 last_stop
将等于current_itinerary
的最后一个元素。- 对于航班中的每个
(origin, destination)
对, -
将
destination
添加到current_itinerary
中。 -
如果
origin
等于last_stop
(这是检查,确保航班是有效的连接), -
用除当前
(origin, destination)
对之外的所有航班返回另一个get_itinerary
运行,并退出该功能。 -
否则,删除最近的
destination
。 - 如果先前的树搜索都不能返回任何解决方案,则返回
None
。
回溯构建的树的简化版本
您可能会观察到,实现回溯的很大一部分与多次使用一个函数和构建一个自动化的递归搜索树有关。
注意,对于这个特殊的问题,有一个更有效的方法来解决它。我们只是用回溯作为例子。实际上,更快的方法是选择出发机场(例如 SFO),在航班中找到中转机场(SFO 到 HNL),然后将目的地添加到旅程中,循环进行。
九宫格游戏
我们能用回溯法解决一个标准的数独难题吗?
可以构造部分解吗?
是的,我们可以部分填充数独板上的位置。
那些部分解决方案可以被验证为有效或无效吗?
是的,如果部分解决方案中有任何数字在行、列或正方形中具有相同的数字,则该解决方案无效。否则有效。
可以验证解决方案是否完整吗?
是的,当整个数独板被填满时,解决方案就完成了。
让我们尝试一个接一个地填充每个空单元格,一旦遇到无效状态就返回。看起来会像这样:
功能sudoku
:
- 获取变量
board
,这是一个数组,每个值代表数独棋盘上的一个单元格。 - 如果
board
完成,返回board
并退出该功能。 - 设
r
和c
代表板上第一个空值的行和列。 - 对于
[1, 2, 3, 4, 5, 6, 7, 8, 9]
中的每个值i
, -
将第
r
行第c
列单元格设置为i
。 -
如果
board
至今有效, -
给定
board
,运行sudoku
的另一个实例。
数独的 4x4 版本如何与回溯一起工作
使用回溯法来解决像困难的数独棋盘这样复杂的事情,简单而又干净,这是非常美妙的。只要勾勒出一个递归函数、一个部分解检查和一个评估解是否完整的函数,程序就会自动为你构建一棵树,找到最佳解(如果有的话)。
结论
我希望这篇文章能够让你理解,概述回溯的三个简单组成部分如何能够概述程序的规则,以便自己进行排序并找到最佳解决方案。
袋装树:每个数据科学家都需要的机器学*算法
袋装树简介
在还没有深入细节的情况下,对决策树有一些基本的了解是很重要的。
从每个算法的评估方法到算法本身,都有很多相似之处。
如果你还不熟悉决策树,我推荐你快速复*一下这里。
也就是说,准备好成为袋装树专家吧!袋装树以提高单个决策树的预测能力而闻名,是一种非常有用的机器学*工具带算法。
什么是袋装树&是什么让它们如此有效?
为什么使用袋装树
袋装树之间的主要思想是,你不是依赖于单个决策树,而是依赖许多许多决策树,这允许你利用许多模型的洞察力。
偏差-方差权衡
当考虑模型的性能时,我们通常会考虑我们输出的偏差-方差权衡。方差与我们的模型处理小错误的方式有关,也与我们的模型偏离的程度有关,偏差会导致拟合不足。该模型实际上对变量之间的关系做出了不正确的假设。
你可以说,变异的问题是,虽然你的模型可能是方向正确的,但它不是非常准确,而如果你的模型非常有偏差,那么变异可能很小;它可能完全方向不正确。
一般来说,决策树的最大问题是它们有很高的方差。这带来的问题是,数据的任何微小变化都可能导致模型和未来预测的重大变化。
这在这里起作用的原因是袋装树的好处之一,它有助于在保持偏差一致的同时最小化变化。
为什么不用袋装树
袋装树的一个主要问题是它们难以解释。在决策树的课程中,我们了解到决策树的一个主要优点是它们非常容易解释。袋装树在这方面证明是相反的,因为它的过程增加了复杂性。我稍后会对此进行更深入的解释。
什么是装袋?
Bagging 代表引导聚集;这就是所谓的集成方法——这是一种有效地将不同的模型、数据、算法等分层的方法。
所以现在你可能会想…好吧,酷,那么什么是引导聚合…
所发生的是,模型将对数据的子集进行采样,并将训练决策树;到目前为止,与决策树没有什么不同…但接下来发生的是获取额外的样本(替换,这意味着相同的数据可以被多次包含),训练新的模型,然后对预测进行*均。一棵袋装树可以包括 5 棵树、50 棵树、100 棵树等等。集合中的每棵树可能有不同的特征、终端节点数、数据等。
可以想象,一棵袋装的树是很难解读的。
培养一棵袋装树
首先,我们将开始训练和测试。这里就不多说火车测试拆分了。我们将用titanic
包中的泰坦尼克号数据集来做这件事
n <- nrow(titanic_train)n_train <- round(0.8 * n)set.seed(123)
train_indices <- sample(1:n, n_train)
train <- titanic_train[train_indices, ]
test <- titanic_train[-train_indices, ]
现在我们已经有了训练和测试集,让我们加载ipred
包。这将允许我们运行装袋功能。
需要记住的几件事是,公式表明我们想通过(~
) Pclass + Sex + Age + SibSp + Parch + Fare + Embarked
来理解Survived
从这里您可以看到,我们正在使用训练数据集来训练这个模型。&最后可以看到这个参数coob
。这是为了确认我们是否想测试袋外样品的性能。
还记得我说过每棵树都重新采样数据吗?这个过程会留下一些记录,这些记录永远不会用于训练&组成一个优秀的数据集来测试模型的性能。这个过程发生在bagging
函数中,当我们打印模型时你会看到。
library(ipred)
set.seed(123)
model <- bagging(formula = Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare + Embarked, data = train, coob = TRUE)
print(model)
如你所*,我们在袋装树模型中训练了默认的 25 棵树。
我们使用与决策树相同的过程来预测我们的测试集。
pred <- predict(object = model, newdata = test, type = "class") print(pred)
性能赋值
现在,我们已经训练了我们的模型,预测了我们的测试集,现在是时候分解不同的性能评估方法了。
ROC 曲线和 AUC
ROC 曲线或受试者工作特征曲线是一种可视化二元分类模型正确诊断或预测能力的方法。ROC 曲线绘出了不同阈值下的真阳性率与假阳性率的关系。
我们对于 ROC 曲线的目标是真阳性率 100%,假阳性率 0%。那条曲线会落在图的左上角。
AUC 旨在确定可分性的程度,或正确预测类别的能力。AUC 越高越好。1 是完美的,0.5 是随机的。
我们将使用metrics
包来计算数据集的 AUC。
library(Metrics)
pred <- predict(object = model, newdata = test, type = "prob") auc(actual = test$Survived, predicted = pred[,"yes"])
在这里,您可以看到我将type
更改为"prob"
以返回百分比可能性,而不是分类。这是计算 AUC 所需要的。
这返回了 0.89 的 AUC,一点也不差。
截止阈值
在分类中,临界值的概念意味着给定一个给定结果的一定百分比的可能性,你会相应地对它进行分类。哇,这是一个满嘴。换句话说,如果你预测 99%的存活率,那么你可能会把它归类为存活率。好吧,假设你看着另一个乘客,你预测他有 60%的可能性活下来。嗯,他们仍然更有可能幸存,所以你可能会把他们归类为幸存。选择type = "pred"
时,您可以灵活指定自己的截止阈值。
准确(性)
这个指标很简单,你的预测有多少是正确的。caret
的混淆矩阵函数就包含了这个。
混淆矩阵
caret
包中的confusionMatrix
功能非常有用。用于评估分类模型性能。加载这个包,把你的预测和实际数据传给它。
library(caret)
confusionMatrix(data = test$pred, reference = test$Survived)
这个函数向你展示的第一件事就是所谓的混淆矩阵。这将向您显示一个预测值和实际值如何匹配的表格。所以预测值和参考值相同的对角线单元格代表我们得到的正确值。将这些记录加起来 149 (106 + 43)并除以记录总数,178;我们达到了 83.4%的准确率。
True positive:象限中引用和预测都为 1 的单元格。这表明你预测了存活,而他们确实存活了下来。
假阳性:这里你预测为阳性,但你错了。
真阴性:当你预测为阴性,并且你是正确的。
假阴性:当你预测为阴性,而你是不正确的。
需要记住的几个关键指标是灵敏度和特异性。敏感度是您正确预测的真实记录的百分比。
另一方面,特异性是衡量实际错误记录中你正确预测的部分。
在不*衡数据集上进行预测时,要记住特异性。一个非常常*的例子就是对垃圾邮件进行分类。99%的情况下它不是垃圾邮件,所以如果你预测没有垃圾邮件,你有 99%的准确率,但你的特异性是 0,导致所有的垃圾邮件都被接受。
结论
总之,我们已经了解了使用袋装树的正确时间,以及使用它们的错误时间。
我们定义了什么是装袋以及它如何改变模型。
我们建立并测试了自己的模型,同时定义和评估了各种性能指标。
我希望你喜欢这个关于袋装树的快速课程。让我知道你是否想要更多的信息,或者你是否想要我在另一篇文章中报道一些事情。
祝数据科学快乐!
装袋、增压和梯度增压
易于理解的解释
埃里克·穆尔在 Unsplash 上拍摄的照片
制袋材料
Bagging 是在 bootstrap 样本上训练的机器学*模型的聚合(Bootstrap AGGregatING)。什么是引导样本?这些是几乎独立同分布(iid)样本——因为样本之间的相关性很低,而且它们来自同一个分布。引导过程用于创建这些样本。这包括从数据集中抽取样本并替换掉,记住如果这些样本足够大,它们将代表抽取样本的数据集,假设抽取样本的数据集也足够大以代表总体。在我们的数据集中有大量的观察值也意味着 bootstrap 样本更有可能在样本之间具有低相关性。
图一。样本取自数据集,数据集也是取自总体的样本。
为什么我们不简单地从总体中抽取更多的样本,而不是从我们的数据集中抽取样本?我们可能没有资源或能力从人群中获取更多样本——通常,在研究和工业中,我们必须完全依赖我们已经获得的或以前收集的数据。在这种情况下,bootstrapping 已经被证明是一种准确且计算效率高的估计人口分布的方法。
例如,如果我们有关于一个人是否拖欠贷款的数据,带有伯努利分布响应变量(0 或 1 表示此人是否拖欠),我们可以计算响应变量的*均值,以快速估计我们的数据集中类的表现程度。为了找到响应变量均值的分布(了解其可变性以及我们的数据集对总体的代表性),我们必须从总体中重新取样几次,并计算每个样本的均值,以便更好地了解响应变量的真实分布。然而,这并不总是可能的,我们只限于一个样本(我们的数据集)。经验表明,通过 bootstrapping,仅使用我们通过从数据集本身中抽取替换样本而获得的数据,有可能获得我们采样统计(响应变量的*均值)的真实分布的相当准确的估计值。
图二。左图:样本统计量α估计值的直方图,该估计值是根据总体中的 1,000 个样本(本例中为数据集)计算得出的。中心:从单个数据集的 1000 个 bootstrap 样本中获得的α估计值的直方图。右图:显示在左图和中间图中的α估计值显示为箱线图。在每个面板中,粉色线表示α的真实值。(詹姆斯等人,未注明)
bagging 的想法自然来自 bootstrapping,因为独立、同质的机器学*模型是在几乎独立的 bootstrap 样本上训练的,并且它们的结果是通过加权*均值聚合的。在这些 bootstrap 样本上进行训练的原因是,样本具有低相关性,因此我们可以更好地代表总体。流行的 bagging 算法,random forest,在为每个引导样本拟合决策树时,也对一小部分特征进行子采样,从而进一步降低样本之间的相关性。Bagging 提供了真实总体的良好表示,因此最常用于具有高方差的模型(如基于树的模型)。
助推
在高层次上,所有提升算法都以相似的方式工作:
- 数据集中的所有观察值最初被赋予相同的权重。
- 在这个数据集上训练机器学*模型。
- 来自步骤 2 的模型被添加到带有与其相关联的误差的集合中,该误差是误分类观测值的权重之和。
- 错误分类的观察值被赋予更大的权重。
- 步骤 2-4 会重复许多个时期。
这里的想法是使错误分类的观察在随后的学*迭代中显得更加重要。在这一点上应该注意的是,boosting 是一种非常强大的集合技术,但是由于其关注困难观测的性质,它容易过拟合。因此,它通常用于相对有偏差的基础模型,例如浅树。
最容易理解的升压算法是 AdaBoost,其工作原理如下:
- 初始化变量。
M = Number of models to fitN = Number of observations in datasetm = 1 # Iteration counter, m <= M.w_i = 1/N # For i = 1, 2, 3, ..., N.F_0 = 0 # Ensemble model.
- 使用最小化加权误差
e_m = sum(w_misclassified)
的观察权重w_i
训练模型f_m
。 - 最新合奏模型
F_m = F_m_minus_1 + (alpha_m * f_m)
哪里alpha_m = log(1 — e_m) / e_m
。 - 以与
alpha_m
成比例的增量更新错误分类观测值的权重。 - 递增迭代计数器。
m += 1if m <= M:
go to step 2
- 最终模型是各个模型的预测总和乘以各自的 alpha 系数。
F = (alpha_1 * f_1) + (alpha_2 * f_2) + ... + (alpha_m * f_m)
梯度推进
这种方法被称为梯度推进,因为它使用梯度下降算法来最小化向集合添加模型时的损失。后续模型被拟合到伪残差而不是调整权重。随机梯度下降(如 XGBoost 所用)通过对每个阶段的观察值和特征进行采样来增加随机性,这类似于随机森林算法,只是采样是在没有替换的情况下进行的。
梯度推进算法通过构建新的模型来改进每次迭代,该新的模型添加了估计器 h 以提供更好的模型。完美的 h 意味着:
其中 y 是目标。或者简单地说:
这是目标和前一次迭代的模型预测之间的残差。为了近似这个残差,我们使用前面提到的伪残差,这在下面的步骤中解释:
- 最初,像往常一样在数据集上训练,并获得每个观察的预测。
- 根据步骤 1 中的预测,将伪残差计算为损失函数偏导数的负值。
- 使用伪残差作为下一个模型的新目标,并像以前一样获得每个观测值的预测。
- 重复步骤 2-3,进行 M 次迭代。
图三。按照步骤 2 的伪残差。该值用作在每个训练时期预测 F(x)和目标 y 之间的“距离”的度量。m 是每个基础模型,N 是之前数据集中的观察次数。
在进行上述操作时,我们有效地预测了每次迭代中残差的近似值,因此,我们得到了以下集合模型:
带 h ,如中所述:
取而代之的是我们的伪残值。
参考
詹姆斯·g·威滕·d·哈斯蒂·t·蒂布希拉尼·r(未注明)。统计学*入门。
基于低方差模型的 Bagging
入门
简单线性回归装袋的奇特案例
Bagging(也称为 bootstrap aggregation)是一种技术,在这种技术中,我们根据均匀的概率分布重复地采取多个样本进行替换,并在其上拟合一个模型。它将多个预测组合在一起,通过多数投票或汇总预测来给出更好的预测。这种技术对于倾向于过度拟合数据集的模型(高方差模型)是有效的。Bagging 减少了方差而不会使预测有偏差。这项技术是许多合奏技术的基础,所以理解它背后的直觉是至关重要的。
如果这种技术这么好,为什么我们只在显示高方差的模型上使用它?当我们将它用于低方差模型时会发生什么?让我们借助演示来理解潜在的问题。
我们将在决策树上使用 bagging 来证明 bagging 提高了高方差模型的准确性,并将其与基于简单线性回归的 bagging 进行比较,后者因数据集而有偏差。当预测值与目标变量不完全相关时,简单线性回归是有偏差的。
偏差和方差
我们将在整篇文章中讨论偏差和方差,所以让我们先了解一下它是什么。
偏置
高偏差是指模型过于简化。即当我们不能捕捉数据的真实关系时。我们创建模型的目的是捕捉数据的真实性质,并根据趋势进行预测,这使得高偏差成为一种不受欢迎的现象。
在这种情况下,正在使用的模型并不合适。作者图片
差异
高方差指的是模型过于复杂的情况。即,在捕捉模型的真实性质的过程中,我们正在创建一个模型,该模型很好地学*了训练数据,以至于它的准确性在任何其他数据集上都恶化了。这种情况也是不希望的,因为我们的目标是对看不*的数据进行预测。
在这种情况下创建的模型不适用于训练数据集中不存在的数据。作者提供的图片
偏差-方差权衡
当我们创建一个模型时,我们希望在偏差和方差之间取得*衡。偏差和方差是相反的,所以每当我们试图减少方差时,我们就同时增加了模型的偏差。这种过拟合/欠拟合的困境被称为偏差-方差权衡。这张图片很好地展示了他们之间的关系。
偏差-方差权衡。作者图片
高方差模型—决策树
决策树对目标变量进行分类,在默认设置下,它不会停止,除非它对每个类别进行了完美的分类。这使得树过度适应所提供的数据,并且模型在测试数据集上的准确性将会很低。让我们用一个数据集来验证这一点。我们将使用皮马印第安人糖尿病数据集。
决策树的准确性:
作者图片
决策树的打包
正如我们之前讨论的,bagging 应该在不增加偏差的情况下减少我们预测的方差。这一特性的直接影响可以从预测准确性的变化中看出。装袋会让训练精度和测试精度的差异变小。我们可能不会总是观察到训练精度的变化,但是在这种情况下,测试精度总是更好。让我们检查一下装袋对数据集的影响。
作者图片
这个结果证明了我们的观点!装袋提高了高方差模型的性能!
低方差模型—简单线性回归
到目前为止,我们在本文中讨论的一切都是已知和直观的,但是当我们试图在简单线性回归这样的低方差模型上使用 bagging 时会发生什么呢?让我们通过演示每个袋装模型会发生什么来探索这个场景。我们可以直观地宣称,由于 bagging 只影响高方差模型,它应该对有偏模型没有影响。我们将在文章的其余部分验证我们的假设是否正确。
我们将使用金县房价数据集。我们只使用一个变量来简化可视化。让我们看看 price 和 sqft_living 之间的散点图,以大致了解它们之间的关系,并在此基础上建立一个简单的线性回归模型。
作者提供的图片
这种情况下简单线性回归模型的准确性:
作者图片
简单线性回归装袋
在讨论“简单线性回归装袋的奇怪案例”之前,让我们快速检查装袋简单线性回归后的准确性是否提高或甚至保持模型性能不变。
作者图片
尽管打包了 200 个简单的线性回归模型,RMSE(均方根误差)还是下降了 2.7 个百分点!简单线性回归的有偏性是其背后的原因。我们观察到 RMSE 的变化非常小,因为我们的模型能够很好地捕捉数据集的趋势。sqft_living 和价格之间的相关性为 0.7,简单线性回归模型捕捉了变量之间的线性关系。如果简单线性回归的相关性较低,RMSE 的差异会更大。让我们在下一节讨论为什么。
为什么简单线性回归对装袋效果不好?
简单线性回归是一种有条件偏差的模型。即当变量之间存在明确的线性关系时,该模型可以被认为是稳定的。在这种情况下,即使我们对其使用 bagging,模型的准确性也不会降低。当变量之间的这种关系改变时,简单线性回归试图创建一条直线来捕捉数据的趋势。在这种情况下,单个袋装模型的偏差会增加。
由于我们的变量之间的相关性是 0.7,它不是完全相关的,但它足够好,在这里使用简单的线性回归是有意义的。这就是为什么当我们在 RMSE 装袋时,它没有大幅度下降的原因。bagging 技术创建多个线性回归模型,并取其预测值的*均值。所有这些点将位于回归线上,该回归线可以通过取每个模型的截距和系数的*均值来产生。让我们将*均回归线的预测与最终的袋装预测进行比较。
作者图片
该图中的每条灰线代表单独的简单线性回归模型。它们的偏差高于直接从原始数据集获得的回归线,因为 bootstrap 样本中存在许多重复点。这使得一些点比其余的点更有影响力。这导致*均回归线偏离了我们在没有装袋的情况下可以获得的回归线。
这意味着我们假设 bagging 对高偏差模型没有影响是不正确的!Bagging 确实会影响具有高偏差的模型,但它反而会降低其准确性。这是不是意味着对有高偏差的模型进行打包,总会得到比我们从原始模型中得到的结果更差的结果?让我们再看几张图来总结一下。
引导样本数= 10。作者图片
引导样本数= 100。"作者图片"
引导样本数= 200。作者图片
我们观察到,随着自助样本数量的增加,范围、标准偏差会缩小。RMSE 中值也向简单线性回归线的 RMSE 移动。这表明袋装预测越来越接近简单的线性回归预测,而没有偏离太多。
结论
从这篇文章中可以得出以下几点:
- 在高方差模型上装袋:在不增加偏差的情况下,模型的方差会减少。这种模型的性能会更好,所以建议装袋。
- 对高偏差模型进行 Bagging:与没有 bagging 的模型相比,模型的准确性总是会下降。查看上面的直方图,我们可以得出结论,装袋精度随着装袋模型数量的增加而增加,并且随着 n 达到无穷大,装袋模型的精度将等于直接模型的精度。由于在有偏差模型的情况下,模型的准确性不会增加,因此不建议使用 bagging。
本文的重点是展示当我们使用 bagging 中方差较低的模型时会发生什么。目的是让读者直观地了解哪种模型适合装袋。
请注意,文章中给出的一些代码可能无法工作,因为 python 中没有这些函数。我不得不从头开始编写代码来展示每个模型的偏*,所以如果你正在寻找代码,请参考这个链接— GitHub
参考
[1] Aishwarya Singh,《集成学*综合指南》(附 Python 代码)(2018)
【2】Daniel t . la rose-Chantal d . la rose,7.5 偏差-方差权衡,数据挖掘和预测分析
【3】Trevor Hastie 等人,8.7 Bagging,The Elements of Statistical Learning
【4】Bradley Boehmke 等人,10 Bagging,Hands on Machine Learning
用 Streamlit 烤面包—
Hojicha 泡制酸面团面包
去拿面包屑!
大家好,让我先说这不是 streamlit 的付费帖子,也不是我的上一篇。我再次写 Streamlit,因为我在那里做了一些工作。
如果你像我一样,在冠状病毒封锁期间,你已经烤了很多。我的旅程始于一月份,当时我在巴黎,在附近的面包店吃到了我有生以来吃过的最好的面包。回来后,我受到启发,自己做了面包。我以前用过商业酵母,但这一次,我打算用酸面团的方法来做更美味的面包。经过一周半的尝试,我终于得到了一个功能启动。遇*巴克斯:
现在,巴克斯很酷,但我们不是真的在这里谈论他。巴克斯帮我做了很棒的酸面团面包,真的很棒。但是做面包可能是一个乏味的过程。这涉及到一点数学,因为你必须知道面包师的百分比,这是一套方便的预设计算方法,可以帮助面包师做出好的面包。让我们看一下,好吗?
一点关于烘焙的科学
你可能意识到了,也可能没有意识到,烘焙更像是一门科学,而不是艺术。你不能反复无常地使用你的配料,否则你的面包会惩罚你的。面包师的百分比有助于我们调整精确的比例,以生产出特定口径的面包。所有的面包都是从面粉、水、盐和酵母开始的。这四种原料以不同的比例混合在一起,可以生产出不同质量的面包。太多的面粉,你最终会做出只适合面包屑的超级厚煎饼。水太多,你会看到一团不会变成面包的汤。盐太多,你会杀死所有的酵母,你不会发酵,你还可能做硬面饼。你明白了。
为了解决这个问题,人们开始使用贝克百分比。这些是使用每种配料的理想比例,稍加调整,就能做出像样的面包。这些百分比是基于面粉的初始数量,一切都从那里开始。
例如,以下是亚瑟王面粉公司关于面包师百分比的一个公式:
来源:https://www . kingarthurflour . com/pro/reference/bakers-percentage
你会注意到面粉是 100%,所有其他成分都是 100%的百分比。盐一般固定在 2%,有些多一些,有些少一些,但我*过的食谱中没有一个超过 2.5%或低于 1.75%。对于发酵面团,一般来说,你可以用酵母代替 25%的成熟发酵剂。所有的面包食谱都会相应地调整,因此,一般来说,面包师们传递的食谱更像是数学公式,而不是实际的食谱。
然而,在这些公式中有一个关键变量是水。水合作用是制作面包的关键。水的存在不仅促进了酵母及其非常理想的副产品二氧化碳的生长,而且对面筋的形成也是必不可少的,面筋有助于捕获酵母产生的气体。一般来说,水合程度越高,你的面筋越有弹性和强度,这增加了你面包中的气泡大小,从而增加了你最终面包的膨松度。如果你喜欢有大气泡的面包,你会想要更高的水分含量,特别是在不揉的食谱中,面筋的发展是非常不干涉的。
为了得到更高的水合作用,你必须计算加入面团的水的百分比。这包括摆弄信封背面的计算,计算出你的开胃菜中有多少水和面粉,将它加回到你的总数中,并找到最终的百分比。这实际上是非常简单的数学,但是当你想要修改食谱的时候,它变得很乏味。为了简化这项任务,我想,为什么不用电脑呢?
终于说到重点了!
首先,我用 Python 写了一个简单的公式。这在 Jupyter 笔记本上很容易做到。任何时候我想修改食谱,只要启动它,输入我的变量,瞧!我有完美的比例。这个公式是这样的:
看,我告诉过你数学很简单。但是我不喜欢做数学,因为犯粗心错误的可能性太大了。这个函数会处理好这个问题,永远不会出错。计算机万岁!我需要做的就是用我的起始面粉重量、我想要的水合百分比和一个增加水合的可选参数(如果我使用全麦,全麦非常渴,所以通常需要增加 5-10%的额外水合)调用函数。
这很好,但唯一的问题是,我必须去我的笔记本电脑,启动 Jupyter 笔记本,手动输入数值。如果我在家计划一个食谱,这没问题,但是如果我想在厨房里做这个呢?此外,我认识的其他人可能想做他们自己的计算,我是否想在每次我想提供一些有用的建议时启动它?
输入 Streamlit。对于那些不了解情况的人来说,Streamlit 正在成为当今创建数据科学应用程序最受欢迎的框架之一。在几个小时内,你可以使用 Python 直接从你的 Jupyter 笔记本上创建一个用于机器学*、神经网络等的应用或前端,不需要额外的工作。我要用它来做面包。
S-S-S-S-stttrreaaaaaammmlitttt!!!!
我们要做的第一件事是把我们珍贵的公式粘贴到一个新的笔记本上。然后,因为这个应用程序将是一个首页,扔在一个标题,和一些介绍性的文字解释我为什么做这个计算器,以及它是如何工作的。
这就行了。正如你所看到的,streamlit 有一个标题功能,可以自动在页面顶部粘贴一个大标题,还有一个 markdown 功能,可以让我们输入文本作为 markdown,这很方便。它会根据屏幕大小自动设置文本换行,所以你不必担心像以前蹩脚的 html 编码那样,大段的文本会超出你的页面大小。
下一步是创建交互式小部件,使拨入菜谱变得容易。我从一个单选按钮开始,询问食谱是否包括全麦。正如我前面提到的,全麦面粉一般比普通白面粉更渴。此外,它的麸皮含量往往会切断面筋,额外的水浸泡或自溶有助于软化麸皮,使其更有利于面筋。第一个单选按钮是为白面粉面团或全麦含量最低的面团预设的。我的开胃菜含有黑麦,但它不是整个面团的重要组成部分,所以我会选择这个选项。如果一个面团含有少于 50%的全麦,他们会选择“少于 50%”选项,如果它含有超过 50%,他们会选择“超过 50%”选项。这个选择之后是 If、Elif 脚本,分别为我们的全麦选项参数增加 5%或 10%的水合作用。
现在我们已经建立了变量,下一步是创建一个滑块来设置面粉重量和水合百分比变量。我更喜欢在这里使用滑块,而不是让用户手动输入金额,因为它允许我控制用户的错误。无论是我自己还是用户,在面对空白字段时,都不必担心输入错误或不确定性。只需滑动你的面粉重量,你想要的水合百分比,它会照顾自己。可以想象,该公式可以处理滑块设置的重量和百分比,但大多数家庭烘焙师不需要每批烘焙那么多。1000 克面粉足够做两个大面包,足够 4 个人吃一天。下面是代码:
st.slider(最小值、最大值、起始值、增量)
所以现在我们已经建立了一个方便易用的应用程序来设计我们自己的酸奶配方。这是我们最后一页的样子!
我已经把它上传到 Heroku,所以每个人都可以使用它,它是每个人都可以使用的快速参考。对于在厨房外工作的人来说,它也是移动友好的。
可以在这里找到 app 。请试运行一下,让我知道你的想法!祝你烘焙好运!
*衡数据扩充的正则化效果
利用卫星图像上的图像分割应用程序来识别水体,通过数据扩充来*衡过拟合和欠拟合的需要。
数据扩充的效果
在训练神经网络时,数据扩充是最常用的预处理技术之一。“增强”这个词的字面意思是“在尺寸或数量上变得更大的行为或过程”,概括了这种技术的结果。但是另一个重要的影响是它增加或扩大了数据的多样性。多样性的增加意味着,在每个训练阶段,模型都会遇到不同版本的原始数据。
按作者
为什么我们需要数据的这种“增加的多样性”? 答案就在机器学*的核心宗旨——偏差-方差权衡。更复杂的模型,如深度神经网络,具有较低的偏差,但存在较高的方差。这意味着,这些模型过度拟合训练数据,并会在测试数据或数据上表现不佳,这是他们以前从未*过的。这将导致更高的 预测误差。因此,通过使模型在 一般化 时变得更好,来自数据扩充的增加的多样性减少了模型的方差。
对于图像,一些常*的数据增强方法是截取部分、放大/缩小、沿轴旋转、垂直/水*翻转、调整亮度和绝对强度。音频数据的数据扩充包括添加噪声、改变速度和音调。
虽然数据增强可以防止模型过度拟合,但一些 增强组合实际上会导致 拟合不足。这降低了训练速度,导致可用处理时间、GPU 配额等资源的巨大压力。此外,该模型无法学*足够多的信息来给出准确的预测,这再次导致高预测误差。在这篇博文中,我们以卫星图像的语义分割为例,来看看数据增强的不同组合对训练的影响。
关于数据集
这个 Kaggle 数据集给出了来自哨兵 2 号的卫星图像及其相应的分割水体的遮罩。使用归一化差异水指数或 NDWI 计算掩膜。在数据集中总共 2841 幅图像中,分别为训练集提取了 2560 幅,为验证集提取了 256 幅,为测试集提取了 25 幅。整个分析和建模是在 GPU 支持下在 Google Colab 上完成的。
U 网的结构
简而言之,U-NET 是一个自动编码器,具有从编码器中的每个卷积块到解码器中其对应部分的剩余或跳过连接。这导致了对称的“U”形结构。这篇文章从原始论文开始,对 U-NET 的结构给出了全面的逐行解释。
我们使用稍微修改的 U-NET 版本,如下所示。
所使用的 UNET 块的快照(由作者提供)
看看数据扩充的不同案例
在 Keras ImageDataGenerator 的帮助下,我们探讨了 5 种不同的数据增强情况。我们想看看增强如何导致训练期间过度适应或适应不足。因此,为了对 5 个案例进行比较,使用了培训&验证期间的准确度和损失;其中二进制交叉熵作为损失函数。
在处理语义分割时,需要记住的重要一点是将相同的增强应用于图像及其相应的遮罩!
在所有 5 种情况下,图像和蒙版的像素值都以 1/255 的因子重新缩放。验证和测试集中的所有图像及其遮罩也被重新缩放。
案例 1: 这是基础案例。只有图像及其遮罩的像素值被重新缩放。没有应用任何增强。这个案例产生了一个方差最小的训练集。
案例二:除了重新缩放,还随机垂直或水*翻转图像及其蒙版。
情况 3: 对于这种情况,重新缩放、随机垂直或水*翻转以及[-20,20]度之间的随机旋转被应用于图像及其相应的遮罩。
情况 4: 图像和它们对应的蒙版沿着宽度和高度以因子 0.3 随机移动。
情况 5: 使用因子 20 将透明变换随机应用于图像及其相应的遮罩。它们也在范围[0.2,0.5]之间随机放大。
同一图像及其遮罩上的不同类型的增强(由作者提供)
结果的比较
在所有 5 个案例中,模型被训练了 250 个时期,批次大小为 16。Adam 优化器的学*率为 0.00001,beta 1 为 0.99,beta 2 为 0.99。在下面的图表中,我们可以看到,每个数据扩充案例都为相同的模型提供了不同的性能,这些模型在相同的优化器初始状态下接受了相同数量的时期训练。
训练历史的情节(作者)
基准案例在训练准确性和损失方面表现最佳。然而,这可能意味着过度拟合。另一方面,第三、第四和第五种情况的表现更差。这三种情况的训练准确度没有超过 80%,训练损失没有低于 0.1。这可能意味着不合身。在第二种情况下,数据增强由随机翻转图像及其相应的遮罩组成,这似乎显示了*衡的性能。尽管它的表现比基本情况稍差,但它比最后三种情况具有更高的准确性和更低的损失。
验证历史图(按作者)
验证的准确性和损失,显示了类似的趋势。最后一种情况在这两个指标上表现最差。仔细观察我们会发现,案例 3 和案例 4 在损失方面表现出与训练相似的性能,但验证准确性略高于训练。这表明不合适。对于基本情况,验证损失和准确性比它们的训练对应物差得多,这再次指向过度拟合。虽然我们看到第二种情况的验证准确性和损失波动非常大,但*均来看,它似乎是五种情况中表现最好的。
从这四个图中,我们还可以看到,对于相同数量的时期和相同的优化器初始状态,在训练期间,每个数据增加的情况都收敛在不同的点。这几乎就像 每一个案例都遵循着一条独立的轨迹 。
下表显示了训练和验证的最大准确度和最小损失。该表支持从图表中得出的结论。第二种情况似乎很好地*衡了训练中的过度适应和欠适应。
按作者
对 5 种情况的测试图像的预测
我们在使用 3 幅测试图像的五个案例中的每一个案例中看到了卫星图像中水体的预测分割。再次值得注意的是,使用 5 个不同的数据扩充组合训练的相同模型为每个测试图像预测了 5 个不同的图像。
应注意的是,测试图像在格式方面与基础案例最为相似,因为基础案例没有使用增强。因此,对于所有三个图像,基本情况模型能够分割水体的整体形状。然而,案例 2 也能够捕捉微小的边缘。这证实了我们从图表中得出的结论,即基本情况模型略微超过了训练数据(由于方差最小)。
按作者
情况 3 和 4 的性能随着每个测试图像而变化。情况 5 给出了所有三幅图像(尤其是第二幅和第三幅图像)的最差预测。这可能意味着,为了在这样的数据集上训练该模型,改变绝对强度或放大太多可能会导致糟糕的预测结果。这可以归因于这样一个事实,即模型欠拟合训练数据,一个非常高的方差。
按作者
按作者
最后, 又回到了核心原则——*衡偏差和方差 。虽然数据扩充确实具有显式的正则化效果,但利用它实际上会导致模型学*不足,从而导致预测结果不佳。因此,我们可以看到,有必要尝试不同的数据扩充组合,以找到最适合问题陈述数据集的组合。
完整代码可以在Github上找到!
作为数据科学家*衡理论和实践
推论和发现之间的权衡
照片致谢: Unsplash
理论和实践在人类努力的地图上是一条双行道。许多发现和发明都是偶然和修补的结果,而不是根据基本原理进行的预测和设计。蒸汽机早于热力学定律,空气阻力和帆自古以来就为人所知,但对空气动力学的正式描述出现得要晚得多。
另一个方向也有一些。T4 希格斯玻色子 T5 在被实验观测到之前就被预言了。在爱丁顿的远征之前,广义相对论在很长一段时间内仍然是一个理论。因此,重要的是要认识到这两种方法都是我们寻求知识的重要工具。
机器学*的快速发展归功于这两种方法,但它是 2017 年激烈辩论的主题,一个小组将这个主题比作炼金术,并很快被反驳说:
“将太多精力从尖端技术转移到核心理解可能会减缓创新。
这不是炼金术,这是工程学。工程很乱”
一方认为实践者“操之过急”,而理论家则被批评为“把婴儿和洗澡水一起泼出去”。
根据基本原则构建的领域具有“可解释的失败”的优势——这是生产逐渐可靠的系统所需的关键原则,也是每个工程领域努力的目标。
但是当我们评估不使用它的成本时,实用方法的重要性就凸显出来了。在某些情况下,如果人们坚持要有一个公理化的描述,整个研究领域就不会开始——现代飞机设计的关键贡献者计算流体动力学,为完全依赖尚未解决的千年问题的一面提供了一个典型的例子。
机器学*的中间立场后来被澄清,并开始讨论更好的实践。特别强调了经验评估的标准,无论环境如何,都必须遵循这些标准。
作为一名数据科学家,在执行分析时,有哪些要点[1]需要牢记在心?
- 分享您的调整方法 应该对所有模型(包括基线和共享模型)执行所有关键超参数的调整(使用既定方法)。
- 切片分析 对完整测试集的准确性或曲线下面积(AUC)等性能测量可能会掩盖重要的影响,例如在一个区域质量提高,但在另一个区域质量下降。根据不同维度或不同类别的数据分解绩效指标是全面实证分析的关键部分。
- 消融研究
测试模型架构中的每一个组件从之前的基线单独或组合变化。 - 使用测试分布之外的数据 对模型行为的理解应该由测试分布之外的数据提供信息。例如,对于来自不同人口分布的用户的数据,模型的表现如何?
- 报告负面结果 发现并报告新方法的表现不如先前基线的领域。会有这样一个地区是因为没有免费的午餐。
请注意,任何用于解决现实世界问题的机器学*框架,其核心都是“模型”——区分好的模型已经在这个博客中讨论过了。
非常感谢下面这篇文章开启了这个方向的对话
[1]d .斯卡利,Snoek,j .,Wiltschko,a .,& Rahimi,A. (2018)。赢家的诅咒?关于速度、进度和经验主义的严谨性。
此外,请务必查看以下关于此主题的视频
[2] 深度学*的认识论
[3] 深度学*简介和“炼金术”之争
运动中的机器学*。
快速浏览自动球检测的可用解决方案
🚩 目标
我们希望评估在体育赛事中检测球的最快方法,以便开发一种体育人工智能,而无需在技术或开发人员上花费一百万美元。 我们很快发现,探测球是开发一个健壮的体育 AI 的关键组成部分。
(我不是我团队中的技术人员,这意味着这篇文章中提供的观点不会让你深入了解任何算法或神经网络)。
🚩你为什么要关心?为什么是舞会?
如果你是在人工智能运动利基完全相关 为你 了解球探的艺术状态,这个物体永远是任何运动的主要关注中心。如果你能探测到球(即使是在高速下),那么你就能探测到比赛中更容易的关键事件、度量和更多有用的信息。
🚩 玩家呢?
拥有一个成功的体育人工智能是一套出色的计算机视觉检测的结果,现在有许多可用的神经网络擅长检测人体(例如 OpenPose ),所以球员将很容易被检测到,但球却不容易..更不用说在高速下… 这就是为什么我们创建这个帖子来评估最快的球探方法。
仅仅能够探测到球不会带你去那里但是我们相信,使用一个好的球探测器和来自预训练神经网络的真人探测器是最快的开始方式。
简介:跟踪和检测运动物体
正如我们之前所说的检测 和 跟踪移动物体是人工智能在这个领域取得成功和发展的关键任务。运动相当于运动,人和物体以不同的速度和方向运动。
跟踪移动物体并对其进行分析的能力起着至关重要的作用。对我们来说,开发并教会一个人工智能去观看一场足球比赛并检测比赛中的元素或事件听起来像是一个简单的任务,但实际上非常具有挑战性..
这里有几个原因
有时,即使是人类也很难理解复杂的体育比赛中发生了什么。看看 2010 年世界杯赛场上发生了多少疯狂的事情。很难注意到苏亚雷斯实际上是用手触球来阻止进球。对加纳来说幸运的是,裁判发现了这一点,并给了他们点球和最后一次晋级半决赛的机会。
- 相机不断地*移、变焦,有时倾斜,有时从一个完全不同的角度回放,我们的大脑非常善于否定这种运动,以至于我们甚至没有注意到它。
- 以不同的速度和不可预测的轨迹向各个方向移动的物体和人的数量
- 背景中混有球员和球,物体和外形几乎相同的人
- 假阳性,游戏外的相同物体(板凳上穿着相同服装的球员,游戏外的运动球与“游戏中”的球相同)
但是我们人类在这项任务中表现出色!
或者迷失在人(球员)和物体(球、网等)的快速且有时无规律的运动中。人工智能很难与人类竞争。
我们开始吧!—我的球探之旅
我的目标是尝试我在谷歌搜索 5 小时内遇到的球探测器让这个实验非常简单,没有人工智能行业的内部观点。
为了做到这一点,我使用了一种“即插即用”的方法,我不修改我找到的检测器和神经网络的代码,我只是下载并运行我的本地示例,只做了很小的修改。
我成功地想在下面的视频中跟踪球,当然我的期望不是太高,我意识到球移动得难以置信的快..
让我们看看发生了什么!!
这是我将使用 3 个球检测器选项进行分析的视频。
乌拉圭 vs 加哈纳[2010 年南非世界杯四分之一决赛]
1st — PyImageSearch,OpenCV 球检测器
好得难以置信!我搜索的第一个结果!
📹以 32fps 的速度在 CPU 上运行🤯
✅实时功能。
参考链接源代码:
https://www . pyimagesearch . com/2015/09/14/ball-tracking-with-opencv/
用和 PyImageSearch 进行球检测和跟踪。
这篇 PyImageSearch 文章描述了一种非常简单的检测和跟踪网球的方法:只需在图像上寻找一个绿色区域,然后找到该区域的封闭圆。轻松点。
报告的结果显示,球实际上被很好地跟踪,即使被手部分遮挡,它甚至以 32 FPS 的速度运行,这是非常高的,并允许实时检测。
到目前为止还不错,完全符合我的需求,所以我需要在我的视频上试一试!
这是应用该检测器的结果。
这里做个小澄清: 我们确实把颜色检测器从绿色改成了白色,以便尝试检测足球,因为被设置为绿色。
根本不起作用,它与屏幕上的其他白色物体混淆了,球从未被检测到或跟踪到。
第二个检测器 2(来自脸书的预训练神经网络)
📹在 GPU (Nvidia GTX 1060Ti 6Gb Ram)上以 2 fps 运行,
❌ 非实时能力
参考链接源代码:
https://nol.cs.nctu.edu.tw:234/open-source/TrackNet/
我不拥有这个图像的权利。摘自侦探 2 Github
在第二个选项中,我将尝试实现一个由脸书提供的神经网络,该网络已经用大量对象(包括运动球)进行了预训练。我对“开箱即用”的结果很感兴趣。另外,我想看看它是否能够探测到玩家的身体。
这是应用该检测器的结果:
探测器 2 的结果对球来说不是很好,但对球员来说却很棒。我不拥有这个图像的权利。
球员们都被完美地探测到了。关于球,它在几帧内被探测到但这是我第一次看到它被探测到!
只有静止或缓慢运动时,才能以良好的精度检测到球对象。
我们发现当球处于静止位置时,它能够被探测器 2 检测到,并且具有高置信度得分。
但是这种预先训练的神经网络对于像球这样快速移动的物体有问题。
这让我想到了最后一个实验,一个定制的跟踪器,特别是基于热图解决快速移动的物体这下一个发展是有希望的,因为对网球的近乎完美的检测(这是一个更小的球,移动更快!)
第三轨道网
📹在文档中说明它能够以 22fps 的速度运行!允许实时能力但不是那么正确..
在我的 GPU 上(英伟达 GTX 1060Ti 6Gb Ram) 它以 2 fps 的速度运行..
没有实时能力。
参考链接源代码:
https://nol.cs.nctu.edu.tw:234/open-source/TrackNet/
这是我跟踪球的最佳选择,尽管探测是在网球上我相信它可以更容易地探测到一个更大的球,并且永远不会以那么高的速度运行,但是…
这看起来很适合我们的提议,小网球被完美地检测和跟踪。我不拥有这个图像的权利。摘自 TrackNet Github
应用该检测器的结果:
我错了,结果很糟糕 …尽管与 PyImageSearch 检测器相比,足球的检测有所改进,但帧中有太多的误报…这意味着 TrackNet 即使在根本没有球的情况下也能检测到球…
此外它以 2 fps 运行,而不是文档中提到的 22 fps ,这阻碍了实时分析和检测的可能性。
一个很大的优势是,这个 TrackNet 神经网络在如何用你自己的数据训练方面有很好的文档和建议。这可能是解决足球上的球检测的一个解决方案,但这显然不是一件容易的事情。
如果任何人有足球数据集(真实的和/或合成的),我们有兴趣合作训练这个神经网络或开发一个定制的解决方案,请发送电子邮件到 gcor@eidos.ai
从结果得出的结论
总之,在人工智能运动中,没有“即插即用”的神经网络会把你带到那里,在这个领域没有全局解决方案。这对于那些早期进入这一领域并开发全球解决方案的人来说是一个不可思议的优势。这还没有到来..
但是,即使没有全球解决方案,每个不同的情况都可以用不同的方法来解决,为每个问题创建定制的解决方案。
这就是为什么你需要联系一个团队来开发这种类型的人工智能。
如果你有兴趣与我们合作或建立你的人工智能。
伸手!
我们是一家专注于机器学*,特别是计算机视觉的软件公司,你可以通过 info@eidos.ai 联系我们,我们的网站是https://eidos . ai
敬请关注我们下个月在 medium 上的下一篇文章!
用 OpenCV 和 Tensorflow 实现排球中的球跟踪
运动技术中的计算机视觉和神经网络
介绍
在第一次在运动中应用 AI 的经历之后,我受到了继续下去的启发。家庭练*看起来是一个无关紧要的目标,我的目标是团队合作。
人工智能在体育领域是一个相当新的事物。有几个有趣的作品:
我是个打排球的大粉丝,那就说说最后一个参考吧。这是一个分析当地业余联赛的奥地利机构的网站。
有些文档需要阅读,更重要的是——打开视频数据集。
排球是一项复杂的运动,有许多不同的方面。所以我从一个小但非常重要的东西开始——球。
跟踪球是一项非常著名的任务。谷歌给出了很多链接,但其中许多只是一个演示。显然,在摄像机前识别和跟踪颜色不同的大球无法与真实游戏球检测相比,真实游戏球检测中的球很小,移动很快,并融入背景中。
最后,我们想得到这样的东西:
开始之前,让我们注意一下视频数据集的一些细节:
- 摄像机是静态的,位于球场后面
- 技术水*允许自由看球(职业选手击球太狠,没有电视回放几乎不可能看球)
- 不幸的是,球的颜色,蓝色和黄色,与地面没有太大的对比。这使得所有基于颜色的方法变得毫无意义
解决办法
到目前为止,最明显的方法——用颜色——不起作用,我用了一个事实,球在移动。然后让我们找到移动的物体并捡球,听起来很容易。
OpenCV 包含检测移动物体和背景移除的工具:
mask = backSub.apply(frame)
mask = cv.dilate(mask, None)
mask = cv.GaussianBlur(mask, (15, 15),0)
ret,mask = cv.threshold(mask,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)
还有这样的图片:
转化为:
在这个例子中,球在顶部,人的大脑和眼睛可以很容易地发现它。我们是怎么决定的?从这幅图中可以推断出一些规律:
- 这个球是一团
- 这是图片上最高的斑点
第二条规则不太管用。例如,在这张图片中,最高的斑点是裁判的肩膀。
但是最高斑点方法为进一步的步骤提供了初始数据。
我们可以收集这些斑点,并训练一个分类器来区分球。
这个数据集看起来像这样:
在人工智能方面——它是彩色图像的二进制分类,非常类似于猫对狗挑战。
有许多方法可以实现,但最流行的方法是用 VGG 神经网络。
一个问题-球图片非常小,多个卷积层不适合在那里。所以我不得不把 VGG 切割成一个非常简单的建筑:
model = Sequential([Convolution2D(32,(3,3), activation='relu', input_shape=input_shape), MaxPooling2D(), Convolution2D(64,(3,3), activation='relu'),
MaxPooling2D(),
Flatten(),
Dense(64, activation='relu'),
Dropout(0.1),
Dense(2, activation='softmax')
])
model.compile(loss="categorical_crossentropy", optimizer=SGD(lr=0.01), metrics=["accuracy"])
这个模型很简单,产生的结果一般:大约 20%的假阳性和大约 30%的假阴性。
这当然比什么都没有强,但还不够。
应用于游戏的模型产生许多假球:
实际上有两种假球:
- 他们在随机的时间出现在随机的地方
- 这个模型总是犯错误,把别的东西当成球
轨道
作为下一步,有一个想法,球不是随机运动,而是遵循抛物线或直线轨迹。
对该几何图形上的斑点运动的验证将切断随机和一致的错误。
有一个在一场球赛中记录轨迹的例子:
其中定向路径用蓝色表示,静态路径用绿色表示,随机路径用灰色表示。
只有蓝色的轨迹才有趣。它们至少由 3 个点组成,并且有一个方向。方向非常重要,因为如果下一个点在实际流中丢失并且没有检测到新的路径,则可以预测下一个点。
应用于片段的这一逻辑生成了非常逼真的跟踪:
链接
利用时空上下文改进体育活动识别
乔治·瓦尔特纳、托马斯·毛特纳和霍斯特·比朔夫
在 Proc。DVS-体育领域计算机科学会议(DVS/GSSS),2014 年
自动化体育游戏分析的室内活动检测与识别
乔治·瓦尔特纳、托马斯·毛特纳和霍斯特·比朔夫
在 Proc。奥地利模式识别协会(AAPR/OAGM)研讨会,2014 年
强盗算法
婴儿机器人强化学*指南
多武装匪徒:第三部分
概观
机器人宝宝在商场走失。利用强化学*,我们想帮助他找到回到妈妈身边的路。然而,在他开始寻找她之前,他需要从一组电源插座充电,每个插座的电量略有不同。
使用多臂强盗问题中的策略,我们需要在最短的时间内找到最好的插座,让机器人宝宝充电上路。
这是关于多重武装匪徒的六集系列的第三集。到目前为止,我们已经介绍了在 Multi-Armed Bandits 中使用的数学框架和术语以及Bandit 框架,其中我们描述了我们试图解决的问题,并给出了我们将用来定义和测试问题环境的基本代码块的细节。
现在我们已经有了合适的术语、符号和测试框架,所有缺少的是一个可以解决强盗问题的实际算法,在给出不同奖励级别的行动之间进行选择,以寻找最佳行动。在接下来的几个部分中,我们将研究几个这样的算法,它们的复杂度越来越高。
为了让我们开始,我们将首先看看解决 Bandit 问题的一些最基本的方法,并检查以下算法:
此外,为了让我们评估解决 Bandit 问题的不同方法,我们将描述 后悔 的概念,其中您将您的算法的性能与理论上最佳的算法的性能进行比较,然后后悔您的方法没有表现得更好一点!
bandit 算法和测试框架的所有代码都可以在 github 上找到: Multi_Armed_Bandits
概述
机器人宝宝进入了一个充电室,里面有 5 个不同的电源插座。每个插座返回的电荷数量略有不同。我们希望在最短的时间内给机器人宝宝充电,所以我们需要找到最好的插座,然后使用它,直到充电完成。
这和多臂强盗问题是一样的,除了我们不是在找一个能给出最好回报的吃角子老丨虎丨机,而是在找一个能给出最多电量的电源插座。
贪婪算法
每次我们插入一个插座,我们都会得到一个奖励,以一定数量的电荷的形式,我们得到的每个奖励都可以让我们计算出一个插座的真实输出的更准确的估计。如果我们随后选择具有最高估计值的插座,希望这将是最佳可用插座。
当选择具有最高值的动作时,在时间步' t 【T3 ')选择的动作可以由公式表示:
其中“ argmax ”指定选择动作“ a ”,其中 Qₜ(a) 被最大化。记住' Qₜ(a)' 是动作' a 在时间步 't ',的估计值,所以我们选择当前估计值最高的动作。
当采用这种方法时,选择具有最高估计值的动作,我们称之为“贪婪地选择”,具有最大值的动作(可能不止一个)称为“贪婪动作”。
所有这些听起来像是选择一个好的动作的合理方法,但是有一个主要的缺陷:贪婪算法想要选择具有最佳估计的动作,但是没有提供形成这些估计的方法。它纯粹利用可用的信息,但不做生成这些信息所需的任何探索。
因此,贪婪算法最初是从尚未尝试的动作中进行选择,因此对它们的真实值没有估计。此外,即使选择了一个好的操作,也不能保证这是最好的操作,因为贪婪算法现在已经锁定了所选择的操作,所以不会测试其他操作来确认当前的操作是否是最好的。因此,可以提供更高长期回报的行动将被错过。
乐观贪婪算法
修改贪婪算法的一个非常简单的方法是将初始动作估计值设置为非常高的值,以使其在搜索最优动作时探索可用动作的集合。
在电源插座问题中,如果动作估计被初始化为零,一旦采取一个动作,假设插座返回甚至最小量的电荷,该动作的*均回报将变得大于零。结果,在贪婪算法的眼里,这个动作会比其他所有动作都好,因此会永远是被选中的动作。
相反,如果动作估计被初始化为高于任何可能的套接字输出的值,则当首次尝试套接字时,其*均回报降低。然后,它的估计值低于任何其他值,因此在下一个时间步中不被选择。这导致在第一个' k '时间步中尝试每个套接字(其中' k 是套接字的数量)。
如果我们实现这个算法,我们就能确切地看到发生了什么:
因此,在上面的代码中,我们从我们在[第 2 部分](http://link to Part 2)中定义的标准 PowerSocket 类中派生出一个新的 OptimisticPowerSocket 。唯一的区别是,现在将套接字奖励值的估计值' Q '初始化为所提供的初始估计值,并且将该套接字被尝试的次数' n '设置为 1,以考虑初始化。
如果我们将插座估计值初始化为略高于最大可能奖励值的值,那么这将鼓励在早期步骤中进行探索,而不会花费太长时间来发现哪个插座产生最高奖励。
回顾每个插座的奖励分布的小提琴图,最高输出是大约 16 秒的充电。因此,我们选择了值 20,这比最大可能的奖励稍高,并初始化了所有的套接字估计值,如下表所示。
表 1:使用乐观-贪婪算法对 20 个时间步长的插座回报估计。
表 1 显示了在 20 个时间步长上对 5 个插座中的每一个插座的回报估计。黄色高亮显示的单元显示在每个时间步长选择的套接字。需要注意的要点是:
- 最初,所有套接字的估计值都设置为 20。
- 在每个时间步长,使用贪婪算法选择插座,因此选择具有当前最大估计值的插座。当不止一个插座具有最大值时,随机选择其中一个。可以看出,这发生在前四个时间步长(0–3)。
- 在时间步骤 4,只有一个插座仍未测试(插座 4)。因为它的初始估计值仍然是 20,所以它的估计值是所有套接字中最高的,因此被选为贪婪操作。
- 作为初始化的结果,在前 5 个时间步骤中,5 个插座中的每一个都被尝试一次。这推广到标准的 Bandit 问题,其中在第一个“ k 时间步中,每个“ k ”动作将被尝试一次。
- 在接下来的几个时间步骤(5–13)中,可以看到尝试了各种插座。这是该过程的探索阶段,因为该算法搜索具有最高回报的套接字(要采取的最佳行动)。
- 从时间步骤 14 向前,算法已经锁定到插座 4。这是开发阶段,在此期间发现了最佳行动,并且只有这一行动将被采取。
下图显示了相同的结果(尽管这里显示的是前 30 个时间步)。可以看出,对于每个插座,估计的回报如何从初始值 20 开始,然后随着时间的推移而减少。一旦非最佳插座的估计值低于最佳插座的真实值(如图中的黑线所示),则不会再次尝试。在除了最佳插座(插座 4)之外的所有插座都发生这种情况之后,只有它将被选择,并且只有它的估计值将向真实值收敛。非最优行为的回报估计永远不会收敛到它们的真实回报。
图 3.1:电源插座输出的乐观初始化。
从上面的图表可以看出,乐观贪婪算法工作得很好。不需要太长的时间,次优行动就会被丢弃,焦点就会转向最优行动,如果我们想在最短的时间内获得最大的电量,我们就要采取最优行动。
然而,我们的实验有几个问题:
- 首先,我们作弊了!基于我们对套接字输出的了解,我们选择了最初的套接字估计值 20。在现实世界中,在机器人宝宝的例子中,我们可能没有这方面的知识。
- 其次,我们不太擅长作弊!我们选择值 20,因为它略高于我们在查看套接字输出时获得的最高输出(参*上面 violin-plot 中 socket 4 的输出)。然而,事实证明这并不是最好的价值。
看看下面的图,显示了*均总回报和插座选择百分比,是在一系列初始值的 30 个时间步长内获得的。
图 3.2:乐观初始化。
在上面的图中,有几点需要注意:
- 当初始插座值被设置为零时,*均总回报具有大约 8 的值。在这种情况下,实现的是纯粹的贪婪算法。没有探索,只有剥削,所以会随机选择插座。在我们的例子中,*均套接字输出是 4、6、8、10 和 12,所以*均套接字回报是 8。这也可以从插座选择百分比图中看出。在初始化值为零的情况下,以相等的概率选择所有的插座,并且因为有 5 个插座,所以每个插座以 20%的概率被选择。
- 类似地,对于非常大的初始值,*均总回报开始向值 8 下降,这标志着所有插座以相等的概率被选择的点。在这种情况下,从每个套接字返回的奖励比选择的初始值小得多。因此,估计的回报要花更长的时间才能降到接近真实的最大回报。在此期间,每个插座将有近似相等的真实回报的高估。
- 最大*均总奖励不会在初始值为 20 时出现。相反,如下图 3.3 所示,当初始估计值设置为 11 时,实际上会发生这种情况。这也可以在上面的选择概率图中看到,其中,对于初始值 11,选择最佳插座的概率增加到最大值,而同时对于所有其他插座降低到最小值。由于该初始化值大于除了最佳插座奖励之外的所有值,一旦选择了最佳插座,其估计奖励将被设置为高于所有其他值(假设其返回接近其*均奖励值),因此它将被贪婪地选择用于所有剩余的时间步骤。因此,最佳套接字只需要测试一次,使其成为贪婪操作。
图 3.3:乐观初始化——*均总报酬与初始值。
乐观贪婪算法是一种在测试早期鼓励探索的简单方法。最初将尝试所有动作,并且如果使用合适的初始化值,该算法将快速丢弃非最佳动作并聚焦于最佳动作。然而,如上所示,一个选择不当的初始值会导致次优的总回报,如果事先不知道可能的回报范围,就很难选择最佳的初始值。
另一个主要缺点是,探索局限于最初的时间步骤,将其应用限制在 静止 问题上,其中每个行动的回报从不改变。它不适合 非*稳 的情况,在这种情况下,由于缺乏持续的探索,行动奖励会随时间而变化。
ε-贪婪算法(ε-贪婪)
正如我们已经看到的,一个纯粹的贪婪策略有很高的风险选择一个次优插座,然后坚持这个选择。结果就是永远找不到最好的插座。
克服这个问题的一个简单方法是引入探索元素。这正是 Epsilon-Greedy 所做的:
- 默认情况下,行动是贪婪地选择的。具有最高估计奖励的动作是所选择的动作。
- 然而,在每个时间步长,可以从所有可能动作的集合中随机选择一个动作。以概率'ε'(ε)选择随机动作。
以这种方式,探索被添加到标准贪婪算法中。随着时间的推移,每一个行为都将被反复取样,以给出对其真实回报价值越来越准确的估计。
实现ε-贪婪策略的代码如下所示。注意,这改变了 socket tester 类的行为,修改了它在可用套接字之间的选择方式,而不是对实际套接字的改变。
在每个时间步' select_socket '被调用。如果随机值' p '小于ε,则将选择随机动作,否则将选择具有最高当前估计回报的插座。
查看下图,可以看出 ε 的值如何影响对套接字问题的探索和利用:
图 3.4: Epsilon-Greedy —每次运行 100 个时间步。
- 当 ε 值为零时,这就是贪婪算法。每个插座以相等的概率被选择。没有插座是随机选择的,也没有探索。
- 随着 ε 的增加,行动的随机选择也增加,因此,探索也增加。最初,这导致以增加的频率定位和选择最佳插座。与此同时,非最佳插座开始被较少地选择。
- 最佳插座的选择,以及*均总奖励的相应增加,持续到大约为 0.2 的 ε 值。这一点代表了勘探\开发权衡的顶峰。探索是寻找最好的行动,而开发是选择这个行动。
- 在选择最佳插座的高峰之后,勘探和开发之间的*衡开始向有利于勘探的方向转变。随机选择插座的可能性越来越大。结果,非最佳插座开始被更频繁地选择,因此*均总报酬开始下降。
- 套接字的随机选择继续增加,直到 ε 的值为 1,此时算法已经切换为没有利用的纯探索策略。插座再次被完全随机地选择,并且每个插座以相等的概率被选择,而不考虑其估计的回报。
ε-贪婪策略是在基本贪婪算法中增加探索的一种简单方法。由于行动的随机抽样,所有行动的估计奖励值将收敛于其真实值。这可以从上面显示的最终插座估算图中看出。在 ε 值高于大约 0.2 的情况下,估计的套接字值都与其真实值匹配。这也是 Epsilon-Greedy 算法的缺点:非最优的行动继续被选择,它们的回报估计被改进,即使它们已经被确定为非最优。因此,对最佳行动的利用没有最大化,总的整体回报也低于预期。
遗憾
在插座选择问题中,如果在每个时间步都选择了最好的插座,将获得最大可能的回报。每次选择一个非最佳插座,可以获得的总的可能回报从这个理论上的最大值进一步减少。结果你 后悔 选择了这个插座,反而希望你选择了最好的那个。正如术语后悔所暗示的,你可能无法提前知道你正在做一个非最优的选择,只有在事后你才会意识到你的错误。
尽管您可能无法提前判断是否选择了最佳操作,但您可以计算出您的选择策略与最佳策略相比的表现,在最佳策略中,最佳操作是在每个时间步选择的。这两种政策获得的总回报的差异代表了遗憾。
最佳动作由下式给出:
最佳行动是在每个时间步选择时,最大化预期(*均)回报的行动。
通过在总共' T '个时间步长内,取所实施政策获得的奖励与如果遵循最优政策本应获得的奖励之间的差值,计算遗憾' L ':
因此,对于所有的' T '时间步,最优策略获得了在每个时间步采取最优行动时所获得的期望报酬。由此我们减去从我们的策略所选择的行动中返回的预期回报的总和,其中所选择的行动,以及因此它的预期回报,可以在每个时间步长变化。
通过最小化遗憾的价值,我们可以最大化回报的总和。
ε-贪婪的后悔
ε-Greedy 通过以概率' ε '随机选择任何可能的动作来实现探索。因此,在' T '时间步的过程中,行动的' εT 将被随机选择。
此外,在插座选择问题的一般形式中,有' k '个不同的插座可供选择,其中只有一个会给出最大可能的回报。剩下的' k-1' 插座会给出一个次优奖励。结果,存在选择次优插座的' εT(k-1)/k' 轮。
如果在选择次优行动的几轮中,我们幸运地选择了第二好的插座,其中奖励与最好的插座相差一个固定的量“δ”(delta),那么这将使我们对ε贪婪的后悔最小。这由下式给出:
对于所有其他非最佳插座,所获得的奖励和最佳奖励之间的差将高于“δ”,因此大于或等于符号,因为在这种情况下遗憾将更大。
由于'ε','δ'和' k '都是常数,因此ε-Greedy 的结果最低界限遗憾与时间成线性关系( T '将只是乘以一个常数值)。这意味着在找到最佳行动后,遗憾将继续增加。
这可以从下图中看出。在最初的几个时间步骤之后,通过ε贪婪方法获得的总累积奖励线性增加。然而,由于随机探索仍在发生,这一增长率略低于最佳行动积累其回报的速率,导致后悔随时间线性增加。在运行的早期阶段,遗憾的增加率稍高,这是由于还没有找到最佳动作,因此在这些时间步骤中更有可能选择次优插座。
摘要
在这一部分,我们来看看多臂强盗,我们最终研究了一些可以用来解决强盗问题的算法。
纯粹的贪婪算法,除非它有一些可能的行动奖励的初始知识,并不比简单的随机选择方法好多少。然而,通过一些轻微的修改,例如乐观-贪婪使用大的初始值或者ε贪婪引入随机探索的方法,选择性能可以大大提高。
然而,即使有了这些改进,总回报仍然远远低于最佳水*。乐观-贪婪的表现非常依赖于为其初始奖励选择的值,并且 Epsilon Greedy 继续探索所有行动的集合,即使它已经获得足够的知识来知道这些行动中哪些是不好的行动。结果, Epsilon Greedy 算法被证明具有线性后悔,其中返回的奖励和最优奖励之间的差异继续随着时间线性增加。
在本系列的剩余部分中,我们将看看解决 Bandit 问题的几个更复杂的方法,即 置信上限 算法和 Thompson 采样 ,这两种方法都降低了后悔的程度,从而产生了更高的回报水*。使用这些,我们可以在超快的时间内给机器人宝宝充电!
**< Part 2:** [**The Bandit Framework**](/multi-armed-bandits-part-2-5834cb7aba4b) **Part 4:** [**UCB Bandit Algorithm**](/the-upper-confidence-bound-ucb-bandit-algorithm-c05c2bf4c13f) **>**
万隆市公共交通:服务覆盖分析
万隆附近的街道网络(来源:作者,2020;OpenStreetMap 贡献者)
实践教程
万隆市的公共交通服务覆盖怎么样?万隆市的公共交通网络尚未覆盖哪些区域?
介绍
万隆市是印度尼西亚西爪哇省的省会,也有自己的交通问题。一度被认为是印尼最拥堵的城市之一,亚洲第 14(ADB,2019 )。这是令人震惊的,因为预计雅加达是最拥堵的城市,因为雅加达是首都,也因其拥堵而受欢迎,但雅加达是第二名(例如,椰子雅加达(2019) ,D etik (2019) 等等)。万隆市甚至比孟买还糟糕。这让身为万隆市居民的我思考;是什么让拥堵如此严重?我们如何解决拥堵问题?
万隆市 1 天的时空干扰因子(来源:作者分析,2020;底图:OpenStreetMap 贡献者;CARTO 在知识共享署名-相似分享 2.0 许可下获得许可(CC BY-SA 2.0)
好吧,不可避免的解决办法是市民步行,骑自行车,或者根本不旅行。虽然步行和骑自行车限制了旅行者的耐力,但公共交通成为了解决方案。公共交通支持长途旅行,因为它使用石油/另一种能源,因此节省了旅行者的体力。通过共享空间,公共交通使交通更节能,空间效率更高,这也是它被推广的原因。
在这篇文章中,公共交通成为了讨论的主题。对于市民来说,使用公共交通应该是容易和合理的。如上所述,这种通路依赖于人的耐力,而耐力有限,旅行距离也有限。因此,到公共交通的距离应该尽可能地靠近市民。我敢打赌,你不会乘坐公共交通工具进行 7 公里的步行,但如果只是 300 米的步行呢?缩短距离确保了市民步行或骑自行车到公共交通站的低能耗。在我看来,这是公共交通规划的第一要务。于是我想到一个问题:公共交通的距离分布如何?和万隆市哪个区域距离公共交通最远?
通过了解远离公共交通的区域,我们可以规划或建议一条提供公共交通服务的新路线。通过了解距离的分布,我们可以了解公共交通可达性的现状。这种分布可以与其他城市进行比较,甚至可以与人口数据一起进行分析,以进行进一步的相关性分析,但这是另一篇文章的另一个主题。让我们先把注意力集中在简单的问题上。
本文分为六个部分。
- 首先,简介:你现在正在阅读。这一部分解释了本文的背景;
- 二、目标与方法:本文试图达到的目标和实现的途径;
- 三、关于万隆市:万隆在哪里,与雅加达的关系以及万隆市公共交通的大致描述;
- 第四,分析:进行分析;
- 五、结论:回答主问题,总结结果;
- 六、建议:下一步做什么解决问题,做改进。
目标和方法
本文的目标是描述万隆市到最近公共交通网络的距离,以及识别离公共交通网络最远的区域(****)。
主要的地理分析技术是公共交通网络的欧氏距离分析。该欧几里得距离的结果是连续空间数据(栅格)的形式,因此在统计上可视为间隔/比率数据。与传统/典型统计数据的不同之处在于,它具有空间属性,因此我们可以制作一个关于它的地图。
距离的描述将通过理解由欧几里德距离产生的距离的分布来完成。这将使用直方图分析来完成,我们不需要空间信息。
将使用地图对地理区域标识进行可视化和分析。光栅数据实际上是一幅图像,所以我们可以用一种颜色来显示这些值。为了使官僚机构和政策规划变得具体和实用,我将采用基于最小行政边界单位的分区统计( Kelurahan )。之所以这样做,是因为这种分析产生的栅格的解释性质是模糊的(罗宾逊(2009 ),扎德(1988) )。虽然我必须说,我喜欢模糊地做,因为它清楚地表明它是什么,但要制定一项政策,我们必须明确界限。
此外,上述识别(使用地图)将通过进行 Anselin Local Moran's I(聚类)分析来完成。进行这种分析是为了确定需要干预的战略区域。这种分析考虑到了地理关系,因此可以推断出空间关系和因果关系。别担心,我不会用数学来烦你的。这种分析的目的只是为了识别集群。
论文框架(来源:作者,2020)
关于万隆市
对于这一部分,我将分为两个小节。第一小节是雅加达和万隆;这解释了万隆和雅加达之间的地理特征和关系。第二分段是万隆市公共交通;这是万隆公共交通的简要信息。
雅加达和万隆
的地图爪哇岛的雅加达和万隆建成环境,Landsat 影像的假着色(来源:作者分析,2019;包含来自美国地质调查局 提供的 Landsat-8 图像的修改内容)
万隆市位于印度尼西亚爪哇岛。它是西爪哇省的首府。该市是万隆都市区的核心,包括西万隆县、万隆县和 Cimahi 市。如上图所示,万隆没有雅加达宽。万隆与雅加达的关系多年来一直在加强。连接雅加达和万隆的 Cipularang 收费公路的开发甚至为万隆市带来了更多的交通和投资( Dorodjatoen (2009 ))。下图中的粗线显示了 Cipiularang 收费公路;这条路位于城市的南部。
****万隆市路网图1:275.000 比例尺(来源:作者分析,2020;OpenStreetMap 贡献者许可证(CC BY-SA 2.0)
万隆市公共交通
城市公共交通主要有两种类型:公交网络和小巴网络。小型巴士网络类似于菲律宾的吉普尼。这辆小巴叫“ angkot ”,无处不在。公交网络只是一种在世界任何地方都能找到的典型公交。这辆巴士由一家国有企业 Damri 公司运营。虽然城市间的公共交通是存在的,而且通常由私人公司运营,但这不在本文的主题范围之内。该网络如下图所示。
****图中的图万隆都市区公共交通网络及万隆市行政边界(来源:作者,2020;OpenStreetMap 贡献者许可(CC BY-SA 2.0);路线数据: angkot.web.id
根据经验,万隆系统的一个主要功能是没有公共交通停靠点。你可以在任何地方上船,也可以在任何地方下船,只要你是在线路内上船/下船。公共交通站是有的,但在社会中并没有制度化。
另一种公共交通工具是由 Gojek 和 Grab 提供的出租车和叫车服务(就像优步一样)。打车有它自己的问题,因为政府的政策不承认打车是公共交通。然而,这些非路线基础的公共交通工具不是这个话题的议题。
分析
本节分为两小节:距离分布,和最远距离地理标识。
距离分布
使用欧几里德距离,可以生成分辨率为 10 米的栅格。Y 轴表示细胞的频率。所以,下面的 Y 轴图代表了实际面积,如果我们把它乘以 100 *方米。如图所示,*均距离为 387.4 米。这很好,因为空间规划指导部规定,以公交为导向的开发区距离交通设施 800 米。虽然,我们必须注意,387,4 m 是欧几里得的,不是基于网络分析的。这意味着我们假设人们直接飞往交通网络,因此这种分析更多的是一种近似。然而,仍有一些地区的距离超过 800 米。
到最近交通网络的距离直方图(来源:作者的分析,2020 年)
地理标识欧几里得距离
下面这张地图是欧几里德距离分析的结果。这是一幅分辨率为 10 米的栅格图像,其中包含的数字表示到最近交通网络的距离。较暗的单元格表示离最近的蓝线(公共交通网络)较远。最远距离 3918.99 米。
使用欧氏距离的模糊分析(来源:作者分析,2020;路线数据: angkot.web.id
原始欧氏距离栅格是模糊的。没有界限来决定哪个区域高或者低。当然,我们可以将其与前面提到的 800 米 TOD 距离进行比较,但它截断了远距离的统计特性。例如,这将距离为 900 米的区域视为距离为 3,000 公里的区域。对我来说,更合理的方法是识别聚类。识别集群是有帮助的,因为我们可以创建到达集群的新路径。这是合理的,因为通过将网络的一条线添加到一个集群(假设是一个区域),它会影响集群周围的区域。这有效地缩短了距离。
Anselin Moran 的-I 是一种空间统计方法,用于通过了解数据的空间关系来识别聚类。结果是每个地理单元的分类,有 4 类:高-高、高-低、低-高和低-低。高-高意味着该区域的值(或地理单元)被高值区域包围。高低意味着该区域的值被低值区域包围,以此类推。一个地理单元的低/高通过与其他单元进行比较来统计确定。
在这种情况下,有 3 个识别的聚类:高-高、低-低和高-低,如下图所示。有 8 个高-高区域,有 1 个高-低区域。低-低区域意味着该区域周围的距离很短,这很好,但现在这不是本文的兴趣所在。高低点区域是一个距离网络很远的区域,但它被距离很近的区域所包围。现在,在城市的东部有许多高-高区域,我会说:这些(东部)区域在万隆市的公共交通可达性方面是最差的。****
距离聚类分析(来源:作者分析,2020;路线数据: angkot.web.id
结论
万隆市被认为是印尼最拥堵的城市(亚行,2019)。为此,公共交通不可避免地必须得到促进。其中一个方法是缩短到公共交通的距离。这样,公共交通的可达性可以得到改善,因为人们更容易步行。本文探讨万隆市与公共交通的距离,本文使用的主要方法是进行欧氏距离分析。
首先,本文从欧氏距离的角度分析了距离的分布。这些区域的*均距离是 387.4 米。这很棒,因为它低于空间规划部 TOD 指南建议的 800 米步行距离。但是,直方图显示,有些区域距离最近的公共交通超过 800 米。
其次,本文制作了两张地图:欧氏距离地图,这是一种模糊分析;和聚类图(使用区域统计和安瑟林·莫兰的 I 到最低行政边界(凯鲁拉汉))来支持政策规划。大多数远离公共交通的地区位于城市的东部。这些东部地区对于即将制定的新公共交通计划具有战略意义。
建议
现在我们知道,城市东部的公共交通可达性很差。在未来,这个问题需要通过规划新的路线来解决。必须咨询当地人,以便更好地规划路线目的地。
这项研究只确定了距离,但有些地区不需要公共交通。例如,作为跑道的机场跑道占用了大量土地。这项研究将机场跑道确定为远离公共交通网络的区域,因此我们需要考虑距离背后的土地利用。也许,这些区域无法进入是有原因的。下一步的研究应该考虑土地利用(或土地覆盖)。
最后,下一次分析需要考虑人口因素。就像土地使用一样,也许,有些地区就是没有居民。尽管这些地区远离公共交通网络,但规划一条通往无人居住的荒凉地区的交通路线是不合理的(以确保商业可行性)。除此之外,还有一些地区发展规划考虑在内。
银行机构定期存款预测模型
循序渐进的方法
在 Unsplash 上由 Carlos Muza 拍摄的照片
感谢 10 学院培训项目,通过参与不同的项目,我了解了许多数据科学概念,每个项目都以自己的方式面临挑战。
银行机构定期存款预测模型是我觉得有意思的一个项目。它的主要目标是建立一个模型,预测客户是否会订阅银行定期存款,本文旨在分享我建立模型的一步一步的方法。
内容
- 数据
- 探索性数据分析
- 数据预处理
- 机器学*模型
- 比较结果
- 预言;预测;预告
- 结论
- 继续教育
数据
此项目中使用的数据集(Bank-additional-full.csv)包含银行客户的数据。数据集及其信息可以在这里获得。执行数据分析的第一步是导入必要的库和数据集。
# importing the necessary libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')#importing the dataset
dataset = pd.read_csv('bank-additional-full.csv', sep=';')
dataset.name = 'dataset'
dataset.head()
作者图片
探索性数据分析
EDA 是机器学*模型开发的重要组成部分,因为它帮助我们理解我们的数据并提取有用的*解,这将有助于特征工程。本项目中执行的一些 EDA 包括但不限于以下内容:
- 数据集的形状和大小
# function to check the shape of a dataset
def data_shape(data):
print(data.name,'shape:',data.shape)# function to check the size of a dataset
def data_size(data):
print(data.name,'size:',data.size)# Getting the shape of the dataset
data_shape(dataset)# Getting the size of the dataset
data_size(dataset)
数据集形状:(41188,21)
数据集大小:864948
。shape 返回数据集的行数和列数。
。size 返回数据中元素的数量,即行数乘以列数。
- 信息和统计汇总
# function to ckeck the information of a dataset
def data_info(data):
print(data.name,'information:')
print('---------------------------------------------')
print(data.info())
print('---------------------------------------------')# Getting the information of the dataset
data_info(dataset)
作者图片
。info() 用于获得数据集的简明摘要。
# Getting the statistical summary
dataset.describe().T
作者图片
。describe() 用于查看一些基本的统计细节,如百分位数、*均值、标准差等。数据集中的数字列。
- 唯一值和缺失值
# function to get all unique values in the categorical variables
def unique_val(data):
cols = data.columns
for i in cols:
if data[i].dtype == 'O':
print('Unique values in',i,'are',data[i].unique())
print('----------------------------------------------')# Getting the unique values in the categorical columns
unique_val(dataset)
作者图片
。unique() 返回数据集分类列中的唯一值。
# function to check for missing values
def missing_val(data):
print('Sum of missing values in', data.name)
print('------------------------------')
print(data.isnull().sum())
print('------------------------------')# Getting the missing values in the dataset
missing_val(dataset)
作者图片
。isnull()。sum() 返回数据集中每一列缺失值的总和。幸运的是,我们的数据集没有缺失值。
- 分类变量和数值变量
# Categorical variables
cat_data = dataset.select_dtypes(exclude='number')
cat_data.head()# Numerical variables
num_data = dataset.select_dtypes(include='number')
num_data.head()
分类变量
数字变量
。select _ dtypes(exclude = ' number)返回所有不具有数值数据类型的列。
。select _ dtypes(exclude = ' number)返回所有具有数字数据类型的列。
- 单变量和双变量分析
我利用 tableau(一种数据可视化工具)进行单变量和双变量分析,tableau 的故事可以在这里找到。
- 相关性
# using heatmap to visualize correlation between the columns
fig_size(20,10)
ax = sns.heatmap(dataset.corr(), annot=True, fmt='.1g',
vmin=-1, vmax=1, center= 0)# setting the parameters
fig_att(ax, "Heatmap correlation between Data Features",
"Features", "Features", 35, 25, "bold")
plt.show()
作者图片
相关性显示数据集中变量之间的关系。
- 异常值
Seaborn boxplot 是检查数据集异常值的方法之一。
# Using boxplot to identify outliers
for col in num_data:
ax = sns.boxplot(num_data[col])
save(f"{col}")
plt.show()
上面的代码将数据集中的数值列可视化,并使用四分位间距(IQR)方法处理检测到的异常值。代码可以在这个 GitHub 库中找到。
在 EDA 过程中,我发现了我们的目标变量“y”——客户是否订阅了定期存款?(二进制:“是”,“否”),是高度不*衡的,这可能会影响我们的预测模型。这一点很快就会被注意到,本文给出了一些处理职业不*衡的技巧。
数据预处理
在构建机器学*模型时,对数据进行预处理以获得高效的模型是很重要的。
# create list containing categorical columns
cat_cols = ['job', 'marital', 'education', 'default', 'housing',
'loan', 'contact', 'month', 'day_of_week', 'poutcome']# create list containing numerical columns
num_cols = ['duration', 'campaign', 'emp.var.rate',"pdays","age", 'cons.price.idx', 'cons.conf.idx', 'euribor3m', 'nr.employed', 'previous']
在此阶段完成了以下预处理:
- 编码分类列
机器学*算法只读取数值,这就是为什么我们需要将分类值改为数值。我使用 pandas get_dummies 方法和类型转换对列进行一次性编码。
# function to encode categorical columns
def encode(data):
cat_var_enc = pd.get_dummies(data[cat_cols], drop_first=False)
return cat_var_enc# defining output variable for classification
dataset_new['subscribed'] = (dataset_new.y == 'yes').astype('int')
作者图片
- 重新调整数值列
另一种数据预处理方法是重新调整我们的数字列;这有助于在特定范围内使我们的数据正常化。这里使用了 Sklearn 预处理 StandardScaler()。
# import library for rescaling
from sklearn.preprocessing import StandardScaler# function to rescale numerical columns
def rescale(data):
# creating an instance of the scaler object
scaler = StandardScaler()
data[num_cols] = scaler.fit_transform(data[num_cols])
return data
作者图片
- 指定因变量和自变量
为了继续建立我们的预测模型,我们必须指定我们的因变量和自变量。
独立变量—是被分析过程的输入。
因变量—因变量是流程的输出。
X = data.drop(columns=[ "subscribed", 'duration'])
y = data["subscribed"]
列“duration”已被删除,因为它对输出目标有很大影响(例如,如果 duration=0,则 y =“no”)。
- 分割数据集
在构建机器学*模型时,总是将数据集分为训练集和测试集是合理的,因为这有助于我们评估模型的性能。
# import library for splitting dataset
from sklearn.model_selection import train_test_split# split the data
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.1,random_state=1)
- 降维
在我们有大量变量的情况下,建议考虑通过保留最重要的变量来减少这些变量,有各种技术可以做到这一点,例如:主成分分析、TSNE、自动编码器等。对于这个项目,我们将考虑 PCA。
# import PCA
from sklearn.decomposition import PCA# create an instance of pca
pca = PCA(n_components=20) # fit pca to our data
pca.fit(X_train)
pca_train = pca.transform(X_train)
X_train_reduced = pd.DataFrame(pca_train)
作者图片
- 阶层失衡
如前所述,我们有一个高度不*衡的阶层,如果不加以处理,这会影响我们的预测。
作者图片
在这个项目中,我利用 SMOTE(合成少数过采样技术)来处理类不*衡。
# importing the necessary function
from imblearn.over_sampling import SMOTE# creating an instance
sm = SMOTE(random_state=27)# applying it to the training set
X_train_smote, y_train_smote = sm.fit_sample(X_train_reduced, y_train)
注意:对训练数据使用 SMOTE 为宜。
机器学*模型
咻!,我们终于成功地建立了模型;当试图建立机器学*模型时,数据预处理可能是如此困难。我们不要浪费时间,直接开始吧。
本项目中考虑的机器学*算法包括:
- 逻辑回归
- XGBoost
- 多层感知器
所使用的交叉验证(这是非常重要的,尤其是在我们有不*衡类的情况下)方法包括:
- K-Fold: K-Fold 将给定的数据集分割成 K 个部分/折叠,其中每个折叠在某个点被用作测试集。
- 分层 K-Fold: 这是返回分层褶皱的 K-Fold 的变体。折叠是通过保留每个类别的样本百分比来完成的。
# import machine learning model libraries
from sklearn.linear_model import LogisticRegression
from xgboost import XGBClassifier
from sklearn.neural_network import MLPClassifier# import libraries for cross validation
from sklearn.model_selection import KFold
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import cross_validatemetrics = ['accuracy', 'roc_auc', f1', 'precision', 'recall']# function to build machine learning models
def model(model, cv_method, metrics, X_train, X_test, y_train):
if (model == 'LR'):
# creating an instance of the regression
model_inst = LogisticRegression()
print('Logistic Regression\n----------------------')
elif (model == 'XGB'):
# creating an instance of the classifier
model_inst = XGBClassifier()
print('XGBoost\n----------------------')
elif (model == 'MLP'):
# creating an instance of the classifier
model_inst = MLPClassifier()
print('Multi Layer Perceptron\n----------------------')
# cross validation
if (cv_method == 'KFold'):
print('Cross validation: KFold\n--------------------------')
cv = KFold(n_splits=10, random_state=100)
elif (cv_method == 'StratifiedKFold'):
print('Cross validation: StratifiedKFold\n-----------------')
cv = StratifiedKFold(n_splits=10, random_state=100)
else:
print('Cross validation method not found!')
try:
cv_scores = cross_validate(model_inst, X_train, y_train,
cv=cv, scoring=metrics)
# displaying evaluation metric scores
cv_metric = cv_scores.keys()
for metric in cv_metric:
mean_score = cv_scores[metric].mean()*100
print(metric+':', '%.2f%%' % mean_score)
print('')
except:
metrics = ['accuracy', 'f1', 'precision', 'recall']
cv_scores = cross_validate(model_inst, X_train, y_train,
cv=cv, scoring=metrics)
# displaying evaluation metric scores
cv_metric = cv_scores.keys()
for metric in cv_metric:
mean_score = cv_scores[metric].mean()*100
print(metric+':', '%.2f%%' % mean_score)
print('') return model_inst
评估指标
- 精度:正确预测的数据点个数。对于不*衡的数据集,这可能是一个误导性的指标。因此,建议考虑其他评估指标。
- AUC(ROC 曲线下的面积):它提供了对所有可能的分类阈值的综合性能测量。
- 精度:计算为正确预测的正例数除以预测的正例总数的比率。
- 召回:指被你的算法正确分类的相关结果总数的百分比。
- F1 评分:这是准确率和召回率的加权*均值。
k 倍交叉验证评估指标
分层 K 倍评估指标
比较结果
- K 线折叠 vs 层状 k 线折叠
从上表中可以看出,与 K 倍交叉验证相比,分层 K 倍验证呈现出更好的结果。K 倍交叉验证未能提供逻辑回归和 XGBoost 模型的 AUC 评分。因此,为了进一步比较,将使用分层的 K 倍结果。
- 机器学*模型
从得到的结果来看,XGBoost 被证明是比逻辑回归和 MLP 更好的预测模型,因为它在 4/5 的评价指标中具有最高的百分比值。
预言;预测;预告
XGboost 是性能最好的模型,用于预测。
# fitting the model to the train data
model_xgb = xgb.fit(X_train_smote, y_train_smote)# make predictions
y_pred = xgb.predict(X_test_pca)
结论
这个项目的主要目标是建立一个模型来预测将订阅银行定期存款的客户,我们通过考虑三个不同的模型并使用最佳模型来进行预测,从而实现了这一目标。我们还经历了为模型准备数据和选择各种评估指标来衡量模型性能的严格步骤。
在得到的结果中,我们观察到 XGBoost 是最好的模型,在 4/5 的评估指标中有很高的百分比值。
深造
在这个项目中,我只用了三种机器学*算法。然而,算法如;SVM、随机森林、决策树等。可以探索。
这个项目的详细代码可以在这个 GitHub 库中找到。
我知道这是一个很长的旅程,但谢谢你陪我到最后。我也再次感谢学院和我的同学们给了我参与这个项目的绝佳机会。
参考
银行机构定期存款预测模型
不同机器学*模型在银行定期存款预测中的比较。
蒂姆·埃文斯在 Unsplash 上拍摄的照片
简介
葡萄牙银行的投资和投资组合部门希望能够识别出有可能认购其定期存款的客户。由于营销经理越来越有兴趣仔细调整他们的定向活动,以严格选择联系人,手头的任务是找到一个模型,可以预测哪些未来客户将订阅银行的定期存款。
在这篇文章中,我将讨论数据探索、数据清理、特征提取、处理类别不*衡,以及开发一个强大的机器学*算法来预测哪些潜在客户将使用不同的机器学*库来订阅定期存款。包含所有代码的 Github 库在这里可以找到。
套餐
下面是使用的不同的机器学*和 python 包。
探索性数据分析
探索性数据分析通常是每个数据科学项目的初始过程。通常,对数据进行初步调查以识别模式、异常值、不*衡以及检验先前的假设是至关重要的。汇总统计和可视化主要用于执行探索性数据分析。
"没有常规的统计问题,只有可疑的统计常规."大卫·考克斯爵士
定期存款的认购利率
从上面的输出中,可以提取数据的一些模式。根据潜在客户是否认购定期存款对数据进行分组表明,大多数客户没有认购定期存款,88.7%的客户拒绝认购,而 11.3%的客户接受了认购要约。我们试图预测的这种阶层比例的显著差异导致了不*衡的数据。
一组基于婚姻状况的订阅费率
上面的输出显示了订阅定期存款的客户群和根据婚姻状况拒绝订阅的客户群。
数据预处理
使用 PyOD 清除异常值
异常值是与其他观察值显著不同的数据点,这可能是由于测量中的可变性,或者它可能表明实验误差。在不检查和处理异常值的情况下训练机器学*模型的诱惑通常是失败的原因。数据中的异常值会极大地影响模型的准确性,但是简单地从数据中移除异常值而不考虑对结果的影响是一种不好的做法,因为异常值并不总是一件坏事。
“离群值不一定是坏事。这些只是观察结果,与其他观察结果没有遵循相同的模式。但是异常值可能是非常有趣的。例如,如果在一个生物实验中,一只老鼠没有死,而其他所有的老鼠都死了,那么理解为什么会这样会很有趣。这可能会导致新的科学发现。因此,检测异常值非常重要。”皮埃尔·拉法叶·德·米肖,作家和统计学家。
检测异常值的常*做法是使用箱线图、直方图和散点图。这种方法在大型数据集中可能效率不高。PyOD,python 库有不同的算法,可以用来检测和清除异常值。对于这种情况,我们使用 k-最近邻检测器。
一键编码
数据集通常包含数字和分类变量,但机器学*算法只理解数字而不理解文本,这就是为什么我们需要转换或变换分类变量,这一过程称为分类编码。有两种类型的分类编码:
- 标签编码
- 一键编码
当分类列中的类别包含具有某种顺序或层次结构的数据时,标签编码非常有用。One-Hot 编码的工作方式是,根据列中类别的数量,将要编码的列分成多个列。然后,根据哪一列有什么值,类别被替换为 1 和 0。我们还使用 StandardScaler 来重新调整所有数字列。这是有用的,因为一些变量经常在不同的尺度上测量,并且不会对模型拟合做出同等贡献,这可能导致训练的模型产生一些偏差。
处理不*衡数据
在不*衡的数据集上训练机器学*模型可能会导致不准确的预测。在这种情况下,我们使用随机抽样技术来处理不*衡数据。随机过采样的工作原理是从少数类中随机采样数据,并复制它以创建更多的样本,这个过程一直重复,直到分布相等。
随机采样技术的缺点之一是,它可能会导致过度拟合,因为它会复制现有的少数数据集。
利用主成分分析进行维数约简
降维是一种减少数据集中输入变量或特征数量的技术。更多的输入特征通常会使预测建模任务对模型更具挑战性,这被称为维数灾难。有不同的降维技术,如自动编码器和 t-SNE,这是一种概率技术。对于我们的情况,我们使用主成分分析(PCA)进行降维。PCA 执行数据到低维空间的线性映射,使得低维表示中数据的方差最大化。我们只对特征进行了 PCA,不包括标签。
系统模型化
下面的代码片段显示了我在比较不同建模算法时使用的一种方法。初始化参数时需要四个参数
- 型号类型。对于这个案例,我使用了 XGBoost 分类器、多层感知器分类器、逻辑回归和支持向量机。
- 交叉验证技术,即 k 倍或分层 k 倍
- x 是数据集的特征
- 哪个是标签
不同模型的初始化
结果和结论
在所有选择的模型中,即使使用超参数调整,XGBoost 分类器也具有更高的准确度分数。下图显示了所使用的 XGBoost 模型的不同指标得分。使用分层 k 倍和 k 倍交叉验证时,得分略有显著差异。分层 k 倍比 k 倍有更高的分数。
Accuracy scores of the model: 0.88
Classification report of the model
--------------------------------------
precision recall f1-score support
0 0.89 0.87 0.88 3442
1 0.88 0.90 0.89 3537
accuracy 0.88 6979
macro avg 0.89 0.88 0.88 6979
weighted avg 0.89 0.88 0.88 6979
Confusion Matrix of the model
--------------------------------------
[[2993 449]
[ 354 3183]]
我们的模型的准确率为 0.88,精确度和召回率高于 0.87。
使用 k 倍交叉验证时的 ROC 图显示得分为 0.88。
k 倍 ROC 图
当使用分层 k 倍时,得分增加了 0.01
分层 k 倍 ROC 图
由于 XGBoost 对少数类具有更高的精确度、召回率和 f1 分数,而少数类是潜在客户是否会认购定期存款的更重要的分类,因此银行应使用 XGBoost 模型。通过不同的超参数调整技术,模型可以得到更高的分数。
尊重并感谢我所有的同学和10 学院的工作人员,感谢他们的支持。
参考
k-fold 交叉验证过程是评估机器学*性能的标准方法。
machinelearningmastery.com](https://machinelearningmastery.com/how-to-configure-k-fold-cross-validation/) [## Python -机器学*掌握中的 4 种自动离群点检测算法
分类或回归数据集中异常值的存在会导致拟合不佳和预测性降低…
machinelearningmastery.com](https://machinelearningmastery.com/model-based-outlier-detection-and-removal-in-python/) [## 使用 PyOD 库学* Python 离群点检测的精彩教程
我最近的数据科学项目涉及预测特定商店中每种产品的销售额。有几个…
www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2019/02/outlier-detection-python-pyod/) [## 。神经网络。MLP 分类器-sci kit-学* 0.23.2 文档
sklearn.neural_network 类。MLP classifier(hidden _ layer _ sizes =(100,),activation='relu ',*,solver='adam'…
scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.neural_network.MLPClassifier.html) [## Python API 参考-xgboost 1 . 3 . 0-快照文档
本页给出了 xgboost 的 Python API 参考,更多内容请参考 Python 包介绍…
xgboost.readthedocs.io](https://xgboost.readthedocs.io/en/latest/python/python_api.html) [## 3.2.4.3.1.sk learn . ensemble . randomforestclassifier-sci kit-learn 0 . 23 . 2 文档
class sk learn . ensemble . RandomForestClassifier(n _ estimators = 100,*,criterion='gini ',max_depth=None…
scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html)
依靠人工智能
利用人工智能在新的十年里重塑银行业
我们的银行系统今天面临着日益激烈的竞争。创新服务正在兴起,从而使我们几十年来所熟知的传统银行业慢慢过时。对客户来说,更便宜、更方便的 24 小时自助银行服务似乎成为一种趋势。所有这一切都发生在一个全球环境中,在这个环境中,法规遵从性变得越来越严格,安全风险呈指数级增长。最后,随着交易以光速进行,数据量正以创纪录的速度增长,从而使有效决策变得困难。当然,所有这些目标对传统银行来说可能听起来令人生畏,但在人工智能(AI)的帮助下,它们可以轻松实现。让我们来看看将传统银行转变为金融科技机构的技术。
数字银行助理为用户提供金融指导和访问银行提供的各种服务。人们可以把他们看作是一个个性化的收银员,他们知道每个客户的名字,并随时准备给他们提供他们想要的所有信息。这种系统利用人类语言技术(HLTs ),该技术使用自然语言(例如英语、汉语等)与用户对话。).这项技术极大地提高了用户的整体体验,因为用户与虚拟助理进行交互,就好像他在与另一个人交谈一样。此外,该助理能够追加销售其他银行产品,从而帮助客户探索新的可能性。
客户档案是人工智能可以提供帮助的另一个领域。通过查看人口统计和历史数据,银行可以根据客户的风险状况自动对客户进行分类。然后,顾问可以利用这些信息,根据客户的个人资料,以自动化的方式为客户提供不同的金融产品。使用这种系统的优点是客户不会受到数据引起的偏差的影响。此外,由于人工智能不断更新客户的资料,它可以立即注意到任何增长的风险,并在为时过晚之前向银行发出警报。
合同分析是一项有些重复的任务,需要大量资源。正因为如此,经理和顾问可以将这项任务分配给人工智能助理。光学字符识别(OCR)可用于将文件(打印和手写)数字化,并将其发送至合同分析器。然后,自然语言处理(NLP)模块将解释文本、分析文本并应用业务规则。所应用的业务规则可以不同;从简单的(比如检查复选框的状态)到极其复杂的(比如检查文本背后的逻辑)。人工智能模型使用过去的合同进行训练,从而大幅提高其准确性。像 JP 摩根这样的大公司报告说,使用这种方法;他们设法将每年 36 万小时的工作压缩到几秒钟内完成。一旦系统完成处理,它会以非常高的速度提供带有建议纠正的警报,并由经理或顾问进行审查。
在这样一个竞争激烈的环境中,客户流失是另一个令人头疼的问题。人工智能有利于根据客户与银行的互动(或缺乏互动)来预测客户流失。该系统可以快速分析有关客户的所有数据,做出预测,并创建一个优先客户名单,这些客户可能会终止与该银行的业务。然后,经理可以直接干预客户,希望留住他们,或者至少理解他们为什么选择一家与之竞争的银行。研究表明,获得一个新客户比留住一个现有客户要困难和昂贵得多。在这种情况下,大众营销会失败,因为顾客是如此的多样化,以至于信息无法传递。因此,客户分析和流失预测对于创建针对特定客户的营销计划至关重要。
算法交易利用人工智能技术交易股份、股票等。它通过分析来自不同来源的数据来实现这一点,如过去的历史数据、新闻条目等。做出难以置信的快速决策。在这些数据中发现的模式很难被人发现,或者说一个人不可能迅速处理这些海量信息。当然,计算机可以相当快地自动执行交易,并以闪电般的速度完成买卖。
米歇尔·汉德森在 Unsplash 上的照片
自动化研究工具处理批准或拒绝金融投资所需的背景研究。这项任务对于人类来说非常耗时,但对于人工智能来说,却相当简单。该系统能够对关于个人或公司的信息进行情感分析。它可以检测人们对该实体的看法是消极还是积极,从而为管理者提供关键信息。先进的语言处理技术可以帮助研究人员通过放大关键主题和自动突出特定段落来快速浏览公司的财务报告。
投资的自动估价是人工智能的另一个应用。使用诸如年龄、历史值等各种特征。;该系统可以计算资产的价值。传统上,这种系统最初用于房地产,以计算房屋的估价。然而,金融公司通过查看经济指标、增长预测等采取了类似的方法。以得出最终的估计。
这些只是银行业使用人工智能的几个例子。在未来几年,我们预计会看到更多的创新,涉及运营、营销、销售、客户体验、收入和交易质量等方面。人工智能是一种工具,它将永远改变我们的银行方式,并引领现代银行时代的到来。我们的银行不能停滞不前,否则就会倒闭。正如一句古老的中国谚语所说…
“不要害怕慢慢成长;只怕站着不动。”
本文原载于https://www.businesstoday.com.mt请在下面留下你的想法评论。如果你喜欢这篇文章,请跟我来🐦推特,🔗 LinkedIn 或者😊脸书。
疫情之后人工智能的兴起
towardsdatascience.com](/a-whole-new-ai-world-6a5e9e49aa12) [## 杀死汽车保险商
正如我们所知,人工智能正在如何改变汽车保险
towardsdatascience.com](/killing-the-motor-underwriter-cb11317cda98) [## 在 2020 年推动您的小型企业
毫无疑问,2019 年是人工智能(AI)年。我们听说了很多,但很多人不确定…
towardsdatascience.com](/boosting-your-small-business-in-2020-6ae3529cbfb0)
阿列克谢·丁力教授 是马耳他大学的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他出版了几本同行评审的出版物,并且是马耳他的一部分。由马耳他政府成立的人工智能工作组,旨在使马耳他成为世界上人工智能水*最高的国家之一。*
Python 条形图竞赛动画:新冠肺炎案例
变更数据
条形图比赛 GIF
八个多月来,新冠肺炎已经摧毁了许多国家。100 万病例已经得到证实,而且这个数字每天都在增加。
感谢谷歌为我们公开和免费提供了 Corona 数据集。它使我们有可能做我们自己的与这个疫情相关的分析,例如,创建条形图比赛动画。数据存储在谷歌云*台上,可以在这里访问。
收集数据
首先在bigquery-public-data
数据集中找到名为covid19_open_data
的 BigQuery 表。
新冠肺炎数据集。作者图片
共 45 栏,逐日呈现各个国家(和地区)的电晕案例信息。您可以根据要进行的分析类型,专门选择要下载的数据。例如,我运行下面的 SQL 来检索日期、国家、地区和发生的案例数。
SELECT
date,
country_code,
country_name,
subregion1_name,
COALESCE(new_confirmed,0) AS new_confirmed,
COALESCE(new_deceased,0) AS new_deceased,
COALESCE(cumulative_confirmed,0) AS cumulative_confirmed,
COALESCE(cumulative_deceased,0) AS cumulative_deceased,
COALESCE(cumulative_tested,0) AS cumulative_tested
FROM
`bigquery-public-data.covid19_open_data.covid19_open_data`
查询结果。作者图片
您可以将结果保存到。CSV 文件,稍后使用 Python 打开它。
准备数据
现在,让我们用 Python 来转换数据。首先要做的是打开 Jupyter 笔记本,然后导入必要的包来转换和可视化数据。之后,打开。csv 文件并将其保存为 DataFrame 对象。
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.animation as animation
import numpy as np
import matplotlib.colors as mcimport colorsys
from IPython.display import HTML
from datetime import datetime
from random import randintdf = pd.read_csv ('covid19-20200917.csv')
为了利用数据,我们需要首先了解数据的特征。您可以通过查看数据类型和每一列的值来探索它。
作者图片
从上面的结果中,我们知道在国家代码和子区域 1 名称列中有空值。
就我而言,分析的目的是创建一个从 2020 年初到去年 8 月每个国家确诊病例总数的条形图。我们可以依赖数据集中的三个主要列;日期、国家名称、累计确认。这些列没有空值,所以我们可以继续下一步。
通过使用熊猫,总结每个国家每天的累计确认总数。然后,检查结果。例如,我使用2020-08-31
作为日期参数
df = pd.DataFrame(df.groupby(['country_name','date'])['cumulative_confirmed'].sum()).reset_index()current_date = '2020-08-31'
dff = df[df['date'].eq(current_date)].sort_values(by='cumulative_confirmed', ascending=False).head(15)
8 月确诊病例最多的 15 个国家。作者图片
将数据可视化
然后,我们可以开始使用 Matplotlib 来可视化它。
fig, ax = plt.subplots(figsize=(15, 8))
sns.set(style="darkgrid")
ax.barh(dff['country_name'], dff['cumulative_confirmed'])
作者图片
要创建条形图比赛动画,我们需要用某种颜色将每个国家分组。所以,不管国家的位置在哪里,看它的颜色还是可以追踪到的。
主代码在。ipynb 格式。由于美观的需要,这个特定的功能被分离到一个. py 文件中。
这个方法的主要作用是给每个国家颜色,这个颜色是随机确定的。定义了颜色的变换方式后,我们就可以继续画柱状图了。
主代码在。ipynb 格式。由于美观的需要,这个特定的功能被分离到一个. py 文件中。
在上面的方法中,我们对数据框中的数据进行了排序,因此只有每个日期确诊病例最多的 15 个国家将出现在条形图中。然后,我们给颜色的酒吧和它的属性。对于每个日期,我们提取要在条形右侧强调的月份名称。
条形图设计
如果我们使用2020-08-31
作为日期参数,上面的图表就是 draw_barchart 方法的结果。你可以根据自己的喜好调整代码来装饰条形图。
完成条形图设计后,我们需要做的就是定义将要出现在条形图动画范围内的日期。
dates=pd.Series(pd.to_datetime(df[‘date’].unique()))dates=dates.where(dates < ‘2020–09–01’)dates.dropna(inplace=True)
dates = dates.astype(str)
就我而言,我排除了 2020 年 9 月之前的日期。日期范围如下所示:
日期范围。作者图片
最后,我们到了神奇的部分,动画!我们可以利用 matplotlib.animation 创建一个动画。
import matplotlib.animation as animation
from IPython.display import HTMLfig, ax = plt.subplots(figsize=(15, 8 ))
animator = animation.FuncAnimation(fig, draw_barchart, frames=dates)
HTML(animator.to_jshtml())
瞧啊。这是结果。
条形图竞赛
要将动画保存为 GIF 格式,我们可以使用以下简单的代码行。
animator.save('covid_til_august.gif', writer='Pillow')
结论
有很多方法可以处理数据,因为有很多工具可以支持我们。BigQuery 帮助我们获取和查询数据,Pandas 帮助我们转换和聚合数据,Matplotlib 帮助我们可视化数据。尽管如此,仍有很大的探索空间。
现在,您可以创建自己的条形图并进行自己的分析。你可以在这里看到 Jupyter 笔记本文件的完整代码。快乐尝试,保持健康!
参考
[1] P. Vardhan,用 Matplotlib 在 Python 中进行条形图竞赛(2019),https://medium.com/r/?URL = https % 3A % 2F % 2f pratapvardhan . com % 2f blog % 2f bar-chart-race-python-matplotlib % 2F
[2] G. Berardi,用 Python 创建*滑条形图竞赛(2020),https://www . datasciencecoffee . com/2020-Smooth-Bar-Chart-Race/
与 Plotly 进行条形图竞赛
巴塞罗那最常*的婴儿名字
最近,动画条形图变得非常流行,尽管它们看起来很难创建,但事实是使用像这样的库,它们很容易执行。在这篇文章中,我们将一步一步地解释如何制作一个条形图比赛与plottly来可视化从 1996 年到 2017 年在巴塞罗纳市最常*的婴儿名字。
你想知道这个动画条形剧情是怎么制作的吗?继续阅读🌈
数据集
该数据集可以在巴塞罗那公开数据中找到,包含了巴塞罗那市最常*的 25 个婴儿名字,按性别分类。
[## 巴塞罗那最常*的 25 个宝宝名字,按性别分类-25 _ noms _ padro _ any _ sexe _ 1996 _ 2018 . CSV…
这个数据集包含了出生到出院的 25 个最常*的孩子名字的频率数据
open data-a jument . Barcelona . cat](https://opendata-ajuntament.barcelona.cat/data/en/dataset/est-noms-nadons/resource/e1b5dd1f-a88e-43eb-86d1-d3880d9a6718)
探索性数据分析和数据清理
探索性数据分析包括分析数据集的主要特征,通常采用可视化方法和汇总统计。目标是理解数据,发现模式和异常,并在我们执行进一步评估之前检查假设。
下载完 csv 文件后,我们可以使用Pandas . read _ CSV函数将其加载到 Pandas 数据框中,并使用 pandas 可视化前 5 行。data frame . head方法。
前五排
不合适的数据类型和缺失值是数据集最常*的问题。我们可以使用 熊猫轻松分析这两者。DataFrame.info 方法。此方法提供了数据框的简明摘要,包括每列的数据类型、非空值的数量以及内存使用情况。
信息方法
数据集不包含空值和数据类型是预期的。
如上所示,数据帧包含 5 列:(1) Ordre,(2) Nom,(3) Sexe,(4) Any,和(5) Nombre。巴塞罗那开放数据提供了大部分加泰罗尼亚语的数据集。因此,在开始可视化之前,我们必须将数据集翻译成英语。首先,我们用 熊猫翻译列名。DataFrame.rename 功能如下:
使用的熊猫。DataFrame.columns 属性,我们可以检查翻译是否正确执行。接下来,我们用熊猫翻译列 Sex 的值。DataFrame.replace** 功能。**
翻译数据帧
当检查列名的唯一值时,我们可以观察到多个条目包含尾随空格。
多个条目包含尾随空格
我们删除了 熊猫的尾随空格。串联方法。该方法对 Series 对象的每个元素(列名)调用 Python 函数( lambda x: x.strip() )。
如上所示,尾部空格被成功删除。
数据清理完毕!!👏现在!我们准备好开始条形图竞赛了!
色彩设计
该数据集包含了 25 个最常*的男女婴儿名字。由于我们将制作两个交互式条形图,一个用于女性姓名,另一个用于男性姓名,我们将数据分为两个数据集,如下所示:
女性名字
男性名字
请注意,我们只选择了 10 个最常*的婴儿名字。
接下来,我们将为每个名称分配一种独特的颜色。为此,我们创建了一个函数,它接受系列和 RGB (红、绿、蓝)颜色格式(从 0 到 255 的整数值)的每个参数的最小和最大强度作为输入。该函数返回一个字典,其中键是系列的唯一名称,而值是 RGB 颜色。这些颜色是使用函数 random.randint(a,b) 随机分配的,该函数返回一个介于 a 和 b 之间的随机整数(两者都包括在内)。
利用上面的函数,我们创建了两个字典,一个用于女性名字,另一个用于男性名字。字典的值是字符串( 'rgb({},{},{})' ),因为这是我们稍后将用来给条分配颜色的符号。
女性名字词典
男性名字词典
正如你所观察到的,对于女性名字来说,主要颜色是红色。相反,男性的名字主要是蓝色调。
现在,我们在两个数据框中创建一个名为 Color 的列,使用熊猫为每个名字(根据字典)指定一种颜色。方法如下:
df_man 数据帧前五行
现在,我们准备创建条形图!
条形图竞赛
要制作一个条形图竞赛,首先我们必须创建一系列帧。每个帧包含一年的柱状图(从 1996 年到 2017 年)。
如上图所示,我们使用 plotly.graph_objects 创建了一个条形图。 栏功能(在库中定义)Plotly** 。一个条形图显示了分类变量和数值变量之间的关系。在这个可视化中,每个条代表一个名字( x 轴—分类变量),其高度与婴儿数量成比例( y 轴—数值变量)。条的颜色是我们之前分配给每个名称的颜色。此外,我们在横条上包含一个文本,显示婴儿的名字(轴 x** )和数量(轴 y )。由于我们不想在鼠标悬停在条上时显示任何信息,我们将参数 hoverinfo 设置为等于‘无’。****
我们创建的第二个元素是使用 plotly.graph_objects 的布局。布局功能,这里我们定义了轴、标题、背景颜色等等。可以看出,在处理颜色时, Plotly 不仅支持 rgb 还支持十六进制符号。为了指定背景颜色,我们使用形式为 #RRGGBB 的字符串,其中 RR (红色)、 GG (绿色)和 BB (蓝色)是介于 00 和 FF 之间的十六进制数,代表颜色的强度。
接下来,我们使用 plotly.graph_objects 创建框架对象。框架功能,输入条对象(数据参数)和布局对象(布局参数)。最后,我们将框架对象添加到一个列表中。
在创建了帧列表后,我们准备好使用 plotly.graph_objects 生成条形图比赛图。图功能,提供输入:
- 初始年份的柱状图(数据自变量)
- 初始地块的布局(布局自变量)
- 帧列表(帧自变量)
现在,我们准备创建两个动画条形图!💪
对女孩来说👧
动画条形图-巴塞罗那最受欢迎的婴儿名字
对于男孩来说👦 😃
动画柱状图——巴塞罗那最受欢迎的婴儿名字
录像
一定不要忘了提一下启发我写这篇文章的视频!
阿曼达:)
Python 中的条形码和 QR 码解码器
利用 pyzbar 解码一维条形码和 QR 码
procylink 访客管理系统在 Unsplash 上拍摄的照片
通过阅读本文,您将了解生成不同格式的一维条形码以及快速响应码(QR 码)生成的技巧和诀窍。此外,本教程将概述使用相同的 Python 库解码条形码和 QR 码的方法。之前,我已经介绍过一个关于如何用 Python 生成和解码二维码的教程,Python 使用 OpenCV 解码二维码。在本教程中,我将使用另一个名为pyzbar
的模块进行解码。基于官方文件,pyzbar
是
“…一个使用 zbar 库读取一维条形码和 QR 码的纯 Python 库,zbar 库是一个开源软件套件,用于从各种来源读取条形码,如视频流、图像文件和原始强度传感器。它支持许多流行的符号(条形码类型),包括 EAN-13/UPC-A、UPC-E、EAN-8、Code 128、Code 39、Interleaved 2 of 5 和 QR 码。”
根据我所做的实验,在解码二维码的准确性方面,pyzbar
比python-opencv
表现更好。最重要的是,pyzbar
还能够解码条形码。
让我们继续下一部分,开始安装必要的模块。
1.设置
强烈建议您在继续安装之前设置一个虚拟环境。您可以通过pip install
轻松安装所有模块。
python-条形码
我们的第一个模块是 python-barcode 包,它有助于根据我们指定的格式生成一维条形码。运行以下命令来安装它
pip install python-barcode
默认情况下,结果将被导出为 SVG。您需要安装额外的依赖项,如Pillow
。您可以选择独立安装依赖项,或者与python-barcode
一起安装,如下所示:
pip install python-barcode[images]
二维码
您可以通过以下命令单独安装qrcode
包
pip install qrcode
可选地,您也可以在标准安装中包含Pillow
依赖项
pip install qrcode[pil]
皮兹巴尔
pyzbar
的安装有点复杂,取决于您机器的操作系统。对于 Windows 用户,zbar
DLL 与 Windows Python 轮子一起提供。
对于 Mac OS X,您可以通过以下命令安装zbar
共享库
brew install zbar
如果您使用的是 Linux,应该使用下面的命令。
sudo apt-get install libzbar0
完成后,运行下面的命令来安装pyzbar
Python 包。
pip install pyzbar
事实上,它还支持命令行功能,允许您直接在命令行中运行它。为此,您应该按如下方式安装它:
pip install pyzbar[scripts]
2.条形码生成
在本节中,我们将使用python-barcode
包生成条形码。
支持的格式
在撰写本文时,这个包支持以下格式:
- EAN-8
- EAN-13
- EAN-14
- 刚果爱国者联盟
- 一月
- ISBN-10
- ISBN-13
- 国际标准系列出版物编号
- 代码 39
- 代码 128
- PZN
我将使用 EAN13 格式生成一个新的条形码。结果将是 PNG 格式。
导入
让我们添加下面的导入语句。如果将结果保存为图像,则需要ImageWriter
。否则,它将被默认为 SVG。
from barcode import EAN13
from barcode.writer import ImageWriter
创建条形码并保存为图像
继续在它下面追加下面的代码。因为我们正在编写一个图像,所以您需要将 filemode 指定为wb
。供您参考,EAN13 接受包含 12 位而不是 13 位的字符串。最后一位是校验和,将自动生成。如果您输入的是一个 13 位的字符串,最后一位将被忽略。
with open('barcode.png', 'wb') as f:
EAN13('123456789102', writer=ImageWriter()).write(f)
完整的代码片段如下:
当您运行 Python 文件时,它应该会生成以下图像。
作者图片
3.二维码生成
与条形码相比,QR 码的生成稍微复杂一些,因为 QR 码是二维的。
导入
添加以下导入语句
import qrcode
from PIL import Image
用以下参数创建一个QRCode
对象的实例
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=10,
border=4,
)
version
—控制二维码的大小。它接受 1 到 40 之间的整数。版本 1 由 21×21 矩阵组成。error_correction
—控制用于二维码的纠错。box_size
—控制二维码每个方框的像素数。border
—控制边框的框厚度。缺省值为 4,这也是规范中的最小值。
有 4 个常量可用于error_correction
。可以纠正的错误越多越好。
ERROR_CORRECT_L
—大约 7%或更少的错误可以被纠正。ERROR_CORRECT_M
—大约 15%或更少的错误可以被纠正。这是默认值。ERROR_CORRECT_Q
—大约 25%或更少的错误可以被纠正。ERROR_CORRECT_H
—大约 30%或更少的错误可以被纠正。
继续在它下面追加下面的代码片段。根据您自己的使用案例替换add_data
的输入参数。
qr.add_data("https://medium.com/@ngwaifoong92")
qr.make(fit=True)img = qr.make_image(fill_color="black", back_color="white")
img.save("qrcode.png")
你可以在下面的要点中找到完整的代码。
你应该得到一个二维码一旦你运行代码。我的情况是这样的。
作者图片
一旦你完成了,继续下一部分,开始实现我们的解码器。
4.用 pyzbar 解码
pyzbar
的一个主要特点是直接使用同一个函数进行解码。此外,它支持解码单个图像中的多个条形码或 QR 码。从模块导入decode()
函数,如下所示:
from pyzbar.pyzbar import decode
你可以传递一个PIL.Image
的实例或者一个numpy.ndarray
的实例。您可以使用OpenCV
轻松地将图像加载到numpy.ndarry
中。用PIL
加载时,使用以下代码
from PIL import Imageimg = Image.open('qrcode.png')
下面是一个如何使用OpenCV
加载图像的例子。
import cv2img = cv2.imread('qrcode.png')
在它下面附加以下代码。它将以字符串形式打印出结果。
result = decode(img)
decode()
函数返回一个名为Decoded
的namedtuple
列表。其中每个都包含以下字段:
data
—以字节为单位的解码后的字符串。你需要用 utf8 解码得到一个字符串。type
—仅对条形码有用,因为它概括了条形码格式。rect
—Rect
对象,表示捕获的定位区域。polygon
—代表条形码或 QR 码的Point
实例列表。
如果您要打印出整个返回结果,您应该得到以下输出
[Decoded(data=b'[https://medium.com/@ngwaifoong92'](https://medium.com/@ngwaifoong92'), type='QRCODE', rect=Rect(left=40, top=40, width=330, height=330), polygon=[Point(x=40, y=40), Point(x=40, y=369), Point(x=370, y=370), Point(x=369, y=40)])]
使用以下代码循环遍历每个元素,并打印出解码后的字符串
for i in result:
print(i.data.decode("utf-8"))
完整的代码可以在下面的要点中找到。
5.结论
让我们回顾一下今天所学的内容。
我们从解释python-barcode
、qrcode
和pyzbar
背后的基本概念开始。
之后,我们继续安装必要的模块。使用pip install
安装非常简单。
完成后,我们使用我们选择的配置参数实现了条形码和 QR 码的生成。
最后,我们利用pyzbar
模块对之前生成的图像进行解码。
感谢你阅读这篇文章。希望在下一篇文章中再*到你!
参考
Bardvja 推荐系统:同行评议文章的个人图书馆员
Bardvja 将为你的下一次期刊俱乐部或小组会议提供合适的论文,以减轻拖延症!
推荐系统在我们的生活中变得无处不在——激发和引导我们的兴趣。这些系统主要利用协作或基于内容的过滤来提出符合个人兴趣的建议。在这篇博客中,我们讨论了一个基于内容的推荐系统,推荐来自康奈尔大学 arXiv 的开源出版物。
arXiv 是一项免费分发服务,是一个开放的学术文章档案库,涵盖物理、数学、计算机科学、定量生物学、定量金融学、统计学、电气工程和系统科学以及经济学等领域。arXiv 由康奈尔大学维护和运营,是由 Paul Ginsparg 于 1991 年创建的一个合作资助、社区支持的资源。这是学术文章的极好来源,通常是提交给同行评审期刊的文章的预印本。
研究人员和研究生中用于类似任务的流行工具是 Mendeley ,这是一个具有多种服务的优秀工具。它的一个功能是根据用户的同行评审出版物库进行推荐。本项目的目标绝不是模仿或替代门德利的目的或用途。
创建 Bardvja 的动机源于我本地机器上以 PDF 文件形式存在的大量学术文章。这些不一定是期刊文章,它们可以是报告、提案、海报、论文、学位论文、小册子等。任何具有有用科学信息的文章都可能是有价值的,包含可能直接影响一个人的研究或为未来的提议提供新想法的信息。不管是有意还是无意,研究都是人类的努力和团队的努力。有时,一种方法或途径可能与相邻的研究领域、学科或过去十年大量研究的主题相关。如果能构想出一种工具,在过滤了数万篇论文之后,能够解释一个人的兴趣,并提出跨学科或跨领域的推荐,那将是极其方便的。
Bardvja 有望成为这个无所不知的工具,成为每个研究者的助手。Bardvja 这个名字的灵感来自于围绕着 Bharadwaja 的古印度神话,Bharadwaja 是一个决心获取宇宙中所有知识的圣人。剧透:他失败了,事实证明,他有幸在学*的道路上继续的几世证明是不够的和无关紧要的。虽然 Bharadwaja 的故事可能看起来令人沮丧,但不像他和神,我们有机器学*!
在机器学*出现之前,Bharadwaja 正在思考和摆弄他的头发。图片来自维基百科。
Bardvja 的目标是将自然语言处理和 web 抓取结合起来,以提供来自康奈尔大学 arXiv 的推荐。arXiv 有一个优秀的 API,可以用来获取大量元数据。对于那些有兴趣了解 arXiv API 及其在这项工作中的应用的人,请考虑阅读 arXiv 手册,并在这里使用托管的 Jupyter 笔记本。
接近
Bardvja 推荐系统有三个阶段:
- 使用关键字作为 API 请求中的搜索查询来创建 arXiv 元数据的数据库。可以在 API 请求中调整不同的变量。
- 使用 PyPDF2 解析位于本地目录中的 PDF 文件,以训练机器学*模型并提取主题词汇。
- 开发一个推荐引擎来识别与当地报纸最匹配的 arXiv 文章。
这三个步骤的每一个都在下面描述。
a)使用 PyPDF2 进行解析
尽管 PDF 文件具有漂亮的渲染和可移植的特性,但从其中提取信息却是丑陋的二进制文件。 PyPDF2 是一款流行的工具,易于实施并提供最佳结果,但是存在以下挑战:
- 并非所有的 PDF 文件都可以被解析,有些给出了错误,有些不包含可解析的信息。**
- 解析的大多数文件包含不带空格的文本。thisprovedparticularlychalingtoextractanyusefulinformation from。学术文章中出现的大量数学符号和乳胶符号使这变得更加复杂。
虽然有些文件可能无法解析或读取(这些文件通常是扫描文件或旧的 PDF 文件),但是使用 PyPDF2 可以处理大量的文章。在本研究分析的 25 篇文章中,只有 2 篇是不可分析的。
第二个挑战更有趣也更令人沮丧。幸运的是, StackOverflow 讨论解决了这个问题,并导致了 Python 库的创建。 WordNinja 是一个 Python 库,它将不带空格的句子解析成单词列表!使用 WordNinja 和 RegularExpression,PDF 文件在输入到 CountVectorizer 之前被转换成句子。GitHub 资源库中提供了模型的细节和这些工具的使用顺序。
arXiv
在这一步中,创建了一个包含 arXiv 开源文章的摘要、标题、PDF 链接和其他元数据的库。例如,我使用的当地论文广泛来自粒子和流体动力学领域。因此,用于创建 arXiv 数据库的搜索查询是单词物理、流体、和粒子。请注意,这些关键字是使用先前的主题专业知识选择的。然而,Bardvja 的未来版本可能会包含完整的 arXiv 元数据,在这种情况下,主题专业知识是不必要的。对于这项工作,在几分钟内总共获得了大约 72,000 篇论文。
一旦使用早期的机器学*模型刮出标题和摘要,每篇论文都被矢量化。使用在本地文件上训练的模型转换 arXiv 数据,确保 arXiv 矢量表示使用相似的词汇。**
Bardvja 推荐系统
最后,推荐系统寻找 arXiv 向量与本地向量的相似性。在这项工作中,我们使用余弦相似度进行推荐。然后,arXiv 论文按相似性降序排列,并导出到包含所有 arXiv 论文的标题和链接的 csv 文件中。
如前所述,这项工作的灵感来自我自己在研究生院发现论文的经历,尤其是跨领域和学科的论文。在学术界任职期间,我研究了各种流动中流体与粒子相互作用的理论和计算。然而,作为一名工程师,我的研究领域主要涉及工业流、燃烧和环境现象。因此,令人惊喜的是,Bardvja 推荐的前 10 篇论文中有两篇来自天体物理学,题目如下:
粒子吸积到带有流体动力湍流的圆盘中的行星上
垂直剪切不稳定性产生湍流时圆盘中的粒子动力学
在我的 Macbook 上,整个系统的执行花费了不到半个小时的真实时间和大约 12 分钟的 CPU 时间。
结论
开发了一个推荐系统来利用本地 PDF 文件并推荐来自 arXiv 的开源论文。Bardvja 系统仅使用论文的标题和摘要,因此其识别大量细节的能力有限。目标是广泛搜索跨学科和跨领域的论文,并提出研究者可能感兴趣的建议。Bardvja 只是作为个人图书馆员或研究生院同事集思广益,它仍然希望专家阅读和推断论文。然而,这是一个从大量同行评议的论文中筛选并获得新灵感的宝贵工具。
最后,请考虑使用 Bardvja 并提供可能有助于推进该项目的反馈。GitHub 提供了使用它的代码和步骤,你可以在这里派生和克隆它。请随时联系我的 Github 或 LinkedIn 个人资料了解详情或提出问题。
医疗保健中自主人工智能的障碍
人工智能就在我们身边——它彻底改变了购物、电视和音乐——但它还没有到达医疗保健领域。是什么阻碍了它?
卡尔·比维克在 Unsplash 上的照片
简介
人工智能在当今社会无处不在——它通过我们的手机与我们交谈,推荐我们观看新的节目,并过滤掉与我们无关的内容。它无处不在,以至于我们大多数人在日常生活中没有理解它在我们生活中的作用。但它还没有像彻底改变我们的购物一样改变医疗保健行业的面貌。这是为什么呢?
答案不止一个。在我看来,至少有三个很好的理由让你看不到人工智能在医疗保健领域的广泛应用。不过,只要有足够的时间,我相信我们会克服所有这些障碍。
明确地说,我在这篇文章中讨论的人工智能是那种代替医疗专业人员的人工智能。被动人工智能只是帮助支持提供商的决策过程,已经得到了大量的研究,并改变了我们对待医疗保健的方式。
联邦法规
人工智能要在医疗保健领域发挥作用,必须克服的最大障碍之一是旨在保护消费者的众多联邦法规。虽然不同国家有许多独特的管理机构,但我将把这个主题的范围缩小到美国 FDA。根据 FDA 的官方指南,医疗器械有几种不同的类别[1,2]。
I 级—这类设备被定义为最小风险,也就是说,产品的设计者可以很容易地向 FDA 证明,该设备对消费者没有伤害威胁,或者非常类似于已经获得 FDA 批准的设备。大约 47%的医疗设备属于这一类别。
第二类—该类装置定义为中度风险。大约 43%的医疗设备属于这一类别。你可以将这一类别视为医疗器械,它类似于已有的产品,但具有一些可能伤害消费者的独特功能。这方面的一个例子是电动轮椅,因为它非常类似于现有技术(即非电动轮椅),但具有电子元件,如果这些电子元件发生故障,可能会伤害用户。
III 类—这是为对消费者构成高风险的其余 10%医疗器械保留的。如果这些设备出现故障,可能会导致死亡(例如心脏起搏器)。
医疗保健中的自主人工智能应用大多属于第三类。一个护士可以用来识别黑色素瘤而不需要咨询专家的设备?自动检测乳腺癌的算法?一个为医生区分病人优先级的神经网络?都是三级。
虽然可以说这些例子中的每一个都可以用来帮助医务人员,而不是取代专家,但很难说这些设备是否会超越医疗保健专业人员的判断。当然,放射科医师可以像她应该做的那样手动检查病人的影像,但当工具似乎在大多数时候都是正确的时,她可能会在行使自己的判断时变得自满——这可能会付出生命的代价。
但这让我想到了下一个障碍:即使 FDA 批准了这些医疗设备,医疗服务提供者和他们的病人会信任它们吗?
患者和提供者信任度
让我们从医疗保健中一个糟糕的人工智能实施的例子开始。想象你是一名医生。像你的其他同事一样,你花了十几年的时间参加富有挑战性的大学课程,努力完成住院医师培训,或者努力工作以在你的职业中取得成功。经过多年的努力,你终于成功了。你是一家知名医院受人尊敬的医疗保健专家,你经常阅读你所在领域的最新创新,你知道如何优先考虑病人的需求。
突然,你从阅读的许多学术期刊中熟悉的人工智能开始在你的医院中使用。在这种特殊情况下,也许它可以预测病人的住院时间,这样你就可以更好地计划临床试验。你会注意到,有时,它的预测是完全错误的。你甚至开始怀疑算法可能遇到了困扰人工智能的许多问题之一,例如模型漂移。你不信任它,并开始为了自己的利益而推翻它的判断——毕竟,你是医生,这是你学*的目的!你的工作是给你的病人提供极好的护理,但最终,你觉得算法不允许你这么做。
当人工智能试图为你做更多的工作时,会发生什么?你会相信吗?
上述场景中问题的核心是所描述的模型的不透明性。在那种情况下,算法背后的开发者没有考虑到医生和病人都想知道为什么以及什么。即使上述人工智能实现实际上对患者的住院时间进行了非常准确的评估,它也从未试图支持其预测背后的推理。
一个更理想的模型应该包含类似 SHAP 值的东西,你可以在 Dataman 博士的这篇优秀文章中读到更多。本质上,它们允许模型提供所谓的局部特征重要性,用简单的英语来说,这意味着对为什么这种特殊情况具有它所具有的预测结果的估计[3]。尽管它不会以任何方式改变算法本身,但它让提供者和患者都能洞察其判断,在医疗保健这样的循证行业中,这是非常宝贵的。
当人工智能解释其决策过程时,患者和提供者更容易信任它。
事实上,人工智能有巨大的能力来帮助临床决策。它能够发现复杂的模式,这些模式只有在综合查看患者数据时才会变得明显——我们不可能合理地期望人类医生检测到的事情。虽然他们不能取代个人医疗保健提供者的位置,但他们可以提供决策支持,并帮助医疗工作者看到他们否则不会注意到的趋势。但是这种决策支持只有在算法自我解释的时候才有可能。
人工智能驱动的医疗保健的伦理
阿诺·弗朗西斯卡在 Unsplash 上的照片
人工智能是一个复杂的话题,不仅在它的实现方面,而且在它给我们带来的伦理困境方面。2015 年,谷歌的机器学*驱动的照片标记器引发了争议,当时它错误地将一名黑人妇女标记为大猩猩[4]。社交媒体的反弹无可非议地巨大。一个简单的错误分类就足以将全世界的目光吸引到人工智能的状态上。发生这样的事情,谁来负责?我们应该如何回应?
不幸的是,这样的问题即使在 5 年后也并不少*。就在过去的一个月里,麻省理工学院不得不关闭广泛使用的微型图像数据集,因为在其中发现了种族主义和攻击性的内容[5]。现在使用的算法中有多少是从这些数据中学来的?
从表面上看,这些问题可能与医疗保健中的人工智能无关,但我提出它们有几个原因:
- 他们证明,即使我们有最好的意图,偏*也可能在我们的模型中表现出来
- 经常发生的情况是,只有当模型已经发布到世界上并且犯了错误时,这些偏*才变得明显
我们能自信地说这不会发生在医疗保健领域吗?我不相信我们可以。作为研究人员,还有更多的工作要做,以过滤掉我们的数据、我们的预处理技术、我们的模型和我们自己的固有偏*。人工智能在医疗保健领域的最大障碍是缺乏对任何给定模型在所有潜在用例中的公*性、安全性和有效性的保证。
已经在努力改善这种状况。像 Aequitas 这样的库使得开发者比以往任何时候都更容易测试他们的模型和数据的偏差。与此同时,研究人员和开发人员都越来越意识到模型偏差的影响,这将导致检测和处理模型偏差的工具、技术和最佳实践的进一步发展。人工智能可能还没有为今天医疗保健的黄金时间做好准备,但我和其他许多人将努力工作,让它成为现实。只要给予适当的照顾和关注,我相信人工智能有能力改变我们所知的医疗保健的面貌。
关于我
我叫 Josh Cardosi,是一名研究人工智能在医疗保健中的应用的硕士生。你可以在这篇文章中阅读更多关于我是如何来到这里的信息。虽然我上面谈到的问题非常真实,需要解决,但我坚信我们会克服它们,并通过这样做,改善医疗保健状况。我相信这将导致更好的卫生服务利用,降低患者死亡率,并提高患者和提供者对治疗计划的信心。
请随时在 LinkedIn 上与我联系。我喜欢阅读你的消息,并谈论医疗保健或机器学*方面的人工智能。
参考文献
[1] 对您的医疗器械进行分类 (2020),美国美国食品药品监督管理局
[2]FDA 医疗器械分类有什么区别? (2020),BMP 医疗
[3] Dataman,用 SHAP 价值观 (2019)向数据科学解释你的模型
[4] J. Snow,谷歌照片仍然对大猩猩有问题 (2018),《麻省理工科技评论》
[5] K. Johnson,由于种族主义和攻击性内容,麻省理工学院关闭了 8000 万个微型图像数据集 (2020),Venture Beat
[6] 机器学*的偏*和公*审计工具包 (2018),数据科学和公共政策中心
BART 用于解释简单的变压器
释义是用不同的词表达某事,同时保留原来的意思的行为。让我们看看如何利用 BART(一种序列间变压器模型)实现这一点。
介绍
BART 是一个去噪自动编码器,用于预处理序列到序列模型。通过(1)用任意噪声函数破坏文本,以及(2)学*模型以重建原始文本来训练 BART。
如果这听起来有点复杂,不要担心;我们将对其进行分解,看看这一切意味着什么。在我们深入 BART 之前,添加一点背景知识,现在是时候用自我监督的模型来进行迁移学*了。在过去的几年里,人们已经说过很多次了,但是变形金刚确实在各种各样的自然语言处理(NLP)任务中取得了令人难以置信的成功。
BART 使用标准的转换器架构(编码器-解码器),就像最初用于神经机器翻译的转换器模型,但也结合了来自 BERT(仅使用编码器)和 GPT(仅使用解码器)的一些变化。更多细节可以参考 BART 论文的 2.1 架构部分。
培训前 BART
通过最小化解码器输出和原始序列之间的交叉熵损失来预训练 BART。
掩蔽语言建模(MLM)
诸如 BERT 之类的 MLM 模型被预先训练来预测屏蔽令牌。这个过程可以分解如下:
- 用一个掩码标记[MASK]替换输入的随机子集。(添加噪音/损坏)
- 该模型预测每个[掩码] 记号的原始记号。(去噪)
重要的是,当试图预测原始标记时,BERT 模型可以“看到”完整的输入序列(一些标记被替换为[MASK])。这使得 BERT 成为双向模型,即它可以“看到”屏蔽令牌之前和之后的令牌。
BART 论文中的图 1 ( a)
这适用于分类等任务,在这些任务中,您可以使用全序列中的信息来执行预测。但是,它不太适合于文本生成任务,在这种任务中,预测只依赖于前面的单词。
自回归模型
用于文本生成的模型(如 GPT2)被预先训练,以在给定前一个记号序列的情况下预测下一个记号。这种预先训练的目标导致模型非常适合文本生成,但不适合分类之类的任务。
来自 BART 论文的图 1 ( b)
BART 序列到序列
巴特既有编码器(像伯特)又有解码器(像 GPT),基本上是两全其美。
编码器使用类似于 BERT 的去噪目标,而解码器试图使用先前的(未损坏的)令牌和编码器的输出,逐个令牌地再现原始序列(自动编码器)。
BART 论文中的图 1 ( c)
这种设置的一个显著优点是选择讹误方案的无限灵活性;包括改变原始输入的长度。或者,用更花哨的术语来说,文本可能被任意噪声函数破坏。
本文中使用的腐败方案总结如下。
- 令牌屏蔽—输入的随机子集被替换为[屏蔽]令牌,就像在 BERT 中一样。
- 令牌删除-从输入中删除随机令牌。模型必须决定丢失了哪些位置(因为标记只是被删除了,而没有被其他任何东西替换)。
- 文本填充—许多文本跨度(长度可变)都被替换为单个[MASK]标记。
- 句子置换—输入基于句点(.),而且句子都是混排的。
- 文档旋转—随机选择一个令牌,并旋转序列,使其从所选令牌开始。
作者指出,用文本填充来训练 BART,可以在许多任务中产生最稳定的表现。
对于我们感兴趣的任务,即转述,预训练的 BART 模型可以直接使用输入序列(原始短语)和目标序列(转述句子)作为序列到序列模型进行微调。
这也适用于总结和抽象问题回答。
设置
1.从这里安装 Anaconda 或者 Miniconda 包管理器。
2.创建新的虚拟环境并安装软件包。
conda create -n st python pandas tqdmconda activate st
3.如果使用 CUDA:
conda install pytorch>=1.6 cudatoolkit=10.2 -c pytorch
否则:
conda install pytorch cpuonly -c pytorch
4.安装简单变压器。
pip install simpletransformers
数据准备
我们将组合三个数据集,作为 BART 释义模型的训练数据。
下面的 bash 脚本可以用来轻松下载和准备前两个数据集,但是 MSRP 数据集必须从链接中手动下载。(微软没有提供直接链接😞)
确保将文件放在同一个目录( *data*
)中,以避免示例代码中文件路径的麻烦。
我们还有几个助手函数,一个用于加载数据,一个用于清理训练数据中不必要的空间。这两个功能都在utils.py
中定义。
有些数据的标点符号前有空格,我们需要删除。 *clean_unnecessary_spaces()*
功能就是用于这个目的。
向 BART 解释
一旦准备好数据,训练模型就相当简单了。
注意,你可以在 这里 找到简单变形金刚例子中的所有代码。
首先,我们导入所有必要的东西并设置日志记录。
接下来,我们加载数据集。
然后,我们设置模型和超参数值。请注意,我们正在使用预训练的facebook/bart-large
模型,并在我们自己的数据集上对其进行微调。
最后,我们将为测试数据中的每个句子生成释义。
这将把预测写到 *predictions*
目录中。
超参数
超参数值被设置为常规、合理的值,而不进行超参数优化。对于这个任务,基本事实并不代表唯一可能的正确答案(也不一定是最佳答案)。因此,调整超参数以使生成的文本尽可能接近基本事实没有多大意义。
我们的目标是生成好的释义序列,而不是从数据集中产生精确的释义序列。
如果你对简单变压器的超参数优化感兴趣(对分类等其他模型/任务特别有用),请点击这里查看我的指南。
如何使用简单的转换器调整超参数,以实现更好的自然语言处理。
towardsdatascience.com](/hyperparameter-optimization-for-optimum-transformer-models-b95a32b70949)
所使用的解码算法(和相关的超参数)对生成的文本的质量和性质有相当大的影响。我选择的值(如下所示)通常适合生成“自然”文本。
更多信息请参考优秀抱脸指南 这里 。
用你自己的句子试一下这个模式
你可以使用下面的脚本在任何句子上测试这个模型。
结果
让我们来看看模型为测试数据生成的一些转述序列。对于每个输入序列,该模型将生成三个(num_return_sequences
)释义序列。
Orignal:A recording of folk songs done for the Columbia society in 1942 was largely arranged by Pjetër Dungu.Truth:A recording of folk songs made for the Columbia society in 1942 was largely arranged by Pjetër Dungu.Prediction:A recording of folk songs made in 1942 for the Columbia Society was largely arranged by Pjetr Dungu.A recording of folk songs for the Columbia society in 1942 was largely arranged by Pjetr Dungu.A recording of folk songs done for the Columbia Society in 1942 was largely arranged by Pjetr Dungu.
Original:In mathematical astronomy, his fame is due to the introduction of the astronomical globe, and his early contributions to understanding the movement of the planets.Truth:His fame is due in mathematical astronomy to the introduction of the astronomical globe and to his early contributions to the understanding of the movement of the planets.Prediction:His fame in mathematical astronomy is due to the introduction of the astronomical globe and his early contributions to understanding the movement of the planets.In mathematical astronomy, his fame is due to the introduction of the astronomical globe and his early contributions to understanding the motion of the planets.In mathematical astronomy his fame is due to the introduction of the astronomical globe and his early contributions to understanding the movement of the planets.
Original:Why are people obsessed with Cara Delevingne?Truth:Why are people so obsessed with Cara Delevingne?Prediction:Why do people fall in love with Cara Delevingne?Why is everyone obsessed with Cara Delevingne?Why do people like Cara Delevingne?
Original:Earl St Vincent was a British ship that was captured in 1803 and became a French trade man.Truth:Earl St Vincent was a British ship that was captured and became a French merchantman in 1803.Prediction:Earl St Vincent was a British ship captured in 1803 and became a French trader.Earl St Vincent was a British ship captured in 1803 and became a French trade man.Earl St Vincent was a British ship that was captured in 1803 and became a French trade man.
Original:Worcester is a town and county city of Worcestershire in England.Truth:Worcester is a city and county town of Worcestershire in England.Prediction:Worcester is a town and county of Worcestershire in England.Worcester is a town and county town in Worcestershire in England.Worcester is a town and county town of Worcestershire in England.
6.域外句子
Original:The goal of any Deep Learning model is to take in an input and generate the correct output.Predictions >>>
The goal of any deep learning model is to take an input and generate the correct output.The goal of a deep learning model is to take an input and generate the correct output.Any Deep Learning model the goal of which is to take in an input and generate the correct output.
从这些例子中可以看出,我们的 BART 模型已经很好地学会了生成释义!
讨论
潜在的问题
生成的释义有时会有一些小问题,下面列出了其中一些。
- 生成的序列几乎与原始序列完全相同,只有一两个词的细微差别。
- 不正确或笨拙的语法。
- 在域外(来自训练数据)输入上可能没有那么好。
令人鼓舞的是,这些问题似乎非常罕*,并且最有可能通过使用更好的训练数据来避免(同样的问题有时也可以在训练数据中看到)。
包裹
像 BART 这样的序列到序列模型是 NLP 实践者箭筒中的另一支箭。它们对于涉及文本生成的任务特别有用,例如释义、摘要和抽象问题回答。
解释可用于数据扩充,您可以通过解释可用数据来创建更大的数据集。
R 中的基本绘图
在 R 中使用基本的绘图系统看起来让人不知所措,但事实并非如此。
R 中的基本 xy 散点图(左)与使用一些快速技巧的散点图(右)
R 中的基本绘图可能会令人生畏。它采用画布的方式来绘制,允许你在图形上绘制一层又一层的细节。因此,需要学*的函数和属性似乎是无穷无尽的,但是没有必要惊慌失措或者直接跳到 ggplot。本文强调了 base plot()函数的多功能性,同时为您提供了一些创建漂亮绘图的快速技巧。
在本文中,我使用了 Edgar Anderson 的 Iris 数据集,因此您可以复制代码并查看它的运行情况。我们将使用该数据集来创建和比较四个图表:
- 你可以在 R 中创建的最基本的图,一个 XY 散点图
- 使用颜色将 iris 数据集的散点图按物种分组的图
- 具有自定义字体、颜色和大小的绘图,以及
- 带有背景色和网格的绘图。
要加载数据集包并了解 Iris 数据集,请在 RStudio 控制台中输入以下代码:
**library**(datasets)
**help**(iris)
基本图与由数据子集着色的图
上面,我用基数 R 绘制了花瓣宽度和花瓣长度的关系图。左边的图是您可以在 R 中创建的最基本的图:一个带有 x 和 y 变量的散点图。
右边的图表传达了更多的信息,用颜色按物种对数据进行了细分。它看起来也更好,有轴标签、标题、颜色和图例。使用 ifelse()根据虹膜种类应用颜色。只需要多花几秒钟的时间来编写这种详细程度的代码,并增加信息和清晰度。
您可以使用以下代码在 R 中重新创建这两个图形:
##par lets us set global parameters for our graphs.
par(mfrow = c(1,2), mar = c(5,5,4,1))##Simple plot (left)
plot (iris$Petal.Length,iris$Petal.Width)##Plot showing species subsets (right)
plot(iris$Petal.Length, iris$Petal.Width,
xlab = "Petal Length",
ylab = "Petal Width",
main = "Petal Width vs Petal Length",
pch = 20,
col=ifelse(iris$Species == "setosa","coral1",
ifelse(iris$Species == "virginica","cyan4",
ifelse(iris$Species == "versicolor",
"darkgoldenrod2", "grey"))))
##legend
legend("bottomright", c("setosa","virginica", "versicolor"),
col = c("coral1","cyan4", "darkgoldenrod2"), pch=20)
物种子集的代码可分为三个部分:
- 因素
- 绘图属性
- 传奇
1.因素
参数部分固定所有图的设置。这里我们没有添加很多论点。我们有m flow,它指定我们有一行和两列图——也就是说,两个图并排。 mar 属性是我们的边距宽度的向量,第一个值表示绘图下方的边距(5),第二个值表示绘图左侧的边距(5),第三个值表示绘图顶部的边距(4),第四个值表示左侧的边距(1)。
par(mfrow = c(1,2), mar = c(5,5,4,1))
剧情
第二部分是情节的核心。您可以看到,通过向我们的 plot()函数添加五个参数,我们改进了图形的外观和有用性。这些论点是:
- xlab:指定绘图的 x 轴标签
- ylab:指定 y 轴标签
- 主:标题您的图表
- pch:指定图形的符号系统
- col:指定图形的颜色。
##Plot with some customization
plot(iris$Petal.Length, iris$Petal.Width,
xlab = "Petal Length",
ylab = "Petal Width",
main = "Petal Width vs. Petal Length",
pch = 20,
col=ifelse(iris$Species == "setosa","coral1",
ifelse(iris$Species == "virginica","cyan4",
ifelse(iris$Species == "versicolor",
"darkgoldenrod2", "grey"))))
对你的图表外观影响最大的参数是 col 。当你开始的时候,我建议你记住这篇文章末尾的备忘单上的三到四种颜色的名称。
传奇
legend("bottomright", c("setosa","virginica", "versicolor"),
col = c("coral1","cyan4", "darkgoldenrod2"), pch= c(20))
图例功能允许用户定义其位置、显示为标签的字符串以及显示在每个标签旁边的符号。像这样创造传奇是一把双刃剑:事实上,它不是自动的,这让你对你的传奇看起来有很大的控制,但也很容易给你的符号贴错标签,所以 ojo 。
字体和颜色自定义
如果您要为一般流通或有严格品牌指导原则的组织创建图形,这种级别的自定义可能是必要的。代码看起来很长,因为我包含了第二个萼片长度图来显示全局参数的应用,但是代码本质上有相同的三个部分:参数、图和图例。您可以看到,我没有对这些图做任何重大的修改,我只是添加了一些属性来定制我的图形的颜色、字体和字体大小。
这些图与第一部分中的图之间的一个重要变化是在开始的 par()函数中。在这里添加属性来指定字体、字体大小和颜色,为您的绘图创建了“全局”设置,使您的所有后续图形摆脱了 1980 年代的粗糙外观。我添加的属性是:
- 字体:par()表达式中的字体改变绘图函数外项目的字体。在这种情况下,它适用于图例,但也适用于您可能有的任何边距文本。
- font.axis :轴数值标签的字体。
- fg :前景颜色,表示文本和图形轮廓。
- col.axis :坐标轴刻度和文字的颜色。
- cex.axis :坐标轴刻度和文本的大小,相对于默认值 1。
我还在代码的 plot 部分添加了一些类似的属性:
- font.lab :指定标签的字体
- col.lab :指定标签的颜色
- font.main :指定主标题的字体
- 主栏:指定主标题的颜色
这些属性的指定方式与其父属性(col 和 font)的指定方式完全相同。很简单,对吧?
我没有对图例做任何修改;par()函数为我做到了这一点。
##global settings
par(mfrow = c(1,2), mar = c(5,5,4,1),font = 7,font.axis = 7,
fg = "azure4", col.axis = "azure4", cex.axis = .75)## First plot
plot(iris$Petal.Length, iris$Petal.Width,
xlab = "Petal Length",
ylab = "Petal Width",
font.lab = 7,
col.lab = "azure4",
main = "Petal Width vs Petal Length",
font.main = 7,
col.main = "black",
pch = 20,
col=ifelse(iris$Species == "setosa","coral1",
ifelse(iris$Species == "virginica","cyan4",
ifelse(iris$Species == "versicolor",
"darkgoldenrod2", "grey"))))
##legend
legend("bottomright", c("setosa","virginica", "versicolor"),
col = c("coral1","cyan4", "darkgoldenrod2"), pch=20)##Second plot
plot(iris$Sepal.Length, iris$Sepal.Width,
xlab = "Sepal Length",
ylab = "Sepal Width",
font.lab = 7,
col.lab = "azure4",
main = "Sepal Width vs Sepal Length",
font.main=7,
col.main = "black",
pch = 17,
col=ifelse(iris$Species == "setosa","coral1",
ifelse(iris$Species == "virginica","cyan4",
ifelse(iris$Species == "versicolor",
"darkgoldenrod2", "grey"))))
##legend
legend("bottomright", c("setosa","virginica", "versicolor"),
col = c("coral1","cyan4", "darkgoldenrod2"), pch=17)
背景
使用 r 中的基本绘图时,图表的背景很复杂。par()函数有一个背景属性, bg ,但是它将图表的整个区域都着色为背景色。例如:
par(mfrow = c(1,1), mar = c(5,5,4,1),bg = "grey")
plot(iris$Petal.Length, iris$Petal.Width)
不是我们想要的。
在 base R 中,没有简单的方法在你的绘图背景上着色。您可以使用 rect 功能绘制一个与您的轴对齐的矩形,或者您可以使用 abline 。 abline 函数非常通用,用它来为我们的图形创建背景迫使我们以稍微不同的方式创建我们的情节。
我们将在前几节工作的基础上,给花瓣宽度和花瓣长度的关系图添加一个带有网格线的彩色背景。
花瓣宽度与花瓣长度的图表,带有使用 abline 创建的背景
##global parameters
par(mfrow = c(1,1), mar = c(5,5,4,1),font = 7,font.axis = 7,
fg = "azure4", col.axis = "azure4", cex.axis = .75) ##Create the empty plot
plot(NULL, ylim=c(0,2.5),xlim=c(0,7),
xlab = "Petal Length",
ylab = "Petal Width",
font.lab = 7,
main = "Petal Width vs. Petal Length",
font.main = 7,
col.main = "black",)##Add the background color
abline(v = 0:7, col = "aliceblue", lwd = 200)
abline(v = 0:7, col = "white")
abline(h=0:2.5, col = "white")##Add the data points
points(iris$Petal.Length, iris$Petal.Width,
pch = 20,
cex = 1.5,
col=ifelse(iris$Species == "setosa","coral1",
ifelse(iris$Species == "virginica","cyan4",
ifelse(iris$Species == "versicolor",
"darkgoldenrod2", "grey"))))
##legend
legend("bottomright", c("setosa","virginica", "versicolor"),
col = c("coral1","cyan4", "darkgoldenrod2"), pch=20)
如果您查看此图的代码,您会发现它创建情节的方式略有不同。首先,它建立了一个空白图,然后绘制信息层,从背景色开始,然后是数据点,然后是图例。背景颜色是使用粗 ab 线创建的纯色,使用细白线创建的网格:
##Add the background color
abline(v = 0:7, col = "aliceblue", lwd = 200)
abline(v = 0:7, col = "white")
abline(h=0:2.5, col = "white")
您可以看到,我们已经将我们的点属性(数据集、pch 和 col)移动到了 points() 函数中,但是我们没有更改它们。我添加了属性 cex 来增加点的大小。
备忘单
图表是向任何受众传达分析结果的最有效方式之一。像适当的标签、按颜色或符号设置数据子集以及字体调整这样简单的添加既增加了信息又提高了清晰度,然而我们始终看到 R 中的图形看起来就像是 30 年前创建的。在花时间清理、总结和分析你的数据之后,花一分钟在你的图上是有意义的。
下面是一些不错的备忘单,可以帮助你进行定制。
绘图的属性()
绘图函数的一些属性及其相关值(源代码)。对于 col,您可以看到只有 7 种不同的颜色值有一个数字名称,然后它们开始重复。
颜色;色彩;色调
42 个 R 颜色名称的备忘单(源代码
字体
在 R 中有许多处理字体的方法,但是这里有一个基本的备忘单,它使用 font = x 处理与不同字体相关的数值。
本文使用的所有代码都可以在这里找到。
根据你的活跃程度,你应该喜欢这个:Instagram vs 抖音!
通过比较 Instagram 和抖音来评估推荐系统如何了解用户
图片作者:特里斯特·约瑟夫
“根据您的活动,我们认为您可能会喜欢这个。”这句话是几乎每个社交媒体*台上最常*的短语之一,而且有一个很好的理由。这些*台上的转化率是推动业务的因素。这个转换率本质上是看到帖子的总人数中对帖子采取了一些行动的人数。从帖子中采取的行动可以是简单地参与一条内容,访问与帖子链接的网站,甚至购买帖子中提到的商品。
在任何一种情况下,都可以看出为什么转换率越高越好。人们更有可能对他们感兴趣的事情或激发反应需求的事情采取行动。此外,在用户已经与他们感兴趣的东西交互之后,*台的目标是显示更多相似的内容,因为参与度将是相似的。这是推荐系统的本质;它确定一个用户可能感兴趣的列表,评估列表中哪些项目表现最好,然后向用户重复显示那些表现最好的项目。
如果你是一个有兴趣成为数据科学家的人,但你对动漫也不感兴趣,你更有可能点击一个写着“数据科学 5 大算法”的帖子,而不是一个写着“2020 年 5 大动漫”的帖子。在那之后,继续看到关于数据科学的帖子将是理想的。因此,*台用户可以看到的每一条内容都需要优化,以实现其最大潜力。最大化这种潜力的最好方法是只向用户展示他们感兴趣的内容。但是现在大问题来了,*台如何知道用户会对什么感兴趣?
图片作者:特里斯特·约瑟夫
*台可以通过两种主要的、通用的方式来确定用户的兴趣。这就是内容过滤和协同过滤,两种方式各有千秋。内容过滤使用关于用户和帖子的已知信息将事情联系起来。它包括从一组预定义的类别中给每个用户和帖子贴上标签,然后对这些联系进行评分。一旦分数被确定,就假设用户将偏好具有较高分数的内容。
让我们通过一个例子来更好地理解这个过程。为了简单起*,假设 Instagram 上的内容只有两类:爱情和喜剧。Julia 是一名 Instagram 用户,她喜欢喜剧,但不喜欢浪漫,所以她会被赋予喜剧 4 分,浪漫 0 分。现在有两个不同的职位可以推荐给朱莉娅。《邮报》A 只讲述浪漫,而《邮报》B 则兼具浪漫和喜剧。根据总分,茱莉亚应该对岗位 B 更感兴趣,这就是将向她推荐的岗位。
图片作者:特里斯特·约瑟夫
现在有更多的东西可以用来确定用户是否对一个帖子感兴趣,这些可以包括年龄、位置,甚至种族或民族;但概念保持相对一致。为了收集这些信息,*台通常要求用户创建某种偏好列表。这实际上可以通过填写一张表格来完成,“你喜欢喜剧还是爱情片?”,或者通过开发一个社交图。
社交图是将用户映射到他们表示感兴趣的所有内容的记录。在 Instagram 上,这将是关注另一个 Instagram 用户、喜欢其他用户的帖子以及在*台上分享帖子的行为。通过这样做,用户开发了一个他们认为最感兴趣的网络。这给用户一种感觉,他们可以控制自己在提要中看到的内容。这种方法面临的挑战是,对用户来说,填写他们喜欢的内容或与一组用户实际联系似乎是一项工作,人们并不像他们想象的那样擅长列出他们的偏好。
图片作者:特里斯特·约瑟夫
这让我们想到了*台可以用来确定用户兴趣的第二种方法;协同过滤。它的工作原理是,一个用户可能会对具有相似观看*惯的其他用户感兴趣的内容感兴趣。这在某种程度上可以被认为是颠倒了内容过滤方法。协作过滤方法不是有预定义的类别、映射和分数,而是调查用户在参与什么,然后从那里“向后”工作。使用一组参与度数据,目标是确定哪些特征将相似的帖子相互链接。这些特点是未知的,通常不会有一个标签,如喜剧,附在它身上。相反,它们被称为潜在特征,因为它们产生于数据中的潜在模式。
抖音是一个使用协同过滤的*台,所以让我们通过抖音算法来更好地理解这种方法是如何工作的。当一个新用户开始使用抖音时,他们不必提供偏好列表,也不必明确地追随任何人。相反,他们被带到一个欢迎页面,视频开始播放,最重要的指标是他们看了一个视频多长时间。该算法然后分析这些观看时间数据,以及有多少视频被重新观看或退出,以了解用户对什么感兴趣。假设如果用户观看视频的时间较长,如果他们多次重新观看视频,并且如果他们退出视频的频率较低,那么他们对该段内容感兴趣。
图片作者:特里斯特·约瑟夫
当用户再次访问时,他们会收到基于之前视频观看时间分析的个性化内容。这个方法绕过了社交图,而是创建了一个兴趣图。顾名思义,它是基于各种性能指标的用户到他们可能感兴趣的内容的映射。现在,抖音不是第一个使用这种方法的*台。YouTube 算法以类似的方式工作。然而,抖音视频通常比 YouTube 视频短得多,用户可以轻松发布更多内容。因此,抖音有很多数据可以借鉴。
这就是协同过滤方法的力量。有大量的数据可以学*和提取潜在的特征,然后可以用来更好地了解消费者,然后开发出惊人准确的推荐。这种方法的另一个优点是,用户不必通过建立联系或填写表格来表明他们感兴趣的内容。然而,这也可能导致用户陷入一个“相似内容”的兔子洞,他们不会明确搜索。
图片作者:特里斯特·约瑟夫
人们有时会说,任何足够先进的技术都和魔法没什么区别。通常,用户认为当一个*台向他们推荐他们真正感兴趣的东西时,那一定是奇迹。这不是魔法。相反,它是足够先进的技术。内容过滤和协同过滤都利用用户过去行为的一些数据来预测他们的一些情况。内容过滤要求用户建立一个社交图,并根据偏好将用户划分到自定义的类别中。另一方面,协同过滤让用户创建兴趣图,并根据从用户活动中学到的东西将内容特征聚集在一起。
那么*台如何知道用户会对什么感兴趣呢?用户会通过这些方法之一告诉他们。
参考文献:
pitt.edu/~peterb/2480-012/ContentBasedFiltering.pdf
live book . manning . com/book/practical-recommender-systems/chapter-10/
developers . Google . com/机器学*/推荐/基于内容/基础知识
developers . Google . com/machine-learning/推荐/协作/基础知识
link.springer.com/chapter/10.1007/978-3-540-72079-9_9
ieeexplore.ieee.org/document/5197422
其他有用的材料:
or eilly . com/library/view/intelligent-projects-using/9781788996921/
arxiv.org/ftp/arxiv/papers/1503/1503.07475.pdf
towards data science . com/introduction-to-recommender-systems-6 c 66 cf 15 ada
Bash 命令在你的袖子里
我最近遇到的 5 个 Bash 工具非常棒
由 Kelly Sikkema 在 Unsplash 上拍摄的照片
Shell 脚本非常有趣!一旦你对这些工具和它们的作用有所了解,情况会变得更好。
我将使用终端展示这些工具。任何时候你想在 Windows 上运行 Linux 命令行,打开 PowerShell 或命令提示符并输入 bash 。您也可以在搜索栏中搜索 bash 并选择在命令窗口中打开 bash 。
其中一些工具没有预装,因此需要brew
安装。Homebrew 是一个 MacOS 的软件包管理器。
家酿网站的一个片段:
家酿安装你需要的苹果(或你的 Linux 系统)没有的东西。
Homebrew 将软件包安装到它们自己的目录中,然后将它们的文件符号链接到
/usr/local
中。
事情是这样的:
$ brew install <name-of-package>
tldr
$ brew install tldr
:tldr
是一个给你如何使用特定 bash 命令的例子的工具。例如
$ tldr grep
tldr grep
$ tldr find
tldr find
您能想到的任何可能的 bash 命令,使用tldr
并查看您可以使用它的许多方式。
TL;博士代表“太久;没读过”是man
的一种备忘单。
外壳检查
$ brew install shellcheck
:shellcheck
用于对您的脚本进行检查。注意 ShellCheck 只支持sh/bash/
。
$ shellcheck <name-of-bash-file>
ShellCheck 的目标是:
指出并澄清典型的初学者语法问题,这些问题会导致 shell 给出模糊的错误消息。
指出并澄清典型的中级语义问题,这些问题会导致 shell 行为怪异且违反直觉。
指出可能导致高级用户的工作脚本在未来环境中失败的微妙警告、死角和陷阱。
来源: github
为了演示,我使用了我在这里找到的 bash 脚本。在 Vim 中打开的脚本如下:
example.sh
当我运行 shellcheck 命令时,结果如下:
shellcheck example.sh
这个工具我印象超级深刻!
历史
$ history
:该命令输出 bash 终端上最近使用的命令列表。比起使用向上箭头键来浏览最近使用的命令(总是迷路,从来没有真正找到你要找的命令),这是一种更好的方式来筛选你过去运行过的命令。
fzf
$ brew install fzf
:fzf
是一个让你交互使用grep
的工具(grep
是一个模式匹配工具)。
给定一个脚本example2.sh
,我们可以通过将文件的内容输入fzf
:
cat example2.sh | fzf
来交互式地搜索文件中的任何内容
cat example2.sh | fzf
要退出搜索模式,请按ESC
+ q
+ ENTER
。
显然,使用的示例文件不足以展示强大的工具fzf
。
布鲁特
$ brew install broot
:ls
不总是容易看的。仅将所有文件和目录输出到您的终端屏幕上,在导航和定位某些文件/文件夹时效率低下。所以,我们用broot
。这是一个工具,列出您的目录和文件,在一个简单的方式,让你看看。在所需的目录中,键入broot
并输入。一个目录和文件列表显示出来(颜色与类型相匹配)。你可以在一个目录上ENTER
进一步查看它的内容。broot
还可以让你直接从终端的默认应用程序中打开文件。
如果你想找出使用上述命令的更高级的方法,tldr
它!注意,对于某些工具,GitHub 页面可能不存在。
这些不是很光滑吗?亲自尝试一下吧!
基本人工智能算法
旅行商问题的搜索算法
为了用计算机解决问题,有必要用数字或符号的形式来表示问题,并用编程语言提供一个特定的过程。然而,在人工智能(AI)领域解决问题时,很难从一开始就指定一个问题的公式。因此,在观察状态变化的过程中,选择求解过程的灵活性是非常需要的。有些问题可以用图形或树形结构来表示,其中每个节点代表问题的一个状态。这种问题表述方法称为状态空间表示法。
状态空间表示
在状态空间表示方法中,问题的每个状态由图或树结构的节点表示。在这种情况下,该问题被转化为在特定的算子和约束下确定目标的搜索问题。在这篇文章中,我将以旅行商问题(TSP)为例进行介绍。
表示状态空间表示需要的一个问题:
(1)。问题的一组状态
(2)。一组操作符在问题的状态之间进行操作
(3)。初始状态和最终状态(目标)
旅行推销员问题
考虑以下情况。给你一个 n 个城市的列表,其中有任意两个城市之间的距离。现在,你必须从你的办公室开始,每个城市只去一次,然后回到你的办公室。你能走的最短路径是什么?这个问题被称为旅行推销员问题(TSP)。
TSP 问题的公式化
为了使问题简单,我们考虑 3 个城市的问题。
让我们分别给办公室(A)和 3 个城市(B ) ( C ) ( D)打电话。我们通过{A}表示销售员离开了他的办公室来初始化问题状态。作为一个操作员,当他访问 city-B 时,问题状态更新为{A,B},其中考虑了{ 0 }中元素的顺序。当销售人员访问了所有城市时,在这种情况下为{A,B,C,D},离开的点 A 被自动添加到状态中,这意味着{A,B,C,D,A}。因此,这个 TSP 的初始状态是{A},最终状态(目标)是{A,X1,X2,X3,A},在这里旅行距离最小化。
把每个状态作为一个树结构的节点,我们可以把这个 TSP 表示为下面的树搜索问题。
强力搜索
深度优先搜索
深度优先搜索算法从根节点开始,在进行回溯之前沿着每个分支尽可能深地探索。在我们的 TSP 中,当一个带有所有城市标签的状态节点被访问时,它的总距离被存储。该信息稍后将用于定义最短路径。
设访问是一个 栈 来保存访问过的节点,路径是一个集合来保存从根节点到目标的距离。深度优先算法可以写成
广度优先搜索
深度优先搜索算法从根节点开始,在移动到下一个深度级别的节点之前,探索当前深度级别的所有节点。在我们的 TSP 中,当一个带有所有城市标签的状态节点被访问时,它的总距离被存储。该信息稍后将用于定义最短路径。
设访问是一个 队列 来保存访问过的节点,路径是保存从根节点到目标的距离的集合。广度优先算法可以写成
启发式搜索
在强力搜索中,访问所有节点,并且不考虑来自每个节点的信息(从节点到节点的距离)。这导致了大量的时间和内存消耗。为了解决这个问题,启发式搜索是一种解决方案。每个状态节点的信息用于考虑是否访问一个节点。该信息由通常由用户经验建立的启发式函数来表示。例如,我们可以通过从根节点到当前访问节点的距离,或者从当前访问节点到目标节点的距离来定义启发式函数。
最佳优先搜索
在最佳优先搜索中,我们使用到根节点的距离信息来决定首先访问哪个节点。设 g(X)为根节点到 node-X 的距离,因此,根节点访问 node-X 到 node-Y 的距离为 g(Y)=g(X)+d(X,Y),其中 d(X,Y)为 X 和 Y 之间的距离。
让 VISIT 成为一个 列表 来保存访问过的节点。最佳优先算法可以写成
A 算法(a*-算法)
在 A 算法搜索中,我们使用从当前访问节点到目标的距离信息作为启发式函数 h(X)。设 g(X)是根节点到 node-X 的距离,在这种情况下,我们按 f(X)=g(X)+h(X)考虑节点访问顺序的优先级。
在现实问题中,不可能获得 h(X)的精确值。在这种情况下,使用 h(X)的估计值 h’(X)。然而,设置 h’(X)有陷入局部最优解的风险。为了防止这个问题,建议选择 h'(X)其中 h'(X)≤h(X)用于所有 X。在这种情况下,它被称为 a*-算法,并且可以表明所获得的答案是全局最优答案。
在下面描述的实验中,我们将 h'(X)设置为从当前访问节点标签中未出现的每个城市到当前城市的所有可能路线的最小距离之和。例如,如果当前节点是{A,D},则城市 B 和 C 不会出现在标签中。因此,h'(D)=min(从 C 开始的所有可能的路线距离)+min(从 B 开始的所有可能的路线距离)+min(从 D 开始的所有可能的路线距离)。
让 VISIT 成为一个 列表 来保存访问过的节点。A 算法可以写成
搜索算法之间的比较
我们用每一个引入的算法模拟 TSP,并把重点放在搜索问题的有效性上。在这里,搜索问题的有效性通过到达答案所访问的节点数和与树的深度级别相比的
有效分支数来评估。一个问题的有效分支数 b是通过
N+1 = 1 + b + (b) +(b) +…+(b)^d 来计算的,b越小的算法越有效。在这个实验中,我们用牛顿法求解这个方程,得到 b*的近似值。
关于访问节点数的讨论
关于有效分枝数的讨论
用 Python 实现
**# Randomly generate problem**import randommax_city_number = 8Gs = []for NN in range(2,max_city_number):Gs.append([[random.randint(1,10) for e in range(NN+1)] for e in range(NN+1)])**# Problem state representation: Tree structure**class node(object):def __init__(self,number=None):self.pre = Noneself.no = numberself.label = []self.child = []self.cost = None def add_child(self,number):tmp_node = node(number=number)tmp_node.pre = selftmp_node.label=[i for i in self.label]tmp_node.label.append(number)tmp_node.cost= get_bound(tmp_node.label)self.child.append(tmp_node)**# Evaluate Function for A Algorithm**def get_bound(label):f = 0for i in range(0,len(label)-1):f = f+graph[label[i]-1][label[i+1]-1]remain = city.difference(set(label))remain = list(remain)remain.append(label[-1])for i in remain:f = f+min_bound[i-1]if len(remain)==2:f=0label.append(remain[0])label.append(1)for i in range(0,len(label)-1):f = f+graph[label[i]-1][label[i+1]-1]return f**# Evaluate Function for Best-first Algorithm**def get_bound(label):f = 0remain = city.difference(set(label))remain = list(remain)remain.append(label[-1])for i in remain:f = f+min_bound[i-1]if len(remain)==2:f=0label.append(remain[0])label.append(1)for i in range(0,len(label)-1):f = f+graph[label[i]-1][label[i+1]-1]return f**# Evaluate Function for Depth-first/Breadth-first Algorithm**def get_bound(label,n_city):f = 0for i in range(0,len(label)-1):f = f+graph[label[i]-1][label[i+1]-1]if len(label)==len(graph):f = f+graph[label[-1]-1][0]return f**# Effective Branch Number calculation (Newton's Method)**def f(N,d,x):return (x**(d+1) - (N+1)*x + N)**2def df(N,d,x):return 2*f(N,d,x)*((d+1)*x**d-(N+1))def ddf(N,d,x):return 2*df(N,d,x)*((d+1)*x**d-(N+1))+2*f(N,d,x)*((d+1)*d*x**(d-1))def solve(N,d):x = 1.9delta = 1.0count = 0while abs(delta)>0.000001 and count<10000:delta = df(N,d,x)/(ddf(N,d,x)+0.00001)x = x - deltacount = count + 1return x**# EXPERIMENT1/2:
# Search for GOAL (for A algorithm/Best-first Algorithm)**tree = node(number=1)tree.label.append(1)tree.cost=0 for i in range(len(Gs)):print("----------i=%d------------"%i)graph = Gs[i]NN = len(graph)for idx in range(NN):graph[idx][idx] = float('inf')city = range(1,len(graph)+1)city = set(city)min_bound = [min(graph[i]) for i in range(len(graph))] tree = node(number=1)tree.label.append(1)tree.cost=0 visit=[]visit.append(tree)count = 0fcnt = 0ans = 0while len(visit)>0:N = visit[0]if len(N.label)==(len(city)-2):fcnt = fcnt+1del(visit[0])count = count+1child_list = set(city).difference(set(N.label))if len(child_list)==0:ans = 1breakfor c in child_list:N.add_child(number=c)tmp = N.childfor i in tmp:visit.append(i)visit = sorted(visit,key= lambda x:x.cost) if ans==1:print("RESULT:",N.label,N.cost)b = solve(count,NN-2)print("d=%d ,N= %d , b*=%f"%(NN-2,count,b))print("ROUTEs: %d"%(fcnt))resultsA.append((NN-2,count,b))else:print("FAILED")**# EXPERIMENT3:
# Search for GOAL (for Depth-first algorithm)**tree = node(number=1)tree.label.append(1)tree.cost=0for i in range(len(Gs)):print("----------i=%d------------"%i)graph = Gs[i]NN = len(graph)for idx in range(NN):graph[idx][idx] = float('inf')city = range(1,len(graph)+1)city = set(city)tree = node(number=1,n_city=len(city))tree.label.append(1)tree.cost=0visit=[]paths = []count = 0fcnt = 0visit.append(tree)while len(visit)>0:if len(visit)==0:breakN = visit.pop()if len(N.label)==(len(graph)+1):paths.append(N)fcnt = fcnt+1paths=sorted(paths,key= lambda x:x.cost)count = count+1child_list = set(city).difference(set(N.label))if len(child_list)==0:continuefor c in child_list:N.add_child(number=c)tmp = N.childfor i in tmp:visit.append(i)print("RESULT:",paths[0].label,paths[0].cost)print("d=%d ,N= %d , b*=%f"%(NN-2,count,solve(count,NN-2)))print("ROUTEs:%d"%(fcnt))**# EXPERIMENT4:
# Search for GOAL (for Breadth-first algorithm)**tree = node(number=1)tree.label.append(1)tree.cost=0for i in range(len(Gs)):print("----------i=%d------------"%i)graph = Gs[i]NN = len(graph)for idx in range(NN):graph[idx][idx] = float('inf')city = range(1,len(graph)+1)city = set(city)tree = node(number=1,n_city=len(city))tree.label.append(1)tree.cost=0visit=[]paths = []count = 0fcnt = 0visit.append(tree)while len(visit)>0:if len(visit)==0:breakN = visit[0]
del(visit[0])if len(N.label)==(len(graph)+1):paths.append(N)fcnt = fcnt+1paths=sorted(paths,key= lambda x:x.cost)count = count+1child_list = set(city).difference(set(N.label))if len(child_list)==0:continuefor c in child_list:N.add_child(number=c)tmp = N.childfor i in tmp:visit.append(i)print("RESULT:",paths[0].label,paths[0].cost)print("d=%d ,N= %d , b*=%f"%(NN-2,count,solve(count,NN-2)))print("ROUTEs:%d"%(fcnt))
基本算法—计数求逆
分裂-征服方法在随机数组中找到反转对的效率比暴力方法高多少
尽管近年来计算能力有了显著的提高,但是在大型数据集上操作仍然是昂贵的。因此,编写经济高效的代码是数据科学家的关键技能之一。虽然成本与输入数据大小成线性关系的算法可能与成本为*方的算法差别不大,但当数据集增加到数百万时,前者具有巨大的优势。
编写更有效算法的一个基本方法是分治法,在这种方法中,我们编写一个嵌套函数,递归地将相同的函数应用于输入子集。在这篇文章中,我们将比较分裂征服法和蛮力法在计算随机数组中的反转对。
亨利&公司在 Unsplash 上拍摄的照片
我们得到一组没有任何重复的数字,并被要求计算反转数。求逆是两个整数的数组中第Ij、I 个元素大于第 j 个元素的情况。
如果数组由(2,3,8,6,1)组成,我们可以找到(2,1),(3,1),(8,6),(8,1),(6,1)的五个逆。
最简单和最容易的方法是比较数组中的所有对。用数组长度 n 我们正好可以比较 n(n-1)/2 对,代价是θ(n)。下面是一个不到十行的简单代码示例:
def bf_inversion_count(array):
count = 0
for i in range(len(array)):
j = i + 1
while j < len(array):
if array[i] > array[j]:
count +=1
j += 1
return count
让我们想一个更好更有效的方法。我们可以修改合并排序算法。分治算法的成本是:
T(n) = 2T(n/2) + f(n)
其中,总成本 T(n) 是两个半大小数组的成本 T(n/2) 和对两个数组之间的反转进行计数的成本 f(n) 之和。我们应该可以使f(n)=θ(n)使得T(n)=θ(nlgn)。
这是我的示例代码,主要是添加了计数行的合并排序代码。
def sc_inversion_count(array):
length = len(array) if length == 1:
return array, 0 if length == 2:
if array[0] > array[1]:
return np.array([array[1], array[0]]), 1
else:
return array, 0
elif length > 2:
array_l = array[:length//2]
array_r = array[length//2:]
array_l_df = sc_inversion_count(array_l)
array_r_df = sc_inversion_count(array_r)
array_l_sorted = array_l_df[0]
array_r_sorted = array_r_df[0] length_l = len(array_l)
length_r = len(array_r) count = array_l_df[1] + array_r_df[1] l = 0
r = 0
sorted_list = []
for i in range(length):
if r == length_r:
sorted_list.append(array_l_sorted[l])
l += 1 elif l == length_l:
sorted_list.append(array_r_sorted[r])
r += 1
elif array_l_sorted[l] > array_r_sorted[r]:
sorted_list.append(array_r_sorted[r])
r += 1
count += len(array_l_sorted) - l
elif array_l_sorted[l] < array_r_sorted[r]:
sorted_list.append(array_l_sorted[l])
l += 1
return np.array(sorted_list), count
现在,我们可以比较分裂-征服方法与蛮力方法的效率。随着数组大小的增加,显然分裂-征服方法在计算成本方面提供了巨大的优势。这个结果清楚地描述了高效编写算法的重要性。
来源:作者的计算
基本算法—寻找最接近的一对
用分裂-征服算法确定二维*面上两点的最近对
编写性价比高的算法是作为一名数据科学家成功的关键之一,而在上一篇文章中我们在计算一个数组中的求逆时使用了分裂-征服法,这种方法的成本远低于蛮力法。这一次,我们将看到另一种分裂-征服算法如何从二维*面上的一组点中找到最近的一对点。
在时代广场或东京市中心仰望天空,我们会很容易找到最近的一对星星,因为在那里你只能看到几颗星星。如果你在一个不知名的地方,黑暗的夜空中无限多的星星会让你无法确定这一对。
对计算机来说也没什么不同;当他们确定*面上最接近的点对时,数据集的点越多,算法寻找距离最小的点对所需的时间就越长。成本的增加不仅仅是点的数量的线性增加,我们试图编写一个尽可能低的包含成本增加的算法。分裂-征服法在这个挑战中工作得很好,以类似的方式与算法计数倒置。
强力法——寻找最接近的一对
蛮力方法是,像在一个数组中计算反转一样,计算宇宙中每一对点的距离。对于 n 个点,我们需要测量 n(n-1)/2 个距离,成本是 n 的*方,即θ(n)。有了两个循环,这个算法的代码可以写成如下。
def **find_closest_brute_force**(array):
result = {}
result["p1"] = array[0]
result["p2"] = array[1]
result["distance"] = np.sqrt((array[0][0]-array[1][0])**2
+(array[0][1]-array[1][1])**2)
for i in range(len(array)-1):
for j in range(i+1, len(array)):
distance = np.sqrt((array[i][0]-array[j][0])**2
+(array[i][1]-array[j][1])**2)
if distance < result["distance"]:
result["p1"] = array[i]
result["p2"] = array[j]
result["distance"] = distance
return resultreturn result
现在我们想一个更好的方法,它的成本是。使用预分类和分治法是可能的。为了在一个坐标上对数组进行预排序,我们还使用了狭缝征服法,即合并排序算法。
合并排序
我们用一种叫做合并排序的算法对数组进行排序,这种算法比强力排序算法要快。merge-sort 算法拆分数组,对子数组进行排序(作为递归步骤),比较两个子数组中最年轻的数字并挑选较年轻的,并重复该操作,直到两个子数组都用完为止。每个递归步骤的开销仅为θ(n),因此算法的总开销保持在θ(nlgn)。
def **merge_sort**(array, coordinate=0):
length = len(array) if length == 1:
return array if length == 2:
if array[0][coordinate] > array[1][coordinate]:
return np.array([array[1], array[0]])
else:
return array
elif length > 2:
array_l = array[:length//2]
array_r = array[length//2:]
array_l_sorted = **merge_sort**(array_l, coordinate)
array_r_sorted = **merge_sort**(array_r, coordinate)
l_length = len(array_l)
r_length = len(array_r) l = 0
r = 0
sorted_list = []
for i in range(length):
if r == r_length:
sorted_list.append(array_l_sorted[l])
l += 1 elif l == l_length:
sorted_list.append(array_r_sorted[r])
r += 1
elif array_l_sorted[l][coordinate] > array_r_sorted[r][coordinate]:
sorted_list.append(array_r_sorted[r])
r += 1
elif array_l_sorted[l][coordinate] < array_r_sorted[r][coordinate]:
sorted_list.append(array_l_sorted[l])
l += 1
return np.array(sorted_list)
分治法——寻找最接近的一对
如上所述,我们的目标是写一个算法,以 O(nlgn)的代价找到最近的一对点。使用分治算法,其递归步骤花费 O(n) 每一步就足够了。该算法将阵列划分为子阵列,关键是看两个子阵列中最近的一对是否。
分裂征服算法按 X 坐标对数组进行排序,将排序后的数组一分为二,将该算法递归应用于子数组,并检查是否存在一个距离比子数组中的距离短的数组对。
def **find_closest_nest**(array):
X = **merge_sort**(array, 0)
length = len(X)
if length < 4:
return **find_closest_brute_force**(array)
else:
array_l = X[:length//2]
array_r = X[length//2:] dict_l = **find_closest_nest**(array_l)
dict_r = **find_closest_nest**(array_r)
if dict_l["distance"] > dict_r["distance"]:
dict_both = dict_r
else:
dict_both = dict_l
Y_list = []
for i in range(length):
if X[length//2-1][0]-dict_both["distance"] < array[i][0] < X[length//2-1][0]+dict_both["distance"]:
Y_list.append(array[i]) Y = **merge_sort**(np.array(Y_list), 1)
if len(Y) == 1:
dict_final = dict_both
elif len(Y) < 8:
dict_y = **find_closest_brute_force**(Y)
if dict_both["distance"] > dict_y["distance"]:
dict_final = dict_y
else:
dict_final = dict_both
else:
for i in range(len(Y)-7):
dict_y = **find_closest_brute_force**(Y[i:i+7])
if dict_both["distance"] > dict_y["distance"]:
dict_final = dict_y
else:
dict_final = dict_both
return dict_final
最后一步,查看跨子阵列的对,需要一些技巧来将成本保持在线性水*(例如 O(n) ) 。首先,我们将制作一个输入子集,它由距离 X 坐标中点 d 距离内的点组成; d 是子阵列内的一对之间的最短距离。如果我们在子阵列上找到最近的一对点,这对点应该存在于距离将阵列分成子阵列的线的距离 d 内。
在右手侧所示的例子中,子阵列中最近的一对在右侧子阵列中确定(注意虚线上的点属于左侧子阵列),其距离为 d 。
如果最接近的一对存在于左右子阵列中,那么这些点应该在从将阵列分成两个子阵列的虚线开始的 d 的范围内。因此,我们可以查看阴影范围内的子集。
其次,我们通过 Y 坐标对上一步中获得的子集进行排序。我们表明,我们必须着眼于只有八个连续点的集合,每个在排序子集。
如图所示,横跨左右子阵列的 2d* d 矩形中最多可以存在 8 个点(虚线上的点重复;两个属于左侧子阵列,另外两个在右侧)。
第三,我们查看按 Y 坐标排序的子集中的每组八个连续点。如果我们发现距离小于 d 的一对,这意味着最近的一对存在于子阵列中。这一步开销 O(n) ,这个递归算法的总开销停留在 O(nlgn)。
性能检查
我们了解到我们开发的分裂征服算法比暴力破解算法执行得更快。我们来比较两种算法的实际表现。在下面的图表中,两种算法的成本(执行时间)由不同大小的数组显示。这两条线清楚地表明,随着样本量的增加,分治法具有优势。这个结果证明了高效编码的重要性,这在上一篇文章中也讨论过。
来源:作者的计算
基本算法—堆排序
用“堆”数据结构对数组排序
在以前的帖子中,我们看到了不同的排序算法,如合并排序和快速排序,这次讨论的是另一种排序算法 Heapsort。Heapsort,顾名思义,使用“堆”数据结构。
苏珊·霍尔特·辛普森在 Unsplash 拍摄的照片
许多
堆是一种数据结构,堆是二叉树的数组。二叉树的每个节点对应于数组的一个元素。由于一个节点有零个、一个或两个子节点,对于数组的第 i- 个元素,第 2i- 个和第( 2i+1 )个元素分别是其左右子节点。
下图描述了一个示例堆,其中节点数等于 12 元素数组中的顺序数。根是数组中的第一个元素,它的左右子元素分别是第二个和第三个元素。第六个元素只有一个左子,第七个没有。
最小堆示例
有两种堆:最小堆和最大堆。在最小堆中,父节点比子节点小(根节点最小),而在最大堆中则相反(根节点最大)。在本文中,我们将使用 max-heap 属性进行堆排序。
堆排序
策略如下:I)将数组转换成最大堆;ii)挑选根,这是最大数;iii)将剩余的数组保持为最大堆;iv)递归 ii)和 iii)。
下面是步骤 iii)的代码,它也用于步骤 I)。这个“Max-Heapify”函数有两个输入:一个数组和一个整数。该函数将给定顺序的节点(输入整数)与其两个子节点进行比较。如果节点比任何一个子节点都小,它将与两个子节点中最大的一个交换。
def **max_heapify**(array, i):
l = (i+1) * 2 - 1
r = (i+1) * 2
length = len(array) if l < length and array[l] > array[i]:
largest = l
else:
largest = i
if r < length and array[r] > array[largest]:
largest = r
if largest != i:
largest_value = array[largest]
array[largest] = array[i]
array[i] = largest_value
**max_heapify**(array, largest)
return array
虽然 Max-Heapify 不会耗尽整个堆,但是通过对除了叶子(堆的末端节点)之外的所有节点操作该函数,我们可以将任何数组转换为 max-heap。
def **build_max_heap**(array):
length = len(array)
for i in range(length//2, -1, -1):
**max_heapify**(array, i) return array
现在我们准备实现 Heapsort。
def **heap_sort**(array):
length = len(array)
array = **build_max_heap**(array)
for i in range(length-1, 0, -1):
largest = array[0]
array[0] = array[i]
array[i] = largest
**max_heapify**(array[:i], 0)
return array
下图解释了 Heapsort 如何处理一个 12 元素数组;I)首先,我们将数组转换为最大堆;ii)取根 12,用最后一个元素 3 代替;iii)在剩余的 11 元素数组的根上处理 Max-Heapify,受影响的节点以深蓝色显示;iii)递归 ii)和 iii)。最后我们将得到一个按升序排序的数组。堆排序就地操作,在输入数组之外只存储恒定数量的数据。
示例堆排序过程
堆集成本
我们可以通过检查 Max-Heapify 和 Build-Max-Heap 的子函数来分析 Heapsort 的开销。
Max-Heapify 的代价是 O(lgn) 。比较一个节点和它的两个子节点的成本θ(1),在最坏的情况下,我们递归 ⌊log ₂ n⌋ 次到底部。或者,Max-Heapify 的成本可以用堆的高度hO(h)来表示。
Build-Max-Heap 的开销是 O(n) 。由于一个 n 元素堆的深度为 ⌊lgn⌋ ,并且在任意高度,除了叶子之外还有 ⌈n/2ʰ⁺ ⌉ 节点,我们可以将成本导出为 Max-Heapify 成本的总和 O(h) ,如左图所示。
Heapsort 的总开销是 O(nlgn) ,因为它调用 Build-Max-Heap ( O(n) )和 Max-Heapify ( O(lgn) )超过 (n-1) 次。
性能检查
下图描述了不同的排序算法。正如预期的那样,Heapsort 遵循其他的 O(nlgn) -cost 算法,尽管它不如隐藏在 O 符号中的常数更高的 Quicksort 便宜。
来源:作者的计算
尽管 Heapsort 在排序算法上不如 Quicksort,但是 Heap 作为数据结构提供了许多不同的用途,其中最值得注意的是在优先级队列中。作为对堆的介绍,我们将在后面看到堆是如何应用于一个有效的优先级队列算法的。
基本算法—快速排序
用随机选择的枢轴对数组排序
我在的上一篇文章中介绍了一种叫做 Merge-Sort 的排序算法,并在这篇文章中继续讨论另一种排序算法 Quicksort。快速排序的期望代价是θ(nlgn),而代价为θ(n)的最坏情况只会以 2 /n 的概率出现!。我将在稍后的性能比较中展示隐藏在θ符号中的常数在 Quicksort 中更低,因此该算法优于成本相同的 Merge-Sortθ(nlgn)。
安德鲁·布坎南在 Unsplash 上拍摄的照片
插入排序
插入排序是一种强力算法,它比较数组中的所有对来排序。这是人们在 porker 或其他纸牌游戏中常用的发牌方式。代价是θ(n)。
def **insertion_sort**(array):
for j in range(1, len(array)):
key = array[j]
i = j - 1
while i >= 0 and array[i] > key:
array[i+1] = array[i]
i -= 1
array[i+1] = key
return array
合并排序
在之前的文章中,我们讨论了作为基本分治算法之一的合并排序算法。这一次,我们将使用一个更简单的版本,因为我们只处理一维数组。
def **merge_sort**(array):
length = len(array)
if length == 1:
return array
elif length == 2:
if array[0] > array[1]:
return np.array([array[1], array[0]])
else:
return array
elif length > 2:
array_l = array[:length//2]
array_r = array[length//2:]
array_l_sorted = **merge_sort**(array_l)
array_r_sorted = **merge_sort**(array_r) l = 0
r = 0
l_length = len(array_l)
r_length = len(array_r)
sorted_list = []
for i in range(length):
if r == r_length:
sorted_list.append(array_l_sorted[l])
l += 1 elif l == l_length:
sorted_list.append(array_r_sorted[r])
r += 1
elif array_l_sorted[l] > array_r_sorted[r]:
sorted_list.append(array_r_sorted[r])
r += 1
elif array_l_sorted[l] < array_r_sorted[r]:
sorted_list.append(array_l_sorted[l])
l += 1
return np.array(sorted_list)
快速排序
快速排序算法从一个数组中随机选取一个轴心,并将原始数组分成两个子数组:一个子数组由小于轴心的数字组成,另一个子数组由较大的数字组成。通过递归地这样做,我们将最终获得排序后的数组。
这里有一个简单的例子,你有一个 8 个数字的数组。在这种情况下,随机选择的支点变成了 6 个。然后,将小于 6 的数字分配给左边的子数组,将较大的数字分配给右边的子数组。
下一步是将算法递归应用到子阵列;随机枢轴现在在左(较小)子阵列中有两个,在右(较大)子阵列中有七个。通过递归地这样做,你将得到一个排序后的数组。
def **quick_sort**(array):
length = len(array)
if length <= 1:
return array
if length == 2:
if array[0] > array[1]:
return [array[1], array[0]]
else:
return array
else:
pivot = np.random.randint(0, length)
small = []
large = []
for element in array:
if element < array[pivot]:
small.append(element)
elif element > array[pivot]:
large.append(element)
if not small:
return [array[pivot]] + **quick_sort**(large)
elif not large:
return **quick_sort**(small) + [array[pivot]]
else:
return (**quick_sort**(small)
+ [array[pivot]]
+ **quick_sort**(large))
在最坏的情况下,你可以按升序或降序随机选择支点(例如,在上面的例子中,1 比 8 或 8 比 1),成本将是θ(n)。然而,这是可以忽略的,因为它发生的概率只有 2/n!(例中 21600 次一次)。所以我们考虑算法的期望成本。
排序算法的成本取决于它们比较了多少对。让我们考虑一下一个数组中的两个数 Zi 和 Zj (i < j) 进行比较的概率。 Zi 和 Zj 只有在 Zi 或 Zj 被选作支点时才直接比较,如果 Zi 和 Zj 之间的任意一个数被选作支点,则从不直接比较( Zi 和 Zj 被分配给单独的子阵)。当在子和 Zj、之外选择一个支点时,不会影响概率,因为子和 Zj 在同一个子阵列中。这样,子和 Zj 直接比较的概率是 2/(j - i+1) 。
因此,预期的比较次数是数组中所有数字对的 2/(j - i+1) 之和。
通过一些如左图所示的变形,我们发现该数字收敛到熟悉的θ(nlgn)。我们可以说快速排序算法的期望代价是θ(nlgn)。
就地快速排序
我们可以就地编写 Quicksort 算法,这意味着该算法只存储原始数组之外的常量数据。就地算法具有占用内存少的优点。下面是就地快速排序算法的代码。
def **quick_sort_in_place**(array, start, end):
if start < end:
if start + 1 == end:
if array[start] > array[end]:
larger = array[start]
array[start] = array[end]
array[end] = larger
pivot = np.random.randint(start, end+1)
pivot_value = array[pivot]
array[pivot] = array[-1]
array[-1] = pivot_value
border = start - 1
for i in range(start, end):
if array[i] < pivot_value:
border += 1
border_value = array[i]
array[i] = array[border]
array[border] = border_value
array[-1] = array[border+1]
array[border+1] = pivot_value
array = **quick_sort_in_place**(array, start, border+1)
array = **quick_sort_in_place**(array, border+2, end) return array
性能检查
现在我们比较插入排序(θ(n))、合并排序(θ(nlgn))和快速排序(预期θ(nlgn))的性能。
来源:作者的计算
显然,合并排序和快速排序比插入排序有优势,它们的斜率比插入排序*缓。由于隐藏在θ(nlgn)符号中的常数较低,快速排序算法比合并排序更快,而快速就地排序与合并排序花费的时间一样多(即就地优势被一些其他成本抵消)。
由于快速排序算法包含一些随机性,所以查看试验的成本分布是有用的。这是快速排序和合并排序算法处理 2 个⁰数 10,000 次试验的成本直方图。注意,如图所示,合并排序也容易出现随机性。两种分布都向最便宜的一端倾斜(左)。
来源:作者的计算
我们从快速排序算法中学到的一件事是,随机性可以成为我们的朋友。快速排序比其他排序算法更有效地处理大量数字。有了适当的概率论知识,我们也许能够写出成本较低的算法。
作为数据科学家,您需要了解的基本业务概念
初学者指南和基本商业基础的复*
肖恩·波洛克在 Unsplash 上的照片
目录
如果我问你数据科学是什么,你会怎么想?
我敢打赌,你们很多人都会想到大数据、机器学*模型和人工智能。但是我敢打赌,你没有考虑到业务,这是完全合理的。如果数据科学完全是关于商业的,公司就不会雇佣那些有 STEM 背景的人。
也就是说,对于所有数据科学家来说,对业务基础有一个基本的了解是必不可少的。通过了解业务,您将更好地理解每个数据科学项目背后的动机,以及每个项目如何使整个公司受益。
话虽如此,让我们来谈谈企业的主要目标。
企业的主要目标
企业的首要目标是为其所有者获取最大利润
所有者是指公司的创始人,如果公司是上市公司,也指公司的股东。你必须理解这一点,因为每个公司的决策都围绕着利润最大化。
利润等于收入和成本之间的差额。收入定义为收益。成本又称费用,定义为公司运营产生收益所花费的金钱。
为什么了解这一点对您很重要?因为业务中的每一项举措(例如数据科学项目)都是为了增加收入或降低成本以实现利润最大化。从本质上来说,不同的业务部门可以归为两类:收入最大化和成本最小化。
收入最大化
属于这一类别的两个主要部门是产品和营销:
产品和数据科学
一个产品可以是一件商品、一项服务或一个想法,是为了满足一种需求而创造的。例如,汽车是一种商品,是为了满足运输的需要而产生的。
然而,对于业务部门来说,产品是指与产品研发、开发和维护相关的所有活动。不要把这个“产品”的定义和上面的混淆了!
就产品而言,数据科学有两个目的:创造新产品和增强现有产品。自动驾驶汽车是数据科学如何帮助创造新产品的一个例子。然而,更常*的是,数据科学用于增强现有产品。这方面的一个流行的例子是网飞如何开发一个最先进的推荐系统。
营销和数据科学
营销的正式定义是所有与促进购买或销售产品相关的活动。营销包括广告、定价和了解目标市场等内容。市场营销曾经是一门艺术,而不是一门科学,但数据科学已经彻底改变了公司进行市场营销的方式。
数据科学在营销中的应用示例包括:
- 营销归属:一个公司可以使用的营销渠道有几十种。社交媒体、联盟营销、SEO、SEM、博客、电视、广播等等。但是一个公司怎么知道哪些营销渠道比其他的更有效呢?数据科学用于尝试通过归因建模和营销组合建模等方法来衡量各种营销渠道的影响。
- 定价和折扣优化:通过提高产品价格,利润变得更高,但想购买该产品的顾客会更少,反之亦然。这意味着每种产品都有一个最优价格来实现利润最大化。数据科学被用来寻找最优价格。
- 顾客细分:虽然看起来令人惊讶,但许多企业并不十分了解他们的顾客。聚类方法通常用于更好地了解客户群的特征。例如,如果一家公司通过集群意识到他们的产品在青少年中受欢迎,而不是中年人,那么该公司可以重新调整他们的广告策略。
- 流失预测建模:当客户流失时,意味着他们决定停止与该公司的业务往来。例如,如果一家公司与手机公司 A 合作,但转到了公司 B,那么客户就会从公司 A 流失。公司现在正在开发模型来预测客户何时会流失,并制定留住客户的计划。
成本最小化
属于这一类别的数据科学活动可以用一个词来描述;自动化。数据科学发挥巨大作用的两个主要部门是运营和客户服务。
运营和数据科学
由 Ruchindra Gunasekara 在 Unsplash 上拍摄的照片
企业经营是指企业每天从事的活动。通常,运营的主要目标是尽可能提高任务和流程的效率,这意味着在最大限度减少错误的同时最大限度地增加完成任务的时间。人类效率低,成本高,但自动化可以代替人类完成重复而*凡的任务。运营自动化的一个流行例子是亚马逊的仓库机器人。
客户服务和数据科学
客户服务是指公司向客户提供的支持。随着公司规模的增长,有理由认为需要支持的客户数量也会相应增加。就像我之前说的,人类效率低,成本高,这就是为什么数据科学也给客户服务带来了革命。最普遍的例子是聊天机器人的开发。虽然聊天机器人还不能完全取代人类,但它们可以回答简单的问题,并通过 NLP 算法将客户重定向到正确的服务代表。
okr 和 KPI
既然你已经知道了企业的主要目标,以及每一项举措是如何增加收入或降低成本的,我们就可以谈论一下 OKRs 和 KPI 了。
是目标&关键结果的简称,它是一个定义和跟踪目标及其结果的框架——你可以把它们看作目标。通常情况下,每个部门都有自己的 okr,每个季度设置一次。例如,营销部门可能有一个 OKR 来增加从 X 到 y 的转化率
KPI 是关键绩效指标的缩写,它们本质上是显示公司如何有效实现其业务目标的指标。继续以营销为例,上述目标的 KPI 可以是网站流量的增加或营销 ROI 的增加。
作为一名数据科学家,了解这两个术语非常重要,因为它们是机器学*生命周期规划阶段的一部分,我接下来会谈到这一点。
机器学*生命周期的规划阶段
在你开始任何机器学*项目之前,你需要计划一些事情。这一步的主要目的是让公司了解一个给定的项目将如何为公司增加价值,是通过增加收入还是降低成本。
规划包括以下任务:
- 陈述你试图解决的问题。这似乎是一个简单的步骤,但你会惊讶地发现,人们经常试图为一个不存在的问题或一个实际上并不存在的问题找到解决方案。
- 定义你为解决问题而努力实现的业务目标。这听起来像是在定义 OKR,不是吗?这不是巧合。
- ****确定目标变量(如适用)和您可能想要关注的潜在特征变量。例如,如果目标是减少欺诈性交易的数量,您很可能需要欺诈性和非欺诈性交易的标记数据。您可能还需要像交易时间、帐户 ID 和用户 ID 这样的特性。
- ****考虑任何限制、意外和风险。这包括但不限于资源限制(缺少资金、员工或时间)、基础设施限制(例如缺少训练复杂神经网络的计算能力)和数据限制(非结构化数据、缺少数据点、无法解释的数据等)
- 建立你的成功标准**。这听起来像是一个 KPI,不是吗?你如何知道你已经成功实现了你的目标?如果你的机器学*模型有 90%的准确率是成功的吗?85%呢?准确性是最适合您的业务问题的衡量标准吗?查看我关于 的文章,数据科学家使用这些指标来评估他们的模型 。
感谢阅读!
如果你喜欢我的工作,想支持我…
- 支持我的最好方式是在媒体上关注我这里。
- 在 Twitter 这里成为第一批关注我的人之一。我会在这里发布很多更新和有趣的东西!
- 此外,成为第一批订阅我的新 YouTube 频道 这里!
- 在 LinkedIn 上关注我这里。
- 在我的邮箱列表** 这里报名。**
- 看看我的网站,terenceshin.com。
用 Python 实现科学数据的基本曲线拟合
Python 科学绘图
使用 Python 将非线性函数拟合到实验数据点的基本指南
克里斯·利维拉尼在 Unsplash 上拍摄的照片
除了从我们的实验中绘制数据点之外,我们还必须经常将它们拟合到理论模型中,以提取重要的参数。这篇短文将指导如何将一组点拟合到一个已知的模型方程,我们将使用scipy.optimize.curve_fit
函数来完成。用 Python 为科学出版物绘制数据的基础知识可以在我之前的文章这里中找到。我将介绍三种常*的非线性拟合:(1)指数拟合,(2)幂律拟合,以及(3)高斯峰值拟合。
为了使用curve_fit
函数,我们使用下面的import
语句:
# Import curve fitting package from scipy
from scipy.optimize import curve_fit
在这种情况下,我们只使用scipy
包中的一个特定函数,所以我们可以直接导入只是 curve_fit
。
指数拟合
假设我们有一个如下形式的一般指数函数,我们知道这个表达式适合我们的数据(其中 a 和 b 是我们将适合的常数):
一般指数函数
首先,我们必须定义如上所示的指数函数,以便curve_fit
可以使用它来进行拟合。
# Function to calculate the exponential with constants a and b
def exponential(x, a, b):
return a*np.exp(b*x)
我们将从生成一个“虚拟”数据集来适应这个函数开始。要为我们的 x 值生成一组均匀分布在指定间隔上的点,我们可以使用np.linspace
函数。
# Generate dummy dataset
x_dummy = np.linspace(start=5, stop=15, num=50)
start
—我们序列的起始值
stop
—序列的结束值(将包括该值,除非您提供额外的参数endpoint=False
)
num
—将间隔分割成的点数(默认为50
)
注意,您不需要显式地写出输入名称— np.linspace(-5, 5, 100)
同样有效,但是对于本文的目的来说,它使事情更容易理解。
对于我们的虚拟数据集,我们将把 a 和 b 的值都设置为 0.5。
# Calculate y-values based on dummy x-values
y_dummy = exponential(x_dummy, 0.5, 0.5)
为了确保我们的数据集不是完美的,我们将使用np.random.normal
在我们的数据中引入一些噪声,它从正态(高斯)分布中抽取一个随机数。然后,我们将这个随机值乘以一个标量因子(本例中为 5 ),以增加噪声量:
# Add noise from a Gaussian distribution
noise = 5*np.random.normal(size=y_dummy.size)
y_dummy = y_dummy + noise
size
—随机数输出数组的形状(在这种情况下与y_dummy
的大小相同)
现在,让我们绘制我们的虚拟数据集,以检查它看起来像什么。因为我们有一个噪声数据点的集合,我们将做一个散点图,我们可以很容易地使用ax.scatter
函数。我将跳过许多情节美学上的修改,这些在我的上一篇文章中详细讨论过。为了指定点的颜色,我直接使用了十六进制代码。
# Plot the noisy exponential data
ax.scatter(x_dummy, y_dummy, s=20, color='#00b3b3', label='Data')
s
—以(点)为单位的标记大小,因此当该值增加四倍时,标记大小加倍
添加高斯噪声的虚拟指数数据散点图
一种通常更有用的可视化指数数据的方法是使用半对数图,因为它将数据线性化。为了将 y 轴的刻度从线性设置为对数,我们添加以下行:
# Set the y-axis scaling to logarithmic
ax.set_yscale('log')
由于对数函数中的渐近线,我们现在还必须将 y 轴下限设置为大于零。此外,对于刻度线,我们现在将使用LogLocator
功能:
# Set the y-ticks
ax.yaxis.set_major_locator(mpl.ticker.LogLocator(base=10.0))# Set the y-axis limits
ax.set_ylim(0.1, 1000)
base
—用于对数轴主刻度的基数
带有对数 y 轴的虚拟指数数据散点图
我们现在可以将我们的数据拟合到一般的指数函数中,以提取参数 a 和 b ,并将拟合叠加到数据上。请注意,尽管我们在上面给出了半对数图,但我们实际上并没有改变y 数据——我们只是改变了 y 轴的刻度。因此,我们仍然在拟合非线性数据,这通常更好,因为在拟合之前对数据进行线性化会改变拟合的残差和方差。
# Fit the dummy exponential datapars, cov = curve_fit(f=exponential, xdata=x_dummy, ydata=y_dummy, p0=[0, 0], bounds=(-np.inf, np.inf))
输入
f
—用于装配的功能(在本例中为exponential
)
xdata
—拟合的 x 数据数组
ydata
—拟合的 y 数据数组
p0
—拟合参数的初始猜测值数组(aa和 bb均为 0)
bounds
—参数的界限(-∞到∞)
输出
pars
—来自 fit 的参数数组(在本例中为[a, b]
)
cov
—pars
的估计协方差,可用于确定拟合参数的标准偏差(对角线的*方根)
我们可以从curve_fit
输出中提取参数及其标准偏差,并通过从实际观察值(我们的虚拟数据)中减去计算值(从我们的拟合中)来计算残差
# Get the standard deviations of the parameters (square roots of the # diagonal of the covariance)
stdevs = np.sqrt(np.diag(cov))# Calculate the residuals
res = y_dummy - exponential(x_dummy, *pars)
*pars
—允许我们展开pars
数组,即 [a, b]
作为a, b
输入
拟合参数和标准偏差
a =0.509 0.017
b = 0.499 0.002
我们看到两个拟合参数都非常接近我们的输入值a = 0.5
和b = 0.5
,因此curve_fit
函数收敛到正确的值。现在,我们可以将拟合叠加到散点数据上,还可以绘制残差,残差应该是随机分布的,并且接近于 0,从而确认我们有很好的拟合。
# Plot the fit data as an overlay on the scatter data
ax.plot(x_dummy, exponential(x_dummy, *pars), linestyle='--', linewidth=2, color='black')
linestyle
—绘制线的线型(--
表示虚线)
拟合线重叠的虚拟指数数据散点图
指数拟合的残差图
幂律拟合
另一种常用的拟合函数是幂律,其一般公式可以是:
一般幂律函数
与之前的拟合类似,我们首先定义函数:
# Function to calculate the power-law with constants a and b
def power_law(x, a, b):
return a*np.power(x, b)
然后,我们可以再次创建一个虚拟数据集,添加噪声,并绘制我们的幂律函数。
# Generate dummy dataset
x_dummy = np.linspace(start=1, stop=1000, num=100)
y_dummy = power_law(x_dummy, 1, 0.5)# Add noise from a Gaussian distribution
noise = 1.5*np.random.normal(size=y_dummy.size)
y_dummy = y_dummy + noise
添加了高斯噪声的虚拟幂律数据的散点图
与指数拟合情况类似,幂律函数形式的数据可以通过绘制对数图来线性化,这一次, x 和 y 轴都被缩放。
# Set the x and y-axis scaling to logarithmic
ax.set_xscale('log')
ax.set_yscale('log')# Edit the major and minor tick locations of x and y axes
ax.xaxis.set_major_locator(mpl.ticker.LogLocator(base=10.0))
ax.yaxis.set_major_locator(mpl.ticker.LogLocator(base=10.0))# Set the axis limits
ax.set_xlim(10, 1000)
ax.set_ylim(1, 100)
对数轴虚拟幂律数据散点图
现在,我们可以遵循与指数数据相同的拟合步骤:
# Fit the dummy power-law data
pars, cov = curve_fit(f=power_law, xdata=x_dummy, ydata=y_dummy, p0=[0, 0], bounds=(-np.inf, np.inf))# Get the standard deviations of the parameters (square roots of the # diagonal of the covariance)
stdevs = np.sqrt(np.diag(cov))# Calculate the residuals
res = y_dummy - power_law(x_dummy, *pars)
拟合参数和标准偏差
a = 1.057 0.096
b = 0.492 0.014
具有重叠拟合线的虚拟幂律数据散点图
幂律拟合的残差图
高斯峰值拟合
在诸如 X 射线衍射和光致发光的实验中,非常普遍地使用高斯函数、洛伦兹函数或两者组合的峰值拟合来确定线宽和其他属性。在这个例子中,我们将使用下面的通用公式来处理高斯峰值的拟合:
一般高斯函数
# Function to calculate the Gaussian with constants a, b, and c
def gaussian(x, a, b, c):
return a*np.exp(-np.power(x - b, 2)/(2*np.power(c, 2)))# Generate dummy dataset
x_dummy = np.linspace(start=-10, stop=10, num=100)
y_dummy = gaussian(x_dummy, 8, -1, 3)# Add noise from a Gaussian distribution
noise = 0.5*np.random.normal(size=y_dummy.size)
y_dummy = y_dummy + noise
添加了噪声的虚拟高斯数据的散点图
就像在指数和幂律拟合中一样,我们将尝试进行高斯拟合,每个参数的初始猜测值为 0。
# Fit the dummy Gaussian data
pars, cov = curve_fit(f=gaussian, xdata=x_dummy, ydata=y_dummy, p0=[0, 0, 0], bounds=(-np.inf, np.inf))# Get the standard deviations of the parameters (square roots of the # diagonal of the covariance)
stdevs = np.sqrt(np.diag(cov))# Calculate the residuals
res = y_dummy - power_law(x_dummy, *pars)
但是,当我们这样做时,我们会得到以下结果:
print(pars)
>>> [0\. 0\. 0.]print(stdevs)
>>> [inf inf inf]
似乎我们的初始猜测不允许拟合参数收敛,所以我们可以用更真实的初始猜测再次运行拟合。您可以通过检查要拟合的峰值并选择合理的初始值来实现这一点。
# Fit the dummy Gaussian data
pars, cov = curve_fit(f=gaussian, xdata=x_dummy, ydata=y_dummy, p0=[5, -1, 1], bounds=(-np.inf, np.inf))
这一次,我们的拟合成功了,我们得到了以下拟合参数和残差:
拟合参数和标准偏差
一个 = 8.074 0.128
b=–0.948 0.054
c = 2.945 0.054
覆盖拟合的虚拟高斯数据散点图
高斯拟合的残差图
结论
希望,在前面例子的引导下,你现在应该能够将你的实验数据拟合到任何非线性函数!我希望你喜欢这个教程,这里展示的所有例子都可以在这个 Github 仓库找到。
Python 中的基本日期时间操作
布鲁克·拉克在 Unsplash 拍摄的照片
有时,处理包含日期和时间的数据可能是一项乏味的工作,谢天谢地,有这种内置的方式来帮助我们完成这项工作。Python 提供了一个日期时间模块,使我们能够以多种方式操作日期和时间。
在这个模块中,我们需要查看五个主要的对象类,根据我们想要做的工作,我们最终会需要它们。之后,我们将讨论一些解释课程任务的例子。这些类别如下-
- datetime.date :它允许我们在不干扰时间(月、日、年)的情况下操作日期
- datetime.time :它允许我们在不干扰日期(小时、分钟、秒、微秒)的情况下操作日期
- datetime.datetime :它允许我们操作日期和时间的组合(月、日、年、小时、秒、微秒)。
- datetime.tzinfo :处理时区的抽象类。这些类型的对象是不可变的。例如,考虑不同的时区和/或夏令时。
- datetime.timedelta :两个日期、时间或日期时间实例之差;该决议案
创建日期时间对象
由于 datetime includes 使我们能够处理日期和时间,因此,首先让我们看看这个对象的行为。 datetime 既是一个模块,也是该模块中的一个类。我们将从 datetime 模块中导入 datetime 类,并打印当前的日期和时间以便仔细查看。我们可以使用 datetime 的. now()函数来做到这一点。我们将打印我们的日期时间对象。
# import datetime class from datetime module
from datetime import datetime
# get today's date
today = datetime.now()
print(today)
输出如下所示:
现在,如果我们想看类型,我们可以写:
print('Type :- ',type(today))
所以我们从上面看到今天确实是一个 datetime 类的 datetime 对象。
从上面的例子我们可以了解到日期和时间对象应该如何工作。日期只适用于日期,不包括时间,反之亦然。
dt_nw = datetime.now()
# to get hour from datetime
print('Hour: ', dt_nw.hour)
# to get minute from datetime
print('Minute: ', dt_nw.minute)
从 datetime 中,我们还可以使用它的。 weekday() 起数字的作用。但是我们可以使用日历模块和一种叫做的方法将它转换成文本格式(即星期一、星期二、星期三……)。日 _ 名()。
首先,我们将导入日历模块,然后找出月份和年份,并执行上述操作。
# import calendar module
import calendar
my_date= datetime.now()
# To get month from date
print('Month: ', my_date.month)
# To get month from year
print('Year: ', my_date.year)
# To get day of the month
print('Day of Month:', my_date.day)
# to get name of day(in number) from date
print('Day of Week (number): ', my_date.weekday())
# to get name of day from date
print('Day of Week (name): ', calendar.day_name[my_date.weekday()])
处理时区
现在我们需要了解两种 datetime 对象;
- 感知——感知对象具有处理模糊时间所需的知识,它包含时区和夏令时信息,因此它可以相对于其他感知对象定位自己。
- 天真——这个更容易处理。因为它不包含不同时区和夏令时的信息。操作仅仅依赖于程序。
对于需要 aware 对象的程序, datetime 、 date 和 time 对象有一个可选的时区信息属性, tzinfo 。但是 tzinfo 是一个抽象类。处理这个问题时,您必须决定到底需要哪些方法。因为这完全取决于对 aware datetime 对象的使用。
但是处理时区通过 pytz 模块变得很容易。它帮助我们处理跨时区转换,并处理使用该转换的地方的夏令时。让我们看看这个例子:
# import timezone from pytz module
from pytz import timezone
# Create timezone UTC
utc = timezone('UTC')
# Localize date & time
loc = utc.localize(datetime(2020, 1, 1, 3, 50, 0))
print(loc)
# Convert localized date & time into Asia/Dhaka timezone
dhaka = timezone("Asia/Dhaka")
print(loc.astimezone(dhaka))
# Convert localized date & time into Europe/Berlin timezone
berlin = timezone('Europe/Berlin')
print(loc.astimezone(berlin))
我们使用了 localize() 函数向 datetime 对象添加时区位置。函数 astimezone() 将现有的本地时区转换为任何其他指定的时区。
时间跨度和时差
有时在一个程序中,我们可能需要指定剩余时间或时间跨度。在这种情况下,我们总是可以使用时间增量对象。我们可以利用这一点,通过对日期或时间进行加减来操纵它们。让我们看一些例子:
#import timedelta
from datetime import timedelta
print(timedelta(days= 365, hours= 12, minutes= 30))
# get current time
now = datetime.now()
print ("Today's date & time: ", str(now))
#add 365 days to current date
future_date_after_one_year = now + timedelta(days = 365)
print('Date & time after one year: ', future_date_after_one_year)
#subtract 7 days from current date
seven_days_ago = now - timedelta(days = 7)
print('Date & time seven days ago: ', seven_days_ago)
# print('seven_days_ago object type: ', type(seven_days_ago))
这就是我们如何处理时间增量对象。在大多数科学脚本/案例中,delta 总是意味着两个事物之间的差异。
strftime() & strptime():日期格式
datetime 包含两个方法, strptime() 和 strftime() ,用于将对象从字符串转换为 datetime 对象,反之亦然。 strptime( )可以读取带有日期和时间信息的字符串并将其转换为 datetime 对象, strftime() 将 datetime 对象转换回字符串。
# import datetime
from datetime import datetime
date_str = "2 january, 2020"
# format date
date_obj = datetime.strptime(date_str, "%d %B, %Y")
print("Today's date is: ", date_obj)
现在让我们看看 strftime() 的用法:
# current date and time
now = datetime.now()
# format time in HH:MM:SS
time = now.strftime("%H:%M:%S")
print("Time:", time)
# format date
date_time = now.strftime("%m/%d/%Y, %H:%M:%S")
print("Date and Time:",date_time)
处理时间戳
在处理数据时,处理时间戳是非常常*的。也许你想以 Unix 时间戳格式存储你的数据。我们将使用 datetime 的 timestamp() 函数来完成这项工作。
# get current date
now = datetime.now()
# convert current date into timestamp
timestamp = datetime.timestamp(now)
print("Date and Time :", now)
print("Timestamp:", timestamp)
类似地,我们可以从时间戳转换成日期和时间对象。
timestamp = 1577971124.673931
#convert timestamp to datetime object
date_obj = datetime.fromtimestamp(timestamp)
print("Today's date & time:", date_obj)
熊猫日期时间对象
Pandas 是 python 中数据科学项目的主要成分,这是理所当然的。它使得处理日期和时间比其他任何方法都容易。
使用 to_datetime() 将日期和时间文本字符串转换成 pandas Datetime 对象要容易得多。
这个函数很擅长通过自动检测字符串的格式将字符串转换成 Python datetime 对象,而不需要我们使用 strftime 模式来定义它。
# import pandas module
import pandas as pd
# create date object using to_datetime() function
date = pd.to_datetime("2nd of jan, 2020")
print(date)
还有很多操作可以使用带有日期和时间数据的熊猫来完成。但这需要另一个自己的职位。然而,我希望这篇文章提供了关于我们可以用 datetime 模块和 pandas 进行的操作的初步概念。这里用到的所有代码都可以在我的 GitHub 账号https://github.com/muniah上找到。
原载于 2020 年 1 月 2 日 https://muniah.com。
A/B 测试的基本要素——用 Python 代码模拟
照片由 Unsplash 上的 battle creek 咖啡烘焙师拍摄
什么更重要?你花了多少天进行 A/B 测试?或者你每天的样本量?较大的样本量比运行 A/B 测试很多天要重要得多。这篇文章将通过模拟向你展示为什么会这样。
A/B 测试就像咖啡拔火罐;你想客观地决定哪种咖啡更好。这是这两个过程的目的,但是 A/B 测试确实试图做到客观。
假设你正在与一家大型电子商务公司合作。你的客户群*均每天购买 170 美元。网站设计团队希望引入一个更精简的网站,加载速度更快,他们假设这个新的网站设计不会降低*均订单价值。销售团队对此表示怀疑——由于这个新网站在主页上展示的产品较少,他们认为这将降低*均订单价值;他们不想在所有客户群中推出这个新网站。
你带着你的统计工具进来了:“为什么我们不在人口的一个小样本上测试这个,而不是在整个人口上?”
“听起来是个好主意”,web 团队和销售团队都同意,委托你设计测试,即 A/B 测试。
测试需要的东西:
- 您将需要一个控制样本—将向这些客户展示旧网站,他们将继续以相同的*均订单价值 170 美元购买
- 您还需要一个目标样本—您将向这些客户展示新网站
- 你必须选择目标样本的样本大小——最小的样本大小,因为销售团队认为这个新网站有风险
- 你将不得不选择几天来测试这个理论——同样是最少的,因为销售团队真的不急于改变网站,并且通常你想尽快知道这是否会对你的客户的购买*惯产生不利影响
从中心极限定理中你知道,你进行测试的天数越多,它就能更好地反映总体情况。但是您希望用最少的天数测试新特性,并尽快得出结论。
你运行一些模拟。
设置问题和模拟
但是,让我们后退一步,假设我们的控制样本和目标样本完全相同。本质上,我们没有推出一个新的网站。你也可以把这个场景表述为“我们将会看到,如果新网站没有对顾客购买产生影响,会发生什么”。我们一次随机抽取两个客户样本,并试图了解他们之间的差异是否纯粹是由于统计上的随机性。
换句话说,这是在问“如果你从同一个人群中随机抽取样本,他们的*均值有多不一样?”
因此,在本文的其余部分,让我们假设我们从相同的人群中抽取,也就是说,目标组和控制组都显示相同的网站。
让我们生成一个随机的指数分布(为什么是指数分布?我们在关于样本大小、、和均值、、的中心极限定理文章中讨论过,让我们这样做两次——一次针对对照样本,另一次针对(伪)目标样本。我说“伪”是因为他们都来自同一个人群,这是我们的客户群,显示在同一个网站上。每次这样做时,我们都会注意到对照样本和目标样本之间均值的差异:
δμ=对照样本的*均值—目标样本的*均值
那我们就这样做 n 次。
这是对照样本和目标样本之间的均值差异δμ,已绘制出来。
δμ(对照样本的*均值-目标样本的*均值):1)随着 A/B 测试天数的增加(列中向下)以及 2)随着样本量的增加(行中向右)。注意 x 轴上的范围:当您在一行中从左到右移动时,这个 x 轴范围会缩小,但是当您沿着任何一列向下移动时,这个范围或多或少会保持不变。
这些图说明了什么?
以下是一点一点的细节。但是,如果您有困难,请跳过这一步,跳到“模拟观察总结”部分。
增加天数:
- 左上图是当你两次吸引 1000 名顾客(控制和目标)时,你这样做 5 天。控制*均值和目标*均值之间的差值绘制在 x 轴上。
*所以你看到δμ(对照样本的均值——目标样本的均值)可以在负$5 和正$5 之间。也就是说,对照样本的*均值可能比目标样本的*均值少或多 5 美元。 - 如果你看第二行最左边的图,它显示了如果你重复上述实验 15 天会发生什么——也就是说,你抽取 1000 个客户的随机样本对,每个样本对 15 天,然后你看这些对的*均值之间的差异。你可以看到,在这里,大部分时间δμ都在正负 5 美元之间。两个样本(从同一人群中抽取)的*均值相差高达 5 美元。
- 事实上,您一直将天数增加到左下角的 60 天,同时保持 1000 名客户的相同样本量
*您会看到目标组和控制组*均值之间的差异仍然有很大变化——它可以在\(+/-20(x 轴的范围)之间变化,但大多数数据仍然在\)+/-5 之间。 - 所以这是一个问题。我们希望δμ接近 0 美元,因为两个样本都来自我们的同一批客户。
增加样本中的客户数量:
- 我们来看右上方的图。它显示了如果您绘制 5 天的 100,000 个客户对,并计算这些分布对的*均值之间的差异
*您会立即看到控制*均值减去目标*均值现在非常低,降至-0.75 美元至+$0.50 美元(x 轴范围)。也就是说,在所有 5 天的测试中,您的控制*均值和目标*均值的差异不会超过+/-1.00 美元。太好了!请记住,控制样本和目标样本来自相同的分布,因此它们的*均值应该大致相同 - 事实上,如果您使用相同的 100,000 个客户样本对进行 60 天的测试,就像右下角的图一样,您会看到控制*均值和目标*均值之间的差异仍然不会发生很大变化,实际上,它们仍然只相差 1.00 美元
模拟观察总结
- 这就是你看到的模式。如果您沿着任何特定的列向下,其中样本大小保持不变,天数增加,您看不到控制和目标*均值之间的差异δμ改善很多——X 轴上的范围保持不变。
- 如果沿着任何给定的行从左到右,也就是说,如果在保持天数不变的情况下增加样本量,那么您会看到控制*均值和目标*均值之间的差异迅速缩小。请记住,我们希望这样,因为控件和目标都来自同一个客户群——还没有引入网站更改。
A/B 测试参数估计—天数和样本量
这个故事的寓意——只要超过 5 天左右,A/B 测试的天数不会有太大影响。但是你每天看的顾客数量确实有很大的影响。
A/B 测试的天数
理想情况下,至少应该是 30 天。为什么是 30?嗯,30 这个数字背后并没有什么魔力,但在工业上,这已经足够了。从的中心极限定理帖子中,我们看到我们需要抽取足够数量的样本,以确保我们有一个良好的样本均值正态分布。但是没有企业会让你运行 30 天的 A/B 测试,大多数企业不会。
往往一个企业只会给你 7 天时间做结论。你确实可以在上面看到的短短 7 天内做出结论,如果你有一个好的样本量,我们将在下面讨论。
A/B 测试的目标群体的规模
剩下的就是目标群体(和对照组)的客户数量。这在很大程度上取决于你的企业愿意处理多少利润。在这个例子中,如果企业愿意说“由于纯粹的机会,5 美元的正负差异对我们没有影响”,那么您可以使用 1000 名客户的样本规模。如果企业要求他们可以处理不超过 1 美元的差异,那么您将不得不要求 100,000 名客户进行 A/B 测试,以确保您看到的任何差异都不是随机的。
但是,根据你公司的风险偏好,你如何得到准确的样本量呢?
我们可以参考这篇关于中心极限定理的文章。
在那里我们看到:
由于我们的总体是均值为 170 美元的指数分布,并且指数分布的均值和标准差相等,因此我们有:
现在你明白了为什么上面的一组图显示了当你从第一列移动到第三列时沿着 x 轴的分布减小了:当
样本量= 10(第一列)时
,σ(样本均值)=170/sqrt(10 )=$5.40
样本量= 10⁴(第二列),σ(样本 mean)=170/sqrt(10⁴)=$1.70
样本量= 10⁵(第三列),σ(样本 mean)=170/sqrt(10⁵)=$0.54
重新排列上述公式,我们得到样本量估计的方程:
其中,
σ_population 可以近似为总体均值,因为我们通常得到的是近似的指数分布,并且企业通常对总体均值有一个概念。在这种情况下,业务人员会告诉您,日*均订单价值为 170 美元。
σ_(样本均值)是你企业的风险偏好。例如,如果他们说“我们可以处理控制组和目标组之间不超过$2.00 的差异”,那么σ_(样本均值)=$2
在这个例子中,那么你的样本大小将是(170/2) =7225
其他注意事项
做完这一切后,你需要确保企业没有进行促销,或者你可以通过某种方式为你的控制和目标群体控制这些变量。然后,你必须确保你没有在你的目标群体或控制群体中意外地选择了更保守、更喜欢升职的人,反之亦然。但是如果你做了一个好的,真正随机的选择,那么这个问题就解决了。在后面的文章中,我将讨论如何选择一个真正随机的样本。
在下一篇文章中,我会告诉你如何评估你的 A/B 测试。
Python 代码再现情节
您可以使用以下代码生成本文中的图表:
**import** matplotlib.pyplot **as** plt
**import** matplotlib.patches **as** mpatch
**import** statistics
**import** numpy **as** np
**def** two_exponential_distributions(n, samp_size, mu):
*# do n times a sample of samp_size each with same mean sigma to see how they differ
# returns a list of tuples:
# each element in the list corresponds to one of the two distributions: so list is of length2
# each element in the list is a tuple; teh tuple returns the number of samples, the sample size, the mean and the stddev* del_m = []
m1arr = []
m2arr = []
**for** ii **in** range(0, n):
s1 = np.random.exponential(mu, samp_size)
m1 = np.mean(s1)
m1arr.append(m1)
s2 = np.random.exponential(mu, samp_size)
m2 = np.mean(s2)
m2arr.append(m2)
del_m.append(m1 - m2)
musig = []
musig.append((n, samp_size, statistics.mean(m1arr), statistics.stdev(m1arr), del_m))
musig.append((n, samp_size, statistics.mean(m2arr), statistics.stdev(m2arr), del_m))
**return** musig
**def** simulate_n_sampsize():
nn = [5, 15, 30, 60]
ss = [1000, 10000, 100000]
fig = plt.figure(figsize=(10, 7))
fig.suptitle(**'Difference of Average Order Value Between Control and (psuedo)Target'**)
fig.text(0.5, 0.04, **'Number of Customers'**, ha=**'center'**)
fig.text(0.04, 0.5, **'Number of Days'**, ha=**'center'**, rotation=**'vertical'**)
l1 = mpatch.FancyArrow(0.3, 0.08, 0.4, 0,
transform=fig.transFigure, figure=fig)
l2 = mpatch.FancyArrow(0.08, 0.7, 0, -0.3,
transform=fig.transFigure, figure=fig)
fig.lines.extend([l1, l2])
plt.subplots_adjust(hspace=0.5)
ii = 1
nsmusig = []
**for** n **in** nn:
**for** s **in** ss:
ax = fig.add_subplot(4, 3, ii)
musig = two_exponential_distributions(n, s, 2000)
ax.set_title(**'n={}, s={}'**.format(n, s))
ii += 1
nsmusig.append(musig[
0]) *# control sample's n, samp_size, statistics.mean(m1arr), statistics.stdev(m1arr) and del_m between control and target* nsmusig.append(musig[
1]) *# target sample's n, samp_size, statistics.mean(m1arr), statistics.stdev(m1arr) and del_m between control and target* plt.hist(musig[0][4], color=**'blue'**, edgecolor=**'black'**, bins=int(n), histtype=**'step'**)
**for** item **in** ([ax.title, ax.xaxis.label, ax.yaxis.label] +
ax.get_xticklabels() + ax.get_yticklabels()):
item.set_fontsize(8)
plt.show()
print(nsmusig)
print([x[2] **for** x **in** nsmusig])
print([x[2] **if** (x[0] == 5) **else** 0 **for** x **in** nsmusig])
print(**'some means'**)
**for** n **in** nn:
print(n)
print([x[2] **for** x **in** nsmusig **if** x[0] == n])
print(**'some stddevs'**)
**for** n **in** nn:
print(n)
print([x[3] **for** x **in** nsmusig **if** x[0] == n])
simulate_n_sampsize()
实现更高效机器学*的基础特征工程—下一步
克里斯多夫·伯恩斯在 Unsplash 上拍摄的照片
关于 ML 的一个重要的事情是,大多数机器学*算法在只有原始数据的情况下不会有效地执行。你不能仅仅将一组特性输入到模型中,然后期望它表现良好。尤其是当数据集中有非数字数据时,机器学*模型不会像预期的那样工作,并且准确率非常低。
在这篇文章中,我们将看看如何从一组干净的特性中获得更有意义的特性。为了更好地理解,我将使用一个基本的分类问题来解释检测网络 DDOS 攻击的概念。我以前写过一篇文章,介绍了特征工程的基本步骤,包括清理原始数据的不同方法,以及将非数字数据嵌入数字格式的一些基本方法。可以参考更好的理解(基础特征工程达到更高效的机器学*)。
衍生有意义的特征
衍生要素应在清理现有原始要素后执行。那些清除的数据可以是数字格式,也可以是非数字格式。衍生特征的格式取决于上下文。如果您打算直接将这些嵌入数据输入到模型中,那么根据您的模型,它们最好是数字格式。几乎所有机器学*模型的成功都取决于我们如何向模型呈现数据,也取决于训练。
衍生特征并不是一项困难的任务,但是需要对上下文或问题域有很好的理解。推导建立在上下文之上。比方说,对于您要检测的条件,有某个参数超过了阈值。但是如果没有很好地理解问题领域,您可能不知道这些参数、阈值或关系。此外,我们可能需要根据问题推导出多个这样的条件。我们拥有的功能越多,模型的性能就越好。现在让我们看看一些流行的方法来获得这样的特征。
1。通过参数之间的加/减
一种流行的技术是在参数之间加减。这种加减可以在同一列的参数内进行,也可以在不同列之间进行。
2。统计某个窗口内的发生次数
另一种流行的技术是计算一个窗口内的出现次数。大多数情况下,这用于检测是否超过阈值。如果您的输入涉及时间戳,则可以应用时间窗口(即在特定时间窗口内计算发生的次数)。
3。获取参数之间的比率
在某些情况下,两个或多个参数之间的比率代表该领域的某些特征。但是要识别这样的模式,你必须是该领域的专家,或者必须做大量的实验。
4。通过计算统计参数
像*均值、中值、众数和标准差这样的统计参数代表了领域的行为或特征。通过根据领域计算此类参数,您可能能够获得新的特征。然而,需要一些数学背景来容易地识别这种模式。
5。二元决策
二元决策的答案要么是“0”,要么是“1”。通过回答二元问题可以得出新的特征。例如,我们可以通过检查某个参数是否超过阈值来创建一个特性列。特征值将为代表问题答案的“0”或“1”。
6。交叉特征
特征交叉是最流行的技术之一,尤其是涉及到线性问题时。基本思想是通过将两个或多个现有特征相乘(即交叉)形成一个新特征。
上面提到的只是一些流行的获得特征的技术。你可以根据问题域随意定义和衍生任何特性。
在创建了新的特征并为模型选择了最好的特征之后,我们就可以训练模型了。然而,包括原始特征和新特征在内的所有特征可以采用不同的比例。特别是当我们应用像特征交叉或后比率这样的技术时,这些新值将比现有值具有更大的范围。所以我们必须把所有的柱子放在同一个尺度上。
正常化
规范化的最终目标是将所有值放在相同的范围内,从而提高模型的性能。有几种方法可以实现标准化。其中最著名的是。
缩放意味着将列的值转换成标准范围,通常是 0 到 1。但是,只有当列的值近似均匀地分布在整个范围内,并且我们知道数据列的上限和下限时,缩放才有效。Python scikit 学*库提供了缩放值的函数。
如果缩放不适用,您可以尝试一种其他方法,如特征裁剪、对数缩放或 z 分数。要素裁剪将超出特定阈值的值限制为固定值。对数标度通过计算数据的对数,将大范围的值压缩到小范围内。Z-score 表示偏离值集*均值的标准偏差数。
现在让我们通过一个例子来更好地理解特性的派生。
实例研究
让我们考虑一种 DDOS 攻击情况,攻击者试图使系统的目标用户无法使用资源。在 DDOS 攻击中,攻击者通常使用多台计算机向单个系统发送大量请求。通过考虑 DDOS 攻击的基本定义,我们可以确定以下两个特征(这两个不是仅有的两个特征)。
- 攻击者从一台计算机上发送同一组请求的频率比*时高得多。
- 攻击者使用位于不同位置的多台计算机发送请求。
首先,让我们考虑与这两个特征相关的原始特征。通常,一个网络请求包含一个时间戳(如果没有可以用 AI 引擎记录),消息体和包括源 IP 的报头。通过考虑第一个特性,我们可以创建一个特性来计算某个时间窗口内的请求数量。通常,特定网络资源有一个定义的阈值。这个阈值可以随时、因资源、因用户等而改变(这是我们必须使用 AI 来定义这样的阈值的一个原因)。我们可以定义一个特定长度的时间窗口,并计算该窗口内的请求数。输出编号是该模型的一个新功能。
通常,网络请求的报头包含请求的源 IP。IP 地址可用于检测原始系统的位置(位置、国家、州和许多其他事物的坐标可通过使用合适的数据库或 API 服务从 IP 地址获得)。通过考虑第二个特征,我们可以引入一个新的特征来检测在某个时间间隔内相同请求的位置变化。
考虑到上述两个特征,下面列出了检测 DDOS 攻击的两个衍生特征。请注意,上述两个特征并不是控制 DDOS 攻击的唯一两个特征,这两个特征的行为可能会因环境而异。此外,两个特征下面的并不是控制 DDOS 攻击特征的唯一两个特征,因此可能不足以检测攻击情况。
- 5 分钟时间窗口内对资源路径的请求数。
- 同一请求在 10 秒时间窗口内的位置变化距离。
结论
大多数机器学*算法在只有原始数据的情况下无法有效执行,因此需要应用特征工程技术。在本文中,我们已经确定了为机器学*模型派生新特征的重要性,以及如何在示例研究的帮助下派生有意义的特征。此外,我们还确定了标准化的重要性,以便将所有特征置于相同的范围内。作为结论,我想建议特征工程是大多数机器学*模型的核心。
Python 中的线性回归算法:一步一步
杰里米·毕晓普在 Unsplash 上的照片
学*线性回归的概念,并使用 python 从头开始开发一个完整的线性回归算法
最基本的机器学*算法必须是单变量线性回归算法。如今,有如此多的先进的机器学*算法、库和技术可用,以至于线性回归似乎并不重要。但是学*基础知识总是一个好主意。这样你会非常清楚地掌握这些概念。在本文中,我将逐步解释线性回归算法。
想法和公式
线性回归使用预测的非常基本的想法。公式如下:
Y = C + BX
我们在学校都学过这个公式。提醒一下,这是一条直线的方程。这里,Y 是因变量,B 是斜率,C 是截距。通常,对于线性回归,它被写成:
这里,“h”是假设或预测的因变量,X 是输入特征,θ0 和θ1 是系数。θ值是随机初始化的。然后使用梯度下降,我们将更新θ值以最小化成本函数。下面是成本函数和梯度下降的解释。
成本函数和梯度下降
成本函数决定了预测与原始因变量的距离。这是它的公式
任何机器学*算法的思想都是最小化代价函数,使假设接近原始因变量。为此,我们需要优化θ值。如果我们分别基于θ0 和θ1 对代价函数取偏导数,就会得到梯度下降。为了更新θ值,我们需要从相应的θ值中减去梯度下降:
偏导数之后,上面的公式将变成:
这里,m 是训练数据的数量,α是学*率。我说的是一元线性回归。这就是为什么我只有两个θ值。如果有很多变量,那么每个变量都会有θ值。
工作示例
我要用的数据集来自吴恩达在 Coursera 上的机器学*课程。下面是用 Python 一步步实现线性回归的过程。
- 导入包和数据集。
import numpy as np
import pandas as pd
df = pd.read_csv('ex1data1.txt', header = None)
df.head()
在该数据集中,第 0 列是输入要素,第 1 列是输出变量或因变量。我们将使用上面的直线公式使用第 0 列来预测第 1 列。
2.根据第 0 列绘制第 1 列。
输入变量和输出变量之间的关系是线性的。当关系是线性时,线性回归效果最好。
3.初始化θ值。我将θ值初始化为零。但是任何其他值也应该起作用。
theta = [0,0]
4.根据之前讨论的公式定义假设和成本函数。
def hypothesis(theta, X):
return theta[0] + theta[1]*Xdef cost_calc(theta, X, y):
return (1/2*m) * np.sum((hypothesis(theta, X) - y)**2)
5.根据数据帧的长度计算训练数据的数量。然后定义梯度下降的函数。在这个函数中,我们将更新θ值,直到成本函数最小。它可能需要任意次迭代。在每次迭代中,它将更新 theta 值,并且利用每次更新的 theta 值,我们将计算成本以跟踪成本。
m = len(df)
def gradient_descent(theta, X, y, epoch, alpha):
cost = []
i = 0
while i < epoch:
hx = hypothesis(theta, X)
theta[0] -= alpha*(sum(hx-y)/m)
theta[1] -= (alpha * np.sum((hx - y) * X))/m
cost.append(cost_calc(theta, X, y))
i += 1
return theta, cost
6.最后,定义预测函数。它将从梯度下降函数中获得更新的θ,并预测假设或预测的输出变量。
def predict(theta, X, y, epoch, alpha):
theta, cost = gradient_descent(theta, X, y, epoch, alpha)
return hypothesis(theta, X), cost, theta
7.使用预测函数,查找假设、成本和更新的θ值。我选择学*率为 0.01,我将运行这个算法 2000 个时期或迭代。
y_predict, cost, theta = predict(theta, df[0], df[1], 2000, 0.01)
最终的θ值为-3.79 和 1.18。
8.在同一个图表中绘制原始 y 和假设或预测 y。
%matplotlib inline
import matplotlib.pyplot as plt
plt.figure()
plt.scatter(df[0], df[1], label = 'Original y')
plt.scatter(df[0], y_predict, label = 'predicted y')
plt.legend(loc = "upper left")
plt.xlabel("input feature")
plt.ylabel("Original and Predicted Output")
plt.show()
根据公式,假设图是一条直线,并且该直线穿过最佳位置。
9.记住,我们在每次迭代中跟踪成本函数。让我们画出成本函数。
plt.figure()
plt.scatter(range(0, len(cost)), cost)
plt.show()
正如我之前提到的,我们的目的是优化θ值,以最小化成本。正如你从这张图表中看到的,成本在开始时急剧下降,然后变得稳定。这意味着θ值如我们预期的那样得到了正确的优化。
我希望这有所帮助。下面是本文中使用的数据集的链接:
[## rashida 048/用 Python 进行机器学*
通过在 GitHub 上创建一个帐户,为 rashida 048/用 Python 进行机器学*开发做出贡献。
github.com](https://github.com/rashida048/Machine-Learning-With-Python/blob/master/ex1data1.txt)
以下是其他一些机器学*算法的解决方案:
实践数据科学的基础项目
从这 6 个基础数据科学项目开始您的数据科学之旅
数据科学是目前最令人兴奋的领域之一,对专家的需求正在增长。网上有很多数据科学课程。学*数据科学的困难在于,它需要大量的实践才能适应现实生活中的数据科学项目。
在过去的几个月里,我一直在学*数据科学并探索这个领域。值得一提的是,我不是数据科学家(我的主要领域是 Web 开发),但我喜欢所有编程的东西,我想尝试一下,并找到更多关于各种数据科学技术和算法的信息。
我想知道数据科学是否真的像人们所说的那样令人兴奋和强大。我将在另一篇文章中回答我对它的看法,但现在,我想与您分享我参与的六个项目,如果您是数据科学新手或想尝试一下,它们将帮助您扩展您的数据科学知识。如果你是数据科学的新手,或者只是想多探索一下这个领域,那么下面的项目将非常适合你。
在这 6 个项目中,您将发现在从事数据科学项目时可能面临的最常*问题。从数据清理,通过标准化和规范化、降维、特征工程到回归、计算机视觉、自然语言处理(NLP)到神经网络,使用流行的 Python 库,如 Pandas、Numpy、scikit-learn、Tensorflow、Keras、TextBlob 等。完成此列表中的所有项目后,您将拥有流行的数据科学技术和算法的实践经验。
如果您从未从事过数据科学项目,这也是一些介绍性的文章,它们将帮助您设置您的计算机,为您提供从事这些项目所必需的一切,并向您展示如何使用 Git 和 Github,以便您可以在那里存储您的项目。
你需要知道的事情
对 Python 的基本理解和知识会很有用。在这些文章中,我没有涉及 Python 编程语言。如果您不了解 Python,我建议您在开始使用这些项目之前,至少要熟悉基本的 Python。例如,你可以在 Coursera 上完成人人编程(Python 入门)课程。
一旦你掌握了 Python 的基础知识,你就可以开始从事这些项目了。先前的数据科学知识是有帮助的,但不是必需的。所有项目都包含对项目中使用的所有算法、概念和 Python 数据科学库的解释。我会解释代码和项目的每一步,所以你可以理解什么和为什么你必须为每个项目做。
虽然用于所有项目的 Jupyter 笔记本也可以在 Github 上获得,并且欢迎您使用它们,但是我建议您自己编写代码,不要复制/粘贴或使用 Jupyter 笔记本。这样你会学到更多,记住更多的信息。
简介和设置
(1) 如何设置你的计算机进行数据科学
在开始从事数据科学项目之前,您需要在计算机上设置一些东西。幸运的是,有一些免费的开源工具可以让这个过程变得非常简单。
(2)Git 和 GitHub 简介
在本教程中,我将解释一些基本步骤,这些步骤将使您能够创建您的 GitHub 资源库,将您的本地文件添加并提交到 Git,并将它们推送到 GitHub 上的在线资源库。
基础数据科学项目
(1) 分析医药销售数据
在本项目的第一部分,您将学*如何将数据集从文件加载到 Pandas (Python 数据操作和分析库),以及如何执行统计分析并在 Pandas 数据框中查找特定信息。在本项目的第二部分,您将学*使用回归(一种能够发现自变量和因变量之间关系的技术)根据历史销售数据预测未来销售。您将使用三种不同的回归算法:线性回归、多项式回归和支持向量回归(SVR)。在训练您的回归模型之前,您将缩放数据并将其分为训练数据和测试数据,这两者都是非常常*和重要的数据科学技术。缩放将实现更好的模型性能,由于分割数据,我们可以在不同的数据集上训练我们的模型,然后计算模型的准确性分数,以查看它在另一组数据上的表现。因为您使用不同的回归模型,所以您也可以使用 VotingRegressor 来获得更好的结果。VotingRegressor 是一种集合方法,可拟合多个回归变量,并对各个预测进行*均,以形成最终预测。您将使用一个流行的 Matplotlib 库来可视化数据和回归预测。熟悉和练* Pandas 数据操作和 Matplotlib 可视化非常重要,因为它们在许多数据科学项目中非常常*,用于操作数据和可视化结果。回归也是许多数据科学项目中非常常*和有用的技术。
以下是项目资源:
中篇:https://towards data science . com/analyzing-pharmaceutical-sales-data-in-python-6 ce 74 da 818 ab
GitHub 上的项目:https://GitHub . com/pj online/Basic-Data-Science-Projects/tree/master/1-analyzing-Pharmaceutical-Sales-Data
(2) 利用数据科学和机器学*预测泰坦尼克号幸存者
在本项目中,您将使用泰坦尼克号幸存者的数据集来构建一个模型,根据乘客的性别、年龄、乘客等级等特征来预测泰坦尼克号灾难中的幸存者和死者。将数据从文件加载到 Pandas 数据框后,您将执行探索性数据分析。探索性数据分析使我们能够了解我们的数据集中有哪些特征,它们是如何分布的,以及我们的数据集中是否有任何缺失值。更好地理解数据将有助于我们进行数据预处理和特征工程。在预处理阶段,您将清理数据并填充任何缺失的值。您还将从现有要素中提取一些新要素(通过使用数据宁滨等技术),并移除不需要且对模型性能没有影响的要素。为了训练模型,您将使用两个新的分类器模型:KNeighborsClassifier 和 DecisionTreeClassifier。然后,您将比较这些模型的性能。在这个项目中,你还将学* K-Fold 交叉验证技术。这种技术有助于更好地使用数据,减少偏差,并让我们更好地了解模型的性能。
以下是项目资源:
中篇:https://towards data science . com/data-science-titanic-challenge-solution-DD 9437683 DCF
GitHub 上的项目:https://GitHub . com/pj online/Basic-Data-Science-Projects/tree/master/5-Titanic-Challenge
(3) 计算机视觉导论与 MNIST
在这个项目中,你将开始学*两个非常重要的数据科学概念;计算机视觉和神经网络。MNIST 是一个手写数字的数字数据库。您将构建并训练一个神经网络来识别手写的数字图像。您将使用 Keras,它是专门针对神经网络的 Python 库。您将看到不同类型的神经网络层激活功能以及神经网络的其他功能和配置。您还将学*如何在文件中保存和加载您的训练模型。您还将使用 Keras 函数to _ categorial,该函数将整数转换为二进制类矩阵,从而提高神经网络的性能。在本练*中,您将学*如何使用 Keras 创建、训练和使用简单有效的神经网络,并评估其性能。
以下是项目资源:
Medium 文章:https://Medium . com/swlh/introduction-to-computer-vision-with-mnist-2d 31 c 6 f 4d 9 a 6
(4) 利用 Tensorflow 神经网络识别猫和狗
在这个项目中,你将继续使用计算机视觉和神经网络,并使用 Keras 和 Tensorflow 构建一个稍微复杂一点的网络。你在这个项目中的任务是建立、训练和测试一个神经网络,该网络将对猫和狗的图片进行识别和分类。你会有三组猫狗的图像:训练、测试、有效;训练对神经网络模型进行训练,在训练期间对模型进行有效性验证,然后测试对训练好的模型进行测试。每组包含不同的猫和狗的图像。
以下是项目资源:
GitHub 上的项目:https://GitHub . com/pj online/Basic-Data-Science-Projects/tree/master/9-Cats-and-Dogs
(5)Python 中的图像人脸识别
在这个项目中,你将处理一个不同的但也很常*和有趣的计算机视觉问题,即人脸识别。您将使用face _ recognitionPython 库进行人脸识别,使用 Python 图像库(PIL) 进行图像处理。你不仅可以在测试图像上识别出已知的人脸,还可以用 PIL 在图像上标记人脸。
以下是项目资源:
Medium 文章:https://Medium . com/an-idea/image-face-recognition-in-python-30 b6b 815 f 105
GitHub 上的项目:https://GitHub . com/pj online/Basic-Data-Science-Projects/tree/master/4-Face-Recognition
(6)Python 中的 Twitter 情绪分析
在这个项目中,您将了解数据科学的另一个重要概念,即自然语言处理(NLP) 。使用 Python NLP 库 TextBlob ,您将对一个选定的 Twitter 帐户最近的一些推文进行情感分析。要访问 tweets,您首先要设置 Twitter 开发者 API 账户。然后,您将创建一个虚拟环境并安装项目所需的库。您将使用 Tweepy Python 库向 Twitter 开发者 API 认证并下载 tweets。然后,您将清理 tweets 并执行一些基本的 NLP。你将计算每条推文的主观性和极性,并将每条记录标记为正面或负面。然后,您将计算该帐户的积极推文的百分比,并在图表上显示推文的类别。最后,你将生成一个单词云,以查看你正在分析的推文中使用的主题和最常用的单词。
以下是项目资源:
中篇:https://towards data science . com/Twitter-perspection-analysis-in-python-1 bafebe 0 b 566
GitHub 上的项目:https://GitHub . com/pj online/Basic-Data-Science-Projects/tree/master/8-Twitter-情操-分析
总而言之,您将学*和实践以下数据科学技术、算法和概念:
- 熊猫
- Matplotlib
- Python 图像库(PIL)
- 数据预处理
- 特征工程
- 特征缩放
- 训练/测试数据分割
- 宁滨数据
- 统计数字
- 投票回归变量
- 线性回归
- 逻辑回归
- 多项式回归
- 支持向量回归
- k 近邻分类器(KNN)
- 决策树分类器
- 带 Keras 的神经网络
- 人脸识别(计算机视觉)
- 主成分分析
- k 倍交叉验证
- 使用 accuracy_score 指标进行性能验证
- 十二岁
- WordCloud
- 文本二进制大对象
- 词干分析
- 标记化(计数矢量器)
我希望这个基本数据科学项目列表是有用的,它将帮助您了解更多信息并练*您的数据科学技能。
编码快乐!
还没有订阅媒体?考虑报名成为中等会员。每月只需 5 美元,你就可以无限制地阅读媒体上的所有报道。订阅媒介支持我和媒介上的其他作者。
基本航海指南
您的数据科学工具
照片由 F rank Mckenna 在 Unsplash 上拍摄
Seaborn 是一个可视化库,位于 matplotlib 之上,使它看起来更好看,并增加了一些额外的功能。数据可视化允许数据科学家向非科学读者传达他们的发现和结果,所以如果你想进入数据科学领域,这是一个很好的工具!
让我们从加载 2019 车型年车辆的真实数据集开始,但首先,我们需要导入相关的包!
import matplotlib.pyplot as plt%matplotlib inlineimport seaborn as sns
条形图
在本例中,我们希望查看所有车辆的档位数量。
gear_counts = df['# Gears'].value_counts()gear_counts.plot(kind='bar')
我们可以加载 Seaborn,只需对它调用 set()就可以将 matplotlib 的默认设置更改为更具视觉效果的设置。
现在,如果我们做同样的情节命令,它看起来更现代一点。
sns.set()gear_counts.plot(kind='bar')
好多了!
距离图
Seaborn 包括 matplotlib 没有提供的许多类型的情节。例如,“distplot”可用于绘制直方图以及叠加在其上的直方图的*滑分布。让我们以此数据库中车辆的 MPG 值分布为例。
这是我们正在处理的数据
sns.distplot(df['CombMPG'])
配对图
你经常遇到的是 Seaborn 的“结对情节”。这使您可以将各种属性的每种组合的图可视化,因此您可以在特征之间寻找有趣的模式。
作为一个例子,让我们寻找气缸、城市 MPG 等级、公路 MPG 等级和综合 MPG 等级之间的关系。
使用的数据
sns.pairplot(df2, height=2.5)
通过研究上面的结果,你可以看到气缸数量和 MPG 之间的关系,但 4 缸车辆的 MPG 范围非常广。在测量 MPG 值的不同方法之间似乎也有很好的线性关系,直到你达到更高的 MPG 等级。
散点图
这将在您选择的两个轴上绘制各个数据点,因此您可以看到数据在这些维度上的分布情况。
当你有发动机排量这样的顺序数据时,散点图会将自己排列成列,但它告诉我们,发动机排量的每个值都有一个相当大的 MPG 值范围,尽管如果你看看数据点聚集的地方,你可以看到随着发动机排量的增加,MPG 值有下降的趋势。
sns.scatterplot(x="Eng Displ", y="CombMPG", data=df)
带直方图的散点图
Seaborn 还提供了一个“jointplot ”,它结合了散点图和两个轴上的直方图。这使您可以同时看到单个数据点和两个维度上的分布。
sns.jointplot(x="Eng Displ", y="CombMPG", data=df)
最常*的发动机排量似乎是 2,3 紧随其后。每加仑汽油的得分似乎大致遵循一条以 22 分左右为中心的钟形曲线。
线性散点图
“lmplot”为我们提供了覆盖在图表上的数据的线性回归,这使得较低 MPG 与较高发动机排量的总体趋势更加明显。就效率而言,高发动机排量似乎并不更好。
sns.lmplot(x="Eng Displ", y="CombMPG", data=df)
箱线图
接下来,我们来看一个“盒状图”。这就是所谓的“方框和胡须”图,它对于可视化给定类别的典型值非常有用,不会被异常值分散注意力。每个方框代表数据的第一个和第三个四分位数之间的范围,一条线代表中值。从框中延伸出来的“胡须”代表数据的其余部分的分布,除了清晰的异常值,这些异常值被绘制为胡须外部的单个点。
例如,让我们看看每个汽车制造商的箱线图,可视化他们生产的汽车的每加仑英里数。这让我们可以看到每个制造商提供的所有车辆的 MPG 评级的分布情况。
有很多制造商,所以为了使结果图可读,我们将增加 Seaborn 的默认图形大小,并使用 set_xticklabels 将标签旋转 45 度。
sns.set(rc={'figure.figsize':(15, 5)})ax = sns.boxplot(x='Mfr Name', y='CombMPG', data=df)ax.set_xticklabels(ax.get_xticklabels(),rotation=45)
箱线图告诉我们,我们在每种变速箱类型上看到的 MPG 值的范围并不像乍看上去那样疯狂分布;许多极值实际上是离群值,在分析趋势时最好将其丢弃。
群体图
另一种可视化相同数据的方法是“群体图”它绘制的不是方框和触须,而是每一个单独的数据点——但这样做的方式是根据它们的分布将它们组合在一起。你看着就更有道理了。
ax = sns.swarmplot(x='Mfr Name', y='CombMPG', data=df)ax.set_xticklabels(ax.get_xticklabels(),rotation=45)
计数图
另一个工具是“计数图”这和直方图基本上是一样的,只是针对分类数据。它可以让你计算 X 轴上每个给定类别在数据中出现的次数,并绘制图表。例如,我们可以看到通用汽车公司提供的车型比其他任何公司都多,宝马紧随其后。
ax = sns.countplot(x='Mfr Name', data=df)ax.set_xticklabels(ax.get_xticklabels(), rotation=45)
热图
热图允许你绘制某种表格形式的 2D 数据,用颜色代表 2D 表中每个单元格的单个值。
在本例中,我们将根据原始数据框创建一个数据透视表,以创建一个 2D 表,其中包含气缸数和发动机排量的每种组合的*均 MPG 评级。
生成的热图显示了沿 X 轴的所有发动机排量值,以及沿 Y 轴的所有气缸排量值。对于表格中的每个单元格,气缸和发动机排量组合的实际*均 MPG 等级不是用数字表示,而是用颜色表示,颜色范围从深色表示小数值,浅色表示大数值。
这确实可以让您看到一个清晰的趋势,随着我们从图表的左上移到右下,情况会逐渐变暗。这是有道理的。较高的 MPG 等级与较低的气缸数量和较低的发动机排量值相关。当我们使用 8 升 16 缸发动机时,*均每加仑汽油跑 12 英里,用黑色表示。
这张图表有很多缺失的数据,但是热图很好地处理了这些数据。3 缸 8 升发动机根本不存在!
df2 = df.pivot_table(index='Cylinders', columns='Eng Displ', values='CombMPG', aggfunc='mean')sns.heatmap(df2)
我的 Seaborn 教程到此结束。希望这对你的兼职项目和工作有帮助。谢谢大家!
Python 中时间序列分析的基本统计数据
了解描述性统计和推断性统计,快速启动您的时间序列分析
时间序列只是一组按时间顺序排列的数据点,其中时间通常是独立变量。
现在,预测未来并不是时间序列分析的唯一目的。它还与评估重要属性相关,如*稳性、季节性或自相关性。
在进入更高级的建模实践之前,我们必须首先掌握基础知识。
在本文中,我们将通过介绍描述性和推断性统计来介绍时间序列分析的构建模块。当我们在时间序列上实现复杂的模型时,这些概念将会派上用场,因为统计显著性对于建立稳健的分析是必要的。
所有的代码示例都是 Python 语言,你可以拿着的笔记本跟着学。
我们开始吧!
通过 Python 课程中的应用时间序列分析,使用 Python 和 TensorFlow 应用更复杂的模型进行时间序列分析!
描述统计学
描述性统计是对数据集进行汇总的一组值和系数。它提供了关于集中趋势和可变性的信息。
*均值、中值、标准偏差、最小值和最大值通常是我们要寻找的值。
那么,让我们看看如何用 Python 获得这些值。
首先,我们将导入所有需要的库。并非所有这些都用于描述性统计,但我们稍后会用到它们。
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
import seaborn as snsfrom sklearn.linear_model import LinearRegressionimport statsmodels.api as sm
现在,我们将探索数据集shampoo . CSV。该数据集追踪某段时间内洗发水的历史销量。
为了查看整个数据集,我们可以执行以下 Python 代码:
data = pd.read_csv('shampoo.csv')
data
小心,因为这将显示整个数据集。在这种情况下,只有 36 个实例,但是对于较大的数据集,这不是很实际。
相反,我们应该使用下面这段代码:
data.head()
上面的代码行将显示数据集的前五个条目。您可以通过指定想要查看的条目数量来决定显示更多条目。
data.head(10)
上面一行将显示数据集的前 10 个条目。
现在,有一种非常简单的方法可以获得*均值、中值、标准差和其他关于数据集中心趋势的信息。
只需运行下面的代码行:
data.describe()
您应该会看到洗发水数据集的以下信息:
数据集的描述性统计
如您所*,通过这个简单的方法,我们获得了关于数据集大小、*均值和标准偏差、最小值和最大值的信息,以及关于其四分位数的信息。
形象化
数字是一个很好的起点,但是能够可视化一个时间序列可以给你快速的洞察力,这将帮助你把你的分析引向正确的方向。
当涉及到时间序列时,直方图和散点图是最广泛使用的可视化工具。
我们数据集的简单直方图可以显示为:
data.hist()
数据集的基本直方图
然而,我们可以做得更好。让我们绘制一个更好的直方图,并给这个轴添加标签。
plt.figure(figsize=[10, 7.5]); # Set dimensions for figureplt.hist(data['Sales'])
plt.title('Histogram of Shampoo Sales');
plt.xlabel('Shampoo Sales ($M)');
plt.ylabel('Frequency');
洗发水数据集的直方图
上面的直方图好多了。您可以更改许多参数来根据需要定制可视化。例如,您可以更改直方图中条柱的颜色和数量。
plt.figure(figsize=[10, 7.5]); # Set dimensions for figureplt.hist(data['Sales'], bins=20, color='#fcba03')
plt.title('Histogram of Shampoo Sales');
plt.xlabel('Shampoo Sales ($M)');
plt.ylabel('Frequency');
洗发水数据集的直方图
现在,您应该可以非常轻松地绘制直方图,并根据自己的需要进行定制。
最后但同样重要的是知道如何显示散点图。非常简单,我们可以像这样可视化我们的数据集:
plt.figure(figsize=[20, 7.5]); # Set dimensions for figuresns.scatterplot(x=data['Month'], y=data['Sales']);
plt.title('Historical Shampoo Sales');
plt.ylabel('Shampoo Sales ($M)');
plt.xlabel('Month');
洗发水数据集的散点图
如果你想了解更多关于使用我们使用的库绘图的知识,并看看不同的参数如何改变绘图,请务必查阅 matplotlib 或 seaborn 的文档。
推断统计学
顾名思义,推断统计是使用分析从数据集中推断属性。
通常,我们希望在数据集中找到一个趋势,以便进行预测。这也是我们检验不同假设的机会。
出于介绍的目的,我们将使用一个简单的线性回归来说明和解释时间序列背景下的推断统计。
时间序列的线性回归
在本节中,我们将使用另一个数据集来追溯大气中 CO2 的历史浓度。由于数据集跨越了 2014 年的历史,让我们只考虑 1950 年及以后的数据。
让我们应用之前所学的知识,展示我们数据的散点图。
# Dataset from here: [https://www.co2.earth/historical-co2-datasets](https://www.co2.earth/historical-co2-datasets)
co2_dataset = pd.read_csv('co2_dataset.csv')plt.figure(figsize=[20, 7.5]); # Set dimensions for figure# Let's only consider the data from the year 1950
X = co2_dataset['year'].values[1950:]
y = co2_dataset['data_mean_global'].values[1950:]sns.scatterplot(x=X, y=y);
plt.title('Historical Global CO2 Concentration in the Atmosphere');
plt.ylabel('CO2 Concentration (ppm)');
plt.xlabel('Year');
从 1950 年到 2014 年的二氧化碳浓度
如你所*,浓度似乎随着时间而增加。
虽然趋势似乎不是线性的,但它可能仍然可以解释数据的部分可变性。因此,让我们做如下假设:
- CO2 浓度以线性方式依赖于时间,存在一些误差
在数学上,这表示为:
线性方程
你应该很容易把它看作一个线性方程,包含一个常数项、一个斜率和一个误差项。
重要的是要注意,在进行简单的线性回归时,要做以下假设:
- 误差呈正态分布,*均为 0
- 误差具有相同的方差(同方差)
- 这些错误互不相关
然而,在执行简单的线性回归时,这些假设在技术上都没有使用。我们不生成误差项的正态分布来估计线性方程的参数。
相反,普通最小二乘法 (OLS)用于估计参数。这只是试图找到误差*方和的最小值:
用 OLS 最小化的参数
线性回归在起作用
现在,让我们用一个线性模型来拟合我们的数据,并查看模型的估计参数:
X = co2_dataset['year'].values[1950:].reshape(-1, 1)
y = co2_dataset['data_mean_global'].values[1950:].reshape(-1, 1)reg = LinearRegression()reg.fit(X, y)print(f"The slope is {reg.coef_[0][0]} and the intercept is {reg.intercept_[0]}")predictions = reg.predict(X.reshape(-1, 1))plt.figure(figsize=(20, 8))
plt.scatter(X, y,c='black')
plt.plot(X, predictions, c='blue', linewidth=2)
plt.title('Historical Global CO2 Concentration in the Atmosphere');
plt.ylabel('CO2 Concentration (ppm)');
plt.xlabel('Year');
plt.show()
线性回归
运行上面的代码,你应该得到同样的图,你会看到斜率是 1.3589,截距是-2348。
参数有意义吗?
斜率确实是正的,这是正常的,因为浓度无疑在增加。
然而,截距是负的。这是否意味着时间 0,CO2 浓度为负?
不。我们的模型绝对不足以让我们回到 1950 年。但是这些参数是最小化误差*方和的参数,因此产生最佳的线性拟合。
评估模型的质量
从图中,我们可以直观地说直线不是我们数据的最佳拟合,但也不是最差的。
回想一下假设误差是正态分布的线性模型。我们可以通过绘制残差的 QQ 图来检验这个假设。
QQ 图是两种不同分布的分位数散点图。如果分布是相同的,那么我们会看到一条直线。
因此,如果我们绘制残差相对于正态分布的 QQ 图,我们可以看到它们是否落在一条直线上;这意味着我们的残差确实是正态分布的。
X = sm.add_constant(co2_dataset['year'].values[1950:])
model = sm.OLS(co2_dataset['data_mean_global'].values[1950:], X).fit()
residuals = model.resid
qq_plot = sm.qqplot(residuals, line='q')
plt.show()
QQ-残差图
如你所*,蓝点代表残差,它们不在一条直线上。因此,它们不是正态分布的,这表明线性模型不是我们数据的最佳拟合。
这可以通过绘制残差直方图得到进一步支持:
X = sm.add_constant(co2_dataset['year'].values[1950:])
model = sm.OLS(co2_dataset['data_mean_global'].values[1950:], X).fit()
residuals = model.residplt.hist(residuals);
残差直方图
同样,我们可以清楚地看到它不是正态分布。
假设检验
推断统计学的一个主要组成部分是假设检验。这是一种确定观察到的趋势是否是由于随机性,或者是否有真正的统计意义的方法。
对于假设检验,我们必须定义一个假设和一个无效假设。假设通常是我们试图从数据中提取的趋势,而零假设恰恰相反。
让我们为我们的情况定义假设:
- 假设:时间与 CO2 浓度呈线性相关
- 零假设:时间和 CO2 浓度没有线性关系
厉害!现在,让我们使用另一个库为我们的数据集拟合一个线性模型,该库将为我们自动运行假设检验:
X = sm.add_constant(co2_dataset['year'].values[1950:])
model = sm.OLS(co2_dataset['data_mean_global'].values[1950:], X).fit()
print(model.summary())
现在,这里有很多信息,但让我们只考虑几个数字。
首先,我们有一个非常高的 R 值 0.971。这意味着超过 97%的 CO2 浓度变化可以用时间变量来解释。
然后,F 统计量也很大:2073。这意味着时间和 CO2 浓度之间存在线性相关性具有统计学意义。
最后,查看斜率系数的 p 值,您会注意到它是 0。虽然该数字可能不为 0,但仍然非常小,这是存在线性相关性的另一个统计显著性指标。
通常,阈值 0.05 用于 p 值。如果小于这个值,则拒绝零假设。
因此,由于一个大的 F 统计量,结合一个小的 p 值,我们可以拒绝零假设。
就是这样!你现在处于一个非常好的位置来启动你的时间序列分析。
有了这些基本概念,我们将在它们的基础上构建更好的模型来帮助我们预测时间序列数据。
了解 Python 中时间序列分析的最新最佳实践:
干杯!
数据科学需要了解的基本统计数据
让您开始数据科学之旅的基本统计概念
这样做的目的是全面概述统计学的基础知识,这是您开始数据科学之旅所需要的。已经有很多文章了,但我的目标是让这篇文章更简洁!
如果你发现了这个有价值的东西,愿意支持我,就来看看 我的 Patreon 页面 !
数据类型
数值:用数字表示的数据;是可以衡量的。可以是离散的或连续的。
分类的:将定性数据分类成类别。可以是名义(无顺序)也可以是序数(有序数据)。
集中趋势测量
均值:一个数据集的*均值。
中位数:有序数据集的中间;不易受离群值的影响。
模式:一个数据集中最常*的值;仅与离散数据相关。
差异量数
范围:数据集中最高值和最低值之差。
方差(σ2): 测量一组数据相对于*均值的分布程度。
标准差(σ): 数据集中数字分布的另一种度量;它是方差的*方根。
Z-score: 确定数据点偏离*均值的标准偏差数。
R *方:拟合的统计测量,表明自变量解释了因变量的多少变化;仅对简单的线性回归有用。
调整后的 R *方:已针对模型中预测器的数量进行调整的 R *方的修改版本;如果新项对模型的改进超过偶然的预期,那么它就会增加,反之亦然。
变量之间关系的度量
协方差:测量两个(或多个)变量之间的方差。如果是正的,那么它们倾向于向同一个方向移动,如果是负的,那么它们倾向于向相反的方向移动,如果它们是零,那么它们彼此没有关系。
样本的分母变为(n-1)
相关性:衡量两个变量之间的关系强度,范围从-1 到 1;协方差的标准化版本。一般来说,+/- 0.7 的相关性代表两个变量之间的密切关系。另一方面,介于-0.3 和 0.3 之间的相关性表明变量之间几乎没有关系。
概率分布函数
概率密度函数(PDF): 连续数据的函数,其中任意点的值可以被解释为提供随机变量的值等于该样本的相对可能性。(维基)
概率质量函数(PMF): 离散数据的函数,给出给定值出现的概率。
累积密度函数(CDF): 告诉我们随机变量小于某个值的概率的函数;PDF 的积分。
连续数据分布
均匀分布:所有结果可能性相等的概率分布。
正态/高斯分布:通常称为钟形曲线,与 中心极限定理 有关;*均值为 0,标准偏差为 1。
T-分布:在样本量较小和/或总体方差未知时用于估计总体参数的一种概率分布(参*更多 此处 )。
卡方分布:卡方统计量的分布(* 此处 )。
离散数据分布
泊松分布:概率分布,表示给定数量的事件在固定时间段内发生的概率。
二项式分布:一系列 n 次独立经历中成功次数的概率分布,每次经历都有自己的布尔值结果(p,1-p)。
朋友圈
矩描述了分布的性质和形状的不同方面。一阶矩是均值,二阶矩是方差,三阶矩是偏度,四阶矩是峰度。
可能性
概率是事件发生的可能性。
条件概率[P(A|B)] 是基于前一事件的发生,某一事件发生的可能性。
独立事件是其结果不影响另一事件结果概率的事件;P(A|B) = P(A)。
互斥事件是不能同时发生的事件;P(A|B) = 0。
贝叶斯定理:确定条件概率的数学公式。“给定 B 的概率等于给定 A 的 B 的概率乘以 A 的概率超过 B 的概率”。
准确(性)
真阳性:检测条件出现时的条件。
真否定:当条件不存在时,不检测条件。
假阳性:检测条件不存在时的条件。
假阴性:在条件存在时不检测条件。
灵敏度:又称召回;当条件存在时,测量测试检测条件的能力;灵敏度= TP/(TP+FN)
特异性:测量当条件不存在时,测试正确排除条件的能力;特异性= TN/(TN+FP)
预测值阳性:又称精度;对应于条件存在的阳性比例;PVP = TP/(TP+FP)
预测值阴性:对应于条件不存在的阴性比例;PVN = TN/(TN+FN)
假设检验和统计显著性
查看我的文章“尽可能简单地解释假设检验”以获得更深入的解释 这里 。
零假设:样本观察值完全来自偶然的假设。
备选假设:样本观测值受某种非随机原因影响的假设。
P 值:假设零假设正确,获得某项检验的观测结果的概率;较小的 p 值意味着有更强的证据支持替代假设。
Alpha: 显著性水*;当零假设为真时拒绝零假设的概率,也称为1 型错误。
Beta:2 型错误;未能拒绝虚假的零假设。
假设检验的步骤:
1。陈述零假设和替代假设
2。确定测试规模;是单尾还是双尾检验?
3。计算测试统计和概率值
4。分析结果,拒绝或不拒绝零假设(如果 p 值大于α,不拒绝零假设!)
就是这样!如果我发现我在旅程中错过了很多重要的话题,请随时评论并告诉我:)
更多类似的文章,请看 https://blog.datatron.com/的
感谢阅读!
如果你喜欢我的工作,想支持我…
- 支持我的最好方式就是在媒体这里关注我。
- 成为第一批在Twitter这里关注我的人之一。我会在这里发布很多更新和有趣的东西!
- 此外,成为第一批订阅我的新 YouTube 频道 这里!
- 关注我LinkedIn这里。
- 在我的邮箱列表 这里报名。
- 看看我的网站,terenceshin.com。
机器学*的基本步骤
内部 Ai
透过肿瘤学的镜头
让我们开始更深入地研究机器学*的基础知识。我们将从使用机器学*背后的基本理论和我们将用于解决新问题的大纲开始。最后,我们将讨论一些常*的 ML 模型可以解决的潜在问题。
为什么是机器学*?
机器学*需要一种处理问题的新方法。在传统的编程中,一个具有一些领域知识的人必须推导出一个将输入转换成期望输出的程序。在这种情况下,输入和转换是已知的。
在机器学*中,未知的是转换。也就是说,我们提供输入和结果输出(至少在监督学*中)。随着我们的建模变得越来越复杂,一个人通过传统的编程为所有的特性做出必要的转换变得很困难。
传统编程和机器学*之间的差异通过它们的输出凸显出来。链接
此外,随着我们的数据集变得越来越大和越来越复杂,人类很难在数据中识别出新的、重要的模式。但是机器更容易理解这种维度。也就是说,由于“维数灾难”,我们可以在模型中包含的特征数量是有限的。随着维度的增加,我们的点之间的距离增加,数据变得稀疏。我们将在后面讨论为什么这很重要,以及如何对抗“诅咒”。
我们应该如何处理一个 ML 问题?
我先说这个帖子是针对一个通用的 ML 模型的。各种模型的相对用例、优点和缺点超出了本文的范围,但是可以通过快速的 Google 搜索获得资源。这里以为例。
1-获取数据
这可以采取多种形式。如果你能接触到电子健康记录(EHR),那太好了。如果你有单一研究的实验数据或跨元研究的数据,那就更好了。一般来说,一开始你能检查的越多越好。在数据清理和 EDA 过程中,我们将对数据有更好的感觉,并将对包括或不包括什么做出更明智的决定。
API 是一个很好的资源。以下是一些可供选择的方法:
- HealthData.gov:新冠肺炎、EHR、医疗保险等。
- 【HealthIT.gov】T2:EHR、全州绩效指数、临床医生流失等。
- Rapid API :收集了一系列医疗保健相关的 API,主题广泛
2 —处理您的数据
一旦有了数据集合,就需要对其进行预处理,以便在机器学*模型中使用。有些模型对输入数据有非常具体的要求(比如没有遗漏条目),所以如果适用的话,请确保阅读所选模型和包的文档。
无论型号类型如何,都需要采取一些步骤。您应该熟悉的一些流程:
- 处理缺失值:您可以删除 NaN 值,估算相似子集中的中值/*均值,或者将缺失值标记为类别或选择的替代值。
- 删除重复条目 : Pandas 有一个 drop_duplicate()方法。
- 检查不一致性:例如,如果在列中添加了额外类别的拼写错误,或者某个数值被存储为“字符串”或“对象”,请使用 df.column.dtype 进行检查
- 过滤掉有影响的离群值:警告一句,你不应该删除离群值,除非它是真实存在的危险。并非所有的异常值都会影响模型的准确性。
- 如果分类,检查等级不*衡。
你可能需要做的另一个过程是特性选择和工程。这可能包括为分类列创建虚拟变量、移除具有多重共线性的要素(相关变量)或创建基于其他列提供潜在新*解的新列。
这里有一篇很棒的文章深入探讨特性工程,包括缩放、日志转换、一键编码等。
3 —选择一个模型
终于到了模特的时间了!同样,有许多资源可以确定哪种模型适合您的需求。这里有一个来自 scikit-learn 的精彩总结。
基于我们的用例,我们需要确定我们的模型是应该利用监督学*还是非监督学*。对于监督学*,我们试图训练一个模型,将输入正确地转换为相应的已知的输出。这意味着我们需要知道输出是什么,但情况并非总是如此。然后将使用无监督学*,其中我们让模型在我们的数据中找到关系。
监督学*模型的一些例子是回归和分类模型,如逻辑回归、支持向量机(SVMs)或神经网络。
对于无监督学*,我们没有已知的输出。这些模型常用于聚类分析和降维。
4 —培训
现在我们已经选择了一个模型,收集并处理了数据。我们准备开始训练模型。我们首先将数据集分为训练集、验证集和测试集。训练/验证/测试数据的确切比例取决于您使用的模型。具有较少功能的模型更容易调整,因此可能需要较少的验证数据。
根据你的训练计划,你将以不同的方式进行训练。像往常一样,检查文档。Scipy 和 Keras 模型有一个. fit()方法。PyTorch 要求编写自己的训练循环。
5 —评估
有几个指标你可能听说过,可以用来确定你的模型是否成功:
- 准确度:正确分类输出的百分比(真阳性+真阴性)
- 精度:真阳性与真阳性和假阳性的比率
- 回忆:真阳性与实际总阳性的比率(真阳性+假阴性)
这些乍一看都很像。在假阳性很重要的情况下,精确度很重要。在假阴性很重要的情况下,回忆很重要。一如既往,牢记您的业务理解和目标应该推动您的评估指标。
我警告不要把准确性作为你的主要或者唯一的评估标准。举个例子,假设你正在开发一个模型来预测一个病人是否患有一种只影响 0.01%人口的罕*疾病。由于大类不*衡,我们的模型每次都会预测“无病”!那将会有 99.99%的准确度!但是,你可以猜到,这不是一个有用的模型。
关于使用验证集优化模型的说明。当您迭代地改进您的模型时,请注意一遍又一遍地针对您的验证集进行测试将会导致过度适应该验证集,并且模型将不会很好地推广到新的数据(实际的测试集)。解决这个问题的一种方法是使用合成方法,通过交叉验证来“洗牌”训练和验证集,如 k-fold 交叉验证。简而言之,您将训练数据的不同子集视为该单次拟合的验证集,然后再进行下一次拟合。
这是机器学*计算机视觉的一个伟大而幽默的应用:吉娃娃还是松饼?
6 —调谐
在我们开始之前,我们必须划分参数和超参数。参数是模型本身使用误差最小化和梯度下降来改变不同特征的权重和偏差。
超参数是人类用户可以改变的,例如,改变模型经历的迭代次数、改变学*速率、隐藏层的数量和组成、丢弃、优化器和损失函数等。这些超参数是我们实际调整模型的方式。经过大量的耐心和反复试验,我们可以找到一个更好的设置来获得更好的指标。请记住,根据我们的目标,推理或预测,这个过程可能看起来非常不同。也许我们需要增加复杂性来提高准确性,或者我们需要去除复杂性来使我们的模型更容易解释(例如,更少的黑箱)。
7 —预测
现在我们已经训练和调整了我们的模型,我们可以开始进行预测了!这就是我们一直在建设的。我们确切的预测显然取决于我们的模型是什么。也许使用一个 CNN 通过输入组织切片来预测癌症的存在。或者使用 EHR 记录开发一个分类模型来预测患者住院情况。
回顾一下我们的流程
- 收集和准备您的数据
- 选择型号
- 训练、评估、调整、重复
- 预测!
因此,现在你可以在头脑中有计划地进行数据科学研究了!请记住,这不是一个线性的过程,你应该为你的目标尽可能多地重复这些步骤。
我之前关于机器学*在肿瘤学中的应用的文章可以在这里找到—
肿瘤学的最新进展为癌症治疗和长期缓解带来了令人兴奋的选择。然而…
towardsdatascience.com](/machine-learning-ai-applications-in-oncology-73a8963c4735)
Python 中的基本 Tweet 预处理
推文预处理!
了解如何使用 Python 预处理推文
https://hdqwalls.com/astronaut-hanging-on-moon-wallpaper
编者注: 走向数据科学 是一份以研究数据科学和机器学*为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
只是为了给你一点背景,为什么我要预处理推文:鉴于截至 2020 年 5 月的当前形势,我对美国州长关于正在进行的的政治话语感兴趣。我想分析一下两个政党——共和党&民主党对给定的形势做出了怎样的反应,新冠肺炎。他们此时的主要目标是什么?谁更关注什么?他们最关心的是什么?
在收集了从新冠肺炎案例 1 的第一天开始的各州州长的推文后,我们将它们合并成一个数据帧(如何将各种 JSON 文件合并成一个数据帧)并进行预处理。
我们总共收到了大约 3 万条推文。一条推文包含了很多关于它所代表的数据的观点。未经预处理的原始推文是高度非结构化的,包含冗余信息。为了克服这些问题,通过采取多个步骤来执行 tweets 的预处理。
几乎每个社交媒体网站都因其以标签形式表现的主题而闻名。特别是对我们来说,标签起了重要作用,因为我们对#Covid19、#冠状病毒、#StayHome、#InThisTogether 等感兴趣。因此,第一步是基于 hashtag 值形成一个单独的特征,并对它们进行分段。
1。使用正则表达式提取 hashtag
作为新功能“hashtag”添加到新列的所有 hashtag 的列表
*tweets[‘hashtag’] = tweets[‘tweet_text’].apply(lambda x: re.findall(r”#(\w+)”, x))*
提取标签后
然而,超过一个单词的标签必须分段。我们使用库 ekphrasis 将这些标签分割成 n 个单词。
*#installing ekphrasis
!pip install ekphrasis*
安装完成后,我选择了一个基于 twitter 语料库的分割器
*from ekphrasis.classes.segmenter import Segmenter#segmenter using the word statistics from Twitter
seg_tw = Segmenter(corpus=”twitter”)*
我找到的最相关的 tweet-preprocessor—tweet-preprocessor,这是 Python 中的一个 tweet 预处理库。
它处理—
- 资源定位符
- 提及
- 保留字(RT,FAV)
- 表情符号
- 笑脸消除(游戏名)
*#installing tweet-preprocessor
!pip install tweet-preprocessor*
2 .文本清理(URL、提及等。)
将清理后的(删除网址和提及后的)推文添加到一个新列,作为新功能“文本”
清理是使用tweet-preprocessor包完成的。
*import preprocessor as p#forming a separate feature for cleaned tweets
for i,v in enumerate(tweets['text']):
tweets.loc[v,’text’] = p.clean(i)*
3.标记化、删除数字、停用词和标点符号
新特征“文本”的进一步预处理
NLTK(自然语言工具包)是预处理文本数据的最佳库之一。
*#important libraries for preprocessing using NLTK
import nltk
from nltk import word_tokenize, FreqDist
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
nltk.download
nltk.download('wordnet')
nltk.download('stopwords')
from nltk.tokenize import TweetTokenizer*
- 去掉数字,降低文字高度(便于处理)
*data = data.astype(str).str.replace('\d+', '')
lower_text = data.str.lower()*
- 删除标点符号
*def remove_punctuation(words):
new_words = []
for word in words:
new_word = re.sub(r'[^\w\s]', '', (word))
if new_word != '':
new_words.append(new_word)
return new_words*
- 词汇化+标记化—使用内置的 TweetTokenizer()
*lemmatizer = nltk.stem.WordNetLemmatizer()
w_tokenizer = TweetTokenizer()def lemmatize_text(text):
return [(lemmatizer.lemmatize(w)) for w in \
w_tokenizer.tokenize((text))]*
最后一个预处理步骤是
- 删除停用字词—有一个预定义的英文停用字词列表。但是,您可以像这样修改停用字词,只需将这些字词附加到停用字词列表中。
*stop_words = set(stopwords.words('english'))tweets['text'] = tweets['text'].apply(lambda x: [item for item in \
x if item not in stop_words])*
4.词云
分段标签的频率分布
在预处理步骤之后,我们排除了推文中的所有地名和缩写,因为它充当了泄漏变量,然后我们对最常出现的标签进行了频率分布,并创建了一个词云—
这是意料之中的。
*from wordcloud import WordCloud#Frequency of words
fdist = FreqDist(tweets['Segmented#'])#WordCloud
wc = WordCloud(width=800, height=400, max_words=50).generate_from_frequencies(fdist)
plt.figure(figsize=(12,10))
plt.imshow(wc, interpolation="bilinear")
plt.axis("off")
plt.show()*
最终的数据集—
最终的代码—
*import pandas as pd
import numpy as np
import json
from collections import Counter
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import re, string, unicodedata
import nltk
from nltk import word_tokenize, sent_tokenize, FreqDist
from nltk.corpus import stopwords
from nltk.stem import LancasterStemmer, WordNetLemmatizer
nltk.download
nltk.download('wordnet')
nltk.download('stopwords')
from nltk.tokenize import TweetTokenizer!pip install ekphrasis
!pip install tweet-preprocessor
import preprocessor as ptweets['hashtag'] = tweets['tweet_text'].apply(lambda x: re.findall(r"#(\w+)", x))for i,v in enumerate(tweets['text']):
tweets.loc[v,’text’] = p.clean(i)def preprocess_data(data):
#Removes Numbers
data = data.astype(str).str.replace('\d+', '')
lower_text = data.str.lower()
lemmatizer = nltk.stem.WordNetLemmatizer()
w_tokenizer = TweetTokenizer()
def lemmatize_text(text):
return [(lemmatizer.lemmatize(w)) for w \
in w_tokenizer.tokenize((text))] def remove_punctuation(words):
new_words = []
for word in words:
new_word = re.sub(r'[^\w\s]', '', (word))
if new_word != '':
new_words.append(new_word)
return new_words words = lower_text.apply(lemmatize_text)
words = words.apply(remove_punctuation)
return pd.DataFrame(words)pre_tweets = preprocess_data(tweets['text'])
tweets['text'] = pre_tweetsstop_words = set(stopwords.words('english'))
tweets['text'] = tweets['text'].apply(lambda x: [item for item in \
x if item not in stop_words])from ekphrasis.classes.segmenter import Segmenter# segmenter using the word statistics from Twitter
seg_tw = Segmenter(corpus="twitter")
a = []
for i in range(len(tweets)):
if tweets['hashtag'][i] != a
listToStr1 = ' '.join([str(elem) for elem in \
tweets['hashtag'][i]])
tweets.loc[i,'Segmented#'] = seg_tw.segment(listToStr1)#Frequency of words
fdist = FreqDist(tweets['Segmented#'])
#WordCloud
wc = WordCloud(width=800, height=400, max_words=50).generate_from_frequencies(fdist)
plt.figure(figsize=(12,10))
plt.imshow(wc, interpolation="bilinear")
plt.axis("off")
plt.show()*
希望我帮到你们了。
如果文本预处理得好,文本分类通常会工作得更好。一定要给它一些额外的时间,最终一切都是值得的。
1 ↩︎