如何为小说作者搭建一个可控的写作助手
实践教程
使用迁移学习和 OpenAI GPT2 构建一个嵌入在开源接口中的最先进的文本生成工具
AITextGenerator —根据周围环境以及指定的实体、类型和大小生成文本—图片由作者提供
几年前,创造了一个写作工具,包括使用简单的概率模型和精心设计的语法规则,以便在已知前一个世界的基础上选择下一个世界。除了冗长和挑剔之外,结果极其有限。
随着最近在 NLP 深度学习方面的进展,我们现在可以摆脱这种琐碎的工作,建立更加强大的文本生成算法🌟正如您将在本教程中看到的。这一进展与变压器架构的出现相一致(Vaswani 等人)🏭,实现了在巨大文本语料库上训练的大规模语言模型(Devlin et al .,2018;戴等,2019)达到卓越的性能,产生接近人类会写的东西。
如果你不相信我,我会建议你去看看刚刚发布的 GPT-3 ,,它展示了众多令人惊叹的功能。
然而,这些强大的模型呈现出⛔.的几个缺点训练他们是非常困难和昂贵的。他们仍然很难在长段落中保持连贯的上下文。最后,用户还不能操纵生成和控制所生成文本的某些特定方面。
为了解决这些限制,我们的秘密武器是使用大规模预训练语言模型,开放人工智能 GPT-2 🦄[1],结合创新的迁移学习微调技术——用于受控和情境化的文本生成。
从这个角度来看,我们的工作类似于拥抱脸的最先进的对话式人工智能 **,**在以往历史和机器人“个性”的语境化对话方面做了出色的工作。
更具体地说,我们的目标🏆是让用户在写小说的任何时候,能够自动生成与文章其余部分一致的新章节,尤其是前面和后面的段落。我们给他们选择实体的机会(角色、地点等)。)👤他们已经在小说中介绍了,并希望包含在新的章节中。同样,他们可以指定所需文本的大小📝,其内容通过一个小摘要或关键词💬甚至他们正在写的书的类型📗。
开源平台的缺乏促使我们将我们的工具集成到一个用户友好的交互式开源网络服务中,让任何作者都能从中受益——简单、直观且免费。
一定要去看看!🎮
更新:我们已经关闭了服务器,因为我们快没钱了——抱歉😅但是你仍然可以在你的电脑上运行它。
最后,我们提出了一个易用的 写作助手,它自动做出几个建议,用户可以从中选择并编辑。目标是在遵守以下限制的情况下,产生为作者提供想法的创造性输出:
- 确保流利和正确的语法
- 在符合周围环境的同时,始终如一地填补作者指出的空白
- 尊重想要的长度和类型
- 使用选定的实体并反映所需内容的摘要
卢卡斯·布拉塞克的图片来自unpalsh
📆以下是我们今天要学习和玩的内容:
- 如何使用迁移学习来构建一个基于open aiGPT-2transformer 语言模型的最先进的文本生成工具。
- 如何从头开始创建此类任务所需的复杂数据集。暗示了多种型号的综合使用。虽然核心代基于 OpenAI GPT-2,但我们采用了其他几个模型,如 BERT、BART、T5 等。在项目的不同阶段。
- 如何在云实例上为不到 100 美元的培训这个模型。
- 如何在开源 JavaScript/Python web 服务中使用我们的创新用户界面 (UI)作为实用的创作生成工具。
我们到了,让我们开始吧🚀
受控和语境化的文本生成
在深入这个过程的细节之前,让我们先弄清楚我们的方法背后的直觉。💡
理想情况下,我们希望从头开始训练 一个模型来生成与上下文和用户特定输入一致的段落。在实践中,我们会教我们的模型使用前一段和后一段(P1 和 P3)以及用户提供的附加信息来重新生成每本书的段落(P2)。
当然,这意味着使用特定的数据集📁数百部小说被分成段落,还有关于它们的大小、它们展示的实体、它们的内容摘要以及它们所属的书的类型的信息。但是我们稍后会回到这个话题。
然而,这将是一个重大的挑战🙈!这将涉及训练一个拥有数百万参数的巨大语言模型,让它有足够的时间学习产生一致且语法正确的句子,这些句子还应该是语境化和可控的。
【3】例如,一个出色的假新闻文章生成器,拥有 15 亿个参数,需要用 256 个 TPU 进行两周的训练,花费了 35000 美元。💸
为了解决这个问题,我们将走一条在过去几个月/几年里引起极大兴趣的道路:迁移学习💯。这种方法背后的想法很简单:****
- 从在一个非常大的文本语料库上预先训练一个语言模型开始,以便能够生成长段连续连贯的文本。
- ****微调这个语言模型,使其适应我们的最终任务:语境化和可控的文本生成。
由于预训练语言模型是一个昂贵的操作,通常最好从已经预训练和开源的模型开始。在这个项目中,我们决定使用现有的语言模型 Open AI GPT2 ,它已经经过训练,可以生成流畅的句子,并以特定的方式对其进行微调,以产生更具情境性和可控性的输出。
让我们快速浏览一下🔎
🦄打开人工智能 GPT-2
在 2018 年和 2019 年,亚历克·拉德福德、杰弗里·吴和他们在 OpenAI 的同事开源了两个语言模型,对非常大量的数据进行了训练:GPT 和 GPT-2(其中 GPT 代表生成式预训练变压器)。它们是两个非常相似的基于语言模型的转换器,被称为 T2 解码器,因为它们使用左上下文来预测下一个单词。
许多论文和博客帖子描述了变形金刚模型以及它们如何使用注意力机制来处理顺序输入,所以我不会花时间详细介绍它们。如果你对这些模型不熟悉,可以指点一下: Emma Strubell 的 EMNLP 幻灯片是我个人最喜欢的,Jay Alammar 的“ Illustrated Transformer ”是非常详细的介绍。
出于我们的目的,语言模型将只是一个模型,它将一系列标记作为输入,并且为输入序列之后的下一个标记生成词汇表上的概率分布。语言模型通常以并行方式训练,即预测长输入序列中每个标记后面的标记。
🎯调整语言模型
一个经典的语言模型是用一个单一的输入来训练的:一个单词序列。但是正如我们之前看到的,我们的模型将不得不使用上下文的几种类型来生成输出序列:
- 所需段落的长度
- 所需段落的风格/主题
- 要包括的实体列表
- (各种形式的)内容的简短总结
- 过去的和后面的段**
我们如何从这些不同的上下文中为我们的模型构建输入呢?
一个简单的答案就是将上下文片段连接成一个序列,将真正的段落放在最后。然后,我们可以通过继续该序列来逐词生成段落的完成**。因此,每个数据点将具有以下形式:**
[P3] P3 [Sum] Sum [T] Theme [Ent] Entities [Size] [P1] P1 [P2] P2 <|endoftext|>
其中[P 1]、[P 2]、[P 3]、[Sum]、[T]和[Ent]表示模型接收到的输入类型(特殊标记)。请注意,输入的顺序并不重要。你只需要坚持下去。我们只是把 P1 放在最后,这样 GPT-2 就可以从那里继续,因为它已经被训练这样做了。更具体地说,我们有这样的东西:
[P3] And he decided to join the guild... [Sum] Josh thinks about his application to the guild [T] Fantasy [Ent] Josh, the guild, Ella [Size-Large] [P1] Ella has asked Josh to join the guild long before... [P2] ... <|endoftext|>
****技术说明:通常,在训练期间,GPT-2 将一个完整的文本文件作为输入,对其进行标记化并分成大小=块大小的块,这是小型 GPT-2 模型的最大输入大小,1024 个标记。然后,它将它们保存在 torch 数据集中的内存中,并通过数据加载器加载它们。很明显,我们在这方面必须有所不同。我们不想给 GPT-2 提供一个连续的文本,这个文本将根据它的最大输入容量被分割,而是我们上面指定的块,一次一个。因为它们很可能不会完全填满 GPT-2 的输入空间,所以我们在必要时在右边填充。当输入样本太大时,我们截断左边的 P1 和右边的 P3,以便留在 P2 周围。这并不平均,因为我们将剩余空间的 2/3 分配给 P1,1/3 分配给 P3,因为我们认为 P1 比 P3 更重要。
我们训练一个模型,使用前一个和后一个段落(P1 和 P3)以及关于 P2 的信息,重新生成每本书的段落(称为 P2):它的大小,它所属的书的流派,它展示的实体和它的内容摘要。如前所述,我们不是从零开始训练模型,而是微调预训练的 GPT-2 模型,教导它使用上述上下文信息和已经生成的单词来预测下一个单词。这有助于我们的模型学习如何生成与提供的上下文一致的段落。因为它是在许多书籍上训练的,所以希望它能够概括并满足引言中提到的目标——作者的图像
这个简单的设置有两个问题**😗*
- 我们的变压器是色盲🎨!分隔符标记只能给它一个每个单词属于哪个片段的微弱的概念。我们应该添加更多关于段的信息,这意味着我们应该指定这个标记说明生成的段落的大小,以及要包含的实体。**
- 我们的变压器是位置盲的👣!*注意力是对称的点积,所以*我们应该为每个标记添加位置信息。****
添加此信息**的一个简单方法是为字、位置和段构建三个并行输入序列,并将它们融合在一个序列中,将三种类型的嵌入相加:**
- 单词嵌入:单词的矢量表示,在训练中学习。
- 位置嵌入:向量表示(固定的或学习的),包含输入的顺序性质,告诉模型单词具有时间属性。它们对单词在输入句子中的位置进行编码。
- 片段嵌入:帮助模型区分不同输入片段的向量表示。它们标记每个令牌所属的段。在这种情况下,P1,P2,P3,主题,大小,摘要和实体。
我们如何实现这一点?
F 首先,我们将添加特殊令牌** 💥分隔符和段指示符([P1]、[S]、[T])。这些令牌不是我们模型预训练的一部分,所以我们需要为它们创建和训练新的嵌入。**
这些特殊标记方法分别将我们的特殊标记添加到标记器的词汇表中,并在模型中创建五个额外的嵌入。
总的来说,我们使用GPT 2 字节对编码(BPE)标记器**【4】对传递给模型的整个输入进行标记。因此,这个长度为 n 的符号化输入具有三个不同的表示/嵌入,都是形状(1,n,768),其中 768 是小 GPT-2 的嵌入维度,我们将它们加在一起以创建单个输入嵌入。**
我们现在已经初始化了我们的预训练模型👻并且建立了我们的培训投入,剩下的就是选择一个损失到优化🎯在微调期间。
为此,请注意,我们还给网络一个维度为(1,n,768)的标签向量**,除了属于 P2 的令牌,它在任何地方都等于-100。这最终用于逐个令牌地计算仅在生成的和原始的 P2 之间的交叉熵损失函数。实际上,我们并不训练模型来重现全部输入,而是只训练我们感兴趣的段落 P2,如上图所示。想法是该模型利用所提供的上下文信息来学习感兴趣段落 P2 的正确重建。**
在新数据集上训练
既然我们已经描述了框架,我们需要训练我们的模型🏋🏻♂️.因此,让我们回到项目的关键部分:数据集。事实上,如上所述,我们需要创建一个非常具体的数据集来以这种方式调优模型。
让我们强调充分数据生成阶段的一些关键方面,因为预训练的 GPT 新协议的情境化强烈依赖于它。
数据预处理管道-按作者分类的图像
小说数据:我们使用著名的开放图书图书馆项目古腾堡来训练模型。对于 Gutenberg 上现有的每本书,我们创建一个 json 文件,其中包含干净的文本内容及其相关元数据:作者、标题、主题和流派。注意,每本书的独特流派是从非结构化主题信息中手动定义的。然后,我们将每本书的正文分成不同长度的段落,有最小和最大的界限,小心不要在中间切掉一个句子,也不要将核心部分如章节分开,甚至将大段分成不均匀的片段。我们将每个段落的大小存储为一些字符,然后将用于将它们分类为小、中或大。**
实体提取:一旦每本书都按照上面的细节进行了处理,我们就使用一个预先训练好的伯特 NER 大型模型【5】来检测每个段落的实体。分为四类:人员、地点、机构和其他。用此数据训练模型使其能够生成包含已建立实体的文本。它允许作者指定他们想要合并到生成中的内容。**
摘要:类似地,为了让作者能够通过给出想要的内容的信息来指导生成,我们使用最先进的摘要器为每个段落导出了四个非常不同的摘要:
- 如果作者对他们的想法提供了一个详细或简要的总结。[6, 7]
- **BertSum ( 摘录摘要)如果用户给出所需段落的第一句话或关键句。[8]
- KW 如果用户提供一个非结构化的单词序列作为内容的摘要。更多详情此处。[9]
****使用各种汇总类型有助于使我们的模型对作者提供这种类型信息的可能方式更加稳健。参见 r 资源了解不同类型的总结。
O 数据集建立后,我们进行微调🏋🏻来自拥抱脸的预训练 GPT2LMHeadModel (小-117 米)——一个顶部带有语言建模头部的 GPT-2 模型转换器,这是一个线性层,权重与输入嵌入相关联——使用他们的训练脚本的定制版本。
训练期间损失函数的演变——作者图片
我们在 313 本预处理过的书上训练它,使用拥抱脸的所有训练设置** ⚙️.如前所述,我们受到资源的限制,无法真正大规模地运行这个项目。使用 CUDA 在一个 AWS 的 p 3.2x 大型实例(包含一个 NVidia Tesla V100 GPU)上进行训练,花费约 100 美元。总的来说,该模型每个时期接收 134k 个样本,并且有 10 个时期。然而,我们使用的其他指标表明,更少的时期可能足以达到良好的性能。💯**
与模特交谈
文本生成模型的神奇之处在于你可以使用它🤗
为了与我们的模型进行交互,我们需要添加一个东西:一个解码器**,它将从我们模型的下一个令牌预测中构建完整的序列。**
技术说明:与培训不同,我们不输入 P2。然而,我们需要为它的生成留出足够的空间,因为模型的输出等于模型的输入加上生成的序列。因此,输入不能超过小于 1024 个令牌的特定限制,这是我们基于置信区间确定的。如果输入太大,我们截断它,类似于在训练中所做的。
在这种模式下,在对输入进行编码之后,我们使用嵌入在 transformers 生成函数中的精心选择的解码策略来生成适当的新段落 P2。更准确地说,为了生成新单词(或令牌),该模型输出单个向量,并将其乘以所学习的嵌入矩阵。它为词汇表中的每个单词产生一个唯一的分数,这个分数最终决定了每个单词被生成的概率。参见图 4。选择最佳的解码策略和超参数是获得好的生成文本的关键步骤,因为它对作者生成图像有很大的影响
在过去的几个月里,解码器有了非常有趣的发展,我想在这里快速展示一下,让你了解最新情况。
用于语言生成的两个最常见的解码器曾经是贪婪解码和波束搜索**。⚜️⚜️⚜️**
贪婪解码(Greedy-decoding)是生成句子最简单的方法:在每个时间步,我们根据模型选择最有可能的下一个记号,直到我们到达序列结束记号。贪婪解码的一个风险是高概率令牌可能隐藏在低概率令牌之后而被错过。**
波束搜索 试图通过保持我们逐字构建的几个可能序列的波束来缓解这个问题[10]。在这个过程的最后,我们从这些句子中选出最好的句子。在过去的几年里,beam-search 已经成为几乎所有语言生成任务的标准解码算法。总的来说,它会产生更流畅的输出,但经常会重复,这在故事生成中是特别不理想的。
除此之外,Ari Holtzman 等人[11]最近发表的研究表明,使用波束搜索和贪婪解码生成的文本中的单词分布与人类生成的文本中的单词分布非常不同。显然,波束搜索和贪婪解码无法再现人类文本的某些分布方面,因此被当前最有前途的两种方法 top-k 和 细胞核(或 top-p)采样 、所取代。这两种方法的一般原理是在过滤下一个记号分布以仅保留前 k 个记号( top-k )或累积概率刚好高于阈值的前 k 个记号( nucleus/top-p )之后,从该分布中采样。
换句话说, top-k sampling 建立在采样的基础上,它简单地选择 k 个最可能的单词,并跨 k 个所选单词重新调整概率质量分布。这种方法产生了非常好的结果(拉德福德等人,2019)。它的唯一限制是,无论是窄分布还是宽分布,k 都是固定的,而我们可能希望区分这两种情况。
这就是为什么核心采样被创建为单词集的大小(也称为集合中的单词数)可以根据下一个单词的概率分布动态增加和减少。**
注意降低温度🌡️使提高概率质量分布成为可能。增加它促进了多样性,更适合我们,因为我们想要创造性的输出,给作者提供想法,即使有些错误。**
我们现在可以开始玩我们的模型了🚀
网络服务
对于这个项目,我们也想创新,并给出一个关于人工智能增强界面在用户体验方面看起来会是什么样子的建议。因此,我们设计了一个接口,并将其链接到后端的弹性实例。然后,我们向一小部分公众开放,以测试我们的模型。🎬
由于资源有限,我们现在关闭了它*——是的,它很贵。但是你仍然可以在你的本地计算机上运行并使用它。***
建筑——作者的图像
技术说明:为了在选择执行繁重计算的实例时获得灵活性,并允许在几个实例上实现负载平衡,我们将主实例(服务于 javascript 前端和一般数据)与计算实例(按需执行 NER 和文本生成)分离。客户端也可以在本地运行服务器,以避免延迟和服务器过载。下图给出了我们服务的总体架构。
在这个界面,🏝️ ️users 被邀请在一个简单的编辑器中写一些文本。命名的实体,如人物,地点,组织和其他被 NER 后端即时检测,并显示在左边的面板上。如果需要,用户可以很容易地手动编辑它们。
用户有的可能性来选择几个选项:所需段落的长度、他们写作的风格以及他们希望在这一代中看到的实体列表。他们还可以突出显示文本的一小部分,作为摘要(或关键字列表)。当他们准备好了,他们只需要按下生成按钮,让奇迹发生。**
AITextGenerator 菜单指南快照—作者图片
进一步发展和结论
在总结中,我们展示了一个来自古登堡计划库的原始文本文件的端到端管道📚给写书人的网络服务。后者嵌入了一个可控的和情境化的 GPT-2,用于特定于小说的文本生成,这是根据我们在十个时代期间数百部小说的管道进行微调的🎳。总的来说,尽管计算资源有限,我们还是设法建立了一个最终模型,它能够考虑用户指定的上下文。**
随着计算能力的不断提高和最近旨在减少模型大小而不损害生成能力的研究趋势,我们坚信这种可控的生成框架将在未来的中很容易实现,并将大大增强作者的创造力。****
一些曲目甚至更进一步*😗**
- 在我们微调过的 GPT-2 模型的基础上增加一个 PPLM 模型,进一步引导这一代人,例如控制段落的主题和情绪。
- 改变损失来惩罚一个实体的缺席
- 使用一个大 GPT-2* 模型来提高生成文本的质量。***
W 我们已经到了这篇文章的结尾描述了如何使用迁移学习和 OpenAI GPT2 这样的大规模语言模型,为小说作者构建一个最先进的受控和情境化的写作工具。**
务必检查相关的演示和代码*😗**
- 这里的接口是(你现在需要在本地运行它,因为我们剪切了我们的实例)**
- 开源代码和预训练模型在这里是。
与托马斯·拉姆森和盖尔·德·莱塞勒一起写的
参考
[1] 语言模型是无监督的多任务学习器,亚历克·拉德福德等人(2019)https://D4 mucfpksywv . cloudfront . net/better-Language-models/Language-models . pdf
**[2] 关注是你所需要的一切,作者 A 瓦斯瓦尼等人(2017)https://arxiv.org/pdf/1706.03762.pdf
**[3] 防御神经性假新闻,罗文·泽勒斯、阿里·霍尔茨曼等人(2019)https://grover.allenai.org/
**[4] 具有子词单元的罕见词的神经机器翻译,作者森里奇(Sennrich,r .),哈道(Haddow,b .),&伯奇(Birch,a .)(2015)https://arxiv.org/pdf/1508.07909.pdf
**[5] 伯特:语言理解的深度双向变压器预训练,作者雅各布·德夫林等人 2018https://arxiv.org/abs/1810.04805
**[6] Bart:自然语言生成、翻译和理解的去噪序列间预训练,https://arxiv.org/abs/1910.13461 迈克·刘易斯等 2019
****[7] 用统一的文本到文本转换器探索迁移学习的极限科林·拉弗尔等人 2019 年【https://arxiv.org/abs/1910.10683 ****
[8] 微调伯特进行提炼总结作者刘洋。2019.https://arxiv.org/abs/1903.10318
[9] Textrank:将秩序带入文本作者拉达·米哈尔恰和保罗·塔劳。2004.https://www.aclweb.org/anthology/W04-3252/
[10] 神经对话建模中搜索和评估策略的重要性,伊利亚·库利科夫等人 2019。https://arxiv.org/abs/1811.00907
【11】阿里·霍尔茨曼、简·布伊斯、麦斯威尔·福布斯、叶筋·崔(https://arxiv.org/abs/1904.09751)撰写的《神经文本退化的奇特案例》
如何推动有效人工智能/人工智能的实验文化
实验产生持续的改进(图片来自 Adobe 的 VectorMine
据哈佛商业评论报道,许多创新公司的一个众所周知的秘密是他们能够每天使用数据科学进行成千上万次实验,以了解他们客户的需求。仅举几个例子,Expedia,Spotify,Bookings.com,扩大了他们的数据科学管道,进行将影响他们底线的测试。然而,仅仅建立一个数据科学管道是不够的;你需要将实验文化融入其中才能成功。
实验文化的瓶颈
为什么实验这么难?(图片由 Adobe 的 VectorMine 提供)
在大型组织中,大量的工作流、应用程序和数据平台可能会垄断您的所有开发资源。简单的修补-修补-发布项目不会产生长期收入。在不稳定的整合工作基础上构建数据科学管道可能会对数据治理造成严重破坏。当将数据从管道的一部分移动到另一部分时,延迟甚至会阻碍最好的数据科学成果。
即使在拥有高效团队的组织中,数据科学的努力也取得了回报,但在运营系统和分析系统之间往往存在隔阂。例如,设想一家保险公司,其中一个小组开发和维护核保应用程序,另一个小组开发模型来确定客户在保单应用程序上是否诚实。运营和分析工作负载的分离只是传统文化的一个例子,它阻止了新的实验文化在整个组织中蔓延。
数据科学团队经常无意中在独立于组织内所有其他团队的专用孤岛中工作。应用程序开发人员和业务部门专家没有在项目中与基层的数据科学团队合作。相反,他们只有在需要彼此的东西(通常是数据)时才会一起工作。最终结果是,当数据科学家获得实时数据时,这些数据往往已经过时。通过多层计算,数据经常在混乱中丢失。
数据科学民主化
打破数据科学孤岛(图片来自 Adobe 的 VectorMine
公司真正收获创新时代回报的唯一方式是发展一种实验文化,从组织内的数据工程和数据科学团队民主化开始。数据科学必须集成到业务部门专家和应用程序开发团队的工作中,数据科学项目应该从一开始就优先考虑扩大规模。应用程序开发人员、数据科学家、数据工程师和业务部门专家应该在数据科学管道中协同工作,以确保持续改进业务成果。如果数据不能自由共享,并且数据科学家在应用程序的生命周期中没有积极参与,数据管道就会受到损害。
数据科学民主化可以解决三个问题:
1)整合数据源以消除延迟,并采取更准确的业务行动
2)创造值得信赖的数据科学,通过持续创新对底线产生积极影响
3)维护数据血统以改善 AI/ML 的共享治理。
我们相信一个集成的数据库和机器学习平台是在整个组织内实现数据科学民主化所必需的。借助这一新框架,数据科学家、业务部门专家、操作员和应用程序开发人员从数据科学研究的一开始就协同工作,并持续协作。
- 应用程序开发人员可以利用更多数据并提供实时分析,而无需 ETL。
- 数据工程师可以轻松地为数据科学家提供实时特征管道。
- 数据科学家可以自由试验,以优化预测准确性,从而带来更好的业务成果。
每个人都可以访问与生产同步的数据。对算法如何处理实时数据没有限制,也没有在机器之间来回传输数据集。通过与应用程序开发人员合作,数据科学家可以实现治理和部署,以确保数据和算法的完整性。
应用程序开发人员拥有生产基础架构的很大一部分,并成为与其支持的业务部门相关的数据科学项目的真正利益相关者。他们的角色越来越成为治理者。随着时间的推移,随着应用程序开发人员扩大其数据科学知识,他们可以使用一组透明的测试和流程来监控和治理模型。
独立运行的团队,如 DevOps、DBOps 和 MLOps,也可以聚合在实验和治理的保护伞下。应用程序开发人员可以与基础设施团队紧密合作,消除沟通障碍,实现更顺畅的部署、监控和生产管理。
利用精选数据—特征商店
重复使用费力的数据管理,无需重复劳动(图片由来自 Adobe 的 VectorMine 提供)
一个释放实验文化的新创新是采用特色商店。正如在之前的博客中所总结的那样,功能库使数据科学家能够共享从原始数据转换而来的精选数据。人们常说,数据科学家 80%的时间花在特性工程上,只有 20%的时间花在模型实验上。要素存储使数据科学家能够重复使用数据工程师和数据科学家执行的繁重任务,以创建提供预测信号的要素。最佳要素存储使要素能够通过复杂的分析管道基于事件进行更新,从而创建强大的预测模型。它还使数据科学家能够创建从模型实验到特征实验的明确谱系。
有了聚合 SQL 数据平台上的功能存储,数据科学家可以在过去所需时间的一小部分内运行数百或数千次测试。通过与业务单位专家的紧密合作,以及与 it 组织的合作,测试可以在许多模型上连续地、跨功能地运行。例如,销售模型可以通过测试消费者群体的总体消费行为来优化。类似地,为了实现企业内的最佳财务目标,测试风险或欺诈模型可能是必要的,但同时测试消费者情绪的变化也可能是必要的。当使用特征库时,所有这些组都能够重用特征,使得实验更有效率。在这个框架中,数据科学家更接近管理层,使用最新的创新技术来分析数据,这些数据用于支持组织级别的“宏观”决策。如果没有功能存储,数据科学家必须花费宝贵的时间和资源来集成计算元素和处理数据。
实验文化最终允许你的组织从一个 使用 技术的组织转变为一个 通过技术授权 的组织。它成为进一步创新的基石,尤其是在需要企业人工智能的时候。
遍布整个企业—易于供应、管理和操作
在任何地方创建实验沙盒(图片由来自 Adobe 的 VectorMine 提供)
创建实验文化的最大挑战之一是计算资源的无摩擦供应和管理。但现在有了 Kubernetes,可以轻松地调配和编排自我修复的计算和存储资源,根据工作负载的需求扩展和缩小平台,甚至在不使用时暂停平台。例如,我们的新拼接机 Kubernetes Ops Center ,这是一套 Kubernetes 操作员和掌舵图表,一个小型 DevOps 团队可以供应、管理和操作许多不同的 SQL 和 ML 平台,每个平台甚至支持数百个小型到大型分布式 SQL 数据库。借助 OpCenter,运营商可以轻松搜索日志和监控指标,以保持平台健康。团队可以快速高效地在整个企业以及开发、测试和生产集群中构建沙盒。这消除了创造实验环境的摩擦。
结论
大多数组织仍然停留在专家孤岛的思维模式中。应用程序开发人员、数据工程师和数据科学家都需要计算资源,如今他们在他们之间移动数据并执行重复的工作。如果这些孤岛能够在预集成和优化的基础架构上共享数据以消除延迟,会怎么样?如果团队可以重用彼此策划的特性和模型来消除不必要的重复工作,会怎么样?如果每个团队都可以利用真正敏捷的计算资源,会怎么样?你可以打破这些壁垒,将人工智能/人工智能有效地注入到流程中,真正将现有的基础设施升级为智能平台。通过这一过程,您正在构建一个融合了实验文化的数据科学管道。这种文化不仅能让您的数据科学项目获得回报,还能不断让您的组织更快地创新,适应业务环境的变化,并根据预测将要发生的事情而不是对已经发生的事情做出反应来采取行动。
要观看 Kubernetes 架构数据和 ML 平台如何通过功能商店形成实验文化的基础的演示,请点击此处。
如何使用 TensorFlow 对象检测 API 构建和部署自定义对象检测器和分类器?
了解如何构建交通灯检测器和分类器,用于对真正的自动驾驶汽车进行编程。
交通灯分类器:现场(左)和模拟器(右)
动机:
使用 TensorFlow 对象检测 API 实现一个交通灯分类器——这可以用于使用边界框检测图像和/或视频中的对象,使用一些可用的预训练模型或通过您可以自己训练的模型。
应用:
编程一辆真正的自动驾驶汽车。解决自主车辆视觉和感知问题的尝试。
代码和实现:
请在我的 GitHub 库 中找到与这篇博文相关的所有必要文件、代码、模块和结果。
这个交通灯分类器是 Udacity 的自动驾驶汽车工程师 Nanodegree 的关键部分。我带领一个 4 人团队(合作的有 w/ 阿伦·萨加尔、马里斯·p·拉纳维拉和李爽),每个成员都有着不同的背景和经验,来编写一辆真正的自动驾驶汽车。请在 GitHub 上找到这个项目资源库。
为什么选择 TensorFlow 物体检测 API?
TensorFlow 的对象检测 API 是一个强大的工具,可以轻松构建、训练和部署对象检测模型。在大多数情况下,从头开始训练整个卷积网络非常耗时,并且需要大型数据集。这个问题可以通过使用 TensorFlow API 的预训练模型利用迁移学习的优势来解决。
构建分类器:
安装入门:找到 TensorFlow 对象检测 API 库上的说明,转到路径:tensorflow/models/object_detection/g3doc/installation.md
。
- 克隆或下载 TensorFlow 模型库。在终端/cmd.exe 中导航到该目录
- 转到
[https://github.com/protocolbuffers/protobuf/releases/tag/v3.4.0](https://github.com/protocolbuffers/protobuf/releases/tag/v3.4.0)
并下载 protocol-3 . 4 . 0-win32 . zip(根据您的操作系统和要求选择合适的版本) - 从上面的连续步骤中提取两个下载的文件。现在,在
models
(或models-master
)目录中,您可以使用protoc
命令:
在 Windows 上:
"C:/Program Files/protoc/bin/protoc"object_detection/protos/*.proto --python_out=.
在 Ubuntu 上:
protoc object_detection/protos/*.proto --python_out=.export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
- 运行朱庇特笔记本
[object_detection_tutorial.ipynb](https://github.com/tensorflow/models/blob/master/research/object_detection/colab_tutorials/object_detection_tutorial.ipynb)
。这会为您下载一个预先训练好的模型。这里的预训练模型是 COCO(上下文中的公共对象)。在笔记本上,注释掉get_ipython().magic('matplotlib inline')
行。 - 接下来,使用
import cv2
引入 Python Open CV 包装器 - 实际的检测过程发生在“for”循环中(在最后一个单元格中),我们需要根据我们的需要相应地修改它。当然,我们还可以做更多的代码清理工作,比如去掉 Matplotlib 导入,如果你愿意,可以随意清理。
- 加载您的自定义图像:在 jupyter 笔记本中,进行必要的导入以从目录中加载您的图像,修改笔记本以满足您的需要,然后运行它。
如何使用 TensorFlow 对象检测 API 建立红绿灯检测模型?
将您感兴趣的对象添加到预训练的模型中,或者使用该模型的权重来给自己一个训练这些新对象的良好开端。Tensorflow 对象检测 API 基本上是准确性和速度之间的折衷。考虑到我正在处理的数据集,我选择使用*faster_rcnn_inception_v2_coco*
。请查看 TensorFlow 检测模型动物园下可用模型的完整列表。
步骤:
- 收集大约 500 张(或者更多,如果你愿意)自定义交通灯图像。对于这个项目,我选择的图片来自——Udacity 模拟器、uda city 的卡拉测试网站和网络
- 使用“labelImg”注释自定义图像
- 将它们分成训练测试集
- 为列车测试分割生成 TFRecord
- 设置配置文件
- 训练实际模型
- 从新训练的模型中导出图表
- 引入冻结推理图对交通灯进行实时分类
步骤 1:收集自定义交通灯图像
- 模拟器:在相机打开的情况下运行模拟器,并按照指示从模拟器中收集交通灯图像
从 Udacity 模拟器中收集的一些示例图像
- 站点:从 Udacity 提供的 ROS 包中下载卡拉站点的红绿灯图像
从 Udacity 的卡拉网站收集的一些样本图像
步骤 2:注释自定义交通灯图像
使用‘label img’手工标记交通灯数据集图像。
步骤:
- 克隆 labelImg 库
- 遵循符合您的 python 版本要求的安装步骤。但是,对于 Ubuntu 上的 Python3:
sudo apt-get install pyqt5-dev-toolssudo pip3 install lxmlmake qt5py3python3 labelImg.py
- 运行
python labelImg.py
- 打开保存了所有交通灯图像的目录
- 对于每个图像,在您想要检测的交通灯周围创建一个矩形框,并相应地添加标签(在我们的例子中是红色、绿色、黄色)
- 将它们保存在您选择的目录中。按照以下步骤定制所有图像的标签
“labelImg GUI ”,其中示例交通灯被标注为“红色”
步骤 3:训练-测试分割
进行 90-10 分割:将带注释的图像及其匹配的 XML 注释文件添加到两个独立的文件夹中,分别命名为“train”(90%的图像)和“test”(10%的图像)。
步骤 4:为训练测试分割生成 TFRecords
我们需要一些来自 GitHub 的 Dat Tran 的浣熊数据集仓库的帮助器代码。我们只需要从这个回购 2 脚本:xml_to_csv.py
和generate_tfrecord.py
。
(1) xml_to_csv.py :
- 对该文件的 main 函数进行必要的修改。这将遍历训练和测试,以创建那些单独的 CSV,然后从这些 CSV 中,我们创建 TFRecord
在xml_to_csv.py
脚本中,我替换了:
def main():
image_path = os.path.join(os.getcwd(), 'annotations')
xml_df = xml_to_csv(image_path)
xml_df.to_csv('raccoon_labels.csv', index=None)
print('Successfully converted xml to csv.')
使用:
def main():
for directory in ['train','test']:
image_path = os.path.join(os.getcwd(), 'images/{}'.format(directory))
xml_df = xml_to_csv(image_path)
xml_df.to_csv('data/{}_labels.csv'.format(directory), index=None)
print('Successfully converted xml to csv.')
- 运行
python3 xml_to_csv.py
命令。现在,您已经准备好了 CSV 文件:train_labels.csv
和test_labels.csv
(2)generate _ TF record . py:
- 接下来,我们需要抓取 TFRecord:转到
[datitran/raccoon_dataset/blob/master/generate_tfrecord.py](https://github.com/datitran/raccoon_dataset/blob/master/generate_tfrecord.py)
- 这里您需要做的唯一修改是在
class_text_to_int
函数中。您需要将此更改为您的特定类。在这种情况下,在 if-elif-else 语句中为红色、绿色和黄色各添加三个“row_label”值
# TO-DO replace this with label map
def class_text_to_int(row_label):
if row_label == 'Red':
return 1
elif row_label == 'Yellow':
return 2
elif row_label == 'Green':
return 3
else:
None
记得使用相同的 id 值
%%writefile training/labelmap.pbtxt
item {
id: 1
name: 'Red'
}
item {
id: 2
name: 'Yellow'
}
item {
id: 3
name: 'Green'
}
- 确保已经安装了 Object Detection(GitHub 上的 installation.md)。运行
generate_tfrecord.py
的“使用”部分中的两个命令,分别用于训练和测试。
对于列车 TFRecord:
python3 generate_tfrecord.py --csv_input=data/train_labels.csv --output_path=data/train.record --image_dir=images/
对于测试 TFRecord:
python3 generate_tfrecord.py --csv_input=data/test_labels.csv --output_path=data/test.record --image_dir=images/
现在我们已经准备好了训练和测试记录文件。我们需要 TFRecord 文件的原因是将任何会生成数据的文件(比如 PASCAL VOC 格式)转换成 TFRecord,这样我们就可以在对象检测 API 中使用它们。
步骤 5:设置配置文件
为了训练我们的模型,我们需要设置一个配置文件(连同 TFRecord 和一个预训练的模型)。请在 Tensorflow 对象检测 API 上找到所有相关文件、安装信息、预训练模型等。
步骤:
- 去 GitHub 上的
[https://github.com/tensorflow/models/tree/master/research/object_detection/samples/configs](https://github.com/tensorflow/models/tree/master/research/object_detection/samples/configs)
- 从 TF 模型检测动物园下载 faster _ rcnn _ inception _ v2 _ coco 模型的配置文件(
[faster_rcnn_inception_v2_coco.config](https://github.com/tensorflow/models/blob/master/research/object_detection/samples/configs/faster_rcnn_inception_v2_coco.config)
)和检查点(. tar.gz 文件) - 运行两个命令,分别下载配置文件和更快的 R-CNN 模型(同时提取下载的模型)。将配置文件放在
training
目录下,提取models/object_detection
目录下的faster_rcnn_inception_v2_coco
- 修改配置文件以满足您的要求,包括但不限于
PATH_TO_BE_CONFIGURED
、num_classes
、batch_size
、checkpoint name
、到fine_tune_checkpoint
、label_map_path: “training/object-detect.pbtxt”
的路径 - 添加带有红色、黄色和绿色的项目和 id 值的标签映射文件(如步骤 4 所示)
步骤 6:训练实际模型
- 在
models/object_detection
中,使用 python 命令运行您的模型,同时包含保存模型的路径,配置文件的管道
python3 train.py --logtostderr --train_dir=training/ --pipeline_config_path=training/faster_rcnn_inception_v2_coco.config
- 此时,除非出现错误,否则您应该会看到模型摘要,其中包含步骤及其相应的损失值,如下所示
INFO:tensorflow:global step 11788: loss = 0.6717 (0.398 sec/step)
INFO:tensorflow:global step 11789: loss = 0.5310 (0.436 sec/step)
INFO:tensorflow:global step 11790: loss = 0.6614 (0.405 sec/step)
INFO:tensorflow:global step 11791: loss = 0.7758 (0.460 sec/step)
INFO:tensorflow:global step 11792: loss = 0.7164 (0.378 sec/step)
INFO:tensorflow:global step 11793: loss = 0.8096 (0.393 sec/step)
你的步骤从 1 开始,亏损会高很多。根据你的 GPU 和你有多少训练数据,这个过程将需要不同的时间。你希望平均损失约为 1 英镑(或更低)。
- 您可以加载 Tensorboard 来可视化这些值,包括损耗、准确度、步数和训练时间
- 现在,您已经准备好了经过训练的模型。接下来,通过检查点加载模型
更快的 R-CNN 模型架构:
更快的 R-CNN 最初发表于 NIPS 2015 。它的结构很复杂,因为它有几个移动的部分。
这是该模型的高级概述。这一切都始于一幅图像,我们希望从中获得:
- 边界框列表
- 分配给每个边界框的标签
- 每个标签和边界框的概率
由哈维尔·雷撰写的博客很好地解释了物体检测如何在更快的 R-CNN 上工作,这可以在 Tryolabs 上找到。
要快速了解更快的 R-CNN 及其地区提案网络,请参考高昊在媒体上的博文。
注:
- 在尝试了包括 SSD Inception V2、更快的 R-CNN 和 Nvidia 的卷积神经网络在内的不同模型后,我们最终决定使用更快的 R-CNN,因为我们发现它的性能对于我们的交通灯数据集来说非常有吸引力。归根结底,选择合适的型号是在“准确性”和“速度”之间进行权衡,以满足您的要求。
- 请在代码为的纸上找到对象检测的最新模型。我决定选择更快的 R-CNN,因为它的性能满足目标检测过程中“准确性”而不是“速度”的要求。此外,TensorFlow 没有通过将 SOTA 模型添加到其 TensorFlow 对象检测 API 存储库中来与它们保持同步。
步骤 7:从新训练的模型中导出图表
- 在这一步,我们将测试我们的模型,看看它是否如我们所愿。为了做到这一点,我们需要导出推理图。在
models/object_detection
目录中,有一个脚本为我们完成了这项工作:export_inference_graph.py
- 转到
installation.md
(https://github . com/tensor flow/models/blob/master/research/object _ detection/g3doc/installation . MD)中的“Protobuf 编译”部分,按照给出的说明导出路径。这就加载了 TensorFlow,然后制作图表并保存 - 使用 API 附带的笔记本
object_detection_tutorial.ipynb
进行物体检测
第八步:引入冻结推理图对交通灯进行实时分类
- 修改
export_inference_graph.py
来满足你的要求。要运行这个,您只需要传入您的检查点和您的管道配置,然后在任何您想要放置推理图的地方。例如:
python3 export_inference_graph.py \
--input_type image_tensor \
--pipeline_config_path training/faster_rcnn_inception_v2_coco.config \
--trained_checkpoint_prefix training/model.ckpt-10856 \
--output_directory traffic_lights_inference_graph
- 运行安装命令导出推理图(https://github . com/tensor flow/models/blob/master/research/object _ detection/g3doc/installation . MD)。现在,您已经准备好了
frozen_inference_graph.pb
和检查点文件 - 您的检查点文件应该在
training
目录中。只要找一个步长最大的(破折号后最大的数字),那就是你要用的。接下来,确保将pipeline_config_path
设置为您选择的任何配置文件,然后最后选择输出目录的名称,比如说traffic_lights_inference_graph
从models/object_detection
运行上述命令。如果您得到一个关于没有名为“nets”的模块的错误,那么您需要重新运行:
# From tensorflow/models/
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
# switch back to object_detection after this and re run the above command
- 打开
object_detection_tutorial.ipynb
笔记本。在笔记本上进行必要的修改,包括但不限于MODEL_NAME
、PATH_TO_CKPT
、PATH_TO_LABELS
、NUM_CLASSES
、TEST_IMAGE_PATHS
。运行笔记本以查看带有边界框的交通灯及其预测精度
结果:
来自模拟器的图像用边界框和预测精度分类
使用边界框和预测精度分类的站点图像
限制:
- 鉴于这个项目的范围,除了模拟器和 CARLA 网站上的图片,我只使用了网上的一些图片。而且,这个模型还没有在一个新的未知网站上测试过。
- 该模型在独特的光照和天气条件下的表现尚不清楚,因为这里使用的大多数图像都是在典型的晴朗天气拍摄的。
- 随着该领域的不断研究,还有其他最先进的物体检测模型可能具有相对更好的性能精度。
致谢:
感谢巴斯蒂安·特龙和大卫·斯塔文斯(创始人, Udacity )、大卫·西尔弗、瑞安·基南、塞尚·卡马乔对课程材料和指导的帮助,以及官方合作伙伴的演讲嘉宾,包括英伟达 AI 、 UberATG 、梅赛德斯-奔驰、宝马、迈凯轮、滴滴出行,他们提供的专业知识极大地帮助了研究。
如果你有任何意见想与我分享(或)对我的写作或想法提供任何相关的反馈,我会很高兴收到你的来信。请随时在Twitter*LinkedIn上与我联系,或者在GitHub上关注我。*
如何使用 TPOT 构建 Dask 分布式集群进行自动管道搜索
实践教程
这是一个深入的教程,指导您通过开源 python 库(即 Dask 和 TPOT)建立可扩展的自动化机器学习模型管道搜索所需的所有步骤。
您是否曾经遇到过这样的情况:您知道自己已经尽了最大努力清理数据集,但却无法选择最佳模型?你有很多 CPU,但是它们在不同的主机上吗?那么这就是给你的指南!我们将探索 Dask ,特别是 Dask 的分布式库,不仅并行化我们的 TPOT 管道搜索,而且将它们分布在不同的机器上。
Dask 是什么?
Dask 是一个开源并行计算库,可以扩展现有的 Python 生态系统。它与通用数据科学堆栈集成良好; NumPy 、熊猫和 scikit-learn 。有了 Dask,我们可以从笔记本电脑到整个集群进行大规模计算。我们将关注后者。
Dask 分布式是什么?
Dask.distributed :是一个轻量级的开源 Python 分布式计算库。
架构: Dask.distributed 是一个集中管理的、分布式的、动态的任务调度器。它有三个主要过程:
- **dask-scheduler:**中央 dask-scheduler 进程协调分布在多台机器上的多个 dask-worker 进程的动作以及多个客户端的并发请求。
- ***dask-worker:*dask-worker 分布在多台机器上,处理多个客户端的并发请求。
- ****dask-client:dask-client 是 dask.distributed 用户的主要入口点
设置调度程序和工人的步骤:
在本例中,我们将使用 VMware ESXi 在一台主机上创建 3 台虚拟机。一个是调度程序,同时运行 jupyter 笔记本,另外两个是工人。这只是一个概念验证设置。不可否认,这不是启动集群工作者的最有效的方法。尽管如此,这将提出一个更通用的流程,然后可以采用云解决方案和/或 Dask Kubernetes 。
我们将从调度程序实例开始。首先点击创建/注册虚拟机>创建新的虚拟机>然后****
您可以选择任何名称,但我建议指定一个容易识别的名称,如 cluster-master。对于这个例子,我在所有机器上都使用了 Ubuntu 20.04.1 live server 。这不是强制性的,但强烈建议在所有机器中使用相同的分布。这些机器将用于对大型数据集进行计算。因此,强烈建议为每台机器分配大量 RAM,如果不可能,至少设置交换内存。对于本例,我们将在每台机器上使用 24 Gb 的 RAM 和 8 个 vCPUs。
在本教程中,我们将使用熊猫数据帧。对于特别大的数据集,我们可以使用 Dask 的数据框架对象。达斯克。数据帧是一个大型并行数据帧,由许多较小的数据帧组成,沿着索引分割。这些 Pandas 数据帧可能存在于磁盘上,用于单台机器或集群中许多不同机器上的大内存计算。
这是我们虚拟机规格的快照。你可以根据你的需要改变这些。
对工作机器重复该过程。我们选择相同的规格,但这不是强制性的。在每台机器上安装操作系统后,我们将通过 SSH 安装必要的软件。对于这样的小集群,我们选择 ClusterSSH 。ClusterSSH 是围绕 XTerm 和 SSH 等标准 Linux 工具的 Tk/Perl 包装器。我们将使用它同时向所有机器复制命令。事不宜迟,言归正传。
运行以下命令在本地机器上安装 ClusterSSH。在本教程中,我们将通过 SSH 从我们的个人计算机管理集群。我们将不配置集群。我们将通过在 CLI 中传递用户名和 IP 地址来连接到机器。对于更大或多个集群,建议编辑位于~/.csshrc
的配置文件。
*sudo apt-get install clusterssh
clusterssh cluster-master-name@cluster-master-ip cluster-worker1-name@cluster-worker1-ip cluster-worker2-name@cluster-worker2-ip*
在上图中,您在 CLUSTERSSH 灰色窗口中键入的任何内容都将被复制到所有机器上。您也可以在每个窗口上分别键入单独的 shell 命令。我们希望将以下命令复制到所有计算机上:
*sudo apt-get update
sudo apt-get upgrade -y
wget [https://repo.anaconda.com/archive/Anaconda3-2020.07-Linux-x86_64.sh](https://repo.anaconda.com/archive/Anaconda3-2020.07-Linux-x86_64.sh)
chmod 755 Anaconda3-2020.07-Linux-x86_64.sh
bash Anaconda3-2020.07-Linux-x86_64.sh
conda init*
然后我们必须重启 shell,这非常简单,我们可以通过 ClusterSSH 断开连接并重新连接。如果您将 Anaconda3 安装到不同的位置,只需导出路径并运行./anaconda3/condabin/conda init
。重新连接后,运行以下命令来安装 TPOT 和 Dask 的必要先决条件。请注意,除了 PyTorch 之外,我们还为 TPOT 的额外功能安装了所有可选的依赖项。
*conda install -c conda-forge tpot xgboost dask distributed dask-ml scikit-mdr skrebate -y
conda update conda
conda update --all*
建立分布式集群的步骤:
首先,我们需要设置调度程序,这样我们可以稍后连接其余的机器。尽管所有这些机器都驻留在同一个主机中,但为了涵盖一般情况,我们不会通过 LAN 连接它们。我们开始吧!我们将使用一个名为 screen 的终端复用器来管理一个 ssh 会话中的多个 shells。这里有一个你需要的选项的快速备忘单:
*screen -S session_name #Starts a new screen named session_name
screen -r #Resumes a screen session
screen -ls #Returns the session IDs of running screens
screen -X -S <id or name> kill #Kills the specified screen
While inside an attached screen: Ctrl+a d #Detaches the current screen*
太好了!现在我们准备在屏幕中设置调度程序!单击主/调度程序虚拟机实例 SSH 窗口,并键入以下内容:
*screen -S schedulerdask-scheduler*
您应该会看到这个输出!
当然,调度程序的 IP 地址会有所不同。调度程序本身位于8786
港口,这是我们将所有工人指向的地方。8787
端口托管 dask 仪表板。在我们连接所有的工人之后,我们将稍后回到这一点。现在,按下Ctrl+a d
分离屏幕。现在让我们设置我们的 jupyter 笔记本:
*screen -S notebookjupyter notebook --no-browser --port=8888*
保存令牌!你以后会需要它的。
保存令牌,分离屏幕并关闭 SSH 连接。不要关闭到其他机器的 SSH 连接。我们现在必须将主虚拟机实例中远程笔记本的端口转发到本地端口,以便我们可以从浏览器访问它。我们可以使用以下命令来实现这一点:
*ssh **-**N **-**f **-**L localhost**:**8003**:**localhost**:**8888 remoteuser**@**remotehost#Forwards the port 8888 of our remote machine to port 8003 of our local machine. We can now access it in our browser at localhost:8003*
在指定的端口(我们选择 8003)上转到您的本地主机,输入您保存的令牌,瞧!笔记本在远程机器上运行,而我们在本地机器上编辑它。
现在,我们可以继续设置所有工作线程来指向调度程序。这很简单。我们通过灰色的 ClusterSSH 终端创建一个屏幕,这次是在所有的 workers 中,并将它们指向主 VM 实例中的调度程序。
*screen -S workerdask-worker IP-of-the-scheduler:8786 --nprocs 1 --nthreads 8*
拆下屏幕,一切就绪。客户端已连接,调度程序已启动并正在运行,您还有一个仪表板来检查一切!使用 nprocs 和 nthreads 参数分别选择每个工作线程的进程数和线程数。这个选择取决于工作量。Dask 的主要撰稿人 Matthew Rocklin 建议如下:
如果您主要处理数字工作负载,比如 Numpy、Pandas 和 Scikit-Learn 代码中常见的,每个进程使用几个进程和多个线程是很好的,这不受 Python 的全局解释器锁 (GIL)的影响。但是,如果您将大部分计算时间花在处理纯 Python 对象(如字符串或字典)上,那么您可能希望通过用更少的线程处理更多的进程来避免 GIL 问题。使用更多的进程避免了 GIL 问题,但是由于进程间的通信而增加了成本。如果您的计算需要大量的内部通信,您可能希望避免许多进程。来源:MRocklin - StackOverflow
什么是 TPOT?
TPOT 是一个 Python 自动机器学习(AutoML)工具,它使用遗传编程来优化机器学习管道。TPOT 构建在 scikit-learn 库之上,就像 Dask 一样,它使用现有的 Python APIs 和数据结构。这意味着对于 scikit-learn 用户来说,它的用法应该非常直观。它还可以很好地与 Dask 集成!
机器学习管道示例 —来源:文档
TPOT 快速概览:
TPOT 使用进化算法来寻找最佳管道。但是什么是管道*?在机器学习项目中,你很少有理想的数据格式来创建一个性能模型。您可以执行多种转换,如输入,特征缩放和标准化或分类变量编码——其本身有多种实施方式,即一键编码或目标编码。然后你可以通过装袋、助推或堆叠模型来创造一个整体。最终的模型将使用上述部分或全部的组合。这叫做管道。TPOT 尝试了各种管道,让它们“随机变异”,就像活的有机体一样(或者病毒和染色体外 DNA,如果你想卖弄学问的话),直到它找到一个性能更好的管道。你可以在这里阅读完整的 TPOT 论文。*
TPOT 管道的一个例子——来源:文档
最后,让我们使用我们的集群来寻找数据集的最佳管道。下面的笔记本大部分摘自文档,有一些细微的改动。
当 TPOT 运行时,你可以在调度器的localhost:8787
查看仪表盘。如果您不在远程调度器中,您可以在本地机器的IP-of-scheduler:8787
处检查它。仪表板提供了对每一代进程的洞察、对工作人员和整个集群的基本系统监控、每个工作人员的日志和调用堆栈,以及一个非常,非常酷的图表。以下是 dask 仪表板运行时的外观:
最后,我想提一下,Dask 的主要贡献者成立了一家名为 coiled 的公司,为托管 Dask 集群和 python 扩展提供云和企业解决方案。他们目前处于测试阶段,并在云中提供多达 100 个免费 CPU 来演示他们的平台。
如何建立一个有气流的数据管道
开始在 Python 中使用 Airflow 时需要知道的一些基础知识
简介
Airflow 是一个允许调度和监控数据管道的工具。这个工具是用 Python 编写的,它是一个开源的工作流管理平台。
Airflow 可以用来编写机器学习管道、ETL 管道,或者一般来说用来调度作业。因此,感谢气流,我们可以自动化工作流程,避免许多无聊的手动任务。
在 Apache Airflow 中,工作流中的各种任务形成了一个图表。这些任务通过依赖关系链接在一起。连接一个任务和另一个任务的箭头有一个特定的方向,没有循环,因此在气流中我们有 DAGs,意思是有向无环图。
第一部分:如何创建 DAG 和操作符来执行任务?
当我们想要创建 DAG 时,我们必须提供名称、描述、开始日期和间隔,如下所示。
from airflow import DAGfirst_dag = DAG( ‘first’,
description = ‘text’,
start_date = datetime(2020, 7, 28),
schedule_interval = ‘@daily’)
操作符是 DAG 的构造块。它们定义了 DAG 将执行的实际工作。我们需要通过设置 task_id、python_callable 和 dag 来参数化操作符。
from airflow import DAGfrom airflow.operators.python_operator import PythonOperatordef my_func():
print('done')first_dag = DAG(...)task = PythonOperator(
task_id = 'first_task',
python_callable=my_func ,
dag=first_dag)
其他常见的运算符有:
- PostgresOperator- RedshiftToS3Operator- S3ToRedshiftOperator- BashOperator- SimpleHttpOperator- Sensor
计划是可选的,默认情况下,如果我们忽略计划间隔,我们的 DAG 将从开始日起每天运行一次。无论如何,在下面你可以找到设置你的时间间隔的所有选择。
@once →run a DAG only once time@hourly → run the DAG every hour@daily → run the DAG every day@weekly → run the DAG every week@monthly → run the DAG every month@yearly → run the DAG every year
第二部分:任务依赖和气流挂钩
在 Airflow 中,每个有向无环图都由节点(即任务)和边来表征,这些节点和边强调了任务之间的顺序和依赖性。
我们可以使用双箭头操作符“> >”来描述依赖关系。所以:
- a>b表示 a 在 b 之前
- 甲< <乙的意思是乙先于甲
另一种方法是使用设置 _ 下游和设置 _ 上游:
- a.set_downstream(b) 表示 a 在 b 之前
- a.set_upstream(b) 意思是 a 在 b 之后
为了与我们的数据存储和其他外部系统(如 Redshift、Postgres 或 MySQL)进行交互,我们可以配置**气流挂钩。**下面用举例说明一下它的样子。
from airflow import DAGfrom airflow.hooks.postgres_hook import PostgresHookform airflow.operators.python_operator import PythonOperatordef load():
#create a PostgresHook option using the 'example' connection
db_hook = PostgresHook('example')
df = db_hook.get_pandas_df('SELECT * FROM my_table')load_task = PyhtonOperator(task_id='load', python_callable=my_func_name, ...)
上面你可以看到我导入了一个 PostgresHook,我通过给它命名为‘example’来初始化它。
然后通过函数db _ hook . get _ pandas _ df(’ SELECT * FROM my _ table ')我请求给我一个 pandas 数据框。因此,Airflow 开始运行 SQL 语句,最后结果被加载到 pandas 数据框中并返回给 Airflow。
然而,气流还有其他的挂钩,比如:
- HttpHook- MySqlHook- SlackHook
第三部分:上下文和模板
气流提供了几个特定于运行时给定 DAG 和任务的执行的上下文变量。在处理之前访问或分割数据的过程中,上下文变量非常有用。你可以在这里找到一个变量列表,可以作为夸尔格包含在内。
下面,我们有一个函数叫做 my_func。函数中有*args 和kwargs(即关键字参数列表)。此外,您可以注意到,在任务**中,提供 _ 上下文被设置为 True。
from airflow import DAG
from airflow.operators.python_operator import PythonOperatordef my_func(*args, **kwargs):
logging_info(f"start{kwargs['ds']}")first_dag = DAG(...)
task = PythonOperator(
task_id = 'date',
python_callable = my_func,
provide_context = True,
dag=first_dag)
结论
现在,您已经具备了构建气流管道的基础。我认为理解这些概念的最好方法是建立你的气流环境并自己尝试。
我发出一份期刊简讯。如果您想加入,请通过此链接 注册。
除了我的简讯,我们还可以在我的电报群 数据科学初学者 中取得联系。
如何建立能让你找到工作的数据科学投资组合
职业,数据科学
如何制作一个强有力的关于你的作品集!
这些人日以继夜地努力工作,仍然在找工作,然后两手空空地着陆!这是寻找数据科学和机器学习领域职业的求职者最常见的问题之一。
如何获得数据科学工作的聘用?
我的作品集应该在招聘人员面前展示什么?
答案很简单:“你的作品集应该展示你做了什么!”是的,听起来就是这么简单。你的作品集可以展示很多东西,实际上你应该展示那些只与你的领域相关的东西。如果我们考虑数据科学,无论是机器学习还是深度学习,有一点是共同的,那就是关于你的技术能力和非技术能力之间的化学反应。
请记住,投资组合可以是任何东西,可以是你的简历或 LinkedIn 个人资料,也可以是你的 Kaggle 个人资料或你的 GitHub 个人资料,也可以是你正在参加的不同类型的比赛。任何能照亮你的东西!
技术能力
在这个领域,每个人都知道自己的技术能力,比如作为一名数据科学家,你需要知道什么是机器学习,什么是深度学习,你需要知道统计、各种算法,它们如何工作,以及它们背后的数学原理。你需要了解数据清理流程,以及与你在行业中必须做的工作相关的一切。你需要知道如何使用任何编程语言编程,不管是 Python、R、Julia、Java 还是 T11 等等。看你选了哪一个,学了哪一个。你需要对各种云架构有一个基本的了解,比如 AWS、GCP、IBM Cloud 等。以及如何在服务器上部署功能齐全的数据科学项目。
一般来说,您需要了解完整的数据科学生命周期及其在现实生活数据中的实施,并为数据科学应用程序开发端到端系统。
非技术能力
数据科学更多的是关于理解数据和交流你从研究和分析中所理解的东西。它是关于在世界面前贡献你的理解。总的来说,我们可以说,一个优秀的数据科学家应该善于交流结果,能够与不同类型的团队成员协作,并能够从数据中理解和推理。因此,您需要展示讲故事的艺术,这是数据科学概要文件的核心基础之一。
从数据中理解和推理更多内容、分析数据、从数据中提出更多问题并解决这些现实问题的能力是驱动数据科学行业的好奇心。
那么我们应该做些什么呢?
对于正在大学学习的学生或正在积极找工作的新生来说,最重要的是:
争取拿到一个 “实习”。
实习是一个人在完成核心领域的概念学习后应该寻找的最重要的事情之一。数据科学领域的实习将为你的投资组合增加更多价值,向招聘人员展示你在该行业有一些工作经验,并且对现实世界的问题有很好的了解。
现在你已经实习过了,所以你可以加上你完成的项目和解决的问题,所有这些你都可以在简历中自豪地提及。所以这是你应该做的第一件也是最重要的事情。
如果我们得不到实习机会呢?
假设你是一名大学生,正在努力争取实习机会,但通过某种方式,你最终一无所获。那该怎么办呢?
或者
假设你是一名在职专业人士,你一直在某公司的不同领域工作,现在你想转向数据科学职业,但你没有在现有公司获得关于数据科学的实习或任何项目。那么在这种情况下该怎么办呢?
打造自己的**“项目”。**
是的,这是真的。接受你在这个世界上看到的任何问题,如果你有机会解决它,你知道你可以带来改变。正是时候!接手一个项目,并为其构建完整的端到端解决方案。相信我,一个完全由你完成的个人项目会给你的作品集增加很大的价值,有时这相当于实习。
你可以从像 Kaggle 这样的网站上收集你感兴趣的数据集,那里有大量免费的数据集。然后你就可以开始你的项目了。建立一个端到端的系统来解决您的问题,并在任何云服务上部署您的项目,如 AWS、GCP 等。请记住,您需要确保您正在进行一个完整的端到端项目,而不仅仅是从数据收集到交流结果并最终在云上部署即用型系统的一部分。
接下来,参加数据科学竞赛
有各种网站定期举办数据科学竞赛,如 Kaggle 每个月都有一些竞赛在网站上直播。HackerRank 是另一个这样的好网站,它定期举办招聘竞赛和长期挑战,在那里你可以通过应用你的技能和努力提高你的模型的准确性或诸如此类的事情来解决问题。
Kaggle 排名排行榜
所以这样的网站仅限于提高机器学习模型的准确性,但你并不止步于此。从那里拿数据集,自己搭建一个完整的端到端系统。这样做,你会学到很多新东西,这对你在某个领域知识的全面增长非常有用,并能在面试中让你受益匪浅。现在,你需要考虑如何利用特定网站(如 Kaggle)的资源,并使用它来制作一个完全准备好的工作系统,可以添加到你的投资组合中。
注意:即使你没有任何现实行业的工作经验,一个项目也能创造奇迹!
一个强大的投资组合必须做的事情
你需要在 GitHub、LinkedIn、Kaggle 等公开个人资料上多下功夫。给招聘人员留下好印象,如果简历写得好,他们肯定会对你印象深刻。
- GitHub :让你的 GitHub 个人资料来讲述你吧!每当您创建一个项目时,在您的 GitHub 帐户上共享它,并用最新的项目文件更新存储库。保留您工作的适当文档,并定期更新您的 README.md 文件,它是您项目的发言人。是的,证明你的非技术能力通过记录项目和解释你如何在项目中实现每个管道的完整架构,并在自述文件中漂亮地解释它,这大大提升了你的个人资料。
- LinkedIn 是最大的职业招聘网站之一,它可以帮你找到潜在的雇主。不断更新你的 LinkedIn 个人资料,清楚地提及你所有的经历和项目。你可以尝试联系招聘经理,如果他们喜欢你的投资组合,他们可以为你安排面试,或者你可以联系在特定公司工作的人,了解公司的工作暴露和数据科学文化。
- 写博客:写至少一篇关于你的大项目实施的博客,交流它的见解、结果和工作,期望你的读者是一个门外汉,你希望他从头开始解释你项目的一切。数据科学是一个开放的社区,在这里分享你所知道的知识,并通过撰写文章的方式为社区做出贡献,可以为你的投资组合增加更多价值。这无疑会给招聘人员留下非常好的印象,因为你更愿意分享知识和研究成果。
这些东西肯定会帮助你建立一个更好更强大的投资组合。让自己与新技术保持同步,假以时日,你一定会成功的!
更多关于数据科学的文章,作者: Paras Varshney :
释放你内心的超能力!
medium.com](https://medium.com/@pv009/how-to-become-super-powerful-and-successful-cdf65722a765) [## “正态分布”的功效
理解钟形曲线背后的科学!
medium.com](https://medium.com/analytics-vidhya/the-powers-of-normal-distribution-4cbb06e4a955) [## Q-Q 图解释
探索 Q-Q 图的力量。
medium.com](https://medium.com/@pv009/q-q-plots-explained-5aa8495426c0)
还有更多在 Paras Varshney 的。
我希望你能从这篇文章中有所收获!
如果你喜欢它并且与你的朋友分享它,帮助社区变得更好更强大。在 Linkedin 上与我联系。
谢谢你!
如何建立数据科学作品集网站
展示您的作品——从零开始创建网站
你的代码在 GitHub 上,你的博客文章在 Medium 上,你的比赛结果在 Kaggle 上,你的职业简介在 LinkedIn 上。然而,在你的简历上添加四个甚至更多的链接,让潜在雇主不得不逐个查找,这是浪费时间和空间。一个月前,我决定从头开始创建一个网站——没有 WordPress 或 Squarespace 或任何其他模板——在一个地方展示我的项目和我的个人资料。我不确定从哪里或如何开始,特别是因为作为数据科学家,我们不经常使用 HTML、CSS、JavaScript 或 Flask。所以我想给提供一个指南,希望也能帮助你创建自己的数据科学组合网站。
从哪里开始
在你开始编码之前,你应该有一个大致的结构,并且对你的网站应该是什么样子有一个想法。考虑你的受众:潜在雇主可能有兴趣了解你和你的数据科学职业的哪些方面?我发现有用的一点是看看其他人的投资组合网站。显然,你想确保没有他们的允许你不会复制他们。但是看看他们如何展示他们的工作和他们自己可以给你一个想法从哪里开始。一些伟大的网站是由
- 大卫·文丘里
- 哈里森·詹斯马
- 布兰登·沃克
你也可以看看我的网站寻找灵感(编辑:我给网站增加了双语功能,所以现在除了德语还有英语。
包括什么
根据上面的研究,一个好的开始是在你的网站上包括以下页面/部分:
- 一个登陆页面,上面有一些关于你的简要信息和你网站其他部分的参考。
- 一个投资组合页面,提供你的项目的概述。给你的代码、博客文章和网站添加简短的描述和链接。
- 一个关于页面,在这里你可以谈论你的资历、教育背景、技能或者任何你想让你的观众了解你的事情。
- 例如,博客区/页面,包含你网站上的博客文章或者链接到你的媒体简介。
- 关于联系方式和您在线状态的部分。在你的 GitHub、LinkedIn、Kaggle、Twitter 或任何其他可能与你网站的受众相关的在线个人资料中添加链接。
你还记得其他章节或页面吗?太好了!包括他们。这只是一个起点,只有最少的信息。你也可以使用你的网站来托管你的实际项目,无论是机器学习模型还是 Plotly Dash 实现。
如何构建它
需要考虑的事项
你想从头开始。这是否意味着一个空白的 HTML 文件,空白的 CSS 文件和空白的 Python 文件?其实不需要从 0 开始。
- Bootstrap 是一个集成了 JavaScript 的 CSS 框架,让你的网站反应灵敏、美观,无需太多手工 CSS 工作。您可以使用这个 Bootstrap starter 模板,并向其中添加您自己的 HTML 代码。
- 使用Jinja——一种模板语言——它允许你动态地向你的 HTML 文件添加内容(而不是硬编码)并创建你的其他页面可以引用的模板(在下一个要点中有更多内容)。关于 Jinja 是什么以及我们为什么需要它,有一个很好的 5 分钟总结。
- 使用一个layout.html 文件,它在你的其他 HTML 页面中被引用。这将是您的父模板。在你的其他 HTML 文件(子模板)中,你可以引用 layout.html,比如你的导航条会显示在每一页上,但是你只需要实现一次。
- 看看你喜欢的网站的源代码(关于如何做这件事的指导,检查一下 Chrome 、 Firefox 和 Safari )。记住,没有网站创建者的许可,不要复制任何东西,但看看其他人是如何实现某些东西并从中获得灵感是没问题的。
- 使用一个微型 web 框架来帮你完成服务器通信的重担。我更喜欢 Flask,因为它易于实现,有丰富的文档和强大的社区,但是你也可以使用你选择的另一个 Python 框架。
请随意查看我的网站的代码,以了解如何实现上述要点。
起始文件
为了给您一个实际的起点,您可以创建以下文件,然后在此基础上进行构建:
-
layout.html→这包含了引导启动模板、导航栏和页面页脚。所有这些都摘自引导文档。
-
index.html→这是你的登陆页面,扩展了 layout.html 模板。
-
styles.css →在这里你可以添加额外的 css 样式来调整你正在使用的引导内容或者创建你自己的样式。
-
app.py →你需要用 pip 安装烧瓶,这个代码才能工作。这个文件将呈现你的 html 模板。
测试它
确保您的网站项目有一个本地文件夹。在里面,创建一个文件夹模板来包含 layout.html 和 index.html 的文件。为 styles.css 文件创建另一个文件夹 static 。app.py 文件需要直接在项目文件夹中。在你的 shell 中(我用的是 Git Bash),移动到网站项目文件夹,输入flask run
。这将输出一个 http 地址,您可以在浏览器中输入,它将显示您的基本网站。从那里,你可以添加内容,功能,调整设计和布局;它应该让你开始。基于上面的代码,它看起来应该是这样的:
上述代码片段的第一个实现。资料来源:朱莉娅·尼库尔斯基。
如何部署它
当您对您的网站满意时,您可以部署它并使其可在线访问。请遵循以下步骤:
- 选择一个平台来托管你的网站。我在所有的项目中使用 Heroku,因为它们可以从 GitHub repos 中方便地部署。你可以免费主持你的前 5 个项目。然而,需要考虑的是,30 分钟没有流量之后,他们会让你的网站进入睡眠状态。如果有人访问您的网站,它会在短暂的延迟后再次唤醒。为了避免这段睡眠期,你可以升级到 Heroku 的爱好计划,或者使用一种变通方法,定期 ping 你的网站来保持清醒。
- 创建一个
**requirements.txt**
文件。如果你已经为你的项目创建了一个虚拟环境,你可以运行$ pip freeze > requirements.txt
,或者你可以使用[pipreqs](https://pypi.org/project/pipreqs/)
来获得托管平台需要为你的网站正常运行安装的软件包列表。 - 创造出
**Procfile**
**。**这个文件应该只包含web: gunicorn app:app
。注意,您需要安装[gunicorn](https://docs.gunicorn.org/en/stable/install.html)
包,它也应该包含在您上面的requirements.txt
文件中。 - 创建一个 Heroku 账号 **并部署你的网站。**你需要在 GitHub repo 中有上面提到的所有文件。关于 Heroku 上部署过程的更多细节,查看他们的文档这里和这里。我也在这篇中帖中描述了这个过程(文章末尾的第 5 点)。
如何改善呢
一旦你创建了你的 MVP,考虑一下你可以添加什么功能来传达额外的信息或者使你的网站更加用户友好。
- 为什么不加一个 时间线 展示你的学习历程呢?
- 添加一个技能部分 显示你的专业领域。
- 创建一个内容管理系统,这样你就不必在 HTML 模板或 Python 文件中添加你的网站上显示的所有内容/文本。我在 Heroku 上创建了一个 PostgreSQL 数据库,这个数据库是由输入我的内容的 Excel 文件。
我希望这个指南对你有用。它应该可以帮助你开始建立自己的网站,这在一开始可能看起来有点吓人。我不是 web 开发人员,但我的重点是数据科学,所以我欢迎对上述指南的任何反馈!
你想在媒体上阅读更多高质量的故事吗?考虑注册一个支持我和其他媒体作者的会员。
[## 通过我的推荐链接加入 Medium-Julia Nikulski
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@julia.nikulski/membership)
如果您正在寻找一个新的项目创意来添加到您的投资组合中,请查看我的指南,了解如何开发新的独特的数据科学项目创意。
帮助您识别值得一试的新颖独特的数据项目的指南
towardsdatascience.com](/5-steps-to-develop-unique-data-science-project-ideas-6c2b3a0014b)
如何用 Python 构建数据科学 Web 应用程序
数据科学
第 1 部分:您的第一个 Web 应用程序,只有几行代码
在本文中,我将向您展示如何使用 streamlit Python 库,只用几行代码,快速构建一个简单的数据驱动的 web 应用程序。
作为一名数据科学家或机器学习工程师,能够部署我们的数据科学项目非常重要。使用 Django 或 Flask 等已建立框架的机器学习模型的传统部署可能是一项艰巨和/或耗时的任务。
这篇文章基于我在 YouTube 上制作的同一主题的视频(T21,如何用 Python 构建你的第一个数据科学 Web 应用,你可以边看边读这篇文章)。
我们正在构建的股票 web 应用程序概述
今天,我们将构建一个简单的 web 应用程序来显示股票价格和交易量。这将需要使用两个 Python 库,即streamlit
和yfinance
。从概念上讲,该应用程序将从雅虎检索历史市场数据。来自yfinance
图书馆的资金。该数据被保存到一个数据帧中,并且streamlit
将使用该数据作为输入参数,将其显示为一个折线图。
安装必备库
在本教程中,我们将使用两个需要安装的 Python 库。其中包括streamlit
和yfinance
。您可以通过如下的pip install
命令轻松安装streamlit
:
pip install streamlit
对yfinance
也进行如下操作:
pip install yfinance
web 应用程序的代码
让我们来看看我们今天正在构建的 web 应用程序的代码。您将会看到少于 20 行的代码(即如果不计算注释,那么它将减少到 14 行代码,其中 3 行是出于美观目的的空行)。
对代码的逐行解释
让我们花点时间对上面的代码做一些了解。
- 第 1 行和第 2 行 导入
yfinance
并赋予其别名yf
以及导入streamlit
并赋予其别名st
。 - 第 4–7 行
使用st.write()
功能打印出文本。这些打印出来的文本是以减价的形式写的。 - 第 9–16 行
使用yfinance
库从 Yahoo!金融。- 第 11 行— 将股票代码定义为
GOOGL
。 - 第 13 行 —使用
yf.Ticker()
函数创建tickerData
变量,顾名思义,该函数允许访问股票行情自动收录器数据。应该注意,tickerData 是一个 Ticker 对象,如果我们将 tickerData 作为一个命令运行,我们会得到下面的输出yfinance.Ticker object <GOOGL>
。 - 第 15 行 —创建
tickerDf
数据帧并定义日期范围(从 2010 年 5 月 31 日至 2020 年 5 月 31 日)和时间段(1 天)。
- 第 11 行— 将股票代码定义为
- 第 18 行和第 19 行
使用st.line_chart()
函数绘制折线图(使用第 15 行定义的tickerDf
数据框中的收盘价和成交量列)。
运行 web 应用程序
将代码保存到名为 myapp.py 的文件中后,启动命令提示符(或 Microsoft Windows 中的 Power Shell)并运行以下命令:
streamlit run myapp.py
接下来,我们应该会看到以下消息:
> streamlit run myapp.pyYou can now view your Streamlit app in your browser.Local URL: [http://localhost:8501](http://localhost:8501)
Network URL: http://10.0.0.11:8501
很快,一个互联网浏览器窗口将弹出,引导您进入创建的 web 应用程序,如下图所示的[http://localhost:8501](http://localhost:8501.)
。
股票价格 web 应用程序的屏幕截图。
恭喜你!您已经用 Python 创建了您的第一个 web 应用程序!
自定义 web 应用程序
好吧,所以你可能想加点料,定制 web 应用程序。
让我们花点时间对上面的代码做一些了解。
- 第 6 行 注意,我们加粗了*【收盘价】*,在短语前后使用了两个星号,如下:
**closing price**
。还要注意的是,我们通过在单词前后使用三个星号,使单词“volume”变成了粗体和斜体形式,如下所示:***volume***
。 - 第 18–20 行和第 22–25 行 这里我们在收盘价和成交量图之前添加了一个降价格式的标题。
更新后的 web 应用程序的屏幕截图。
瞧吧!
现在,我们有了一个更新的 web 应用程序,它会在你眼前自动更新。
订阅我的邮件列表,获取我在数据科学方面的最佳更新(偶尔还有免费赠品)!
关于我
我是泰国一所研究型大学的生物信息学副教授和数据挖掘和生物医学信息学负责人。在我下班后的时间里,我是一名 YouTuber(又名数据教授)制作关于数据科学的在线视频。在我做的所有教程视频中,我也在 GitHub 上分享 Jupyter 笔记本(数据教授 GitHub page )。
数据科学、机器学习、生物信息学、研究和教学是我的激情所在。数据教授 YouTube…
www.youtube.com](https://www.youtube.com/dataprofessor?sub_confirmation=1)
在社交网络上与我联系
YouTube: http://youtube.com/dataprofessor/
LinkedIn:https://www.linkedin.com/company/dataprofessor/
https://www.linkedin.com/company/dataprofessor/
【HTTP://facebook.com/dataprofessor/】
【GitHub:【HTTPS://github.com/dataprofessor/】
Instagram:【HTTPS://www.instagram.com/data
如何用 Python(企鹅分类器)构建数据科学 Web 应用
数据科学
第 3 部分:ML 支持的 Web 应用程序,代码 100 多行
T 这是第三部分和我将向您展示如何使用 Streamlit 库用 Python 构建一个机器学习驱动的数据科学 web 应用程序,代码只有 100 多行。
我们今天要构建的 web 应用程序是企鹅分类器。我们正在构建的这个企鹅分类器网络应用的演示可以在http://dp-penguins.herokuapp.com/获得。
之前,在本 Streamlit 教程系列的第 1 部分 中,我已经向您展示了如何用 Python 构建您的第一个数据科学 web 应用程序,它能够从 Yahoo!财务,然后显示一个简单的折线图。在 第二部分 中,我已经向你展示了如何使用 Iris 数据集构建一个机器学习 web 应用。
正如本 Streamlit 教程系列的前几篇文章中所解释的,模型部署是数据科学生命周期的基本和最终组成部分,有助于将数据驱动的洞察力的力量带给最终用户,无论是业务利益相关者、经理还是客户。
数据科学生命周期。由 Chanin Nantasenamat 绘制。
这篇文章基于我在数据教授 YouTube 频道 ( 如何用 Python 构建企鹅分类 Web 应用)上制作的同一主题的视频,你可以边看边看这篇文章。
企鹅分类网络应用概述
在本文中,我们将构建一个企鹅分类器 web 应用程序,作为 4 个定量变量和 2 个定性变量的函数,预测企鹅物种的分类标签是阿德利企鹅、下巴颏企鹅还是巴布亚企鹅。
艺术作品 @allison_horst
企鹅数据集
这个机器学习驱动的网络应用程序中使用的数据被称为 帕尔默企鹅数据集,它是由艾利森·霍斯特作为 R 包发布的。特别地,该数据来源于 Kristen Gorman 博士及其同事发表的题为 南极企鹅(Pygoscelis 属) 群落内的生态性二态性和环境可变性的工作。
数据集由 4 个定量变量组成:
- 票据长度(毫米)
- 票据深度(毫米)
- 脚蹼长度(毫米)
- 体重(克)
和 2 个定性变量:
- 性别(男性/女性)
- 岛屿(比斯科/梦幻/托格森)
让我们来看看企鹅数据集(下面显示的是一个截短的版本,只显示了 3 种企鹅中每一种的前 3 行条目):
*(Note: The full version of the* [*Penguins dataset is available on the Data Professor GitHub*](https://github.com/dataprofessor/data/blob/master/penguins_cleaned.csv)*)*
企鹅分类器 web 应用程序的组件
企鹅分类器 web app 由前端和后端组成:
前端 —这是我们加载 web app 时看到的。前端可进一步分解为侧面板和主面板。web 应用程序的截图如下所示。
侧面板位于左侧,标签标题为*“用户输入特性”*。在这里,用户可以上传包含输入特征(2 个定性变量和 4 个定量变量)的 CSV 文件。对于 4 个定量变量,用户可以通过调节滑动条手动输入这些输入特征的输入值。对于 2 个定性变量,用户可以通过下拉菜单选择输入值。
这些用户输入特征用作将在后端讨论的机器学习模型的输入。一旦做出预测,产生的类别标签(企鹅种类)连同预测概率值被发送回前端,以显示在主面板上。
后端 —用户输入的特征将被转换成数据帧,并发送给机器学习模型进行预测。在这里,我们将使用一个预先训练的模型,该模型之前被保存为一个名为penguins_clf.pkl
的 pickle 对象,该对象可以由 web 应用程序快速加载(无需在用户每次加载 web 应用程序时构建机器学习模型)。
企鹅分类器 web 应用程序的屏幕截图。
安装必备库
对于本教程,我们将使用 5 个 Python 库:streamlit
、pandas
、numpy
、scikit-learn
和pickle
。如果您的计算机中尚未安装前 4 个库,则必须安装前 4 个库,而最后一个库是内置库。
要安装这些库,您可以通过如下的pip install
命令轻松完成:
pip install streamlit
然后,重复上述命令,首先将streamlit
替换为其他库的名称,如pandas
,使其变成pip install pandas
,依此类推。
或者,您可以使用这个一行程序一次性安装它们:
pip install streamlit pandas numpy scikit-learn
web 应用程序的代码
现在,让我们看看 web 应用程序的内部。您将看到 web 应用程序由两个文件组成:penguins-model-building.py
和penguins-app.py
。
第一个文件(penguins-model-building.py
)用于构建机器学习模型,保存为 pickle 文件,penguins_clf.pkl
。
随后,第二个文件(penguins-app.py
)将应用经过训练的模型(penguins_clf.pkl
)通过使用来自 web 应用前端的侧边栏面板的输入参数来预测类别标签(企鹅的种类是阿德利企鹅、下巴颏企鹅还是巴布亚企鹅)。
对代码的逐行解释
企鹅-建模. py
让我们从第一个文件的解释开始,它本质上允许我们在运行 web 应用程序之前预先构建一个经过训练的机器学习模型。我们为什么要这么做?从长远来看,这是为了节省计算资源,因为我们最初只构建一次模型,然后应用它对 web 应用程序侧边栏面板上的用户输入参数进行不确定的预测(或至少直到我们重新训练模型)。
企鹅-建模. py
- 行 1
导入别名为pd
的pandas
库 - 第 2 行
从 CSV 文件中读取清理后的企鹅数据集,并将其赋给penguins
变量 - 第 4-19 行
对目标 Y 变量(species
)和 2 个 X 变量(sex
和island
)组成的 3 个定性变量进行顺序特征编码。
在执行序数特征编码之前。
执行顺序特征编码后。
- 第 21–23 行
将df
数据帧分隔成X
和Y
矩阵。 - 第 25–28 行
训练一个随机森林模型 - 第 30–32 行
将训练好的随机森林模型保存到一个名为penguins_clf.pkl
的酸洗文件中。
企鹅-app.py
第二个文件将服务于 web 应用程序,该应用程序将允许使用从 pickled 文件加载的机器学习模型进行预测。如上所述,web 应用程序接受来自两个来源的 inout 值:
- 滑动条中的特征值。
- 上传的 CSV 文件中的特征值。
企鹅-app.py
- 行 1–5
分别导入别名为st
、pd
和np
的streamlit
、pandas
和numpy
库。接下来,导入pickle
库,最后从sklearn.ensemble
导入RandomForestClassifier()
函数。 - 第 7–13 行
编写 web 应用程序标题和介绍文本。
侧边栏面板
- 第 15 行
侧边栏面板的页眉标题。 - 第 17–19 行
链接下载一个示例 CSV 文件。 - 第 21–41 行
采集特征值并放入数据帧。我们将使用条件语句 if 和 else 来确定用户是否上传了 CSV 文件(如果是,则读取 CSV 文件并将其转换为 dataframe ),或者通过滑动其值也将被转换为 dataframe 的滑动条来输入特征值。 - 第 43–47 行
将用户输入特征(来自 CSV 文件或滑动条)与整个企鹅数据集相结合。这样做的原因是为了确保所有变量包含最大数量的可能值。例如,如果用户输入包含 1 只企鹅的数据,那么序数特征编码将不起作用。原因是因为代码将只检测定性变量的 1 个可能值。为了使序数特征编码起作用,每个定性变量都需要有所有可能的值。
情况一
在第一个场景中,定性变量island
只有一个可能的值,即Biscoe
。
上述输入特征在编码后将产生以下序数特征。
情况 B
上述输入特征将产生以下序数特征。
- 第 49–56 行
以与上述模型构建阶段(penguins-model-building.py
)类似的方式执行序数特征编码。 - 第 58–65 行
显示用户输入特征的数据帧。条件语句将允许代码自动决定是显示 CSV 文件中的数据帧,还是显示滑动条中的数据帧。 - 第 67–68 行
从酸洗文件中加载预测模型,penguins_clf.pkl
。 - 第 70–72 行
应用加载的模型对 df 变量进行预测,该变量对应于来自 CSV 文件或滑动条的输入。 - 第 74–76 行
预测的企鹅种类的类标签显示在这里。 - 第 78–79 行
这里显示了 3 种企鹅中每一种的预测概率值。
运行 web 应用程序
现在我们已经完成了 web 应用程序的编码,让我们首先启动您的命令提示符(终端窗口)并键入以下命令来启动它:
streamlit run penguins-app.py
然后,命令提示符中应该会显示以下消息:
> streamlit run penguins-app.pyYou can now view your Streamlit app in your browser.Local URL: http://localhost:8501
Network URL: http://10.0.0.11:8501
企鹅分类器 web 应用程序的屏幕截图如下所示:
在 Heroku 上部署企鹅分类器 web 应用程序。
部署和展示 web 应用程序
干得好!您现在已经创建了一个基于机器学习的 web 应用程序。让我们将 web 应用程序部署到互联网上,以便您可以与朋友和家人分享。本 Streamlit 教程系列的下一部分将深入介绍如何在 Heroku 上部署 web 应用程序。与此同时,请观看以下视频:
与此同时,您可以将它纳入您的数据科学投资组合。
订阅我的邮件列表,获取我在数据科学方面的最佳更新(偶尔还有免费内容)!
关于我
我是泰国一所研究型大学的生物信息学副教授和数据挖掘和生物医学信息学负责人。在我下班后的时间里,我是一名 YouTuber(又名数据教授)制作关于数据科学的在线视频。在我做的所有教程视频里,我也分享 GitHub 上的 Jupyter 笔记本(数据教授 GitHub page )。
数据科学、机器学习、生物信息学、研究和教学是我的激情所在。数据教授 YouTube…
www.youtube.com](https://www.youtube.com/dataprofessor?sub_confirmation=1)
在社交网络上与我联系
YouTube: http://youtube.com/dataprofessor/
LinkedIn:https://www.linkedin.com/company/dataprofessor/
https://www.linkedin.com/company/dataprofessor/
【HTTP://facebook.com/dataprofessor/】
【GitHub:【HTTPS://github.com/dataprofessor/】
Instagram:【HTTPS://www.instagram.com/data
如何从头开始为图像分类器构建数据集(与汽车相关)
设计一个过程来收集网络上的数据,并使其可用于图像分类项目(使用 Beautifulsoup,Selenium)
乔纳森·加莱戈斯在 Unsplash 上拍摄的照片
在这篇文章中,我将介绍我几周前构建的从网站 Turo 收集数据(文本和图片)的管道,以及清理收集的数据以在图像分类器项目中使用它的过程。
免责声明:这些数据是供我使用的(我不拥有它),所以我不会分享它。
项目的概念
几周前,我开始思考在深度学习中更详细地潜水,我想围绕图像分类启动一个项目。
我在这个主题中阅读的大多数文章都使用了与 mnist 数据集(手写数字)、 deepfashion (贴有标签的衣服集合)或狗品种分类器相同的数据集。
这些数据集是合适的,但此时此刻我想研究一些不同的东西:
- 我同时发现了 Turo platform 这是一个人们可以从北美其他人那里租车的平台(它似乎运行得很好)。
- 我开始从游乐场游戏在 PC 上玩《极限纵横 4》。
几周前,我发现了两个相同主题的数据集
但是我想在抓取方面增加我的游戏,所以我决定建立我的 Turo 网站的抓取器。
在一份 Turo 的报价中,我才意识到有标注了车型的图片。
Turo 网站
因此,为什么不使用该网站作为图像分类数据集的来源来构建汽车检测系统呢?
为了执行从网站中提取数据,我不能使用与我在 Crossfit open 上的文章中的美汤相同的方法,因为:
- URL 不是很容易填充,所以我需要自动完成我的 Turo 研究
- 要让所有广告都显示在结果页面上,需要进行一些滚动操作
我仍然可以使用 Beautiful Soup 从源页面获取数据,但是我需要将这个包与另一个名为 Selenium 的包关联起来,以自动化对 Turo 的研究。
包装的展示
在这一部分,我将简单介绍一下我一直在 Turo 上爬行的库。
美味的汤
美汤是一个从 HTML 和 XML 文件中提取数据的包*。它与您喜欢的解析器一起工作,提供导航、搜索和修改解析树的惯用方式。它通常为程序员节省数小时或数天的工作。*
https://info python . files . WordPress . com/2007/03/beautiful soup . jpg
有了这个包之后,收集网页在线的源码,你就可以分段所有的 HTML 标签,并在里面研究收集你需要的信息。在我看来,这个包是开始使用 Python 进行 web 抓取的一个很好的开端,在这个主题上有很多有用的资源。
硒
这个包可以看作是一个 web 浏览器自动化包。
https://huddle . eurostarsoftware testing . com/WP-content/uploads/2017/02/selenium . png
这个包允许 Python 脚本打开像 Firefox 这样的网络浏览器,在网页上填充字段,在网页上滚动,像人类一样点击按钮。
让我们深入了解数据管道。
数据管道的介绍
概观
在数据收集方面,我决定将我的数据收集集中在北美最重要的城市,所以我选择了:
- 美国各州的中心城镇,至少有一百万人口
- 加拿大人口最多的 15 个城市
有一张我正在搜集数据的城市面板地图。
谷歌地图
它代表了 60 个城市(蓝色的美国和红色的加拿大),就像我有多种类型的环境(山,海)和不同的天气可以诱导各种类型的车辆。
这个想法是每 6 个小时收集一次从城市列表中随机挑选的 5 个城市的新报价。接收数据的存储是这样进行的:
我用了大约两周的时间运行这个管道,下载了大约 164000 张图片。
https://media.giphy.com/media/3NtY188QaxDdC/giphy.gif
现在让我们更详细地看看用 Selenium 和 Beautiful Soup 进行数据收集的脚本。
收集报价
首先,为了收集这些数据,我需要有一种方法来给出一个城市,并获得当前可用的优惠。
有一个代码可以收集蒙特利尔市的报价。
我们可以看到:
- Selenium 的用法是通过一个驱动程序的声明,该驱动程序可以控制 web 浏览器在网站上进行导航
- 使用对象驱动程序,我可以设置我的脚本来填充由 id 定义的特定字段(在本例中为“js-searchformexpandlocationinput ”),并将键发送到该特定输入(在本例中为城市字段中的位置)
turo 首页检查
- Selenium 的另一部分是与页面上的按钮的直接交互(需要找到页面上的按钮并激活它)。
对于页面上的滚动,这有点棘手;我用迈克尔·J·桑德斯的方法在“无限页”上滚动。
在每一次滚动之间,我都使用 Beautiful Soup 来收集页面上的所有报价。
有一个脚本的动画。
之后,我只是对以前从未见过的报价(不在我的 dynamodb 表中)进行过滤,并使用一个新的流程从一个特定的报价中收集数据。
收集图片
有一个为要约收集数据的脚本。
这个脚本的棘手部分是收集报价上图片的 URL。下面的屏幕截图说明了图片存储在一个转盘中。
我使用同样的技巧,然后在首页上使用验证按钮,这样,我可以很容易地收集所有图片的 URL,并通过 GET 请求,将它们下载到我的机器上。有一个先前脚本的动画在运行。
如果你想运行脚本,我邀请你用 Github 库(在一台 Linux 机器上)上的配置设置一个 python 环境。
现在让我们看一下数据集的数据准备。
从 ze(原始)数据集到图像分类器的 hero 数据集
用我的刮刀,我在 Turo 网站上收集了很多(164000 左右)与他们的汽车报价相关的图片。这是一个很好的开始,但所有这些图片都是不可用的,例如,汽车的内部。
Turo 广告图片
有很多这样的图片,所以我需要对这个原始数据集做一些清理。
清洗管道的描述
该管道背后的流程是:
- 检测原始数据集图像上的所有对象
- 根据图片中检测到的对象应用一些规则来选择正确的图像
- 裁剪图像上的车辆,并将其存储在新文件中
有一个过程的简要说明
这个管道中最棘手的部分是检测引擎;对于管道的这一部分,我决定我可以使用一个预先制作的模型。可以在线找到大量的模型来执行检测图像上的对象的任务。
看起来最有效的实现是由克里斯·福塔什在 Pytorch 上实现的。
对于过滤规则,这很简单;一幅好的汽车图片可以定义为:
- 图像上只有一辆车(汽车或卡车)
- 车辆检测的置信指数应高于 90%
过滤规则后,碰巧只有 57000 张图片可用。
让我们看看这些图片的标签。
最后一步:调整大小和标签
完成数据集的最后一步是调整图片的大小,并为分类添加标签。
调整大小
从所有这些被选中的照片中,有两件事是值得注意的
- 它们有不同的尺寸(就高度和长度而言)
- 它们是彩色的(因此有 3 个原色通道)
下图显示了图片的高度和长度。
这些图片有适当的分辨率,但我需要使它们一致,以便每个管道都可以用于分类。我构建了下面这段代码来调整图片的大小(这个函数可以将图片变成黑白的)。
我根据高度和长度的像素尝试了数据集的多种大小配置。
现在让我们看看标签。
贴标签于
该数据集有两个明显的标签:
- 有 51 种可能标签的制造商
- 有 526 个可能标签的模型
下图显示了每个制造商的型号数量。
我们可以看到,有很多厂商和型号,有这么多标签(我觉得)是一个很难的开始。我决定建立我的“标签机制”
我建立了两种标签:
- 一个用于二元分类器
- 一个用于多类分类器
对于二元分类器,我选择一个特定的制造商和一个特定的型号。对于厂商,我决定选择特斯拉;第一个原因是它在网上很流行,第二个原因是特斯拉的图片数量与可用车型数量之间的比例不同寻常,如下图所示。
对于车型,我决定选择福特野马,是因为我喜欢福特野马,不是别的。但老实说,这是数据集中最受欢迎的模型之一,正如我们在下图中看到的 10 大最受欢迎的模型。
让我们谈谈多类分类器;在这种情况下,我使用一种简单的方法来标记。这个想法就是取前 X 个最受欢迎的厂商/型号,如果图片的厂商/型号不在前 X,那么他分配的标签就是 other。我为以下产品创建标签:
- 十大制造商/型号
- 前 25 名制造商/型号
- 前 50 名制造商/型号
- 前 100/200/400 型号
现在有很多不同的图片标签。尽管如此,对于我在图像分类器上的第一个工作,我将把我的测试集中在二进制标签和前 10 名制造商/型号上。
为了完成这篇文章,我只想谈一些事情,它是关于数据集的平衡。对于我选择的标签,我可以告诉你,要预测的类根本不是平衡的。下图显示了数据集的不平衡。
当我使用这些标签进行图像分类时,我将测试影响以平衡训练的类别。
请继续关注,不要犹豫,请给我们一些反馈。
如何用 PyTorch 构建 DCGAN
GAN 入门教程
图片来源: Pixabay
在本教程中,我们将在 PyTorch 中构建一个简单的 DCGAN ,并训练它生成手写数字。作为本教程的一部分,我们将讨论 PyTorch 数据加载器,以及如何使用它将真实图像数据输入 PyTorch 神经网络进行训练。PyTorch 是本教程的重点,所以我假设您熟悉 GANs 的工作方式。
要求
- Python 3.7 以上版本。再低的话,你就要重构 f 弦了。
- PyTorch 1.5 不确定怎么安装?这可能会有所帮助。
- Matplotlib 3.1 或更高版本
- 大约 22 分钟。
这不是必需的,但我建议先阅读我的香草甘教程;它解释了一些本教程认为理所当然的事情。我还建议你在配有 CUDA GPU 的电脑上完成本教程,或者准备一本厚厚的数独书。
手头的任务
创建一个函数 G: Z → X 其中 Z~N₁ ₆ (0,1)和 X~MNIST。
也就是说,训练一个 GAN,它采用 16 维随机噪声并产生看起来像来自 MNIST 数据集的真实样本的图像。
来自 MNIST 数据集的数字样本(来源:约瑟夫·斯特潘
但是在我们开始之前…
…让我们做一点家务。如果您还没有,请安装所需版本的 Python 和上述库。然后,创建您的项目目录。我把我的叫做DCGAN
。在该目录中,创建一个名为data
的目录。然后,导航到这个 GitHub repo 并下载mnist_png.tar.gz
。这个压缩文件包含 70000 个独立的 png 文件形式的 MNIST 数据集。当然,我们可以使用 PyTorch 的内置 MNIST 数据集,但这样你就不会知道如何实际加载图像数据进行训练。解压文件并将mnist_png
目录放到你的data
目录中。创建一个名为dcgan_mnist.py
的文件,并将其放在您的 DCGAN 目录中。您的项目目录应该如下所示:
我们的项目目录,包括图像文件和 Python 脚本。0/、1/等中的数千个图像文件。未示出。
最后,将以下内容添加到您的dcgan_mnist.py
脚本中:
import osimport torch
from torch import nn
from torch import optim
import torchvision as tv
from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader
好了,现在我们准备开始了。
发电机
将以下内容添加到您的dcgan_mnist.py
脚本中:
生成器继承了nn.Module
,它是 PyTorch 神经网络的基类。生成器有三种方法:
发电机。init
构造函数,存储实例变量并调用_init_layers
。这里不多说了。
发电机。_init_modules
这个方法实例化 PyTorch 模块(或者其他框架中称为“层”)。其中包括:
- 线性(“全连通”)模块,用于将潜在空间映射到 7×7×256 = 12544 维空间。正如我们将在
forward
方法中看到的,这个 12544 长度的张量被整形为(256,7,7)“图像”张量(通道 × 高度×宽度)。在 PyTorch 中,与 TensorFlow 不同,通道出现在空间维度之前。 - 一维批处理规范化模块(如果指定)。
- 泄漏的 ReLU 模块。
- 二维卷积层。
- 两个 2 维转置卷积层;这些用于放大图像。请注意,一个卷积层的输出通道是下一个卷积层的输入通道。
- 两个二维批处理规范化层(如果指定)。
- 一个 Tanh 模块作为输出激活。我们将重新调整我们的图像到范围[-1,1],所以我们的发生器输出激活应该反映这一点。
这些可以在__init__
方法中实例化,但是我喜欢将模块实例化与构造函数分开。对于这么简单的模型来说,这是微不足道的,但是随着模型变得越来越复杂,这有助于保持代码的简单。
发电机。forward
这是我们的生成器用来从随机噪声中生成样本的方法。输入张量传递给第一个模块,其输出传递给下一个模块,的输出传递给下一个模块,依此类推。这相当简单,但我想提醒您注意两个有趣的特性:
- 注意线
intermediate = intermediate.view((-1, 256, 7, 7))
。与 Keras 不同,PyTorch 不使用显式的“整形”模块;相反,我们使用 PyTorch 操作“视图”手动重塑张量。其他简单的 PyTorch 操作也可以在向前传递的过程中应用,比如将一个张量乘以 2,PyTorch 不会眨一下眼睛。 - 注意在
forward
方法中有多少if
语句。PyTorch 使用运行定义策略,这意味着计算图是在向前传递的过程中动态构建的。这使得 PyTorch 极其灵活;没有什么可以阻止你向前传球添加循环,或者随机选择几个模块中的一个来使用。
鉴别器
将以下内容添加到您的dcgan_mnist.py
脚本中:
我不会对这个做太多的描述,因为它和发生器非常相似,但方向相反。通读一遍,确保你明白它在做什么。
DCGAN
将以下内容添加到您的dcgan_mnist.py
脚本中:
DCGAN。init
让我们一行一行地检查构造函数:
self.generator = Generator(latent_dim).to(device)
self.discriminator = Discriminator().to(device)
构造函数的前两行(非 docstring)实例化生成器和鉴别器,将它们移动到指定的设备,并将它们存储为实例变量。该设备通常是“cpu”,或者“cuda”,如果你想使用 gpu。
self.noise_fn = noise_fn
接下来,我们将noise_fn
存储为一个实例变量;noise_fn
是一个以整数num
作为输入,以 PyTorch 张量的形式返回num
潜在向量作为 shape (num,latent_dim)输出的函数。这个 PyTorch 张量必须在指定的设备上。
self.dataloader = dataloader
我们将一个 torch.utils.data.DataLoader 对象 dataloader 存储为实例变量;稍后将详细介绍。
self.batch_size = batch_size
self.device = device
将批次大小和设备存储为实例变量。简单。
self.criterion = nn.BCELoss()
self.optim_d = optim.Adam(self.discriminator.parameters(), lr=lr_d, betas=(0.5, 0.999))
self.optim_g = optim.Adam(self.generator.parameters(), lr=lr_g, betas=(0.5, 0.999))
将损失函数设置为二进制交叉熵,并为生成器和鉴别器实例化 Adam 优化器。PyTorch 优化器需要知道他们在优化什么。对于鉴别器,这意味着鉴别器网络内的所有可训练参数。因为我们的 Discriminator 类继承自 nn。模块中,它有parameters()
方法,该方法返回所有实例变量中的所有可训练参数,这些变量也是 PyTorch 模块。发电机也是如此。
self.target_ones = torch.ones((batch_size, 1), device=device)
self.target_zeros = torch.zeros((batch_size, 1), device=device)
训练目标,设置到指定的设备。记住,鉴别器试图将真实样本分类为 1,将生成的样本分类为 0,而生成器试图让鉴别器将生成的样本错误分类为 1。我们在这里定义并存储它们,这样我们就不必在每个训练步骤中重新创建它们。
DCGAN.generate_samples
生成样本的辅助方法。注意,使用了no_grad
上下文管理器,它告诉 PyTorch 不要跟踪梯度,因为这种方法不用于训练网络。还要注意,不管指定的设备是什么,返回的张量都被设置为 cpu,这是进一步使用所必需的,比如显示样本或将样本保存到磁盘。
DCGAN.train_step_generator
该方法执行生成器的一个训练步骤,并以浮点形式返回损失。让我们一步一步来:
self.generator.zero_grad()
清除发生器的渐变。这是必要的,因为 PyTorch 自动跟踪梯度和计算网络。我们不希望一个训练步骤影响下一个。
latent_vec = self.noise_fn(self.batch_size)
generated = self.generator(latent_vec)
classifications = self.discriminator(generated)
loss = self.criterion(classifications, self.target_ones)
获得一批潜在向量,用它们生成样本,区分每个样本的真实程度,然后使用二进制交叉熵准则计算损失。请注意,通过将这些网络链接在一起,我们创建了一个单一的计算图,从潜在向量开始,包括发生器和鉴别器网络,并在损耗处结束。
loss.backward()
self.optim_g.step()
PyTorch 的主要优点之一是它自动跟踪计算图形及其梯度。通过对损失调用backward
方法,PyTorch 应用反向传播并计算损失相对于计算图中每个参数的梯度。然后通过调用生成器的优化器的step
方法,生成器的参数(只有和生成器的参数)在梯度的负方向上被轻微推动。
return loss.item()
最后,我们归还损失。使用item
方法很重要,这样我们将返回一个浮点数而不是 PyTorch 张量。如果我们返回张量,Python 垃圾收集器将无法清理底层的计算图形,我们将很快耗尽内存。
DCGAN.train_step_discriminator
这种方法与train_step_generator
非常相似,但是有两个显著的不同。首先:
with torch.no_grad():
fake_samples = self.generator(latent_vec)
上下文管理器no_grad
在这里用来告诉 PyTorch 不要担心跟踪渐变。这是不必要的,但减少了不必要的计算。第二:
loss = (loss_real + loss_fake) / 2
这条线真的很酷。loss_real
是鉴别器对真实样本的损耗(并附上其计算图),而loss_fake
是对假样本的损耗(及图)。PyTorch 能够使用+
操作符将这些组合成一个计算图。然后,我们将反向传播和参数更新应用于该组合计算图。如果你不认为这非常简单,尝试在另一个框架中重写。
DCGAN.train_epoch
该函数为一个时期训练发生器和鉴别器,这是对整个数据集的一次遍历。在短暂的迂回之后,我们将回到这个问题上。
主要的
将以下代码添加到您的脚本中:
该功能构建、训练和展示 GAN。
import matplotlib.pyplot as plt
from time import time
batch_size = 32
epochs = 100
latent_dim = 16
导入pyplot
(用于可视化生成的数字)和time
(用于训练计时)。将训练批次大小设置为 32,将时期数设置为 100,将潜在维度设置为 16。
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
该行检查 cuda 设备是否可用。如果是,device
被指定为该设备;否则,device
被分配 cpu。
transform = tv.transforms.Compose([
tv.transforms.Grayscale(num_output_channels=1),
tv.transforms.ToTensor(),
tv.transforms.Normalize((0.5,), (0.5,))
])
数据加载器使用这种复合转换来预处理图像。我们之前下载的 MNIST 数据集是。png 文件;当 PyTorch 从磁盘加载它们时,它们必须经过处理,以便我们的神经网络可以正确使用它们。这些转换依次为:
Grayscale(num_output_channels=1)
:将图像转换成灰度。加载时,MNIST 数字为三通道 RGB 格式。Greyscale
把这三个减为一个。ToTensor()
:将图像转换为 PyTorch 张量,尺寸为 channels × height × width。这也会重新调整像素值,从 0 到 255 之间的整数到 0.0 到 1.0 之间的浮点数。Normalize((0.5,), (0.5,))
:从范围[0.0,1.0]到[-1.0,1.0]缩放和平移像素值。第一个参数为μ,第二个参数为σ,应用于每个像素的函数为:
μ和σ是一元组的原因是这种变换是针对每个通道应用的。到 RGB 图像的等效变换将是Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
dataset = ImageFolder(
root=os.path.join("data", "mnist_png", "training"),
transform=transform
)
在这里,我们通过指定它的根和要应用的转换来创建数据集。这用于创建数据加载器:
dataloader = DataLoader(dataset,
batch_size=batch_size,
shuffle=True,
num_workers=2
)
DataLoader 是一个对象,它从数据集中加载数据。在这里,我们指定我们的批处理大小,告诉数据加载器在不同的时期之间混洗数据集,并使用两个工作进程的多处理(如果您使用的是 Windows,这会导致问题,请将num_workers
设置为 0)。您可以遍历这个数据加载器,每次迭代都会返回一个元组,其中包含:
- 形状为(32,1,28,28)的 PyTorch 张量,对应于一批(32 个样本)灰度(1 通道)MNIST 图像(28×28 像素)。
- 数字 0 到 9 的形状(32)py torch 张量,对应于该图像的标签(数字)。这些类标签取自目录结构,因为所有的 0 都在目录
0
中,所有的 1 都在1
中,等等。
noise_fn = lambda x: torch.rand((x, latent_dim), device=device)
产生随机正态分布噪声的函数。
gan = DCGAN(latent_dim, noise_fn, dataloader, device=device)
start = time()
for i in range(10):
print(f"Epoch {i+1}; Elapsed time = {int(time() - start)}s")
gan.train_epoch()
建立和训练 GAN。
DCGAN.train_epoch,再来一遍:
既然我们已经讨论了什么是数据加载器,让我们再来看看这个。该方法非常简单明了,尽管有些冗长,但我想重点介绍两行代码:
for batch, (real_samples, _) in enumerate(self.dataloader):
real_samples = real_samples.to(self.device)
这里,我们遍历数据加载器。我们将数据加载器包装在一个枚举器中,这样我们就可以跟踪批号,但是正如您所看到的,数据加载器确实像承诺的那样返回了一个元组。我们将一批图像张量分配给real_samples
,并忽略标签,因为我们不需要它们。然后,在循环中,我们将real_samples
移动到指定的设备。模型的输入和模型本身在同一个设备上是很重要的;如果你忘记这样做,不要担心,PyTorch 一定会让你知道的!此外,不要担心数据加载器“耗尽”。一旦我们遍历了整个数据集,循环将会结束,但是如果我们再次尝试遍历它,它将会从头开始(首先洗牌,因为我们在制作数据加载器时指定了这一点)。
让我们试着运行它?
如果复制和粘贴正确,运行脚本应该会显示几分钟的训练统计数据,然后是一些生成的数字。希望它看起来像这样:
如果它们看起来很糟糕,你的损失暴增,试着再跑一次(甘的不稳定性是出了名的)。如果它仍然不工作,请在下面留下评论,我们看看是否能调试它。
只是为了好玩,我修改了脚本,看看在每 10 个训练步骤之后,生成器能够做什么。这是结果。
我觉得只走 1000 步就已经很不错了。这是那些训练步骤的损失,分成 10 步“时期”。
结束语
- 本教程中描述的 DCGAN 显然非常简单,但应该足以让您开始在 PyTorch 中实现更复杂的 GAN。
- 在我制作一个教程之前,你能修改这个脚本来制作一个条件句吗?
- 完整的脚本可在这里获得。
- 所有未引用的图片都是我自己的。请随意使用它们,但请引用❤的这篇文章
[## ConorLazarou/py torch-生成模型
产生 MNIST 数字的简单 DCGAN 实现。
github.com](https://github.com/ConorLazarou/pytorch-generative-models/blob/master/GAN/DCGAN/dcgan_mnist.py)
如何用 10 行构建深度学习模型
快速沉浸在深度学习中的指南
Alex Kotliarskyi 在 Unsplash 上的照片
本文将通过一个案例研究向读者介绍神经网络的基础知识,该案例研究仅使用 10 行 Python 代码创建并训练了一个神经网络,该网络通过 3 个基本步骤识别手写数字:
1-加载并预处理数据
2-定义模型
3-训练模型
为此,我们将使用目前深度学习社区中最流行的库 TensorFlow Keras API 。让我们去吧!
手写数字
作为一个案例研究,我们将创建一个允许我们识别手写数字的模型,例如下列数字:
目标是创建一个数学模型,给定一幅图像,该模型识别它所代表的数字。例如,如果我们向模型输入第一张图片,我们会期望它回答这是一张 5。下一个是 0,下一个是 4,以此类推。
分类问题
实际上,我们正在处理一个分类问题,给定一幅图像,模型将其分类在 0 到 9 之间。但有时,甚至我们会发现自己有某些疑问,例如,第一个图像代表 5 还是 3?
为此,我们将创建的神经网络返回一个具有 10 个位置的向量,指示 10 个可能数字中每一个的可能性:
只有 10 行代码
是的,只需 10 行 python 代码,您就可以创建并训练一个对手写数字进行分类的神经网络模型:
**1:** import tensorflow as tf
**2:** from tensorflow.keras.utils import to_categorical**3:**(x_train, y_train), _ = tf.keras.datasets.mnist.load_data()**4:** x_train = x_train.reshape(60000, 784).astype('float32')/255
**5:** y_train = to_categorical(y_train, num_classes=10)**6:** model = tf.keras.Sequential()
**7:** model.add(tf.keras.layers.Dense(10, activation='sigmoid',
input_shape=(784,)))
**8:** model.add(tf.keras.layers.Dense(10, activation='softmax'))**9:** model.compile(loss="categorical_crossentropy", optimizer="sgd",
metrics = ['accuracy'])**10:** model.fit(x_train, y_train, epochs=10, verbose=0)
我们使用了 TensorFlow **的 API Keras。**它是推荐给初学者的库,因为它的学习曲线与其他库相比非常平滑,并且目前它是实现神经网络的流行中间件之一。Keras 由来自谷歌的工程师Fran ois Chollet开发和维护,目前收录在 Tensorflow 库中。
环境设置
这是谷歌的一个研究项目,旨在帮助传播机器学习教育和研究。这是一个 Jupyter 笔记本环境,不需要任何配置,完全在云中运行,允许使用不同的深度学习库,如 TensorFlow 和 PyTorch 。Colab 区别于其他免费云服务的最重要的特点是;Colab 提供 GPU(或 TPU)并且完全免费。关于这项服务的详细信息可以在 faq 页面找到。
默认情况下,Colab 笔记本运行在 CPU 上。你可以切换你的笔记本电脑运行与 GPU(或 TPU)。为了访问一个 GPU,我们需要选择标签运行时间,然后选择“更改运行时间类型”,如下图所示:
当弹出窗口出现时,选择 GPU。确保“硬件加速器”设置为 GPU(默认为 CPU)。
然后,确保您已连接到运行时(在菜单功能区中“已连接”旁边有一个绿色复选标记):
现在你可以运行这篇文章中的代码了。我建议将这篇文章的代码复制粘贴到一个 colab 笔记本上,以便在你阅读这篇文章的同时看到执行过程。
准备好了吗?我们开始吧!
1.加载和预处理数据
首先,我们需要导入一些 Python 库,以便在 TensorFlow 中对我们的神经网络进行编程:
**import tensorflow as tf
from tensorflow.keras.utils import to_categorical**
下一步是加载将用于训练我们的神经网络的数据。我们将使用 MNIST 数据集,该数据集可以从MNIST 数据库页面下载。该数据集包含 60,000 个手工制作的数字图像来训练模型,对于首次进入模式识别技术来说是理想的,无需花费大量时间预处理和格式化数据,这在数据分析中是非常重要和昂贵的步骤,并且在处理图像时具有特殊的复杂性。**
在 TensorFlow 中,这可以通过下面这行代码来实现(第 3 行):
**(x_train, y_train), _ = tf.keras.datasets.mnist.load_data()**
****可选步骤:如果需要,您可以使用以下代码验证加载的数据:
**import numpy as np
import matplotlib.pyplot as pltfig = plt.figure(figsize=(25, 4))
for idx in np.arange(20):
ax = fig.add_subplot(2, 20/2, idx+1, xticks=[], yticks=[])
ax.imshow(x_train[idx], cmap=plt.cm.binary)
ax.set_title(str(y_train[idx]))**
这个黑白图像(包含灰度级的图像)的数据集已经归一化为 20×20 像素,同时保留了它们的纵横比。随后,将图像居中,计算这些图像的质心并移动图像,以便将该点定位在 28×28 视场的中心。
这些 28×28 像素的 MNIST 图像被表示为一个数字数组,其值的范围从类型uint8
的[0,255]开始。但是通常将神经网络的输入值调整到一定的范围。在这篇文章的例子中,输入值应该在区间[0,1]内换算成类型为float32
的值。
另一方面,为了便于将数据输入到我们的神经网络中,我们必须将输入(图像)从二维(2D)转换为一维(1D)向量。也就是说,28×28 个数字的矩阵可以由 784 个数字(逐行连接)的向量(数组)表示,这种格式接受密集连接的神经网络作为输入,就像我们将在本文中看到的那样。
我们可以用下面的代码行(第 4 行)实现这些转换:
**x_train = x_train.reshape(60000, 784).astype('float32')/255**
此外,数据集对每张图像都有一个标签,表明它代表什么数字(在y_train)
下载)。在我们的例子中,0 到 9 之间的数字表示图像代表哪个数字,也就是说,它与哪个类相关联。
如前所述,我们需要用 10 个位置的向量来表示每个标签,其中对应于表示图像的数字的位置包含 1,其余的包含 0。这个将标签转换成与不同标签的数量一样多的零的向量,并将 1 放入对应于标签的索引中的过程被称为一键编码。例如,数字 7 将被编码为:
我们可以用下面的代码行(第 5 行)实现这种转换:
**y_train = to_categorical(y_train, num_classes=10)**
2.定义模型
为了用 Keras 的 API 定义模型,我们只需要这些代码行(第 6–8 行):
**model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(10,activation='sigmoid',
input_shape=(784,)))
model.add(tf.keras.layers.Dense(10,activation='softmax'))**
然而,在解释这些代码行之前,让我先介绍一些基本的神经网络概念。
普通的人工神经元
为了展示基本神经元是怎样的,让我们假设一个简单的例子,其中我们在二维平面中有一组点,并且每个点已经被标记为“正方形”或“圆形”:
给定一个新的点“ X ”,我们想知道它对应什么标号:
一种常见的方法是画一条线将两个组分开,并使用这条线作为分类器:
在这种情况下,输入数据将由( x1,x2 )形式的向量表示,这些向量表示它们在这个二维空间中的坐标,我们的函数将返回‘0’或‘1’(在线的上方或下方),以知道它应该被分类为“正方形”还是“圆形”。它可以定义为:
更一般地说,我们可以将这条线表示为:
为了对输入元素 X(在我们的例子中是二维的)进行分类,我们必须学习一个与输入向量维数相同的权重向量 W,即向量( w1,w2 )和一个 b 偏差。
有了这些计算值,我们现在可以构建一个人工神经元来对新元素 X 进行分类。基本上,神经元将计算出的权重的向量 W 应用于输入元素 X 的每个维度中的值,并在最后添加偏差 b. ,其结果将通过非线性“激活”函数来产生结果“0”或“1”。我们刚刚定义的这种人工神经元的功能可以用更正式的方式来表达,例如:
现在,我们将需要一个函数,它对变量 z 进行转换,使其变成‘0’或‘1’。虽然有几个函数(“激活函数”),但在本例中,我们将使用一个称为 sigmoid 函数的函数,该函数针对任何输入值返回 0 到 1 之间的实际输出值:
如果我们分析前面的公式,我们可以看到它总是倾向于给出接近 0 或 1 的值。如果输入 z 相当大且为正,则在负 z 处的“e”为零,因此 y 取值为 1。如果 z 具有大的负值,那么对于“e”的大正数,公式的分母将是一个大的数字,因此 y 的值将接近 0。从图形上看,sigmoid 函数呈现如下形式:
到目前为止,我们已经介绍了如何定义人工神经元,这是神经网络可以拥有的最简单的架构。具体来说,这种架构在本主题的文献中被命名为感知器(也称为线性阈值单元 (LTU)),由 Frank Rosenblatt 于 1957 年发明,并在视觉上概括为以下方案:
多层感知器
但是在继续讨论这个例子之前,我们将简要介绍当神经网络是由我们刚刚介绍过的感知器构造而成时,它们通常采用的形式。
在该领域的文献中,当我们发现神经网络具有一个输入层,一个或多个由感知器组成的层,称为隐藏层,以及具有几个感知器的最后一层,称为输出层时,我们称之为多层感知器(MLP)。一般来说,当基于神经网络的模型由多个隐藏层组成时,我们称之为深度学习。在视觉上,它可以用以下方案来表示:
MLP 通常用于分类,特别是当类别是排他性的时,如在数字图像分类的情况下(从 0 到 9 的类别)。在这种情况下,由于一个名为 softmax 的函数,输出图层返回属于每个类的概率。视觉上,我们可以用以下方式表示它:
正如我们提到的,除了 sigmoid 之外,还有几个激活函数,每个都有不同的属性。其中一个是我们刚刚提到的 softmax 激活函数,它将有助于提供一个简单的神经网络的例子来分类两个以上的类。目前,我们可以把 softmax 函数看作是 sigmoid 函数的推广,它允许我们对两个以上的类进行分类。
Softmax 激活功能
我们将以这样的方式来解决这个问题:给定一个输入图像,我们将获得它是 10 个可能数字中的每一个的概率。这样,我们将有一个模型,例如,可以预测图像中的 5,但只有 70%的把握是 5。由于这幅图中数字上半部分的笔画,看起来它有 20%的几率变成 3,甚至有一定的概率变成其他数字。虽然在这种特殊情况下,我们会认为我们的模型的预测是 5,因为它是概率最高的一个,但这种使用概率分布的方法可以让我们更好地了解我们对预测的信心程度。这在这种情况下很好,因为数字是手工制作的,当然在很多情况下,我们不能 100%确定地识别数字。
因此,对于这个分类示例,我们将为每个输入示例获得一个输出向量,该输出向量具有在一组互斥标签上的概率分布。也就是说,10 个概率的向量(每个概率对应于一个数字)以及所有这 10 个概率的总和导致值 1(概率将在 0 和 1 之间表示)。
正如我们已经提出的,这是通过在我们的神经网络中使用具有 softmax 激活函数的输出层来实现的,其中该 softmax 层中的每个神经元取决于该层中所有其他神经元的输出,因为所有这些神经元的输出之和必须为 1。
但是 softmax 激活功能是如何工作的呢? softmax 函数基于计算某一图像属于特定类别的“证据”,然后将这些证据转换为它属于每个可能类别的概率。
一种测量某一图像属于特定类别的证据的方法是对属于该类别的每个像素的证据进行加权求和。为了解释这个想法,我将使用一个可视化的例子。
假设我们已经学习了数字 0 的模型。目前,我们可以把模型看作是“某种东西”,它包含了知道一个数是否属于某一类的信息。在这种情况下,对于数字 0,假设我们有一个如下所示的模型:
在这种情况下,具有 28×28 像素的矩阵,其中红色像素表示负权重(即,减少其所属的证据),而蓝色像素表示正权重(其证据是更大的增加)。白色代表中性值。
假设我们在上面画了一个零。一般来说,零点的轨迹会落在蓝色区域(请记住,我们讨论的是归一化为 20×20 像素的图像,后来以 28×28 的图像为中心)。很明显,如果我们的笔画越过红色区域,很可能我们写的不是零;因此,使用基于如果我们通过蓝色区域则相加,如果我们通过红色区域则相减的度量标准似乎是合理的。
为了确认它是一个好的度量,现在让我们想象我们画了一个三;很明显,我们用于零的前一个模型中心的红色区域会影响前面提到的指标,因为,正如我们在下图的左部看到的,当我们写 3 时,我们忽略了:
但另一方面,如果参考模型是对应于数字 3 的模型,如上图右侧所示,我们可以看到,一般来说,代表数字 3 的不同可能走线大多位于蓝色区域。
我希望读者看到这个直观的例子后,已经直觉地知道上面提到的权重的近似值是如何让我们估计出它是多少的。
一旦属于 10 个类别中的每一个的证据被计算出来,这些必须被转换成概率,其所有成分的总和加 1。为此,softmax 使用计算证据的指数值,然后将它们归一化,使总和等于 1,形成概率分布。属于类别 i 的概率为:
直观地说,使用指数得到的效果是,多一个单位的证据具有乘数效应,少一个单位的证据具有反效应。关于这个函数有趣的事情是,一个好的预测在向量中有一个接近 1 的值,而其余的值接近 0。在弱预测中,将有几个可能的标签,它们将具有或多或少相同的概率。
Keras 中的顺序类
Keras 中的主要数据结构是序列类,它允许创建一个基本的神经网络。Keras 还提供了一个 API ,允许以图形的形式实现更复杂的模型,可以有多个输入,多个输出,中间有任意连接,但这超出了本文的范围。
Keras 库的 序列类是 Keras 提供的序列神经网络模型的包装器,可以通过以下方式创建:
**model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(10,activation='sigmoid',
input_shape=(784,)))
model.add(tf.keras.layers.Dense(10,activation='softmax'))**
在这种情况下,Keras 中的模型被视为一系列层,每一层都逐渐“提取”输入数据以获得所需的输出。在 Keras 中,我们可以找到所有需要的层类型,这些层可以通过add()
方法轻松添加到模型中。
在这里,神经网络已经被定义为密集连接(或完全连接)的两层序列,意味着每层中的所有神经元都连接到下一层中的所有神经元。视觉上,我们可以用以下方式表示它:
在前面的代码中,我们在第一层的 input_shape 参数中明确表达了输入数据是什么样的:一个张量,表示我们有 784 个模型特征。
Keras 库的一个非常有趣的特点是,它会在第一个张量之后自动推导出层间张量的形状。这意味着程序员只需要为其中的第一个建立这些信息。此外,对于每一层,我们指出它所具有的节点数量以及我们将在其中应用的激活函数(在本例中, sigmoid )。
本例中的第二层是由 10 个神经元组成的 softmax 层,这意味着它将返回代表 10 个可能数字的 10 个概率值的矩阵(通常,分类网络的输出层将具有与类一样多的神经元,除了在二元分类中,只需要一个神经元)。每个值将是当前数字的图像属于它们中的每一个的概率。
****可选步骤:Keras 提供的一个非常有用的方法是summary()
:
**model.summary()_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_1 (Dense) (None, 10) 7850
_________________________________________________________________
dense_2 (Dense) (None, 10) 110
=================================================================
Total params: 7,960
Trainable params: 7,960
Non-trainable params: 0**
对于我们的简单示例,我们看到它指示需要 7960 个参数(列 Param # ),这对应于第一层的 7850 个参数和第二层的 110 个参数。
在第一层中,对于每个神经元 i (在 0 和 9 之间),我们需要 784 个参数作为权重 wij ,因此需要 10×784 个参数来存储 10 个神经元的权重。此外还有 10 个附加参数,分别对应于 10 个 bj 偏置。在第二层中,作为 softmax 函数,需要将所有 10 个神经元与前一层的 10 个神经元连接。因此,需要 10×10 个 wi 参数,另外还需要 10 个 bj 偏置对应于每个节点。
我们可以为dense
层指出的参数细节可以在 Keras 手册中找到。在我们的例子中,最相关的出现在例子中。第一个参数表示层中神经元的数量;下面是我们将在其中使用的激活函数。在这篇文章中,我们将更详细地讨论除了这里介绍的两个激活功能之外的其他可能的激活功能: sigmoid 和 softmax 。
3.训练模型
我们差不多完成了,我们只需要解释最后两行代码:
**model.compile(loss="categorical_crossentropy", optimizer="sgd",
metrics = ['accuracy'])model.fit(x_train, y_train, epochs=10, verbose=0)**
学习过程
神经网络如何学习神经元的权重 W 和偏差 b 的方式是对所有已知标记输入示例的迭代过程,将通过模型估计的其标记值与每个元素的标记的期望值进行比较。在每次迭代之后,以这样的方式调整参数值,使得图像的估计值和实际值之间的不一致(误差)变得更小。下面的方案希望以一种通用的方式直观地总结一个感知器的学习过程:
学习过程的配置
我们可以用compile()
方法配置这个学习过程,使用它我们可以通过方法参数指定一些属性。
第一个参数是损失函数,我们将使用它来评估训练数据的计算输出和期望输出之间的误差程度。另一方面,我们指定一个优化器,这是我们必须指定的优化算法,允许神经网络根据输入数据和定义的损失函数计算参数的权重。
最后,我们必须指出我们将用来监控神经网络学习过程的度量标准。在第一个例子中,我们将只考虑准确度(被正确分类的图像的比例)。例如,在我们的例子中我们可以在 compile() 方法中指定以下参数来测试它:
**model.compile(loss="categorical_crossentropy",
optimizer="sgd",
metrics = ['accuracy'])**
在本例中,我们指定损失函数为分类 _ 交叉熵,使用的优化器为随机梯度下降(sgd) ,度量标准为准确度,我们将使用它来评估正确猜测的百分比
在一篇新文章中,读者可以了解学习过程的更多细节。
模特培训
一旦我们的模型被定义,学习方法被配置,它就可以被训练了。为此,我们可以通过调用模型的 fit() 方法,将模型训练或“调整”为可用的训练数据:
**model.fit(x_train, y_train, epochs=10, verbose=0)**
在前两个参数中,我们已经以 Numpy 数组的形式指出了用于训练模型的数据。 batch_size 参数表示我们将在每次更新模型参数时使用的数据数量,而 epochs 表示我们将在学习过程中使用所有数据的次数。
这种方法通过我们提到的迭代训练算法找到网络的参数值。大致来说,在该算法的每次迭代中,该算法从 x_train 中获取训练数据,将它们通过神经网络(具有它们的参数在该时刻的值),将获得的结果与预期的结果(在 y_train 中指示)进行比较,并计算损失以指导模型参数的调整过程。 其直观地包括应用上面在 compile() 方法中指定的优化器,以减少损失的方式计算每次迭代中每个模型参数(权重和偏差)的新值。
正如我们将看到的,这种方法可能需要更长时间,Keras 允许我们使用冗长的参数(默认情况下等于 1)来查看其进度,此外还指示每个时期花费的估计时间:
**Epoch 1/5
60000/60000 [========] — 1s 15us/step — loss: 2.1822 — acc: 0.2916
Epoch 2/5
60000/60000 [========] — 1s 12us/step — loss: 1.9180 — acc: 0.5283
Epoch 3/5
60000/60000 [========] — 1s 13us/step — loss: 1.6978 — acc: 0.5937
Epoch 4/5
60000/60000 [========] — 1s 14us/step — loss: 1.5102 — acc: 0.6537
Epoch 5/5
60000/60000 [========] — 1s 13us/step — loss: 1.3526 — acc: 0.7034
10000/10000 [========] — 0s 22us/step**
使用模型
为了使用该模型,我们可以使用以下代码下载另一组图像(不同于训练图像):
**_, (x_test_, y_test_)= tf.keras.datasets.mnist.load_data()
x_test = x_test_.reshape(10000, 784).astype('float32')/255
y_test = to_categorical(y_test_, num_classes=10)**
可选步骤:模型评估
此时,神经网络已经完成训练,现在可以使用evaluation()
方法评估其在新测试数据下的行为。此方法返回两个值:
**test_loss, test_acc = model.evaluate(x_test, y_test)**
这些值表明我们的模型在处理从未见过的新数据时表现得如何。当我们执行了 mnist.load_data() 时,这些数据已经存储在 x_test 和 y_test 中,我们将它们作为参数传递给方法。在本帖的范围内,我们将只关注其中之一,准确性:
**print(‘Test accuracy:’, test_acc)
Test accuracy: 0.9018**
准确性告诉我们,我们在这篇文章中创建的模型,应用于该模型从未见过的数据,正确分类了 90%。
生成预测
最后,读者需要知道我们如何使用上一节中训练的模型进行预测。在我们的例子中,它包括预测哪个数字代表一幅图像。为了做到这一点,Keras 提供了predict()
方法。
让我们选择一个图像(并绘制它)来预测数字:
**image = 5_ = plt.imshow(x_test_[image], cmap=plt.cm.binary)**
为了预测这个数字,我们可以使用下面的代码:
**import numpy as np
prediction = model.predict(x_test_)
print("Model prediction: ", np.argmax(prediction[image]) )**
仅此而已!
下一步?
现在你已经准备好学习如何编程一个更高级的神经网络(本文中的):卷积神经网络。准备好了吗?
** [## 卷积神经网络初学者使用 Keras 和 TensorFlow 2
边做边学:包含 GitHub 代码的实用指南
towardsdatascience.com](/convolutional-neural-networks-for-beginners-using-keras-and-tensorflow-2-c578f7b3bf25)
GitHub上有这个帖子的代码
于 2020 年 5 月 02 日https://Torres . ai以西班牙语原文发表。**
我如何建立一个动态定价系统
现实世界中的 DS
众所周知,在商业中有这样一条真理:价格高,数量少。高容量,低价格。或者是?
在本文中,我将与您分享我为一家长途火车公司构建动态定价系统的经验,以及我们如何通过应用非常基本的微观经济学原理,在不改变我们的时间表,也不降低每个座位的平均价格的情况下,增加售出座位的数量。
这种实现也适用于其销售的服务与火车座位共享一些特征的任何商业,也就是说:
- 多卖一个单位的成本,或者说边际成本,接近于零。
- 如果一个可用的单元在提供服务时没有卖出去(例如,一列火车离开车站),那么它就不能保存在库存中,它的潜在价值就永远失去了。
酒店房间、航空公司、长途汽车票、电影院、剧院、音乐会、动物园、游轮、体育赛事等都是如此。
为了建立模型,我们首先需要回答以下问题:
- 顾客购买多少商品或服务?
- 顾客付多少钱?
- 客户什么时候购买?
顾客买了多少
让我们先来看看一个典型的需求函数:
需求函数是商品或服务的价格与你能以给定价格出售的所述商品或服务的数量之间关系的数学表达式。如前所述,对于正常商品,价格越高,售出的商品数量越少。这导致需求函数向下倾斜。当你在水平轴上向右移动时,你增加了你要销售的产品的数量,那么你需要降低你的价格来达到销售的数量。
所以,顾客想买多少商品或服务将取决于价格。在其他条件不变的情况下,你降低价格,就会有更多的顾客愿意为服务付费。
顾客愿意付多少钱
上面的图表也能告诉我们,在给定你想要出售的单位数量的情况下,我们可以收取多少费用。
为了简化,让我们假设一个客户只能购买一个单位的服务(在这种情况下是一张火车票)。那么如果你把票的价格定在€9,那么就有 30 个人愿意买票。如果你把价格定在€3,那么有 90 个人愿意买票(30 个人愿意在€9 买,另外 60 个人愿意在€3 买)。
收入最大化
如果一个公司只能向所有顾客收取同一个价格,因为收入等于价格乘以数量,那么如果公司每张票收费 6 欧元,那么它将出售 60 张票,总收入为€360。
尽管有时公司有能力对不同的顾客收取不同的价格。经济学家称这种能力为价格歧视,,这使得公司能够通过获取需求曲线函数下的更多价值来增加收入。
在上面的例子中,如果我们的火车公司可以对成人和儿童乘客收取不同的价格,那么他们可能会增加收入,从他们可以以单一价格达到的最高€360 到€440(每个成人 40 张€8 的票,加上每个儿童 20 张€6 的票)。
需求曲线下的面积代表特定商品或服务交付给客户的价值。因此,如果你不仅可以对两种不同类型的客户收取两种不同的价格,而且可以对几种不同类型的客户收取几种不同的价格,那么你就可以抓住需求曲线下的大部分区域,并完全从你的定价策略中大幅增加收入,而不必承担增加航班、改变座位安排、增加广告或在飞机上提供额外服务的成本。
正如我们已经确定的那样,在一列无论如何都将空着的火车上出售一个座位几乎没有额外的成本,并且未出售的座位的价值将永远失去,只要你有空座位,以高于零的任何价格出售任何空座位都是有意义的。
要是我们知道如何根据客户对价格的敏感度来对他们进行细分就好了。
顾客什么时候购买
我们都会拖延,消费者也一样。人们通常会尽可能推迟购买决定。在火车票的例子中,我们发现这种行为创造了一种模式,即在很久以后才零星地购买火车票。然后,在出发前一个月左右,购买变得更加频繁,在出发前一周加速,并且在出发前一天达到购买机票的高峰。
如果我们在横轴上画出剩余待售车票的百分比,在纵轴上画出火车离站的剩余天数,那么我们得到一个向下倾斜的函数。随着离出发时间越来越近,售票速度加快,因此剩余的待售票数量也相应减少。
我们还发现,越晚购票的乘客对价格越不敏感。因此,我们找到了允许我们进行价格歧视的变量:时间。
把它放在一起
现在,我们需要找到在特定时间需要收取的特定价格,因为我们有特定数量的门票要出售。幸运的是,我们有两个共享两个变量的方程,可以同时求解:
- 价格需求函数:P = g(Q)
其中价格§是数量(Q)的函数(g)。 - 和剩余的票数:Q = h(T)
其中数量(Q)是时间(T)的函数(h)。
这给了我们一个新的函数,价格是时间的函数。
- P = f(T) = g(h(T))
在上图的右上象限中以图形方式显示。这个函数告诉我们在任何特定时间每张票的价格,给定我们还有多少票要卖。
使用这个函数,我们还可以计算时间 T 和数量 Q 的任何给定值的预期价格 P,以填充一个矩阵,并以表格形式显示这个函数。
当事情不按计划进行时
有时事情不会像预期的那样发生,例如,与我们的功能预测相反,我们卖出了更多或更少的票。
如果在任何给定的时间(T)和价格§,售出的商品数量高于预期,那么这意味着更多的人愿意在当时的时间和价格购买一张票。
我们可以把这种变化表示为需求函数的上移。
如果需求函数在上图的左上象限向上移动。然后,为了有剩余的票在以后出售,当我们可以收取更高的价格时,价格现在就需要上涨。这导致在右上象限中代表作为时间函数的价格的曲线中类似的平行上移。都用红色表示。
同样,如果我们卖出的票比预期的少,那么这意味着在给定的时间和价格下,售出的数量比预期的少。这导致向下移动的曲线为绿色。为了填满火车,价格需要下降。
如果随着时间的推移,我们发现预期售出的门票数量与实际售出的门票数量之间存在进一步的差异,我们可以将它们视为需求函数的进一步变化。
想象一下,我们一直发现我们卖出的票比预期的多。这些可以被视为门票价格需求函数的连续向上移动,以及价格/时间函数的匹配平行向上移动,如上图中向上移动的红色曲线所示。
计算这些向上和向下移动的需求函数给我们的所有价格 P 的所有值,给定时间 T 和数量 Q 的组合,以填充我们假设的火车出发的全部价格矩阵,向我们显示我们在出发前时间和出售离开的座位的的任何给定组合下需要收取的价格,这将最大化该出发的收入。
履行
在实施过程中,我们必须做出一些政策决定,以简化向新系统的过渡。
考虑到对铁路网络中的不同旅行段进行定价是一项相当复杂的工作,我们没有对现有的定价模型进行太大的修改,而是在现有模型的基础上实施了价格矩阵,以标价的百分比表示。
我们现在有两种定价等级(不要与运输等级混淆):新的、动态定价的折扣票,不可退款;和全价票,全价票可以作为可全额退款的机票在任何时候以相同的固定全价购买。
需要做的第一个决定是将每次出发的座位分配给这两种机票等级,这最初是手动完成的,但后来是自动完成的,使用历史数据作为参考。
为了简化营销沟通,我们决定不收取高于所列全价票的费用,有效地限制了我们可以收取的最高价格,即使火车会非常满。同样,我们也决定永远不收取低于全价 20%的费用。
我们还必须对不同的偏离进行分组,并为不同的分组实现不同的矩阵。下面是我们实现的一个矩阵的例子。
最后的想法
这种定价系统的引入使我们能够淘汰依赖于更多变量、需要大量手动输入和昂贵的软件许可费用的更老、更复杂的系统。取而代之的是一个更简单、更稳健、更便宜的模型,它需要更少的、事实上只有两个输入:(1)出发时间和(2)售出的座位数量。
经济学家通常说,所有的信息最终都会反映在价格中。在这种情况下,结果就是这样。我们实际上用更少的输入做出了更准确的预测,所以模型需要更少的维护。简单性的维护成本更低。
我们还取消了几个复杂的折扣机票等级。这种单一的、与时间相关的定价允许我们更换它们,同时获得更广泛的价格范围,不仅在较低的价格点(如果您较早购买了机票),而且在较高的价格点,通过引入更细微的定价,随着出发时间的临近,更接近需求函数。实际上,它大大提高了我们辨别价格的能力。
在我们使用这些价格矩阵后,我们看到售出的门票数量增加了 5%。不仅是因为打折票的额外销售,有趣的是,还因为全价票的增加,因为该系统允许我们更准确地预测我们可以销售的全价票的数量。
由于售出的额外门票的边际成本接近零,所有相关的收入增长都直接进入了底线,因为在我们的票务系统中实施矩阵后,不会产生额外的可变成本,从而导致利润率的纯增长。
支持艾蒂安和其他数千名作家的作品